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);
|
||||||
|
|
||||||
|
# if PNG_LIBPNG_VER < 10700
|
||||||
pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */
|
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
|
||||||
|
|||||||
246
pngread.c
246
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: */
|
||||||
|
if (display->file_to_sRGB != PNG_FP_1)
|
||||||
|
value = png_gamma_nxmbit_correct(value >> (8U-significant_bits),
|
||||||
|
display->file_to_sRGB, significant_bits, 16U);
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
value *= 257U;
|
value *= 257U;
|
||||||
|
|
||||||
if (display->file_to_sRGB != PNG_FP_1)
|
if (significant_bits < 8U)
|
||||||
value = png_gamma_16bit_correct(png_ptr, value, display->file_to_sRGB);
|
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.
|
||||||
*/
|
*/
|
||||||
|
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];
|
red = png_sRGB_table[red];
|
||||||
green = png_sRGB_table[green];
|
green = png_sRGB_table[green];
|
||||||
blue = png_sRGB_table[blue];
|
blue = png_sRGB_table[blue];
|
||||||
alpha *= 257;
|
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