mirror of
				https://git.code.sf.net/p/libpng/code.git
				synced 2025-07-10 18:04:09 +02:00 
			
		
		
		
	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 <jbowler@acm.org>
This commit is contained in:
		
							parent
							
								
									8dfa93beed
								
							
						
					
					
						commit
						23324b8559
					
				| @ -1361,6 +1361,60 @@ insert_hIST(png_structp png_ptr, png_infop info_ptr, int nparams, | |||||||
|    png_set_hIST(png_ptr, info_ptr, freq); |    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 | #if 0 | ||||||
| static void | static void | ||||||
| insert_sPLT(png_structp png_ptr, png_infop info_ptr, int nparams, png_charpp params) | 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); |             return make_insert(what, insert_hIST, nparams, parameter_list); | ||||||
|          break; |          break; | ||||||
| 
 | 
 | ||||||
|  |       case CHUNK(115,66,73,84): /* sBIT */ | ||||||
|  |          if (nparams <= 4) | ||||||
|  |             return make_insert(what, insert_sBIT, nparams, parameter_list); | ||||||
|  |          break; | ||||||
|  | 
 | ||||||
| #if 0 | #if 0 | ||||||
|       case CHUNK(115,80,76,84):  /* sPLT */ |       case CHUNK(115,80,76,84):  /* sPLT */ | ||||||
|          return make_insert(what, insert_sPLT, nparams, parameter_list); |          return make_insert(what, insert_sPLT, nparams, parameter_list); | ||||||
|  | |||||||
| @ -1949,7 +1949,7 @@ typedef struct png_modifier | |||||||
|    unsigned int              repeat :1;   /* Repeat this transform test. */ |    unsigned int              repeat :1;   /* Repeat this transform test. */ | ||||||
|    unsigned int              test_uses_encoding :1; |    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; |    png_byte                 sbitlow; | ||||||
| 
 | 
 | ||||||
|    /* Error control - these are the limits on errors accepted by the gamma tests
 |    /* 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_gamma_expand16 :1; | ||||||
|    unsigned int             test_exhaustive :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 images in some cases because of gross inaccuracies in the grayscale | ||||||
|     * gamma handling for low bit depth. |     * gamma handling for low bit depth. | ||||||
|     */ |     */ | ||||||
| @ -11125,7 +11125,11 @@ int main(int argc, char **argv) | |||||||
|    pm.encodings = test_encodings; |    pm.encodings = test_encodings; | ||||||
|    pm.nencodings = ARRAY_SIZE(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
 |    /* 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 |     * transformed range [input-.5,input+.5]; this is is required because of the | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								contrib/testpngs/gray-2-sBIT-tRNS.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								contrib/testpngs/gray-2-sBIT-tRNS.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 500 B | 
| @ -72,19 +72,8 @@ case "$1" in | |||||||
|       done;; |       done;; | ||||||
| 
 | 
 | ||||||
|    --coverage) |    --coverage) | ||||||
|       # Comments below indicate cases known to be required and not duplicated |       # Extra images made to improve code coverage: | ||||||
|       # in other (required) cases; the aim is to get a minimal set that gives |       ${MAKEPNG} --insert sBIT 1 --tRNS gray 2 gray-2-sBIT-tRNS.png | ||||||
|       # 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 |  | ||||||
|       :;; |       :;; | ||||||
| 
 | 
 | ||||||
|    *) |    *) | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								pngpriv.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								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
 | /* Internal fixed point gamma correction.  These APIs are called as
 | ||||||
|  * required to convert single values - they don't need to be fast, |  * required to convert single values - they don't need to be fast, | ||||||
|  * they are not used when processing image pixel values. |  * 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_INTERNAL_FUNCTION(unsigned int,png_gamma_nxmbit_correct, | ||||||
|    (png_const_structrp png_ptr, png_uint_32 value, png_fixed_point gamma_value), |    (unsigned int value, png_fixed_point gamma_val, unsigned int n/*input bits*/, | ||||||
|    PNG_EMPTY); |     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
 | /* 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 |  * from the given screen gamma to require gamma correction (only needed for a | ||||||
|  | |||||||
							
								
								
									
										256
									
								
								pngread.c
									
									
									
									
									
								
							
							
						
						
									
										256
									
								
								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_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_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_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
 | /* Color-map processing: after libpng has run on the PNG image further
 | ||||||
|  * processing may be needed to convert the data to color-map indices. |  * processing may be needed to convert the data to color-map indices. | ||||||
| @ -1083,6 +1084,7 @@ typedef struct | |||||||
|    int             file_encoding;       /* E_ values above */ |    int             file_encoding;       /* E_ values above */ | ||||||
|    png_fixed_point file_to_sRGB;        /* Cached correction factor */ |    png_fixed_point file_to_sRGB;        /* Cached correction factor */ | ||||||
|    int             colormap_processing; /* PNG_CMAP_ values above */ |    int             colormap_processing; /* PNG_CMAP_ values above */ | ||||||
|  |    png_byte        sBIT[4];             /* Significant bits for channels */ | ||||||
| } png_image_read_control; | } png_image_read_control; | ||||||
| 
 | 
 | ||||||
