Make png_struct palette, trans_alpha private

This removes the side-effect on the png_struct palette of calling png_set_PLTE
or png_set_tRNS.  NOTE: this is a quiet API change, it was possible before to
alter the palette on a PNG image by using png_set_PLTE, but this was unintended
and inconsistent with the other png_set APIs.

Fix a bug in palette index checking; png_struct::num_palette could, in
principle, get changed by the transformations (e.g. png_set_quantize) and this
would invalidate the check.  The palette checking init function now makes a copy
of png_struct::num_palette.

Fix a bug in pngvalid error handling.  A png_error in png_write_info is not
continuable (a valid image cannot necessarily be written afterward) because the
png_error aborts the write of subsequent pre-IDAT chunks.  In particular an
abort as a result of a bogus colorspace information (gAMA, cHRM, sBIT etc)
prevents the write of the PLTE chunk.

Signed-off-by: John Bowler <jbowler@acm.org>
This commit is contained in:
John Bowler
2015-12-01 08:16:53 -08:00
parent 8fe2eac47f
commit 84a8bb8244
8 changed files with 137 additions and 139 deletions

View File

@@ -580,12 +580,13 @@ init_transform_mech(png_structrp png_ptr, png_transform_control *tc, int start)
#ifdef PNG_PALETTE_MAX_SUPPORTED
static int
set_palette_max(png_structrp png_ptr, png_transformp tr, unsigned int max)
set_palette_max(png_structrp png_ptr, png_transformp tr, unsigned int max,
unsigned int format_max)
/* Called whenever a new maximum pixel value is found */
{
/* One of these must be true: */
# ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
if (max >= png_ptr->num_palette && !png_ptr->palette_index_check_issued)
if (max >= tr->args && !png_ptr->palette_index_check_issued)
{
# ifdef PNG_READ_SUPPORTED
# ifdef PNG_WRITE_SUPPORTED
@@ -604,7 +605,7 @@ set_palette_max(png_structrp png_ptr, png_transformp tr, unsigned int max)
png_ptr->palette_index_max = png_check_bits(png_ptr, max, 9);
# endif
if (max == (1U << png_ptr->bit_depth)-1U)
if (max == format_max)
{
tr->fn = NULL; /* no point continuing once the max has been seen */
return 1; /* stop */
@@ -633,7 +634,7 @@ palette_max_1bpp(png_transformp *tr, png_transform_controlp tc)
}
/* If the code reaches this point there is a set pixel */
(void)set_palette_max(tc->png_ptr, *tr, 1);
(void)set_palette_max(tc->png_ptr, *tr, 1U, 1U);
}
static void
@@ -690,7 +691,7 @@ palette_max_2bpp(png_transformp *tr, png_transform_controlp tc)
continue;
/* new_max is greater than max: */
if (set_palette_max(tc->png_ptr, *tr, new_max))
if (set_palette_max(tc->png_ptr, *tr, new_max, 3U))
return;
/* Record new_max: */
@@ -726,7 +727,7 @@ palette_max_4bpp(png_transformp *tr, png_transform_controlp tc)
if (max > (*tr)->args)
{
if (set_palette_max(tc->png_ptr, *tr, max))
if (set_palette_max(tc->png_ptr, *tr, max, 15U))
return;
(*tr)->args = max;
@@ -752,7 +753,7 @@ palette_max_8bpp(png_transformp *tr, png_transform_controlp tc)
if (max > (*tr)->args)
{
if (set_palette_max(tc->png_ptr, *tr, max))
if (set_palette_max(tc->png_ptr, *tr, max, 255U))
return;
(*tr)->args = max;
@@ -765,13 +766,19 @@ palette_max_init(png_transformp *tr, png_transform_controlp tc)
# define png_ptr (tc->png_ptr)
if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
{
if (tc->init == PNG_TC_INIT_FINAL) switch (tc->bit_depth)
if (tc->init == PNG_TC_INIT_FINAL)
{
case 1: (*tr)->fn = palette_max_1bpp; break;
case 2: (*tr)->fn = palette_max_2bpp; break;
case 4: (*tr)->fn = palette_max_4bpp; break;
case 8: (*tr)->fn = palette_max_8bpp; break;
default:impossible("palette bit depth");
/* Record the palette depth to check here: */
(*tr)->args = png_ptr->num_palette;
switch (tc->bit_depth)
{
case 1: (*tr)->fn = palette_max_1bpp; break;
case 2: (*tr)->fn = palette_max_2bpp; break;
case 4: (*tr)->fn = palette_max_4bpp; break;
case 8: (*tr)->fn = palette_max_8bpp; break;
default:impossible("palette bit depth");
}
}
}