summaryrefslogtreecommitdiff
path: root/plugins/FreeImage/Source/LibPNG/pngrtran.c
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2012-05-30 17:27:49 +0000
committerGeorge Hazan <george.hazan@gmail.com>2012-05-30 17:27:49 +0000
commit88708cffa15662dcd2755fce699112d24a10a087 (patch)
tree55d362220b42a52b52eaef2254f894c9a61fb4fd /plugins/FreeImage/Source/LibPNG/pngrtran.c
parent7fa5563a954339f3feeb156285ef56bfde7cbec8 (diff)
update for zlib & FreeImage
git-svn-id: http://svn.miranda-ng.org/main/trunk@238 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/FreeImage/Source/LibPNG/pngrtran.c')
-rw-r--r--plugins/FreeImage/Source/LibPNG/pngrtran.c814
1 files changed, 442 insertions, 372 deletions
diff --git a/plugins/FreeImage/Source/LibPNG/pngrtran.c b/plugins/FreeImage/Source/LibPNG/pngrtran.c
index c23886f3e3..26083a0dd5 100644
--- a/plugins/FreeImage/Source/LibPNG/pngrtran.c
+++ b/plugins/FreeImage/Source/LibPNG/pngrtran.c
@@ -1,7 +1,7 @@
/* pngrtran.c - transforms the data in a row for PNG readers
*
- * Last changed in libpng 1.5.4 [July 7, 2011]
+ * Last changed in libpng 1.5.7 [December 15, 2011]
* Copyright (c) 1998-2011 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -936,15 +936,15 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
switch(error_action)
{
- case 1:
+ case PNG_ERROR_ACTION_NONE:
png_ptr->transformations |= PNG_RGB_TO_GRAY;
break;
- case 2:
+ case PNG_ERROR_ACTION_WARN:
png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
break;
- case 3:
+ case PNG_ERROR_ACTION_ERROR:
png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
break;
@@ -968,13 +968,17 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
{
png_uint_16 red_int, green_int;
- red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
- green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
+ /* NOTE: this calculation does not round, but this behavior is retained
+ * for consistency, the inaccuracy is very small. The code here always
+ * overwrites the coefficients, regardless of whether they have been
+ * defaulted or set already.
+ */
+ red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);
+ green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);
png_ptr->rgb_to_gray_red_coeff = red_int;
png_ptr->rgb_to_gray_green_coeff = green_int;
- png_ptr->rgb_to_gray_blue_coeff =
- (png_uint_16)(32768 - red_int - green_int);
+ png_ptr->rgb_to_gray_coefficients_set = 1;
}
else
@@ -983,17 +987,18 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
png_warning(png_ptr,
"ignoring out of range rgb_to_gray coefficients");
- /* Use the defaults, from the cHRM chunk if set, else the built in Rec
- * 709 values (which correspond to sRGB, so we don't have to worry
- * about the sRGB chunk!)
+ /* Use the defaults, from the cHRM chunk if set, else the historical
+ * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See
+ * png_do_rgb_to_gray for more discussion of the values. In this case
+ * the coefficients are not marked as 'set' and are not overwritten if
+ * something has already provided a default.
*/
if (png_ptr->rgb_to_gray_red_coeff == 0 &&
- png_ptr->rgb_to_gray_green_coeff == 0 &&
- png_ptr->rgb_to_gray_blue_coeff == 0)
+ png_ptr->rgb_to_gray_green_coeff == 0)
{
- png_ptr->rgb_to_gray_red_coeff = 6968; /* .212671 * 32768 + .5 */
- png_ptr->rgb_to_gray_green_coeff = 23434; /* .715160 * 32768 + .5 */
- png_ptr->rgb_to_gray_blue_coeff = 2366;
+ png_ptr->rgb_to_gray_red_coeff = 6968;
+ png_ptr->rgb_to_gray_green_coeff = 23434;
+ /* png_ptr->rgb_to_gray_blue_coeff = 2366; */
}
}
}
@@ -1193,53 +1198,44 @@ png_init_rgb_transformations(png_structp png_ptr)
{
{
/* Expand background and tRNS chunks */
+ int gray = png_ptr->background.gray;
+ int trans_gray = png_ptr->trans_color.gray;
+
switch (png_ptr->bit_depth)
{
case 1:
- png_ptr->background.gray *= (png_uint_16)0xff;
- png_ptr->background.red = png_ptr->background.green
- = png_ptr->background.blue = png_ptr->background.gray;
- if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
- {
- png_ptr->trans_color.gray *= (png_uint_16)0xff;
- png_ptr->trans_color.red = png_ptr->trans_color.green
- = png_ptr->trans_color.blue = png_ptr->trans_color.gray;
- }
+ gray *= 0xff;
+ trans_gray *= 0xff;
break;
case 2:
- png_ptr->background.gray *= (png_uint_16)0x55;
- png_ptr->background.red = png_ptr->background.green
- = png_ptr->background.blue = png_ptr->background.gray;
- if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
- {
- png_ptr->trans_color.gray *= (png_uint_16)0x55;
- png_ptr->trans_color.red = png_ptr->trans_color.green
- = png_ptr->trans_color.blue = png_ptr->trans_color.gray;
- }
+ gray *= 0x55;
+ trans_gray *= 0x55;
break;
case 4:
- png_ptr->background.gray *= (png_uint_16)0x11;
- png_ptr->background.red = png_ptr->background.green
- = png_ptr->background.blue = png_ptr->background.gray;
- if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
- {
- png_ptr->trans_color.gray *= (png_uint_16)0x11;
- png_ptr->trans_color.red = png_ptr->trans_color.green
- = png_ptr->trans_color.blue = png_ptr->trans_color.gray;
- }
+ gray *= 0x11;
+ trans_gray *= 0x11;
break;
default:
case 8:
+ /* Already 8 bits, fall through */
case 16:
- png_ptr->background.red = png_ptr->background.green
- = png_ptr->background.blue = png_ptr->background.gray;
+ /* Already a full 16 bits */
break;
}
+
+ png_ptr->background.red = png_ptr->background.green =
+ png_ptr->background.blue = (png_uint_16)gray;
+
+ if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
+ {
+ png_ptr->trans_color.red = png_ptr->trans_color.green =
+ png_ptr->trans_color.blue = (png_uint_16)trans_gray;
+ }
}
} /* background expand and (therefore) no alpha association. */
#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
@@ -1401,7 +1397,7 @@ png_init_read_transformations(png_structp png_ptr)
if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
{
/* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
- * the file was greyscale the background value is gray.
+ * the file was grayscale the background value is gray.
*/
if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
@@ -1469,6 +1465,28 @@ png_init_read_transformations(png_structp png_ptr)
}
#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
+ (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
+ defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
+ if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) &&
+ (png_ptr->transformations & PNG_COMPOSE) &&
+ !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
+ png_ptr->bit_depth == 16)
+ {
+ /* On the other hand, if a 16-bit file is to be reduced to 8-bits per
+ * component this will also happen after PNG_COMPOSE and so the background
+ * color must be pre-expanded here.
+ *
+ * TODO: fix this too.
+ */
+ png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);
+ png_ptr->background.green =
+ (png_uint_16)(png_ptr->background.green * 257);
+ png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);
+ png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);
+ }
+#endif
+
/* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the
* background support (see the comments in scripts/pnglibconf.dfa), this
* allows pre-multiplication of the alpha channel to be implemented as
@@ -1516,6 +1534,16 @@ png_init_read_transformations(png_structp png_ptr)
#ifdef PNG_READ_BACKGROUND_SUPPORTED
if (png_ptr->transformations & PNG_COMPOSE)
{
+ /* Issue a warning about this combination: because RGB_TO_GRAY is
+ * optimized to do the gamma transform if present yet do_background has
+ * to do the same thing if both options are set a
+ * double-gamma-correction happens. This is true in all versions of
+ * libpng to date.
+ */
+ if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+ png_warning(png_ptr,
+ "libpng does not support gamma+background+rgb_to_gray");
+
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
/* We don't get to here unless there is a tRNS chunk with non-opaque
@@ -1635,7 +1663,7 @@ png_init_read_transformations(png_structp png_ptr)
/* Prevent the transformations being done again.
*
- * NOTE: this is highly dubious; it zaps the transformations in
+ * NOTE: this is highly dubious; it removes the transformations in
* place. This seems inconsistent with the general treatment of the
* transformations elsewhere.
*/
@@ -1645,8 +1673,9 @@ png_init_read_transformations(png_structp png_ptr)
/* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
else /* color_type != PNG_COLOR_TYPE_PALETTE */
{
- png_fixed_point g = PNG_FP_1;
- png_fixed_point gs = PNG_FP_1;
+ int gs_sig, g_sig;
+ png_fixed_point g = PNG_FP_1; /* Correction to linear */
+ png_fixed_point gs = PNG_FP_1; /* Correction to screen */
switch (png_ptr->background_gamma_type)
{
@@ -1670,34 +1699,45 @@ png_init_read_transformations(png_structp png_ptr)
png_error(png_ptr, "invalid background gamma type");
}
- png_ptr->background_1.gray = png_gamma_correct(png_ptr,
- png_ptr->background.gray, g);
+ g_sig = png_gamma_significant(g);
+ gs_sig = png_gamma_significant(gs);
+
+ if (g_sig)
+ png_ptr->background_1.gray = png_gamma_correct(png_ptr,
+ png_ptr->background.gray, g);
- png_ptr->background.gray = png_gamma_correct(png_ptr,
- png_ptr->background.gray, gs);
+ if (gs_sig)
+ png_ptr->background.gray = png_gamma_correct(png_ptr,
+ png_ptr->background.gray, gs);
if ((png_ptr->background.red != png_ptr->background.green) ||
(png_ptr->background.red != png_ptr->background.blue) ||
(png_ptr->background.red != png_ptr->background.gray))
{
/* RGB or RGBA with color background */
- png_ptr->background_1.red = png_gamma_correct(png_ptr,
- png_ptr->background.red, g);
+ if (g_sig)
+ {
+ png_ptr->background_1.red = png_gamma_correct(png_ptr,
+ png_ptr->background.red, g);
- png_ptr->background_1.green = png_gamma_correct(png_ptr,
- png_ptr->background.green, g);
+ png_ptr->background_1.green = png_gamma_correct(png_ptr,
+ png_ptr->background.green, g);
- png_ptr->background_1.blue = png_gamma_correct(png_ptr,
- png_ptr->background.blue, g);
+ png_ptr->background_1.blue = png_gamma_correct(png_ptr,
+ png_ptr->background.blue, g);
+ }
- png_ptr->background.red = png_gamma_correct(png_ptr,
- png_ptr->background.red, gs);
+ if (gs_sig)
+ {
+ png_ptr->background.red = png_gamma_correct(png_ptr,
+ png_ptr->background.red, gs);
- png_ptr->background.green = png_gamma_correct(png_ptr,
- png_ptr->background.green, gs);
+ png_ptr->background.green = png_gamma_correct(png_ptr,
+ png_ptr->background.green, gs);
- png_ptr->background.blue = png_gamma_correct(png_ptr,
- png_ptr->background.blue, gs);
+ png_ptr->background.blue = png_gamma_correct(png_ptr,
+ png_ptr->background.blue, gs);
+ }
}
else
@@ -1709,13 +1749,22 @@ png_init_read_transformations(png_structp png_ptr)
png_ptr->background.red = png_ptr->background.green
= png_ptr->background.blue = png_ptr->background.gray;
}
+
+ /* The background is now in screen gamma: */
+ png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;
} /* color_type != PNG_COLOR_TYPE_PALETTE */
}/* png_ptr->transformations & PNG_BACKGROUND */
else
/* Transformation does not include PNG_BACKGROUND */
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
- if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
+ && ((png_ptr->transformations & PNG_EXPAND) == 0 ||
+ (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
+#endif
+ )
{
png_colorp palette = png_ptr->palette;
int num_palette = png_ptr->num_palette;
@@ -1783,26 +1832,38 @@ png_init_read_transformations(png_structp png_ptr)
if ((png_ptr->transformations & PNG_SHIFT) &&
(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
{
- png_uint_16 i;
- png_uint_16 istop = png_ptr->num_palette;
- int sr = 8 - png_ptr->sig_bit.red;
- int sg = 8 - png_ptr->sig_bit.green;
- int sb = 8 - png_ptr->sig_bit.blue;
+ int i;
+ int istop = png_ptr->num_palette;
+ int shift = 8 - png_ptr->sig_bit.red;
+
+ /* significant bits can be in the range 1 to 7 for a meaninful result, if
+ * the number of significant bits is 0 then no shift is done (this is an
+ * error condition which is silently ignored.)
+ */
+ if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
+ {
+ int component = png_ptr->palette[i].red;
- if (sr < 0 || sr > 8)
- sr = 0;
+ component >>= shift;
+ png_ptr->palette[i].red = (png_byte)component;
+ }
- if (sg < 0 || sg > 8)
- sg = 0;
+ shift = 8 - png_ptr->sig_bit.green;
+ if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
+ {
+ int component = png_ptr->palette[i].green;
- if (sb < 0 || sb > 8)
- sb = 0;
+ component >>= shift;
+ png_ptr->palette[i].green = (png_byte)component;
+ }
- for (i = 0; i < istop; i++)
+ shift = 8 - png_ptr->sig_bit.blue;
+ if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
{
- png_ptr->palette[i].red >>= sr;
- png_ptr->palette[i].green >>= sg;
- png_ptr->palette[i].blue >>= sb;
+ int component = png_ptr->palette[i].blue;
+
+ component >>= shift;
+ png_ptr->palette[i].blue = (png_byte)component;
}
}
#endif /* PNG_READ_SHIFT_SUPPORTED */
@@ -1895,7 +1956,7 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
info_ptr->bit_depth = 8;
# else
-# if PNG_READ_SCALE_16_TO_8_SUPPORTED
+# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
png_ptr->transformations |= PNG_SCALE_16_TO_8;
info_ptr->bit_depth = 8;
# else
@@ -1908,12 +1969,14 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
if (png_ptr->transformations & PNG_GRAY_TO_RGB)
- info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
+ info_ptr->color_type = (png_byte)(info_ptr->color_type |
+ PNG_COLOR_MASK_COLOR);
#endif
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
if (png_ptr->transformations & PNG_RGB_TO_GRAY)
- info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
+ info_ptr->color_type = (png_byte)(info_ptr->color_type &
+ ~PNG_COLOR_MASK_COLOR);
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
@@ -1953,7 +2016,8 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
if (png_ptr->transformations & PNG_STRIP_ALPHA)
{
- info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
+ info_ptr->color_type = (png_byte)(info_ptr->color_type &
+ ~PNG_COLOR_MASK_ALPHA);
info_ptr->num_trans = 0;
}
#endif
@@ -2010,7 +2074,7 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
* decide how it fits in with the other transformations here.
*/
void /* PRIVATE */
-png_do_read_transformations(png_structp png_ptr)
+png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
{
png_debug(1, "in png_do_read_transformations");
@@ -2041,9 +2105,9 @@ png_do_read_transformations(png_structp png_ptr)
#ifdef PNG_READ_EXPAND_SUPPORTED
if (png_ptr->transformations & PNG_EXPAND)
{
- if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
+ if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
{
- png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ png_do_expand_palette(row_info, png_ptr->row_buf + 1,
png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
}
@@ -2051,11 +2115,11 @@ png_do_read_transformations(png_structp png_ptr)
{
if (png_ptr->num_trans &&
(png_ptr->transformations & PNG_EXPAND_tRNS))
- png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ png_do_expand(row_info, png_ptr->row_buf + 1,
&(png_ptr->trans_color));
else
- png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ png_do_expand(row_info, png_ptr->row_buf + 1,
NULL);
}
}
@@ -2064,9 +2128,9 @@ png_do_read_transformations(png_structp png_ptr)
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
!(png_ptr->transformations & PNG_COMPOSE) &&
- (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
- png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
- png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+ png_do_strip_channel(row_info, png_ptr->row_buf + 1,
0 /* at_start == false, because SWAP_ALPHA happens later */);
#endif
@@ -2074,7 +2138,7 @@ png_do_read_transformations(png_structp png_ptr)
if (png_ptr->transformations & PNG_RGB_TO_GRAY)
{
int rgb_error =
- png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info),
+ png_do_rgb_to_gray(png_ptr, row_info,
png_ptr->row_buf + 1);
if (rgb_error)
@@ -2128,45 +2192,55 @@ png_do_read_transformations(png_structp png_ptr)
*/
if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
!(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
- png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
#endif
#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
(defined PNG_READ_ALPHA_MODE_SUPPORTED)
if (png_ptr->transformations & PNG_COMPOSE)
- png_do_compose(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
+ png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
#ifdef PNG_READ_GAMMA_SUPPORTED
if ((png_ptr->transformations & PNG_GAMMA) &&
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ /* Because RGB_TO_GRAY does the gamma transform. */
+ !(png_ptr->transformations & PNG_RGB_TO_GRAY) &&
+#endif
#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
(defined PNG_READ_ALPHA_MODE_SUPPORTED)
+ /* Because PNG_COMPOSE does the gamma transform if there is something to
+ * do (if there is an alpha channel or transparency.)
+ */
!((png_ptr->transformations & PNG_COMPOSE) &&
((png_ptr->num_trans != 0) ||
(png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
#endif
+ /* Because png_init_read_transformations transforms the palette, unless
+ * RGB_TO_GRAY will do the transform.
+ */
(png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
- png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
+ png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
(png_ptr->transformations & PNG_COMPOSE) &&
- (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
- png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
- png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+ png_do_strip_channel(row_info, png_ptr->row_buf + 1,
0 /* at_start == false, because SWAP_ALPHA happens later */);
#endif
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
if ((png_ptr->transformations & PNG_ENCODE_ALPHA) &&
- (png_ptr->row_info.color_type & PNG_COLOR_MASK_ALPHA))
- png_do_encode_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
+ (row_info->color_type & PNG_COLOR_MASK_ALPHA))
+ png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
#endif
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
if (png_ptr->transformations & PNG_SCALE_16_TO_8)
- png_do_scale_16_to_8(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
@@ -2175,16 +2249,16 @@ png_do_read_transformations(png_structp png_ptr)
* calling the API or in a TRANSFORM flag) this is what happens.
*/
if (png_ptr->transformations & PNG_16_TO_8)
- png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ png_do_chop(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
if (png_ptr->transformations & PNG_QUANTIZE)
{
- png_do_quantize(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ png_do_quantize(row_info, png_ptr->row_buf + 1,
png_ptr->palette_lookup, png_ptr->quantize_index);
- if (png_ptr->row_info.rowbytes == 0)
+ if (row_info->rowbytes == 0)
png_error(png_ptr, "png_do_quantize returned rowbytes=0");
}
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
@@ -2196,62 +2270,62 @@ png_do_read_transformations(png_structp png_ptr)
* better accuracy results faster!)
*/
if (png_ptr->transformations & PNG_EXPAND_16)
- png_do_expand_16(&png_ptr->row_info, png_ptr->row_buf + 1);
+ png_do_expand_16(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
/*NOTE: moved here in 1.5.4 (from much later in this list.) */
if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
- png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_READ_INVERT_SUPPORTED
if (png_ptr->transformations & PNG_INVERT_MONO)
- png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ png_do_invert(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_READ_SHIFT_SUPPORTED
if (png_ptr->transformations & PNG_SHIFT)
- png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ png_do_unshift(row_info, png_ptr->row_buf + 1,
&(png_ptr->shift));
#endif
#ifdef PNG_READ_PACK_SUPPORTED
if (png_ptr->transformations & PNG_PACK)
- png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ png_do_unpack(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_READ_BGR_SUPPORTED
if (png_ptr->transformations & PNG_BGR)
- png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ png_do_bgr(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_READ_PACKSWAP_SUPPORTED
if (png_ptr->transformations & PNG_PACKSWAP)
- png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ png_do_packswap(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_READ_FILLER_SUPPORTED
if (png_ptr->transformations & PNG_FILLER)
- png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ png_do_read_filler(row_info, png_ptr->row_buf + 1,
(png_uint_32)png_ptr->filler, png_ptr->flags);
#endif
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
if (png_ptr->transformations & PNG_INVERT_ALPHA)
- png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
if (png_ptr->transformations & PNG_SWAP_ALPHA)
- png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_READ_16BIT_SUPPORTED
#ifdef PNG_READ_SWAP_SUPPORTED
if (png_ptr->transformations & PNG_SWAP_BYTES)
- png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ png_do_swap(row_info, png_ptr->row_buf + 1);
#endif
#endif
@@ -2260,8 +2334,8 @@ png_do_read_transformations(png_structp png_ptr)
{
if (png_ptr->read_user_transform_fn != NULL)
(*(png_ptr->read_user_transform_fn)) /* User read transform function */
- (png_ptr, /* png_ptr */
- &(png_ptr->row_info), /* row_info: */
+ (png_ptr, /* png_ptr */
+ row_info, /* row_info: */
/* png_uint_32 width; width of row */
/* png_size_t rowbytes; number of bytes in row */
/* png_byte color_type; color type of pixels */
@@ -2271,16 +2345,15 @@ png_do_read_transformations(png_structp png_ptr)
png_ptr->row_buf + 1); /* start of pixel data for row */
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
if (png_ptr->user_transform_depth)
- png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
+ row_info->bit_depth = png_ptr->user_transform_depth;
if (png_ptr->user_transform_channels)
- png_ptr->row_info.channels = png_ptr->user_transform_channels;
+ row_info->channels = png_ptr->user_transform_channels;
#endif
- png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
- png_ptr->row_info.channels);
+ row_info->pixel_depth = (png_byte)(row_info->bit_depth *
+ row_info->channels);
- png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
- png_ptr->row_info.width);
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
}
#endif
}
@@ -2394,105 +2467,128 @@ void /* PRIVATE */
png_do_unshift(png_row_infop row_info, png_bytep row,
png_const_color_8p sig_bits)
{
+ int color_type;
+
png_debug(1, "in png_do_unshift");
- if (
- row_info->color_type != PNG_COLOR_TYPE_PALETTE)
+ /* The palette case has already been handled in the _init routine. */
+ color_type = row_info->color_type;
+
+ if (color_type != PNG_COLOR_TYPE_PALETTE)
{
int shift[4];
int channels = 0;
- int c;
- png_uint_16 value = 0;
- png_uint_32 row_width = row_info->width;
+ int bit_depth = row_info->bit_depth;
- if (row_info->color_type & PNG_COLOR_MASK_COLOR)
+ if (color_type & PNG_COLOR_MASK_COLOR)
{
- shift[channels++] = row_info->bit_depth - sig_bits->red;
- shift[channels++] = row_info->bit_depth - sig_bits->green;
- shift[channels++] = row_info->bit_depth - sig_bits->blue;
+ shift[channels++] = bit_depth - sig_bits->red;
+ shift[channels++] = bit_depth - sig_bits->green;
+ shift[channels++] = bit_depth - sig_bits->blue;
}
else
{
- shift[channels++] = row_info->bit_depth - sig_bits->gray;
+ shift[channels++] = bit_depth - sig_bits->gray;
}
- if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+ if (color_type & PNG_COLOR_MASK_ALPHA)
{
- shift[channels++] = row_info->bit_depth - sig_bits->alpha;
+ shift[channels++] = bit_depth - sig_bits->alpha;
}
- for (c = 0; c < channels; c++)
{
- if (shift[c] <= 0)
- shift[c] = 0;
+ int c, have_shift;
- else
- value = 1;
- }
+ for (c = have_shift = 0; c < channels; ++c)
+ {
+ /* A shift of more than the bit depth is an error condition but it
+ * gets ignored here.
+ */
+ if (shift[c] <= 0 || shift[c] >= bit_depth)
+ shift[c] = 0;
- if (!value)
- return;
+ else
+ have_shift = 1;
+ }
- switch (row_info->bit_depth)
+ if (!have_shift)
+ return;
+ }
+
+ switch (bit_depth)
{
default:
+ /* Must be 1bpp gray: should not be here! */
+ /* NOTREACHED */
break;
case 2:
+ /* Must be 2bpp gray */
+ /* assert(channels == 1 && shift[0] == 1) */
{
- png_bytep bp;
- png_size_t i;
- png_size_t istop = row_info->rowbytes;
+ png_bytep bp = row;
+ png_bytep bp_end = bp + row_info->rowbytes;
- for (bp = row, i = 0; i < istop; i++)
+ while (bp < bp_end)
{
- *bp >>= 1;
- *bp++ &= 0x55;
+ int b = (*bp >> 1) & 0x55;
+ *bp++ = (png_byte)b;
}
break;
}
case 4:
+ /* Must be 4bpp gray */
+ /* assert(channels == 1) */
{
png_bytep bp = row;
- png_size_t i;
- png_size_t istop = row_info->rowbytes;
- png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
- (png_byte)((int)0xf >> shift[0]));
+ png_bytep bp_end = bp + row_info->rowbytes;
+ int gray_shift = shift[0];
+ int mask = 0xf >> gray_shift;
- for (i = 0; i < istop; i++)
+ mask |= mask << 4;
+
+ while (bp < bp_end)
{
- *bp >>= shift[0];
- *bp++ &= mask;
+ int b = (*bp >> gray_shift) & mask;
+ *bp++ = (png_byte)b;
}
break;
}
case 8:
+ /* Single byte components, G, GA, RGB, RGBA */
{
png_bytep bp = row;
- png_uint_32 i;
- png_uint_32 istop = row_width * channels;
+ png_bytep bp_end = bp + row_info->rowbytes;
+ int channel = 0;
- for (i = 0; i < istop; i++)
+ while (bp < bp_end)
{
- *bp++ >>= shift[i%channels];
+ int b = *bp >> shift[channel];
+ if (++channel >= channels)
+ channel = 0;
+ *bp++ = (png_byte)b;
}
break;
}
#ifdef PNG_READ_16BIT_SUPPORTED
case 16:
+ /* Double byte components, G, GA, RGB, RGBA */
{
png_bytep bp = row;
- png_uint_32 i;
- png_uint_32 istop = channels * row_width;
+ png_bytep bp_end = bp + row_info->rowbytes;
+ int channel = 0;
- for (i = 0; i < istop; i++)
+ while (bp < bp_end)
{
- value = (png_uint_16)((*bp << 8) + *(bp + 1));
- value >>= shift[i%channels];
+ int value = (bp[0] << 8) + bp[1];
+
+ value >>= shift[channel];
+ if (++channel >= channels)
+ channel = 0;
*bp++ = (png_byte)(value >> 8);
*bp++ = (png_byte)(value & 0xff);
}
@@ -2514,7 +2610,7 @@ png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
if (row_info->bit_depth == 16)
{
png_bytep sp = row; /* source */
- png_bytep dp = row; /* destinaton */
+ png_bytep dp = row; /* destination */
png_bytep ep = sp + row_info->rowbytes; /* end+1 */
while (sp < ep)
@@ -2575,7 +2671,7 @@ png_do_chop(png_row_infop row_info, png_bytep row)
if (row_info->bit_depth == 16)
{
png_bytep sp = row; /* source */
- png_bytep dp = row; /* destinaton */
+ png_bytep dp = row; /* destination */
png_bytep ep = sp + row_info->rowbytes; /* end+1 */
while (sp < ep)
@@ -3055,7 +3151,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
}
}
}
- row_info->channels += (png_byte)2;
+ row_info->channels = (png_byte)(row_info->channels + 2);
row_info->color_type |= PNG_COLOR_MASK_COLOR;
row_info->pixel_depth = (png_byte)(row_info->channels *
row_info->bit_depth);
@@ -3066,33 +3162,61 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
/* Reduce RGB files to grayscale, with or without alpha
- * using the equation given in Poynton's ColorFAQ at
- * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008)
- * New link:
- * <http://www.poynton.com/notes/colour_and_gamma/>
+ * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
+ * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008 but
+ * versions dated 1998 through November 2002 have been archived at
+ * http://web.archive.org/web/20000816232553/http://www.inforamp.net/
+ * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
* Charles Poynton poynton at poynton.com
*
* Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
*
- * We approximate this with
+ * which can be expressed with integers as
+ *
+ * Y = (6969 * R + 23434 * G + 2365 * B)/32768
+ *
+ * Poynton's current link (as of January 2003 through July 2011):
+ * <http://www.poynton.com/notes/colour_and_gamma/>
+ * has changed the numbers slightly:
*
- * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
+ * Y = 0.2126*R + 0.7152*G + 0.0722*B
*
* which can be expressed with integers as
*
- * Y = (6969 * R + 23434 * G + 2365 * B)/32768
+ * Y = (6966 * R + 23436 * G + 2366 * B)/32768
+ *
+ * Historically, however, libpng uses numbers derived from the ITU-R Rec 709
+ * end point chromaticities and the D65 white point. Depending on the
+ * precision used for the D65 white point this produces a variety of different
+ * numbers, however if the four decimal place value used in ITU-R Rec 709 is
+ * used (0.3127,0.3290) the Y calculation would be:
+ *
+ * Y = (6968 * R + 23435 * G + 2366 * B)/32768
*
- * The calculation is to be done in a linear colorspace.
+ * While this is correct the rounding results in an overflow for white, because
+ * the sum of the rounded coefficients is 32769, not 32768. Consequently
+ * libpng uses, instead, the closest non-overflowing approximation:
*
- * Other integer coefficents can be used via png_set_rgb_to_gray().
+ * Y = (6968 * R + 23434 * G + 2366 * B)/32768
+ *
+ * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk
+ * (including an sRGB chunk) then the chromaticities are used to calculate the
+ * coefficients. See the chunk handling in pngrutil.c for more information.
+ *
+ * In all cases the calculation is to be done in a linear colorspace. If no
+ * gamma information is available to correct the encoding of the original RGB
+ * values this results in an implicit assumption that the original PNG RGB
+ * values were linear.
+ *
+ * Other integer coefficents can be used via png_set_rgb_to_gray(). Because
+ * the API takes just red and green coefficients the blue coefficient is
+ * calculated to make the sum 32768. This will result in different rounding
+ * to that used above.
*/
int /* PRIVATE */
png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
{
- png_uint_32 i;
-
- png_uint_32 row_width = row_info->width;
int rgb_error = 0;
png_debug(1, "in png_do_rgb_to_gray");
@@ -3100,235 +3224,180 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) &&
(row_info->color_type & PNG_COLOR_MASK_COLOR))
{
- png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
- png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
- png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
+ PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
+ PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
+ PNG_CONST png_uint_32 bc = 32768 - rc - gc;
+ PNG_CONST png_uint_32 row_width = row_info->width;
+ PNG_CONST int have_alpha =
+ (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ if (row_info->bit_depth == 8)
{
- if (row_info->bit_depth == 8)
- {
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
- if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
+ /* Notice that gamma to/from 1 are not necessarily inverses (if
+ * there is an overall gamma correction). Prior to 1.5.5 this code
+ * checked the linearized values for equality; this doesn't match
+ * the documentation, the original values must be checked.
+ */
+ if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
{
- png_bytep sp = row;
- png_bytep dp = row;
+ png_byte red = *(sp++);
+ png_byte green = *(sp++);
+ png_byte blue = *(sp++);
- for (i = 0; i < row_width; i++)
+ if (red != green || red != blue)
{
- png_byte red = png_ptr->gamma_to_1[*(sp++)];
- png_byte green = png_ptr->gamma_to_1[*(sp++)];
- png_byte blue = png_ptr->gamma_to_1[*(sp++)];
-
- if (red != green || red != blue)
- {
- rgb_error |= 1;
- *(dp++) = png_ptr->gamma_from_1[
- (rc*red + gc*green + bc*blue)>>15];
- }
+ red = png_ptr->gamma_to_1[red];
+ green = png_ptr->gamma_to_1[green];
+ blue = png_ptr->gamma_to_1[blue];
- else
- *(dp++) = *(sp - 1);
+ rgb_error |= 1;
+ *(dp++) = png_ptr->gamma_from_1[
+ (rc*red + gc*green + bc*blue + 16384)>>15];
}
- }
- else
-#endif
- {
- png_bytep sp = row;
- png_bytep dp = row;
- for (i = 0; i < row_width; i++)
- {
- png_byte red = *(sp++);
- png_byte green = *(sp++);
- png_byte blue = *(sp++);
- if (red != green || red != blue)
- {
- rgb_error |= 1;
- *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
- }
+ else
+ {
+ /* If there is no overall correction the table will not be
+ * set.
+ */
+ if (png_ptr->gamma_table != NULL)
+ red = png_ptr->gamma_table[red];
- else
- *(dp++) = *(sp - 1);
+ *(dp++) = red;
}
+
+ if (have_alpha)
+ *(dp++) = *(sp++);
}
}
-
- else /* RGB bit_depth == 16 */
+ else
+#endif
{
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
- if (png_ptr->gamma_16_to_1 != NULL &&
- png_ptr->gamma_16_from_1 != NULL)
- {
- png_bytep sp = row;
- png_bytep dp = row;
- for (i = 0; i < row_width; i++)
- {
- png_uint_16 red, green, blue, w;
-
- red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
-
- if (red == green && red == blue)
- w = red;
-
- else
- {
- png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff)
- >> png_ptr->gamma_shift][red>>8];
- png_uint_16 green_1 =
- png_ptr->gamma_16_to_1[(green&0xff) >>
- png_ptr->gamma_shift][green>>8];
- png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff)
- >> png_ptr->gamma_shift][blue>>8];
- png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
- + bc*blue_1)>>15);
- w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
- png_ptr->gamma_shift][gray16 >> 8];
- rgb_error |= 1;
- }
+ png_bytep sp = row;
+ png_bytep dp = row;
+ png_uint_32 i;
- *(dp++) = (png_byte)((w>>8) & 0xff);
- *(dp++) = (png_byte)(w & 0xff);
- }
- }
- else
-#endif
+ for (i = 0; i < row_width; i++)
{
- png_bytep sp = row;
- png_bytep dp = row;
- for (i = 0; i < row_width; i++)
- {
- png_uint_16 red, green, blue, gray16;
+ png_byte red = *(sp++);
+ png_byte green = *(sp++);
+ png_byte blue = *(sp++);
- red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
+ if (red != green || red != blue)
+ {
+ rgb_error |= 1;
+ /*NOTE: this is the historical approach which simply
+ * truncates the results.
+ */
+ *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
+ }
- if (red != green || red != blue)
- rgb_error |= 1;
+ else
+ *(dp++) = red;
- gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
- *(dp++) = (png_byte)((gray16>>8) & 0xff);
- *(dp++) = (png_byte)(gray16 & 0xff);
- }
+ if (have_alpha)
+ *(dp++) = *(sp++);
}
}
}
- if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+
+ else /* RGB bit_depth == 16 */
{
- if (row_info->bit_depth == 8)
- {
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
- if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
+ if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
{
- png_bytep sp = row;
- png_bytep dp = row;
- for (i = 0; i < row_width; i++)
- {
- png_byte red = png_ptr->gamma_to_1[*(sp++)];
- png_byte green = png_ptr->gamma_to_1[*(sp++)];
- png_byte blue = png_ptr->gamma_to_1[*(sp++)];
+ png_uint_16 red, green, blue, w;
- if (red != green || red != blue)
- rgb_error |= 1;
+ red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
+ green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
+ blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- *(dp++) = png_ptr->gamma_from_1
- [(rc*red + gc*green + bc*blue)>>15];
+ if (red == green && red == blue)
+ {
+ if (png_ptr->gamma_16_table != NULL)
+ w = png_ptr->gamma_16_table[(red&0xff)
+ >> png_ptr->gamma_shift][red>>8];
- *(dp++) = *(sp++); /* alpha */
+ else
+ w = red;
}
- }
- else
-#endif
- {
- png_bytep sp = row;
- png_bytep dp = row;
- for (i = 0; i < row_width; i++)
+
+ else
{
- png_byte red = *(sp++);
- png_byte green = *(sp++);
- png_byte blue = *(sp++);
- if (red != green || red != blue)
- rgb_error |= 1;
-
- *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
- *(dp++) = *(sp++); /* alpha */
+ png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff)
+ >> png_ptr->gamma_shift][red>>8];
+ png_uint_16 green_1 =
+ png_ptr->gamma_16_to_1[(green&0xff) >>
+ png_ptr->gamma_shift][green>>8];
+ png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff)
+ >> png_ptr->gamma_shift][blue>>8];
+ png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
+ + bc*blue_1 + 16384)>>15);
+ w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
+ png_ptr->gamma_shift][gray16 >> 8];
+ rgb_error |= 1;
+ }
+
+ *(dp++) = (png_byte)((w>>8) & 0xff);
+ *(dp++) = (png_byte)(w & 0xff);
+
+ if (have_alpha)
+ {
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
}
}
}
- else /* RGBA bit_depth == 16 */
+ else
+#endif
{
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
- if (png_ptr->gamma_16_to_1 != NULL &&
- png_ptr->gamma_16_from_1 != NULL)
- {
- png_bytep sp = row;
- png_bytep dp = row;
- for (i = 0; i < row_width; i++)
- {
- png_uint_16 red, green, blue, w;
-
- red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
-
- if (red == green && red == blue)
- w = red;
-
- else
- {
- png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
- png_ptr->gamma_shift][red>>8];
-
- png_uint_16 green_1 =
- png_ptr->gamma_16_to_1[(green&0xff) >>
- png_ptr->gamma_shift][green>>8];
+ png_bytep sp = row;
+ png_bytep dp = row;
+ png_uint_32 i;
- png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
- png_ptr->gamma_shift][blue>>8];
+ for (i = 0; i < row_width; i++)
+ {
+ png_uint_16 red, green, blue, gray16;
- png_uint_16 gray16 = (png_uint_16)((rc * red_1
- + gc * green_1 + bc * blue_1)>>15);
+ red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
+ green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
+ blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
- png_ptr->gamma_shift][gray16 >> 8];
+ if (red != green || red != blue)
+ rgb_error |= 1;
- rgb_error |= 1;
- }
+ /* From 1.5.5 in the 16 bit case do the accurate conversion even
+ * in the 'fast' case - this is because this is where the code
+ * ends up when handling linear 16 bit data.
+ */
+ gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
+ 15);
+ *(dp++) = (png_byte)((gray16>>8) & 0xff);
+ *(dp++) = (png_byte)(gray16 & 0xff);
- *(dp++) = (png_byte)((w>>8) & 0xff);
- *(dp++) = (png_byte)(w & 0xff);
- *(dp++) = *(sp++); /* alpha */
- *(dp++) = *(sp++);
- }
- }
- else
-#endif
- {
- png_bytep sp = row;
- png_bytep dp = row;
- for (i = 0; i < row_width; i++)
+ if (have_alpha)
{
- png_uint_16 red, green, blue, gray16;
- red = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2;
- green = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2;
- blue = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2;
-
- if (red != green || red != blue)
- rgb_error |= 1;
-
- gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
- *(dp++) = (png_byte)((gray16>>8) & 0xff);
- *(dp++) = (png_byte)(gray16 & 0xff);
- *(dp++) = *(sp++); /* alpha */
+ *(dp++) = *(sp++);
*(dp++) = *(sp++);
}
}
}
}
- row_info->channels -= 2;
+
+ row_info->channels = (png_byte)(row_info->channels - 2);
row_info->color_type = (png_byte)(row_info->color_type &
~PNG_COLOR_MASK_COLOR);
row_info->pixel_depth = (png_byte)(row_info->channels *
@@ -3398,7 +3467,8 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette)
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-#ifdef PNG_READ_BACKGROUND_SUPPORTED
+#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
+ (defined PNG_READ_ALPHA_MODE_SUPPORTED)
/* Replace any alpha or transparency with the supplied background color.
* "background" is already in the screen gamma, while "background_1" is
* at a gamma of 1.0. Paletted files have already been taken care of.
@@ -4106,7 +4176,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
}
}
}
-#endif
+#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */
#ifdef PNG_READ_GAMMA_SUPPORTED
/* Gamma correct the image, avoiding the alpha channel. Make sure
@@ -4762,7 +4832,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
-/* If the bit depth is 8 and the colour type is not a palette type expand the
+/* If the bit depth is 8 and the color type is not a palette type expand the
* whole row to 16 bits. Has no effect otherwise.
*/
void /* PRIVATE */
@@ -4939,8 +5009,8 @@ png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
- png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL);
- png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL);
+ png_uint_32 red = (s0 + s1 + 65536) & 0xffff;
+ png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
*(rp ) = (png_byte)((red >> 8) & 0xff);
*(rp + 1) = (png_byte)(red & 0xff);
*(rp + 4) = (png_byte)((blue >> 8) & 0xff);