| /* Do all the *safe* initialization - 'safe' means that png_error won't be
 | /* 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; |    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 | #ifdef PNG_STDIO_SUPPORTED | ||||||
| int PNGAPI | int PNGAPI | ||||||
| png_image_begin_read_from_stdio(png_imagep image, FILE* file) | 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 | 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<<significant_bits)-1 by rounding *down* the rounding add below | ||||||
|  |        * (so, e.g. rather than 2, 1 is used when significant bits is 2). | ||||||
|  |        */ | ||||||
|  |       value = (value * ((1U<<bit_depth)-1U) + ((1U<<(significant_bits-1U))-1U)) | ||||||
|  |          / ((1U<<significant_bits)-1U); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return value; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static png_uint_32 | ||||||
|  | convert_to_sRGB(png_image_read_control *display, png_uint_32 value, | ||||||
|  |    unsigned int significant_bits) | ||||||
| { | { | ||||||
|    /* Converts an 8-bit value from P_FILE to P_sRGB */ |    /* Converts an 8-bit value from P_FILE to P_sRGB */ | ||||||
|    png_const_structrp png_ptr = display->image->opaque->png_ptr; |    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) |    if (display->file_to_sRGB == 0) | ||||||
|       init_correct(png_ptr, &display->file_to_sRGB); |       init_correct(png_ptr, &display->file_to_sRGB); | ||||||
| 
 | 
 | ||||||
|    /* Now simply apply this correction factor and scale back to 8 bits. */ |    /* Now simply apply this correction factor and scale back to 8 bits. */ | ||||||
|    if (display->file_to_sRGB != PNG_FP_1) |    if (display->file_to_sRGB != PNG_FP_1) | ||||||
|       value = PNG_DIV257( |       value = png_gamma_nxmbit_correct(value >> (8U-significant_bits), | ||||||
|          png_gamma_16bit_correct(png_ptr, value*257U, display->file_to_sRGB)); |             display->file_to_sRGB, significant_bits, 8U); | ||||||
|  | 
 | ||||||
|  |    else if (significant_bits < 8U) | ||||||
|  |       value = update_for_sBIT(value, significant_bits, 8U); | ||||||
| 
 | 
 | ||||||
|    return value; |    return value; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static png_uint_32 | 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 */ |    /* Converts an 8-bit value from P_FILE to 16-bit P_LINEAR */ | ||||||
|    png_const_structrp png_ptr = display->image->opaque->png_ptr; |    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) |    if (display->file_to_sRGB == 0) | ||||||
|       init_correct(png_ptr, &display->file_to_sRGB); |       init_correct(png_ptr, &display->file_to_sRGB); | ||||||
| 
 | 
 | ||||||
|    /* Use this correct to get a 16-bit sRGB value: */ |    /* Use this correction to get a 16-bit sRGB value: */ | ||||||
|    value *= 257U; |  | ||||||
| 
 |  | ||||||
