blob: 9cb45584215eb201734bb65ca5070b6c721dcf94 [file] [log] [blame]
/* pngrtran.c - transforms the data in a row for PNG readers
*
* Last changed in libpng 1.7.0 [(PENDING RELEASE)]
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*
* This file contains functions optionally called by an application
* in order to tell libpng how to handle data when reading a PNG.
* Transformations that are used in both reading and writing are
* in pngtrans.c.
*/
#include "pngpriv.h"
#define PNG_SRC_FILE PNG_SRC_FILE_pngrtran
#ifdef PNG_READ_QUANTIZE_SUPPORTED
typedef struct
{
png_transform tr;
png_byte map[256U]; /* Map of palette values */
png_byte lut[1U << /* LUT for RGB values */
(PNG_QUANTIZE_RED_BITS+PNG_QUANTIZE_GREEN_BITS+PNG_QUANTIZE_BLUE_BITS)];
} png_transform_quantize;
#define PNG_QUANTIZE_MAP 1U /* map is present and not a 1:1 mapping */
#define PNG_QUANTIZE_LUT 2U /* lut has been built */
static void
do_quantize_rgb(png_transformp *transform, png_transform_controlp tc)
{
# define png_ptr (tc->png_ptr)
png_transform_quantize *tr = png_transform_cast(png_transform_quantize,
*transform);
unsigned int channels = PNG_TC_CHANNELS(*tc);
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc) - channels/*safety*/;
png_bytep dp = png_voidcast(png_bytep, tc->dp);
affirm(tc->bit_depth == 8 && (channels == 3 || channels == 4) &&
!(tc->format & PNG_FORMAT_FLAG_SWAPPED) &&
(tr->tr.args & PNG_QUANTIZE_LUT) != 0);
tc->sp = dp;
tc->format |= PNG_FORMAT_FLAG_COLORMAP;
while (sp <= ep)
{
unsigned int r = sp[0];
unsigned int g = sp[1];
unsigned int b = sp[2];
/* This looks real messy, but the compiler will reduce
* it down to a reasonable formula. For example, with
* 5 bits per color, we get:
* p = (((r >> 3) & 0x1f) << 10) |
* (((g >> 3) & 0x1f) << 5) |
* ((b >> 3) & 0x1f);
*/
*dp++ = tr->lut[(((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
(PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
(((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
(PNG_QUANTIZE_BLUE_BITS)) |
((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
((1 << PNG_QUANTIZE_BLUE_BITS) - 1))];
sp += channels;
}
affirm(sp == ep+channels);
UNTESTED
# undef png_ptr
}
static void
do_quantize_pal(png_transformp *transform, png_transform_controlp tc)
{
# define png_ptr (tc->png_ptr)
png_transform_quantize *tr = png_transform_cast(png_transform_quantize,
*transform);
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc);
png_bytep dp = png_voidcast(png_bytep, tc->dp);
affirm(tc->bit_depth == 8 && (tc->format & PNG_FORMAT_FLAG_COLORMAP) != 0 &&
!(tc->format & PNG_FORMAT_FLAG_SWAPPED) &&
(tr->tr.args & PNG_QUANTIZE_MAP) != 0);
tc->sp = dp;
while (sp < ep)
*dp++ = tr->map[*sp++];
UNTESTED
# undef png_ptr
}
static void
png_init_quantize(png_transformp *transform, png_transform_controlp tc)
{
if (tc->bit_depth == 8 && (tc->format & PNG_FORMAT_FLAG_COLOR) != 0)
{
/* Either colormapped input, RGB or RGBA: */
if (!(tc->format & PNG_FORMAT_FLAG_COLORMAP)) /* RGB, RGBA */
{
/* This must be a 'palette' lookup */
if (((*transform)->args & PNG_QUANTIZE_LUT) != 0)
{
/* This changes the format and invalidates pretty much everything in
* the info struct:
*/
tc->format |= PNG_FORMAT_FLAG_COLORMAP;
if (tc->init == PNG_TC_INIT_FINAL)
{
(*transform)->fn = do_quantize_rgb;
tc->invalid_info |= PNG_INFO_tRNS+PNG_INFO_hIST+PNG_INFO_pCAL+
PNG_INFO_sBIT+PNG_INFO_bKGD;
tc->sBIT_R = tc->sBIT_G = tc->sBIT_B = tc->sBIT_A =
png_check_byte(tc->png_ptr, tc->bit_depth);
}
return;
}
}
else /* colormapped */
{
/* This must be a 'quantize' lookup */
if (((*transform)->args & PNG_QUANTIZE_MAP) != 0)
{
/* This doesn't change the format, just the values: */
if (tc->init == PNG_TC_INIT_FINAL)
{
(*transform)->fn = do_quantize_pal;
tc->invalid_info |= PNG_INFO_sBIT+PNG_INFO_pCAL;
tc->sBIT_R = tc->sBIT_G = tc->sBIT_B = tc->sBIT_A =
png_check_byte(tc->png_ptr, tc->bit_depth);
}
return;
}
}
}
/* Else not applicable */
(*transform)->fn = NULL;
}
/* Dither file to 8-bit. Supply a palette, the current number
* of elements in the palette, the maximum number of elements
* allowed, and a histogram if possible. If the current number
* of colors is greater then the maximum number, the palette will be
* modified to fit in the maximum number. "full_quantize" indicates
* whether we need a quantizing cube set up for RGB images, or if we
* simply are reducing the number of colors in a paletted image.
*/
typedef struct png_dsort_struct
{
struct png_dsort_struct * next;
png_byte left;
png_byte right;
} png_dsort;
typedef png_dsort * png_dsortp;
typedef png_dsort * * png_dsortpp;
static void
init_map(png_bytep map)
/* Initialize a mapping table to be 1:1 */
{
png_byte b = 0U;
do
map[b] = b;
while (b++ != 255U);
}
/* Save typing and make code easier to understand */
#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \
abs((int)((c1).green) - (int)((c2).green)) + \
abs((int)((c1).blue) - (int)((c2).blue)))
void PNGAPI
png_set_quantize(png_structrp png_ptr, png_colorp palette,
int num_palette, int maximum_colors, png_const_uint_16p histogram,
int full_quantize)
{
png_debug(1, "in png_set_quantize");
if (png_ptr != NULL)
{
png_transform_quantize *tr = png_transform_cast(png_transform_quantize,
png_add_transform(png_ptr, sizeof (png_transform_quantize),
png_init_quantize, PNG_TR_QUANTIZE));
/* This is weird (consider what happens to png_set_background on a palette
* image with a tRNS chunk).
*/
if (palette == png_ptr->palette)
png_app_warning(png_ptr, "png_set_quantize: PLTE will be damaged");
if (maximum_colors <= 0 || num_palette > 256)
{
/* The spuriously allocated transform will be removed by the init
* code.
*/
png_app_error(png_ptr, "png_set_quantize: invalid color count");
return;
}
/* The app passed in a palette with too many colors, it's not clear why
* libpng is providing this functionality, it's nothing to do with PNG and
* can be done by the application without any PNG specific knowledge.
*/
if (num_palette > maximum_colors)
{
int map_changed = 0;
/* The map table must be preset to do no mapping initially: */
init_map(tr->map);
if (histogram != NULL)
{
/* This is easy enough, just throw out the least used colors.
* Perhaps not the best solution, but good enough.
*/
int i;
png_byte quantize_sort[256U];
/* Initialize an array to sort colors */
init_map(quantize_sort);
/* Find the least used palette entries by starting a
* bubble sort, and running it until we have sorted
* out enough colors. Note that we don't care about
* sorting all the colors, just finding which are
* least used.
*/
for (i = num_palette - 1; i >= maximum_colors; i--)
{
int done; /* To stop early if the list is pre-sorted */
int j;
done = 1;
for (j = 0; j < i; j++)
{
if (histogram[quantize_sort[j]] <
histogram[quantize_sort[j+1]])
{
png_byte t = quantize_sort[j];
quantize_sort[j] = quantize_sort[j+1];
quantize_sort[j+1] = t;
done = 0;
}
}
if (done != 0)
break;
}
/* Swap the palette around, and set up a table, if necessary */
if (full_quantize)
{
int j = num_palette;
/* Put all the useful colors within the max, but don't
* move the others.
*
* NOTE: if the app passes in the result of png_get_PLTE it will
* be overwritten at this point, what is the API?
*/
for (i = 0; i < maximum_colors; i++)
{
if (quantize_sort[i] >= maximum_colors)
{
do
j--;
while (quantize_sort[j] >= maximum_colors);
/* NOTE: NOT swapped, so the original palette[i] has been
* lost.
*/
palette[i] = palette[j];
}
}
}
else /* !full_quantize */
{
int j = num_palette;
/* Move all the used colors inside the max limit, and
* develop a translation table.
*/
for (i = 0; i < maximum_colors; i++)
{
/* Only move the colors we need to */
if (quantize_sort[i] >= maximum_colors)
{
png_color tmp_color;
do
j--;
while (quantize_sort[j] >= maximum_colors);
tmp_color = palette[j];
palette[j] = palette[i];
palette[i] = tmp_color;
/* Indicate where the color went */
tr->map[j] = png_check_byte(png_ptr, i);
tr->map[i] = png_check_byte(png_ptr, j);
map_changed = 1;
}
}
/* Find closest color for those colors we are not using */
for (i = 0; i < num_palette; i++)
{
if (tr->map[i] >= maximum_colors)
{
int min_d, k, min_k, d_index;
/* Find the closest color to one we threw out */
d_index = tr->map[i];
min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
for (k = 1, min_k = 0; k < maximum_colors; k++)
{
int d;
d = PNG_COLOR_DIST(palette[d_index], palette[k]);
if (d < min_d)
{
min_d = d;
min_k = k;
}
}
/* Point to closest color */
tr->map[i] = png_check_byte(png_ptr, min_k);
map_changed = 1;
}
}
} /* !full_quantize */
} /* have a histogram */
else /* no histogram */
{
/* This is much harder to do simply (and quickly). Perhaps
* we need to go through a median cut routine, but those
* don't always behave themselves with only a few colors
* as input. So we will just find the closest two colors,
* and throw out one of them (chosen somewhat randomly).
* [We don't understand this at all, so if someone wants to
* work on improving it, be our guest - AED, GRP]
*/
int max_d;
int num_new_palette;
png_byte index_to_palette[256U];
png_byte palette_to_index[256U];
png_dsortp hash[769];
/* Initialize palette index sort arrays */
init_map(index_to_palette);
init_map(palette_to_index);
memset(hash, 0, sizeof hash);
num_new_palette = num_palette;
/* Initial wild guess at how far apart the farthest pixel
* pair we will be eliminating will be. Larger
* numbers mean more areas will be allocated, Smaller
* numbers run the risk of not saving enough data, and
* having to do this all over again.
*
* I have not done extensive checking on this number.
*/
max_d = 96;
while (num_new_palette > maximum_colors)
{
int i;
png_dsortp t = NULL;
for (i = 0; i < num_new_palette - 1; i++)
{
int j;
for (j = i + 1; j < num_new_palette; j++)
{
int d = PNG_COLOR_DIST(palette[i], palette[j]);
if (d <= max_d)
{
t = png_voidcast(png_dsortp, png_malloc_warn(png_ptr,
sizeof (*t)));
if (t == NULL)
break;
t->next = hash[d];
t->left = png_check_byte(png_ptr, i);
t->right = png_check_byte(png_ptr, j);
hash[d] = t;
}
}
if (t == NULL)
break;
}
if (t != NULL) for (i = 0; i <= max_d; i++)
{
if (hash[i] != NULL)
{
png_dsortp p;
for (p = hash[i]; p != NULL; p = p->next)
{
if (index_to_palette[p->left] < num_new_palette &&
index_to_palette[p->right] < num_new_palette)
{
int j, next_j;
if (num_new_palette & 0x01)
{
j = p->left;
next_j = p->right;
}
else
{
j = p->right;
next_j = p->left;
}
num_new_palette--;
/* NOTE: overwrites palette */
palette[index_to_palette[j]] =
palette[num_new_palette];
if (full_quantize == 0)
{
int k;
for (k = 0; k < num_palette; k++)
{
if (tr->map[k] == index_to_palette[j])
{
tr->map[k] = index_to_palette[next_j];
map_changed = 1;
}
if (tr->map[k] == num_new_palette)
{
tr->map[k] = index_to_palette[j];
map_changed = 1;
}
}
}
index_to_palette[palette_to_index[num_new_palette]] =
index_to_palette[j];
palette_to_index[index_to_palette[j]] =
palette_to_index[num_new_palette];
index_to_palette[j] =
png_check_byte(png_ptr, num_new_palette);
palette_to_index[num_new_palette] =
png_check_byte(png_ptr, j);
}
if (num_new_palette <= maximum_colors)
break;
}
if (num_new_palette <= maximum_colors)
break;
}
}
for (i = 0; i < 769; i++)
{
if (hash[i] != NULL)
{
png_dsortp p = hash[i];
while (p)
{
t = p->next;
png_free(png_ptr, p);
p = t;
}
hash[i] = NULL;
}
}
max_d += 96;
} /* while num_new_colors > maximum_colors */
} /* no histogram */
num_palette = maximum_colors;
if (map_changed) /* else the map is 1:1 */
tr->tr.args |= PNG_QUANTIZE_MAP;
} /* num_palette > maximum_colors */
/* The palette has been reduced to the requested number of colors if it
* was over maximum colors before.
*/
/* TODO: what is this? Apparently the png_struct::palette member gets
* updated if it didn't originally have a palette, but the update relies
* on the app not freeing the passed in palette.
*/
if (png_ptr->palette == NULL)
png_ptr->palette = palette;
png_ptr->num_palette = png_check_bits(png_ptr, num_palette, 9);
if (full_quantize)
{
int i;
png_byte distance[1U << (PNG_QUANTIZE_RED_BITS+PNG_QUANTIZE_GREEN_BITS+
PNG_QUANTIZE_BLUE_BITS)];
memset(distance, 0xff, sizeof distance);
for (i = 0; i < num_palette; i++)
{
int ir;
int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));
int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));
int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
for (ir = 0; ir < (1<<PNG_QUANTIZE_RED_BITS); ir++)
{
/* int dr = abs(ir - r); */
int ig;
int dr = ((ir > r) ? ir - r : r - ir);
int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
PNG_QUANTIZE_GREEN_BITS));
for (ig = 0; ig < (1<<PNG_QUANTIZE_GREEN_BITS); ig++)
{
/* int dg = abs(ig - g); */
int ib;
int dg = ((ig > g) ? ig - g : g - ig);
int dt = dr + dg;
int dm = ((dr > dg) ? dr : dg);
int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
for (ib = 0; ib < (1<<PNG_QUANTIZE_BLUE_BITS); ib++)
{
int d_index = index_g | ib;
/* int db = abs(ib - b); */
int db = ((ib > b) ? ib - b : b - ib);
int dmax = ((dm > db) ? dm : db);
int d = dmax + dt + db;
if (d < distance[d_index])
{
distance[d_index] = png_check_byte(png_ptr, d);
tr->lut[d_index] = png_check_byte(png_ptr, i);
}
} /* for blue */
} /* for green */
} /* for red */
} /* num_palette */
} /* full_quantize */
} /* png_ptr != NULL */
}
#endif /* READ_QUANTIZE */
#ifdef PNG_READ_PACK_SUPPORTED
/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
* without changing the actual values. Thus, if you had a row with
* a bit depth of 1, you would end up with bytes that only contained
* the numbers 0 or 1. If you would rather they contain 0 and 255, use
* png_set_expand_gray_1_2_4_to_8 instead.
*/
static void
png_do_read_unpack(png_transformp *transform, png_transform_controlp tc)
{
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_const_bytep ep = png_voidcast(png_const_bytep, tc->dp);
png_bytep dp = png_voidcast(png_bytep, tc->dp);
sp += PNG_TC_ROWBYTES(*tc) - 1; /* Start from end */
dp += tc->width; /* output bit depth is 8 */
# define png_ptr (tc->png_ptr)
png_debug(1, "in png_do_unpack");
switch (tc->bit_depth)
{
case 1:
{
/* Because we copy from the last pixel down the shift required
* at the start is 8-pixels_in_last_byte, which is just:
*/
unsigned int shift = 7U & -tc->width;
while (dp > ep)
{
*--dp = (*sp >> shift) & 1U;
shift = 7U & (shift+1U);
if (shift == 0U)
--sp;
}
debug(shift == 0U);
break;
}
case 2:
{
unsigned int shift = 7U & -(tc->width << 1);
while (dp > ep)
{
*--dp = (*sp >> shift) & 3U;
shift = 7U & (shift+2U);
if (shift == 0U)
--sp;
}
debug(shift == 0U);
break;
}
case 4:
{
unsigned int shift = 7U & -(tc->width << 2);
while (dp > ep)
{
*--dp = (*sp >> shift) & 15U;
shift = 7U & (shift+4U);
if (shift == 0U)
--sp;
}
debug(shift == 0U);
break;
}
default:
impossible("bit depth");
}
debug(dp == ep && sp == png_upcast(png_const_bytep, tc->sp)-1U);
tc->sp = dp;
if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0U)
{
tc->range++;
tc->format |= PNG_FORMAT_FLAG_RANGE;
}
tc->bit_depth = 8U;
PNG_UNUSED(transform)
# undef png_ptr
}
/* Called from the curiously named png_set_packing API in pngtrans.c; the read
* and write code is separated because read 'unpacks' (from PNG format) and
* write 'packs' (to PNG format.)
*/
void /* PRIVATE */
png_init_read_pack(png_transformp *transform, png_transform_controlp tc)
{
# define png_ptr tc->png_ptr
debug(tc->init);
if (tc->bit_depth < 8) /* else no packing/unpacking */
{
/* For indexed images the pack operation does not invalidate the range; in
* fact the corresponding shift operation would!
*/
if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0U)
{
tc->range++;
tc->format |= PNG_FORMAT_FLAG_RANGE;
}
tc->bit_depth = 8U;
if (tc->init == PNG_TC_INIT_FINAL)
(*transform)->fn = png_do_read_unpack/* sic: it unpacks */;
}
else /* the transform is not applicable */
(*transform)->fn = NULL;
# undef png_ptr
}
#endif /* READ_PACK */
#if defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
# ifdef PNG_READ_tRNS_SUPPORTED
static unsigned int
fill_transparent_pixel(png_const_structrp png_ptr, png_byte *trans)
/* Fill a byte array according to the transparent pixel value and return a
* count of the number of bytes. Low bit depth gray values are replicated in
* the first byte. Writes from 1 to 6 bytes.
*/
{
/* There must be a tRNS chunk and this must not be a palette image: */
debug(png_ptr->num_trans == 1 &&
!(png_ptr->color_type & (PNG_COLOR_MASK_ALPHA+PNG_COLOR_MASK_PALETTE)));
if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* gray */
{
unsigned int t = png_ptr->trans_color.gray;
unsigned int depth = png_ptr->bit_depth;
if (depth < 16U)
{
/* ISO PNG 11.3.2.1 "tRNS Transparency": "If the image bit depth is
* less than 16, the least significant bits are used and the others are
* 0." So mask out the upper bits.
*/
t &= (1U<<depth)-1U;
/* And replicate low bit-depth values across the byte: */
while (depth < 8U)
{
t |= t << depth;
depth <<= 1;
}
trans[0] = PNG_BYTE(t);
return 1U;
}
/* Else a 16 bit value: */
trans[0] = PNG_BYTE(t >> 8);
trans[1] = PNG_BYTE(t);
return 2U;
}
else /* color */ switch (png_ptr->bit_depth)
{
case 8: /* 8-bit RGB */
trans[0] = PNG_BYTE(png_ptr->trans_color.red);
trans[1] = PNG_BYTE(png_ptr->trans_color.green);
trans[2] = PNG_BYTE(png_ptr->trans_color.blue);
return 3U;
case 16: /* 16-bit RGB */
trans[0] = PNG_BYTE(png_ptr->trans_color.red >> 8);
trans[1] = PNG_BYTE(png_ptr->trans_color.red);
trans[2] = PNG_BYTE(png_ptr->trans_color.green >> 8);
trans[3] = PNG_BYTE(png_ptr->trans_color.green);
trans[4] = PNG_BYTE(png_ptr->trans_color.blue >> 8);
trans[5] = PNG_BYTE(png_ptr->trans_color.blue);
return 6U;
default:
NOT_REACHED;
return 0U; /* safe */
}
}
# endif /* READ_tRNS */
#endif /* READ_EXPAND || READ_BACKGROUND */
#ifdef PNG_READ_EXPAND_SUPPORTED
/* Flags for png_init_expand */
#define PNG_EXPAND_PALETTE 1U /* palette images only, includes tRNS */
#define PNG_EXPAND_LBD_GRAY 2U /* grayscale low-bit depth only */
#define PNG_EXPAND_tRNS 4U /* non-palette images only */
/* This struct is only required for tRNS matching, but it is convenient to
* allocated it anyway even if READ_tRNS is not supported.
*/
typedef struct
{
png_transform tr;
unsigned int ntrans; /* number of bytes below */
png_byte transparent_pixel[6]; /* the transparent pixel value */
} png_expand;
#ifdef PNG_READ_tRNS_SUPPORTED
/* Look for colors matching the trans_color in png_ptr, low bit depth gray is
* covered below so this only need handle 8 abd 16-bit channels.
*/
static void
png_do_expand_tRNS(png_transformp *transform, png_transform_controlp tc)
{
# define png_ptr (tc->png_ptr)
png_expand *tr = png_transform_cast(png_expand, *transform);
png_bytep dp = png_voidcast(png_bytep, tc->dp);
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
const png_const_bytep ep = sp;
const unsigned int spixel_size = PNG_TC_PIXEL_DEPTH(*tc) >> 3;
unsigned int alpha_size;
/* We expect opaque and transparent pixels to be interleaved but with long
* sequences of each. Because we are adding an alpha channel we must copy
* down.
*/
debug(!(tc->format & PNG_FORMAT_FLAG_ALPHA));
debug(spixel_size == tr->ntrans);
sp += PNG_TC_ROWBYTES(*tc);
tc->sp = dp;
tc->format |= PNG_FORMAT_FLAG_ALPHA;
tc->invalid_info |= PNG_INFO_tRNS;
tc->transparent_alpha = 1U;
alpha_size = (PNG_TC_PIXEL_DEPTH(*tc)>>3) - spixel_size;
debug(alpha_size == 1 || alpha_size == 2);
dp += PNG_TC_ROWBYTES(*tc);
do
{
unsigned int i = spixel_size;
png_byte alpha = 0U;
dp -= alpha_size;
alpha = 0U;
/* Copy and check one source pixel (backwards, to avoid any
* overwrite):
*/
do if ((*--dp = *--sp) != tr->transparent_pixel[--i]) /* pixel != tRNS */
alpha = 0xFFU;
while (i != 0U);
/* i == 0 */
do
dp[spixel_size + i] = alpha;
while (++i < alpha_size);
} while (sp > ep);
debug(sp == ep && dp == tc->dp); /* else overwrite */
# undef png_ptr
}
#endif /* READ_tRNS */
/* Expand grayscale images of less than 8-bit depth to 8 bits.
* libpng 1.7.0: this no longer expands everything, it just expands the low bit
* depth gray row. It does *NOT* expand the tRNS into an alpha channel unless
* it is told to do so.
*
* API CHANGE: the function now does what it was always meant to do.
*
* This is like do_unpack except that the packed data is expanded to the full
* 8-bit range; scaled up. This is not a good thing to do on an indexed image;
* the indices will be invalid.
*
* The tRNS handling is included here too; speed is not important because the
* result will always be cached unless the PNG is very small.
*/
static void
png_do_expand_lbd_gray(png_transformp *transform, png_transform_controlp tc)
{
# define png_ptr (tc->png_ptr)
png_bytep dp = png_voidcast(png_bytep, tc->dp);
const png_const_bytep ep = dp;
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
const unsigned int bit_depth = tc->bit_depth;
# ifdef PNG_READ_sBIT_SUPPORTED
unsigned int insignificant_bits = 0U;
# endif /* READ_sBIT */
# ifdef PNG_READ_tRNS_SUPPORTED
unsigned int gray = 0xffffU; /* doesn't match anything */
unsigned int do_alpha = 0U;
# endif /* READ_tRNS */
sp += PNG_TC_ROWBYTES(*tc); /* last byte +1 */
tc->bit_depth = 8U;
tc->invalid_info |= PNG_INFO_tRNS;
# ifdef PNG_READ_sBIT_SUPPORTED
if (bit_depth > 1U /* irrelevant for bit depth 1 */ &&
!(tc->invalid_info & PNG_INFO_sBIT) &&
tc->sBIT_G > 0U/*SAFETY*/ && tc->sBIT_G < bit_depth)
insignificant_bits = bit_depth - tc->sBIT_G;
# endif /* READ_sBIT */
# ifdef PNG_READ_tRNS_SUPPORTED
if (((*transform)->args & PNG_EXPAND_tRNS) != 0)
{
tc->format |= PNG_FORMAT_FLAG_ALPHA;
tc->transparent_alpha = 1U;
gray = png_ptr->trans_color.gray & ((1U << bit_depth)-1U);
do_alpha = 1U;
}
/* This helps avoid cluttering the code up with #ifdefs: */
# define check_tRNS if (do_alpha) *--dp = (pixel != gray) * 255U;
# else /* !READ_tRNS */
# define check_tRNS
# endif /* READ_tRNS */
dp += PNG_TC_ROWBYTES(*tc); /* pre-decremented below */
switch (bit_depth)
{
case 1:
{
unsigned int shift = 7U & -tc->width;
unsigned int s = *--sp;
for(;;)
{
if (shift == 8U) s = *--sp, shift = 0;
{
const unsigned int pixel = (s >> shift) & 1U;
check_tRNS
*--dp = PNG_BYTE(pixel * 255U);
if (dp <= ep) break;
}
++shift;
}
debug(dp == ep && shift == 7U && sp == tc->sp);
break;
}
case 2:
{
unsigned int shift = 7U & -(tc->width << 1)/*overflow ok*/;
unsigned int s = *--sp;
for (;;)
{
if (shift == 8U) s = *--sp, shift = 0;
{
const unsigned int pixel = (s >> shift) & 3U;
check_tRNS
# ifdef PNG_READ_sBIT_SUPPORTED
/* 'sig_bits' must be 1 or 2 leaving insignificant_bits 0 or
* 1. This may look silly but it allows a compact representation
* of 1 bit gray + 1 bit alpha (transparency):
*/
if (insignificant_bits /* only 1 bit significant */)
*--dp = PNG_BYTE((pixel >> 1) * 255U);
else
# endif
*--dp = PNG_BYTE(pixel * 85U);
if (dp <= ep) break;
}
shift += 2U;
}
debug(dp == ep && shift == 6U && sp == tc->sp);
break;
}
case 4:
{
unsigned int shift = 7U & -(tc->width << 2)/*overflow ok*/;
unsigned int s = *--sp;
# ifdef PNG_READ_sBIT_SUPPORTED
const unsigned int div = (1U << (4U-insignificant_bits)) - 1U;
# endif
for (;;)
{
if (shift == 8U) s = *--sp, shift = 0;
{
unsigned int pixel = (s >> shift) & 15U;
check_tRNS
# ifdef PNG_READ_sBIT_SUPPORTED
/* insignificant_bits may be 0, 1, 2 or 3, requiring a multiply
* by 17, 255/7, 85 or 255. Since this operation is always
* cached we don't much care about the time to do the divide
* below.
*/
if (insignificant_bits)
pixel = ((pixel>>insignificant_bits) * 255U + (div>>1)) / div;
else
# endif
pixel *= 17U;
*--dp = PNG_BYTE(pixel);
if (dp <= ep) break;
}
shift += 4U;
}
debug(dp == ep && shift == 4U && sp == tc->sp);
break;
}
default:
impossible("bit depth");
}
tc->sp = ep;
# undef check_tRNS
# undef png_ptr
}
static void
png_init_expand(png_transformp *transform, png_transform_controlp tc)
{
# define png_ptr (tc->png_ptr)
/* The possible combinations are:
*
* 1) PALETTE: the 'palette' flag should be set on the transform control and
* all that need be done is cancel this to cause the cache code to do the
* expansion.
*
* 2) LBP_GRAY, LBP_GRAY+tRNS: use png_do_expand_lbd_gray to do the required
* expand. Can be cached.
*
* 3) tRNS: scan the row for the relevant tRNS value.
*
* Note that expanding 8 to 16 bits is a byte op in pngtrans.c (it just
* replicates bytes).
*/
if (tc->palette)
{
debug(tc->caching && !(tc->format & PNG_FORMAT_FLAG_COLORMAP));
if (((*transform)->args & PNG_EXPAND_PALETTE) != 0U)
{
tc->palette = 0U;
tc->invalid_info |= PNG_INFO_PLTE + PNG_INFO_tRNS;
tc->cost = PNG_CACHE_COST_LIMIT; /* the cache is required! */
}
/* Note that this needs to happen when the row is processed (!tc->init) as
* well.
*/
}
else if (!(tc->format & PNG_FORMAT_FLAG_COLORMAP))
{
png_uint_32 args = (*transform)->args & PNG_BIC_MASK(PNG_EXPAND_PALETTE);
unsigned int bit_depth = tc->bit_depth;
debug(tc->init);
if (bit_depth >= 8U)
args &= PNG_BIC_MASK(PNG_EXPAND_LBD_GRAY);
# ifdef PNG_READ_tRNS_SUPPORTED
if (png_ptr->num_trans == 0U ||
(tc->format & PNG_FORMAT_FLAG_ALPHA) != 0U ||
(tc->invalid_info & PNG_INFO_tRNS) != 0U)
# endif
args &= PNG_BIC_MASK(PNG_EXPAND_tRNS);
(*transform)->args = args;
switch (args)
{
case PNG_EXPAND_LBD_GRAY:
tc->bit_depth = 8U;
tc->invalid_info |= PNG_INFO_tRNS;
if (tc->init == PNG_TC_INIT_FINAL)
(*transform)->fn = png_do_expand_lbd_gray;
break;
# ifdef PNG_READ_tRNS_SUPPORTED
case PNG_EXPAND_LBD_GRAY + PNG_EXPAND_tRNS:
tc->bit_depth = 8U;
tc->format |= PNG_FORMAT_FLAG_ALPHA;
tc->invalid_info |= PNG_INFO_tRNS;
tc->transparent_alpha = 1U;
/* In this case tRNS must be left unmodified for the expansion code
* to handle.
*/
if (tc->init == PNG_TC_INIT_FINAL)
(*transform)->fn = png_do_expand_lbd_gray;
break;
case PNG_EXPAND_tRNS:
if (tc->init == PNG_TC_INIT_FINAL)
{
png_expand *tr = png_transform_cast(png_expand, *transform);
affirm((tc->bit_depth == 8U || tc->bit_depth == 16U) &&
(tc->format &
(PNG_FORMAT_FLAG_COLORMAP|PNG_FORMAT_FLAG_ALPHA)) == 0U);
tr->ntrans = fill_transparent_pixel(png_ptr,
tr->transparent_pixel);
tr->tr.fn = png_do_expand_tRNS;
} /* TC_INIT_FINAL */
tc->format |= PNG_FORMAT_FLAG_ALPHA;
tc->invalid_info |= PNG_INFO_tRNS;
tc->transparent_alpha = 1U;
break;
# endif /* READ_tRNS */
default: /* transform not applicable */
(*transform)->fn = NULL;
break;
}
implies(tc->init == PNG_TC_INIT_FINAL,
(*transform)->fn != png_init_expand);
}
else /* not applicable */
{
debug(tc->init);
(*transform)->fn = NULL;
NOT_REACHED;
}
# undef png_ptr
}
void PNGAPI
png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
{
if (png_ptr != NULL)
png_add_transform(png_ptr, sizeof (png_expand), png_init_expand,
PNG_TR_EXPAND)->args |= PNG_EXPAND_LBD_GRAY;
}
/* Expand paletted images to 8-bit RGB or, if there is a tRNS chunk, RGBA.
* Note that this is effectively handled by the read code palette optimizations.
*
* API CHANGE: this used to have the completely unexpected side effect of
* turning on the above two optimizations.
*/
void PNGAPI
png_set_palette_to_rgb(png_structrp png_ptr)
{
if (png_ptr != NULL)
png_add_transform(png_ptr, sizeof (png_expand), png_init_expand,
PNG_TR_EXPAND)->args |= PNG_EXPAND_PALETTE;
}
/* Expand paletted images to RGB, expand grayscale images of less than 8-bit
* depth to 8-bit depth, and expand tRNS chunks to alpha channels. I.e. all the
* above.
*/
void PNGAPI
png_set_expand(png_structrp png_ptr)
{
if (png_ptr != NULL)
{
png_set_palette_to_rgb(png_ptr);
png_set_expand_gray_1_2_4_to_8(png_ptr);
png_set_tRNS_to_alpha(png_ptr);
}
}
#endif /* READ_EXPAND */
#if defined(PNG_READ_EXPAND_SUPPORTED) ||\
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
#define PNG_INIT_STRIP_ALPHA 1U
#define PNG_INIT_EXPAND_tRNS 2U
static void
png_init_alpha(png_transformp *transform, png_transform_controlp tc)
{
# define png_ptr (tc->png_ptr)
int required = 0;
# if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_tRNS_SUPPORTED)
if ((*transform)->args & PNG_INIT_EXPAND_tRNS)
{
/* Prior to 1.7 the alpha channel was stripped after expanding the tRNS
* chunk, so this effectively cancelled out the expand.
*/
if (png_ptr->num_trans > 0 && !tc->palette &&
!((*transform)->args & PNG_INIT_STRIP_ALPHA))
{
debug((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0);
required = 1;
tc->expand_tRNS = 1U;
/* This happens as a result of an explicit API call to
* png_set_tRNS_to_alpha, so expand low-bit-depth gray too:
*/
if (tc->init == PNG_TC_INIT_FORMAT)
png_add_transform(png_ptr, sizeof (png_expand), png_init_expand,
PNG_TR_EXPAND)->args |= PNG_EXPAND_tRNS + PNG_EXPAND_LBD_GRAY;
}
else
(*transform)->args &= PNG_BIC_MASK(PNG_INIT_EXPAND_tRNS);
}
# endif /* READ_EXPAND && READ_tRNS */
# ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
if ((*transform)->args & PNG_INIT_STRIP_ALPHA)
{
/* When compose is being done tRNS will be expanded regardless of the
* above test. Rather that trying to work out if this will happen the
* code just inserts a strip operation; it will be removed later if it
* is not needed.
*/
required = 1;
tc->strip_alpha = 1U;
if (tc->init == PNG_TC_INIT_FORMAT)
png_add_strip_alpha_byte_ops(png_ptr);
}
# endif /* READ_STRIP_ALPHA */
if (!required)
(*transform)->fn = NULL;
# undef png_ptr
}
#endif /* READ_EXPAND || READ_STRIP_ALPHA */
#ifdef PNG_READ_EXPAND_SUPPORTED
/* Expand tRNS chunks to alpha channels. This only expands the tRNS chunk on
* non-palette formats; call png_set_palette_to_rgb to get the corresponding
* effect for a palette.
*
* Note that this will expand low bit depth gray if there is a tRNS chunk, but
* if not nothing will happen.
*
* API CHANGE: this used to do all the expansions, it was rather pointless
* calling it.
*/
void PNGAPI
png_set_tRNS_to_alpha(png_structrp png_ptr)
{
if (png_ptr != NULL)
png_add_transform(png_ptr, 0/*size*/, png_init_alpha, PNG_TR_INIT_ALPHA)->
args |= PNG_INIT_EXPAND_tRNS;
}
#endif /* READ_EXPAND */
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
void PNGAPI
png_set_strip_alpha(png_structrp png_ptr)
{
if (png_ptr != NULL)
png_add_transform(png_ptr, 0/*size*/, png_init_alpha, PNG_TR_INIT_ALPHA)->
args |= PNG_INIT_STRIP_ALPHA;
}
#endif /* READ_STRIP_ALPHA */
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
static void
png_do_chop_16_to_8(png_transformp *transform, png_transform_controlp tc)
/* This is actually a repeat of the byte transform, unnecessary code
* replication.
*
* TODO: remove this
*/
{
# define png_ptr (tc->png_ptr)
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp); /* source */
png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc); /* end+1 */
png_bytep dp = png_voidcast(png_bytep, tc->dp); /* destination */
debug(tc->bit_depth == 16U);
tc->sp = dp;
tc->bit_depth = 8U;
while (sp < ep)
*dp++ = *sp, sp += 2;
debug(sp == ep);
# undef png_ptr
PNG_UNUSED(transform)
}
/* A transform containing some useful scaling values... */
typedef struct
{
png_transform tr;
png_uint_32 shifts; /* 4 4-bit values preceeded by a shibboleth (1) */
png_uint_32 channel_scale[4];
} png_transform_scale_16_to_8;
/* Scale rows of bit depth 16 down to 8 accurately */
static void
png_do_scale_16_to_8(png_transformp *transform, png_transform_controlp tc)
{
# define png_ptr (tc->png_ptr)
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp); /* source */
png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc); /* end+1 */
png_bytep dp = png_voidcast(png_bytep, tc->dp); /* destination */
png_transform_scale_16_to_8 *tr =
png_transform_cast(png_transform_scale_16_to_8, *transform);
png_uint_32p scale = 0;
png_uint_32 shift = 1U; /* set the shibboleth at the start */
debug(tc->bit_depth == 16U);
tc->sp = dp;
tc->bit_depth = 8U;
while (sp < ep)
{
/* The input is an array of 16 bit components, these must be scaled to
* 8 bits each taking into account the sBIT setting. The calculation
* requires that the insignificant bits be stripped from the input value
* via a shift then scaled back to 8 bits:
*
* output = ((input >> shift) * scale + round) >> 24
*
* The shifts are packed into tr->shifts, with the end of the list marked
* by a shibboleth, 1, which is preset above.
*/
png_uint_32 v = png_get_uint_16(sp);
sp += 2;
if (shift == 1U)
{
shift = tr->shifts;
scale = tr->channel_scale;
}
*dp++ = PNG_BYTE(((v >> (shift & 0xFU)) * *scale++ + 0x800000U) >> 24);
shift >>= 4;
}
affirm(sp == ep);
# undef png_ptr
}
static int
add_scale(png_transform_scale_16_to_8 *tr, unsigned int sBIT, unsigned int ch)
{
/* This is the output max (255) scaled by 2^24 divided by the input max'
* (which is variable) and rounded. It gives the exact 8-bit answer for all
* input sBIT depths when used in the calculation:
*
* output = ((input >> shift) * scale + 0x800000U) >> 24
*/
tr->channel_scale[ch] = (0xFF000000U + ((1U<<sBIT)>>1)) / ((1U<<sBIT)-1U);
tr->shifts |= ((16U-sBIT) & 0xFU) << (4U*ch);
/* The result says whether there are 8 or fewer significant bits in the
* input value; if so we can just drop the low byte.
*/
return sBIT <= 8U;
}
static void
png_init_scale_16_to_8(png_transformp *transform, png_transform_controlp tc)
{
if (tc->bit_depth == 16U)
{
# define png_ptr (tc->png_ptr)
tc->bit_depth = 8U;
/* But this invalidates tRNS (a 16-bit tRNS cannot be updated to match
* 8-bit data correctly).
*/
tc->invalid_info |= PNG_INFO_tRNS+PNG_INFO_hIST+PNG_INFO_pCAL;
/* TODO: These need further processing: PNG_INFO_bKGD */
if (tc->init == PNG_TC_INIT_FINAL)
{
png_transform_scale_16_to_8 *tr =
png_transform_cast(png_transform_scale_16_to_8, *transform);
/* Set the scale factors for each channel (up to 4), the factors are
* made so that:
*
* ((channel >> shift) * factor + 0x800000U) >> 24
*
* Gives the required 8-bit value. The 'shift' is stored in a single
* png_uint_32 with a shibboleth at the end.
*/
unsigned int channels = 0U;
int chop_ok = 1;
tr->shifts = 0U;
/* This adds up to four scale factors, the remainder are left as 0
* which is safe and leads to obvious errors in the output images in
* the event of an (internal) error.
*/
if (tc->format & PNG_FORMAT_FLAG_COLOR)
chop_ok &= add_scale(tr, tc->sBIT_R, channels++);
chop_ok &= add_scale(tr, tc->sBIT_G, channels++);
if (tc->format & PNG_FORMAT_FLAG_COLOR)
chop_ok &= add_scale(tr, tc->sBIT_B, channels++);
if (tc->format & PNG_FORMAT_FLAG_ALPHA)
chop_ok &= add_scale(tr, tc->sBIT_A, channels++);
if (chop_ok)
tr->tr.fn = png_do_chop_16_to_8;
else
{
int handled = 1;
/* Add the shibboleth at the end */
tr->shifts |= 1U << (4U*channels);
tr->tr.fn = png_do_scale_16_to_8;
/* sBIT is a little tricky; it has to be processed in the scaling
* operation. The result will have the same number of bits unless
* there were more than 8 before. The sBIT flags in the transform
* control are left unchanged here because the data is still valid,
* unless all the values end up as 8 in which case there is no
* remaining sBIT info.
*
* Note that fields, such as alpha, which are not set for this row
* format will always have max values, so won't reset 'handled':
*/
if (tc->sBIT_R >= 8U) tc->sBIT_R = 8U; else handled = 0;
if (tc->sBIT_G >= 8U) tc->sBIT_G = 8U; else handled = 0;
if (tc->sBIT_B >= 8U) tc->sBIT_B = 8U; else handled = 0;
if (tc->sBIT_A >= 8U) tc->sBIT_A = 8U; else handled = 0;
/* If all the sBIT values were >= 8U all the bits are now
* significant:
*/
if (handled)
tc->invalid_info |= PNG_INFO_sBIT;
}
}
# undef png_ptr
}
else /* not applicable */
(*transform)->fn = NULL;
}
void PNGAPI
png_set_scale_16(png_structrp png_ptr)
{
if (png_ptr != NULL)
png_add_transform(png_ptr, sizeof (png_transform_scale_16_to_8),
png_init_scale_16_to_8, PNG_TR_SCALE_16_TO_8);
}
#endif /* READ_SCALE_16_TO_8 */
#ifdef PNG_READ_GAMMA_SUPPORTED
/* Code that depends on READ_GAMMA support; RGB to gray convertion and
* background composition (including the various alpha-mode handling
* operations which produce pre-multiplied alpha by composing on 0).
*/
/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
static png_fixed_point
png_reciprocal(png_fixed_point a)
{
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
double r = floor(1E10/a+.5);
if (r <= 2147483647. && r >= -2147483648.)
return (png_fixed_point)r;
#else
png_fixed_point res;
if (png_muldiv(&res, PNG_FP_1, PNG_FP_1, a) != 0)
return res;
#endif
return 0; /* error/overflow */
}
/* This is the shared test on whether a gamma value is 'significant' - whether
* it is worth doing gamma correction. 'significant_bits' is the number of bits
* in the values to be corrected which are significant.
*/
static int
png_gamma_significant(png_const_structrp png_ptr, png_fixed_point gamma_val,
unsigned int sbits)
{
#if 0
/* This seems to be wrong. The issue is that when the app asks for a higher
* bit depth output than the input has significant bits it causes gamma
* correction to be skipped (this was the intent) however there's no
* particular guarantee that the app won't go on to do further gamma
* processing - pngstest does this - and this messes up the results
* completely.
*
* TODO: work out how to optimize this correctly.
*/
/* The following table lists the threshold as a difference from PNG_FP_1 at
* which the gamma correction will make a change to at least an 'sbits'
* value. There is no entry for 1 bit values; gamma correction is never
* significant.
*/
static const png_uint_16 gamma_threshold_by_sbit[15][2] =
{
{ 36907, 63092 }, /* 2 bits */
{ 17812, 21518 }, /* 3 bits */
{ 8675, 9496 }, /* 4 bits */
{ 4290, 4484 }, /* 5 bits */
{ 2134, 2181 }, /* 6 bits */
{ 1064, 1075 }, /* 7 bits */
{ 531, 534 }, /* 8 bits */
{ 265, 266 }, /* 9 bits */
{ 132, 132 }, /* 10 bits */
{ 66, 66 }, /* 11 bits */
{ 33, 33 }, /* 12 bits */
{ 16, 16 }, /* 13 bits */
{ 8, 8 }, /* 14 bits */
{ 4, 4 }, /* 15 bits */
{ 2, 2 }, /* 16 bits */
};
/* Handle out of range values in release by doing the gamma correction: */
debug_handled(sbits > 0U && sbits <= 16U);
if (sbits == 0U || sbits > 16U)
return 1;
/* 1 bit input or zero gamma, no correction possible/required: */
if (gamma_val == 0 || sbits < 2U)
return 0;
if (gamma_val < PNG_FP_1 - gamma_threshold_by_sbit[sbits-2U][0U])
return gamma_val < PNG_FP_1 - png_ptr->gamma_threshold;
else if (gamma_val > PNG_FP_1 + gamma_threshold_by_sbit[sbits-2U][1U])
return gamma_val > PNG_FP_1 + png_ptr->gamma_threshold;
#else /* FIXUP */
if (gamma_val < PNG_FP_1)
return gamma_val < PNG_FP_1 - png_ptr->gamma_threshold;
else if (gamma_val > PNG_FP_1)
return gamma_val > PNG_FP_1 + png_ptr->gamma_threshold;
PNG_UNUSED(sbits)
#endif /* FIXUP */
return 0; /* not significant */
}
static int
png_gamma_equal(png_const_structrp png_ptr, png_fixed_point g1,
png_fixed_point g2, png_fixed_point *c, unsigned int sbits)
/* Gamma values are equal, or at least one is unknown; c is the correction
* factor from g1 to g2, i.e. g2/g1.
*/
{
return sbits == 1U || g1 == 0 || g2 == 0 || g1 == g2 ||
(png_muldiv(c, g2, PNG_FP_1, g1) &&
!png_gamma_significant(png_ptr, *c, sbits));
}
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
int
png_need_gamma_correction(png_const_structrp png_ptr, png_fixed_point gamma,
int sRGB_output)
/* This is a hook for the simplified code; it just decides whether or not the
* given gamma (which defaults to that of the PNG data) is close enough to
* linear or sRGB not to require gamma correction.
*/
{
if (gamma == 0)
gamma = png_ptr->colorspace.gamma;
if (gamma != 0 &&
(png_ptr->colorspace.flags &
(PNG_COLORSPACE_INVALID|PNG_COLORSPACE_HAVE_GAMMA)) ==
PNG_COLORSPACE_HAVE_GAMMA)
{
if (sRGB_output && !png_muldiv(&gamma, gamma, PNG_GAMMA_sRGB, PNG_FP_1))
return 0; /* overflow, so no correction */
return png_gamma_significant(png_ptr, gamma, (png_ptr->color_type &
PNG_COLOR_MASK_PALETTE) ? 8U : png_ptr->bit_depth);
}
return 0; /* no info, no correction */
}
#endif /* SIMPLIFIED_READ */
#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
/* Fixed point gamma.
*
* The code to calculate the tables used below can be found in the shell script
* contrib/tools/intgamma.sh
*
* To calculate gamma this code implements fast log() and exp() calls using only
* fixed point arithmetic. This code has sufficient precision for either 8-bit
* or 16-bit sample values.
*
* The tables used here were calculated using simple 'bc' programs, but C double
* precision floating point arithmetic would work fine.
*
* 8-bit log table
* This is a table of -log(value/255)/log(2) for 'value' in the range 128 to
* 255, so it's the base 2 logarithm of a normalized 8-bit floating point
* mantissa. The numbers are 32-bit fractions.
*/
static const png_uint_32
png_8bit_l2[128] =
{
4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U,
3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U,
3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U,
3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U,
3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U,
2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U,
2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U,
2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U,
2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U,
2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U,
1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U,
1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U,
1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U,
1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U,
1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U,
971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U,
803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U,
639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U,
479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U,
324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U,
172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U,
24347096U, 0U
#if 0 /* NOT USED */
/* The following are the values for 16-bit tables - these work fine for the
* 8-bit conversions but produce very slightly larger errors in the 16-bit
* log (about 1.2 as opposed to 0.7 absolute error in the final value). To
* use these all the shifts below must be adjusted appropriately.
*/
65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054,
57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803,
50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068,
43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782,
37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887,
31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339,
25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098,
20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132,
15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415,
10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523,
6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495,
1119, 744, 372
#endif
};
#if 0 /* UNUSED */
static png_int_32
png_log8bit(unsigned int x)
{
png_uint_32 lg2 = 0U;
/* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log,
* because the log is actually negate that means adding 1. The final
* returned value thus has the range 0 (for 255 input) to 7.994 (for 1
* input), return -1 for the overflow (log 0) case, - so the result is
* always at most 19 bits.
*/
if ((x &= 0xffU) == 0U) /* 0 input, -inf output */
return -0xfffff;
if ((x & 0xf0U) == 0U)
lg2 = 4U, x <<= 4;
if ((x & 0xc0U) == 0U)
lg2 += 2U, x <<= 2;
if ((x & 0x80U) == 0U)
lg2 += 1U, x <<= 1;
/* result is at most 19 bits, so this cast is safe: */
return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128U]+32768U)>>16));
}
#endif /* UNUSED */
/* The above gives exact (to 16 binary places) log2 values for 8-bit images,
* for 16-bit images we use the most significant 8 bits of the 16-bit value to
* get an approximation then multiply the approximation by a correction factor
* determined by the remaining up to 8 bits. This requires an additional step
* in the 16-bit case.
*
* We want log2(value/65535), we have log2(v'/255), where:
*
* value = v' * 256 + v''
* = v' * f
*
* So f is value/v', which is equal to (256+v''/v') since v' is in the range 128
* to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less
* than 258. The final factor also needs to correct for the fact that our 8-bit
* value is scaled by 255, whereas the 16-bit values must be scaled by 65535.
*
* This gives a final formula using a calculated value 'x' which is value/v' and
* scaling by 65536 to match the above table:
*
* log2(x/257) * 65536
*
* Since these numbers are so close to '1' we can use simple linear
* interpolation between the two end values 256/257 (result -368.61) and 258/257
* (result 367.179). The values used below are scaled by a further 64 to give
* 16-bit precision in the interpolation:
*
* Start (256): -23591
* Zero (257): 0
* End (258): 23499
*
* In libpng 1.7.0 this is further generalized to return -log2(value/maxval) for
* any maxval up to 65535. This is done by evaluating -log2(value/65535) first
* then adjusting for the required maxval:
*
* ( value) (value 65535) (value) ( 65535)
* -log2(------) = -log2(----- x ------) = -log2(-----)-log2(------)
* (maxval) (65535 maxval) (65535) (maxval)
*
* The extra argument, 'factor', is (2^(16+12))*log2(65535/maxval) (a positive
* value less than 2^32) and this is *subtracted* from the intermediate
* calculation below.
*/
static png_int_32
png_log(unsigned int x, png_uint_32 factor)
/* x: a value of up to 16 bits,
* factor: a 4.28 number which is subtracted from the log below
*/
{
png_uint_32 lg2 = 0U;
/* As above, but now the input has 16 bits. */
if ((x &= 0xffffU) == 0U)
return -0xfffff;
if ((x & 0xff00U) == 0U)
lg2 = 8U, x <<= 8;
if ((x & 0xf000U) == 0U)
lg2 += 4U, x <<= 4;
if ((x & 0xc000U) == 0U)
lg2 += 2U, x <<= 2;
if ((x & 0x8000U) == 0U)
lg2 += 1U, x <<= 1;
/* Calculate the base logarithm from the top 8 bits as a 28-bit fractional
* value.
*/
lg2 <<= 28;
lg2 += (png_8bit_l2[(x>>8)-128U]+8U) >> 4;
/* Now we need to interpolate the factor, this requires a division by the top
* 8 bits. Do this with maximum precision.
*/
{
png_uint_32 i = x;
i = ((i << 16) + (i >> 9)) / (x>> 8);
/* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24,
* the value at 1<<16 (ignoring this) will be 0 or 1; this gives us
* exactly 16 bits to interpolate to get the low bits of the result.
* Round the answer. Note that the end point values are scaled by 64 to
* retain overall precision and that 'lg2' is current scaled by an extra
* 12 bits, so adjust the overall scaling by 6-12. Round at every step.
*/
i -= 1U << 24;
if (i <= 65536U) /* <= '257' */
lg2 += ((23591U * (65536U-i)) + (1U << (16+6-12-1))) >> (16+6-12);
else
lg2 -= ((23499U * (i-65536U)) + (1U << (16+6-12-1))) >> (16+6-12);
}
if (lg2 >= factor)
return (png_int_32)/*SAFE*/((lg2 - factor + 2048U) >> 12);
else /* the result will be greater than 1.0, so negative: */
return -(png_int_32)/*SAFE*/((factor - lg2 + 2048U) >> 12);
}
#if 0 /* UNUSED */
static png_int_32
png_log16bit(unsigned int x)
{
return png_log(x, 0U);
}
#endif /* UNUSED */
/* libpng 1.7.0: generalization of png_log{8,16}bit to accept an n-bit input
* value. We want to maintain 1% accuracy in linear light space. This
* corresponds to, approximately, (1*g)% in a gamma encoded space where the
* gamma encoding is 'g' (in the PNG sense, e.g. 0.45455 for sRGB). Apparently
* this requires unbounded accuracy as the gamma encoding value goes down and
* this is a problem for modern HDR data because it may require a high gamma to
* accurately encode image data over a wide dynamic range; the dynamic range of
* 16-bit linear data is only 655:1 if 1% accuracy is needed!
*
* However 16-bit gamma encoded data is still limited because PNG can only
* express gamma encoding. (A log-to-base-1.01 encoding is unlimited; a 12-bit
* value, with 4094 steps, has a dynamic range of more than 1:10^17, which
* exceeds the human eye's range of 1:10^14.)
*
* Notice that sRGB uses a 1/2.4 encoding and CIELab uses a 1/3 encoding. It is
* obvious that, if we assume a maximum D difference in the luminance of
* adjacent pixel values the dynamic range is given by the lowest pixel value
* which is D or less greater than its predecessor, so:
*
* ( P ) (1)
* (---)^(-) = D
* (P-1) (g)
*
* and the maximum dynamic range that can be achieved using M+1 separate values,
* where M+1 is 2^N-1 for an N bit value, reserving the first value for 0, is:
*
* (M) (1)
* range(R) = (-)^(-)
* (P) (g)
*
* So we can eliminate 'P' from the two equations:
*
* P = (P-1) x (D^g)
*
* D^g
* P = -----
* D^g-1
*
* (M x (D^g-1)) (1)
* R = (-----------)^(-)
* ( D^g ) (g)
*
* (M x (D^g-1)) ^ (1/g)
* = ---------------------
* D
*
* Which is a function in two variables (R and g) for a given D (maximum delta
* between two adjacent pixel values) and M (number of pixel values, controlled
* by the channel bit depth).
*
* See contrib/tools/dynamic-range.c for code exploring this function. This
* program will output the optimal gamma for a given number of bits and
* precision.
*
* The range of sensitivity of human vision is roughly as follows (this comes
* from the wikipedia article on scotopic vision):
*
* scotopic: 10^-6 to 10^-3.5 cd/m^2
* mesopic: 10^-3 to 10^0.5 cd/m^2
* photopic: 10 to 10^8 cd/m^2
*
* Giving a total range of about 1:10^14. The maximum precision at which this
* range can be achieved using 16-bit channels is about .15% using a gamma of
* 36, higher ranges are possible using higher gammas but precision is reduced.
* The range with 1% precision and 16-bit channels is 1:10^104, using a gamma of
* 240.
*
* In general the optimal gamma for n-bit channels (where 'n' is at least 7 and
* precision is .01 or less) is:
*
* 2^n * precision
* gamma = ---------------
* 2.736
*
* Or: (24000 * precision) for 16-bit data.
*
* The net effect is that we can't rely on the encoding gamma being limited to
* values around 1/2.5!
*/
static png_int_32
png_log_nbit(unsigned int x, unsigned int nbits)
{
static const png_uint_32 factors[16] =
{
4294961387U, /* 1 bit */
3869501255U, /* 2 bit */
3541367788U, /* 3 bit */
3246213428U, /* 4 bit */
2965079441U, /* 5 bit */
2690447525U, /* 6 bit */
2418950626U, /* 7 bit */
2148993476U, /* 8 bit */
1879799410U, /* 9 bit */
1610985205U, /* 10 bit */
1342360514U, /* 11 bit */
1073830475U, /* 12 bit */
805347736U, /* 13 bit */
536888641U, /* 14 bit */
268441365U, /* 15 bit */
0U /* 16 bit */
};
return png_log(x, factors[nbits-1]);
}
/* The 'exp()' case must invert the above, taking a 20-bit fixed point
* logarithmic value and returning a 16 or 8-bit number as appropriate. In
* each case only the low 16 bits are relevant - the fraction - since the
* integer bits (the top 4) simply determine a shift.
*
* The worst case is the 16-bit distinction between 65535 and 65534. This
* requires perhaps spurious accuracy in the decoding of the logarithm to
* distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance
* of needing this accuracy in practice.
*
* To deal with this the following exp() function works out the exponent of the
* frational part of the logarithm by using an accurate 32-bit value from the
* top four fractional bits then multiplying in the remaining bits.
*/
static const png_uint_32
png_32bit_exp[16] =
{
/* NOTE: the first entry is deliberately set to the maximum 32-bit value. */
4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U,
3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U,
2553802834U, 2445529972U, 2341847524U, 2242560872U
};
/* Adjustment table; provided to explain the numbers in the code below. */
#if 0 /* BC CODE */
for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
11 44937.64284865548751208448
10 45180.98734845585101160448
9 45303.31936980687359311872
8 45364.65110595323018870784
7 45395.35850361789624614912
6 45410.72259715102037508096
5 45418.40724413220722311168
4 45422.25021786898173001728
3 45424.17186732298419044352
2 45425.13273269940811464704
1 45425.61317555035558641664
0 45425.85339951654943850496
#endif
static png_uint_32
png_exp(png_int_32 x)
/* Utility, the value 'x' must be in the range 0..0x1fffff */
{
/* Obtain a 4-bit approximation */
png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf];
/* Incorporate the low 12 bits - these decrease the returned value by
* multiplying by a number less than 1 if the bit is set. The multiplier
* is determined by the above table and the shift. Notice that the values
* converge on 45426 and this is used to allow linear interpolation of the
* low bits.
*/
if (x & 0x800)
e -= (((e >> 16) * 44938U) + 16U) >> 5;
if (x & 0x400)
e -= (((e >> 16) * 45181U) + 32U) >> 6;
if (x & 0x200)
e -= (((e >> 16) * 45303U) + 64U) >> 7;
if (x & 0x100)
e -= (((e >> 16) * 45365U) + 128U) >> 8;
if (x & 0x080)
e -= (((e >> 16) * 45395U) + 256U) >> 9;
if (x & 0x040)
e -= (((e >> 16) * 45410U) + 512U) >> 10;
/* And handle the low 6 bits in a single block. */
e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9;
/* Handle the upper bits of x, note that this works for x up to 0x1fffff but
* fails for larger or negative x, where the shift (x >> 16) exceeds 31:
*/
e >>= x >> 16;
return e;
}
#if 0 /* UNUSED */
static png_byte
png_exp8bit(png_int_32 lg2)
{
/* The input is a negative fixed point (16:16) logarithm with a useable range
* of [0.0..8.0). Clamp the value so that the output of png_exp is in the
* range (254.5/255..0.5/255):
*/
if (lg2 <= 185) /* -log2(254.5/255) */
return 255U;
else if (lg2 > 589453) /* -log2(0.5/255) */
return 0U;
else
{
/* Get a 32-bit value: */
png_uint_32 x = png_exp(lg2);
/* Convert the 32-bit value to 0..255 by multiplying by 256-1. Note that
* the second, rounding, step can't overflow because of the first,
* subtraction, step.
*/
x -= x >> 8;
return PNG_BYTE((x + 0x7fffffU) >> 24);
}
}
static png_uint_16
png_exp16bit(png_int_32 lg2)
{
if (lg2 <= 0) /* -log2(65534.5/65535) */
return 65535U;
else if (lg2 > 1114110) /* -log2(0.5/65535) */
return 0U;
else
{
/* Get a 32-bit value: */
png_uint_32 x = png_exp(lg2);
/* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */
x -= x >> 16;
return PNG_UINT_16((x + 32767U) >> 16);
}
}
#endif /* UNUSED */
static png_uint_32
png_exp_nbit(png_int_32 lg2, unsigned int n)
{
/* These pre-computed limits give the low value of lg2 at and below which
* 2^(-lg2/65536) * (2^n-1) gives (2^n-1) and the high value of lg2 above
* which 2(^-lg2/65536) * (2^n-1) gives 0:
*/
static const png_int_32 limits[16][2] =
{
{ 65535, 65535 }, /* bits = 1 */
{ 17238, 169408 }, /* bits = 2 */
{ 7006, 249518 }, /* bits = 3 */
{ 3205, 321577 }, /* bits = 4 */
{ 1537, 390214 }, /* bits = 5 */
{ 753, 457263 }, /* bits = 6 */
{ 372, 523546 }, /* bits = 7 */
{ 185, 589453 }, /* bits = 8 */
{ 92, 655175 }, /* bits = 9 */
{ 46, 720803 }, /* bits = 10 */
{ 23, 786385 }, /* bits = 11 */
{ 11, 851944 }, /* bits = 12 */
{ 5, 917492 }, /* bits = 13 */
{ 2, 983034 }, /* bits = 14 */
{ 1, 1048573 }, /* bits = 15 */
{ 0, 1114110 } /* bits = 16 */
};
/* If 'max' is 2^n-1: */
if (lg2 <= limits[n-1][0]) /* -log2((max-.5)/max) */
return (1U << n)-1U;
else if (lg2 > limits[n-1][1]) /* -log2(.5/max) */
return 0U;
else /* 'n' will be at least 2 */
{
/* Get a 32-bit value: */
png_uint_32 x = png_exp(lg2);
/* Convert the 32-bit value to 0..(2^n-1) by multiplying by 2^n-1: */
x -= x >> n;
return (x + ((1U<<(31U-n))-1U)) >> (32U-n);
}
}
#endif /* !FLOATING_ARITHMETIC */
#if 0 /* UNUSED */
static png_byte
png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val)
{
if (value == 0U)
return 0U;
else if (value >= 255U)
return 255U;
else
{
# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
/* 'value' is unsigned, ANSI-C90 requires the compiler to correctly
* convert this to a floating point value. This includes values that
* would overflow if 'value' were to be converted to 'int'.
*
* Apparently GCC, however, does an intermediate conversion to (int)
* on some (ARM) but not all (x86) platforms, possibly because of
* hardware FP limitations. (E.g. if the hardware conversion always
* assumes the integer register contains a signed value.) This results
* in ANSI-C undefined behavior for large values.
*
* Other implementations on the same machine might actually be ANSI-C90
* conformant and therefore compile spurious extra code for the large
* values.
*
* We can be reasonably sure that an unsigned to float conversion
* won't be faster than an int to float one. Therefore this code
* assumes responsibility for the undefined behavior, which it knows
* can't happen because of the check above.
*
* Note the argument to this routine is an (unsigned int) because, on
* 16-bit platforms, it is assigned a value which might be out of
* range for an (int); that would result in undefined behavior in the
* caller if the *argument* ('value') were to be declared (int).
*/
double r = 255*pow((int)/*SAFE*/value/255.,gamma_val*.00001);
if (r < .5)
return 0U;
else if (r >= 254.5)
return 255U;
r = floor(r+.5);
return (png_byte)/*SAFE*/r;
# else
png_int_32 lg2 = png_log8bit(value);
png_int_32 res;
/* Overflow in the muldiv means underflow in the calculation, this is
* OK (it happens for ridiculously high gamma).
*/
if (!png_muldiv(&res, gamma_val, lg2, PNG_FP_1))
return 0U; /* underflow */
return png_exp8bit(res);
# endif
}
}
#endif /* UNUSED */
/* libpng-1.7.0: this private function converts an n-bit input value to an
* m-bit output value.
*/
unsigned int
png_gamma_nxmbit_correct(unsigned int value, png_fixed_point gamma_val,
unsigned int n/*input bits*/, unsigned int m/*output bits */)
{
if (value == 0U)
return 0U;
else
{
unsigned int min = (1U<<n) - 1U;
unsigned int mout = (1U<<m) - 1U;
if (value >= min)
return mout;
else
{
# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
double r = value;
r /= min;
r = floor(mout * pow(r, gamma_val*.00001)+.5);
if (r < 1)
return 0U;
else if (r >= mout)
return mout;
return (unsigned int)/*SAFE*/r;
# else
png_int_32 lg2 = png_log_nbit(value, n);
png_int_32 res;
if (!png_muldiv(&res, gamma_val, lg2, PNG_FP_1))
return 0U; /* underflow */
return png_exp_nbit(res, m);
# endif
}
}
}
#if 0 /*UNUSED*/
static unsigned int
png_gamma_sbit_correct(unsigned int value, png_fixed_point gamma_val,
unsigned int n/*input bits*/, unsigned int sbits,
unsigned int m/*output bits */)
/* As above but the number of significant bits in 'n' is passed in. */
{
if (sbits < n)
{
value >>= (n-sbits);
n = sbits;
}
return png_gamma_nxmbit_correct(value, gamma_val, n, m);
}
#endif /*UNUSED*/
static int
push_gamma_expand(png_transformp *transform, png_transform_controlp tc,
int need_alpha)
/* Utility to push a transform to expand low-bit-depth gray and, where
* required, tRNS chunks. The caller must return immediately if this
* returns true because the init of the new transform has been run in place
* of the caller's.
*/
{
# define png_ptr (tc->png_ptr)
unsigned int expand = 0;
affirm(tc->init == PNG_TC_INIT_FINAL);
if (tc->bit_depth < 8U) /* low bit gray: expand to 8 bits */
expand = PNG_EXPAND_LBD_GRAY;
/* Gamma correction invalidates tRNS, so if it is being expanded and
* alpha is not being stripped expand it now.
*/
if ((tc->format & PNG_FORMAT_FLAG_ALPHA) == 0 && !tc->palette &&
png_ptr->num_trans == 1 && (tc->invalid_info & PNG_INFO_tRNS) == 0)
{
if (need_alpha || (tc->expand_tRNS && !tc->strip_alpha))
expand |= PNG_EXPAND_tRNS;
else
tc->invalid_info |= PNG_INFO_tRNS;
}
if (expand == 0)
return 0; /* nothing needs to be done */
{
png_transformp tr = png_push_transform(png_ptr, sizeof (png_expand),
png_init_expand, transform, NULL/*don't run init*/);
debug(tr == *transform);
tr->args |= expand;
/* This must be run immediately, because it just got inserted where this
* transform is; this is safe, the caller must return immediately.
*/
png_init_expand(transform, tc);
affirm(tr->fn != NULL); /* because it should need to do something! */
}
return 1;
# undef png_ptr
}
/* Low bit depth gray gamma correction. The 1-bit case is a no-op because 0 and
* 1 always map to 0 and 1. The 2-bit case has the following possiblities:
*
* bits/correction: g0 g1 g2 g3 g4 g5 g6
* 00 -> 00 00 00 00 00 00 00
* 01 -> 11 10 10 01 00 00 00
* 10 -> 11 11 10 10 10 01 00
* 11 -> 11 11 11 11 11 11 11
*
* Where the breakpoints are:
*
* g0: correction <= 16595 (1 - log(2.5/3))
* g1: 16595 < correction <= 44966 (log(2.5/3)/log(2/3))
* g2: 44966 < correction <= 63092 (1 - log(1.5/3))
* g3: 63092 < correction <= 163092 (1 - log(.5/3))
* g4: 163092 < correction <= 170951 (log(1.5/3)/log(2/3))
* g5: 170951 < correction <= 441902 (log(.5/3)/log(2/3)
* g6 441902 < correction
*
* This can be done by bit-hacking on the byte values (4 pixels), given that
* the correction is fixed (indeed, it can be done on whole 32-bit values!)
*
* g0: B |= B>>1; B &= 0x55U; B |= B<<1; * either bit set
* g1: B ^= B>>1; B &= 0x55U; B += B; * one bit set
* g2: B &= (~B)>>1; B &= 0x55U; B += B; * low bit set, high bit unset
* g3: no-op
* g4: B &= (~B)>>1; B &= 0x55U; B -= B; * low bit set, high bit unset
* g5: B ^= B>>1; B &= 0x55U; B -= B; * one bit set
* g6: B &= B>>1; B &= 0x55U; B |= B<<1; * both bits set
*/
typedef struct
{
png_transform tr;
png_fixed_point correct;
png_fixed_point to_gamma;
png_uint_32 shifts; /* 1 followed by up to 4 4-bit shifts */
png_uint_32 channel_scale[4]; /* up to 4 channel scale factors */
/* These factors are used:
*
* (input >> (shifts & 0xFU) * channel_scale + SCALE_R) >> SCALE_S
*
* Where the rounding value, SCALE_R and the shift SCALE_S are dependent
* on the bit depth:
*
* SCALE_S = 32 - bit_depth range 16..31
* SCALE_R = 1 << (SCALE_S-1)
*/
unsigned int to_bit_depth;
unsigned int encode_alpha :1;
unsigned int optimize_alpha :1;
} png_transform_gamma;
static unsigned int
init_gamma_sBIT(png_transform_gamma *tr, png_transform_controlp tc)
/* Returns true if sBIT processing is required, otherwise all relevant sBIT
* values match the from (tc) bit depth.
*/
{
/* The to_bit_depth and to_gamma fields are already set, but updated values
* are needed for sBIT and the shifts and channel_scale fields must be filled
* in correctly. The do_gamma setting says whether gamma correction will be
* done, but the scale factors are filled in regardless.
*
* The general scaling equation is:
*
* ((in >> shift) * factor + round) >> (32 - to_bit_depth)
*
* 'factor' is then the rounded value of:
*
* out_max
* ------- . (1 << (32-to_bit_depth))
* in_max
*/
# define png_ptr (tc->png_ptr)
const unsigned int to_bit_depth = tr->to_bit_depth;
const png_uint_32 numerator = ((1U<<to_bit_depth)-1U) << (32U-to_bit_depth);
/* in_max depends on the number of significant bits */
const unsigned int from_bit_depth = tc->bit_depth;
/* The data in the gamma transform is stored in the order of the channels in
* the input row, which is the PNG order. It may be reversed below.
*/
png_uint_32p channel_scale = tr->channel_scale;
png_uint_32 shifts = 0U;
unsigned int count = 0U;
unsigned int need_sBIT = 0U;
if (tc->format & PNG_FORMAT_FLAG_COLOR)
{
const unsigned int sBIT = tc->sBIT_R;
if (sBIT < from_bit_depth)
need_sBIT = 1U;
debug(sBIT > 0U && sBIT <= from_bit_depth);
shifts |= (from_bit_depth - sBIT) << count;
count += 4U;
/* round the scale: */
*channel_scale++ = (numerator + (1U<<(sBIT-1U))) / ((1U << sBIT)-1U);
}
{
const unsigned int sBIT = tc->sBIT_G;
if (sBIT < from_bit_depth)
need_sBIT = 1U;
debug(sBIT > 0U && sBIT <= from_bit_depth);
shifts |= (from_bit_depth - sBIT) << count;
count += 4U;
*channel_scale++ = (numerator + (1U<<(sBIT-1U))) / ((1U << sBIT)-1U);
}
if (tc->format & PNG_FORMAT_FLAG_COLOR)
{
const unsigned int sBIT = tc->sBIT_B;
if (sBIT < from_bit_depth)
need_sBIT = 1U;
debug(sBIT > 0U && sBIT <= from_bit_depth);
shifts |= (from_bit_depth - sBIT) << count;
count += 4U;
/* round the scale: */
*channel_scale++ = (numerator + (1U<<(sBIT-1U))) / ((1U << sBIT)-1U);
}
if (tc->format & PNG_FORMAT_FLAG_ALPHA)
{
const unsigned int sBIT = tc->sBIT_A;
if (sBIT < from_bit_depth)
need_sBIT = 1U;
debug(sBIT > 0U && sBIT <= from_bit_depth);
shifts |= (from_bit_depth - sBIT) << count;
count += 4U;
/* round the scale: */
*channel_scale++ = (numerator + (1U<<(sBIT-1U))) / ((1U << sBIT)-1U);
}
tr->shifts = shifts | (1U << count);
return need_sBIT;
# undef png_ptr
}
static void
reverse_gamma_sBIT(png_transform_gamma *tr)
{
/* This is called for the 'down' gamma implementations, they read the shifts
* and the channel scales in reverse, so:
*/
png_uint_32 shifts = tr->shifts;
png_uint_32 scales[4U];
unsigned int count = 0U;
tr->shifts = 1U;
while (shifts != 1U)
{
scales[3U-count] = tr->channel_scale[count];
++count;
tr->shifts <<= 4;
tr->shifts |= shifts & 0xFU;
shifts >>= 4;
}
memcpy(tr->channel_scale, scales+(4U-count), count * sizeof (png_uint_32));
}
static void
png_do_gamma8_up(png_transformp *transform, png_transform_controlp tc)
{
# define png_ptr (tc->png_ptr)
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc);
png_bytep dp = png_voidcast(png_bytep, tc->dp);
png_transform_gamma *tr =
png_transform_cast(png_transform_gamma, *transform);
const png_fixed_point correct = tr->correct;
const unsigned int bit_depth = tr->to_bit_depth;
const png_uint_32 shifts = tr->shifts;
affirm(tc->bit_depth == 8U);
affirm(tr->shifts != 0U/*uninitialized*/);
debug((shifts & 0x8888U) == 0U); /* all shifts 7 or less */
debug(!tr->encode_alpha && !tr->optimize_alpha); /* only set for 16 bits */
tc->sp = dp;
tc->bit_depth = bit_depth;
tc->gamma = tr->to_gamma;
/* Handle the <8 bit output case differently because there can be no alpha
* channel.
*/
if (bit_depth < 8U)
{
const unsigned int shift = shifts & 0xFU;
unsigned int bits = 8U;
unsigned int ob = 0U;
debug((shifts >> 4) == 1U && shift < 8U);
affirm(PNG_TC_CHANNELS(*tc) == 1);
do
{
const unsigned int inb = png_gamma_nxmbit_correct(
*sp++ >> shift, correct, 8U-shift, bit_depth);
bits -= bit_depth;
ob = ob | (inb << bits);
if (bits == 0U)
bits = 8U, *dp++ = PNG_BYTE(ob), ob = 0U;
}
while (sp < ep);
if (bits < 8U)
*dp++ = PNG_BYTE(ob);
}
else /* 8-bit --> 8-bit */
{
png_uint_32 alpha_scale;
const unsigned int channels = PNG_TC_CHANNELS(*tc);
unsigned int channel, alpha;
debug(bit_depth == 8U && (shifts >> (4*channels)) == 1U);
/* The alpha channel is always last, so if present checking against the
* top bits of 'channels' works because of the 1U shibboleth at the end.
*/
if ((tc->format & PNG_FORMAT_FLAG_ALPHA) == 0)
alpha_scale = alpha = 0U;
else
{
alpha = shifts >> (4U*(channels-1U));
alpha_scale = tr->channel_scale[channels-1U];
}
channel = 1U;
do
{
unsigned int inb = *sp++, shift;
if (channel == 1U)
channel = shifts;
shift = channel & 0xFU;
inb >>= shift;
/* The alpha channel is not gamma encoded but it may need some
* appropriate scaling.
*/
if (channel == alpha)
inb = (inb * alpha_scale + 0x800000U) >> 24;
else
inb = png_gamma_nxmbit_correct(inb, correct, 8U-shift, 8U);
channel >>= 4; /* for the next channel, or the shibboleth */
*dp++ = PNG_BYTE(inb);
}
while (sp < ep);
debug(channel == 1U);
}
# undef png_ptr
}
static void
png_do_gamma16_up(png_transformp *transform, png_transform_controlp tc)
{
# define png_ptr (tc->png_ptr)
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc) - 1U/*safety*/;
png_bytep dp = png_voidcast(png_bytep, tc->dp);
png_transform_gamma *tr =
png_transform_cast(png_transform_gamma, *transform);
const png_fixed_point correct = tr->correct;
const unsigned int bit_depth = tr->to_bit_depth;
const png_uint_32 shifts = tr->shifts;
affirm(tc->bit_depth == 16U);
affirm(tr->shifts != 0U/*uninitialized*/);
debug(!tr->optimize_alpha);
/* This is exactly the same as above but the input has 16 bits per component,
* not 8.
*/
tc->sp = dp;
tc->bit_depth = bit_depth;
tc->gamma = tr->to_gamma;
/* Handle the <8 bit output case differently, the input cannot be color (at
* present) and, if there is an alpha channel, then it is for the
* low-bit-depth gray input case and we expect the alpha to be transparent.
*/
if (bit_depth < 8U)
{
const unsigned int shift = shifts & 0xFU;
unsigned int bits = 8U;
unsigned int ob = 0U;
affirm((tc->format & PNG_FORMAT_FLAG_COLOR) == 0U);
if ((tc->format & PNG_FORMAT_FLAG_ALPHA) == 0U)
{
debug((shifts >> 4) == 1U && shift < 16U);
debug(!tr->encode_alpha && !tr->optimize_alpha);
do
{
unsigned int inb = *sp++ << 8; /* high bits first */
inb = png_gamma_nxmbit_correct(
(inb + *sp++) >> shift, correct, 16U-shift, bit_depth);
bits -= bit_depth;
ob = ob | (inb << bits);
if (bits == 0U)
bits = 8U, *dp++ = PNG_BYTE(ob), ob = 0U;
}
while (sp < ep);
UNTESTED
}
else /* low bit GA intermediate format */
{
debug((shifts >> 8) == 1U && shift < 16U);
debug(!tr->encode_alpha && !tr->optimize_alpha);
debug(tc->transparent_alpha);
/* Gray is first then the alpha component, the alpha component is just
* mapped to 0 or 1.
*/
do
{
unsigned int gray = *sp++ << 8; /* high bits first */
unsigned int alpha;
gray += *sp++;
alpha = (*sp++ << 8);
alpha += *sp++;
if (alpha == 0U)
gray = 0U; /* will be replaced later */
else
{
gray = png_gamma_nxmbit_correct(gray >> shift, correct,
16U-shift, bit_depth);
debug(alpha == 65535U);
alpha = (1U << bit_depth)-1U;
}
bits -= bit_depth;
ob = ob | (gray << bits);
bits -= bit_depth;
ob = ob | (alpha << bits);
if (bits == 0U)
bits = 8U, *dp++ = PNG_BYTE(ob), ob = 0U;
}
while (sp < ep-2U);
}
if (bits < 8U)
*dp++ = PNG_BYTE(ob);
debug(sp == ep+1U);
}
else
{
png_uint_32 alpha_scale;
const unsigned int channels = PNG_TC_CHANNELS(*tc);
unsigned int channel, alpha;
debug((bit_depth == 8U || bit_depth == 16U) &&
(shifts >> (4*channels)) == 1U);
/* Note that 'encode_alpha' turns on gamma encoding of the alpha
* channel (and this is a really weird operation!)
*/
if ((tc->format & PNG_FORMAT_FLAG_ALPHA) == 0 || tr->encode_alpha)
alpha_scale = alpha = 0U;
else
{
alpha = shifts >> (4U*(channels-1U));
alpha_scale = tr->channel_scale[channels-1U];
}
channel = 1U;
if (bit_depth == 16U)
{
do
{
unsigned int inb = *sp++ << 8, shift;
inb += *sp++;
if (channel == 1U)
channel = shifts;
shift = channel & 0xFU;
inb >>= shift;
/* The 16-16bit scaling factor equation may be off-by-1 but this
* hardly matters for alpha or for gamma operations.
*/
if (channel == alpha)
inb = (inb * alpha_scale + 0x8000U) >> 16;
else
inb = png_gamma_nxmbit_correct(inb, correct, 16U-shift, 16U);
channel >>= 4; /* for the next channel, or the shibboleth */
*dp++ = PNG_BYTE(inb >> 8);
*dp++ = PNG_BYTE(inb);
}
while (sp < ep);
debug(channel == 1U && sp == ep+1U);
}
else /* bit_depth == 8U */
{
do
{
unsigned int inb = *sp++ << 8, shift;
inb += *sp++;
if (channel == 1U)
channel = shifts;
shift = channel & 0xFU;
inb >>= shift;
if (channel == alpha)
inb = (inb * alpha_scale + 0x800000U) >> 24;
else
inb = png_gamma_nxmbit_correct(inb, correct, 16U-shift, 8U);
channel >>= 4; /* for the next channel, or the shibboleth */
*dp++ = PNG_BYTE(inb);
}
while (sp < ep);
debug(channel == 1U && sp == ep+1U);
}
}
# undef png_ptr
}
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
static void
png_do_gamma16_up_optimize(png_transformp *transform, png_transform_controlp tc)
/* As above, but the alpha channel is 'optimized' */
{
# define png_ptr (tc->png_ptr)
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc);
png_bytep dp = png_voidcast(png_bytep, tc->dp);
png_transform_gamma *tr =
png_transform_cast(png_transform_gamma, *transform);
const png_fixed_point correct = tr->correct;
/* The input always as 16 bits, the output 8 or 16. There is always an alpha
* channel and it is converted to the 'optimized' form, where pixels with
* alpha not 0.0 or 1.0 are left in linear form (not gamma corrected.) Where
* bit depth convertion is required it is from 16-bits to 8-bits and the
* DIV257 macro can be used.
*
* The following affirms and NOT_REACHED cases are consequences of the way
* the background (compose) code works:
*/
affirm(tr->optimize_alpha && !tr->encode_alpha && tc->bit_depth == 16U);
/* TODO: split this into separate functions */
switch (tr->to_bit_depth)
{
case 8U: /* 16-bit --> 8-bit */
tc->sp = dp;
tc->bit_depth = 8U;
tc->gamma = tr->to_gamma;
switch (PNG_TC_CHANNELS(*tc))
{
case 2:/* GA */
debug(tr->shifts == 0x100U);
ep -= 3U; /*SAFETY*/
do
{
png_uint_32 alpha = PNG_DIV257((sp[2] << 8) + sp[3]);
switch (alpha)
{
case 0U:
dp[1] = dp[0] = 0U;
break;
default: /* optimized case: linear color data */
dp[0] = png_check_byte(png_ptr,
PNG_DIV257((sp[0] << 8) + sp[1]));
dp[1] = PNG_BYTE(alpha);
break;
case 255U: /* opaque pixels are encoded */
dp[0] = PNG_BYTE(png_gamma_nxmbit_correct(
(sp[0] << 8) + sp[1], correct, 16U, 8U));
dp[1] = 255U;
break;
}
sp += 4U;
dp += 2U;
}
while (sp < ep);
debug(sp == ep+3U);
break;
case