Remove memcpy of png_transform_background

Replaced by a structure copy which is safer since it doesn't depend on knowing
the first member to be copied, also the copies are improved to copy the
transform args too; not required at present but it may prevent a bug being
introduced in the future.

Signed-off-by: John Bowler <jbowler@acm.org>
This commit is contained in:
John Bowler 2015-09-16 21:33:43 -07:00
parent 601ae5387e
commit fea86b1c29

View File

@ -4049,19 +4049,22 @@ png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
typedef struct
{
png_transform tr;
png_color_16 background; /* MUST COME FIRST */
unsigned int need_expand :1; /* Background matches format of this PNG */
unsigned int rgb_to_gray :1; /* RGB-to-gray transform found */
unsigned int compose_background :1; /* png_set_background */
unsigned int associate_alpha :1;
unsigned int encode_alpha :1;
unsigned int optimize_alpha :1;
unsigned int background_is_gray :1; /* Background color is gray */
unsigned int background_bit_depth :5; /* bit depth, 1..16 */
unsigned int ntrans :3; /* 1..6 bytes */
png_byte transparent_pixel[6];
png_byte background_pixel[6];
png_fixed_point background_gamma;
struct
{
png_color_16 background;
unsigned int need_expand :1; /* Background matches format of PNG */
unsigned int rgb_to_gray :1; /* RGB-to-gray transform found */
unsigned int compose_background :1; /* png_set_background */
unsigned int associate_alpha :1;
unsigned int encode_alpha :1;
unsigned int optimize_alpha :1;
unsigned int background_is_gray :1; /* Background color is gray */
unsigned int background_bit_depth :5; /* bit depth, 1..16 */
unsigned int ntrans :3; /* 1..6 bytes */
png_byte transparent_pixel[6];
png_byte background_pixel[6];
png_fixed_point background_gamma;
} st; /* to allow the whole state to be copied reliably */
} png_transform_background;
static void
@ -4074,9 +4077,9 @@ resolve_background_color(png_transform_background *tr,
* special case is when need_expand is set and the PNG has palette format,
* then (and only then) the background value is a palette index.
*/
if (tr->need_expand && tc->palette)
if (tr->st.need_expand && tc->palette)
{
unsigned int i = tr->background.index;
unsigned int i = tr->st.background.index;
png_byte r, g, b;
if (i >= png_ptr->num_palette)
@ -4086,24 +4089,24 @@ resolve_background_color(png_transform_background *tr,
return;
}
tr->background_bit_depth = 8U;
tr->st.background_bit_depth = 8U;
r = png_ptr->palette[i].red;
g = png_ptr->palette[i].green;
b = png_ptr->palette[i].blue;
if (r == g && g == b)
{
tr->background_is_gray = 1U;
tr->background.gray = g;
tr->st.background_is_gray = 1U;
tr->st.background.gray = g;
UNTESTED
}
else
{
tr->background_is_gray = 0U;
tr->background.red = r;
tr->background.green = g;
tr->background.blue = b;
tr->st.background_is_gray = 0U;
tr->st.background.red = r;
tr->st.background.green = g;
tr->st.background.blue = b;
UNTESTED
}
}
@ -4116,10 +4119,10 @@ resolve_background_color(png_transform_background *tr,
/* First work out the bit depth and whether or not to use the RGB
* fields of the background.
*/
if (tr->need_expand)
if (tr->st.need_expand)
{
affirm(!(tc->format & PNG_FORMAT_FLAG_COLORMAP));
tr->background_bit_depth =
tr->st.background_bit_depth =
png_check_bits(png_ptr, png_ptr->bit_depth, 5U);
use_rgb = (png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0;
}
@ -4131,10 +4134,10 @@ resolve_background_color(png_transform_background *tr,
* COLORMAP PNG and png_set_quantize.
*/
if ((png_ptr->row_format & PNG_FORMAT_FLAG_COLORMAP) != 0)
tr->background_bit_depth = 8U;
tr->st.background_bit_depth = 8U;
else
tr->background_bit_depth =
tr->st.background_bit_depth =
png_check_bits(png_ptr, png_ptr->row_bit_depth, 5U);
use_rgb = (png_ptr->row_format & PNG_FORMAT_FLAG_COLOR) != 0;
@ -4144,35 +4147,35 @@ resolve_background_color(png_transform_background *tr,
* the high bits here (at present no warning is produced if they are
* set.)
*/
mask = png_check_u16(png_ptr, (1U << tr->background_bit_depth)-1U);
mask = png_check_u16(png_ptr, (1U << tr->st.background_bit_depth)-1U);
if (use_rgb)
{
png_uint_16 r, g, b;
r = tr->background.red & mask;
g = tr->background.green & mask;
b = tr->background.blue & mask;
r = tr->st.background.red & mask;
g = tr->st.background.green & mask;
b = tr->st.background.blue & mask;
if (r == g && g == b)
{
tr->background_is_gray = 1U;
tr->background.gray = g;
tr->st.background_is_gray = 1U;
tr->st.background.gray = g;
}
else
{
tr->background_is_gray = 0U;
tr->background.red = r;
tr->background.green = g;
tr->background.blue = b;
tr->st.background_is_gray = 0U;
tr->st.background.red = r;
tr->st.background.green = g;
tr->st.background.blue = b;
}
}
else /* gray */
{
tr->background_is_gray = 1U;
tr->background.gray = tr->background.gray & mask;
tr->st.background_is_gray = 1U;
tr->st.background.gray = tr->st.background.gray & mask;
}
}
}
@ -4213,7 +4216,7 @@ gamma_correct_background(png_transform_background *tr,
{
# define png_ptr (tc->png_ptr)
png_fixed_point correction = tc->gamma;
const unsigned int bdback = tr->background_bit_depth;
const unsigned int bdback = tr->st.background_bit_depth;
const unsigned int bdrow = tc->bit_depth;
/* This is harmless if it fails but it will damage the output pixels - they
@ -4221,7 +4224,7 @@ gamma_correct_background(png_transform_background *tr,
* used.
*/
debug(bdback <= bdrow);
debug(tr->background_is_gray || (bdrow >= 8U && bdback >= 8U));
debug(tr->st.background_is_gray || (bdrow >= 8U && bdback >= 8U));
/* The background is assumed to be full precision; there is no sBIT
* information for it. The convertion converts from the current depth and
@ -4229,28 +4232,28 @@ gamma_correct_background(png_transform_background *tr,
* full 16-bit precision when considering the gamma values even though this
* is probably spurious.
*/
if (correction != 0 && (tr->background_gamma == 0 ||
png_gamma_equal(png_ptr, tr->background_gamma, correction, &correction,
16U)))
if (correction != 0 && (tr->st.background_gamma == 0 ||
png_gamma_equal(png_ptr, tr->st.background_gamma, correction,
&correction, 16U)))
correction = 0; /* no correction! */
if (tr->background_is_gray)
gamma_correct_background_component(png_ptr, &tr->background.gray, bdback,
correction, bdrow);
if (tr->st.background_is_gray)
gamma_correct_background_component(png_ptr, &tr->st.background.gray,
bdback, correction, bdrow);
else
{
gamma_correct_background_component(png_ptr, &tr->background.red, bdback,
correction, bdrow);
gamma_correct_background_component(png_ptr, &tr->background.green, bdback,
correction, bdrow);
gamma_correct_background_component(png_ptr, &tr->background.blue, bdback,
correction, bdrow);
gamma_correct_background_component(png_ptr, &tr->st.background.red,
bdback, correction, bdrow);
gamma_correct_background_component(png_ptr, &tr->st.background.green,
bdback, correction, bdrow);
gamma_correct_background_component(png_ptr, &tr->st.background.blue,
bdback, correction, bdrow);
}
/* Regardless of whether there was a correction set the background gamma: */
tr->background_gamma = tc->gamma;
tr->background_bit_depth = png_check_bits(png_ptr, bdrow, 5U);
tr->st.background_gamma = tc->gamma;
tr->st.background_bit_depth = png_check_bits(png_ptr, bdrow, 5U);
# undef png_ptr
}
@ -4269,9 +4272,9 @@ fill_background_pixel(png_transform_background *tr, png_transform_controlp tc)
*/
gamma_correct_background(tr, tc);
if (tr->background_is_gray)
if (tr->st.background_is_gray)
{
unsigned int g = tr->background.gray;
unsigned int g = tr->st.background.gray;
/* 'g' now has enough bits for the destination, note that in the case of
* low bit depth gray this causes the pixel to be replicated through the
@ -4284,40 +4287,40 @@ fill_background_pixel(png_transform_background *tr, png_transform_controlp tc)
bdtc <<= 1;
}
memset(tr->background_pixel, PNG_BYTE(g), 6U);
memset(tr->st.background_pixel, PNG_BYTE(g), 6U);
if (bdtc == 16U)
tr->background_pixel[0] = tr->background_pixel[2] =
tr->background_pixel[4] = PNG_BYTE(g >> 8);
tr->st.background_pixel[0] = tr->st.background_pixel[2] =
tr->st.background_pixel[4] = PNG_BYTE(g >> 8);
/* Must not include the alpha channel here: */
tr->ntrans = png_check_bits(png_ptr,
tr->st.ntrans = png_check_bits(png_ptr,
((tc->format & PNG_FORMAT_FLAG_COLOR)+1U) << (bdtc == 16U), 3U);
}
else
{
unsigned int r = tr->background.red;
unsigned int g = tr->background.green;
unsigned int b = tr->background.blue;
unsigned int r = tr->st.background.red;
unsigned int g = tr->st.background.green;
unsigned int b = tr->st.background.blue;
debug((tc->format & PNG_FORMAT_FLAG_COLOR) != 0);
switch (bdtc)
{
case 8U:
tr->background_pixel[0] = PNG_BYTE(r);
tr->background_pixel[1] = PNG_BYTE(g);
tr->background_pixel[2] = PNG_BYTE(b);
tr->ntrans = 3U;
tr->st.background_pixel[0] = PNG_BYTE(r);
tr->st.background_pixel[1] = PNG_BYTE(g);
tr->st.background_pixel[2] = PNG_BYTE(b);
tr->st.ntrans = 3U;
break;
case 16U:
tr->background_pixel[0] = PNG_BYTE(r>>8);
tr->background_pixel[1] = PNG_BYTE(r);
tr->background_pixel[2] = PNG_BYTE(g>>8);
tr->background_pixel[3] = PNG_BYTE(g);
tr->background_pixel[4] = PNG_BYTE(b>>8);
tr->background_pixel[5] = PNG_BYTE(b);
tr->ntrans = 6U;
tr->st.background_pixel[0] = PNG_BYTE(r>>8);
tr->st.background_pixel[1] = PNG_BYTE(r);
tr->st.background_pixel[2] = PNG_BYTE(g>>8);
tr->st.background_pixel[3] = PNG_BYTE(g);
tr->st.background_pixel[4] = PNG_BYTE(b>>8);
tr->st.background_pixel[5] = PNG_BYTE(b);
tr->st.ntrans = 6U;
break;
default:
@ -4337,7 +4340,7 @@ png_do_replace_tRNS_multi(png_transformp *transform, png_transform_controlp tc)
png_transform_background *tr =
png_transform_cast(png_transform_background, *transform);
png_bytep dp = png_voidcast(png_bytep, tc->dp);
const unsigned int cbytes = tr->ntrans;
const unsigned int cbytes = tr->st.ntrans;
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
const png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc) - cbytes/*safety*/;
const int copy = dp != sp;
@ -4361,7 +4364,7 @@ png_do_replace_tRNS_multi(png_transformp *transform, png_transform_controlp tc)
/* Find a transparent pixel, or the end: */
do
{
if (memcmp(sp, tr->transparent_pixel, cbytes) == 0) /* transparent */
if (memcmp(sp, tr->st.transparent_pixel, cbytes) == 0) /*transparent*/
break;
sp += cbytes;
}
@ -4383,11 +4386,11 @@ png_do_replace_tRNS_multi(png_transformp *transform, png_transform_controlp tc)
*/
if (sp <= ep) do
{
memcpy(dp, tr->background_pixel, cbytes);
memcpy(dp, tr->st.background_pixel, cbytes);
sp += cbytes;
dp += cbytes;
}
while (sp <= ep && memcmp(sp, tr->transparent_pixel, cbytes) == 0);
while (sp <= ep && memcmp(sp, tr->st.transparent_pixel, cbytes) == 0);
} while (sp <= ep);
debug(sp == ep+cbytes);
@ -4405,14 +4408,14 @@ png_do_replace_tRNS_8(png_transformp *transform, png_transform_controlp tc)
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_alloc_size_t row_bytes = tc->width;
const int copy = dp != sp;
const int transparent_pixel = tr->transparent_pixel[0];
const int background_pixel = tr->background_pixel[0];
const int transparent_pixel = tr->st.transparent_pixel[0];
const int background_pixel = tr->st.background_pixel[0];
/* We expect opaque and transparent pixels to be interleaved but with long
* sequences of each.
*/
debug(!(tc->format & PNG_FORMAT_FLAG_ALPHA) &&
PNG_TC_PIXEL_DEPTH(*tc) == 8 && tr->ntrans == 1);
PNG_TC_PIXEL_DEPTH(*tc) == 8 && tr->st.ntrans == 1);
tc->invalid_info |= PNG_INFO_tRNS;
tc->sp = dp;
@ -4486,14 +4489,14 @@ png_do_replace_tRNS_lbd(png_transformp *transform, png_transform_controlp tc)
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc);
const unsigned int copy = sp != dp;
const png_byte transparent_pixel = tr->transparent_pixel[0];
const png_byte background_pixel = tr->background_pixel[0];
const png_byte transparent_pixel = tr->st.transparent_pixel[0];
const png_byte background_pixel = tr->st.background_pixel[0];
/* We expect opaque and transparent pixels to be interleaved but with long
* sequences of each.
*/
debug(!(tc->format & PNG_FORMAT_FLAG_ALPHA) &&
PNG_TC_PIXEL_DEPTH(*tc) < 8 && tr->ntrans == 1);
PNG_TC_PIXEL_DEPTH(*tc) < 8 && tr->st.ntrans == 1);
tc->sp = dp;
/* Now search for a byte that contains the transparent pixel
@ -4593,13 +4596,13 @@ png_do_background_with_transparent_GA8(png_transformp *transform,
png_bytep dp = png_voidcast(png_bytep, tc->dp);
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
const png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc) - 1U/*safety*/;
const png_byte background_pixel = tr->background_pixel[0];
const png_byte background_pixel = tr->st.background_pixel[0];
/* Because this is an alpha format and we are removing the alpha channel we
* can copy up.
*/
debug(tc->bit_depth == 8U && tc->format == PNG_FORMAT_GA &&
tr->ntrans == 1U);
tr->st.ntrans == 1U);
tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_ALPHA);
tc->sp = dp;
@ -4628,14 +4631,14 @@ png_do_background_with_transparent_GA16(png_transformp *transform,
const png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc) - 3U/*safety*/;
debug(tc->bit_depth == 16U && tc->format == PNG_FORMAT_GA &&
tr->ntrans == 2U);
tr->st.ntrans == 2U);
tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_ALPHA);
tc->sp = dp;
do
{
if (sp[2] == 0U && sp[3] == 0U) /* transparent */
dp[0] = tr->background_pixel[0], dp[1] = tr->background_pixel[1];
dp[0] = tr->st.background_pixel[0], dp[1] = tr->st.background_pixel[1];
else
dp[0] = sp[0], dp[1] = sp[1];
@ -4663,10 +4666,10 @@ png_do_background_with_transparent_GAlbd(png_transformp *transform,
const png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc);
const unsigned int bit_depth = tc->bit_depth;
const unsigned int mask = (1U << bit_depth) - 1U;
const unsigned int back = tr->background_pixel[0] & mask;
const unsigned int back = tr->st.background_pixel[0] & mask;
unsigned int opos, ob, inb;
debug(bit_depth < 8U && tc->format == PNG_FORMAT_GA && tr->ntrans == 1U);
debug(bit_depth < 8U && tc->format == PNG_FORMAT_GA && tr->st.ntrans == 1U);
tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_ALPHA);
tc->sp = dp;
@ -4730,14 +4733,14 @@ png_do_background_with_transparent_RGBA8(png_transformp *transform,
const png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc) - 3U/*safety*/;
debug(tc->bit_depth == 8U && tc->format == PNG_FORMAT_RGBA &&
tr->ntrans == 3U);
tr->st.ntrans == 3U);
tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_ALPHA);
tc->sp = dp;
do
{
if (sp[3] == 0U) /* transparent */
memcpy(dp, tr->background_pixel, 3U);
memcpy(dp, tr->st.background_pixel, 3U);
else
memmove(dp, sp, 3U);
@ -4762,14 +4765,14 @@ png_do_background_with_transparent_RGBA16(png_transformp *transform,
const png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc) - 7U/*safety*/;
debug(tc->bit_depth == 16U && tc->format == PNG_FORMAT_RGBA &&
tr->ntrans == 6U);
tr->st.ntrans == 6U);
tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_ALPHA);
tc->sp = dp;
do
{
if (sp[6] == 0U && sp[7] == 0U) /* transparent */
memcpy(dp, tr->background_pixel, 6U);
memcpy(dp, tr->st.background_pixel, 6U);
else
memmove(dp, sp, 6U);
@ -4859,13 +4862,14 @@ png_do_background_alpha_GA(png_transformp *transform, png_transform_controlp tc)
png_bytep dp = png_voidcast(png_bytep, tc->dp);
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
const png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc) - 3U/*safety*/;
const unsigned int background = tr->background.gray;
const unsigned int background = tr->st.background.gray;
const int copy = (sp != dp);
const int compose = tr->compose_background;
const int compose = tr->st.compose_background;
affirm(tc->bit_depth == 16U && tc->format == PNG_FORMAT_GA &&
tr->background_bit_depth == 16U &&
(tr->background_gamma == tc->gamma || tr->background_gamma == 0));
tr->st.background_bit_depth == 16U &&
(tr->st.background_gamma == tc->gamma ||
tr->st.background_gamma == 0));
tc->sp = tc->dp; /* nothing else changes */
@ -4928,15 +4932,16 @@ png_do_background_alpha_RGBA(png_transformp *transform,
png_bytep dp = png_voidcast(png_bytep, tc->dp);
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
const png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc) - 7U/*safety*/;
const unsigned int bred = tr->background.red;
const unsigned int bgreen = tr->background.green;
const unsigned int bblue = tr->background.blue;
const unsigned int bred = tr->st.background.red;
const unsigned int bgreen = tr->st.background.green;
const unsigned int bblue = tr->st.background.blue;
const int copy = (sp != dp);
const int compose = tr->compose_background;
const int compose = tr->st.compose_background;
affirm(tc->bit_depth == 16U && tc->format == PNG_FORMAT_RGBA &&
tr->background_bit_depth == 16U &&
(tr->background_gamma == tc->gamma || tr->background_gamma == 0));
tr->st.background_bit_depth == 16U &&
(tr->st.background_gamma == tc->gamma ||
tr->st.background_gamma == 0));
tc->sp = tc->dp; /* nothing else changes */
@ -5013,11 +5018,11 @@ png_init_background_alpha_end(png_transformp *transform,
debug(tc->gamma == 0 ||
!png_gamma_significant(png_ptr, tc->gamma, tc_sBIT(tc)));
/* tr->background_is_gray was filled in by resolve_background_color and
/* tr->st.background_is_gray was filled in by resolve_background_color and
* records if either the background was a gray value or it was a color
* value with all the channels equal.
*/
if (!tr->background_is_gray && !(tc->format & PNG_FORMAT_FLAG_COLOR))
if (!tr->st.background_is_gray && !(tc->format & PNG_FORMAT_FLAG_COLOR))
{
# ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
/* Color background with gray data: this happens when there is a
@ -5041,7 +5046,7 @@ png_init_background_alpha_end(png_transformp *transform,
* This only happens with background composition, otherwise the
* transparent pixels are already 0 and nothing needs to be done.
*/
if (tr->compose_background)
if (tr->st.compose_background)
{
/* The transparent pixel handling happens *after* the data has been
* re-encoded to the output gamma:
@ -5052,11 +5057,11 @@ png_init_background_alpha_end(png_transformp *transform,
png_init_background_transparent, PNG_TR_GAMMA_ENCODE+0xF0U));
/* Copy the current state into the new png_transform_background: */
memcpy(&tr_alpha->background, &tr->background,
(sizeof *tr) - offsetof(png_transform_background, background));
tr_alpha->st = tr->st;
tr_alpha->tr.args = tr->tr.args;
}
/* Now it is possible to overwrite tr->background with the linear version.
/* Now it is possible to overwrite tr->st.background with the linear version.
*/
gamma_correct_background(tr, tc);
@ -5075,14 +5080,14 @@ png_init_background_alpha_end(png_transformp *transform,
* gray to RGB transform missing and we need it to happen before
* this point!
*/
affirm(tr->background_is_gray);
affirm(tr->st.background_is_gray);
tr->tr.fn = png_do_background_alpha_GA;
break;
case PNG_FORMAT_RGBA:
if (tr->background_is_gray)
tr->background.blue = tr->background.green = tr->background.red =
tr->background.gray;
if (tr->st.background_is_gray)
tr->st.background.blue = tr->st.background.green =
tr->st.background.red = tr->st.background.gray;
tr->tr.fn = png_do_background_alpha_RGBA;
break;
@ -5127,8 +5132,8 @@ png_init_background_alpha(png_transformp *transform, png_transform_controlp tc)
* be set here. Notice that in C++ terms we are very friendly with
* png_transform_gamma.
*/
tr_end->encode_alpha = tr->encode_alpha;
tr_end->optimize_alpha = tr->optimize_alpha;
tr_end->encode_alpha = tr->st.encode_alpha;
tr_end->optimize_alpha = tr->st.optimize_alpha;
}
{
@ -5181,10 +5186,11 @@ png_init_background(png_transformp *transform, png_transform_controlp tc)
/* Background composition removes the alpha channel, so the other
* operations become irrelevant:
*/
if (tr->compose_background)
tr->associate_alpha = tr->encode_alpha = tr->optimize_alpha = 0U;
if (tr->st.compose_background)
tr->st.associate_alpha = tr->st.encode_alpha = tr->st.optimize_alpha =
0U;
else if (!tr->associate_alpha)
else if (!tr->st.associate_alpha)
{
/* There is nothing to do, delete the whole transform. */
tr->tr.fn = NULL;
@ -5200,13 +5206,13 @@ png_init_background(png_transformp *transform, png_transform_controlp tc)
* inserted between this one and an rgb-to-gray transform, so we can find
* out if rgb-to-gray has been requested:
*/
tr->rgb_to_gray = tr->tr.next != NULL &&
tr->st.rgb_to_gray = tr->tr.next != NULL &&
tr->tr.next->order == PNG_TR_RGB_TO_GRAY;
if ((tc->format & PNG_FORMAT_FLAG_ALPHA) != 0)
{
/* Associated alpha does not strip the alpha channel! */
if (tr->compose_background)
if (tr->st.compose_background)
tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_ALPHA);
}
@ -5215,7 +5221,7 @@ png_init_background(png_transformp *transform, png_transform_controlp tc)
{
/* tRNS will be expanded, or handled */
tc->invalid_info |= PNG_INFO_tRNS;
if (!tr->compose_background)
if (!tr->st.compose_background)
{
tc->format |= PNG_FORMAT_FLAG_ALPHA;
/* And in this case, only, because we are adding an alpha channel we
@ -5244,18 +5250,18 @@ png_init_background(png_transformp *transform, png_transform_controlp tc)
* was in the PNG and no gamma information has been provided by
* png_set_gamma or png_set_alpha_mode.
*/
switch (tr->background_gamma)
switch (tr->st.background_gamma)
{
case PNG_BACKGROUND_GAMMA_FILE:
/* png_init_transform_control has already found the file gamma,
* and because this is the first arithmetic transformation
* nothing has changed it.
*/
tr->background_gamma = tc->gamma;
tr->st.background_gamma = tc->gamma;
break;
case PNG_BACKGROUND_GAMMA_SCREEN:
tr->background_gamma = png_ptr->row_gamma;
tr->st.background_gamma = png_ptr->row_gamma;
break;
default:
@ -5279,11 +5285,11 @@ png_init_background(png_transformp *transform, png_transform_controlp tc)
* following gray-to-RGB transform and the now gray image must be
* composited on a color background.
*/
if (tr->compose_background /* alpha channel stripped */ &&
(tr->background_is_gray ||
((tc->format & PNG_FORMAT_FLAG_COLOR) != 0 && !tr->rgb_to_gray))
if (tr->st.compose_background /* alpha channel stripped */ &&
(tr->st.background_is_gray ||
((tc->format & PNG_FORMAT_FLAG_COLOR) != 0 && !tr->st.rgb_to_gray))
/* color compatible */ &&
tc->bit_depth >= tr->background_bit_depth
tc->bit_depth >= tr->st.background_bit_depth
/* bit depth compatible */ &&
(tc->transparent_alpha ||
(!tc->palette && png_ptr->num_trans == 1 &&
@ -5321,8 +5327,8 @@ png_init_background(png_transformp *transform, png_transform_controlp tc)
debug(PNG_PIXEL_DEPTH(*png_ptr) == PNG_TC_PIXEL_DEPTH(*tc));
/* The transparent_pixel value needs to be filled in. */
affirm(tr->ntrans ==
fill_transparent_pixel(png_ptr, tr->transparent_pixel));
affirm(tr->st.ntrans ==
fill_transparent_pixel(png_ptr, tr->st.transparent_pixel));
/* The whole operation is a no-op if the transparent pixel and the
* background pixel match, even in the associated alpha case where
@ -5335,12 +5341,12 @@ png_init_background(png_transformp *transform, png_transform_controlp tc)
* 'background_pixel' have been expanded to fill a byte, so this
* works.
*/
if (memcmp(tr->transparent_pixel, tr->background_pixel, tr->ntrans)
== 0)
if (memcmp(tr->st.transparent_pixel, tr->st.background_pixel,
tr->st.ntrans) == 0)
tr->tr.fn = NULL;
/* Then the processing function depends on the pixel size: */
else if (tr->ntrans > 1U)
else if (tr->st.ntrans > 1U)
tr->tr.fn = png_do_replace_tRNS_multi;
else if (tc->bit_depth == 8U)
@ -5353,7 +5359,7 @@ png_init_background(png_transformp *transform, png_transform_controlp tc)
* bits are replaced by '1' or all the '1' bits are replaced by
* '0':
*/
png_uint_32 args = tr->background_pixel[0];
png_uint_32 args = tr->st.background_pixel[0];
args <<= 24;
args |= PNG_INFO_tRNS | PNG_INFO_sRGB;
@ -5388,8 +5394,8 @@ png_init_background(png_transformp *transform, png_transform_controlp tc)
png_init_background_alpha, PNG_TR_COMPOSE_ALPHA));
/* Copy the current state into the new png_transform_background: */
memcpy(&tr_alpha->background, &tr->background,
(sizeof *tr) - offsetof(png_transform_background, background));
tr_alpha->st = tr->st;
tr_alpha->tr.args = tr->tr.args;
/* The rest of the init occurs later; this transform is no longer
* needed.
@ -5401,7 +5407,7 @@ png_init_background(png_transformp *transform, png_transform_controlp tc)
* invalidate tRNS.
*/
tc->expand_tRNS = 1U;
if (tr->compose_background)
if (tr->st.compose_background)
tc->strip_alpha = 0U;
/* And push the expand: */
@ -5433,20 +5439,20 @@ png_set_background_fixed(png_structrp png_ptr,
/* This silently overwrites the information if png_set_background is
* called more than once.
*/
tr->background = *background_color;
tr->need_expand = need_expand != 0;
tr->compose_background = 1U; /* png_set_background called */
tr->st.background = *background_color;
tr->st.need_expand = need_expand != 0;
tr->st.compose_background = 1U; /* png_set_background called */
switch (background_gamma_code)
{
case PNG_BACKGROUND_GAMMA_SCREEN:
case PNG_BACKGROUND_GAMMA_FILE:
tr->background_gamma = background_gamma_code;
tr->st.background_gamma = background_gamma_code;
break;
case PNG_BACKGROUND_GAMMA_UNIQUE:
if (background_gamma >= 16 && background_gamma <= 625000000)
{
tr->background_gamma = background_gamma;
tr->st.background_gamma = background_gamma;
break;
}
@ -5454,7 +5460,7 @@ png_set_background_fixed(png_structrp png_ptr,
/* FALL THROUGH */
default:
png_app_error(png_ptr, "invalid gamma information");
tr->background_gamma = (need_expand ?
tr->st.background_gamma = (need_expand ?
PNG_BACKGROUND_GAMMA_FILE : PNG_BACKGROUND_GAMMA_SCREEN);
break;
}
@ -5547,32 +5553,32 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
* is the only mode that doesn't interfere with what
* png_set_background does.
*/
tr->associate_alpha = 0U;
tr_gamma->encode_alpha = tr->encode_alpha = 0U;
tr_gamma->optimize_alpha = tr->optimize_alpha = 0U;
tr->st.associate_alpha = 0U;
tr_gamma->encode_alpha = tr->st.encode_alpha = 0U;
tr_gamma->optimize_alpha = tr->st.optimize_alpha = 0U;
break;
case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */
tr->associate_alpha = 1U;
tr_gamma->encode_alpha = tr->encode_alpha = 0U;
tr_gamma->optimize_alpha = tr->optimize_alpha = 0U;
tr->st.associate_alpha = 1U;
tr_gamma->encode_alpha = tr->st.encode_alpha = 0U;
tr_gamma->optimize_alpha = tr->st.optimize_alpha = 0U;
break;
case PNG_ALPHA_OPTIMIZED:
/* associated with opaque pixels having the given gamma and
* non-opaque pixels being linear.
*/
tr->associate_alpha = 1U;
tr_gamma->encode_alpha = tr->encode_alpha = 0U;
tr_gamma->optimize_alpha = tr->optimize_alpha = 1U;
tr->st.associate_alpha = 1U;
tr_gamma->encode_alpha = tr->st.encode_alpha = 0U;
tr_gamma->optimize_alpha = tr->st.optimize_alpha = 1U;
/* output_gamma records the encoding of opaque pixels! */
break;
case PNG_ALPHA_BROKEN:
/* associated+non-linear+alpha encoded */
tr->associate_alpha = 1U;
tr_gamma->encode_alpha = tr->encode_alpha = 1U;
tr_gamma->optimize_alpha = tr->optimize_alpha = 0U;
tr->st.associate_alpha = 1U;
tr_gamma->encode_alpha = tr->st.encode_alpha = 1U;
tr_gamma->optimize_alpha = tr->st.optimize_alpha = 0U;
break;
default: