[devel] Clean up ALPHA flags and transformations

This commit is contained in:
John Bowler
2011-02-12 09:00:16 -06:00
committed by Glenn Randers-Pehrson
parent 5432c01ffd
commit 9b872f4cf9
6 changed files with 111 additions and 164 deletions

View File

@@ -424,170 +424,115 @@ png_do_packswap(png_row_infop row_info, png_bytep row)
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
/* Remove filler or alpha byte(s) */
/* Remove a channel - this used to be 'png_do_strip_filler' but it used a
* somewhat weird combination of flags to determine what to do. All the calls
* to png_do_strip_filler are changed in 1.5.2 to call this instead with the
* correct arguments.
*
* The routine isn't general - the channel must be the channel at the start or
* end (not in the middle) of each pixel.
*/
void /* PRIVATE */
png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
{
png_debug(1, "in png_do_strip_filler");
png_bytep sp = row; /* source pointer */
png_bytep dp = row; /* destination pointer */
png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
/* At the start sp will point to the first byte to copy and dp to where
* it is copied to. ep always points just beyond the end of the row, so
* the loop simply copies (channels-1) channels until sp reaches ep.
*/
/* GA, GX, XG cases */
if (row_info->channels == 2)
{
png_bytep sp = row;
png_bytep dp = row;
png_uint_32 row_width = row_info->width;
png_uint_32 i;
if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
(row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
(flags & PNG_FLAG_STRIP_ALPHA))) &&
row_info->channels == 4)
if (row_info->bit_depth == 8)
{
if (row_info->bit_depth == 8)
{
/* This converts from RGBX or RGBA to RGB */
if (flags & PNG_FLAG_FILLER_AFTER)
{
dp += 3; sp += 4;
for (i = 1; i < row_width; i++)
{
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
sp++;
}
}
if (at_start) /* Skip initial filler */
++sp;
else /* Skip initial channels and, for sp, the filler */
sp += 2, ++dp;
/* This converts from XRGB or ARGB to RGB */
else
{
for (i = 0; i < row_width; i++)
{
sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
}
}
row_info->pixel_depth = 24;
row_info->rowbytes = row_width * 3;
}
/* For a 1 pixel wide image there is nothing to do */
while (sp < ep)
*dp++ = *sp, sp += 2;
else /* if (row_info->bit_depth == 16) */
{
if (flags & PNG_FLAG_FILLER_AFTER)
{
/* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
sp += 8; dp += 6;
for (i = 1; i < row_width; i++)
{
/* This could be (although png_memcpy is probably slower):
png_memcpy(dp, sp, 6);
sp += 8;
dp += 6;
*/
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
sp += 2;
}
}
else
{
/* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
for (i = 0; i < row_width; i++)
{
/* This could be (although png_memcpy is probably slower):
png_memcpy(dp, sp, 6);
sp += 8;
dp += 6;
*/
sp += 2;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
}
}
row_info->pixel_depth = 48;
row_info->rowbytes = row_width * 6;
}
row_info->channels = 3;
row_info->pixel_depth = 8;
}
else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
(row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
(flags & PNG_FLAG_STRIP_ALPHA))) &&
row_info->channels == 2)
else if (row_info->bit_depth == 16)
{
if (row_info->bit_depth == 8)
{
if (flags & PNG_FLAG_FILLER_AFTER)
{
/* This converts from GX or GA to G */
for (i = 0; i < row_width; i++)
{
*dp++ = *sp++;
sp++;
}
}
if (at_start)
sp += 2;
else
sp += 4, dp += 2;
else
{
/* This converts from XG or AG to G */
for (i = 0; i < row_width; i++)
{
sp++;
*dp++ = *sp++;
}
}
while (sp < ep)
*dp++ = *sp++, *dp++ = *sp, sp += 3;
row_info->pixel_depth = 8;
row_info->rowbytes = row_width;
}
else /* if (row_info->bit_depth == 16) */
{
if (flags & PNG_FLAG_FILLER_AFTER)
{
/* This converts from GGXX or GGAA to GG */
sp += 4; dp += 2;
for (i = 1; i < row_width; i++)
{
*dp++ = *sp++;
*dp++ = *sp++;
sp += 2;
}
}
else
{
/* This converts from XXGG or AAGG to GG */
for (i = 0; i < row_width; i++)
{
sp += 2;
*dp++ = *sp++;
*dp++ = *sp++;
}
}
row_info->pixel_depth = 16;
row_info->rowbytes = row_width * 2;
}
row_info->channels = 1;
row_info->pixel_depth = 16;
}
if (flags & PNG_FLAG_STRIP_ALPHA)
row_info->color_type = (png_byte)(row_info->color_type &
~PNG_COLOR_MASK_ALPHA);
else
return; /* bad bit depth */
row_info->channels = 1;
/* Finally fix the color type if it records an alpha channel */
if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
row_info->color_type = PNG_COLOR_TYPE_GRAY;
}
/* RGBA, RGBX, XRGB cases */
else if (row_info->channels == 4)
{
if (row_info->bit_depth == 8)
{
if (at_start) /* Skip initial filler */
++sp;
else /* Skip initial channels and, for sp, the filler */
sp += 4, dp += 3;
/* Note that the loop adds 3 to dp and 4 to sp each time. */
while (sp < ep)
*dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
row_info->pixel_depth = 24;
}
else if (row_info->bit_depth == 16)
{
if (at_start)
sp += 2;
else
sp += 8, dp += 6;
while (sp < ep)
{
/* Copy 6 bytes, skip 2 */
*dp++ = *sp++, *dp++ = *sp++;
*dp++ = *sp++, *dp++ = *sp++;
*dp++ = *sp++, *dp++ = *sp, sp += 3;
}
row_info->pixel_depth = 48;
}
else
return; /* bad bit depth */
row_info->channels = 3;
/* Finally fix the color type if it records an alpha channel */
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
row_info->color_type = PNG_COLOR_TYPE_RGB;
}
else
return; /* The filler channel has gone already */
/* Fix the rowbytes value. */
row_info->rowbytes = dp-row;
}
#endif