From 23324b855981574fb069e4c3c8c9d8140b9900f8 Mon Sep 17 00:00:00 2001 From: John Bowler Date: Sat, 26 Sep 2015 15:24:20 -0700 Subject: [PATCH] sBIT code coverage and fixes Fixes for sBIT handling in the low-bit-depth gray and pngstest cases, extends sBIT handling to the colormap code in the simplified API which is separately implemented in pngread.c Signed-off-by: John Bowler --- contrib/libtests/makepng.c | 59 ++++++ contrib/libtests/pngvalid.c | 10 +- contrib/testpngs/gray-2-sBIT-tRNS.png | Bin 0 -> 500 bytes contrib/testpngs/makepngs.sh | 15 +- pngpriv.h | 12 +- pngread.c | 256 +++++++++++++++++++++----- pngrtran.c | 45 ++--- 7 files changed, 295 insertions(+), 102 deletions(-) create mode 100644 contrib/testpngs/gray-2-sBIT-tRNS.png diff --git a/contrib/libtests/makepng.c b/contrib/libtests/makepng.c index d4b850485..8f009a507 100644 --- a/contrib/libtests/makepng.c +++ b/contrib/libtests/makepng.c @@ -1361,6 +1361,60 @@ insert_hIST(png_structp png_ptr, png_infop info_ptr, int nparams, png_set_hIST(png_ptr, info_ptr, freq); } +static png_byte +bval(png_charp param) +{ + char *endptr = NULL; + unsigned long int l = strtoul(param, &endptr, 0/*base*/); + + if (param[0] && *endptr == 0 && l <= 255) + return (png_byte)l; + + else + { + fprintf(stderr, "sBIT: invalid sBIT value '%s'\n", param); + exit(1); + } +} + +static void +insert_sBIT(png_structp png_ptr, png_infop info_ptr, int nparams, + png_charpp params) +{ + const int ct = png_get_color_type(png_ptr, info_ptr); + const int c = channels_of_type(ct); + png_color_8 sBIT; + + if (nparams != c) + { + fprintf(stderr, "sBIT: expected parameter count %d, not %d\n", c, + nparams); + exit(1); + } + + if (ct & PNG_COLOR_MASK_COLOR) + { + sBIT.red = bval(params[0]); + sBIT.green = bval(params[1]); + sBIT.blue = bval(params[2]); + sBIT.gray = 42; + } + + else + { + sBIT.red = sBIT.green = sBIT.blue = 42; + sBIT.gray = bval(params[0]); + } + + if (ct & PNG_COLOR_MASK_ALPHA) + sBIT.alpha = bval(params[nparams-1]); + + else + sBIT.alpha = 42; + + png_set_sBIT(png_ptr, info_ptr, &sBIT); +} + #if 0 static void insert_sPLT(png_structp png_ptr, png_infop info_ptr, int nparams, png_charpp params) @@ -1488,6 +1542,11 @@ find_insert(png_const_charp what, png_charp param) return make_insert(what, insert_hIST, nparams, parameter_list); break; + case CHUNK(115,66,73,84): /* sBIT */ + if (nparams <= 4) + return make_insert(what, insert_sBIT, nparams, parameter_list); + break; + #if 0 case CHUNK(115,80,76,84): /* sPLT */ return make_insert(what, insert_sPLT, nparams, parameter_list); diff --git a/contrib/libtests/pngvalid.c b/contrib/libtests/pngvalid.c index 35ded08fe..47a24065c 100644 --- a/contrib/libtests/pngvalid.c +++ b/contrib/libtests/pngvalid.c @@ -1949,7 +1949,7 @@ typedef struct png_modifier unsigned int repeat :1; /* Repeat this transform test. */ unsigned int test_uses_encoding :1; - /* Lowest sbit to test (libpng fails for sbit < 8) */ + /* Lowest sbit to test (pre-1.7 libpng fails for sbit < 8) */ png_byte sbitlow; /* Error control - these are the limits on errors accepted by the gamma tests @@ -2036,7 +2036,7 @@ typedef struct png_modifier unsigned int test_gamma_expand16 :1; unsigned int test_exhaustive :1; - /* Whether or not to run the low-bit-depth grayscale tests. This fail on + /* Whether or not to run the low-bit-depth grayscale tests. This fails on * gamma images in some cases because of gross inaccuracies in the grayscale * gamma handling for low bit depth. */ @@ -11125,7 +11125,11 @@ int main(int argc, char **argv) pm.encodings = test_encodings; pm.nencodings = ARRAY_SIZE(test_encodings); - pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */ +# if PNG_LIBPNG_VER < 10700 + pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */ +# else + pm.sbitlow = 1U; +# endif /* The following allows results to pass if they correspond to anything in the * transformed range [input-.5,input+.5]; this is is required because of the diff --git a/contrib/testpngs/gray-2-sBIT-tRNS.png b/contrib/testpngs/gray-2-sBIT-tRNS.png new file mode 100644 index 0000000000000000000000000000000000000000..7a0a29e828bba3ec8b1c7206a1edf39f2021d346 GIT binary patch literal 500 zcmeAS@N?(olHy`uVBq!ia0vp^4j{|~Bp8lvGFuF!7>k`eLm1~@du$8jFqH)P1v4-* zPWihI$kQotjVN)>FQ_caOwTA`SgBxSU}&rZBuo{&@-y-joJ;faGV{_i5_1)t^2>8l zi)u@X{{i)tWQIhP_+%!h<`n~_85kK-^B5R7uIu*r@--_6w66d3h*4&D?(_=5mg!zf zJdGQ<{nvBG*4t|*bKR3jz1QTi<3pkZBnmA@DGcxOiN540>=xuT$?sCp)E$#i_@% literal 0 HcmV?d00001 diff --git a/contrib/testpngs/makepngs.sh b/contrib/testpngs/makepngs.sh index 818758715..761288ea6 100755 --- a/contrib/testpngs/makepngs.sh +++ b/contrib/testpngs/makepngs.sh @@ -72,19 +72,8 @@ case "$1" in done;; --coverage) - # Comments below indicate cases known to be required and not duplicated - # in other (required) cases; the aim is to get a minimal set that gives - # the maxium code coverage. - mpg none gray-alpha 8 # required: code coverage, sRGB opaque component - mpg none palette 8 # required: basic palette read - mpg 1.8 gray 2 # required: tests gamma threshold code - mpg 1.8 palette 2 # required: code coverage - mpg 1.8 palette 4 # required: code coverage - mpg 1.8 palette 8 # error limits only - mpg linear palette 8 # error limits only - mpg linear rgb-alpha 16 # error limits only - mpg sRGB palette 1 # required: code coverage - mpg sRGB rgb-alpha 16 # required: code coverage: pngread.c:2422 untested + # Extra images made to improve code coverage: + ${MAKEPNG} --insert sBIT 1 --tRNS gray 2 gray-2-sBIT-tRNS.png :;; *) diff --git a/pngpriv.h b/pngpriv.h index 0a4d16026..8f6afcfa2 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -2029,13 +2029,13 @@ PNG_INTERNAL_FUNCTION(int,png_muldiv,(png_fixed_point_p res, png_fixed_point a, /* Internal fixed point gamma correction. These APIs are called as * required to convert single values - they don't need to be fast, * they are not used when processing image pixel values. - * - * While the input is an 'unsigned' value it must actually be the - * correct bit value - 0..255 or 0..65535 as required. */ -PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_16bit_correct, - (png_const_structrp png_ptr, png_uint_32 value, png_fixed_point gamma_value), - PNG_EMPTY); +PNG_INTERNAL_FUNCTION(unsigned int,png_gamma_nxmbit_correct, + (unsigned int value, png_fixed_point gamma_val, unsigned int n/*input bits*/, + unsigned int m/*output bits */),PNG_EMPTY); + /* In this case the value must have 'n' bits and the output will have 'm' + * bits. + */ /* Internal check function to saw if the gamma of the PNG data is far enough * from the given screen gamma to require gamma correction (only needed for a diff --git a/pngread.c b/pngread.c index 5e9ca7066..5dc8f7549 100644 --- a/pngread.c +++ b/pngread.c @@ -1051,6 +1051,7 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, int transforms, # define P_LINEAR 2 /* 16-bit linear: not encoded, NOT pre-multiplied! */ # define P_FILE 3 /* 8-bit encoded to file gamma, not sRGB or linear */ # define P_LINEAR8 4 /* 8-bit linear: only from a file value */ +# define P_FILE8 5 /* 8-bit encoded to file gamma but not significant bits */ /* Color-map processing: after libpng has run on the PNG image further * processing may be needed to convert the data to color-map indices. @@ -1083,6 +1084,7 @@ typedef struct int file_encoding; /* E_ values above */ png_fixed_point file_to_sRGB; /* Cached correction factor */ int colormap_processing; /* PNG_CMAP_ values above */ + png_byte sBIT[4]; /* Significant bits for channels */ } png_image_read_control; /* Do all the *safe* initialization - 'safe' means that png_error won't be @@ -1242,6 +1244,47 @@ png_image_read_header(png_voidp argument) return 1; } +static void +png_image_get_sBIT(png_image_read_control *display) + /* Utility to cache the sBIT values. This uses the information from the + * png_struct not png_info because it may be needed after the sBIT + * information in png_info has been invalidated. + */ +{ + if (display->sBIT[0] == 0) + { + const png_const_structrp png_ptr = display->image->opaque->png_ptr; + const unsigned int color_type = png_ptr->color_type; + const png_byte bit_depth = + (color_type & PNG_COLOR_MASK_PALETTE) ? 8U : png_ptr->bit_depth; + + memset(display->sBIT, bit_depth, sizeof display->sBIT); + + if (color_type & PNG_COLOR_MASK_COLOR) + { + if (png_ptr->sig_bit.red > 0 && png_ptr->sig_bit.red < bit_depth) + display->sBIT[0] = png_ptr->sig_bit.red; + if (png_ptr->sig_bit.green > 0 && png_ptr->sig_bit.green < bit_depth) + display->sBIT[1] = png_ptr->sig_bit.green; + if (png_ptr->sig_bit.blue > 0 && png_ptr->sig_bit.blue < bit_depth) + display->sBIT[2] = png_ptr->sig_bit.blue; + } + + else + { + if (png_ptr->sig_bit.gray > 0 && png_ptr->sig_bit.gray < bit_depth) + display->sBIT[2] = display->sBIT[1] = display->sBIT[0] = + png_ptr->sig_bit.gray; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + if (png_ptr->sig_bit.alpha > 0 && png_ptr->sig_bit.alpha < bit_depth) + display->sBIT[3] = png_ptr->sig_bit.alpha; + } + } +} + #ifdef PNG_STDIO_SUPPORTED int PNGAPI png_image_begin_read_from_stdio(png_imagep image, FILE* file) @@ -1493,40 +1536,74 @@ init_correct(png_const_structrp png_ptr, png_fixed_point *correct) } static png_uint_32 -convert_to_sRGB(png_image_read_control *display, png_uint_32 value) +update_for_sBIT(png_uint_32 value, unsigned int significant_bits, + unsigned int bit_depth) + /* Return a bit_depth value adjusted for the number of significant bits in + * the value. + */ +{ + if (significant_bits < bit_depth) + { + value >>= bit_depth - significant_bits; + /* Now scale back to bit_depth, taking care not to overflow when 'value' + * is (1<image->opaque->png_ptr; - affirm(value <= 255U); + debug(value <= 255U && significant_bits <= 8U && significant_bits > 0U); if (display->file_to_sRGB == 0) init_correct(png_ptr, &display->file_to_sRGB); /* Now simply apply this correction factor and scale back to 8 bits. */ if (display->file_to_sRGB != PNG_FP_1) - value = PNG_DIV257( - png_gamma_16bit_correct(png_ptr, value*257U, display->file_to_sRGB)); + value = png_gamma_nxmbit_correct(value >> (8U-significant_bits), + display->file_to_sRGB, significant_bits, 8U); + + else if (significant_bits < 8U) + value = update_for_sBIT(value, significant_bits, 8U); return value; } static png_uint_32 -convert_to_linear(png_image_read_control *display, png_uint_32 value) +convert_to_linear(png_image_read_control *display, png_uint_32 value, + unsigned int significant_bits) { /* Converts an 8-bit value from P_FILE to 16-bit P_LINEAR */ png_const_structrp png_ptr = display->image->opaque->png_ptr; - affirm(value <= 255U); + debug(value <= 255U && significant_bits <= 8U && significant_bits > 0U); if (display->file_to_sRGB == 0) init_correct(png_ptr, &display->file_to_sRGB); - /* Use this correct to get a 16-bit sRGB value: */ - value *= 257U; - + /* Use this correction to get a 16-bit sRGB value: */ if (display->file_to_sRGB != PNG_FP_1) - value = png_gamma_16bit_correct(png_ptr, value, display->file_to_sRGB); + value = png_gamma_nxmbit_correct(value >> (8U-significant_bits), + display->file_to_sRGB, significant_bits, 16U); + + else + { + value *= 257U; + + if (significant_bits < 8U) + value = update_for_sBIT(value, significant_bits, 16U); + } /* Now convert this back to linear, using the correct transfer function. */ if (value <= 2650U /* 65535 * 0.04045 */) @@ -1547,17 +1624,20 @@ convert_to_linear(png_image_read_control *display, png_uint_32 value) */ value *= 62119U; value += 223904831U+32768U; /* cannot overflow; test with 65535 */ - value = png_gamma_16bit_correct(png_ptr, value >> 16, 240000); + value = png_gamma_nxmbit_correct(value >> 16, 240000, 16U, 16U); } return value; } static unsigned int -decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) +decode_gamma(png_image_read_control *display, png_uint_32 value, + unsigned int significant_bits, int encoding) { + int do_sBIT = 0; + if (encoding == P_FILE) /* double check */ - encoding = display->file_encoding; + encoding = display->file_encoding, do_sBIT = 1; if (encoding == P_NOTSET) /* must be the file encoding */ { @@ -1568,18 +1648,26 @@ decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) switch (encoding) { case P_FILE: - value = convert_to_linear(display, value); + /* This is a file value, so the sBIT, if any, needs to be used. */ + value = convert_to_linear(display, value, significant_bits); break; case P_sRGB: + if (do_sBIT) + value = update_for_sBIT(value, significant_bits, 8U); + value = png_sRGB_table[value]; break; case P_LINEAR: + if (do_sBIT) + value = update_for_sBIT(value, significant_bits, 16U); break; case P_LINEAR8: value *= 257; + if (do_sBIT) + value = update_for_sBIT(value, significant_bits, 16U); break; default: @@ -1593,7 +1681,8 @@ decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) static png_uint_32 png_colormap_compose(png_image_read_control *display, - png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha, + png_uint_32 foreground, unsigned int foreground_significant_bits, + int foreground_encoding, png_uint_32 alpha, png_uint_32 background, int encoding) { /* The file value is composed on the background, the background has the given @@ -1601,8 +1690,9 @@ png_colormap_compose(png_image_read_control *display, * file and alpha are 8-bit values. The (output) encoding will always be * P_LINEAR or P_sRGB. */ - png_uint_32 f = decode_gamma(display, foreground, foreground_encoding); - png_uint_32 b = decode_gamma(display, background, encoding); + png_uint_32 f = decode_gamma(display, foreground, + foreground_significant_bits, foreground_encoding); + png_uint_32 b = decode_gamma(display, background, 0U/*UNUSED*/, encoding); /* The alpha is always an 8-bit value (it comes from the palette), the value * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires. @@ -1639,9 +1729,16 @@ png_create_colormap_entry(png_image_read_control *display, P_LINEAR : P_sRGB; const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && (red != green || green != blue); + int use_sBIT = encoding == P_FILE; - if (ip > 255) - png_error(png_ptr, "color-map index out of range"); + affirm(ip <= 255); + implies(encoding != P_LINEAR, red <= 255U && green <= 255U && blue <= 255U + && display->sBIT[0] <= 8U && display->sBIT[1] <= 8U + && display->sBIT[2] <= 8U && display->sBIT[3] <= 8U); + + /* This is a hack for the grayscale colormap below. */ + if (encoding == P_FILE8) + encoding = P_FILE; /* Update the cache with whether the file gamma is significantly different * from sRGB. @@ -1653,37 +1750,61 @@ png_create_colormap_entry(png_image_read_control *display, /* Note that the cached value may be P_FILE too. */ encoding = display->file_encoding; + if (use_sBIT) + png_image_get_sBIT(display); } if (encoding == P_FILE) { if (convert_to_Y != 0 || output_encoding == P_LINEAR) { - red = convert_to_linear(display, red); - green = convert_to_linear(display, green); - blue = convert_to_linear(display, blue); - alpha *= 257; + red = convert_to_linear(display, red, + use_sBIT ? display->sBIT[0] : 8U); + green = convert_to_linear(display, green, + use_sBIT ? display->sBIT[1] : 8U); + blue = convert_to_linear(display, blue, + use_sBIT ? display->sBIT[2] : 8U); + alpha *= 257U; + if (use_sBIT) + alpha = update_for_sBIT(alpha, display->sBIT[3], 16U); + encoding = P_LINEAR; + use_sBIT = 0; } else { - red = convert_to_sRGB(display, red); - green = convert_to_sRGB(display, green); - blue = convert_to_sRGB(display, blue); + red = convert_to_sRGB(display, red, + use_sBIT ? display->sBIT[0] : 8U); + green = convert_to_sRGB(display, green, + use_sBIT ? display->sBIT[1] : 8U); + blue = convert_to_sRGB(display, blue, + use_sBIT ? display->sBIT[2] : 8U); + if (use_sBIT) + alpha = update_for_sBIT(alpha, display->sBIT[3], 8U); encoding = P_sRGB; + use_sBIT = 0; } } else if (encoding == P_LINEAR8) { - /* This encoding occurs quite frequently in test cases because PngSuite - * includes a gAMA 1.0 chunk with most images. + /* This encoding corresponds to a colormap with linear RGB entries, this + * is not a very sensible encoding but it does happen with the PNGSuite + * test images. */ red *= 257; green *= 257; blue *= 257; alpha *= 257; + if (use_sBIT) + { + red = update_for_sBIT(red, display->sBIT[0], 16U); + green = update_for_sBIT(green, display->sBIT[1], 16U); + blue = update_for_sBIT(blue, display->sBIT[2], 16U); + alpha = update_for_sBIT(alpha, display->sBIT[3], 16U); + use_sBIT = 0; + } encoding = P_LINEAR; } @@ -1693,13 +1814,38 @@ png_create_colormap_entry(png_image_read_control *display, /* The values are 8-bit sRGB values, but must be converted to 16-bit * linear. */ - red = png_sRGB_table[red]; - green = png_sRGB_table[green]; - blue = png_sRGB_table[blue]; - alpha *= 257; + if (use_sBIT) + { + red = convert_to_linear(display, red, display->sBIT[0]); + green = convert_to_linear(display, green, display->sBIT[1]); + blue = convert_to_linear(display, blue, display->sBIT[2]); + alpha = update_for_sBIT(alpha * 257U, display->sBIT[3], 16U); + use_sBIT = 0; + } + + else + { + red = png_sRGB_table[red]; + green = png_sRGB_table[green]; + blue = png_sRGB_table[blue]; + alpha *= 257; + } + encoding = P_LINEAR; } + else if (encoding == P_sRGB && use_sBIT) + { + debug(output_encoding == P_sRGB); /* P_LINEAR handled above */ + red = update_for_sBIT(red, display->sBIT[0], 8U); + green = update_for_sBIT(green, display->sBIT[1], 8U); + blue = update_for_sBIT(blue, display->sBIT[2], 8U); + alpha = update_for_sBIT(alpha, display->sBIT[3], 8U); + use_sBIT = 0; + } + + debug(!use_sBIT); /* it should have been handled above */ + /* This is set if the color isn't gray but the output is. */ if (encoding == P_LINEAR) { @@ -1854,7 +2000,7 @@ make_gray_file_colormap(png_image_read_control *display) unsigned int i; for (i=0; i<256; ++i) - png_create_colormap_entry(display, i, i, i, i, 255, P_FILE); + png_create_colormap_entry(display, i, i, i, i, 255, P_FILE8); return i; } @@ -2467,8 +2613,8 @@ png_image_read_colormap(png_voidp argument) if (output_encoding == P_sRGB) gray = png_sRGB_table[gray]; /* now P_LINEAR */ - gray = PNG_DIV257(png_gamma_16bit_correct(png_ptr, gray, - png_ptr->colorspace.gamma)); /* now P_FILE */ + gray = png_gamma_nxmbit_correct(gray, + png_ptr->colorspace.gamma, 16U, 8U); /* And make sure the corresponding palette entry contains * exactly the required sRGB value. @@ -2625,12 +2771,12 @@ png_image_read_colormap(png_voidp argument) */ for (b=0; b<256; b = (b << 1) | 0x7f) png_create_colormap_entry(display, cmap_entries++, - png_colormap_compose(display, r, P_sRGB, 128, - back_r, output_encoding), - png_colormap_compose(display, g, P_sRGB, 128, - back_g, output_encoding), - png_colormap_compose(display, b, P_sRGB, 128, - back_b, output_encoding), + png_colormap_compose(display, r, 8U, P_sRGB, + 128U, back_r, output_encoding), + png_colormap_compose(display, g, 8U, P_sRGB, + 128U, back_g, output_encoding), + png_colormap_compose(display, b, 8U, P_sRGB, + 128U, back_b, output_encoding), 0/*unused*/, output_encoding); } } @@ -2706,17 +2852,31 @@ png_image_read_colormap(png_voidp argument) else { + unsigned int alpha; + /* Must compose the PNG file color in the color-map entry * on the sRGB color in 'back'. */ + png_image_get_sBIT(display); + alpha = update_for_sBIT(trans[i], display->sBIT[3], 8U); + + /* Do the sBIT handling here because it only applies to the + * values from the colormap, not the background. Passing + * output_encoding to png_create_colormap_entry prevents + * this being duplicated. + */ png_create_colormap_entry(display, i, - png_colormap_compose(display, colormap[i].red, P_FILE, - trans[i], back_r, output_encoding), - png_colormap_compose(display, colormap[i].green, P_FILE, - trans[i], back_g, output_encoding), - png_colormap_compose(display, colormap[i].blue, P_FILE, - trans[i], back_b, output_encoding), - output_encoding == P_LINEAR ? trans[i] * 257U : + png_colormap_compose(display, colormap[i].red, + display->sBIT[0], P_FILE, alpha, back_r, + output_encoding), + png_colormap_compose(display, colormap[i].green, + display->sBIT[1], P_FILE, alpha, back_g, + output_encoding), + png_colormap_compose(display, colormap[i].blue, + display->sBIT[2], P_FILE, alpha, back_b, + output_encoding), + output_encoding == P_LINEAR ? + update_for_sBIT(alpha*257U, display->sBIT[3], 16U) : trans[i], output_encoding); } diff --git a/pngrtran.c b/pngrtran.c index 518a4dfef..3d33b3dbb 100644 --- a/pngrtran.c +++ b/pngrtran.c @@ -882,10 +882,7 @@ png_do_expand_lbd_gray(png_transformp *transform, png_transform_controlp tc) 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; - UNTESTED - } # endif /* READ_sBIT */ # ifdef PNG_READ_tRNS_SUPPORTED @@ -949,10 +946,7 @@ png_do_expand_lbd_gray(png_transformp *transform, png_transform_controlp tc) * of 1 bit gray + 1 bit alpha (transparency): */ if (insignificant_bits /* only 1 bit significant */) - { *--dp = PNG_BYTE((pixel >> 1) * 255U); - UNTESTED - } else # endif @@ -990,10 +984,7 @@ png_do_expand_lbd_gray(png_transformp *transform, png_transform_controlp tc) * below. */ if (insignificant_bits) - { pixel = ((pixel>>insignificant_bits) * 255U + (div>>1)) / div; - UNTESTED - } else # endif @@ -2142,10 +2133,10 @@ png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val) } #endif /* UNUSED */ -/* libpng-1.7.0: this internal function converts an n-bit input value to an +/* libpng-1.7.0: this private function converts an n-bit input value to an * m-bit output value. */ -static unsigned int +unsigned int png_gamma_nxmbit_correct(unsigned int value, png_fixed_point gamma_val, unsigned int n/*input bits*/, unsigned int m/*output bits */) { @@ -2186,21 +2177,6 @@ png_gamma_nxmbit_correct(unsigned int value, png_fixed_point gamma_val, } } -#ifdef PNG_SIMPLIFIED_READ_SUPPORTED -png_uint_16 -png_gamma_16bit_correct(png_const_structrp png_ptr, unsigned int value, - png_fixed_point gamma_val) -{ - /* This is a hook into this code for use by the simplified API (only) */ - return png_check_u16(png_ptr, - png_gamma_nxmbit_correct(value, gamma_val, 16U, 16U)); - PNG_UNUSED(png_ptr) -} -#endif /* SIMPLIFIED_READ */ - -#undef png_gamma_16bit_correct /* circumvent the prefix handling */ -#define png_gamma_16bit_correct NOT_USED_HERE /* for checking */ - #if 0 /*UNUSED*/ static unsigned int png_gamma_sbit_correct(unsigned int value, png_fixed_point gamma_val, @@ -4899,9 +4875,12 @@ png_do_background_alpha_GA(png_transformp *transform, png_transform_controlp tc) const int compose = tr->st.compose_background; affirm(tc->bit_depth == 16U && tc->format == PNG_FORMAT_GA && - tr->st.background_bit_depth == 16U && - (tr->st.background_gamma == tc->gamma || - tr->st.background_gamma == 0)); + tr->st.background_bit_depth == 16U); + + /* If gamma transforms are eliminated this might fail: */ + debug(tr->st.background_gamma == tc->gamma || + tr->st.background_gamma == 0 || + tc->sBIT_G == 1); tc->sp = tc->dp; /* nothing else changes */ @@ -4968,9 +4947,11 @@ png_do_background_alpha_RGBA(png_transformp *transform, const int compose = tr->st.compose_background; affirm(tc->bit_depth == 16U && tc->format == PNG_FORMAT_RGBA && - tr->st.background_bit_depth == 16U && - (tr->st.background_gamma == tc->gamma || - tr->st.background_gamma == 0)); + tr->st.background_bit_depth == 16U); + + debug(tr->st.background_gamma == tc->gamma || + tr->st.background_gamma == 0 || + (tc->sBIT_R == 1 && tc->sBIT_G == 1 && tc->sBIT_B == 1)); tc->sp = tc->dp; /* nothing else changes */