|    if (display->file_to_sRGB != PNG_FP_1) |    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. */ |    /* Now convert this back to linear, using the correct transfer function. */ | ||||||
|    if (value <= 2650U /* 65535 * 0.04045 */) |    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 *= 62119U; | ||||||
|       value += 223904831U+32768U; /* cannot overflow; test with 65535 */ |       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; |    return value; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static unsigned int | 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 */ |    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 */ |    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) |    switch (encoding) | ||||||
|    { |    { | ||||||
|       case P_FILE: |       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; |          break; | ||||||
| 
 | 
 | ||||||
|       case P_sRGB: |       case P_sRGB: | ||||||
|  |          if (do_sBIT) | ||||||
|  |             value = update_for_sBIT(value, significant_bits, 8U); | ||||||
|  | 
 | ||||||
|          value = png_sRGB_table[value]; |          value = png_sRGB_table[value]; | ||||||
|          break; |          break; | ||||||
| 
 | 
 | ||||||
|       case P_LINEAR: |       case P_LINEAR: | ||||||
|  |          if (do_sBIT) | ||||||
|  |             value = update_for_sBIT(value, significant_bits, 16U); | ||||||
|          break; |          break; | ||||||
| 
 | 
 | ||||||
|       case P_LINEAR8: |       case P_LINEAR8: | ||||||
|          value *= 257; |          value *= 257; | ||||||
|  |          if (do_sBIT) | ||||||
|  |             value = update_for_sBIT(value, significant_bits, 16U); | ||||||
|          break; |          break; | ||||||
| 
 | 
 | ||||||
|       default: |       default: | ||||||
| @ -1593,7 +1681,8 @@ decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) | |||||||
| 
 | 
 | ||||||
| static png_uint_32 | static png_uint_32 | ||||||
| png_colormap_compose(png_image_read_control *display, | 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) |    png_uint_32 background, int encoding) | ||||||
| { | { | ||||||
|    /* The file value is composed on the background, the background has the given
 |    /* 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 |     * file and alpha are 8-bit values.  The (output) encoding will always be | ||||||
|     * P_LINEAR or P_sRGB. |     * P_LINEAR or P_sRGB. | ||||||
|     */ |     */ | ||||||
|    png_uint_32 f = decode_gamma(display, foreground, foreground_encoding); |    png_uint_32 f = decode_gamma(display, foreground, | ||||||
|    png_uint_32 b = decode_gamma(display, background, encoding); |          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
 |    /* 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. |     * 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; |       P_LINEAR : P_sRGB; | ||||||
|    const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && |    const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && | ||||||
|       (red != green || green != blue); |       (red != green || green != blue); | ||||||
|  |    int use_sBIT = encoding == P_FILE; | ||||||
| 
 | 
 | ||||||
|    if (ip > 255) |    affirm(ip <= 255); | ||||||
|       png_error(png_ptr, "color-map index out of range"); |    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
 |    /* Update the cache with whether the file gamma is significantly different
 | ||||||
|     * from sRGB. |     * 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. */ |       /* Note that the cached value may be P_FILE too. */ | ||||||
|       encoding = display->file_encoding; |       encoding = display->file_encoding; | ||||||
|  |       if (use_sBIT) | ||||||
|  |          png_image_get_sBIT(display); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    if (encoding == P_FILE) |    if (encoding == P_FILE) | ||||||
|    { |    { | ||||||
|       if (convert_to_Y != 0 || output_encoding == P_LINEAR) |       if (convert_to_Y != 0 || output_encoding == P_LINEAR) | ||||||
|       { |       { | ||||||
|          red = convert_to_linear(display, red); |          red = convert_to_linear(display, red, | ||||||
|          green = convert_to_linear(display, green); |                use_sBIT ? display->sBIT[0] : 8U); | ||||||
|          blue = convert_to_linear(display, blue); |          green = convert_to_linear(display, green, | ||||||
|          alpha *= 257; |                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; |          encoding = P_LINEAR; | ||||||
|  |          use_sBIT = 0; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       else |       else | ||||||
|       { |       { | ||||||
|          red = convert_to_sRGB(display, red); |          red = convert_to_sRGB(display, red, | ||||||
|          green = convert_to_sRGB(display, green); |                use_sBIT ? display->sBIT[0] : 8U); | ||||||
|          blue = convert_to_sRGB(display, blue); |          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; |          encoding = P_sRGB; | ||||||
|  |          use_sBIT = 0; | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    else if (encoding == P_LINEAR8) |    else if (encoding == P_LINEAR8) | ||||||
|    { |    { | ||||||
|       /* This encoding occurs quite frequently in test cases because PngSuite
 |       /* This encoding corresponds to a colormap with linear RGB entries, this
 | ||||||
|        * includes a gAMA 1.0 chunk with most images. |        * is not a very sensible encoding but it does happen with the PNGSuite | ||||||
|  |        * test images. | ||||||
|        */ |        */ | ||||||
|       red *= 257; |       red *= 257; | ||||||
|       green *= 257; |       green *= 257; | ||||||
|       blue *= 257; |       blue *= 257; | ||||||
|       alpha *= 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; |       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
 |       /* The values are 8-bit sRGB values, but must be converted to 16-bit
 | ||||||
|        * linear. |        * linear. | ||||||
|        */ |        */ | ||||||
|       red = png_sRGB_table[red]; |       if (use_sBIT) | ||||||
|       green = png_sRGB_table[green]; |       { | ||||||
|       blue = png_sRGB_table[blue]; |          red = convert_to_linear(display, red, display->sBIT[0]); | ||||||
|       alpha *= 257; |          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; |       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. */ |    /* This is set if the color isn't gray but the output is. */ | ||||||
|    if (encoding == P_LINEAR) |    if (encoding == P_LINEAR) | ||||||
|    { |    { | ||||||
| @ -1854,7 +2000,7 @@ make_gray_file_colormap(png_image_read_control *display) | |||||||
|    unsigned int i; |    unsigned int i; | ||||||
| 
 | 
 | ||||||
|    for (i=0; i<256; ++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; |    return i; | ||||||
| } | } | ||||||
| @ -2467,8 +2613,8 @@ png_image_read_colormap(png_voidp argument) | |||||||
|                      if (output_encoding == P_sRGB) |                      if (output_encoding == P_sRGB) | ||||||
|                         gray = png_sRGB_table[gray]; /* now P_LINEAR */ |                         gray = png_sRGB_table[gray]; /* now P_LINEAR */ | ||||||
| 
 | 
 | ||||||
|                      gray = PNG_DIV257(png_gamma_16bit_correct(png_ptr, gray, |                      gray = png_gamma_nxmbit_correct(gray, | ||||||
|                         png_ptr->colorspace.gamma)); /* now P_FILE */ |                         png_ptr->colorspace.gamma, 16U, 8U); | ||||||
| 
 | 
 | ||||||
|                      /* And make sure the corresponding palette entry contains
 |                      /* And make sure the corresponding palette entry contains
 | ||||||
|                       * exactly the required sRGB value. |                       * 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) |                            for (b=0; b<256; b = (b << 1) | 0x7f) | ||||||
|                               png_create_colormap_entry(display, cmap_entries++, |                               png_create_colormap_entry(display, cmap_entries++, | ||||||
|                                  png_colormap_compose(display, r, P_sRGB, 128, |                                  png_colormap_compose(display, r, 8U, P_sRGB, | ||||||
|                                     back_r, output_encoding), |                                     128U, back_r, output_encoding), | ||||||
|                                  png_colormap_compose(display, g, P_sRGB, 128, |                                  png_colormap_compose(display, g, 8U, P_sRGB, | ||||||
|                                     back_g, output_encoding), |                                     128U, back_g, output_encoding), | ||||||
|                                  png_colormap_compose(display, b, P_sRGB, 128, |                                  png_colormap_compose(display, b, 8U, P_sRGB, | ||||||
|                                     back_b, output_encoding), |                                     128U, back_b, output_encoding), | ||||||
|                                  0/*unused*/, output_encoding); |                                  0/*unused*/, output_encoding); | ||||||
|                         } |                         } | ||||||
|                      } |                      } | ||||||
| @ -2706,17 +2852,31 @@ png_image_read_colormap(png_voidp argument) | |||||||
| 
 | 
 | ||||||
|                   else |                   else | ||||||
|                   { |                   { | ||||||
|  |                      unsigned int alpha; | ||||||
|  | 
 | ||||||
|                      /* Must compose the PNG file color in the color-map entry
 |                      /* Must compose the PNG file color in the color-map entry
 | ||||||
|                       * on the sRGB color in 'back'. |                       * 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_create_colormap_entry(display, i, | ||||||
|                         png_colormap_compose(display, colormap[i].red, P_FILE, |                         png_colormap_compose(display, colormap[i].red, | ||||||
|                            trans[i], back_r, output_encoding), |                            display->sBIT[0], P_FILE, alpha, back_r, | ||||||
|                         png_colormap_compose(display, colormap[i].green, P_FILE, |                            output_encoding), | ||||||
|                            trans[i], back_g, output_encoding), |                         png_colormap_compose(display, colormap[i].green, | ||||||
|                         png_colormap_compose(display, colormap[i].blue, P_FILE, |                            display->sBIT[1], P_FILE, alpha, back_g, | ||||||
|                            trans[i], back_b, output_encoding), |                            output_encoding), | ||||||
|                         output_encoding == P_LINEAR ? trans[i] * 257U : |                         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], |                            trans[i], | ||||||
|                         output_encoding); |                         output_encoding); | ||||||
|                   } |                   } | ||||||
|  | |||||||
							
								
								
									
										45
									
								
								pngrtran.c
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								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 */ && |       if (bit_depth > 1U /* irrelevant for bit depth 1 */ && | ||||||
|           !(tc->invalid_info & PNG_INFO_sBIT) && |           !(tc->invalid_info & PNG_INFO_sBIT) && | ||||||
|           tc->sBIT_G > 0U/*SAFETY*/ && tc->sBIT_G < bit_depth) |           tc->sBIT_G > 0U/*SAFETY*/ && tc->sBIT_G < bit_depth) | ||||||
|       { |  | ||||||
|          insignificant_bits = bit_depth - tc->sBIT_G; |          insignificant_bits = bit_depth - tc->sBIT_G; | ||||||
|          UNTESTED |  | ||||||
|       } |  | ||||||
| #  endif /* READ_sBIT */ | #  endif /* READ_sBIT */ | ||||||
| 
 | 
 | ||||||
| #  ifdef PNG_READ_tRNS_SUPPORTED | #  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): |                 * of 1 bit gray + 1 bit alpha (transparency): | ||||||
|                 */ |                 */ | ||||||
|                if (insignificant_bits /* only 1 bit significant */) |                if (insignificant_bits /* only 1 bit significant */) | ||||||
|                { |  | ||||||
|                   *--dp = PNG_BYTE((pixel >> 1) * 255U); |                   *--dp = PNG_BYTE((pixel >> 1) * 255U); | ||||||
|                   UNTESTED |  | ||||||
|                } |  | ||||||
| 
 | 
 | ||||||
|                else |                else | ||||||
| #  endif | #  endif | ||||||
| @ -990,10 +984,7 @@ png_do_expand_lbd_gray(png_transformp *transform, png_transform_controlp tc) | |||||||
|                 * below. |                 * below. | ||||||
|                 */ |                 */ | ||||||
|                if (insignificant_bits) |                if (insignificant_bits) | ||||||
|                { |  | ||||||
|                   pixel = ((pixel>>insignificant_bits) * 255U + (div>>1)) / div; |                   pixel = ((pixel>>insignificant_bits) * 255U + (div>>1)) / div; | ||||||
|                   UNTESTED |  | ||||||
|                } |  | ||||||
| 
 | 
 | ||||||
|                else |                else | ||||||
| #  endif | #  endif | ||||||
| @ -2142,10 +2133,10 @@ png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val) | |||||||
| } | } | ||||||
| #endif /* UNUSED */ | #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. |  * m-bit output value. | ||||||
|  */ |  */ | ||||||
| static unsigned int | unsigned int | ||||||
| png_gamma_nxmbit_correct(unsigned int value, png_fixed_point gamma_val, | png_gamma_nxmbit_correct(unsigned int value, png_fixed_point gamma_val, | ||||||
|    unsigned int n/*input bits*/, unsigned int m/*output bits */) |    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*/
 | #if 0 /*UNUSED*/
 | ||||||
| static unsigned int | static unsigned int | ||||||
| png_gamma_sbit_correct(unsigned int value, png_fixed_point gamma_val, | 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; |    const int compose = tr->st.compose_background; | ||||||
| 
 | 
 | ||||||
|    affirm(tc->bit_depth == 16U && tc->format == PNG_FORMAT_GA && |    affirm(tc->bit_depth == 16U && tc->format == PNG_FORMAT_GA && | ||||||
|          tr->st.background_bit_depth == 16U && |          tr->st.background_bit_depth == 16U); | ||||||
|          (tr->st.background_gamma == tc->gamma || | 
 | ||||||
|           tr->st.background_gamma == 0)); |    /* 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 */ |    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; |    const int compose = tr->st.compose_background; | ||||||
| 
 | 
 | ||||||
|    affirm(tc->bit_depth == 16U && tc->format == PNG_FORMAT_RGBA && |    affirm(tc->bit_depth == 16U && tc->format == PNG_FORMAT_RGBA && | ||||||
|          tr->st.background_bit_depth == 16U && |          tr->st.background_bit_depth == 16U); | ||||||
|          (tr->st.background_gamma == tc->gamma || | 
 | ||||||
|           tr->st.background_gamma == 0)); |    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 */ |    tc->sp = tc->dp; /* nothing else changes */ | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 John Bowler
						John Bowler