[libpng15] Fixes to alpha swap on read, simplified write and filler add code

This commit is contained in:
John Bowler 2011-11-08 21:35:16 -06:00 committed by Glenn Randers-Pehrson
parent d4973837b2
commit e6fb691c49
3 changed files with 46 additions and 21 deletions

View File

@ -1804,10 +1804,12 @@ png_image_read_end(png_voidp argument)
else /* output needs an alpha channel */
{
/* This is tricky because it happens before the swap operation has
* been accomplished, so always add the alpha channel after the
* component channels.
* been accomplished however the swap does *not* swap the added
* alpha channel (weird API), so it must be added in the correct
* place.
*/
png_uint_32 filler; /* opaque filler */
int where;
if (linear)
filler = 65535;
@ -1815,9 +1817,21 @@ png_image_read_end(png_voidp argument)
else
filler = 255;
png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER);
# ifdef PNG_FORMAT_AFIRST_SUPPORTED
if (format & PNG_FORMAT_FLAG_AFIRST)
{
where = PNG_FILLER_BEFORE;
change &= ~PNG_FORMAT_FLAG_AFIRST;
}
else
# endif
where = PNG_FILLER_AFTER;
png_set_add_alpha(png_ptr, filler, where);
}
/* This stops the (irrelevant) call to swap_alpha below. */
change &= ~PNG_FORMAT_FLAG_ALPHA;
}
@ -1841,7 +1855,7 @@ png_image_read_end(png_voidp argument)
}
# ifdef PNG_FORMAT_BGR_SUPPORTED
if (format & PNG_FORMAT_FLAG_BGR)
if (change & PNG_FORMAT_FLAG_BGR)
{
/* Check only the output format; PNG is never BGR, don't do this if
* the output is gray, but fix up the 'format' value in that case.
@ -1857,7 +1871,7 @@ png_image_read_end(png_voidp argument)
# endif
# ifdef PNG_FORMAT_AFIRST_SUPPORTED
if (format & PNG_FORMAT_FLAG_AFIRST)
if (change & PNG_FORMAT_FLAG_AFIRST)
{
/* Only relevant if there is an alpha channel - it's particularly
* important to handle this correctly because do_local_compose may
@ -1924,7 +1938,9 @@ png_image_read_end(png_voidp argument)
# endif
# ifdef PNG_FORMAT_AFIRST_SUPPORTED
if (png_ptr->transformations & PNG_SWAP_ALPHA)
if (png_ptr->transformations & PNG_SWAP_ALPHA ||
((png_ptr->transformations & PNG_ADD_ALPHA) != 0 &&
(png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0))
info_format |= PNG_FORMAT_FLAG_AFIRST;
# endif

View File

@ -3900,6 +3900,16 @@ png_read_start_row(png_structp png_ptr)
max_pixel_depth = png_ptr->pixel_depth;
/* WARNING: * png_read_transform_info (pngrtran.c) performs a simpliar set of
* calculations to calculate the final pixel depth, then
* png_do_read_transforms actually does the transforms. This means that the
* code which effectively calculates this value is actually repeated in three
* separate places. They must all match. Innocent changes to the order of
* transformations can and will break libpng in a way that causes memory
* overwrites.
*
* TODO: fix this.
*/
#ifdef PNG_READ_PACK_SUPPORTED
if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
max_pixel_depth = 8;
@ -3958,10 +3968,7 @@ png_read_start_row(png_structp png_ptr)
#ifdef PNG_READ_FILLER_SUPPORTED
if (png_ptr->transformations & (PNG_FILLER))
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
max_pixel_depth = 32;
else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
{
if (max_pixel_depth <= 8)
max_pixel_depth = 16;
@ -3970,7 +3977,8 @@ png_read_start_row(png_structp png_ptr)
max_pixel_depth = 32;
}
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB ||
png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
if (max_pixel_depth <= 32)
max_pixel_depth = 32;

View File

@ -1805,7 +1805,7 @@ png_write_image_16bit(png_voidp argument)
++out_ptr;
}
png_write_row(png_ptr, (png_bytep)output_row);
png_write_row(png_ptr, display->local_row);
input_row += display->row_bytes/(sizeof (png_uint_16));
}
@ -1911,7 +1911,7 @@ png_write_image_8bit(png_voidp argument)
++out_ptr;
} /* while out_ptr < row_end */
png_write_row(png_ptr, output_row);
png_write_row(png_ptr, display->local_row);
input_row += display->row_bytes/(sizeof (png_uint_16));
} /* while y */
}
@ -1998,11 +1998,9 @@ png_image_write_main(png_voidp argument)
/* Now set up the data transformations (*after* the header is written),
* remove the handled transformations from the 'format' flags for checking.
*
* First check for a little endian system if writing 16 bit files.
*/
format &= ~(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
PNG_FORMAT_FLAG_ALPHA);
/* Check for a little endian system if writing 16 bit files. */
if (write_16bit)
{
PNG_CONST png_uint_16 le = 0x0001;
@ -2014,6 +2012,7 @@ png_image_write_main(png_voidp argument)
# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
if (format & PNG_FORMAT_FLAG_BGR)
{
if (format & PNG_FORMAT_FLAG_COLOR)
png_set_bgr(png_ptr);
format &= ~PNG_FORMAT_FLAG_BGR;
}
@ -2022,13 +2021,15 @@ png_image_write_main(png_voidp argument)
# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
if (format & PNG_FORMAT_FLAG_AFIRST)
{
if (format & PNG_FORMAT_FLAG_ALPHA)
png_set_swap_alpha(png_ptr);
format &= ~PNG_FORMAT_FLAG_AFIRST;
}
# endif
/* That should have handled all the transforms. */
if (format != 0)
/* That should have handled all (both) the transforms. */
if ((format & ~(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
PNG_FORMAT_FLAG_ALPHA)) != 0)
png_error(png_ptr, "png_write_image: unsupported transformation");
{