12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25 /* pngrtran.c - transforms the data in a row for PNG readers
26 *
27 * This file is available under and governed by the GNU General Public
28 * License version 2 only, as published by the Free Software Foundation.
29 * However, the following notice accompanied the original version of this
30 * file and, per its terms, should not be removed:
31 *
32 * Last changed in libpng 1.6.35 [July 15, 2018]
33 * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
34 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
35 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
36 *
37 * This code is released under the libpng license.
38 * For conditions of distribution and use, see the disclaimer
39 * and license in png.h
40 *
41 * This file contains functions optionally called by an application
42 * in order to tell libpng how to handle data when reading a PNG.
43 * Transformations that are used in both reading and writing are
44 * in pngtrans.c.
45 */
46
47 #include "pngpriv.h"
48
49 #ifdef PNG_READ_SUPPORTED
50
51 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
52 void PNGAPI
53 png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
54 {
55 png_debug(1, "in png_set_crc_action");
56
57 if (png_ptr == NULL)
58 return;
59
60 /* Tell libpng how we react to CRC errors in critical chunks */
61 switch (crit_action)
62 {
63 case PNG_CRC_NO_CHANGE: /* Leave setting as is */
64 break;
65
66 case PNG_CRC_WARN_USE: /* Warn/use data */
67 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
68 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
1191 (png_ptr->transformations & PNG_EXPAND) != 0)
1192 {
1193 {
1194 png_ptr->background.red =
1195 png_ptr->palette[png_ptr->background.index].red;
1196 png_ptr->background.green =
1197 png_ptr->palette[png_ptr->background.index].green;
1198 png_ptr->background.blue =
1199 png_ptr->palette[png_ptr->background.index].blue;
1200
1201 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
1202 if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
1203 {
1204 if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1205 {
1206 /* Invert the alpha channel (in tRNS) unless the pixels are
1207 * going to be expanded, in which case leave it for later
1208 */
1209 int i, istop = png_ptr->num_trans;
1210
1211 for (i=0; i<istop; i++)
1212 png_ptr->trans_alpha[i] = (png_byte)(255 -
1213 png_ptr->trans_alpha[i]);
1214 }
1215 }
1216 #endif /* READ_INVERT_ALPHA */
1217 }
1218 } /* background expand and (therefore) no alpha association. */
1219 #endif /* READ_EXPAND && READ_BACKGROUND */
1220 }
1221
1222 static void /* PRIVATE */
1223 png_init_rgb_transformations(png_structrp png_ptr)
1224 {
1225 /* Added to libpng-1.5.4: check the color type to determine whether there
1226 * is any alpha or transparency in the image and simply cancel the
1227 * background and alpha mode stuff if there isn't.
1228 */
1229 int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;
1230 int input_has_transparency = png_ptr->num_trans > 0;
1231
1232 /* If no alpha we can optimize. */
1233 if (input_has_alpha == 0)
2997 * libpng uses, instead, the closest non-overflowing approximation:
2998 *
2999 * Y = (6968 * R + 23434 * G + 2366 * B)/32768
3000 *
3001 * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk
3002 * (including an sRGB chunk) then the chromaticities are used to calculate the
3003 * coefficients. See the chunk handling in pngrutil.c for more information.
3004 *
3005 * In all cases the calculation is to be done in a linear colorspace. If no
3006 * gamma information is available to correct the encoding of the original RGB
3007 * values this results in an implicit assumption that the original PNG RGB
3008 * values were linear.
3009 *
3010 * Other integer coefficients can be used via png_set_rgb_to_gray(). Because
3011 * the API takes just red and green coefficients the blue coefficient is
3012 * calculated to make the sum 32768. This will result in different rounding
3013 * to that used above.
3014 */
3015 static int
3016 png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
3017
3018 {
3019 int rgb_error = 0;
3020
3021 png_debug(1, "in png_do_rgb_to_gray");
3022
3023 if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
3024 (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
3025 {
3026 PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
3027 PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
3028 PNG_CONST png_uint_32 bc = 32768 - rc - gc;
3029 PNG_CONST png_uint_32 row_width = row_info->width;
3030 PNG_CONST int have_alpha =
3031 (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
3032
3033 if (row_info->bit_depth == 8)
3034 {
3035 #ifdef PNG_READ_GAMMA_SUPPORTED
3036 /* Notice that gamma to/from 1 are not necessarily inverses (if
3037 * there is an overall gamma correction). Prior to 1.5.5 this code
3038 * checked the linearized values for equality; this doesn't match
3039 * the documentation, the original values must be checked.
3040 */
3041 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
3042 {
3043 png_bytep sp = row;
3044 png_bytep dp = row;
3045 png_uint_32 i;
3046
3047 for (i = 0; i < row_width; i++)
3048 {
3049 png_byte red = *(sp++);
3050 png_byte green = *(sp++);
3051 png_byte blue = *(sp++);
4154 }
4155 }
4156 #endif
4157
4158 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4159 /* Encode the alpha channel to the output gamma (the input channel is always
4160 * linear.) Called only with color types that have an alpha channel. Needs the
4161 * from_1 tables.
4162 */
4163 static void
4164 png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
4165 {
4166 png_uint_32 row_width = row_info->width;
4167
4168 png_debug(1, "in png_do_encode_alpha");
4169
4170 if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4171 {
4172 if (row_info->bit_depth == 8)
4173 {
4174 PNG_CONST png_bytep table = png_ptr->gamma_from_1;
4175
4176 if (table != NULL)
4177 {
4178 PNG_CONST int step =
4179 (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
4180
4181 /* The alpha channel is the last component: */
4182 row += step - 1;
4183
4184 for (; row_width > 0; --row_width, row += step)
4185 *row = table[*row];
4186
4187 return;
4188 }
4189 }
4190
4191 else if (row_info->bit_depth == 16)
4192 {
4193 PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1;
4194 PNG_CONST int gamma_shift = png_ptr->gamma_shift;
4195
4196 if (table != NULL)
4197 {
4198 PNG_CONST int step =
4199 (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
4200
4201 /* The alpha channel is the last component: */
4202 row += step - 2;
4203
4204 for (; row_width > 0; --row_width, row += step)
4205 {
4206 png_uint_16 v;
4207
4208 v = table[*(row + 1) >> gamma_shift][*row];
4209 *row = (png_byte)((v >> 8) & 0xff);
4210 *(row + 1) = (png_byte)(v & 0xff);
4211 }
4212
4213 return;
4214 }
4215 }
4216 }
4217
4218 /* Only get to here if called with a weird row_info; no harm has been done,
4219 * so just issue a warning.
4220 */
4221 png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
4222 }
4223 #endif
4224
4225 #ifdef PNG_READ_EXPAND_SUPPORTED
4226 /* Expands a palette row to an RGB or RGBA row depending
4227 * upon whether you supply trans and num_trans.
4228 */
4229 static void
4230 png_do_expand_palette(png_row_infop row_info, png_bytep row,
4231 png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
4232 {
4233 int shift, value;
4234 png_bytep sp, dp;
4235 png_uint_32 i;
4236 png_uint_32 row_width=row_info->width;
4237
4238 png_debug(1, "in png_do_expand_palette");
4239
4240 if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4241 {
4242 if (row_info->bit_depth < 8)
4243 {
4244 switch (row_info->bit_depth)
4245 {
4246 case 1:
4247 {
4248 sp = row + (size_t)((row_width - 1) >> 3);
4249 dp = row + (size_t)row_width - 1;
4250 shift = 7 - (int)((row_width + 7) & 0x07);
4251 for (i = 0; i < row_width; i++)
4315 }
4316 break;
4317 }
4318
4319 default:
4320 break;
4321 }
4322 row_info->bit_depth = 8;
4323 row_info->pixel_depth = 8;
4324 row_info->rowbytes = row_width;
4325 }
4326
4327 if (row_info->bit_depth == 8)
4328 {
4329 {
4330 if (num_trans > 0)
4331 {
4332 sp = row + (size_t)row_width - 1;
4333 dp = row + ((size_t)row_width << 2) - 1;
4334
4335 for (i = 0; i < row_width; i++)
4336 {
4337 if ((int)(*sp) >= num_trans)
4338 *dp-- = 0xff;
4339
4340 else
4341 *dp-- = trans_alpha[*sp];
4342
4343 *dp-- = palette[*sp].blue;
4344 *dp-- = palette[*sp].green;
4345 *dp-- = palette[*sp].red;
4346 sp--;
4347 }
4348 row_info->bit_depth = 8;
4349 row_info->pixel_depth = 32;
4350 row_info->rowbytes = row_width * 4;
4351 row_info->color_type = 6;
4352 row_info->channels = 4;
4353 }
4354
4355 else
4356 {
4357 sp = row + (size_t)row_width - 1;
4358 dp = row + (size_t)(row_width * 3) - 1;
4359
4360 for (i = 0; i < row_width; i++)
4361 {
4362 *dp-- = palette[*sp].blue;
4363 *dp-- = palette[*sp].green;
4364 *dp-- = palette[*sp].red;
4365 sp--;
4366 }
4367
4368 row_info->bit_depth = 8;
4369 row_info->pixel_depth = 24;
4370 row_info->rowbytes = row_width * 3;
4371 row_info->color_type = 2;
4372 row_info->channels = 3;
4373 }
4374 }
4375 }
4376 }
4377 }
4378
4379 /* If the bit depth < 8, it is expanded to 8. Also, if the already
4380 * expanded transparency value is supplied, an alpha channel is built.
4754 * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
4755 * PNG_WARN_UNINITIALIZED_ROW removed. In 1.6 the new flag is set only for
4756 * all transformations, however in practice the ROW_INIT always gets done on
4757 * demand, if necessary.
4758 */
4759 if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
4760 (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
4761 {
4762 /* Application has failed to call either png_read_start_image() or
4763 * png_read_update_info() after setting transforms that expand pixels.
4764 * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
4765 */
4766 png_error(png_ptr, "Uninitialized row");
4767 }
4768
4769 #ifdef PNG_READ_EXPAND_SUPPORTED
4770 if ((png_ptr->transformations & PNG_EXPAND) != 0)
4771 {
4772 if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4773 {
4774 png_do_expand_palette(row_info, png_ptr->row_buf + 1,
4775 png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
4776 }
4777
4778 else
4779 {
4780 if (png_ptr->num_trans != 0 &&
4781 (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
4782 png_do_expand(row_info, png_ptr->row_buf + 1,
4783 &(png_ptr->trans_color));
4784
4785 else
4786 png_do_expand(row_info, png_ptr->row_buf + 1, NULL);
4787 }
4788 }
4789 #endif
4790
4791 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4792 if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
4793 (png_ptr->transformations & PNG_COMPOSE) == 0 &&
4794 (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
|
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25 /* pngrtran.c - transforms the data in a row for PNG readers
26 *
27 * This file is available under and governed by the GNU General Public
28 * License version 2 only, as published by the Free Software Foundation.
29 * However, the following notice accompanied the original version of this
30 * file and, per its terms, should not be removed:
31 *
32 * Copyright (c) 2018-2019 Cosmin Truta
33 * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
34 * Copyright (c) 1996-1997 Andreas Dilger
35 * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
36 *
37 * This code is released under the libpng license.
38 * For conditions of distribution and use, see the disclaimer
39 * and license in png.h
40 *
41 * This file contains functions optionally called by an application
42 * in order to tell libpng how to handle data when reading a PNG.
43 * Transformations that are used in both reading and writing are
44 * in pngtrans.c.
45 */
46
47 #include "pngpriv.h"
48
49 #ifdef PNG_ARM_NEON_IMPLEMENTATION
50 # if PNG_ARM_NEON_IMPLEMENTATION == 1
51 # define PNG_ARM_NEON_INTRINSICS_AVAILABLE
52 # if defined(_MSC_VER) && defined(_M_ARM64)
53 # include <arm64_neon.h>
54 # else
55 # include <arm_neon.h>
56 # endif
57 # endif
58 #endif
59
60 #ifdef PNG_READ_SUPPORTED
61
62 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
63 void PNGAPI
64 png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
65 {
66 png_debug(1, "in png_set_crc_action");
67
68 if (png_ptr == NULL)
69 return;
70
71 /* Tell libpng how we react to CRC errors in critical chunks */
72 switch (crit_action)
73 {
74 case PNG_CRC_NO_CHANGE: /* Leave setting as is */
75 break;
76
77 case PNG_CRC_WARN_USE: /* Warn/use data */
78 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
79 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
1202 (png_ptr->transformations & PNG_EXPAND) != 0)
1203 {
1204 {
1205 png_ptr->background.red =
1206 png_ptr->palette[png_ptr->background.index].red;
1207 png_ptr->background.green =
1208 png_ptr->palette[png_ptr->background.index].green;
1209 png_ptr->background.blue =
1210 png_ptr->palette[png_ptr->background.index].blue;
1211
1212 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
1213 if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
1214 {
1215 if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1216 {
1217 /* Invert the alpha channel (in tRNS) unless the pixels are
1218 * going to be expanded, in which case leave it for later
1219 */
1220 int i, istop = png_ptr->num_trans;
1221
1222 for (i = 0; i < istop; i++)
1223 png_ptr->trans_alpha[i] =
1224 (png_byte)(255 - png_ptr->trans_alpha[i]);
1225 }
1226 }
1227 #endif /* READ_INVERT_ALPHA */
1228 }
1229 } /* background expand and (therefore) no alpha association. */
1230 #endif /* READ_EXPAND && READ_BACKGROUND */
1231 }
1232
1233 static void /* PRIVATE */
1234 png_init_rgb_transformations(png_structrp png_ptr)
1235 {
1236 /* Added to libpng-1.5.4: check the color type to determine whether there
1237 * is any alpha or transparency in the image and simply cancel the
1238 * background and alpha mode stuff if there isn't.
1239 */
1240 int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;
1241 int input_has_transparency = png_ptr->num_trans > 0;
1242
1243 /* If no alpha we can optimize. */
1244 if (input_has_alpha == 0)
3008 * libpng uses, instead, the closest non-overflowing approximation:
3009 *
3010 * Y = (6968 * R + 23434 * G + 2366 * B)/32768
3011 *
3012 * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk
3013 * (including an sRGB chunk) then the chromaticities are used to calculate the
3014 * coefficients. See the chunk handling in pngrutil.c for more information.
3015 *
3016 * In all cases the calculation is to be done in a linear colorspace. If no
3017 * gamma information is available to correct the encoding of the original RGB
3018 * values this results in an implicit assumption that the original PNG RGB
3019 * values were linear.
3020 *
3021 * Other integer coefficients can be used via png_set_rgb_to_gray(). Because
3022 * the API takes just red and green coefficients the blue coefficient is
3023 * calculated to make the sum 32768. This will result in different rounding
3024 * to that used above.
3025 */
3026 static int
3027 png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
3028 {
3029 int rgb_error = 0;
3030
3031 png_debug(1, "in png_do_rgb_to_gray");
3032
3033 if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
3034 (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
3035 {
3036 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
3037 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
3038 png_uint_32 bc = 32768 - rc - gc;
3039 png_uint_32 row_width = row_info->width;
3040 int have_alpha = (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
3041
3042 if (row_info->bit_depth == 8)
3043 {
3044 #ifdef PNG_READ_GAMMA_SUPPORTED
3045 /* Notice that gamma to/from 1 are not necessarily inverses (if
3046 * there is an overall gamma correction). Prior to 1.5.5 this code
3047 * checked the linearized values for equality; this doesn't match
3048 * the documentation, the original values must be checked.
3049 */
3050 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
3051 {
3052 png_bytep sp = row;
3053 png_bytep dp = row;
3054 png_uint_32 i;
3055
3056 for (i = 0; i < row_width; i++)
3057 {
3058 png_byte red = *(sp++);
3059 png_byte green = *(sp++);
3060 png_byte blue = *(sp++);
4163 }
4164 }
4165 #endif
4166
4167 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4168 /* Encode the alpha channel to the output gamma (the input channel is always
4169 * linear.) Called only with color types that have an alpha channel. Needs the
4170 * from_1 tables.
4171 */
4172 static void
4173 png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
4174 {
4175 png_uint_32 row_width = row_info->width;
4176
4177 png_debug(1, "in png_do_encode_alpha");
4178
4179 if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4180 {
4181 if (row_info->bit_depth == 8)
4182 {
4183 png_bytep table = png_ptr->gamma_from_1;
4184
4185 if (table != NULL)
4186 {
4187 int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
4188
4189 /* The alpha channel is the last component: */
4190 row += step - 1;
4191
4192 for (; row_width > 0; --row_width, row += step)
4193 *row = table[*row];
4194
4195 return;
4196 }
4197 }
4198
4199 else if (row_info->bit_depth == 16)
4200 {
4201 png_uint_16pp table = png_ptr->gamma_16_from_1;
4202 int gamma_shift = png_ptr->gamma_shift;
4203
4204 if (table != NULL)
4205 {
4206 int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
4207
4208 /* The alpha channel is the last component: */
4209 row += step - 2;
4210
4211 for (; row_width > 0; --row_width, row += step)
4212 {
4213 png_uint_16 v;
4214
4215 v = table[*(row + 1) >> gamma_shift][*row];
4216 *row = (png_byte)((v >> 8) & 0xff);
4217 *(row + 1) = (png_byte)(v & 0xff);
4218 }
4219
4220 return;
4221 }
4222 }
4223 }
4224
4225 /* Only get to here if called with a weird row_info; no harm has been done,
4226 * so just issue a warning.
4227 */
4228 png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
4229 }
4230 #endif
4231
4232 #ifdef PNG_READ_EXPAND_SUPPORTED
4233 /* Expands a palette row to an RGB or RGBA row depending
4234 * upon whether you supply trans and num_trans.
4235 */
4236 static void
4237 png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info,
4238 png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha,
4239 int num_trans)
4240 {
4241 int shift, value;
4242 png_bytep sp, dp;
4243 png_uint_32 i;
4244 png_uint_32 row_width=row_info->width;
4245
4246 png_debug(1, "in png_do_expand_palette");
4247
4248 if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4249 {
4250 if (row_info->bit_depth < 8)
4251 {
4252 switch (row_info->bit_depth)
4253 {
4254 case 1:
4255 {
4256 sp = row + (size_t)((row_width - 1) >> 3);
4257 dp = row + (size_t)row_width - 1;
4258 shift = 7 - (int)((row_width + 7) & 0x07);
4259 for (i = 0; i < row_width; i++)
4323 }
4324 break;
4325 }
4326
4327 default:
4328 break;
4329 }
4330 row_info->bit_depth = 8;
4331 row_info->pixel_depth = 8;
4332 row_info->rowbytes = row_width;
4333 }
4334
4335 if (row_info->bit_depth == 8)
4336 {
4337 {
4338 if (num_trans > 0)
4339 {
4340 sp = row + (size_t)row_width - 1;
4341 dp = row + ((size_t)row_width << 2) - 1;
4342
4343 i = 0;
4344 #ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
4345 if (png_ptr->riffled_palette != NULL)
4346 {
4347 /* The RGBA optimization works with png_ptr->bit_depth == 8
4348 * but sometimes row_info->bit_depth has been changed to 8.
4349 * In these cases, the palette hasn't been riffled.
4350 */
4351 i = png_do_expand_palette_rgba8_neon(png_ptr, row_info, row,
4352 &sp, &dp);
4353 }
4354 #else
4355 PNG_UNUSED(png_ptr)
4356 #endif
4357
4358 for (; i < row_width; i++)
4359 {
4360 if ((int)(*sp) >= num_trans)
4361 *dp-- = 0xff;
4362 else
4363 *dp-- = trans_alpha[*sp];
4364 *dp-- = palette[*sp].blue;
4365 *dp-- = palette[*sp].green;
4366 *dp-- = palette[*sp].red;
4367 sp--;
4368 }
4369 row_info->bit_depth = 8;
4370 row_info->pixel_depth = 32;
4371 row_info->rowbytes = row_width * 4;
4372 row_info->color_type = 6;
4373 row_info->channels = 4;
4374 }
4375
4376 else
4377 {
4378 sp = row + (size_t)row_width - 1;
4379 dp = row + (size_t)(row_width * 3) - 1;
4380 i = 0;
4381 #ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
4382 i = png_do_expand_palette_rgb8_neon(png_ptr, row_info, row,
4383 &sp, &dp);
4384 #else
4385 PNG_UNUSED(png_ptr)
4386 #endif
4387
4388 for (; i < row_width; i++)
4389 {
4390 *dp-- = palette[*sp].blue;
4391 *dp-- = palette[*sp].green;
4392 *dp-- = palette[*sp].red;
4393 sp--;
4394 }
4395
4396 row_info->bit_depth = 8;
4397 row_info->pixel_depth = 24;
4398 row_info->rowbytes = row_width * 3;
4399 row_info->color_type = 2;
4400 row_info->channels = 3;
4401 }
4402 }
4403 }
4404 }
4405 }
4406
4407 /* If the bit depth < 8, it is expanded to 8. Also, if the already
4408 * expanded transparency value is supplied, an alpha channel is built.
4782 * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
4783 * PNG_WARN_UNINITIALIZED_ROW removed. In 1.6 the new flag is set only for
4784 * all transformations, however in practice the ROW_INIT always gets done on
4785 * demand, if necessary.
4786 */
4787 if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
4788 (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
4789 {
4790 /* Application has failed to call either png_read_start_image() or
4791 * png_read_update_info() after setting transforms that expand pixels.
4792 * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
4793 */
4794 png_error(png_ptr, "Uninitialized row");
4795 }
4796
4797 #ifdef PNG_READ_EXPAND_SUPPORTED
4798 if ((png_ptr->transformations & PNG_EXPAND) != 0)
4799 {
4800 if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4801 {
4802 #ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
4803 if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8))
4804 {
4805 if (png_ptr->riffled_palette == NULL)
4806 {
4807 /* Initialize the accelerated palette expansion. */
4808 png_ptr->riffled_palette =
4809 (png_bytep)png_malloc(png_ptr, 256 * 4);
4810 png_riffle_palette_neon(png_ptr);
4811 }
4812 }
4813 #endif
4814 png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1,
4815 png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
4816 }
4817
4818 else
4819 {
4820 if (png_ptr->num_trans != 0 &&
4821 (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
4822 png_do_expand(row_info, png_ptr->row_buf + 1,
4823 &(png_ptr->trans_color));
4824
4825 else
4826 png_do_expand(row_info, png_ptr->row_buf + 1, NULL);
4827 }
4828 }
4829 #endif
4830
4831 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4832 if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
4833 (png_ptr->transformations & PNG_COMPOSE) == 0 &&
4834 (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
|