1*a67afe4dSAndroid Build Coastguard Worker
2*a67afe4dSAndroid Build Coastguard Worker /* pngrtran.c - transforms the data in a row for PNG readers
3*a67afe4dSAndroid Build Coastguard Worker *
4*a67afe4dSAndroid Build Coastguard Worker * Copyright (c) 2018-2024 Cosmin Truta
5*a67afe4dSAndroid Build Coastguard Worker * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
6*a67afe4dSAndroid Build Coastguard Worker * Copyright (c) 1996-1997 Andreas Dilger
7*a67afe4dSAndroid Build Coastguard Worker * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
8*a67afe4dSAndroid Build Coastguard Worker *
9*a67afe4dSAndroid Build Coastguard Worker * This code is released under the libpng license.
10*a67afe4dSAndroid Build Coastguard Worker * For conditions of distribution and use, see the disclaimer
11*a67afe4dSAndroid Build Coastguard Worker * and license in png.h
12*a67afe4dSAndroid Build Coastguard Worker *
13*a67afe4dSAndroid Build Coastguard Worker * This file contains functions optionally called by an application
14*a67afe4dSAndroid Build Coastguard Worker * in order to tell libpng how to handle data when reading a PNG.
15*a67afe4dSAndroid Build Coastguard Worker * Transformations that are used in both reading and writing are
16*a67afe4dSAndroid Build Coastguard Worker * in pngtrans.c.
17*a67afe4dSAndroid Build Coastguard Worker */
18*a67afe4dSAndroid Build Coastguard Worker
19*a67afe4dSAndroid Build Coastguard Worker #include "pngpriv.h"
20*a67afe4dSAndroid Build Coastguard Worker
21*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_ARM_NEON_IMPLEMENTATION
22*a67afe4dSAndroid Build Coastguard Worker # if PNG_ARM_NEON_IMPLEMENTATION == 1
23*a67afe4dSAndroid Build Coastguard Worker # define PNG_ARM_NEON_INTRINSICS_AVAILABLE
24*a67afe4dSAndroid Build Coastguard Worker # if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64)
25*a67afe4dSAndroid Build Coastguard Worker # include <arm64_neon.h>
26*a67afe4dSAndroid Build Coastguard Worker # else
27*a67afe4dSAndroid Build Coastguard Worker # include <arm_neon.h>
28*a67afe4dSAndroid Build Coastguard Worker # endif
29*a67afe4dSAndroid Build Coastguard Worker # endif
30*a67afe4dSAndroid Build Coastguard Worker #endif
31*a67afe4dSAndroid Build Coastguard Worker
32*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_SUPPORTED
33*a67afe4dSAndroid Build Coastguard Worker
34*a67afe4dSAndroid Build Coastguard Worker /* Set the action on getting a CRC error for an ancillary or critical chunk. */
35*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_crc_action(png_structrp png_ptr,int crit_action,int ancil_action)36*a67afe4dSAndroid Build Coastguard Worker png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
37*a67afe4dSAndroid Build Coastguard Worker {
38*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_crc_action");
39*a67afe4dSAndroid Build Coastguard Worker
40*a67afe4dSAndroid Build Coastguard Worker if (png_ptr == NULL)
41*a67afe4dSAndroid Build Coastguard Worker return;
42*a67afe4dSAndroid Build Coastguard Worker
43*a67afe4dSAndroid Build Coastguard Worker /* Tell libpng how we react to CRC errors in critical chunks */
44*a67afe4dSAndroid Build Coastguard Worker switch (crit_action)
45*a67afe4dSAndroid Build Coastguard Worker {
46*a67afe4dSAndroid Build Coastguard Worker case PNG_CRC_NO_CHANGE: /* Leave setting as is */
47*a67afe4dSAndroid Build Coastguard Worker break;
48*a67afe4dSAndroid Build Coastguard Worker
49*a67afe4dSAndroid Build Coastguard Worker case PNG_CRC_WARN_USE: /* Warn/use data */
50*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
51*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
52*a67afe4dSAndroid Build Coastguard Worker break;
53*a67afe4dSAndroid Build Coastguard Worker
54*a67afe4dSAndroid Build Coastguard Worker case PNG_CRC_QUIET_USE: /* Quiet/use data */
55*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
56*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
57*a67afe4dSAndroid Build Coastguard Worker PNG_FLAG_CRC_CRITICAL_IGNORE;
58*a67afe4dSAndroid Build Coastguard Worker break;
59*a67afe4dSAndroid Build Coastguard Worker
60*a67afe4dSAndroid Build Coastguard Worker case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */
61*a67afe4dSAndroid Build Coastguard Worker png_warning(png_ptr,
62*a67afe4dSAndroid Build Coastguard Worker "Can't discard critical data on CRC error");
63*a67afe4dSAndroid Build Coastguard Worker /* FALLTHROUGH */
64*a67afe4dSAndroid Build Coastguard Worker case PNG_CRC_ERROR_QUIT: /* Error/quit */
65*a67afe4dSAndroid Build Coastguard Worker
66*a67afe4dSAndroid Build Coastguard Worker case PNG_CRC_DEFAULT:
67*a67afe4dSAndroid Build Coastguard Worker default:
68*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
69*a67afe4dSAndroid Build Coastguard Worker break;
70*a67afe4dSAndroid Build Coastguard Worker }
71*a67afe4dSAndroid Build Coastguard Worker
72*a67afe4dSAndroid Build Coastguard Worker /* Tell libpng how we react to CRC errors in ancillary chunks */
73*a67afe4dSAndroid Build Coastguard Worker switch (ancil_action)
74*a67afe4dSAndroid Build Coastguard Worker {
75*a67afe4dSAndroid Build Coastguard Worker case PNG_CRC_NO_CHANGE: /* Leave setting as is */
76*a67afe4dSAndroid Build Coastguard Worker break;
77*a67afe4dSAndroid Build Coastguard Worker
78*a67afe4dSAndroid Build Coastguard Worker case PNG_CRC_WARN_USE: /* Warn/use data */
79*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
80*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
81*a67afe4dSAndroid Build Coastguard Worker break;
82*a67afe4dSAndroid Build Coastguard Worker
83*a67afe4dSAndroid Build Coastguard Worker case PNG_CRC_QUIET_USE: /* Quiet/use data */
84*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
85*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
86*a67afe4dSAndroid Build Coastguard Worker PNG_FLAG_CRC_ANCILLARY_NOWARN;
87*a67afe4dSAndroid Build Coastguard Worker break;
88*a67afe4dSAndroid Build Coastguard Worker
89*a67afe4dSAndroid Build Coastguard Worker case PNG_CRC_ERROR_QUIT: /* Error/quit */
90*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
91*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
92*a67afe4dSAndroid Build Coastguard Worker break;
93*a67afe4dSAndroid Build Coastguard Worker
94*a67afe4dSAndroid Build Coastguard Worker case PNG_CRC_WARN_DISCARD: /* Warn/discard data */
95*a67afe4dSAndroid Build Coastguard Worker
96*a67afe4dSAndroid Build Coastguard Worker case PNG_CRC_DEFAULT:
97*a67afe4dSAndroid Build Coastguard Worker default:
98*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
99*a67afe4dSAndroid Build Coastguard Worker break;
100*a67afe4dSAndroid Build Coastguard Worker }
101*a67afe4dSAndroid Build Coastguard Worker }
102*a67afe4dSAndroid Build Coastguard Worker
103*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_TRANSFORMS_SUPPORTED
104*a67afe4dSAndroid Build Coastguard Worker /* Is it OK to set a transformation now? Only if png_start_read_image or
105*a67afe4dSAndroid Build Coastguard Worker * png_read_update_info have not been called. It is not necessary for the IHDR
106*a67afe4dSAndroid Build Coastguard Worker * to have been read in all cases; the need_IHDR parameter allows for this
107*a67afe4dSAndroid Build Coastguard Worker * check too.
108*a67afe4dSAndroid Build Coastguard Worker */
109*a67afe4dSAndroid Build Coastguard Worker static int
png_rtran_ok(png_structrp png_ptr,int need_IHDR)110*a67afe4dSAndroid Build Coastguard Worker png_rtran_ok(png_structrp png_ptr, int need_IHDR)
111*a67afe4dSAndroid Build Coastguard Worker {
112*a67afe4dSAndroid Build Coastguard Worker if (png_ptr != NULL)
113*a67afe4dSAndroid Build Coastguard Worker {
114*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
115*a67afe4dSAndroid Build Coastguard Worker png_app_error(png_ptr,
116*a67afe4dSAndroid Build Coastguard Worker "invalid after png_start_read_image or png_read_update_info");
117*a67afe4dSAndroid Build Coastguard Worker
118*a67afe4dSAndroid Build Coastguard Worker else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)
119*a67afe4dSAndroid Build Coastguard Worker png_app_error(png_ptr, "invalid before the PNG header has been read");
120*a67afe4dSAndroid Build Coastguard Worker
121*a67afe4dSAndroid Build Coastguard Worker else
122*a67afe4dSAndroid Build Coastguard Worker {
123*a67afe4dSAndroid Build Coastguard Worker /* Turn on failure to initialize correctly for all transforms. */
124*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
125*a67afe4dSAndroid Build Coastguard Worker
126*a67afe4dSAndroid Build Coastguard Worker return 1; /* Ok */
127*a67afe4dSAndroid Build Coastguard Worker }
128*a67afe4dSAndroid Build Coastguard Worker }
129*a67afe4dSAndroid Build Coastguard Worker
130*a67afe4dSAndroid Build Coastguard Worker return 0; /* no png_error possible! */
131*a67afe4dSAndroid Build Coastguard Worker }
132*a67afe4dSAndroid Build Coastguard Worker #endif
133*a67afe4dSAndroid Build Coastguard Worker
134*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_BACKGROUND_SUPPORTED
135*a67afe4dSAndroid Build Coastguard Worker /* Handle alpha and tRNS via a background color */
136*a67afe4dSAndroid Build Coastguard Worker void PNGFAPI
png_set_background_fixed(png_structrp png_ptr,png_const_color_16p background_color,int background_gamma_code,int need_expand,png_fixed_point background_gamma)137*a67afe4dSAndroid Build Coastguard Worker png_set_background_fixed(png_structrp png_ptr,
138*a67afe4dSAndroid Build Coastguard Worker png_const_color_16p background_color, int background_gamma_code,
139*a67afe4dSAndroid Build Coastguard Worker int need_expand, png_fixed_point background_gamma)
140*a67afe4dSAndroid Build Coastguard Worker {
141*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_background_fixed");
142*a67afe4dSAndroid Build Coastguard Worker
143*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0 || background_color == NULL)
144*a67afe4dSAndroid Build Coastguard Worker return;
145*a67afe4dSAndroid Build Coastguard Worker
146*a67afe4dSAndroid Build Coastguard Worker if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
147*a67afe4dSAndroid Build Coastguard Worker {
148*a67afe4dSAndroid Build Coastguard Worker png_warning(png_ptr, "Application must supply a known background gamma");
149*a67afe4dSAndroid Build Coastguard Worker return;
150*a67afe4dSAndroid Build Coastguard Worker }
151*a67afe4dSAndroid Build Coastguard Worker
152*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;
153*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
154*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
155*a67afe4dSAndroid Build Coastguard Worker
156*a67afe4dSAndroid Build Coastguard Worker png_ptr->background = *background_color;
157*a67afe4dSAndroid Build Coastguard Worker png_ptr->background_gamma = background_gamma;
158*a67afe4dSAndroid Build Coastguard Worker png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
159*a67afe4dSAndroid Build Coastguard Worker if (need_expand != 0)
160*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
161*a67afe4dSAndroid Build Coastguard Worker else
162*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
163*a67afe4dSAndroid Build Coastguard Worker }
164*a67afe4dSAndroid Build Coastguard Worker
165*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_FLOATING_POINT_SUPPORTED
166*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_background(png_structrp png_ptr,png_const_color_16p background_color,int background_gamma_code,int need_expand,double background_gamma)167*a67afe4dSAndroid Build Coastguard Worker png_set_background(png_structrp png_ptr,
168*a67afe4dSAndroid Build Coastguard Worker png_const_color_16p background_color, int background_gamma_code,
169*a67afe4dSAndroid Build Coastguard Worker int need_expand, double background_gamma)
170*a67afe4dSAndroid Build Coastguard Worker {
171*a67afe4dSAndroid Build Coastguard Worker png_set_background_fixed(png_ptr, background_color, background_gamma_code,
172*a67afe4dSAndroid Build Coastguard Worker need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
173*a67afe4dSAndroid Build Coastguard Worker }
174*a67afe4dSAndroid Build Coastguard Worker # endif /* FLOATING_POINT */
175*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_BACKGROUND */
176*a67afe4dSAndroid Build Coastguard Worker
177*a67afe4dSAndroid Build Coastguard Worker /* Scale 16-bit depth files to 8-bit depth. If both of these are set then the
178*a67afe4dSAndroid Build Coastguard Worker * one that pngrtran does first (scale) happens. This is necessary to allow the
179*a67afe4dSAndroid Build Coastguard Worker * TRANSFORM and API behavior to be somewhat consistent, and it's simpler.
180*a67afe4dSAndroid Build Coastguard Worker */
181*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
182*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_scale_16(png_structrp png_ptr)183*a67afe4dSAndroid Build Coastguard Worker png_set_scale_16(png_structrp png_ptr)
184*a67afe4dSAndroid Build Coastguard Worker {
185*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_scale_16");
186*a67afe4dSAndroid Build Coastguard Worker
187*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0)
188*a67afe4dSAndroid Build Coastguard Worker return;
189*a67afe4dSAndroid Build Coastguard Worker
190*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_SCALE_16_TO_8;
191*a67afe4dSAndroid Build Coastguard Worker }
192*a67afe4dSAndroid Build Coastguard Worker #endif
193*a67afe4dSAndroid Build Coastguard Worker
194*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
195*a67afe4dSAndroid Build Coastguard Worker /* Chop 16-bit depth files to 8-bit depth */
196*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_strip_16(png_structrp png_ptr)197*a67afe4dSAndroid Build Coastguard Worker png_set_strip_16(png_structrp png_ptr)
198*a67afe4dSAndroid Build Coastguard Worker {
199*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_strip_16");
200*a67afe4dSAndroid Build Coastguard Worker
201*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0)
202*a67afe4dSAndroid Build Coastguard Worker return;
203*a67afe4dSAndroid Build Coastguard Worker
204*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_16_TO_8;
205*a67afe4dSAndroid Build Coastguard Worker }
206*a67afe4dSAndroid Build Coastguard Worker #endif
207*a67afe4dSAndroid Build Coastguard Worker
208*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
209*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_strip_alpha(png_structrp png_ptr)210*a67afe4dSAndroid Build Coastguard Worker png_set_strip_alpha(png_structrp png_ptr)
211*a67afe4dSAndroid Build Coastguard Worker {
212*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_strip_alpha");
213*a67afe4dSAndroid Build Coastguard Worker
214*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0)
215*a67afe4dSAndroid Build Coastguard Worker return;
216*a67afe4dSAndroid Build Coastguard Worker
217*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_STRIP_ALPHA;
218*a67afe4dSAndroid Build Coastguard Worker }
219*a67afe4dSAndroid Build Coastguard Worker #endif
220*a67afe4dSAndroid Build Coastguard Worker
221*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
222*a67afe4dSAndroid Build Coastguard Worker static png_fixed_point
translate_gamma_flags(png_structrp png_ptr,png_fixed_point output_gamma,int is_screen)223*a67afe4dSAndroid Build Coastguard Worker translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
224*a67afe4dSAndroid Build Coastguard Worker int is_screen)
225*a67afe4dSAndroid Build Coastguard Worker {
226*a67afe4dSAndroid Build Coastguard Worker /* Check for flag values. The main reason for having the old Mac value as a
227*a67afe4dSAndroid Build Coastguard Worker * flag is that it is pretty near impossible to work out what the correct
228*a67afe4dSAndroid Build Coastguard Worker * value is from Apple documentation - a working Mac system is needed to
229*a67afe4dSAndroid Build Coastguard Worker * discover the value!
230*a67afe4dSAndroid Build Coastguard Worker */
231*a67afe4dSAndroid Build Coastguard Worker if (output_gamma == PNG_DEFAULT_sRGB ||
232*a67afe4dSAndroid Build Coastguard Worker output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)
233*a67afe4dSAndroid Build Coastguard Worker {
234*a67afe4dSAndroid Build Coastguard Worker /* If there is no sRGB support this just sets the gamma to the standard
235*a67afe4dSAndroid Build Coastguard Worker * sRGB value. (This is a side effect of using this function!)
236*a67afe4dSAndroid Build Coastguard Worker */
237*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_READ_sRGB_SUPPORTED
238*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
239*a67afe4dSAndroid Build Coastguard Worker # else
240*a67afe4dSAndroid Build Coastguard Worker PNG_UNUSED(png_ptr)
241*a67afe4dSAndroid Build Coastguard Worker # endif
242*a67afe4dSAndroid Build Coastguard Worker if (is_screen != 0)
243*a67afe4dSAndroid Build Coastguard Worker output_gamma = PNG_GAMMA_sRGB;
244*a67afe4dSAndroid Build Coastguard Worker else
245*a67afe4dSAndroid Build Coastguard Worker output_gamma = PNG_GAMMA_sRGB_INVERSE;
246*a67afe4dSAndroid Build Coastguard Worker }
247*a67afe4dSAndroid Build Coastguard Worker
248*a67afe4dSAndroid Build Coastguard Worker else if (output_gamma == PNG_GAMMA_MAC_18 ||
249*a67afe4dSAndroid Build Coastguard Worker output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
250*a67afe4dSAndroid Build Coastguard Worker {
251*a67afe4dSAndroid Build Coastguard Worker if (is_screen != 0)
252*a67afe4dSAndroid Build Coastguard Worker output_gamma = PNG_GAMMA_MAC_OLD;
253*a67afe4dSAndroid Build Coastguard Worker else
254*a67afe4dSAndroid Build Coastguard Worker output_gamma = PNG_GAMMA_MAC_INVERSE;
255*a67afe4dSAndroid Build Coastguard Worker }
256*a67afe4dSAndroid Build Coastguard Worker
257*a67afe4dSAndroid Build Coastguard Worker return output_gamma;
258*a67afe4dSAndroid Build Coastguard Worker }
259*a67afe4dSAndroid Build Coastguard Worker
260*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_FLOATING_POINT_SUPPORTED
261*a67afe4dSAndroid Build Coastguard Worker static png_fixed_point
convert_gamma_value(png_structrp png_ptr,double output_gamma)262*a67afe4dSAndroid Build Coastguard Worker convert_gamma_value(png_structrp png_ptr, double output_gamma)
263*a67afe4dSAndroid Build Coastguard Worker {
264*a67afe4dSAndroid Build Coastguard Worker /* The following silently ignores cases where fixed point (times 100,000)
265*a67afe4dSAndroid Build Coastguard Worker * gamma values are passed to the floating point API. This is safe and it
266*a67afe4dSAndroid Build Coastguard Worker * means the fixed point constants work just fine with the floating point
267*a67afe4dSAndroid Build Coastguard Worker * API. The alternative would just lead to undetected errors and spurious
268*a67afe4dSAndroid Build Coastguard Worker * bug reports. Negative values fail inside the _fixed API unless they
269*a67afe4dSAndroid Build Coastguard Worker * correspond to the flag values.
270*a67afe4dSAndroid Build Coastguard Worker */
271*a67afe4dSAndroid Build Coastguard Worker if (output_gamma > 0 && output_gamma < 128)
272*a67afe4dSAndroid Build Coastguard Worker output_gamma *= PNG_FP_1;
273*a67afe4dSAndroid Build Coastguard Worker
274*a67afe4dSAndroid Build Coastguard Worker /* This preserves -1 and -2 exactly: */
275*a67afe4dSAndroid Build Coastguard Worker output_gamma = floor(output_gamma + .5);
276*a67afe4dSAndroid Build Coastguard Worker
277*a67afe4dSAndroid Build Coastguard Worker if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN)
278*a67afe4dSAndroid Build Coastguard Worker png_fixed_error(png_ptr, "gamma value");
279*a67afe4dSAndroid Build Coastguard Worker
280*a67afe4dSAndroid Build Coastguard Worker return (png_fixed_point)output_gamma;
281*a67afe4dSAndroid Build Coastguard Worker }
282*a67afe4dSAndroid Build Coastguard Worker # endif
283*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_ALPHA_MODE || READ_GAMMA */
284*a67afe4dSAndroid Build Coastguard Worker
285*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
286*a67afe4dSAndroid Build Coastguard Worker void PNGFAPI
png_set_alpha_mode_fixed(png_structrp png_ptr,int mode,png_fixed_point output_gamma)287*a67afe4dSAndroid Build Coastguard Worker png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
288*a67afe4dSAndroid Build Coastguard Worker png_fixed_point output_gamma)
289*a67afe4dSAndroid Build Coastguard Worker {
290*a67afe4dSAndroid Build Coastguard Worker int compose = 0;
291*a67afe4dSAndroid Build Coastguard Worker png_fixed_point file_gamma;
292*a67afe4dSAndroid Build Coastguard Worker
293*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_alpha_mode_fixed");
294*a67afe4dSAndroid Build Coastguard Worker
295*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0)
296*a67afe4dSAndroid Build Coastguard Worker return;
297*a67afe4dSAndroid Build Coastguard Worker
298*a67afe4dSAndroid Build Coastguard Worker output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
299*a67afe4dSAndroid Build Coastguard Worker
300*a67afe4dSAndroid Build Coastguard Worker /* Validate the value to ensure it is in a reasonable range. The value
301*a67afe4dSAndroid Build Coastguard Worker * is expected to be 1 or greater, but this range test allows for some
302*a67afe4dSAndroid Build Coastguard Worker * viewing correction values. The intent is to weed out the API users
303*a67afe4dSAndroid Build Coastguard Worker * who might use the inverse of the gamma value accidentally!
304*a67afe4dSAndroid Build Coastguard Worker *
305*a67afe4dSAndroid Build Coastguard Worker * In libpng 1.6.0, we changed from 0.07..3 to 0.01..100, to accommodate
306*a67afe4dSAndroid Build Coastguard Worker * the optimal 16-bit gamma of 36 and its reciprocal.
307*a67afe4dSAndroid Build Coastguard Worker */
308*a67afe4dSAndroid Build Coastguard Worker if (output_gamma < 1000 || output_gamma > 10000000)
309*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "output gamma out of expected range");
310*a67afe4dSAndroid Build Coastguard Worker
311*a67afe4dSAndroid Build Coastguard Worker /* The default file gamma is the inverse of the output gamma; the output
312*a67afe4dSAndroid Build Coastguard Worker * gamma may be changed below so get the file value first:
313*a67afe4dSAndroid Build Coastguard Worker */
314*a67afe4dSAndroid Build Coastguard Worker file_gamma = png_reciprocal(output_gamma);
315*a67afe4dSAndroid Build Coastguard Worker
316*a67afe4dSAndroid Build Coastguard Worker /* There are really 8 possibilities here, composed of any combination
317*a67afe4dSAndroid Build Coastguard Worker * of:
318*a67afe4dSAndroid Build Coastguard Worker *
319*a67afe4dSAndroid Build Coastguard Worker * premultiply the color channels
320*a67afe4dSAndroid Build Coastguard Worker * do not encode non-opaque pixels
321*a67afe4dSAndroid Build Coastguard Worker * encode the alpha as well as the color channels
322*a67afe4dSAndroid Build Coastguard Worker *
323*a67afe4dSAndroid Build Coastguard Worker * The differences disappear if the input/output ('screen') gamma is 1.0,
324*a67afe4dSAndroid Build Coastguard Worker * because then the encoding is a no-op and there is only the choice of
325*a67afe4dSAndroid Build Coastguard Worker * premultiplying the color channels or not.
326*a67afe4dSAndroid Build Coastguard Worker *
327*a67afe4dSAndroid Build Coastguard Worker * png_set_alpha_mode and png_set_background interact because both use
328*a67afe4dSAndroid Build Coastguard Worker * png_compose to do the work. Calling both is only useful when
329*a67afe4dSAndroid Build Coastguard Worker * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along
330*a67afe4dSAndroid Build Coastguard Worker * with a default gamma value. Otherwise PNG_COMPOSE must not be set.
331*a67afe4dSAndroid Build Coastguard Worker */
332*a67afe4dSAndroid Build Coastguard Worker switch (mode)
333*a67afe4dSAndroid Build Coastguard Worker {
334*a67afe4dSAndroid Build Coastguard Worker case PNG_ALPHA_PNG: /* default: png standard */
335*a67afe4dSAndroid Build Coastguard Worker /* No compose, but it may be set by png_set_background! */
336*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
337*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
338*a67afe4dSAndroid Build Coastguard Worker break;
339*a67afe4dSAndroid Build Coastguard Worker
340*a67afe4dSAndroid Build Coastguard Worker case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */
341*a67afe4dSAndroid Build Coastguard Worker compose = 1;
342*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
343*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
344*a67afe4dSAndroid Build Coastguard Worker /* The output is linear: */
345*a67afe4dSAndroid Build Coastguard Worker output_gamma = PNG_FP_1;
346*a67afe4dSAndroid Build Coastguard Worker break;
347*a67afe4dSAndroid Build Coastguard Worker
348*a67afe4dSAndroid Build Coastguard Worker case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */
349*a67afe4dSAndroid Build Coastguard Worker compose = 1;
350*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
351*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA;
352*a67afe4dSAndroid Build Coastguard Worker /* output_gamma records the encoding of opaque pixels! */
353*a67afe4dSAndroid Build Coastguard Worker break;
354*a67afe4dSAndroid Build Coastguard Worker
355*a67afe4dSAndroid Build Coastguard Worker case PNG_ALPHA_BROKEN: /* associated, non-linear, alpha encoded */
356*a67afe4dSAndroid Build Coastguard Worker compose = 1;
357*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_ENCODE_ALPHA;
358*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
359*a67afe4dSAndroid Build Coastguard Worker break;
360*a67afe4dSAndroid Build Coastguard Worker
361*a67afe4dSAndroid Build Coastguard Worker default:
362*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "invalid alpha mode");
363*a67afe4dSAndroid Build Coastguard Worker }
364*a67afe4dSAndroid Build Coastguard Worker
365*a67afe4dSAndroid Build Coastguard Worker /* Only set the default gamma if the file gamma has not been set (this has
366*a67afe4dSAndroid Build Coastguard Worker * the side effect that the gamma in a second call to png_set_alpha_mode will
367*a67afe4dSAndroid Build Coastguard Worker * be ignored.)
368*a67afe4dSAndroid Build Coastguard Worker */
369*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->colorspace.gamma == 0)
370*a67afe4dSAndroid Build Coastguard Worker {
371*a67afe4dSAndroid Build Coastguard Worker png_ptr->colorspace.gamma = file_gamma;
372*a67afe4dSAndroid Build Coastguard Worker png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
373*a67afe4dSAndroid Build Coastguard Worker }
374*a67afe4dSAndroid Build Coastguard Worker
375*a67afe4dSAndroid Build Coastguard Worker /* But always set the output gamma: */
376*a67afe4dSAndroid Build Coastguard Worker png_ptr->screen_gamma = output_gamma;
377*a67afe4dSAndroid Build Coastguard Worker
378*a67afe4dSAndroid Build Coastguard Worker /* Finally, if pre-multiplying, set the background fields to achieve the
379*a67afe4dSAndroid Build Coastguard Worker * desired result.
380*a67afe4dSAndroid Build Coastguard Worker */
381*a67afe4dSAndroid Build Coastguard Worker if (compose != 0)
382*a67afe4dSAndroid Build Coastguard Worker {
383*a67afe4dSAndroid Build Coastguard Worker /* And obtain alpha pre-multiplication by composing on black: */
384*a67afe4dSAndroid Build Coastguard Worker memset(&png_ptr->background, 0, (sizeof png_ptr->background));
385*a67afe4dSAndroid Build Coastguard Worker png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
386*a67afe4dSAndroid Build Coastguard Worker png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
387*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
388*a67afe4dSAndroid Build Coastguard Worker
389*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_COMPOSE) != 0)
390*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr,
391*a67afe4dSAndroid Build Coastguard Worker "conflicting calls to set alpha mode and background");
392*a67afe4dSAndroid Build Coastguard Worker
393*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_COMPOSE;
394*a67afe4dSAndroid Build Coastguard Worker }
395*a67afe4dSAndroid Build Coastguard Worker }
396*a67afe4dSAndroid Build Coastguard Worker
397*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_FLOATING_POINT_SUPPORTED
398*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_alpha_mode(png_structrp png_ptr,int mode,double output_gamma)399*a67afe4dSAndroid Build Coastguard Worker png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)
400*a67afe4dSAndroid Build Coastguard Worker {
401*a67afe4dSAndroid Build Coastguard Worker png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
402*a67afe4dSAndroid Build Coastguard Worker output_gamma));
403*a67afe4dSAndroid Build Coastguard Worker }
404*a67afe4dSAndroid Build Coastguard Worker # endif
405*a67afe4dSAndroid Build Coastguard Worker #endif
406*a67afe4dSAndroid Build Coastguard Worker
407*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_QUANTIZE_SUPPORTED
408*a67afe4dSAndroid Build Coastguard Worker /* Dither file to 8-bit. Supply a palette, the current number
409*a67afe4dSAndroid Build Coastguard Worker * of elements in the palette, the maximum number of elements
410*a67afe4dSAndroid Build Coastguard Worker * allowed, and a histogram if possible. If the current number
411*a67afe4dSAndroid Build Coastguard Worker * of colors is greater than the maximum number, the palette will be
412*a67afe4dSAndroid Build Coastguard Worker * modified to fit in the maximum number. "full_quantize" indicates
413*a67afe4dSAndroid Build Coastguard Worker * whether we need a quantizing cube set up for RGB images, or if we
414*a67afe4dSAndroid Build Coastguard Worker * simply are reducing the number of colors in a paletted image.
415*a67afe4dSAndroid Build Coastguard Worker */
416*a67afe4dSAndroid Build Coastguard Worker
417*a67afe4dSAndroid Build Coastguard Worker typedef struct png_dsort_struct
418*a67afe4dSAndroid Build Coastguard Worker {
419*a67afe4dSAndroid Build Coastguard Worker struct png_dsort_struct * next;
420*a67afe4dSAndroid Build Coastguard Worker png_byte left;
421*a67afe4dSAndroid Build Coastguard Worker png_byte right;
422*a67afe4dSAndroid Build Coastguard Worker } png_dsort;
423*a67afe4dSAndroid Build Coastguard Worker typedef png_dsort * png_dsortp;
424*a67afe4dSAndroid Build Coastguard Worker typedef png_dsort * * png_dsortpp;
425*a67afe4dSAndroid Build Coastguard Worker
426*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_quantize(png_structrp png_ptr,png_colorp palette,int num_palette,int maximum_colors,png_const_uint_16p histogram,int full_quantize)427*a67afe4dSAndroid Build Coastguard Worker png_set_quantize(png_structrp png_ptr, png_colorp palette,
428*a67afe4dSAndroid Build Coastguard Worker int num_palette, int maximum_colors, png_const_uint_16p histogram,
429*a67afe4dSAndroid Build Coastguard Worker int full_quantize)
430*a67afe4dSAndroid Build Coastguard Worker {
431*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_quantize");
432*a67afe4dSAndroid Build Coastguard Worker
433*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0)
434*a67afe4dSAndroid Build Coastguard Worker return;
435*a67afe4dSAndroid Build Coastguard Worker
436*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_QUANTIZE;
437*a67afe4dSAndroid Build Coastguard Worker
438*a67afe4dSAndroid Build Coastguard Worker if (full_quantize == 0)
439*a67afe4dSAndroid Build Coastguard Worker {
440*a67afe4dSAndroid Build Coastguard Worker int i;
441*a67afe4dSAndroid Build Coastguard Worker
442*a67afe4dSAndroid Build Coastguard Worker png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
443*a67afe4dSAndroid Build Coastguard Worker (png_alloc_size_t)num_palette);
444*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < num_palette; i++)
445*a67afe4dSAndroid Build Coastguard Worker png_ptr->quantize_index[i] = (png_byte)i;
446*a67afe4dSAndroid Build Coastguard Worker }
447*a67afe4dSAndroid Build Coastguard Worker
448*a67afe4dSAndroid Build Coastguard Worker if (num_palette > maximum_colors)
449*a67afe4dSAndroid Build Coastguard Worker {
450*a67afe4dSAndroid Build Coastguard Worker if (histogram != NULL)
451*a67afe4dSAndroid Build Coastguard Worker {
452*a67afe4dSAndroid Build Coastguard Worker /* This is easy enough, just throw out the least used colors.
453*a67afe4dSAndroid Build Coastguard Worker * Perhaps not the best solution, but good enough.
454*a67afe4dSAndroid Build Coastguard Worker */
455*a67afe4dSAndroid Build Coastguard Worker
456*a67afe4dSAndroid Build Coastguard Worker int i;
457*a67afe4dSAndroid Build Coastguard Worker
458*a67afe4dSAndroid Build Coastguard Worker /* Initialize an array to sort colors */
459*a67afe4dSAndroid Build Coastguard Worker png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
460*a67afe4dSAndroid Build Coastguard Worker (png_alloc_size_t)num_palette);
461*a67afe4dSAndroid Build Coastguard Worker
462*a67afe4dSAndroid Build Coastguard Worker /* Initialize the quantize_sort array */
463*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < num_palette; i++)
464*a67afe4dSAndroid Build Coastguard Worker png_ptr->quantize_sort[i] = (png_byte)i;
465*a67afe4dSAndroid Build Coastguard Worker
466*a67afe4dSAndroid Build Coastguard Worker /* Find the least used palette entries by starting a
467*a67afe4dSAndroid Build Coastguard Worker * bubble sort, and running it until we have sorted
468*a67afe4dSAndroid Build Coastguard Worker * out enough colors. Note that we don't care about
469*a67afe4dSAndroid Build Coastguard Worker * sorting all the colors, just finding which are
470*a67afe4dSAndroid Build Coastguard Worker * least used.
471*a67afe4dSAndroid Build Coastguard Worker */
472*a67afe4dSAndroid Build Coastguard Worker
473*a67afe4dSAndroid Build Coastguard Worker for (i = num_palette - 1; i >= maximum_colors; i--)
474*a67afe4dSAndroid Build Coastguard Worker {
475*a67afe4dSAndroid Build Coastguard Worker int done; /* To stop early if the list is pre-sorted */
476*a67afe4dSAndroid Build Coastguard Worker int j;
477*a67afe4dSAndroid Build Coastguard Worker
478*a67afe4dSAndroid Build Coastguard Worker done = 1;
479*a67afe4dSAndroid Build Coastguard Worker for (j = 0; j < i; j++)
480*a67afe4dSAndroid Build Coastguard Worker {
481*a67afe4dSAndroid Build Coastguard Worker if (histogram[png_ptr->quantize_sort[j]]
482*a67afe4dSAndroid Build Coastguard Worker < histogram[png_ptr->quantize_sort[j + 1]])
483*a67afe4dSAndroid Build Coastguard Worker {
484*a67afe4dSAndroid Build Coastguard Worker png_byte t;
485*a67afe4dSAndroid Build Coastguard Worker
486*a67afe4dSAndroid Build Coastguard Worker t = png_ptr->quantize_sort[j];
487*a67afe4dSAndroid Build Coastguard Worker png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
488*a67afe4dSAndroid Build Coastguard Worker png_ptr->quantize_sort[j + 1] = t;
489*a67afe4dSAndroid Build Coastguard Worker done = 0;
490*a67afe4dSAndroid Build Coastguard Worker }
491*a67afe4dSAndroid Build Coastguard Worker }
492*a67afe4dSAndroid Build Coastguard Worker
493*a67afe4dSAndroid Build Coastguard Worker if (done != 0)
494*a67afe4dSAndroid Build Coastguard Worker break;
495*a67afe4dSAndroid Build Coastguard Worker }
496*a67afe4dSAndroid Build Coastguard Worker
497*a67afe4dSAndroid Build Coastguard Worker /* Swap the palette around, and set up a table, if necessary */
498*a67afe4dSAndroid Build Coastguard Worker if (full_quantize != 0)
499*a67afe4dSAndroid Build Coastguard Worker {
500*a67afe4dSAndroid Build Coastguard Worker int j = num_palette;
501*a67afe4dSAndroid Build Coastguard Worker
502*a67afe4dSAndroid Build Coastguard Worker /* Put all the useful colors within the max, but don't
503*a67afe4dSAndroid Build Coastguard Worker * move the others.
504*a67afe4dSAndroid Build Coastguard Worker */
505*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < maximum_colors; i++)
506*a67afe4dSAndroid Build Coastguard Worker {
507*a67afe4dSAndroid Build Coastguard Worker if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
508*a67afe4dSAndroid Build Coastguard Worker {
509*a67afe4dSAndroid Build Coastguard Worker do
510*a67afe4dSAndroid Build Coastguard Worker j--;
511*a67afe4dSAndroid Build Coastguard Worker while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
512*a67afe4dSAndroid Build Coastguard Worker
513*a67afe4dSAndroid Build Coastguard Worker palette[i] = palette[j];
514*a67afe4dSAndroid Build Coastguard Worker }
515*a67afe4dSAndroid Build Coastguard Worker }
516*a67afe4dSAndroid Build Coastguard Worker }
517*a67afe4dSAndroid Build Coastguard Worker else
518*a67afe4dSAndroid Build Coastguard Worker {
519*a67afe4dSAndroid Build Coastguard Worker int j = num_palette;
520*a67afe4dSAndroid Build Coastguard Worker
521*a67afe4dSAndroid Build Coastguard Worker /* Move all the used colors inside the max limit, and
522*a67afe4dSAndroid Build Coastguard Worker * develop a translation table.
523*a67afe4dSAndroid Build Coastguard Worker */
524*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < maximum_colors; i++)
525*a67afe4dSAndroid Build Coastguard Worker {
526*a67afe4dSAndroid Build Coastguard Worker /* Only move the colors we need to */
527*a67afe4dSAndroid Build Coastguard Worker if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
528*a67afe4dSAndroid Build Coastguard Worker {
529*a67afe4dSAndroid Build Coastguard Worker png_color tmp_color;
530*a67afe4dSAndroid Build Coastguard Worker
531*a67afe4dSAndroid Build Coastguard Worker do
532*a67afe4dSAndroid Build Coastguard Worker j--;
533*a67afe4dSAndroid Build Coastguard Worker while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
534*a67afe4dSAndroid Build Coastguard Worker
535*a67afe4dSAndroid Build Coastguard Worker tmp_color = palette[j];
536*a67afe4dSAndroid Build Coastguard Worker palette[j] = palette[i];
537*a67afe4dSAndroid Build Coastguard Worker palette[i] = tmp_color;
538*a67afe4dSAndroid Build Coastguard Worker /* Indicate where the color went */
539*a67afe4dSAndroid Build Coastguard Worker png_ptr->quantize_index[j] = (png_byte)i;
540*a67afe4dSAndroid Build Coastguard Worker png_ptr->quantize_index[i] = (png_byte)j;
541*a67afe4dSAndroid Build Coastguard Worker }
542*a67afe4dSAndroid Build Coastguard Worker }
543*a67afe4dSAndroid Build Coastguard Worker
544*a67afe4dSAndroid Build Coastguard Worker /* Find closest color for those colors we are not using */
545*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < num_palette; i++)
546*a67afe4dSAndroid Build Coastguard Worker {
547*a67afe4dSAndroid Build Coastguard Worker if ((int)png_ptr->quantize_index[i] >= maximum_colors)
548*a67afe4dSAndroid Build Coastguard Worker {
549*a67afe4dSAndroid Build Coastguard Worker int min_d, k, min_k, d_index;
550*a67afe4dSAndroid Build Coastguard Worker
551*a67afe4dSAndroid Build Coastguard Worker /* Find the closest color to one we threw out */
552*a67afe4dSAndroid Build Coastguard Worker d_index = png_ptr->quantize_index[i];
553*a67afe4dSAndroid Build Coastguard Worker min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
554*a67afe4dSAndroid Build Coastguard Worker for (k = 1, min_k = 0; k < maximum_colors; k++)
555*a67afe4dSAndroid Build Coastguard Worker {
556*a67afe4dSAndroid Build Coastguard Worker int d;
557*a67afe4dSAndroid Build Coastguard Worker
558*a67afe4dSAndroid Build Coastguard Worker d = PNG_COLOR_DIST(palette[d_index], palette[k]);
559*a67afe4dSAndroid Build Coastguard Worker
560*a67afe4dSAndroid Build Coastguard Worker if (d < min_d)
561*a67afe4dSAndroid Build Coastguard Worker {
562*a67afe4dSAndroid Build Coastguard Worker min_d = d;
563*a67afe4dSAndroid Build Coastguard Worker min_k = k;
564*a67afe4dSAndroid Build Coastguard Worker }
565*a67afe4dSAndroid Build Coastguard Worker }
566*a67afe4dSAndroid Build Coastguard Worker /* Point to closest color */
567*a67afe4dSAndroid Build Coastguard Worker png_ptr->quantize_index[i] = (png_byte)min_k;
568*a67afe4dSAndroid Build Coastguard Worker }
569*a67afe4dSAndroid Build Coastguard Worker }
570*a67afe4dSAndroid Build Coastguard Worker }
571*a67afe4dSAndroid Build Coastguard Worker png_free(png_ptr, png_ptr->quantize_sort);
572*a67afe4dSAndroid Build Coastguard Worker png_ptr->quantize_sort = NULL;
573*a67afe4dSAndroid Build Coastguard Worker }
574*a67afe4dSAndroid Build Coastguard Worker else
575*a67afe4dSAndroid Build Coastguard Worker {
576*a67afe4dSAndroid Build Coastguard Worker /* This is much harder to do simply (and quickly). Perhaps
577*a67afe4dSAndroid Build Coastguard Worker * we need to go through a median cut routine, but those
578*a67afe4dSAndroid Build Coastguard Worker * don't always behave themselves with only a few colors
579*a67afe4dSAndroid Build Coastguard Worker * as input. So we will just find the closest two colors,
580*a67afe4dSAndroid Build Coastguard Worker * and throw out one of them (chosen somewhat randomly).
581*a67afe4dSAndroid Build Coastguard Worker * [We don't understand this at all, so if someone wants to
582*a67afe4dSAndroid Build Coastguard Worker * work on improving it, be our guest - AED, GRP]
583*a67afe4dSAndroid Build Coastguard Worker */
584*a67afe4dSAndroid Build Coastguard Worker int i;
585*a67afe4dSAndroid Build Coastguard Worker int max_d;
586*a67afe4dSAndroid Build Coastguard Worker int num_new_palette;
587*a67afe4dSAndroid Build Coastguard Worker png_dsortp t;
588*a67afe4dSAndroid Build Coastguard Worker png_dsortpp hash;
589*a67afe4dSAndroid Build Coastguard Worker
590*a67afe4dSAndroid Build Coastguard Worker t = NULL;
591*a67afe4dSAndroid Build Coastguard Worker
592*a67afe4dSAndroid Build Coastguard Worker /* Initialize palette index arrays */
593*a67afe4dSAndroid Build Coastguard Worker png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
594*a67afe4dSAndroid Build Coastguard Worker (png_alloc_size_t)num_palette);
595*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
596*a67afe4dSAndroid Build Coastguard Worker (png_alloc_size_t)num_palette);
597*a67afe4dSAndroid Build Coastguard Worker
598*a67afe4dSAndroid Build Coastguard Worker /* Initialize the sort array */
599*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < num_palette; i++)
600*a67afe4dSAndroid Build Coastguard Worker {
601*a67afe4dSAndroid Build Coastguard Worker png_ptr->index_to_palette[i] = (png_byte)i;
602*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette_to_index[i] = (png_byte)i;
603*a67afe4dSAndroid Build Coastguard Worker }
604*a67afe4dSAndroid Build Coastguard Worker
605*a67afe4dSAndroid Build Coastguard Worker hash = (png_dsortpp)png_calloc(png_ptr, (png_alloc_size_t)(769 *
606*a67afe4dSAndroid Build Coastguard Worker (sizeof (png_dsortp))));
607*a67afe4dSAndroid Build Coastguard Worker
608*a67afe4dSAndroid Build Coastguard Worker num_new_palette = num_palette;
609*a67afe4dSAndroid Build Coastguard Worker
610*a67afe4dSAndroid Build Coastguard Worker /* Initial wild guess at how far apart the farthest pixel
611*a67afe4dSAndroid Build Coastguard Worker * pair we will be eliminating will be. Larger
612*a67afe4dSAndroid Build Coastguard Worker * numbers mean more areas will be allocated, Smaller
613*a67afe4dSAndroid Build Coastguard Worker * numbers run the risk of not saving enough data, and
614*a67afe4dSAndroid Build Coastguard Worker * having to do this all over again.
615*a67afe4dSAndroid Build Coastguard Worker *
616*a67afe4dSAndroid Build Coastguard Worker * I have not done extensive checking on this number.
617*a67afe4dSAndroid Build Coastguard Worker */
618*a67afe4dSAndroid Build Coastguard Worker max_d = 96;
619*a67afe4dSAndroid Build Coastguard Worker
620*a67afe4dSAndroid Build Coastguard Worker while (num_new_palette > maximum_colors)
621*a67afe4dSAndroid Build Coastguard Worker {
622*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < num_new_palette - 1; i++)
623*a67afe4dSAndroid Build Coastguard Worker {
624*a67afe4dSAndroid Build Coastguard Worker int j;
625*a67afe4dSAndroid Build Coastguard Worker
626*a67afe4dSAndroid Build Coastguard Worker for (j = i + 1; j < num_new_palette; j++)
627*a67afe4dSAndroid Build Coastguard Worker {
628*a67afe4dSAndroid Build Coastguard Worker int d;
629*a67afe4dSAndroid Build Coastguard Worker
630*a67afe4dSAndroid Build Coastguard Worker d = PNG_COLOR_DIST(palette[i], palette[j]);
631*a67afe4dSAndroid Build Coastguard Worker
632*a67afe4dSAndroid Build Coastguard Worker if (d <= max_d)
633*a67afe4dSAndroid Build Coastguard Worker {
634*a67afe4dSAndroid Build Coastguard Worker
635*a67afe4dSAndroid Build Coastguard Worker t = (png_dsortp)png_malloc_warn(png_ptr,
636*a67afe4dSAndroid Build Coastguard Worker (png_alloc_size_t)(sizeof (png_dsort)));
637*a67afe4dSAndroid Build Coastguard Worker
638*a67afe4dSAndroid Build Coastguard Worker if (t == NULL)
639*a67afe4dSAndroid Build Coastguard Worker break;
640*a67afe4dSAndroid Build Coastguard Worker
641*a67afe4dSAndroid Build Coastguard Worker t->next = hash[d];
642*a67afe4dSAndroid Build Coastguard Worker t->left = (png_byte)i;
643*a67afe4dSAndroid Build Coastguard Worker t->right = (png_byte)j;
644*a67afe4dSAndroid Build Coastguard Worker hash[d] = t;
645*a67afe4dSAndroid Build Coastguard Worker }
646*a67afe4dSAndroid Build Coastguard Worker }
647*a67afe4dSAndroid Build Coastguard Worker if (t == NULL)
648*a67afe4dSAndroid Build Coastguard Worker break;
649*a67afe4dSAndroid Build Coastguard Worker }
650*a67afe4dSAndroid Build Coastguard Worker
651*a67afe4dSAndroid Build Coastguard Worker if (t != NULL)
652*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i <= max_d; i++)
653*a67afe4dSAndroid Build Coastguard Worker {
654*a67afe4dSAndroid Build Coastguard Worker if (hash[i] != NULL)
655*a67afe4dSAndroid Build Coastguard Worker {
656*a67afe4dSAndroid Build Coastguard Worker png_dsortp p;
657*a67afe4dSAndroid Build Coastguard Worker
658*a67afe4dSAndroid Build Coastguard Worker for (p = hash[i]; p; p = p->next)
659*a67afe4dSAndroid Build Coastguard Worker {
660*a67afe4dSAndroid Build Coastguard Worker if ((int)png_ptr->index_to_palette[p->left]
661*a67afe4dSAndroid Build Coastguard Worker < num_new_palette &&
662*a67afe4dSAndroid Build Coastguard Worker (int)png_ptr->index_to_palette[p->right]
663*a67afe4dSAndroid Build Coastguard Worker < num_new_palette)
664*a67afe4dSAndroid Build Coastguard Worker {
665*a67afe4dSAndroid Build Coastguard Worker int j, next_j;
666*a67afe4dSAndroid Build Coastguard Worker
667*a67afe4dSAndroid Build Coastguard Worker if (num_new_palette & 0x01)
668*a67afe4dSAndroid Build Coastguard Worker {
669*a67afe4dSAndroid Build Coastguard Worker j = p->left;
670*a67afe4dSAndroid Build Coastguard Worker next_j = p->right;
671*a67afe4dSAndroid Build Coastguard Worker }
672*a67afe4dSAndroid Build Coastguard Worker else
673*a67afe4dSAndroid Build Coastguard Worker {
674*a67afe4dSAndroid Build Coastguard Worker j = p->right;
675*a67afe4dSAndroid Build Coastguard Worker next_j = p->left;
676*a67afe4dSAndroid Build Coastguard Worker }
677*a67afe4dSAndroid Build Coastguard Worker
678*a67afe4dSAndroid Build Coastguard Worker num_new_palette--;
679*a67afe4dSAndroid Build Coastguard Worker palette[png_ptr->index_to_palette[j]]
680*a67afe4dSAndroid Build Coastguard Worker = palette[num_new_palette];
681*a67afe4dSAndroid Build Coastguard Worker if (full_quantize == 0)
682*a67afe4dSAndroid Build Coastguard Worker {
683*a67afe4dSAndroid Build Coastguard Worker int k;
684*a67afe4dSAndroid Build Coastguard Worker
685*a67afe4dSAndroid Build Coastguard Worker for (k = 0; k < num_palette; k++)
686*a67afe4dSAndroid Build Coastguard Worker {
687*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->quantize_index[k] ==
688*a67afe4dSAndroid Build Coastguard Worker png_ptr->index_to_palette[j])
689*a67afe4dSAndroid Build Coastguard Worker png_ptr->quantize_index[k] =
690*a67afe4dSAndroid Build Coastguard Worker png_ptr->index_to_palette[next_j];
691*a67afe4dSAndroid Build Coastguard Worker
692*a67afe4dSAndroid Build Coastguard Worker if ((int)png_ptr->quantize_index[k] ==
693*a67afe4dSAndroid Build Coastguard Worker num_new_palette)
694*a67afe4dSAndroid Build Coastguard Worker png_ptr->quantize_index[k] =
695*a67afe4dSAndroid Build Coastguard Worker png_ptr->index_to_palette[j];
696*a67afe4dSAndroid Build Coastguard Worker }
697*a67afe4dSAndroid Build Coastguard Worker }
698*a67afe4dSAndroid Build Coastguard Worker
699*a67afe4dSAndroid Build Coastguard Worker png_ptr->index_to_palette[png_ptr->palette_to_index
700*a67afe4dSAndroid Build Coastguard Worker [num_new_palette]] = png_ptr->index_to_palette[j];
701*a67afe4dSAndroid Build Coastguard Worker
702*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
703*a67afe4dSAndroid Build Coastguard Worker = png_ptr->palette_to_index[num_new_palette];
704*a67afe4dSAndroid Build Coastguard Worker
705*a67afe4dSAndroid Build Coastguard Worker png_ptr->index_to_palette[j] =
706*a67afe4dSAndroid Build Coastguard Worker (png_byte)num_new_palette;
707*a67afe4dSAndroid Build Coastguard Worker
708*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette_to_index[num_new_palette] =
709*a67afe4dSAndroid Build Coastguard Worker (png_byte)j;
710*a67afe4dSAndroid Build Coastguard Worker }
711*a67afe4dSAndroid Build Coastguard Worker if (num_new_palette <= maximum_colors)
712*a67afe4dSAndroid Build Coastguard Worker break;
713*a67afe4dSAndroid Build Coastguard Worker }
714*a67afe4dSAndroid Build Coastguard Worker if (num_new_palette <= maximum_colors)
715*a67afe4dSAndroid Build Coastguard Worker break;
716*a67afe4dSAndroid Build Coastguard Worker }
717*a67afe4dSAndroid Build Coastguard Worker }
718*a67afe4dSAndroid Build Coastguard Worker
719*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 769; i++)
720*a67afe4dSAndroid Build Coastguard Worker {
721*a67afe4dSAndroid Build Coastguard Worker if (hash[i] != NULL)
722*a67afe4dSAndroid Build Coastguard Worker {
723*a67afe4dSAndroid Build Coastguard Worker png_dsortp p = hash[i];
724*a67afe4dSAndroid Build Coastguard Worker while (p)
725*a67afe4dSAndroid Build Coastguard Worker {
726*a67afe4dSAndroid Build Coastguard Worker t = p->next;
727*a67afe4dSAndroid Build Coastguard Worker png_free(png_ptr, p);
728*a67afe4dSAndroid Build Coastguard Worker p = t;
729*a67afe4dSAndroid Build Coastguard Worker }
730*a67afe4dSAndroid Build Coastguard Worker }
731*a67afe4dSAndroid Build Coastguard Worker hash[i] = 0;
732*a67afe4dSAndroid Build Coastguard Worker }
733*a67afe4dSAndroid Build Coastguard Worker max_d += 96;
734*a67afe4dSAndroid Build Coastguard Worker }
735*a67afe4dSAndroid Build Coastguard Worker png_free(png_ptr, hash);
736*a67afe4dSAndroid Build Coastguard Worker png_free(png_ptr, png_ptr->palette_to_index);
737*a67afe4dSAndroid Build Coastguard Worker png_free(png_ptr, png_ptr->index_to_palette);
738*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette_to_index = NULL;
739*a67afe4dSAndroid Build Coastguard Worker png_ptr->index_to_palette = NULL;
740*a67afe4dSAndroid Build Coastguard Worker }
741*a67afe4dSAndroid Build Coastguard Worker num_palette = maximum_colors;
742*a67afe4dSAndroid Build Coastguard Worker }
743*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->palette == NULL)
744*a67afe4dSAndroid Build Coastguard Worker {
745*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette = palette;
746*a67afe4dSAndroid Build Coastguard Worker }
747*a67afe4dSAndroid Build Coastguard Worker png_ptr->num_palette = (png_uint_16)num_palette;
748*a67afe4dSAndroid Build Coastguard Worker
749*a67afe4dSAndroid Build Coastguard Worker if (full_quantize != 0)
750*a67afe4dSAndroid Build Coastguard Worker {
751*a67afe4dSAndroid Build Coastguard Worker int i;
752*a67afe4dSAndroid Build Coastguard Worker png_bytep distance;
753*a67afe4dSAndroid Build Coastguard Worker int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +
754*a67afe4dSAndroid Build Coastguard Worker PNG_QUANTIZE_BLUE_BITS;
755*a67afe4dSAndroid Build Coastguard Worker int num_red = (1 << PNG_QUANTIZE_RED_BITS);
756*a67afe4dSAndroid Build Coastguard Worker int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);
757*a67afe4dSAndroid Build Coastguard Worker int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);
758*a67afe4dSAndroid Build Coastguard Worker size_t num_entries = ((size_t)1 << total_bits);
759*a67afe4dSAndroid Build Coastguard Worker
760*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
761*a67afe4dSAndroid Build Coastguard Worker (png_alloc_size_t)(num_entries));
762*a67afe4dSAndroid Build Coastguard Worker
763*a67afe4dSAndroid Build Coastguard Worker distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)num_entries);
764*a67afe4dSAndroid Build Coastguard Worker
765*a67afe4dSAndroid Build Coastguard Worker memset(distance, 0xff, num_entries);
766*a67afe4dSAndroid Build Coastguard Worker
767*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < num_palette; i++)
768*a67afe4dSAndroid Build Coastguard Worker {
769*a67afe4dSAndroid Build Coastguard Worker int ir, ig, ib;
770*a67afe4dSAndroid Build Coastguard Worker int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));
771*a67afe4dSAndroid Build Coastguard Worker int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));
772*a67afe4dSAndroid Build Coastguard Worker int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
773*a67afe4dSAndroid Build Coastguard Worker
774*a67afe4dSAndroid Build Coastguard Worker for (ir = 0; ir < num_red; ir++)
775*a67afe4dSAndroid Build Coastguard Worker {
776*a67afe4dSAndroid Build Coastguard Worker /* int dr = abs(ir - r); */
777*a67afe4dSAndroid Build Coastguard Worker int dr = ((ir > r) ? ir - r : r - ir);
778*a67afe4dSAndroid Build Coastguard Worker int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
779*a67afe4dSAndroid Build Coastguard Worker PNG_QUANTIZE_GREEN_BITS));
780*a67afe4dSAndroid Build Coastguard Worker
781*a67afe4dSAndroid Build Coastguard Worker for (ig = 0; ig < num_green; ig++)
782*a67afe4dSAndroid Build Coastguard Worker {
783*a67afe4dSAndroid Build Coastguard Worker /* int dg = abs(ig - g); */
784*a67afe4dSAndroid Build Coastguard Worker int dg = ((ig > g) ? ig - g : g - ig);
785*a67afe4dSAndroid Build Coastguard Worker int dt = dr + dg;
786*a67afe4dSAndroid Build Coastguard Worker int dm = ((dr > dg) ? dr : dg);
787*a67afe4dSAndroid Build Coastguard Worker int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
788*a67afe4dSAndroid Build Coastguard Worker
789*a67afe4dSAndroid Build Coastguard Worker for (ib = 0; ib < num_blue; ib++)
790*a67afe4dSAndroid Build Coastguard Worker {
791*a67afe4dSAndroid Build Coastguard Worker int d_index = index_g | ib;
792*a67afe4dSAndroid Build Coastguard Worker /* int db = abs(ib - b); */
793*a67afe4dSAndroid Build Coastguard Worker int db = ((ib > b) ? ib - b : b - ib);
794*a67afe4dSAndroid Build Coastguard Worker int dmax = ((dm > db) ? dm : db);
795*a67afe4dSAndroid Build Coastguard Worker int d = dmax + dt + db;
796*a67afe4dSAndroid Build Coastguard Worker
797*a67afe4dSAndroid Build Coastguard Worker if (d < (int)distance[d_index])
798*a67afe4dSAndroid Build Coastguard Worker {
799*a67afe4dSAndroid Build Coastguard Worker distance[d_index] = (png_byte)d;
800*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette_lookup[d_index] = (png_byte)i;
801*a67afe4dSAndroid Build Coastguard Worker }
802*a67afe4dSAndroid Build Coastguard Worker }
803*a67afe4dSAndroid Build Coastguard Worker }
804*a67afe4dSAndroid Build Coastguard Worker }
805*a67afe4dSAndroid Build Coastguard Worker }
806*a67afe4dSAndroid Build Coastguard Worker
807*a67afe4dSAndroid Build Coastguard Worker png_free(png_ptr, distance);
808*a67afe4dSAndroid Build Coastguard Worker }
809*a67afe4dSAndroid Build Coastguard Worker }
810*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_QUANTIZE */
811*a67afe4dSAndroid Build Coastguard Worker
812*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
813*a67afe4dSAndroid Build Coastguard Worker void PNGFAPI
png_set_gamma_fixed(png_structrp png_ptr,png_fixed_point scrn_gamma,png_fixed_point file_gamma)814*a67afe4dSAndroid Build Coastguard Worker png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
815*a67afe4dSAndroid Build Coastguard Worker png_fixed_point file_gamma)
816*a67afe4dSAndroid Build Coastguard Worker {
817*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_gamma_fixed");
818*a67afe4dSAndroid Build Coastguard Worker
819*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0)
820*a67afe4dSAndroid Build Coastguard Worker return;
821*a67afe4dSAndroid Build Coastguard Worker
822*a67afe4dSAndroid Build Coastguard Worker /* New in libpng-1.5.4 - reserve particular negative values as flags. */
823*a67afe4dSAndroid Build Coastguard Worker scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
824*a67afe4dSAndroid Build Coastguard Worker file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
825*a67afe4dSAndroid Build Coastguard Worker
826*a67afe4dSAndroid Build Coastguard Worker /* Checking the gamma values for being >0 was added in 1.5.4 along with the
827*a67afe4dSAndroid Build Coastguard Worker * premultiplied alpha support; this actually hides an undocumented feature
828*a67afe4dSAndroid Build Coastguard Worker * of the previous implementation which allowed gamma processing to be
829*a67afe4dSAndroid Build Coastguard Worker * disabled in background handling. There is no evidence (so far) that this
830*a67afe4dSAndroid Build Coastguard Worker * was being used; however, png_set_background itself accepted and must still
831*a67afe4dSAndroid Build Coastguard Worker * accept '0' for the gamma value it takes, because it isn't always used.
832*a67afe4dSAndroid Build Coastguard Worker *
833*a67afe4dSAndroid Build Coastguard Worker * Since this is an API change (albeit a very minor one that removes an
834*a67afe4dSAndroid Build Coastguard Worker * undocumented API feature) the following checks were only enabled in
835*a67afe4dSAndroid Build Coastguard Worker * libpng-1.6.0.
836*a67afe4dSAndroid Build Coastguard Worker */
837*a67afe4dSAndroid Build Coastguard Worker if (file_gamma <= 0)
838*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "invalid file gamma in png_set_gamma");
839*a67afe4dSAndroid Build Coastguard Worker
840*a67afe4dSAndroid Build Coastguard Worker if (scrn_gamma <= 0)
841*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "invalid screen gamma in png_set_gamma");
842*a67afe4dSAndroid Build Coastguard Worker
843*a67afe4dSAndroid Build Coastguard Worker /* Set the gamma values unconditionally - this overrides the value in the PNG
844*a67afe4dSAndroid Build Coastguard Worker * file if a gAMA chunk was present. png_set_alpha_mode provides a
845*a67afe4dSAndroid Build Coastguard Worker * different, easier, way to default the file gamma.
846*a67afe4dSAndroid Build Coastguard Worker */
847*a67afe4dSAndroid Build Coastguard Worker png_ptr->colorspace.gamma = file_gamma;
848*a67afe4dSAndroid Build Coastguard Worker png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
849*a67afe4dSAndroid Build Coastguard Worker png_ptr->screen_gamma = scrn_gamma;
850*a67afe4dSAndroid Build Coastguard Worker }
851*a67afe4dSAndroid Build Coastguard Worker
852*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_FLOATING_POINT_SUPPORTED
853*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_gamma(png_structrp png_ptr,double scrn_gamma,double file_gamma)854*a67afe4dSAndroid Build Coastguard Worker png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
855*a67afe4dSAndroid Build Coastguard Worker {
856*a67afe4dSAndroid Build Coastguard Worker png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
857*a67afe4dSAndroid Build Coastguard Worker convert_gamma_value(png_ptr, file_gamma));
858*a67afe4dSAndroid Build Coastguard Worker }
859*a67afe4dSAndroid Build Coastguard Worker # endif /* FLOATING_POINT */
860*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_GAMMA */
861*a67afe4dSAndroid Build Coastguard Worker
862*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_EXPAND_SUPPORTED
863*a67afe4dSAndroid Build Coastguard Worker /* Expand paletted images to RGB, expand grayscale images of
864*a67afe4dSAndroid Build Coastguard Worker * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
865*a67afe4dSAndroid Build Coastguard Worker * to alpha channels.
866*a67afe4dSAndroid Build Coastguard Worker */
867*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_expand(png_structrp png_ptr)868*a67afe4dSAndroid Build Coastguard Worker png_set_expand(png_structrp png_ptr)
869*a67afe4dSAndroid Build Coastguard Worker {
870*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_expand");
871*a67afe4dSAndroid Build Coastguard Worker
872*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0)
873*a67afe4dSAndroid Build Coastguard Worker return;
874*a67afe4dSAndroid Build Coastguard Worker
875*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
876*a67afe4dSAndroid Build Coastguard Worker }
877*a67afe4dSAndroid Build Coastguard Worker
878*a67afe4dSAndroid Build Coastguard Worker /* GRR 19990627: the following three functions currently are identical
879*a67afe4dSAndroid Build Coastguard Worker * to png_set_expand(). However, it is entirely reasonable that someone
880*a67afe4dSAndroid Build Coastguard Worker * might wish to expand an indexed image to RGB but *not* expand a single,
881*a67afe4dSAndroid Build Coastguard Worker * fully transparent palette entry to a full alpha channel--perhaps instead
882*a67afe4dSAndroid Build Coastguard Worker * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
883*a67afe4dSAndroid Build Coastguard Worker * the transparent color with a particular RGB value, or drop tRNS entirely.
884*a67afe4dSAndroid Build Coastguard Worker * IOW, a future version of the library may make the transformations flag
885*a67afe4dSAndroid Build Coastguard Worker * a bit more fine-grained, with separate bits for each of these three
886*a67afe4dSAndroid Build Coastguard Worker * functions.
887*a67afe4dSAndroid Build Coastguard Worker *
888*a67afe4dSAndroid Build Coastguard Worker * More to the point, these functions make it obvious what libpng will be
889*a67afe4dSAndroid Build Coastguard Worker * doing, whereas "expand" can (and does) mean any number of things.
890*a67afe4dSAndroid Build Coastguard Worker *
891*a67afe4dSAndroid Build Coastguard Worker * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
892*a67afe4dSAndroid Build Coastguard Worker * to expand only the sample depth but not to expand the tRNS to alpha
893*a67afe4dSAndroid Build Coastguard Worker * and its name was changed to png_set_expand_gray_1_2_4_to_8().
894*a67afe4dSAndroid Build Coastguard Worker */
895*a67afe4dSAndroid Build Coastguard Worker
896*a67afe4dSAndroid Build Coastguard Worker /* Expand paletted images to RGB. */
897*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_palette_to_rgb(png_structrp png_ptr)898*a67afe4dSAndroid Build Coastguard Worker png_set_palette_to_rgb(png_structrp png_ptr)
899*a67afe4dSAndroid Build Coastguard Worker {
900*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_palette_to_rgb");
901*a67afe4dSAndroid Build Coastguard Worker
902*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0)
903*a67afe4dSAndroid Build Coastguard Worker return;
904*a67afe4dSAndroid Build Coastguard Worker
905*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
906*a67afe4dSAndroid Build Coastguard Worker }
907*a67afe4dSAndroid Build Coastguard Worker
908*a67afe4dSAndroid Build Coastguard Worker /* Expand grayscale images of less than 8-bit depth to 8 bits. */
909*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)910*a67afe4dSAndroid Build Coastguard Worker png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
911*a67afe4dSAndroid Build Coastguard Worker {
912*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
913*a67afe4dSAndroid Build Coastguard Worker
914*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0)
915*a67afe4dSAndroid Build Coastguard Worker return;
916*a67afe4dSAndroid Build Coastguard Worker
917*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_EXPAND;
918*a67afe4dSAndroid Build Coastguard Worker }
919*a67afe4dSAndroid Build Coastguard Worker
920*a67afe4dSAndroid Build Coastguard Worker /* Expand tRNS chunks to alpha channels. */
921*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_tRNS_to_alpha(png_structrp png_ptr)922*a67afe4dSAndroid Build Coastguard Worker png_set_tRNS_to_alpha(png_structrp png_ptr)
923*a67afe4dSAndroid Build Coastguard Worker {
924*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_tRNS_to_alpha");
925*a67afe4dSAndroid Build Coastguard Worker
926*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0)
927*a67afe4dSAndroid Build Coastguard Worker return;
928*a67afe4dSAndroid Build Coastguard Worker
929*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
930*a67afe4dSAndroid Build Coastguard Worker }
931*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_EXPAND */
932*a67afe4dSAndroid Build Coastguard Worker
933*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_EXPAND_16_SUPPORTED
934*a67afe4dSAndroid Build Coastguard Worker /* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
935*a67afe4dSAndroid Build Coastguard Worker * it may not work correctly.)
936*a67afe4dSAndroid Build Coastguard Worker */
937*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_expand_16(png_structrp png_ptr)938*a67afe4dSAndroid Build Coastguard Worker png_set_expand_16(png_structrp png_ptr)
939*a67afe4dSAndroid Build Coastguard Worker {
940*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_expand_16");
941*a67afe4dSAndroid Build Coastguard Worker
942*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0)
943*a67afe4dSAndroid Build Coastguard Worker return;
944*a67afe4dSAndroid Build Coastguard Worker
945*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
946*a67afe4dSAndroid Build Coastguard Worker }
947*a67afe4dSAndroid Build Coastguard Worker #endif
948*a67afe4dSAndroid Build Coastguard Worker
949*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
950*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_gray_to_rgb(png_structrp png_ptr)951*a67afe4dSAndroid Build Coastguard Worker png_set_gray_to_rgb(png_structrp png_ptr)
952*a67afe4dSAndroid Build Coastguard Worker {
953*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_gray_to_rgb");
954*a67afe4dSAndroid Build Coastguard Worker
955*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 0) == 0)
956*a67afe4dSAndroid Build Coastguard Worker return;
957*a67afe4dSAndroid Build Coastguard Worker
958*a67afe4dSAndroid Build Coastguard Worker /* Because rgb must be 8 bits or more: */
959*a67afe4dSAndroid Build Coastguard Worker png_set_expand_gray_1_2_4_to_8(png_ptr);
960*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_GRAY_TO_RGB;
961*a67afe4dSAndroid Build Coastguard Worker }
962*a67afe4dSAndroid Build Coastguard Worker #endif
963*a67afe4dSAndroid Build Coastguard Worker
964*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
965*a67afe4dSAndroid Build Coastguard Worker void PNGFAPI
png_set_rgb_to_gray_fixed(png_structrp png_ptr,int error_action,png_fixed_point red,png_fixed_point green)966*a67afe4dSAndroid Build Coastguard Worker png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
967*a67afe4dSAndroid Build Coastguard Worker png_fixed_point red, png_fixed_point green)
968*a67afe4dSAndroid Build Coastguard Worker {
969*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_rgb_to_gray_fixed");
970*a67afe4dSAndroid Build Coastguard Worker
971*a67afe4dSAndroid Build Coastguard Worker /* Need the IHDR here because of the check on color_type below. */
972*a67afe4dSAndroid Build Coastguard Worker /* TODO: fix this */
973*a67afe4dSAndroid Build Coastguard Worker if (png_rtran_ok(png_ptr, 1) == 0)
974*a67afe4dSAndroid Build Coastguard Worker return;
975*a67afe4dSAndroid Build Coastguard Worker
976*a67afe4dSAndroid Build Coastguard Worker switch (error_action)
977*a67afe4dSAndroid Build Coastguard Worker {
978*a67afe4dSAndroid Build Coastguard Worker case PNG_ERROR_ACTION_NONE:
979*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_RGB_TO_GRAY;
980*a67afe4dSAndroid Build Coastguard Worker break;
981*a67afe4dSAndroid Build Coastguard Worker
982*a67afe4dSAndroid Build Coastguard Worker case PNG_ERROR_ACTION_WARN:
983*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
984*a67afe4dSAndroid Build Coastguard Worker break;
985*a67afe4dSAndroid Build Coastguard Worker
986*a67afe4dSAndroid Build Coastguard Worker case PNG_ERROR_ACTION_ERROR:
987*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
988*a67afe4dSAndroid Build Coastguard Worker break;
989*a67afe4dSAndroid Build Coastguard Worker
990*a67afe4dSAndroid Build Coastguard Worker default:
991*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "invalid error action to rgb_to_gray");
992*a67afe4dSAndroid Build Coastguard Worker }
993*a67afe4dSAndroid Build Coastguard Worker
994*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
995*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_EXPAND_SUPPORTED
996*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_EXPAND;
997*a67afe4dSAndroid Build Coastguard Worker #else
998*a67afe4dSAndroid Build Coastguard Worker {
999*a67afe4dSAndroid Build Coastguard Worker /* Make this an error in 1.6 because otherwise the application may assume
1000*a67afe4dSAndroid Build Coastguard Worker * that it just worked and get a memory overwrite.
1001*a67afe4dSAndroid Build Coastguard Worker */
1002*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr,
1003*a67afe4dSAndroid Build Coastguard Worker "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
1004*a67afe4dSAndroid Build Coastguard Worker
1005*a67afe4dSAndroid Build Coastguard Worker /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
1006*a67afe4dSAndroid Build Coastguard Worker }
1007*a67afe4dSAndroid Build Coastguard Worker #endif
1008*a67afe4dSAndroid Build Coastguard Worker {
1009*a67afe4dSAndroid Build Coastguard Worker if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
1010*a67afe4dSAndroid Build Coastguard Worker {
1011*a67afe4dSAndroid Build Coastguard Worker png_uint_16 red_int, green_int;
1012*a67afe4dSAndroid Build Coastguard Worker
1013*a67afe4dSAndroid Build Coastguard Worker /* NOTE: this calculation does not round, but this behavior is retained
1014*a67afe4dSAndroid Build Coastguard Worker * for consistency; the inaccuracy is very small. The code here always
1015*a67afe4dSAndroid Build Coastguard Worker * overwrites the coefficients, regardless of whether they have been
1016*a67afe4dSAndroid Build Coastguard Worker * defaulted or set already.
1017*a67afe4dSAndroid Build Coastguard Worker */
1018*a67afe4dSAndroid Build Coastguard Worker red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);
1019*a67afe4dSAndroid Build Coastguard Worker green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);
1020*a67afe4dSAndroid Build Coastguard Worker
1021*a67afe4dSAndroid Build Coastguard Worker png_ptr->rgb_to_gray_red_coeff = red_int;
1022*a67afe4dSAndroid Build Coastguard Worker png_ptr->rgb_to_gray_green_coeff = green_int;
1023*a67afe4dSAndroid Build Coastguard Worker png_ptr->rgb_to_gray_coefficients_set = 1;
1024*a67afe4dSAndroid Build Coastguard Worker }
1025*a67afe4dSAndroid Build Coastguard Worker
1026*a67afe4dSAndroid Build Coastguard Worker else
1027*a67afe4dSAndroid Build Coastguard Worker {
1028*a67afe4dSAndroid Build Coastguard Worker if (red >= 0 && green >= 0)
1029*a67afe4dSAndroid Build Coastguard Worker png_app_warning(png_ptr,
1030*a67afe4dSAndroid Build Coastguard Worker "ignoring out of range rgb_to_gray coefficients");
1031*a67afe4dSAndroid Build Coastguard Worker
1032*a67afe4dSAndroid Build Coastguard Worker /* Use the defaults, from the cHRM chunk if set, else the historical
1033*a67afe4dSAndroid Build Coastguard Worker * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See
1034*a67afe4dSAndroid Build Coastguard Worker * png_do_rgb_to_gray for more discussion of the values. In this case
1035*a67afe4dSAndroid Build Coastguard Worker * the coefficients are not marked as 'set' and are not overwritten if
1036*a67afe4dSAndroid Build Coastguard Worker * something has already provided a default.
1037*a67afe4dSAndroid Build Coastguard Worker */
1038*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->rgb_to_gray_red_coeff == 0 &&
1039*a67afe4dSAndroid Build Coastguard Worker png_ptr->rgb_to_gray_green_coeff == 0)
1040*a67afe4dSAndroid Build Coastguard Worker {
1041*a67afe4dSAndroid Build Coastguard Worker png_ptr->rgb_to_gray_red_coeff = 6968;
1042*a67afe4dSAndroid Build Coastguard Worker png_ptr->rgb_to_gray_green_coeff = 23434;
1043*a67afe4dSAndroid Build Coastguard Worker /* png_ptr->rgb_to_gray_blue_coeff = 2366; */
1044*a67afe4dSAndroid Build Coastguard Worker }
1045*a67afe4dSAndroid Build Coastguard Worker }
1046*a67afe4dSAndroid Build Coastguard Worker }
1047*a67afe4dSAndroid Build Coastguard Worker }
1048*a67afe4dSAndroid Build Coastguard Worker
1049*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_FLOATING_POINT_SUPPORTED
1050*a67afe4dSAndroid Build Coastguard Worker /* Convert a RGB image to a grayscale of the same width. This allows us,
1051*a67afe4dSAndroid Build Coastguard Worker * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
1052*a67afe4dSAndroid Build Coastguard Worker */
1053*a67afe4dSAndroid Build Coastguard Worker
1054*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_rgb_to_gray(png_structrp png_ptr,int error_action,double red,double green)1055*a67afe4dSAndroid Build Coastguard Worker png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
1056*a67afe4dSAndroid Build Coastguard Worker double green)
1057*a67afe4dSAndroid Build Coastguard Worker {
1058*a67afe4dSAndroid Build Coastguard Worker png_set_rgb_to_gray_fixed(png_ptr, error_action,
1059*a67afe4dSAndroid Build Coastguard Worker png_fixed(png_ptr, red, "rgb to gray red coefficient"),
1060*a67afe4dSAndroid Build Coastguard Worker png_fixed(png_ptr, green, "rgb to gray green coefficient"));
1061*a67afe4dSAndroid Build Coastguard Worker }
1062*a67afe4dSAndroid Build Coastguard Worker #endif /* FLOATING POINT */
1063*a67afe4dSAndroid Build Coastguard Worker
1064*a67afe4dSAndroid Build Coastguard Worker #endif /* RGB_TO_GRAY */
1065*a67afe4dSAndroid Build Coastguard Worker
1066*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
1067*a67afe4dSAndroid Build Coastguard Worker defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1068*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_read_user_transform_fn(png_structrp png_ptr,png_user_transform_ptr read_user_transform_fn)1069*a67afe4dSAndroid Build Coastguard Worker png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
1070*a67afe4dSAndroid Build Coastguard Worker read_user_transform_fn)
1071*a67afe4dSAndroid Build Coastguard Worker {
1072*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_set_read_user_transform_fn");
1073*a67afe4dSAndroid Build Coastguard Worker
1074*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1075*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_USER_TRANSFORM;
1076*a67afe4dSAndroid Build Coastguard Worker png_ptr->read_user_transform_fn = read_user_transform_fn;
1077*a67afe4dSAndroid Build Coastguard Worker #endif
1078*a67afe4dSAndroid Build Coastguard Worker }
1079*a67afe4dSAndroid Build Coastguard Worker #endif
1080*a67afe4dSAndroid Build Coastguard Worker
1081*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_TRANSFORMS_SUPPORTED
1082*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
1083*a67afe4dSAndroid Build Coastguard Worker /* In the case of gamma transformations only do transformations on images where
1084*a67afe4dSAndroid Build Coastguard Worker * the [file] gamma and screen_gamma are not close reciprocals, otherwise it
1085*a67afe4dSAndroid Build Coastguard Worker * slows things down slightly, and also needlessly introduces small errors.
1086*a67afe4dSAndroid Build Coastguard Worker */
1087*a67afe4dSAndroid Build Coastguard Worker static int /* PRIVATE */
png_gamma_threshold(png_fixed_point screen_gamma,png_fixed_point file_gamma)1088*a67afe4dSAndroid Build Coastguard Worker png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
1089*a67afe4dSAndroid Build Coastguard Worker {
1090*a67afe4dSAndroid Build Coastguard Worker /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma
1091*a67afe4dSAndroid Build Coastguard Worker * correction as a difference of the overall transform from 1.0
1092*a67afe4dSAndroid Build Coastguard Worker *
1093*a67afe4dSAndroid Build Coastguard Worker * We want to compare the threshold with s*f - 1, if we get
1094*a67afe4dSAndroid Build Coastguard Worker * overflow here it is because of wacky gamma values so we
1095*a67afe4dSAndroid Build Coastguard Worker * turn on processing anyway.
1096*a67afe4dSAndroid Build Coastguard Worker */
1097*a67afe4dSAndroid Build Coastguard Worker png_fixed_point gtest;
1098*a67afe4dSAndroid Build Coastguard Worker return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) ||
1099*a67afe4dSAndroid Build Coastguard Worker png_gamma_significant(gtest);
1100*a67afe4dSAndroid Build Coastguard Worker }
1101*a67afe4dSAndroid Build Coastguard Worker #endif
1102*a67afe4dSAndroid Build Coastguard Worker
1103*a67afe4dSAndroid Build Coastguard Worker /* Initialize everything needed for the read. This includes modifying
1104*a67afe4dSAndroid Build Coastguard Worker * the palette.
1105*a67afe4dSAndroid Build Coastguard Worker */
1106*a67afe4dSAndroid Build Coastguard Worker
1107*a67afe4dSAndroid Build Coastguard Worker /* For the moment 'png_init_palette_transformations' and
1108*a67afe4dSAndroid Build Coastguard Worker * 'png_init_rgb_transformations' only do some flag canceling optimizations.
1109*a67afe4dSAndroid Build Coastguard Worker * The intent is that these two routines should have palette or rgb operations
1110*a67afe4dSAndroid Build Coastguard Worker * extracted from 'png_init_read_transformations'.
1111*a67afe4dSAndroid Build Coastguard Worker */
1112*a67afe4dSAndroid Build Coastguard Worker static void /* PRIVATE */
png_init_palette_transformations(png_structrp png_ptr)1113*a67afe4dSAndroid Build Coastguard Worker png_init_palette_transformations(png_structrp png_ptr)
1114*a67afe4dSAndroid Build Coastguard Worker {
1115*a67afe4dSAndroid Build Coastguard Worker /* Called to handle the (input) palette case. In png_do_read_transformations
1116*a67afe4dSAndroid Build Coastguard Worker * the first step is to expand the palette if requested, so this code must
1117*a67afe4dSAndroid Build Coastguard Worker * take care to only make changes that are invariant with respect to the
1118*a67afe4dSAndroid Build Coastguard Worker * palette expansion, or only do them if there is no expansion.
1119*a67afe4dSAndroid Build Coastguard Worker *
1120*a67afe4dSAndroid Build Coastguard Worker * STRIP_ALPHA has already been handled in the caller (by setting num_trans
1121*a67afe4dSAndroid Build Coastguard Worker * to 0.)
1122*a67afe4dSAndroid Build Coastguard Worker */
1123*a67afe4dSAndroid Build Coastguard Worker int input_has_alpha = 0;
1124*a67afe4dSAndroid Build Coastguard Worker int input_has_transparency = 0;
1125*a67afe4dSAndroid Build Coastguard Worker
1126*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->num_trans > 0)
1127*a67afe4dSAndroid Build Coastguard Worker {
1128*a67afe4dSAndroid Build Coastguard Worker int i;
1129*a67afe4dSAndroid Build Coastguard Worker
1130*a67afe4dSAndroid Build Coastguard Worker /* Ignore if all the entries are opaque (unlikely!) */
1131*a67afe4dSAndroid Build Coastguard Worker for (i=0; i<png_ptr->num_trans; ++i)
1132*a67afe4dSAndroid Build Coastguard Worker {
1133*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->trans_alpha[i] == 255)
1134*a67afe4dSAndroid Build Coastguard Worker continue;
1135*a67afe4dSAndroid Build Coastguard Worker else if (png_ptr->trans_alpha[i] == 0)
1136*a67afe4dSAndroid Build Coastguard Worker input_has_transparency = 1;
1137*a67afe4dSAndroid Build Coastguard Worker else
1138*a67afe4dSAndroid Build Coastguard Worker {
1139*a67afe4dSAndroid Build Coastguard Worker input_has_transparency = 1;
1140*a67afe4dSAndroid Build Coastguard Worker input_has_alpha = 1;
1141*a67afe4dSAndroid Build Coastguard Worker break;
1142*a67afe4dSAndroid Build Coastguard Worker }
1143*a67afe4dSAndroid Build Coastguard Worker }
1144*a67afe4dSAndroid Build Coastguard Worker }
1145*a67afe4dSAndroid Build Coastguard Worker
1146*a67afe4dSAndroid Build Coastguard Worker /* If no alpha we can optimize. */
1147*a67afe4dSAndroid Build Coastguard Worker if (input_has_alpha == 0)
1148*a67afe4dSAndroid Build Coastguard Worker {
1149*a67afe4dSAndroid Build Coastguard Worker /* Any alpha means background and associative alpha processing is
1150*a67afe4dSAndroid Build Coastguard Worker * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1151*a67afe4dSAndroid Build Coastguard Worker * and ENCODE_ALPHA are irrelevant.
1152*a67afe4dSAndroid Build Coastguard Worker */
1153*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
1154*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1155*a67afe4dSAndroid Build Coastguard Worker
1156*a67afe4dSAndroid Build Coastguard Worker if (input_has_transparency == 0)
1157*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
1158*a67afe4dSAndroid Build Coastguard Worker }
1159*a67afe4dSAndroid Build Coastguard Worker
1160*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1161*a67afe4dSAndroid Build Coastguard Worker /* png_set_background handling - deals with the complexity of whether the
1162*a67afe4dSAndroid Build Coastguard Worker * background color is in the file format or the screen format in the case
1163*a67afe4dSAndroid Build Coastguard Worker * where an 'expand' will happen.
1164*a67afe4dSAndroid Build Coastguard Worker */
1165*a67afe4dSAndroid Build Coastguard Worker
1166*a67afe4dSAndroid Build Coastguard Worker /* The following code cannot be entered in the alpha pre-multiplication case
1167*a67afe4dSAndroid Build Coastguard Worker * because PNG_BACKGROUND_EXPAND is cancelled below.
1168*a67afe4dSAndroid Build Coastguard Worker */
1169*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
1170*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_EXPAND) != 0)
1171*a67afe4dSAndroid Build Coastguard Worker {
1172*a67afe4dSAndroid Build Coastguard Worker {
1173*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.red =
1174*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette[png_ptr->background.index].red;
1175*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.green =
1176*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette[png_ptr->background.index].green;
1177*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.blue =
1178*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette[png_ptr->background.index].blue;
1179*a67afe4dSAndroid Build Coastguard Worker
1180*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
1181*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
1182*a67afe4dSAndroid Build Coastguard Worker {
1183*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1184*a67afe4dSAndroid Build Coastguard Worker {
1185*a67afe4dSAndroid Build Coastguard Worker /* Invert the alpha channel (in tRNS) unless the pixels are
1186*a67afe4dSAndroid Build Coastguard Worker * going to be expanded, in which case leave it for later
1187*a67afe4dSAndroid Build Coastguard Worker */
1188*a67afe4dSAndroid Build Coastguard Worker int i, istop = png_ptr->num_trans;
1189*a67afe4dSAndroid Build Coastguard Worker
1190*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < istop; i++)
1191*a67afe4dSAndroid Build Coastguard Worker png_ptr->trans_alpha[i] =
1192*a67afe4dSAndroid Build Coastguard Worker (png_byte)(255 - png_ptr->trans_alpha[i]);
1193*a67afe4dSAndroid Build Coastguard Worker }
1194*a67afe4dSAndroid Build Coastguard Worker }
1195*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_INVERT_ALPHA */
1196*a67afe4dSAndroid Build Coastguard Worker }
1197*a67afe4dSAndroid Build Coastguard Worker } /* background expand and (therefore) no alpha association. */
1198*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_EXPAND && READ_BACKGROUND */
1199*a67afe4dSAndroid Build Coastguard Worker }
1200*a67afe4dSAndroid Build Coastguard Worker
1201*a67afe4dSAndroid Build Coastguard Worker static void /* PRIVATE */
png_init_rgb_transformations(png_structrp png_ptr)1202*a67afe4dSAndroid Build Coastguard Worker png_init_rgb_transformations(png_structrp png_ptr)
1203*a67afe4dSAndroid Build Coastguard Worker {
1204*a67afe4dSAndroid Build Coastguard Worker /* Added to libpng-1.5.4: check the color type to determine whether there
1205*a67afe4dSAndroid Build Coastguard Worker * is any alpha or transparency in the image and simply cancel the
1206*a67afe4dSAndroid Build Coastguard Worker * background and alpha mode stuff if there isn't.
1207*a67afe4dSAndroid Build Coastguard Worker */
1208*a67afe4dSAndroid Build Coastguard Worker int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;
1209*a67afe4dSAndroid Build Coastguard Worker int input_has_transparency = png_ptr->num_trans > 0;
1210*a67afe4dSAndroid Build Coastguard Worker
1211*a67afe4dSAndroid Build Coastguard Worker /* If no alpha we can optimize. */
1212*a67afe4dSAndroid Build Coastguard Worker if (input_has_alpha == 0)
1213*a67afe4dSAndroid Build Coastguard Worker {
1214*a67afe4dSAndroid Build Coastguard Worker /* Any alpha means background and associative alpha processing is
1215*a67afe4dSAndroid Build Coastguard Worker * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
1216*a67afe4dSAndroid Build Coastguard Worker * and ENCODE_ALPHA are irrelevant.
1217*a67afe4dSAndroid Build Coastguard Worker */
1218*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_READ_ALPHA_MODE_SUPPORTED
1219*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
1220*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1221*a67afe4dSAndroid Build Coastguard Worker # endif
1222*a67afe4dSAndroid Build Coastguard Worker
1223*a67afe4dSAndroid Build Coastguard Worker if (input_has_transparency == 0)
1224*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
1225*a67afe4dSAndroid Build Coastguard Worker }
1226*a67afe4dSAndroid Build Coastguard Worker
1227*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1228*a67afe4dSAndroid Build Coastguard Worker /* png_set_background handling - deals with the complexity of whether the
1229*a67afe4dSAndroid Build Coastguard Worker * background color is in the file format or the screen format in the case
1230*a67afe4dSAndroid Build Coastguard Worker * where an 'expand' will happen.
1231*a67afe4dSAndroid Build Coastguard Worker */
1232*a67afe4dSAndroid Build Coastguard Worker
1233*a67afe4dSAndroid Build Coastguard Worker /* The following code cannot be entered in the alpha pre-multiplication case
1234*a67afe4dSAndroid Build Coastguard Worker * because PNG_BACKGROUND_EXPAND is cancelled below.
1235*a67afe4dSAndroid Build Coastguard Worker */
1236*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
1237*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_EXPAND) != 0 &&
1238*a67afe4dSAndroid Build Coastguard Worker (png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1239*a67afe4dSAndroid Build Coastguard Worker /* i.e., GRAY or GRAY_ALPHA */
1240*a67afe4dSAndroid Build Coastguard Worker {
1241*a67afe4dSAndroid Build Coastguard Worker {
1242*a67afe4dSAndroid Build Coastguard Worker /* Expand background and tRNS chunks */
1243*a67afe4dSAndroid Build Coastguard Worker int gray = png_ptr->background.gray;
1244*a67afe4dSAndroid Build Coastguard Worker int trans_gray = png_ptr->trans_color.gray;
1245*a67afe4dSAndroid Build Coastguard Worker
1246*a67afe4dSAndroid Build Coastguard Worker switch (png_ptr->bit_depth)
1247*a67afe4dSAndroid Build Coastguard Worker {
1248*a67afe4dSAndroid Build Coastguard Worker case 1:
1249*a67afe4dSAndroid Build Coastguard Worker gray *= 0xff;
1250*a67afe4dSAndroid Build Coastguard Worker trans_gray *= 0xff;
1251*a67afe4dSAndroid Build Coastguard Worker break;
1252*a67afe4dSAndroid Build Coastguard Worker
1253*a67afe4dSAndroid Build Coastguard Worker case 2:
1254*a67afe4dSAndroid Build Coastguard Worker gray *= 0x55;
1255*a67afe4dSAndroid Build Coastguard Worker trans_gray *= 0x55;
1256*a67afe4dSAndroid Build Coastguard Worker break;
1257*a67afe4dSAndroid Build Coastguard Worker
1258*a67afe4dSAndroid Build Coastguard Worker case 4:
1259*a67afe4dSAndroid Build Coastguard Worker gray *= 0x11;
1260*a67afe4dSAndroid Build Coastguard Worker trans_gray *= 0x11;
1261*a67afe4dSAndroid Build Coastguard Worker break;
1262*a67afe4dSAndroid Build Coastguard Worker
1263*a67afe4dSAndroid Build Coastguard Worker default:
1264*a67afe4dSAndroid Build Coastguard Worker
1265*a67afe4dSAndroid Build Coastguard Worker case 8:
1266*a67afe4dSAndroid Build Coastguard Worker /* FALLTHROUGH */ /* (Already 8 bits) */
1267*a67afe4dSAndroid Build Coastguard Worker
1268*a67afe4dSAndroid Build Coastguard Worker case 16:
1269*a67afe4dSAndroid Build Coastguard Worker /* Already a full 16 bits */
1270*a67afe4dSAndroid Build Coastguard Worker break;
1271*a67afe4dSAndroid Build Coastguard Worker }
1272*a67afe4dSAndroid Build Coastguard Worker
1273*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.red = png_ptr->background.green =
1274*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.blue = (png_uint_16)gray;
1275*a67afe4dSAndroid Build Coastguard Worker
1276*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
1277*a67afe4dSAndroid Build Coastguard Worker {
1278*a67afe4dSAndroid Build Coastguard Worker png_ptr->trans_color.red = png_ptr->trans_color.green =
1279*a67afe4dSAndroid Build Coastguard Worker png_ptr->trans_color.blue = (png_uint_16)trans_gray;
1280*a67afe4dSAndroid Build Coastguard Worker }
1281*a67afe4dSAndroid Build Coastguard Worker }
1282*a67afe4dSAndroid Build Coastguard Worker } /* background expand and (therefore) no alpha association. */
1283*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_EXPAND && READ_BACKGROUND */
1284*a67afe4dSAndroid Build Coastguard Worker }
1285*a67afe4dSAndroid Build Coastguard Worker
1286*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_init_read_transformations(png_structrp png_ptr)1287*a67afe4dSAndroid Build Coastguard Worker png_init_read_transformations(png_structrp png_ptr)
1288*a67afe4dSAndroid Build Coastguard Worker {
1289*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_init_read_transformations");
1290*a67afe4dSAndroid Build Coastguard Worker
1291*a67afe4dSAndroid Build Coastguard Worker /* This internal function is called from png_read_start_row in pngrutil.c
1292*a67afe4dSAndroid Build Coastguard Worker * and it is called before the 'rowbytes' calculation is done, so the code
1293*a67afe4dSAndroid Build Coastguard Worker * in here can change or update the transformations flags.
1294*a67afe4dSAndroid Build Coastguard Worker *
1295*a67afe4dSAndroid Build Coastguard Worker * First do updates that do not depend on the details of the PNG image data
1296*a67afe4dSAndroid Build Coastguard Worker * being processed.
1297*a67afe4dSAndroid Build Coastguard Worker */
1298*a67afe4dSAndroid Build Coastguard Worker
1299*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
1300*a67afe4dSAndroid Build Coastguard Worker /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds
1301*a67afe4dSAndroid Build Coastguard Worker * png_set_alpha_mode and this is another source for a default file gamma so
1302*a67afe4dSAndroid Build Coastguard Worker * the test needs to be performed later - here. In addition prior to 1.5.4
1303*a67afe4dSAndroid Build Coastguard Worker * the tests were repeated for the PALETTE color type here - this is no
1304*a67afe4dSAndroid Build Coastguard Worker * longer necessary (and doesn't seem to have been necessary before.)
1305*a67afe4dSAndroid Build Coastguard Worker */
1306*a67afe4dSAndroid Build Coastguard Worker {
1307*a67afe4dSAndroid Build Coastguard Worker /* The following temporary indicates if overall gamma correction is
1308*a67afe4dSAndroid Build Coastguard Worker * required.
1309*a67afe4dSAndroid Build Coastguard Worker */
1310*a67afe4dSAndroid Build Coastguard Worker int gamma_correction = 0;
1311*a67afe4dSAndroid Build Coastguard Worker
1312*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->colorspace.gamma != 0) /* has been set */
1313*a67afe4dSAndroid Build Coastguard Worker {
1314*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->screen_gamma != 0) /* screen set too */
1315*a67afe4dSAndroid Build Coastguard Worker gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
1316*a67afe4dSAndroid Build Coastguard Worker png_ptr->screen_gamma);
1317*a67afe4dSAndroid Build Coastguard Worker
1318*a67afe4dSAndroid Build Coastguard Worker else
1319*a67afe4dSAndroid Build Coastguard Worker /* Assume the output matches the input; a long time default behavior
1320*a67afe4dSAndroid Build Coastguard Worker * of libpng, although the standard has nothing to say about this.
1321*a67afe4dSAndroid Build Coastguard Worker */
1322*a67afe4dSAndroid Build Coastguard Worker png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
1323*a67afe4dSAndroid Build Coastguard Worker }
1324*a67afe4dSAndroid Build Coastguard Worker
1325*a67afe4dSAndroid Build Coastguard Worker else if (png_ptr->screen_gamma != 0)
1326*a67afe4dSAndroid Build Coastguard Worker /* The converse - assume the file matches the screen, note that this
1327*a67afe4dSAndroid Build Coastguard Worker * perhaps undesirable default can (from 1.5.4) be changed by calling
1328*a67afe4dSAndroid Build Coastguard Worker * png_set_alpha_mode (even if the alpha handling mode isn't required
1329*a67afe4dSAndroid Build Coastguard Worker * or isn't changed from the default.)
1330*a67afe4dSAndroid Build Coastguard Worker */
1331*a67afe4dSAndroid Build Coastguard Worker png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
1332*a67afe4dSAndroid Build Coastguard Worker
1333*a67afe4dSAndroid Build Coastguard Worker else /* neither are set */
1334*a67afe4dSAndroid Build Coastguard Worker /* Just in case the following prevents any processing - file and screen
1335*a67afe4dSAndroid Build Coastguard Worker * are both assumed to be linear and there is no way to introduce a
1336*a67afe4dSAndroid Build Coastguard Worker * third gamma value other than png_set_background with 'UNIQUE', and,
1337*a67afe4dSAndroid Build Coastguard Worker * prior to 1.5.4
1338*a67afe4dSAndroid Build Coastguard Worker */
1339*a67afe4dSAndroid Build Coastguard Worker png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;
1340*a67afe4dSAndroid Build Coastguard Worker
1341*a67afe4dSAndroid Build Coastguard Worker /* We have a gamma value now. */
1342*a67afe4dSAndroid Build Coastguard Worker png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
1343*a67afe4dSAndroid Build Coastguard Worker
1344*a67afe4dSAndroid Build Coastguard Worker /* Now turn the gamma transformation on or off as appropriate. Notice
1345*a67afe4dSAndroid Build Coastguard Worker * that PNG_GAMMA just refers to the file->screen correction. Alpha
1346*a67afe4dSAndroid Build Coastguard Worker * composition may independently cause gamma correction because it needs
1347*a67afe4dSAndroid Build Coastguard Worker * linear data (e.g. if the file has a gAMA chunk but the screen gamma
1348*a67afe4dSAndroid Build Coastguard Worker * hasn't been specified.) In any case this flag may get turned off in
1349*a67afe4dSAndroid Build Coastguard Worker * the code immediately below if the transform can be handled outside the
1350*a67afe4dSAndroid Build Coastguard Worker * row loop.
1351*a67afe4dSAndroid Build Coastguard Worker */
1352*a67afe4dSAndroid Build Coastguard Worker if (gamma_correction != 0)
1353*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_GAMMA;
1354*a67afe4dSAndroid Build Coastguard Worker
1355*a67afe4dSAndroid Build Coastguard Worker else
1356*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_GAMMA;
1357*a67afe4dSAndroid Build Coastguard Worker }
1358*a67afe4dSAndroid Build Coastguard Worker #endif
1359*a67afe4dSAndroid Build Coastguard Worker
1360*a67afe4dSAndroid Build Coastguard Worker /* Certain transformations have the effect of preventing other
1361*a67afe4dSAndroid Build Coastguard Worker * transformations that happen afterward in png_do_read_transformations;
1362*a67afe4dSAndroid Build Coastguard Worker * resolve the interdependencies here. From the code of
1363*a67afe4dSAndroid Build Coastguard Worker * png_do_read_transformations the order is:
1364*a67afe4dSAndroid Build Coastguard Worker *
1365*a67afe4dSAndroid Build Coastguard Worker * 1) PNG_EXPAND (including PNG_EXPAND_tRNS)
1366*a67afe4dSAndroid Build Coastguard Worker * 2) PNG_STRIP_ALPHA (if no compose)
1367*a67afe4dSAndroid Build Coastguard Worker * 3) PNG_RGB_TO_GRAY
1368*a67afe4dSAndroid Build Coastguard Worker * 4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY
1369*a67afe4dSAndroid Build Coastguard Worker * 5) PNG_COMPOSE
1370*a67afe4dSAndroid Build Coastguard Worker * 6) PNG_GAMMA
1371*a67afe4dSAndroid Build Coastguard Worker * 7) PNG_STRIP_ALPHA (if compose)
1372*a67afe4dSAndroid Build Coastguard Worker * 8) PNG_ENCODE_ALPHA
1373*a67afe4dSAndroid Build Coastguard Worker * 9) PNG_SCALE_16_TO_8
1374*a67afe4dSAndroid Build Coastguard Worker * 10) PNG_16_TO_8
1375*a67afe4dSAndroid Build Coastguard Worker * 11) PNG_QUANTIZE (converts to palette)
1376*a67afe4dSAndroid Build Coastguard Worker * 12) PNG_EXPAND_16
1377*a67afe4dSAndroid Build Coastguard Worker * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
1378*a67afe4dSAndroid Build Coastguard Worker * 14) PNG_INVERT_MONO
1379*a67afe4dSAndroid Build Coastguard Worker * 15) PNG_INVERT_ALPHA
1380*a67afe4dSAndroid Build Coastguard Worker * 16) PNG_SHIFT
1381*a67afe4dSAndroid Build Coastguard Worker * 17) PNG_PACK
1382*a67afe4dSAndroid Build Coastguard Worker * 18) PNG_BGR
1383*a67afe4dSAndroid Build Coastguard Worker * 19) PNG_PACKSWAP
1384*a67afe4dSAndroid Build Coastguard Worker * 20) PNG_FILLER (includes PNG_ADD_ALPHA)
1385*a67afe4dSAndroid Build Coastguard Worker * 21) PNG_SWAP_ALPHA
1386*a67afe4dSAndroid Build Coastguard Worker * 22) PNG_SWAP_BYTES
1387*a67afe4dSAndroid Build Coastguard Worker * 23) PNG_USER_TRANSFORM [must be last]
1388*a67afe4dSAndroid Build Coastguard Worker */
1389*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1390*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
1391*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_COMPOSE) == 0)
1392*a67afe4dSAndroid Build Coastguard Worker {
1393*a67afe4dSAndroid Build Coastguard Worker /* Stripping the alpha channel happens immediately after the 'expand'
1394*a67afe4dSAndroid Build Coastguard Worker * transformations, before all other transformation, so it cancels out
1395*a67afe4dSAndroid Build Coastguard Worker * the alpha handling. It has the side effect negating the effect of
1396*a67afe4dSAndroid Build Coastguard Worker * PNG_EXPAND_tRNS too:
1397*a67afe4dSAndroid Build Coastguard Worker */
1398*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA |
1399*a67afe4dSAndroid Build Coastguard Worker PNG_EXPAND_tRNS);
1400*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1401*a67afe4dSAndroid Build Coastguard Worker
1402*a67afe4dSAndroid Build Coastguard Worker /* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen
1403*a67afe4dSAndroid Build Coastguard Worker * so transparency information would remain just so long as it wasn't
1404*a67afe4dSAndroid Build Coastguard Worker * expanded. This produces unexpected API changes if the set of things
1405*a67afe4dSAndroid Build Coastguard Worker * that do PNG_EXPAND_tRNS changes (perfectly possible given the
1406*a67afe4dSAndroid Build Coastguard Worker * documentation - which says ask for what you want, accept what you
1407*a67afe4dSAndroid Build Coastguard Worker * get.) This makes the behavior consistent from 1.5.4:
1408*a67afe4dSAndroid Build Coastguard Worker */
1409*a67afe4dSAndroid Build Coastguard Worker png_ptr->num_trans = 0;
1410*a67afe4dSAndroid Build Coastguard Worker }
1411*a67afe4dSAndroid Build Coastguard Worker #endif /* STRIP_ALPHA supported, no COMPOSE */
1412*a67afe4dSAndroid Build Coastguard Worker
1413*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
1414*a67afe4dSAndroid Build Coastguard Worker /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA
1415*a67afe4dSAndroid Build Coastguard Worker * settings will have no effect.
1416*a67afe4dSAndroid Build Coastguard Worker */
1417*a67afe4dSAndroid Build Coastguard Worker if (png_gamma_significant(png_ptr->screen_gamma) == 0)
1418*a67afe4dSAndroid Build Coastguard Worker {
1419*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
1420*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
1421*a67afe4dSAndroid Build Coastguard Worker }
1422*a67afe4dSAndroid Build Coastguard Worker #endif
1423*a67afe4dSAndroid Build Coastguard Worker
1424*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1425*a67afe4dSAndroid Build Coastguard Worker /* Make sure the coefficients for the rgb to gray conversion are set
1426*a67afe4dSAndroid Build Coastguard Worker * appropriately.
1427*a67afe4dSAndroid Build Coastguard Worker */
1428*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1429*a67afe4dSAndroid Build Coastguard Worker png_colorspace_set_rgb_coefficients(png_ptr);
1430*a67afe4dSAndroid Build Coastguard Worker #endif
1431*a67afe4dSAndroid Build Coastguard Worker
1432*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1433*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
1434*a67afe4dSAndroid Build Coastguard Worker /* Detect gray background and attempt to enable optimization for
1435*a67afe4dSAndroid Build Coastguard Worker * gray --> RGB case.
1436*a67afe4dSAndroid Build Coastguard Worker *
1437*a67afe4dSAndroid Build Coastguard Worker * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
1438*a67afe4dSAndroid Build Coastguard Worker * RGB_ALPHA (in which case need_expand is superfluous anyway), the
1439*a67afe4dSAndroid Build Coastguard Worker * background color might actually be gray yet not be flagged as such.
1440*a67afe4dSAndroid Build Coastguard Worker * This is not a problem for the current code, which uses
1441*a67afe4dSAndroid Build Coastguard Worker * PNG_BACKGROUND_IS_GRAY only to decide when to do the
1442*a67afe4dSAndroid Build Coastguard Worker * png_do_gray_to_rgb() transformation.
1443*a67afe4dSAndroid Build Coastguard Worker *
1444*a67afe4dSAndroid Build Coastguard Worker * TODO: this code needs to be revised to avoid the complexity and
1445*a67afe4dSAndroid Build Coastguard Worker * interdependencies. The color type of the background should be recorded in
1446*a67afe4dSAndroid Build Coastguard Worker * png_set_background, along with the bit depth, then the code has a record
1447*a67afe4dSAndroid Build Coastguard Worker * of exactly what color space the background is currently in.
1448*a67afe4dSAndroid Build Coastguard Worker */
1449*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
1450*a67afe4dSAndroid Build Coastguard Worker {
1451*a67afe4dSAndroid Build Coastguard Worker /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
1452*a67afe4dSAndroid Build Coastguard Worker * the file was grayscale the background value is gray.
1453*a67afe4dSAndroid Build Coastguard Worker */
1454*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
1455*a67afe4dSAndroid Build Coastguard Worker png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
1456*a67afe4dSAndroid Build Coastguard Worker }
1457*a67afe4dSAndroid Build Coastguard Worker
1458*a67afe4dSAndroid Build Coastguard Worker else if ((png_ptr->transformations & PNG_COMPOSE) != 0)
1459*a67afe4dSAndroid Build Coastguard Worker {
1460*a67afe4dSAndroid Build Coastguard Worker /* PNG_COMPOSE: png_set_background was called with need_expand false,
1461*a67afe4dSAndroid Build Coastguard Worker * so the color is in the color space of the output or png_set_alpha_mode
1462*a67afe4dSAndroid Build Coastguard Worker * was called and the color is black. Ignore RGB_TO_GRAY because that
1463*a67afe4dSAndroid Build Coastguard Worker * happens before GRAY_TO_RGB.
1464*a67afe4dSAndroid Build Coastguard Worker */
1465*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
1466*a67afe4dSAndroid Build Coastguard Worker {
1467*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->background.red == png_ptr->background.green &&
1468*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.red == png_ptr->background.blue)
1469*a67afe4dSAndroid Build Coastguard Worker {
1470*a67afe4dSAndroid Build Coastguard Worker png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
1471*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.gray = png_ptr->background.red;
1472*a67afe4dSAndroid Build Coastguard Worker }
1473*a67afe4dSAndroid Build Coastguard Worker }
1474*a67afe4dSAndroid Build Coastguard Worker }
1475*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_EXPAND && READ_BACKGROUND */
1476*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_GRAY_TO_RGB */
1477*a67afe4dSAndroid Build Coastguard Worker
1478*a67afe4dSAndroid Build Coastguard Worker /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
1479*a67afe4dSAndroid Build Coastguard Worker * can be performed directly on the palette, and some (such as rgb to gray)
1480*a67afe4dSAndroid Build Coastguard Worker * can be optimized inside the palette. This is particularly true of the
1481*a67afe4dSAndroid Build Coastguard Worker * composite (background and alpha) stuff, which can be pretty much all done
1482*a67afe4dSAndroid Build Coastguard Worker * in the palette even if the result is expanded to RGB or gray afterward.
1483*a67afe4dSAndroid Build Coastguard Worker *
1484*a67afe4dSAndroid Build Coastguard Worker * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and
1485*a67afe4dSAndroid Build Coastguard Worker * earlier and the palette stuff is actually handled on the first row. This
1486*a67afe4dSAndroid Build Coastguard Worker * leads to the reported bug that the palette returned by png_get_PLTE is not
1487*a67afe4dSAndroid Build Coastguard Worker * updated.
1488*a67afe4dSAndroid Build Coastguard Worker */
1489*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1490*a67afe4dSAndroid Build Coastguard Worker png_init_palette_transformations(png_ptr);
1491*a67afe4dSAndroid Build Coastguard Worker
1492*a67afe4dSAndroid Build Coastguard Worker else
1493*a67afe4dSAndroid Build Coastguard Worker png_init_rgb_transformations(png_ptr);
1494*a67afe4dSAndroid Build Coastguard Worker
1495*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
1496*a67afe4dSAndroid Build Coastguard Worker defined(PNG_READ_EXPAND_16_SUPPORTED)
1497*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
1498*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_COMPOSE) != 0 &&
1499*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
1500*a67afe4dSAndroid Build Coastguard Worker png_ptr->bit_depth != 16)
1501*a67afe4dSAndroid Build Coastguard Worker {
1502*a67afe4dSAndroid Build Coastguard Worker /* TODO: fix this. Because the expand_16 operation is after the compose
1503*a67afe4dSAndroid Build Coastguard Worker * handling the background color must be 8, not 16, bits deep, but the
1504*a67afe4dSAndroid Build Coastguard Worker * application will supply a 16-bit value so reduce it here.
1505*a67afe4dSAndroid Build Coastguard Worker *
1506*a67afe4dSAndroid Build Coastguard Worker * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at
1507*a67afe4dSAndroid Build Coastguard Worker * present, so that case is ok (until do_expand_16 is moved.)
1508*a67afe4dSAndroid Build Coastguard Worker *
1509*a67afe4dSAndroid Build Coastguard Worker * NOTE: this discards the low 16 bits of the user supplied background
1510*a67afe4dSAndroid Build Coastguard Worker * color, but until expand_16 works properly there is no choice!
1511*a67afe4dSAndroid Build Coastguard Worker */
1512*a67afe4dSAndroid Build Coastguard Worker # define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
1513*a67afe4dSAndroid Build Coastguard Worker CHOP(png_ptr->background.red);
1514*a67afe4dSAndroid Build Coastguard Worker CHOP(png_ptr->background.green);
1515*a67afe4dSAndroid Build Coastguard Worker CHOP(png_ptr->background.blue);
1516*a67afe4dSAndroid Build Coastguard Worker CHOP(png_ptr->background.gray);
1517*a67afe4dSAndroid Build Coastguard Worker # undef CHOP
1518*a67afe4dSAndroid Build Coastguard Worker }
1519*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_BACKGROUND && READ_EXPAND_16 */
1520*a67afe4dSAndroid Build Coastguard Worker
1521*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
1522*a67afe4dSAndroid Build Coastguard Worker (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
1523*a67afe4dSAndroid Build Coastguard Worker defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
1524*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0 &&
1525*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_COMPOSE) != 0 &&
1526*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
1527*a67afe4dSAndroid Build Coastguard Worker png_ptr->bit_depth == 16)
1528*a67afe4dSAndroid Build Coastguard Worker {
1529*a67afe4dSAndroid Build Coastguard Worker /* On the other hand, if a 16-bit file is to be reduced to 8-bits per
1530*a67afe4dSAndroid Build Coastguard Worker * component this will also happen after PNG_COMPOSE and so the background
1531*a67afe4dSAndroid Build Coastguard Worker * color must be pre-expanded here.
1532*a67afe4dSAndroid Build Coastguard Worker *
1533*a67afe4dSAndroid Build Coastguard Worker * TODO: fix this too.
1534*a67afe4dSAndroid Build Coastguard Worker */
1535*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);
1536*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.green =
1537*a67afe4dSAndroid Build Coastguard Worker (png_uint_16)(png_ptr->background.green * 257);
1538*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);
1539*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);
1540*a67afe4dSAndroid Build Coastguard Worker }
1541*a67afe4dSAndroid Build Coastguard Worker #endif
1542*a67afe4dSAndroid Build Coastguard Worker
1543*a67afe4dSAndroid Build Coastguard Worker /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the
1544*a67afe4dSAndroid Build Coastguard Worker * background support (see the comments in scripts/pnglibconf.dfa), this
1545*a67afe4dSAndroid Build Coastguard Worker * allows pre-multiplication of the alpha channel to be implemented as
1546*a67afe4dSAndroid Build Coastguard Worker * compositing on black. This is probably sub-optimal and has been done in
1547*a67afe4dSAndroid Build Coastguard Worker * 1.5.4 betas simply to enable external critique and testing (i.e. to
1548*a67afe4dSAndroid Build Coastguard Worker * implement the new API quickly, without lots of internal changes.)
1549*a67afe4dSAndroid Build Coastguard Worker */
1550*a67afe4dSAndroid Build Coastguard Worker
1551*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
1552*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_READ_BACKGROUND_SUPPORTED
1553*a67afe4dSAndroid Build Coastguard Worker /* Includes ALPHA_MODE */
1554*a67afe4dSAndroid Build Coastguard Worker png_ptr->background_1 = png_ptr->background;
1555*a67afe4dSAndroid Build Coastguard Worker # endif
1556*a67afe4dSAndroid Build Coastguard Worker
1557*a67afe4dSAndroid Build Coastguard Worker /* This needs to change - in the palette image case a whole set of tables are
1558*a67afe4dSAndroid Build Coastguard Worker * built when it would be quicker to just calculate the correct value for
1559*a67afe4dSAndroid Build Coastguard Worker * each palette entry directly. Also, the test is too tricky - why check
1560*a67afe4dSAndroid Build Coastguard Worker * PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that
1561*a67afe4dSAndroid Build Coastguard Worker * PNG_GAMMA is cancelled even if the gamma is known? The test excludes the
1562*a67afe4dSAndroid Build Coastguard Worker * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction
1563*a67afe4dSAndroid Build Coastguard Worker * the gamma tables will not be built even if composition is required on a
1564*a67afe4dSAndroid Build Coastguard Worker * gamma encoded value.
1565*a67afe4dSAndroid Build Coastguard Worker *
1566*a67afe4dSAndroid Build Coastguard Worker * In 1.5.4 this is addressed below by an additional check on the individual
1567*a67afe4dSAndroid Build Coastguard Worker * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
1568*a67afe4dSAndroid Build Coastguard Worker * tables.
1569*a67afe4dSAndroid Build Coastguard Worker */
1570*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_GAMMA) != 0 ||
1571*a67afe4dSAndroid Build Coastguard Worker ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&
1572*a67afe4dSAndroid Build Coastguard Worker (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
1573*a67afe4dSAndroid Build Coastguard Worker png_gamma_significant(png_ptr->screen_gamma) != 0)) ||
1574*a67afe4dSAndroid Build Coastguard Worker ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
1575*a67afe4dSAndroid Build Coastguard Worker (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
1576*a67afe4dSAndroid Build Coastguard Worker png_gamma_significant(png_ptr->screen_gamma) != 0
1577*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_READ_BACKGROUND_SUPPORTED
1578*a67afe4dSAndroid Build Coastguard Worker || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
1579*a67afe4dSAndroid Build Coastguard Worker png_gamma_significant(png_ptr->background_gamma) != 0)
1580*a67afe4dSAndroid Build Coastguard Worker # endif
1581*a67afe4dSAndroid Build Coastguard Worker )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
1582*a67afe4dSAndroid Build Coastguard Worker png_gamma_significant(png_ptr->screen_gamma) != 0))
1583*a67afe4dSAndroid Build Coastguard Worker {
1584*a67afe4dSAndroid Build Coastguard Worker png_build_gamma_table(png_ptr, png_ptr->bit_depth);
1585*a67afe4dSAndroid Build Coastguard Worker
1586*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_BACKGROUND_SUPPORTED
1587*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_COMPOSE) != 0)
1588*a67afe4dSAndroid Build Coastguard Worker {
1589*a67afe4dSAndroid Build Coastguard Worker /* Issue a warning about this combination: because RGB_TO_GRAY is
1590*a67afe4dSAndroid Build Coastguard Worker * optimized to do the gamma transform if present yet do_background has
1591*a67afe4dSAndroid Build Coastguard Worker * to do the same thing if both options are set a
1592*a67afe4dSAndroid Build Coastguard Worker * double-gamma-correction happens. This is true in all versions of
1593*a67afe4dSAndroid Build Coastguard Worker * libpng to date.
1594*a67afe4dSAndroid Build Coastguard Worker */
1595*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
1596*a67afe4dSAndroid Build Coastguard Worker png_warning(png_ptr,
1597*a67afe4dSAndroid Build Coastguard Worker "libpng does not support gamma+background+rgb_to_gray");
1598*a67afe4dSAndroid Build Coastguard Worker
1599*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0)
1600*a67afe4dSAndroid Build Coastguard Worker {
1601*a67afe4dSAndroid Build Coastguard Worker /* We don't get to here unless there is a tRNS chunk with non-opaque
1602*a67afe4dSAndroid Build Coastguard Worker * entries - see the checking code at the start of this function.
1603*a67afe4dSAndroid Build Coastguard Worker */
1604*a67afe4dSAndroid Build Coastguard Worker png_color back, back_1;
1605*a67afe4dSAndroid Build Coastguard Worker png_colorp palette = png_ptr->palette;
1606*a67afe4dSAndroid Build Coastguard Worker int num_palette = png_ptr->num_palette;
1607*a67afe4dSAndroid Build Coastguard Worker int i;
1608*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
1609*a67afe4dSAndroid Build Coastguard Worker {
1610*a67afe4dSAndroid Build Coastguard Worker
1611*a67afe4dSAndroid Build Coastguard Worker back.red = png_ptr->gamma_table[png_ptr->background.red];
1612*a67afe4dSAndroid Build Coastguard Worker back.green = png_ptr->gamma_table[png_ptr->background.green];
1613*a67afe4dSAndroid Build Coastguard Worker back.blue = png_ptr->gamma_table[png_ptr->background.blue];
1614*a67afe4dSAndroid Build Coastguard Worker
1615*a67afe4dSAndroid Build Coastguard Worker back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
1616*a67afe4dSAndroid Build Coastguard Worker back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
1617*a67afe4dSAndroid Build Coastguard Worker back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
1618*a67afe4dSAndroid Build Coastguard Worker }
1619*a67afe4dSAndroid Build Coastguard Worker else
1620*a67afe4dSAndroid Build Coastguard Worker {
1621*a67afe4dSAndroid Build Coastguard Worker png_fixed_point g, gs;
1622*a67afe4dSAndroid Build Coastguard Worker
1623*a67afe4dSAndroid Build Coastguard Worker switch (png_ptr->background_gamma_type)
1624*a67afe4dSAndroid Build Coastguard Worker {
1625*a67afe4dSAndroid Build Coastguard Worker case PNG_BACKGROUND_GAMMA_SCREEN:
1626*a67afe4dSAndroid Build Coastguard Worker g = (png_ptr->screen_gamma);
1627*a67afe4dSAndroid Build Coastguard Worker gs = PNG_FP_1;
1628*a67afe4dSAndroid Build Coastguard Worker break;
1629*a67afe4dSAndroid Build Coastguard Worker
1630*a67afe4dSAndroid Build Coastguard Worker case PNG_BACKGROUND_GAMMA_FILE:
1631*a67afe4dSAndroid Build Coastguard Worker g = png_reciprocal(png_ptr->colorspace.gamma);
1632*a67afe4dSAndroid Build Coastguard Worker gs = png_reciprocal2(png_ptr->colorspace.gamma,
1633*a67afe4dSAndroid Build Coastguard Worker png_ptr->screen_gamma);
1634*a67afe4dSAndroid Build Coastguard Worker break;
1635*a67afe4dSAndroid Build Coastguard Worker
1636*a67afe4dSAndroid Build Coastguard Worker case PNG_BACKGROUND_GAMMA_UNIQUE:
1637*a67afe4dSAndroid Build Coastguard Worker g = png_reciprocal(png_ptr->background_gamma);
1638*a67afe4dSAndroid Build Coastguard Worker gs = png_reciprocal2(png_ptr->background_gamma,
1639*a67afe4dSAndroid Build Coastguard Worker png_ptr->screen_gamma);
1640*a67afe4dSAndroid Build Coastguard Worker break;
1641*a67afe4dSAndroid Build Coastguard Worker default:
1642*a67afe4dSAndroid Build Coastguard Worker g = PNG_FP_1; /* back_1 */
1643*a67afe4dSAndroid Build Coastguard Worker gs = PNG_FP_1; /* back */
1644*a67afe4dSAndroid Build Coastguard Worker break;
1645*a67afe4dSAndroid Build Coastguard Worker }
1646*a67afe4dSAndroid Build Coastguard Worker
1647*a67afe4dSAndroid Build Coastguard Worker if (png_gamma_significant(gs) != 0)
1648*a67afe4dSAndroid Build Coastguard Worker {
1649*a67afe4dSAndroid Build Coastguard Worker back.red = png_gamma_8bit_correct(png_ptr->background.red,
1650*a67afe4dSAndroid Build Coastguard Worker gs);
1651*a67afe4dSAndroid Build Coastguard Worker back.green = png_gamma_8bit_correct(png_ptr->background.green,
1652*a67afe4dSAndroid Build Coastguard Worker gs);
1653*a67afe4dSAndroid Build Coastguard Worker back.blue = png_gamma_8bit_correct(png_ptr->background.blue,
1654*a67afe4dSAndroid Build Coastguard Worker gs);
1655*a67afe4dSAndroid Build Coastguard Worker }
1656*a67afe4dSAndroid Build Coastguard Worker
1657*a67afe4dSAndroid Build Coastguard Worker else
1658*a67afe4dSAndroid Build Coastguard Worker {
1659*a67afe4dSAndroid Build Coastguard Worker back.red = (png_byte)png_ptr->background.red;
1660*a67afe4dSAndroid Build Coastguard Worker back.green = (png_byte)png_ptr->background.green;
1661*a67afe4dSAndroid Build Coastguard Worker back.blue = (png_byte)png_ptr->background.blue;
1662*a67afe4dSAndroid Build Coastguard Worker }
1663*a67afe4dSAndroid Build Coastguard Worker
1664*a67afe4dSAndroid Build Coastguard Worker if (png_gamma_significant(g) != 0)
1665*a67afe4dSAndroid Build Coastguard Worker {
1666*a67afe4dSAndroid Build Coastguard Worker back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
1667*a67afe4dSAndroid Build Coastguard Worker g);
1668*a67afe4dSAndroid Build Coastguard Worker back_1.green = png_gamma_8bit_correct(
1669*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.green, g);
1670*a67afe4dSAndroid Build Coastguard Worker back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,
1671*a67afe4dSAndroid Build Coastguard Worker g);
1672*a67afe4dSAndroid Build Coastguard Worker }
1673*a67afe4dSAndroid Build Coastguard Worker
1674*a67afe4dSAndroid Build Coastguard Worker else
1675*a67afe4dSAndroid Build Coastguard Worker {
1676*a67afe4dSAndroid Build Coastguard Worker back_1.red = (png_byte)png_ptr->background.red;
1677*a67afe4dSAndroid Build Coastguard Worker back_1.green = (png_byte)png_ptr->background.green;
1678*a67afe4dSAndroid Build Coastguard Worker back_1.blue = (png_byte)png_ptr->background.blue;
1679*a67afe4dSAndroid Build Coastguard Worker }
1680*a67afe4dSAndroid Build Coastguard Worker }
1681*a67afe4dSAndroid Build Coastguard Worker
1682*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < num_palette; i++)
1683*a67afe4dSAndroid Build Coastguard Worker {
1684*a67afe4dSAndroid Build Coastguard Worker if (i < (int)png_ptr->num_trans &&
1685*a67afe4dSAndroid Build Coastguard Worker png_ptr->trans_alpha[i] != 0xff)
1686*a67afe4dSAndroid Build Coastguard Worker {
1687*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->trans_alpha[i] == 0)
1688*a67afe4dSAndroid Build Coastguard Worker {
1689*a67afe4dSAndroid Build Coastguard Worker palette[i] = back;
1690*a67afe4dSAndroid Build Coastguard Worker }
1691*a67afe4dSAndroid Build Coastguard Worker else /* if (png_ptr->trans_alpha[i] != 0xff) */
1692*a67afe4dSAndroid Build Coastguard Worker {
1693*a67afe4dSAndroid Build Coastguard Worker png_byte v, w;
1694*a67afe4dSAndroid Build Coastguard Worker
1695*a67afe4dSAndroid Build Coastguard Worker v = png_ptr->gamma_to_1[palette[i].red];
1696*a67afe4dSAndroid Build Coastguard Worker png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
1697*a67afe4dSAndroid Build Coastguard Worker palette[i].red = png_ptr->gamma_from_1[w];
1698*a67afe4dSAndroid Build Coastguard Worker
1699*a67afe4dSAndroid Build Coastguard Worker v = png_ptr->gamma_to_1[palette[i].green];
1700*a67afe4dSAndroid Build Coastguard Worker png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
1701*a67afe4dSAndroid Build Coastguard Worker palette[i].green = png_ptr->gamma_from_1[w];
1702*a67afe4dSAndroid Build Coastguard Worker
1703*a67afe4dSAndroid Build Coastguard Worker v = png_ptr->gamma_to_1[palette[i].blue];
1704*a67afe4dSAndroid Build Coastguard Worker png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
1705*a67afe4dSAndroid Build Coastguard Worker palette[i].blue = png_ptr->gamma_from_1[w];
1706*a67afe4dSAndroid Build Coastguard Worker }
1707*a67afe4dSAndroid Build Coastguard Worker }
1708*a67afe4dSAndroid Build Coastguard Worker else
1709*a67afe4dSAndroid Build Coastguard Worker {
1710*a67afe4dSAndroid Build Coastguard Worker palette[i].red = png_ptr->gamma_table[palette[i].red];
1711*a67afe4dSAndroid Build Coastguard Worker palette[i].green = png_ptr->gamma_table[palette[i].green];
1712*a67afe4dSAndroid Build Coastguard Worker palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1713*a67afe4dSAndroid Build Coastguard Worker }
1714*a67afe4dSAndroid Build Coastguard Worker }
1715*a67afe4dSAndroid Build Coastguard Worker
1716*a67afe4dSAndroid Build Coastguard Worker /* Prevent the transformations being done again.
1717*a67afe4dSAndroid Build Coastguard Worker *
1718*a67afe4dSAndroid Build Coastguard Worker * NOTE: this is highly dubious; it removes the transformations in
1719*a67afe4dSAndroid Build Coastguard Worker * place. This seems inconsistent with the general treatment of the
1720*a67afe4dSAndroid Build Coastguard Worker * transformations elsewhere.
1721*a67afe4dSAndroid Build Coastguard Worker */
1722*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
1723*a67afe4dSAndroid Build Coastguard Worker } /* color_type == PNG_COLOR_TYPE_PALETTE */
1724*a67afe4dSAndroid Build Coastguard Worker
1725*a67afe4dSAndroid Build Coastguard Worker /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1726*a67afe4dSAndroid Build Coastguard Worker else /* color_type != PNG_COLOR_TYPE_PALETTE */
1727*a67afe4dSAndroid Build Coastguard Worker {
1728*a67afe4dSAndroid Build Coastguard Worker int gs_sig, g_sig;
1729*a67afe4dSAndroid Build Coastguard Worker png_fixed_point g = PNG_FP_1; /* Correction to linear */
1730*a67afe4dSAndroid Build Coastguard Worker png_fixed_point gs = PNG_FP_1; /* Correction to screen */
1731*a67afe4dSAndroid Build Coastguard Worker
1732*a67afe4dSAndroid Build Coastguard Worker switch (png_ptr->background_gamma_type)
1733*a67afe4dSAndroid Build Coastguard Worker {
1734*a67afe4dSAndroid Build Coastguard Worker case PNG_BACKGROUND_GAMMA_SCREEN:
1735*a67afe4dSAndroid Build Coastguard Worker g = png_ptr->screen_gamma;
1736*a67afe4dSAndroid Build Coastguard Worker /* gs = PNG_FP_1; */
1737*a67afe4dSAndroid Build Coastguard Worker break;
1738*a67afe4dSAndroid Build Coastguard Worker
1739*a67afe4dSAndroid Build Coastguard Worker case PNG_BACKGROUND_GAMMA_FILE:
1740*a67afe4dSAndroid Build Coastguard Worker g = png_reciprocal(png_ptr->colorspace.gamma);
1741*a67afe4dSAndroid Build Coastguard Worker gs = png_reciprocal2(png_ptr->colorspace.gamma,
1742*a67afe4dSAndroid Build Coastguard Worker png_ptr->screen_gamma);
1743*a67afe4dSAndroid Build Coastguard Worker break;
1744*a67afe4dSAndroid Build Coastguard Worker
1745*a67afe4dSAndroid Build Coastguard Worker case PNG_BACKGROUND_GAMMA_UNIQUE:
1746*a67afe4dSAndroid Build Coastguard Worker g = png_reciprocal(png_ptr->background_gamma);
1747*a67afe4dSAndroid Build Coastguard Worker gs = png_reciprocal2(png_ptr->background_gamma,
1748*a67afe4dSAndroid Build Coastguard Worker png_ptr->screen_gamma);
1749*a67afe4dSAndroid Build Coastguard Worker break;
1750*a67afe4dSAndroid Build Coastguard Worker
1751*a67afe4dSAndroid Build Coastguard Worker default:
1752*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "invalid background gamma type");
1753*a67afe4dSAndroid Build Coastguard Worker }
1754*a67afe4dSAndroid Build Coastguard Worker
1755*a67afe4dSAndroid Build Coastguard Worker g_sig = png_gamma_significant(g);
1756*a67afe4dSAndroid Build Coastguard Worker gs_sig = png_gamma_significant(gs);
1757*a67afe4dSAndroid Build Coastguard Worker
1758*a67afe4dSAndroid Build Coastguard Worker if (g_sig != 0)
1759*a67afe4dSAndroid Build Coastguard Worker png_ptr->background_1.gray = png_gamma_correct(png_ptr,
1760*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.gray, g);
1761*a67afe4dSAndroid Build Coastguard Worker
1762*a67afe4dSAndroid Build Coastguard Worker if (gs_sig != 0)
1763*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.gray = png_gamma_correct(png_ptr,
1764*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.gray, gs);
1765*a67afe4dSAndroid Build Coastguard Worker
1766*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->background.red != png_ptr->background.green) ||
1767*a67afe4dSAndroid Build Coastguard Worker (png_ptr->background.red != png_ptr->background.blue) ||
1768*a67afe4dSAndroid Build Coastguard Worker (png_ptr->background.red != png_ptr->background.gray))
1769*a67afe4dSAndroid Build Coastguard Worker {
1770*a67afe4dSAndroid Build Coastguard Worker /* RGB or RGBA with color background */
1771*a67afe4dSAndroid Build Coastguard Worker if (g_sig != 0)
1772*a67afe4dSAndroid Build Coastguard Worker {
1773*a67afe4dSAndroid Build Coastguard Worker png_ptr->background_1.red = png_gamma_correct(png_ptr,
1774*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.red, g);
1775*a67afe4dSAndroid Build Coastguard Worker
1776*a67afe4dSAndroid Build Coastguard Worker png_ptr->background_1.green = png_gamma_correct(png_ptr,
1777*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.green, g);
1778*a67afe4dSAndroid Build Coastguard Worker
1779*a67afe4dSAndroid Build Coastguard Worker png_ptr->background_1.blue = png_gamma_correct(png_ptr,
1780*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.blue, g);
1781*a67afe4dSAndroid Build Coastguard Worker }
1782*a67afe4dSAndroid Build Coastguard Worker
1783*a67afe4dSAndroid Build Coastguard Worker if (gs_sig != 0)
1784*a67afe4dSAndroid Build Coastguard Worker {
1785*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.red = png_gamma_correct(png_ptr,
1786*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.red, gs);
1787*a67afe4dSAndroid Build Coastguard Worker
1788*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.green = png_gamma_correct(png_ptr,
1789*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.green, gs);
1790*a67afe4dSAndroid Build Coastguard Worker
1791*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.blue = png_gamma_correct(png_ptr,
1792*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.blue, gs);
1793*a67afe4dSAndroid Build Coastguard Worker }
1794*a67afe4dSAndroid Build Coastguard Worker }
1795*a67afe4dSAndroid Build Coastguard Worker
1796*a67afe4dSAndroid Build Coastguard Worker else
1797*a67afe4dSAndroid Build Coastguard Worker {
1798*a67afe4dSAndroid Build Coastguard Worker /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
1799*a67afe4dSAndroid Build Coastguard Worker png_ptr->background_1.red = png_ptr->background_1.green
1800*a67afe4dSAndroid Build Coastguard Worker = png_ptr->background_1.blue = png_ptr->background_1.gray;
1801*a67afe4dSAndroid Build Coastguard Worker
1802*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.red = png_ptr->background.green
1803*a67afe4dSAndroid Build Coastguard Worker = png_ptr->background.blue = png_ptr->background.gray;
1804*a67afe4dSAndroid Build Coastguard Worker }
1805*a67afe4dSAndroid Build Coastguard Worker
1806*a67afe4dSAndroid Build Coastguard Worker /* The background is now in screen gamma: */
1807*a67afe4dSAndroid Build Coastguard Worker png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;
1808*a67afe4dSAndroid Build Coastguard Worker } /* color_type != PNG_COLOR_TYPE_PALETTE */
1809*a67afe4dSAndroid Build Coastguard Worker }/* png_ptr->transformations & PNG_BACKGROUND */
1810*a67afe4dSAndroid Build Coastguard Worker
1811*a67afe4dSAndroid Build Coastguard Worker else
1812*a67afe4dSAndroid Build Coastguard Worker /* Transformation does not include PNG_BACKGROUND */
1813*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_BACKGROUND */
1814*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
1815*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1816*a67afe4dSAndroid Build Coastguard Worker /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
1817*a67afe4dSAndroid Build Coastguard Worker && ((png_ptr->transformations & PNG_EXPAND) == 0 ||
1818*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
1819*a67afe4dSAndroid Build Coastguard Worker #endif
1820*a67afe4dSAndroid Build Coastguard Worker )
1821*a67afe4dSAndroid Build Coastguard Worker {
1822*a67afe4dSAndroid Build Coastguard Worker png_colorp palette = png_ptr->palette;
1823*a67afe4dSAndroid Build Coastguard Worker int num_palette = png_ptr->num_palette;
1824*a67afe4dSAndroid Build Coastguard Worker int i;
1825*a67afe4dSAndroid Build Coastguard Worker
1826*a67afe4dSAndroid Build Coastguard Worker /* NOTE: there are other transformations that should probably be in
1827*a67afe4dSAndroid Build Coastguard Worker * here too.
1828*a67afe4dSAndroid Build Coastguard Worker */
1829*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < num_palette; i++)
1830*a67afe4dSAndroid Build Coastguard Worker {
1831*a67afe4dSAndroid Build Coastguard Worker palette[i].red = png_ptr->gamma_table[palette[i].red];
1832*a67afe4dSAndroid Build Coastguard Worker palette[i].green = png_ptr->gamma_table[palette[i].green];
1833*a67afe4dSAndroid Build Coastguard Worker palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1834*a67afe4dSAndroid Build Coastguard Worker }
1835*a67afe4dSAndroid Build Coastguard Worker
1836*a67afe4dSAndroid Build Coastguard Worker /* Done the gamma correction. */
1837*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_GAMMA;
1838*a67afe4dSAndroid Build Coastguard Worker } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
1839*a67afe4dSAndroid Build Coastguard Worker }
1840*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_BACKGROUND_SUPPORTED
1841*a67afe4dSAndroid Build Coastguard Worker else
1842*a67afe4dSAndroid Build Coastguard Worker #endif
1843*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_GAMMA */
1844*a67afe4dSAndroid Build Coastguard Worker
1845*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_BACKGROUND_SUPPORTED
1846*a67afe4dSAndroid Build Coastguard Worker /* No GAMMA transformation (see the hanging else 4 lines above) */
1847*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
1848*a67afe4dSAndroid Build Coastguard Worker (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
1849*a67afe4dSAndroid Build Coastguard Worker {
1850*a67afe4dSAndroid Build Coastguard Worker int i;
1851*a67afe4dSAndroid Build Coastguard Worker int istop = (int)png_ptr->num_trans;
1852*a67afe4dSAndroid Build Coastguard Worker png_color back;
1853*a67afe4dSAndroid Build Coastguard Worker png_colorp palette = png_ptr->palette;
1854*a67afe4dSAndroid Build Coastguard Worker
1855*a67afe4dSAndroid Build Coastguard Worker back.red = (png_byte)png_ptr->background.red;
1856*a67afe4dSAndroid Build Coastguard Worker back.green = (png_byte)png_ptr->background.green;
1857*a67afe4dSAndroid Build Coastguard Worker back.blue = (png_byte)png_ptr->background.blue;
1858*a67afe4dSAndroid Build Coastguard Worker
1859*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < istop; i++)
1860*a67afe4dSAndroid Build Coastguard Worker {
1861*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->trans_alpha[i] == 0)
1862*a67afe4dSAndroid Build Coastguard Worker {
1863*a67afe4dSAndroid Build Coastguard Worker palette[i] = back;
1864*a67afe4dSAndroid Build Coastguard Worker }
1865*a67afe4dSAndroid Build Coastguard Worker
1866*a67afe4dSAndroid Build Coastguard Worker else if (png_ptr->trans_alpha[i] != 0xff)
1867*a67afe4dSAndroid Build Coastguard Worker {
1868*a67afe4dSAndroid Build Coastguard Worker /* The png_composite() macro is defined in png.h */
1869*a67afe4dSAndroid Build Coastguard Worker png_composite(palette[i].red, palette[i].red,
1870*a67afe4dSAndroid Build Coastguard Worker png_ptr->trans_alpha[i], back.red);
1871*a67afe4dSAndroid Build Coastguard Worker
1872*a67afe4dSAndroid Build Coastguard Worker png_composite(palette[i].green, palette[i].green,
1873*a67afe4dSAndroid Build Coastguard Worker png_ptr->trans_alpha[i], back.green);
1874*a67afe4dSAndroid Build Coastguard Worker
1875*a67afe4dSAndroid Build Coastguard Worker png_composite(palette[i].blue, palette[i].blue,
1876*a67afe4dSAndroid Build Coastguard Worker png_ptr->trans_alpha[i], back.blue);
1877*a67afe4dSAndroid Build Coastguard Worker }
1878*a67afe4dSAndroid Build Coastguard Worker }
1879*a67afe4dSAndroid Build Coastguard Worker
1880*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_COMPOSE;
1881*a67afe4dSAndroid Build Coastguard Worker }
1882*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_BACKGROUND */
1883*a67afe4dSAndroid Build Coastguard Worker
1884*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_SHIFT_SUPPORTED
1885*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_SHIFT) != 0 &&
1886*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_EXPAND) == 0 &&
1887*a67afe4dSAndroid Build Coastguard Worker (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
1888*a67afe4dSAndroid Build Coastguard Worker {
1889*a67afe4dSAndroid Build Coastguard Worker int i;
1890*a67afe4dSAndroid Build Coastguard Worker int istop = png_ptr->num_palette;
1891*a67afe4dSAndroid Build Coastguard Worker int shift = 8 - png_ptr->sig_bit.red;
1892*a67afe4dSAndroid Build Coastguard Worker
1893*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations &= ~PNG_SHIFT;
1894*a67afe4dSAndroid Build Coastguard Worker
1895*a67afe4dSAndroid Build Coastguard Worker /* significant bits can be in the range 1 to 7 for a meaningful result, if
1896*a67afe4dSAndroid Build Coastguard Worker * the number of significant bits is 0 then no shift is done (this is an
1897*a67afe4dSAndroid Build Coastguard Worker * error condition which is silently ignored.)
1898*a67afe4dSAndroid Build Coastguard Worker */
1899*a67afe4dSAndroid Build Coastguard Worker if (shift > 0 && shift < 8)
1900*a67afe4dSAndroid Build Coastguard Worker for (i=0; i<istop; ++i)
1901*a67afe4dSAndroid Build Coastguard Worker {
1902*a67afe4dSAndroid Build Coastguard Worker int component = png_ptr->palette[i].red;
1903*a67afe4dSAndroid Build Coastguard Worker
1904*a67afe4dSAndroid Build Coastguard Worker component >>= shift;
1905*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette[i].red = (png_byte)component;
1906*a67afe4dSAndroid Build Coastguard Worker }
1907*a67afe4dSAndroid Build Coastguard Worker
1908*a67afe4dSAndroid Build Coastguard Worker shift = 8 - png_ptr->sig_bit.green;
1909*a67afe4dSAndroid Build Coastguard Worker if (shift > 0 && shift < 8)
1910*a67afe4dSAndroid Build Coastguard Worker for (i=0; i<istop; ++i)
1911*a67afe4dSAndroid Build Coastguard Worker {
1912*a67afe4dSAndroid Build Coastguard Worker int component = png_ptr->palette[i].green;
1913*a67afe4dSAndroid Build Coastguard Worker
1914*a67afe4dSAndroid Build Coastguard Worker component >>= shift;
1915*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette[i].green = (png_byte)component;
1916*a67afe4dSAndroid Build Coastguard Worker }
1917*a67afe4dSAndroid Build Coastguard Worker
1918*a67afe4dSAndroid Build Coastguard Worker shift = 8 - png_ptr->sig_bit.blue;
1919*a67afe4dSAndroid Build Coastguard Worker if (shift > 0 && shift < 8)
1920*a67afe4dSAndroid Build Coastguard Worker for (i=0; i<istop; ++i)
1921*a67afe4dSAndroid Build Coastguard Worker {
1922*a67afe4dSAndroid Build Coastguard Worker int component = png_ptr->palette[i].blue;
1923*a67afe4dSAndroid Build Coastguard Worker
1924*a67afe4dSAndroid Build Coastguard Worker component >>= shift;
1925*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette[i].blue = (png_byte)component;
1926*a67afe4dSAndroid Build Coastguard Worker }
1927*a67afe4dSAndroid Build Coastguard Worker }
1928*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_SHIFT */
1929*a67afe4dSAndroid Build Coastguard Worker }
1930*a67afe4dSAndroid Build Coastguard Worker
1931*a67afe4dSAndroid Build Coastguard Worker /* Modify the info structure to reflect the transformations. The
1932*a67afe4dSAndroid Build Coastguard Worker * info should be updated so a PNG file could be written with it,
1933*a67afe4dSAndroid Build Coastguard Worker * assuming the transformations result in valid PNG data.
1934*a67afe4dSAndroid Build Coastguard Worker */
1935*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_read_transform_info(png_structrp png_ptr,png_inforp info_ptr)1936*a67afe4dSAndroid Build Coastguard Worker png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
1937*a67afe4dSAndroid Build Coastguard Worker {
1938*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_read_transform_info");
1939*a67afe4dSAndroid Build Coastguard Worker
1940*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_EXPAND_SUPPORTED
1941*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_EXPAND) != 0)
1942*a67afe4dSAndroid Build Coastguard Worker {
1943*a67afe4dSAndroid Build Coastguard Worker if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1944*a67afe4dSAndroid Build Coastguard Worker {
1945*a67afe4dSAndroid Build Coastguard Worker /* This check must match what actually happens in
1946*a67afe4dSAndroid Build Coastguard Worker * png_do_expand_palette; if it ever checks the tRNS chunk to see if
1947*a67afe4dSAndroid Build Coastguard Worker * it is all opaque we must do the same (at present it does not.)
1948*a67afe4dSAndroid Build Coastguard Worker */
1949*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->num_trans > 0)
1950*a67afe4dSAndroid Build Coastguard Worker info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1951*a67afe4dSAndroid Build Coastguard Worker
1952*a67afe4dSAndroid Build Coastguard Worker else
1953*a67afe4dSAndroid Build Coastguard Worker info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1954*a67afe4dSAndroid Build Coastguard Worker
1955*a67afe4dSAndroid Build Coastguard Worker info_ptr->bit_depth = 8;
1956*a67afe4dSAndroid Build Coastguard Worker info_ptr->num_trans = 0;
1957*a67afe4dSAndroid Build Coastguard Worker
1958*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->palette == NULL)
1959*a67afe4dSAndroid Build Coastguard Worker png_error (png_ptr, "Palette is NULL in indexed image");
1960*a67afe4dSAndroid Build Coastguard Worker }
1961*a67afe4dSAndroid Build Coastguard Worker else
1962*a67afe4dSAndroid Build Coastguard Worker {
1963*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->num_trans != 0)
1964*a67afe4dSAndroid Build Coastguard Worker {
1965*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
1966*a67afe4dSAndroid Build Coastguard Worker info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1967*a67afe4dSAndroid Build Coastguard Worker }
1968*a67afe4dSAndroid Build Coastguard Worker if (info_ptr->bit_depth < 8)
1969*a67afe4dSAndroid Build Coastguard Worker info_ptr->bit_depth = 8;
1970*a67afe4dSAndroid Build Coastguard Worker
1971*a67afe4dSAndroid Build Coastguard Worker info_ptr->num_trans = 0;
1972*a67afe4dSAndroid Build Coastguard Worker }
1973*a67afe4dSAndroid Build Coastguard Worker }
1974*a67afe4dSAndroid Build Coastguard Worker #endif
1975*a67afe4dSAndroid Build Coastguard Worker
1976*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
1977*a67afe4dSAndroid Build Coastguard Worker defined(PNG_READ_ALPHA_MODE_SUPPORTED)
1978*a67afe4dSAndroid Build Coastguard Worker /* The following is almost certainly wrong unless the background value is in
1979*a67afe4dSAndroid Build Coastguard Worker * the screen space!
1980*a67afe4dSAndroid Build Coastguard Worker */
1981*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_COMPOSE) != 0)
1982*a67afe4dSAndroid Build Coastguard Worker info_ptr->background = png_ptr->background;
1983*a67afe4dSAndroid Build Coastguard Worker #endif
1984*a67afe4dSAndroid Build Coastguard Worker
1985*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
1986*a67afe4dSAndroid Build Coastguard Worker /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
1987*a67afe4dSAndroid Build Coastguard Worker * however it seems that the code in png_init_read_transformations, which has
1988*a67afe4dSAndroid Build Coastguard Worker * been called before this from png_read_update_info->png_read_start_row
1989*a67afe4dSAndroid Build Coastguard Worker * sometimes does the gamma transform and cancels the flag.
1990*a67afe4dSAndroid Build Coastguard Worker *
1991*a67afe4dSAndroid Build Coastguard Worker * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
1992*a67afe4dSAndroid Build Coastguard Worker * the screen_gamma value. The following probably results in weirdness if
1993*a67afe4dSAndroid Build Coastguard Worker * the info_ptr is used by the app after the rows have been read.
1994*a67afe4dSAndroid Build Coastguard Worker */
1995*a67afe4dSAndroid Build Coastguard Worker info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
1996*a67afe4dSAndroid Build Coastguard Worker #endif
1997*a67afe4dSAndroid Build Coastguard Worker
1998*a67afe4dSAndroid Build Coastguard Worker if (info_ptr->bit_depth == 16)
1999*a67afe4dSAndroid Build Coastguard Worker {
2000*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_READ_16BIT_SUPPORTED
2001*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2002*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
2003*a67afe4dSAndroid Build Coastguard Worker info_ptr->bit_depth = 8;
2004*a67afe4dSAndroid Build Coastguard Worker # endif
2005*a67afe4dSAndroid Build Coastguard Worker
2006*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2007*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_16_TO_8) != 0)
2008*a67afe4dSAndroid Build Coastguard Worker info_ptr->bit_depth = 8;
2009*a67afe4dSAndroid Build Coastguard Worker # endif
2010*a67afe4dSAndroid Build Coastguard Worker
2011*a67afe4dSAndroid Build Coastguard Worker # else
2012*a67afe4dSAndroid Build Coastguard Worker /* No 16-bit support: force chopping 16-bit input down to 8, in this case
2013*a67afe4dSAndroid Build Coastguard Worker * the app program can chose if both APIs are available by setting the
2014*a67afe4dSAndroid Build Coastguard Worker * correct scaling to use.
2015*a67afe4dSAndroid Build Coastguard Worker */
2016*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2017*a67afe4dSAndroid Build Coastguard Worker /* For compatibility with previous versions use the strip method by
2018*a67afe4dSAndroid Build Coastguard Worker * default. This code works because if PNG_SCALE_16_TO_8 is already
2019*a67afe4dSAndroid Build Coastguard Worker * set the code below will do that in preference to the chop.
2020*a67afe4dSAndroid Build Coastguard Worker */
2021*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_16_TO_8;
2022*a67afe4dSAndroid Build Coastguard Worker info_ptr->bit_depth = 8;
2023*a67afe4dSAndroid Build Coastguard Worker # else
2024*a67afe4dSAndroid Build Coastguard Worker
2025*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2026*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations |= PNG_SCALE_16_TO_8;
2027*a67afe4dSAndroid Build Coastguard Worker info_ptr->bit_depth = 8;
2028*a67afe4dSAndroid Build Coastguard Worker # else
2029*a67afe4dSAndroid Build Coastguard Worker
2030*a67afe4dSAndroid Build Coastguard Worker CONFIGURATION ERROR: you must enable at least one 16 to 8 method
2031*a67afe4dSAndroid Build Coastguard Worker # endif
2032*a67afe4dSAndroid Build Coastguard Worker # endif
2033*a67afe4dSAndroid Build Coastguard Worker #endif /* !READ_16BIT */
2034*a67afe4dSAndroid Build Coastguard Worker }
2035*a67afe4dSAndroid Build Coastguard Worker
2036*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2037*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
2038*a67afe4dSAndroid Build Coastguard Worker info_ptr->color_type = (png_byte)(info_ptr->color_type |
2039*a67afe4dSAndroid Build Coastguard Worker PNG_COLOR_MASK_COLOR);
2040*a67afe4dSAndroid Build Coastguard Worker #endif
2041*a67afe4dSAndroid Build Coastguard Worker
2042*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2043*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
2044*a67afe4dSAndroid Build Coastguard Worker info_ptr->color_type = (png_byte)(info_ptr->color_type &
2045*a67afe4dSAndroid Build Coastguard Worker ~PNG_COLOR_MASK_COLOR);
2046*a67afe4dSAndroid Build Coastguard Worker #endif
2047*a67afe4dSAndroid Build Coastguard Worker
2048*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_QUANTIZE_SUPPORTED
2049*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
2050*a67afe4dSAndroid Build Coastguard Worker {
2051*a67afe4dSAndroid Build Coastguard Worker if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2052*a67afe4dSAndroid Build Coastguard Worker (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
2053*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette_lookup != 0 && info_ptr->bit_depth == 8)
2054*a67afe4dSAndroid Build Coastguard Worker {
2055*a67afe4dSAndroid Build Coastguard Worker info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
2056*a67afe4dSAndroid Build Coastguard Worker }
2057*a67afe4dSAndroid Build Coastguard Worker }
2058*a67afe4dSAndroid Build Coastguard Worker #endif
2059*a67afe4dSAndroid Build Coastguard Worker
2060*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_EXPAND_16_SUPPORTED
2061*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
2062*a67afe4dSAndroid Build Coastguard Worker info_ptr->bit_depth == 8 &&
2063*a67afe4dSAndroid Build Coastguard Worker info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
2064*a67afe4dSAndroid Build Coastguard Worker {
2065*a67afe4dSAndroid Build Coastguard Worker info_ptr->bit_depth = 16;
2066*a67afe4dSAndroid Build Coastguard Worker }
2067*a67afe4dSAndroid Build Coastguard Worker #endif
2068*a67afe4dSAndroid Build Coastguard Worker
2069*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_PACK_SUPPORTED
2070*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_PACK) != 0 &&
2071*a67afe4dSAndroid Build Coastguard Worker (info_ptr->bit_depth < 8))
2072*a67afe4dSAndroid Build Coastguard Worker info_ptr->bit_depth = 8;
2073*a67afe4dSAndroid Build Coastguard Worker #endif
2074*a67afe4dSAndroid Build Coastguard Worker
2075*a67afe4dSAndroid Build Coastguard Worker if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2076*a67afe4dSAndroid Build Coastguard Worker info_ptr->channels = 1;
2077*a67afe4dSAndroid Build Coastguard Worker
2078*a67afe4dSAndroid Build Coastguard Worker else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
2079*a67afe4dSAndroid Build Coastguard Worker info_ptr->channels = 3;
2080*a67afe4dSAndroid Build Coastguard Worker
2081*a67afe4dSAndroid Build Coastguard Worker else
2082*a67afe4dSAndroid Build Coastguard Worker info_ptr->channels = 1;
2083*a67afe4dSAndroid Build Coastguard Worker
2084*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
2085*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0)
2086*a67afe4dSAndroid Build Coastguard Worker {
2087*a67afe4dSAndroid Build Coastguard Worker info_ptr->color_type = (png_byte)(info_ptr->color_type &
2088*a67afe4dSAndroid Build Coastguard Worker ~PNG_COLOR_MASK_ALPHA);
2089*a67afe4dSAndroid Build Coastguard Worker info_ptr->num_trans = 0;
2090*a67afe4dSAndroid Build Coastguard Worker }
2091*a67afe4dSAndroid Build Coastguard Worker #endif
2092*a67afe4dSAndroid Build Coastguard Worker
2093*a67afe4dSAndroid Build Coastguard Worker if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
2094*a67afe4dSAndroid Build Coastguard Worker info_ptr->channels++;
2095*a67afe4dSAndroid Build Coastguard Worker
2096*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_FILLER_SUPPORTED
2097*a67afe4dSAndroid Build Coastguard Worker /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
2098*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_FILLER) != 0 &&
2099*a67afe4dSAndroid Build Coastguard Worker (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
2100*a67afe4dSAndroid Build Coastguard Worker info_ptr->color_type == PNG_COLOR_TYPE_GRAY))
2101*a67afe4dSAndroid Build Coastguard Worker {
2102*a67afe4dSAndroid Build Coastguard Worker info_ptr->channels++;
2103*a67afe4dSAndroid Build Coastguard Worker /* If adding a true alpha channel not just filler */
2104*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_ADD_ALPHA) != 0)
2105*a67afe4dSAndroid Build Coastguard Worker info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
2106*a67afe4dSAndroid Build Coastguard Worker }
2107*a67afe4dSAndroid Build Coastguard Worker #endif
2108*a67afe4dSAndroid Build Coastguard Worker
2109*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
2110*a67afe4dSAndroid Build Coastguard Worker defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
2111*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
2112*a67afe4dSAndroid Build Coastguard Worker {
2113*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->user_transform_depth != 0)
2114*a67afe4dSAndroid Build Coastguard Worker info_ptr->bit_depth = png_ptr->user_transform_depth;
2115*a67afe4dSAndroid Build Coastguard Worker
2116*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->user_transform_channels != 0)
2117*a67afe4dSAndroid Build Coastguard Worker info_ptr->channels = png_ptr->user_transform_channels;
2118*a67afe4dSAndroid Build Coastguard Worker }
2119*a67afe4dSAndroid Build Coastguard Worker #endif
2120*a67afe4dSAndroid Build Coastguard Worker
2121*a67afe4dSAndroid Build Coastguard Worker info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
2122*a67afe4dSAndroid Build Coastguard Worker info_ptr->bit_depth);
2123*a67afe4dSAndroid Build Coastguard Worker
2124*a67afe4dSAndroid Build Coastguard Worker info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
2125*a67afe4dSAndroid Build Coastguard Worker
2126*a67afe4dSAndroid Build Coastguard Worker /* Adding in 1.5.4: cache the above value in png_struct so that we can later
2127*a67afe4dSAndroid Build Coastguard Worker * check in png_rowbytes that the user buffer won't get overwritten. Note
2128*a67afe4dSAndroid Build Coastguard Worker * that the field is not always set - if png_read_update_info isn't called
2129*a67afe4dSAndroid Build Coastguard Worker * the application has to either not do any transforms or get the calculation
2130*a67afe4dSAndroid Build Coastguard Worker * right itself.
2131*a67afe4dSAndroid Build Coastguard Worker */
2132*a67afe4dSAndroid Build Coastguard Worker png_ptr->info_rowbytes = info_ptr->rowbytes;
2133*a67afe4dSAndroid Build Coastguard Worker
2134*a67afe4dSAndroid Build Coastguard Worker #ifndef PNG_READ_EXPAND_SUPPORTED
2135*a67afe4dSAndroid Build Coastguard Worker if (png_ptr != NULL)
2136*a67afe4dSAndroid Build Coastguard Worker return;
2137*a67afe4dSAndroid Build Coastguard Worker #endif
2138*a67afe4dSAndroid Build Coastguard Worker }
2139*a67afe4dSAndroid Build Coastguard Worker
2140*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_PACK_SUPPORTED
2141*a67afe4dSAndroid Build Coastguard Worker /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
2142*a67afe4dSAndroid Build Coastguard Worker * without changing the actual values. Thus, if you had a row with
2143*a67afe4dSAndroid Build Coastguard Worker * a bit depth of 1, you would end up with bytes that only contained
2144*a67afe4dSAndroid Build Coastguard Worker * the numbers 0 or 1. If you would rather they contain 0 and 255, use
2145*a67afe4dSAndroid Build Coastguard Worker * png_do_shift() after this.
2146*a67afe4dSAndroid Build Coastguard Worker */
2147*a67afe4dSAndroid Build Coastguard Worker static void
png_do_unpack(png_row_infop row_info,png_bytep row)2148*a67afe4dSAndroid Build Coastguard Worker png_do_unpack(png_row_infop row_info, png_bytep row)
2149*a67afe4dSAndroid Build Coastguard Worker {
2150*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_unpack");
2151*a67afe4dSAndroid Build Coastguard Worker
2152*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth < 8)
2153*a67afe4dSAndroid Build Coastguard Worker {
2154*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
2155*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width=row_info->width;
2156*a67afe4dSAndroid Build Coastguard Worker
2157*a67afe4dSAndroid Build Coastguard Worker switch (row_info->bit_depth)
2158*a67afe4dSAndroid Build Coastguard Worker {
2159*a67afe4dSAndroid Build Coastguard Worker case 1:
2160*a67afe4dSAndroid Build Coastguard Worker {
2161*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)((row_width - 1) >> 3);
2162*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = row + (size_t)row_width - 1;
2163*a67afe4dSAndroid Build Coastguard Worker png_uint_32 shift = 7U - ((row_width + 7U) & 0x07);
2164*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2165*a67afe4dSAndroid Build Coastguard Worker {
2166*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)((*sp >> shift) & 0x01);
2167*a67afe4dSAndroid Build Coastguard Worker
2168*a67afe4dSAndroid Build Coastguard Worker if (shift == 7)
2169*a67afe4dSAndroid Build Coastguard Worker {
2170*a67afe4dSAndroid Build Coastguard Worker shift = 0;
2171*a67afe4dSAndroid Build Coastguard Worker sp--;
2172*a67afe4dSAndroid Build Coastguard Worker }
2173*a67afe4dSAndroid Build Coastguard Worker
2174*a67afe4dSAndroid Build Coastguard Worker else
2175*a67afe4dSAndroid Build Coastguard Worker shift++;
2176*a67afe4dSAndroid Build Coastguard Worker
2177*a67afe4dSAndroid Build Coastguard Worker dp--;
2178*a67afe4dSAndroid Build Coastguard Worker }
2179*a67afe4dSAndroid Build Coastguard Worker break;
2180*a67afe4dSAndroid Build Coastguard Worker }
2181*a67afe4dSAndroid Build Coastguard Worker
2182*a67afe4dSAndroid Build Coastguard Worker case 2:
2183*a67afe4dSAndroid Build Coastguard Worker {
2184*a67afe4dSAndroid Build Coastguard Worker
2185*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)((row_width - 1) >> 2);
2186*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = row + (size_t)row_width - 1;
2187*a67afe4dSAndroid Build Coastguard Worker png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1);
2188*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2189*a67afe4dSAndroid Build Coastguard Worker {
2190*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)((*sp >> shift) & 0x03);
2191*a67afe4dSAndroid Build Coastguard Worker
2192*a67afe4dSAndroid Build Coastguard Worker if (shift == 6)
2193*a67afe4dSAndroid Build Coastguard Worker {
2194*a67afe4dSAndroid Build Coastguard Worker shift = 0;
2195*a67afe4dSAndroid Build Coastguard Worker sp--;
2196*a67afe4dSAndroid Build Coastguard Worker }
2197*a67afe4dSAndroid Build Coastguard Worker
2198*a67afe4dSAndroid Build Coastguard Worker else
2199*a67afe4dSAndroid Build Coastguard Worker shift += 2;
2200*a67afe4dSAndroid Build Coastguard Worker
2201*a67afe4dSAndroid Build Coastguard Worker dp--;
2202*a67afe4dSAndroid Build Coastguard Worker }
2203*a67afe4dSAndroid Build Coastguard Worker break;
2204*a67afe4dSAndroid Build Coastguard Worker }
2205*a67afe4dSAndroid Build Coastguard Worker
2206*a67afe4dSAndroid Build Coastguard Worker case 4:
2207*a67afe4dSAndroid Build Coastguard Worker {
2208*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)((row_width - 1) >> 1);
2209*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = row + (size_t)row_width - 1;
2210*a67afe4dSAndroid Build Coastguard Worker png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2);
2211*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2212*a67afe4dSAndroid Build Coastguard Worker {
2213*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)((*sp >> shift) & 0x0f);
2214*a67afe4dSAndroid Build Coastguard Worker
2215*a67afe4dSAndroid Build Coastguard Worker if (shift == 4)
2216*a67afe4dSAndroid Build Coastguard Worker {
2217*a67afe4dSAndroid Build Coastguard Worker shift = 0;
2218*a67afe4dSAndroid Build Coastguard Worker sp--;
2219*a67afe4dSAndroid Build Coastguard Worker }
2220*a67afe4dSAndroid Build Coastguard Worker
2221*a67afe4dSAndroid Build Coastguard Worker else
2222*a67afe4dSAndroid Build Coastguard Worker shift = 4;
2223*a67afe4dSAndroid Build Coastguard Worker
2224*a67afe4dSAndroid Build Coastguard Worker dp--;
2225*a67afe4dSAndroid Build Coastguard Worker }
2226*a67afe4dSAndroid Build Coastguard Worker break;
2227*a67afe4dSAndroid Build Coastguard Worker }
2228*a67afe4dSAndroid Build Coastguard Worker
2229*a67afe4dSAndroid Build Coastguard Worker default:
2230*a67afe4dSAndroid Build Coastguard Worker break;
2231*a67afe4dSAndroid Build Coastguard Worker }
2232*a67afe4dSAndroid Build Coastguard Worker row_info->bit_depth = 8;
2233*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2234*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width * row_info->channels;
2235*a67afe4dSAndroid Build Coastguard Worker }
2236*a67afe4dSAndroid Build Coastguard Worker }
2237*a67afe4dSAndroid Build Coastguard Worker #endif
2238*a67afe4dSAndroid Build Coastguard Worker
2239*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_SHIFT_SUPPORTED
2240*a67afe4dSAndroid Build Coastguard Worker /* Reverse the effects of png_do_shift. This routine merely shifts the
2241*a67afe4dSAndroid Build Coastguard Worker * pixels back to their significant bits values. Thus, if you have
2242*a67afe4dSAndroid Build Coastguard Worker * a row of bit depth 8, but only 5 are significant, this will shift
2243*a67afe4dSAndroid Build Coastguard Worker * the values back to 0 through 31.
2244*a67afe4dSAndroid Build Coastguard Worker */
2245*a67afe4dSAndroid Build Coastguard Worker static void
png_do_unshift(png_row_infop row_info,png_bytep row,png_const_color_8p sig_bits)2246*a67afe4dSAndroid Build Coastguard Worker png_do_unshift(png_row_infop row_info, png_bytep row,
2247*a67afe4dSAndroid Build Coastguard Worker png_const_color_8p sig_bits)
2248*a67afe4dSAndroid Build Coastguard Worker {
2249*a67afe4dSAndroid Build Coastguard Worker int color_type;
2250*a67afe4dSAndroid Build Coastguard Worker
2251*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_unshift");
2252*a67afe4dSAndroid Build Coastguard Worker
2253*a67afe4dSAndroid Build Coastguard Worker /* The palette case has already been handled in the _init routine. */
2254*a67afe4dSAndroid Build Coastguard Worker color_type = row_info->color_type;
2255*a67afe4dSAndroid Build Coastguard Worker
2256*a67afe4dSAndroid Build Coastguard Worker if (color_type != PNG_COLOR_TYPE_PALETTE)
2257*a67afe4dSAndroid Build Coastguard Worker {
2258*a67afe4dSAndroid Build Coastguard Worker int shift[4];
2259*a67afe4dSAndroid Build Coastguard Worker int channels = 0;
2260*a67afe4dSAndroid Build Coastguard Worker int bit_depth = row_info->bit_depth;
2261*a67afe4dSAndroid Build Coastguard Worker
2262*a67afe4dSAndroid Build Coastguard Worker if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
2263*a67afe4dSAndroid Build Coastguard Worker {
2264*a67afe4dSAndroid Build Coastguard Worker shift[channels++] = bit_depth - sig_bits->red;
2265*a67afe4dSAndroid Build Coastguard Worker shift[channels++] = bit_depth - sig_bits->green;
2266*a67afe4dSAndroid Build Coastguard Worker shift[channels++] = bit_depth - sig_bits->blue;
2267*a67afe4dSAndroid Build Coastguard Worker }
2268*a67afe4dSAndroid Build Coastguard Worker
2269*a67afe4dSAndroid Build Coastguard Worker else
2270*a67afe4dSAndroid Build Coastguard Worker {
2271*a67afe4dSAndroid Build Coastguard Worker shift[channels++] = bit_depth - sig_bits->gray;
2272*a67afe4dSAndroid Build Coastguard Worker }
2273*a67afe4dSAndroid Build Coastguard Worker
2274*a67afe4dSAndroid Build Coastguard Worker if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
2275*a67afe4dSAndroid Build Coastguard Worker {
2276*a67afe4dSAndroid Build Coastguard Worker shift[channels++] = bit_depth - sig_bits->alpha;
2277*a67afe4dSAndroid Build Coastguard Worker }
2278*a67afe4dSAndroid Build Coastguard Worker
2279*a67afe4dSAndroid Build Coastguard Worker {
2280*a67afe4dSAndroid Build Coastguard Worker int c, have_shift;
2281*a67afe4dSAndroid Build Coastguard Worker
2282*a67afe4dSAndroid Build Coastguard Worker for (c = have_shift = 0; c < channels; ++c)
2283*a67afe4dSAndroid Build Coastguard Worker {
2284*a67afe4dSAndroid Build Coastguard Worker /* A shift of more than the bit depth is an error condition but it
2285*a67afe4dSAndroid Build Coastguard Worker * gets ignored here.
2286*a67afe4dSAndroid Build Coastguard Worker */
2287*a67afe4dSAndroid Build Coastguard Worker if (shift[c] <= 0 || shift[c] >= bit_depth)
2288*a67afe4dSAndroid Build Coastguard Worker shift[c] = 0;
2289*a67afe4dSAndroid Build Coastguard Worker
2290*a67afe4dSAndroid Build Coastguard Worker else
2291*a67afe4dSAndroid Build Coastguard Worker have_shift = 1;
2292*a67afe4dSAndroid Build Coastguard Worker }
2293*a67afe4dSAndroid Build Coastguard Worker
2294*a67afe4dSAndroid Build Coastguard Worker if (have_shift == 0)
2295*a67afe4dSAndroid Build Coastguard Worker return;
2296*a67afe4dSAndroid Build Coastguard Worker }
2297*a67afe4dSAndroid Build Coastguard Worker
2298*a67afe4dSAndroid Build Coastguard Worker switch (bit_depth)
2299*a67afe4dSAndroid Build Coastguard Worker {
2300*a67afe4dSAndroid Build Coastguard Worker default:
2301*a67afe4dSAndroid Build Coastguard Worker /* Must be 1bpp gray: should not be here! */
2302*a67afe4dSAndroid Build Coastguard Worker /* NOTREACHED */
2303*a67afe4dSAndroid Build Coastguard Worker break;
2304*a67afe4dSAndroid Build Coastguard Worker
2305*a67afe4dSAndroid Build Coastguard Worker case 2:
2306*a67afe4dSAndroid Build Coastguard Worker /* Must be 2bpp gray */
2307*a67afe4dSAndroid Build Coastguard Worker /* assert(channels == 1 && shift[0] == 1) */
2308*a67afe4dSAndroid Build Coastguard Worker {
2309*a67afe4dSAndroid Build Coastguard Worker png_bytep bp = row;
2310*a67afe4dSAndroid Build Coastguard Worker png_bytep bp_end = bp + row_info->rowbytes;
2311*a67afe4dSAndroid Build Coastguard Worker
2312*a67afe4dSAndroid Build Coastguard Worker while (bp < bp_end)
2313*a67afe4dSAndroid Build Coastguard Worker {
2314*a67afe4dSAndroid Build Coastguard Worker int b = (*bp >> 1) & 0x55;
2315*a67afe4dSAndroid Build Coastguard Worker *bp++ = (png_byte)b;
2316*a67afe4dSAndroid Build Coastguard Worker }
2317*a67afe4dSAndroid Build Coastguard Worker break;
2318*a67afe4dSAndroid Build Coastguard Worker }
2319*a67afe4dSAndroid Build Coastguard Worker
2320*a67afe4dSAndroid Build Coastguard Worker case 4:
2321*a67afe4dSAndroid Build Coastguard Worker /* Must be 4bpp gray */
2322*a67afe4dSAndroid Build Coastguard Worker /* assert(channels == 1) */
2323*a67afe4dSAndroid Build Coastguard Worker {
2324*a67afe4dSAndroid Build Coastguard Worker png_bytep bp = row;
2325*a67afe4dSAndroid Build Coastguard Worker png_bytep bp_end = bp + row_info->rowbytes;
2326*a67afe4dSAndroid Build Coastguard Worker int gray_shift = shift[0];
2327*a67afe4dSAndroid Build Coastguard Worker int mask = 0xf >> gray_shift;
2328*a67afe4dSAndroid Build Coastguard Worker
2329*a67afe4dSAndroid Build Coastguard Worker mask |= mask << 4;
2330*a67afe4dSAndroid Build Coastguard Worker
2331*a67afe4dSAndroid Build Coastguard Worker while (bp < bp_end)
2332*a67afe4dSAndroid Build Coastguard Worker {
2333*a67afe4dSAndroid Build Coastguard Worker int b = (*bp >> gray_shift) & mask;
2334*a67afe4dSAndroid Build Coastguard Worker *bp++ = (png_byte)b;
2335*a67afe4dSAndroid Build Coastguard Worker }
2336*a67afe4dSAndroid Build Coastguard Worker break;
2337*a67afe4dSAndroid Build Coastguard Worker }
2338*a67afe4dSAndroid Build Coastguard Worker
2339*a67afe4dSAndroid Build Coastguard Worker case 8:
2340*a67afe4dSAndroid Build Coastguard Worker /* Single byte components, G, GA, RGB, RGBA */
2341*a67afe4dSAndroid Build Coastguard Worker {
2342*a67afe4dSAndroid Build Coastguard Worker png_bytep bp = row;
2343*a67afe4dSAndroid Build Coastguard Worker png_bytep bp_end = bp + row_info->rowbytes;
2344*a67afe4dSAndroid Build Coastguard Worker int channel = 0;
2345*a67afe4dSAndroid Build Coastguard Worker
2346*a67afe4dSAndroid Build Coastguard Worker while (bp < bp_end)
2347*a67afe4dSAndroid Build Coastguard Worker {
2348*a67afe4dSAndroid Build Coastguard Worker int b = *bp >> shift[channel];
2349*a67afe4dSAndroid Build Coastguard Worker if (++channel >= channels)
2350*a67afe4dSAndroid Build Coastguard Worker channel = 0;
2351*a67afe4dSAndroid Build Coastguard Worker *bp++ = (png_byte)b;
2352*a67afe4dSAndroid Build Coastguard Worker }
2353*a67afe4dSAndroid Build Coastguard Worker break;
2354*a67afe4dSAndroid Build Coastguard Worker }
2355*a67afe4dSAndroid Build Coastguard Worker
2356*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_16BIT_SUPPORTED
2357*a67afe4dSAndroid Build Coastguard Worker case 16:
2358*a67afe4dSAndroid Build Coastguard Worker /* Double byte components, G, GA, RGB, RGBA */
2359*a67afe4dSAndroid Build Coastguard Worker {
2360*a67afe4dSAndroid Build Coastguard Worker png_bytep bp = row;
2361*a67afe4dSAndroid Build Coastguard Worker png_bytep bp_end = bp + row_info->rowbytes;
2362*a67afe4dSAndroid Build Coastguard Worker int channel = 0;
2363*a67afe4dSAndroid Build Coastguard Worker
2364*a67afe4dSAndroid Build Coastguard Worker while (bp < bp_end)
2365*a67afe4dSAndroid Build Coastguard Worker {
2366*a67afe4dSAndroid Build Coastguard Worker int value = (bp[0] << 8) + bp[1];
2367*a67afe4dSAndroid Build Coastguard Worker
2368*a67afe4dSAndroid Build Coastguard Worker value >>= shift[channel];
2369*a67afe4dSAndroid Build Coastguard Worker if (++channel >= channels)
2370*a67afe4dSAndroid Build Coastguard Worker channel = 0;
2371*a67afe4dSAndroid Build Coastguard Worker *bp++ = (png_byte)(value >> 8);
2372*a67afe4dSAndroid Build Coastguard Worker *bp++ = (png_byte)value;
2373*a67afe4dSAndroid Build Coastguard Worker }
2374*a67afe4dSAndroid Build Coastguard Worker break;
2375*a67afe4dSAndroid Build Coastguard Worker }
2376*a67afe4dSAndroid Build Coastguard Worker #endif
2377*a67afe4dSAndroid Build Coastguard Worker }
2378*a67afe4dSAndroid Build Coastguard Worker }
2379*a67afe4dSAndroid Build Coastguard Worker }
2380*a67afe4dSAndroid Build Coastguard Worker #endif
2381*a67afe4dSAndroid Build Coastguard Worker
2382*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
2383*a67afe4dSAndroid Build Coastguard Worker /* Scale rows of bit depth 16 down to 8 accurately */
2384*a67afe4dSAndroid Build Coastguard Worker static void
png_do_scale_16_to_8(png_row_infop row_info,png_bytep row)2385*a67afe4dSAndroid Build Coastguard Worker png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
2386*a67afe4dSAndroid Build Coastguard Worker {
2387*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_scale_16_to_8");
2388*a67afe4dSAndroid Build Coastguard Worker
2389*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 16)
2390*a67afe4dSAndroid Build Coastguard Worker {
2391*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row; /* source */
2392*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = row; /* destination */
2393*a67afe4dSAndroid Build Coastguard Worker png_bytep ep = sp + row_info->rowbytes; /* end+1 */
2394*a67afe4dSAndroid Build Coastguard Worker
2395*a67afe4dSAndroid Build Coastguard Worker while (sp < ep)
2396*a67afe4dSAndroid Build Coastguard Worker {
2397*a67afe4dSAndroid Build Coastguard Worker /* The input is an array of 16-bit components, these must be scaled to
2398*a67afe4dSAndroid Build Coastguard Worker * 8 bits each. For a 16-bit value V the required value (from the PNG
2399*a67afe4dSAndroid Build Coastguard Worker * specification) is:
2400*a67afe4dSAndroid Build Coastguard Worker *
2401*a67afe4dSAndroid Build Coastguard Worker * (V * 255) / 65535
2402*a67afe4dSAndroid Build Coastguard Worker *
2403*a67afe4dSAndroid Build Coastguard Worker * This reduces to round(V / 257), or floor((V + 128.5)/257)
2404*a67afe4dSAndroid Build Coastguard Worker *
2405*a67afe4dSAndroid Build Coastguard Worker * Represent V as the two byte value vhi.vlo. Make a guess that the
2406*a67afe4dSAndroid Build Coastguard Worker * result is the top byte of V, vhi, then the correction to this value
2407*a67afe4dSAndroid Build Coastguard Worker * is:
2408*a67afe4dSAndroid Build Coastguard Worker *
2409*a67afe4dSAndroid Build Coastguard Worker * error = floor(((V-vhi.vhi) + 128.5) / 257)
2410*a67afe4dSAndroid Build Coastguard Worker * = floor(((vlo-vhi) + 128.5) / 257)
2411*a67afe4dSAndroid Build Coastguard Worker *
2412*a67afe4dSAndroid Build Coastguard Worker * This can be approximated using integer arithmetic (and a signed
2413*a67afe4dSAndroid Build Coastguard Worker * shift):
2414*a67afe4dSAndroid Build Coastguard Worker *
2415*a67afe4dSAndroid Build Coastguard Worker * error = (vlo-vhi+128) >> 8;
2416*a67afe4dSAndroid Build Coastguard Worker *
2417*a67afe4dSAndroid Build Coastguard Worker * The approximate differs from the exact answer only when (vlo-vhi) is
2418*a67afe4dSAndroid Build Coastguard Worker * 128; it then gives a correction of +1 when the exact correction is
2419*a67afe4dSAndroid Build Coastguard Worker * 0. This gives 128 errors. The exact answer (correct for all 16-bit
2420*a67afe4dSAndroid Build Coastguard Worker * input values) is:
2421*a67afe4dSAndroid Build Coastguard Worker *
2422*a67afe4dSAndroid Build Coastguard Worker * error = (vlo-vhi+128)*65535 >> 24;
2423*a67afe4dSAndroid Build Coastguard Worker *
2424*a67afe4dSAndroid Build Coastguard Worker * An alternative arithmetic calculation which also gives no errors is:
2425*a67afe4dSAndroid Build Coastguard Worker *
2426*a67afe4dSAndroid Build Coastguard Worker * (V * 255 + 32895) >> 16
2427*a67afe4dSAndroid Build Coastguard Worker */
2428*a67afe4dSAndroid Build Coastguard Worker
2429*a67afe4dSAndroid Build Coastguard Worker png_int_32 tmp = *sp++; /* must be signed! */
2430*a67afe4dSAndroid Build Coastguard Worker tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
2431*a67afe4dSAndroid Build Coastguard Worker *dp++ = (png_byte)tmp;
2432*a67afe4dSAndroid Build Coastguard Worker }
2433*a67afe4dSAndroid Build Coastguard Worker
2434*a67afe4dSAndroid Build Coastguard Worker row_info->bit_depth = 8;
2435*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2436*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_info->width * row_info->channels;
2437*a67afe4dSAndroid Build Coastguard Worker }
2438*a67afe4dSAndroid Build Coastguard Worker }
2439*a67afe4dSAndroid Build Coastguard Worker #endif
2440*a67afe4dSAndroid Build Coastguard Worker
2441*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
2442*a67afe4dSAndroid Build Coastguard Worker static void
2443*a67afe4dSAndroid Build Coastguard Worker /* Simply discard the low byte. This was the default behavior prior
2444*a67afe4dSAndroid Build Coastguard Worker * to libpng-1.5.4.
2445*a67afe4dSAndroid Build Coastguard Worker */
png_do_chop(png_row_infop row_info,png_bytep row)2446*a67afe4dSAndroid Build Coastguard Worker png_do_chop(png_row_infop row_info, png_bytep row)
2447*a67afe4dSAndroid Build Coastguard Worker {
2448*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_chop");
2449*a67afe4dSAndroid Build Coastguard Worker
2450*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 16)
2451*a67afe4dSAndroid Build Coastguard Worker {
2452*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row; /* source */
2453*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = row; /* destination */
2454*a67afe4dSAndroid Build Coastguard Worker png_bytep ep = sp + row_info->rowbytes; /* end+1 */
2455*a67afe4dSAndroid Build Coastguard Worker
2456*a67afe4dSAndroid Build Coastguard Worker while (sp < ep)
2457*a67afe4dSAndroid Build Coastguard Worker {
2458*a67afe4dSAndroid Build Coastguard Worker *dp++ = *sp;
2459*a67afe4dSAndroid Build Coastguard Worker sp += 2; /* skip low byte */
2460*a67afe4dSAndroid Build Coastguard Worker }
2461*a67afe4dSAndroid Build Coastguard Worker
2462*a67afe4dSAndroid Build Coastguard Worker row_info->bit_depth = 8;
2463*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = (png_byte)(8 * row_info->channels);
2464*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_info->width * row_info->channels;
2465*a67afe4dSAndroid Build Coastguard Worker }
2466*a67afe4dSAndroid Build Coastguard Worker }
2467*a67afe4dSAndroid Build Coastguard Worker #endif
2468*a67afe4dSAndroid Build Coastguard Worker
2469*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
2470*a67afe4dSAndroid Build Coastguard Worker static void
png_do_read_swap_alpha(png_row_infop row_info,png_bytep row)2471*a67afe4dSAndroid Build Coastguard Worker png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
2472*a67afe4dSAndroid Build Coastguard Worker {
2473*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
2474*a67afe4dSAndroid Build Coastguard Worker
2475*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_read_swap_alpha");
2476*a67afe4dSAndroid Build Coastguard Worker
2477*a67afe4dSAndroid Build Coastguard Worker if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2478*a67afe4dSAndroid Build Coastguard Worker {
2479*a67afe4dSAndroid Build Coastguard Worker /* This converts from RGBA to ARGB */
2480*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
2481*a67afe4dSAndroid Build Coastguard Worker {
2482*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + row_info->rowbytes;
2483*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp;
2484*a67afe4dSAndroid Build Coastguard Worker png_byte save;
2485*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
2486*a67afe4dSAndroid Build Coastguard Worker
2487*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2488*a67afe4dSAndroid Build Coastguard Worker {
2489*a67afe4dSAndroid Build Coastguard Worker save = *(--sp);
2490*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2491*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2492*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2493*a67afe4dSAndroid Build Coastguard Worker *(--dp) = save;
2494*a67afe4dSAndroid Build Coastguard Worker }
2495*a67afe4dSAndroid Build Coastguard Worker }
2496*a67afe4dSAndroid Build Coastguard Worker
2497*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_16BIT_SUPPORTED
2498*a67afe4dSAndroid Build Coastguard Worker /* This converts from RRGGBBAA to AARRGGBB */
2499*a67afe4dSAndroid Build Coastguard Worker else
2500*a67afe4dSAndroid Build Coastguard Worker {
2501*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + row_info->rowbytes;
2502*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp;
2503*a67afe4dSAndroid Build Coastguard Worker png_byte save[2];
2504*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
2505*a67afe4dSAndroid Build Coastguard Worker
2506*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2507*a67afe4dSAndroid Build Coastguard Worker {
2508*a67afe4dSAndroid Build Coastguard Worker save[0] = *(--sp);
2509*a67afe4dSAndroid Build Coastguard Worker save[1] = *(--sp);
2510*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2511*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2512*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2513*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2514*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2515*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2516*a67afe4dSAndroid Build Coastguard Worker *(--dp) = save[0];
2517*a67afe4dSAndroid Build Coastguard Worker *(--dp) = save[1];
2518*a67afe4dSAndroid Build Coastguard Worker }
2519*a67afe4dSAndroid Build Coastguard Worker }
2520*a67afe4dSAndroid Build Coastguard Worker #endif
2521*a67afe4dSAndroid Build Coastguard Worker }
2522*a67afe4dSAndroid Build Coastguard Worker
2523*a67afe4dSAndroid Build Coastguard Worker else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2524*a67afe4dSAndroid Build Coastguard Worker {
2525*a67afe4dSAndroid Build Coastguard Worker /* This converts from GA to AG */
2526*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
2527*a67afe4dSAndroid Build Coastguard Worker {
2528*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + row_info->rowbytes;
2529*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp;
2530*a67afe4dSAndroid Build Coastguard Worker png_byte save;
2531*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
2532*a67afe4dSAndroid Build Coastguard Worker
2533*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2534*a67afe4dSAndroid Build Coastguard Worker {
2535*a67afe4dSAndroid Build Coastguard Worker save = *(--sp);
2536*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2537*a67afe4dSAndroid Build Coastguard Worker *(--dp) = save;
2538*a67afe4dSAndroid Build Coastguard Worker }
2539*a67afe4dSAndroid Build Coastguard Worker }
2540*a67afe4dSAndroid Build Coastguard Worker
2541*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_16BIT_SUPPORTED
2542*a67afe4dSAndroid Build Coastguard Worker /* This converts from GGAA to AAGG */
2543*a67afe4dSAndroid Build Coastguard Worker else
2544*a67afe4dSAndroid Build Coastguard Worker {
2545*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + row_info->rowbytes;
2546*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp;
2547*a67afe4dSAndroid Build Coastguard Worker png_byte save[2];
2548*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
2549*a67afe4dSAndroid Build Coastguard Worker
2550*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2551*a67afe4dSAndroid Build Coastguard Worker {
2552*a67afe4dSAndroid Build Coastguard Worker save[0] = *(--sp);
2553*a67afe4dSAndroid Build Coastguard Worker save[1] = *(--sp);
2554*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2555*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2556*a67afe4dSAndroid Build Coastguard Worker *(--dp) = save[0];
2557*a67afe4dSAndroid Build Coastguard Worker *(--dp) = save[1];
2558*a67afe4dSAndroid Build Coastguard Worker }
2559*a67afe4dSAndroid Build Coastguard Worker }
2560*a67afe4dSAndroid Build Coastguard Worker #endif
2561*a67afe4dSAndroid Build Coastguard Worker }
2562*a67afe4dSAndroid Build Coastguard Worker }
2563*a67afe4dSAndroid Build Coastguard Worker #endif
2564*a67afe4dSAndroid Build Coastguard Worker
2565*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
2566*a67afe4dSAndroid Build Coastguard Worker static void
png_do_read_invert_alpha(png_row_infop row_info,png_bytep row)2567*a67afe4dSAndroid Build Coastguard Worker png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
2568*a67afe4dSAndroid Build Coastguard Worker {
2569*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width;
2570*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_read_invert_alpha");
2571*a67afe4dSAndroid Build Coastguard Worker
2572*a67afe4dSAndroid Build Coastguard Worker row_width = row_info->width;
2573*a67afe4dSAndroid Build Coastguard Worker if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2574*a67afe4dSAndroid Build Coastguard Worker {
2575*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
2576*a67afe4dSAndroid Build Coastguard Worker {
2577*a67afe4dSAndroid Build Coastguard Worker /* This inverts the alpha channel in RGBA */
2578*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + row_info->rowbytes;
2579*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp;
2580*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
2581*a67afe4dSAndroid Build Coastguard Worker
2582*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2583*a67afe4dSAndroid Build Coastguard Worker {
2584*a67afe4dSAndroid Build Coastguard Worker *(--dp) = (png_byte)(255 - *(--sp));
2585*a67afe4dSAndroid Build Coastguard Worker
2586*a67afe4dSAndroid Build Coastguard Worker /* This does nothing:
2587*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2588*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2589*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2590*a67afe4dSAndroid Build Coastguard Worker We can replace it with:
2591*a67afe4dSAndroid Build Coastguard Worker */
2592*a67afe4dSAndroid Build Coastguard Worker sp-=3;
2593*a67afe4dSAndroid Build Coastguard Worker dp=sp;
2594*a67afe4dSAndroid Build Coastguard Worker }
2595*a67afe4dSAndroid Build Coastguard Worker }
2596*a67afe4dSAndroid Build Coastguard Worker
2597*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_16BIT_SUPPORTED
2598*a67afe4dSAndroid Build Coastguard Worker /* This inverts the alpha channel in RRGGBBAA */
2599*a67afe4dSAndroid Build Coastguard Worker else
2600*a67afe4dSAndroid Build Coastguard Worker {
2601*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + row_info->rowbytes;
2602*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp;
2603*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
2604*a67afe4dSAndroid Build Coastguard Worker
2605*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2606*a67afe4dSAndroid Build Coastguard Worker {
2607*a67afe4dSAndroid Build Coastguard Worker *(--dp) = (png_byte)(255 - *(--sp));
2608*a67afe4dSAndroid Build Coastguard Worker *(--dp) = (png_byte)(255 - *(--sp));
2609*a67afe4dSAndroid Build Coastguard Worker
2610*a67afe4dSAndroid Build Coastguard Worker /* This does nothing:
2611*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2612*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2613*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2614*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2615*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2616*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2617*a67afe4dSAndroid Build Coastguard Worker We can replace it with:
2618*a67afe4dSAndroid Build Coastguard Worker */
2619*a67afe4dSAndroid Build Coastguard Worker sp-=6;
2620*a67afe4dSAndroid Build Coastguard Worker dp=sp;
2621*a67afe4dSAndroid Build Coastguard Worker }
2622*a67afe4dSAndroid Build Coastguard Worker }
2623*a67afe4dSAndroid Build Coastguard Worker #endif
2624*a67afe4dSAndroid Build Coastguard Worker }
2625*a67afe4dSAndroid Build Coastguard Worker else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2626*a67afe4dSAndroid Build Coastguard Worker {
2627*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
2628*a67afe4dSAndroid Build Coastguard Worker {
2629*a67afe4dSAndroid Build Coastguard Worker /* This inverts the alpha channel in GA */
2630*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + row_info->rowbytes;
2631*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp;
2632*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
2633*a67afe4dSAndroid Build Coastguard Worker
2634*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2635*a67afe4dSAndroid Build Coastguard Worker {
2636*a67afe4dSAndroid Build Coastguard Worker *(--dp) = (png_byte)(255 - *(--sp));
2637*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2638*a67afe4dSAndroid Build Coastguard Worker }
2639*a67afe4dSAndroid Build Coastguard Worker }
2640*a67afe4dSAndroid Build Coastguard Worker
2641*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_16BIT_SUPPORTED
2642*a67afe4dSAndroid Build Coastguard Worker else
2643*a67afe4dSAndroid Build Coastguard Worker {
2644*a67afe4dSAndroid Build Coastguard Worker /* This inverts the alpha channel in GGAA */
2645*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + row_info->rowbytes;
2646*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp;
2647*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
2648*a67afe4dSAndroid Build Coastguard Worker
2649*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2650*a67afe4dSAndroid Build Coastguard Worker {
2651*a67afe4dSAndroid Build Coastguard Worker *(--dp) = (png_byte)(255 - *(--sp));
2652*a67afe4dSAndroid Build Coastguard Worker *(--dp) = (png_byte)(255 - *(--sp));
2653*a67afe4dSAndroid Build Coastguard Worker /*
2654*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2655*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2656*a67afe4dSAndroid Build Coastguard Worker */
2657*a67afe4dSAndroid Build Coastguard Worker sp-=2;
2658*a67afe4dSAndroid Build Coastguard Worker dp=sp;
2659*a67afe4dSAndroid Build Coastguard Worker }
2660*a67afe4dSAndroid Build Coastguard Worker }
2661*a67afe4dSAndroid Build Coastguard Worker #endif
2662*a67afe4dSAndroid Build Coastguard Worker }
2663*a67afe4dSAndroid Build Coastguard Worker }
2664*a67afe4dSAndroid Build Coastguard Worker #endif
2665*a67afe4dSAndroid Build Coastguard Worker
2666*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_FILLER_SUPPORTED
2667*a67afe4dSAndroid Build Coastguard Worker /* Add filler channel if we have RGB color */
2668*a67afe4dSAndroid Build Coastguard Worker static void
png_do_read_filler(png_row_infop row_info,png_bytep row,png_uint_32 filler,png_uint_32 flags)2669*a67afe4dSAndroid Build Coastguard Worker png_do_read_filler(png_row_infop row_info, png_bytep row,
2670*a67afe4dSAndroid Build Coastguard Worker png_uint_32 filler, png_uint_32 flags)
2671*a67afe4dSAndroid Build Coastguard Worker {
2672*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
2673*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
2674*a67afe4dSAndroid Build Coastguard Worker
2675*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_16BIT_SUPPORTED
2676*a67afe4dSAndroid Build Coastguard Worker png_byte hi_filler = (png_byte)(filler>>8);
2677*a67afe4dSAndroid Build Coastguard Worker #endif
2678*a67afe4dSAndroid Build Coastguard Worker png_byte lo_filler = (png_byte)filler;
2679*a67afe4dSAndroid Build Coastguard Worker
2680*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_read_filler");
2681*a67afe4dSAndroid Build Coastguard Worker
2682*a67afe4dSAndroid Build Coastguard Worker if (
2683*a67afe4dSAndroid Build Coastguard Worker row_info->color_type == PNG_COLOR_TYPE_GRAY)
2684*a67afe4dSAndroid Build Coastguard Worker {
2685*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
2686*a67afe4dSAndroid Build Coastguard Worker {
2687*a67afe4dSAndroid Build Coastguard Worker if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2688*a67afe4dSAndroid Build Coastguard Worker {
2689*a67afe4dSAndroid Build Coastguard Worker /* This changes the data from G to GX */
2690*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)row_width;
2691*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp + (size_t)row_width;
2692*a67afe4dSAndroid Build Coastguard Worker for (i = 1; i < row_width; i++)
2693*a67afe4dSAndroid Build Coastguard Worker {
2694*a67afe4dSAndroid Build Coastguard Worker *(--dp) = lo_filler;
2695*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2696*a67afe4dSAndroid Build Coastguard Worker }
2697*a67afe4dSAndroid Build Coastguard Worker *(--dp) = lo_filler;
2698*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 2;
2699*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = 16;
2700*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width * 2;
2701*a67afe4dSAndroid Build Coastguard Worker }
2702*a67afe4dSAndroid Build Coastguard Worker
2703*a67afe4dSAndroid Build Coastguard Worker else
2704*a67afe4dSAndroid Build Coastguard Worker {
2705*a67afe4dSAndroid Build Coastguard Worker /* This changes the data from G to XG */
2706*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)row_width;
2707*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp + (size_t)row_width;
2708*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2709*a67afe4dSAndroid Build Coastguard Worker {
2710*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2711*a67afe4dSAndroid Build Coastguard Worker *(--dp) = lo_filler;
2712*a67afe4dSAndroid Build Coastguard Worker }
2713*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 2;
2714*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = 16;
2715*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width * 2;
2716*a67afe4dSAndroid Build Coastguard Worker }
2717*a67afe4dSAndroid Build Coastguard Worker }
2718*a67afe4dSAndroid Build Coastguard Worker
2719*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_16BIT_SUPPORTED
2720*a67afe4dSAndroid Build Coastguard Worker else if (row_info->bit_depth == 16)
2721*a67afe4dSAndroid Build Coastguard Worker {
2722*a67afe4dSAndroid Build Coastguard Worker if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2723*a67afe4dSAndroid Build Coastguard Worker {
2724*a67afe4dSAndroid Build Coastguard Worker /* This changes the data from GG to GGXX */
2725*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)row_width * 2;
2726*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp + (size_t)row_width * 2;
2727*a67afe4dSAndroid Build Coastguard Worker for (i = 1; i < row_width; i++)
2728*a67afe4dSAndroid Build Coastguard Worker {
2729*a67afe4dSAndroid Build Coastguard Worker *(--dp) = lo_filler;
2730*a67afe4dSAndroid Build Coastguard Worker *(--dp) = hi_filler;
2731*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2732*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2733*a67afe4dSAndroid Build Coastguard Worker }
2734*a67afe4dSAndroid Build Coastguard Worker *(--dp) = lo_filler;
2735*a67afe4dSAndroid Build Coastguard Worker *(--dp) = hi_filler;
2736*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 2;
2737*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = 32;
2738*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width * 4;
2739*a67afe4dSAndroid Build Coastguard Worker }
2740*a67afe4dSAndroid Build Coastguard Worker
2741*a67afe4dSAndroid Build Coastguard Worker else
2742*a67afe4dSAndroid Build Coastguard Worker {
2743*a67afe4dSAndroid Build Coastguard Worker /* This changes the data from GG to XXGG */
2744*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)row_width * 2;
2745*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp + (size_t)row_width * 2;
2746*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2747*a67afe4dSAndroid Build Coastguard Worker {
2748*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2749*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2750*a67afe4dSAndroid Build Coastguard Worker *(--dp) = lo_filler;
2751*a67afe4dSAndroid Build Coastguard Worker *(--dp) = hi_filler;
2752*a67afe4dSAndroid Build Coastguard Worker }
2753*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 2;
2754*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = 32;
2755*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width * 4;
2756*a67afe4dSAndroid Build Coastguard Worker }
2757*a67afe4dSAndroid Build Coastguard Worker }
2758*a67afe4dSAndroid Build Coastguard Worker #endif
2759*a67afe4dSAndroid Build Coastguard Worker } /* COLOR_TYPE == GRAY */
2760*a67afe4dSAndroid Build Coastguard Worker else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2761*a67afe4dSAndroid Build Coastguard Worker {
2762*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
2763*a67afe4dSAndroid Build Coastguard Worker {
2764*a67afe4dSAndroid Build Coastguard Worker if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2765*a67afe4dSAndroid Build Coastguard Worker {
2766*a67afe4dSAndroid Build Coastguard Worker /* This changes the data from RGB to RGBX */
2767*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)row_width * 3;
2768*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp + (size_t)row_width;
2769*a67afe4dSAndroid Build Coastguard Worker for (i = 1; i < row_width; i++)
2770*a67afe4dSAndroid Build Coastguard Worker {
2771*a67afe4dSAndroid Build Coastguard Worker *(--dp) = lo_filler;
2772*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2773*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2774*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2775*a67afe4dSAndroid Build Coastguard Worker }
2776*a67afe4dSAndroid Build Coastguard Worker *(--dp) = lo_filler;
2777*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 4;
2778*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = 32;
2779*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width * 4;
2780*a67afe4dSAndroid Build Coastguard Worker }
2781*a67afe4dSAndroid Build Coastguard Worker
2782*a67afe4dSAndroid Build Coastguard Worker else
2783*a67afe4dSAndroid Build Coastguard Worker {
2784*a67afe4dSAndroid Build Coastguard Worker /* This changes the data from RGB to XRGB */
2785*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)row_width * 3;
2786*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp + (size_t)row_width;
2787*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2788*a67afe4dSAndroid Build Coastguard Worker {
2789*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2790*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2791*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2792*a67afe4dSAndroid Build Coastguard Worker *(--dp) = lo_filler;
2793*a67afe4dSAndroid Build Coastguard Worker }
2794*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 4;
2795*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = 32;
2796*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width * 4;
2797*a67afe4dSAndroid Build Coastguard Worker }
2798*a67afe4dSAndroid Build Coastguard Worker }
2799*a67afe4dSAndroid Build Coastguard Worker
2800*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_16BIT_SUPPORTED
2801*a67afe4dSAndroid Build Coastguard Worker else if (row_info->bit_depth == 16)
2802*a67afe4dSAndroid Build Coastguard Worker {
2803*a67afe4dSAndroid Build Coastguard Worker if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
2804*a67afe4dSAndroid Build Coastguard Worker {
2805*a67afe4dSAndroid Build Coastguard Worker /* This changes the data from RRGGBB to RRGGBBXX */
2806*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)row_width * 6;
2807*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp + (size_t)row_width * 2;
2808*a67afe4dSAndroid Build Coastguard Worker for (i = 1; i < row_width; i++)
2809*a67afe4dSAndroid Build Coastguard Worker {
2810*a67afe4dSAndroid Build Coastguard Worker *(--dp) = lo_filler;
2811*a67afe4dSAndroid Build Coastguard Worker *(--dp) = hi_filler;
2812*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2813*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2814*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2815*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2816*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2817*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2818*a67afe4dSAndroid Build Coastguard Worker }
2819*a67afe4dSAndroid Build Coastguard Worker *(--dp) = lo_filler;
2820*a67afe4dSAndroid Build Coastguard Worker *(--dp) = hi_filler;
2821*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 4;
2822*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = 64;
2823*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width * 8;
2824*a67afe4dSAndroid Build Coastguard Worker }
2825*a67afe4dSAndroid Build Coastguard Worker
2826*a67afe4dSAndroid Build Coastguard Worker else
2827*a67afe4dSAndroid Build Coastguard Worker {
2828*a67afe4dSAndroid Build Coastguard Worker /* This changes the data from RRGGBB to XXRRGGBB */
2829*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)row_width * 6;
2830*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp + (size_t)row_width * 2;
2831*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2832*a67afe4dSAndroid Build Coastguard Worker {
2833*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2834*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2835*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2836*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2837*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2838*a67afe4dSAndroid Build Coastguard Worker *(--dp) = *(--sp);
2839*a67afe4dSAndroid Build Coastguard Worker *(--dp) = lo_filler;
2840*a67afe4dSAndroid Build Coastguard Worker *(--dp) = hi_filler;
2841*a67afe4dSAndroid Build Coastguard Worker }
2842*a67afe4dSAndroid Build Coastguard Worker
2843*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 4;
2844*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = 64;
2845*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width * 8;
2846*a67afe4dSAndroid Build Coastguard Worker }
2847*a67afe4dSAndroid Build Coastguard Worker }
2848*a67afe4dSAndroid Build Coastguard Worker #endif
2849*a67afe4dSAndroid Build Coastguard Worker } /* COLOR_TYPE == RGB */
2850*a67afe4dSAndroid Build Coastguard Worker }
2851*a67afe4dSAndroid Build Coastguard Worker #endif
2852*a67afe4dSAndroid Build Coastguard Worker
2853*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2854*a67afe4dSAndroid Build Coastguard Worker /* Expand grayscale files to RGB, with or without alpha */
2855*a67afe4dSAndroid Build Coastguard Worker static void
png_do_gray_to_rgb(png_row_infop row_info,png_bytep row)2856*a67afe4dSAndroid Build Coastguard Worker png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
2857*a67afe4dSAndroid Build Coastguard Worker {
2858*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
2859*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
2860*a67afe4dSAndroid Build Coastguard Worker
2861*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_gray_to_rgb");
2862*a67afe4dSAndroid Build Coastguard Worker
2863*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth >= 8 &&
2864*a67afe4dSAndroid Build Coastguard Worker (row_info->color_type & PNG_COLOR_MASK_COLOR) == 0)
2865*a67afe4dSAndroid Build Coastguard Worker {
2866*a67afe4dSAndroid Build Coastguard Worker if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2867*a67afe4dSAndroid Build Coastguard Worker {
2868*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
2869*a67afe4dSAndroid Build Coastguard Worker {
2870*a67afe4dSAndroid Build Coastguard Worker /* This changes G to RGB */
2871*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)row_width - 1;
2872*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp + (size_t)row_width * 2;
2873*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2874*a67afe4dSAndroid Build Coastguard Worker {
2875*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *sp;
2876*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *sp;
2877*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp--);
2878*a67afe4dSAndroid Build Coastguard Worker }
2879*a67afe4dSAndroid Build Coastguard Worker }
2880*a67afe4dSAndroid Build Coastguard Worker
2881*a67afe4dSAndroid Build Coastguard Worker else
2882*a67afe4dSAndroid Build Coastguard Worker {
2883*a67afe4dSAndroid Build Coastguard Worker /* This changes GG to RRGGBB */
2884*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)row_width * 2 - 1;
2885*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp + (size_t)row_width * 4;
2886*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2887*a67afe4dSAndroid Build Coastguard Worker {
2888*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *sp;
2889*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp - 1);
2890*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *sp;
2891*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp - 1);
2892*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp--);
2893*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp--);
2894*a67afe4dSAndroid Build Coastguard Worker }
2895*a67afe4dSAndroid Build Coastguard Worker }
2896*a67afe4dSAndroid Build Coastguard Worker }
2897*a67afe4dSAndroid Build Coastguard Worker
2898*a67afe4dSAndroid Build Coastguard Worker else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2899*a67afe4dSAndroid Build Coastguard Worker {
2900*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
2901*a67afe4dSAndroid Build Coastguard Worker {
2902*a67afe4dSAndroid Build Coastguard Worker /* This changes GA to RGBA */
2903*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)row_width * 2 - 1;
2904*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp + (size_t)row_width * 2;
2905*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2906*a67afe4dSAndroid Build Coastguard Worker {
2907*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp--);
2908*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *sp;
2909*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *sp;
2910*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp--);
2911*a67afe4dSAndroid Build Coastguard Worker }
2912*a67afe4dSAndroid Build Coastguard Worker }
2913*a67afe4dSAndroid Build Coastguard Worker
2914*a67afe4dSAndroid Build Coastguard Worker else
2915*a67afe4dSAndroid Build Coastguard Worker {
2916*a67afe4dSAndroid Build Coastguard Worker /* This changes GGAA to RRGGBBAA */
2917*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row + (size_t)row_width * 4 - 1;
2918*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = sp + (size_t)row_width * 4;
2919*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
2920*a67afe4dSAndroid Build Coastguard Worker {
2921*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp--);
2922*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp--);
2923*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *sp;
2924*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp - 1);
2925*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *sp;
2926*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp - 1);
2927*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp--);
2928*a67afe4dSAndroid Build Coastguard Worker *(dp--) = *(sp--);
2929*a67afe4dSAndroid Build Coastguard Worker }
2930*a67afe4dSAndroid Build Coastguard Worker }
2931*a67afe4dSAndroid Build Coastguard Worker }
2932*a67afe4dSAndroid Build Coastguard Worker row_info->channels = (png_byte)(row_info->channels + 2);
2933*a67afe4dSAndroid Build Coastguard Worker row_info->color_type |= PNG_COLOR_MASK_COLOR;
2934*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = (png_byte)(row_info->channels *
2935*a67afe4dSAndroid Build Coastguard Worker row_info->bit_depth);
2936*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2937*a67afe4dSAndroid Build Coastguard Worker }
2938*a67afe4dSAndroid Build Coastguard Worker }
2939*a67afe4dSAndroid Build Coastguard Worker #endif
2940*a67afe4dSAndroid Build Coastguard Worker
2941*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2942*a67afe4dSAndroid Build Coastguard Worker /* Reduce RGB files to grayscale, with or without alpha
2943*a67afe4dSAndroid Build Coastguard Worker * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
2944*a67afe4dSAndroid Build Coastguard Worker * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008 but
2945*a67afe4dSAndroid Build Coastguard Worker * versions dated 1998 through November 2002 have been archived at
2946*a67afe4dSAndroid Build Coastguard Worker * https://web.archive.org/web/20000816232553/www.inforamp.net/
2947*a67afe4dSAndroid Build Coastguard Worker * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
2948*a67afe4dSAndroid Build Coastguard Worker * Charles Poynton poynton at poynton.com
2949*a67afe4dSAndroid Build Coastguard Worker *
2950*a67afe4dSAndroid Build Coastguard Worker * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2951*a67afe4dSAndroid Build Coastguard Worker *
2952*a67afe4dSAndroid Build Coastguard Worker * which can be expressed with integers as
2953*a67afe4dSAndroid Build Coastguard Worker *
2954*a67afe4dSAndroid Build Coastguard Worker * Y = (6969 * R + 23434 * G + 2365 * B)/32768
2955*a67afe4dSAndroid Build Coastguard Worker *
2956*a67afe4dSAndroid Build Coastguard Worker * Poynton's current link (as of January 2003 through July 2011):
2957*a67afe4dSAndroid Build Coastguard Worker * <http://www.poynton.com/notes/colour_and_gamma/>
2958*a67afe4dSAndroid Build Coastguard Worker * has changed the numbers slightly:
2959*a67afe4dSAndroid Build Coastguard Worker *
2960*a67afe4dSAndroid Build Coastguard Worker * Y = 0.2126*R + 0.7152*G + 0.0722*B
2961*a67afe4dSAndroid Build Coastguard Worker *
2962*a67afe4dSAndroid Build Coastguard Worker * which can be expressed with integers as
2963*a67afe4dSAndroid Build Coastguard Worker *
2964*a67afe4dSAndroid Build Coastguard Worker * Y = (6966 * R + 23436 * G + 2366 * B)/32768
2965*a67afe4dSAndroid Build Coastguard Worker *
2966*a67afe4dSAndroid Build Coastguard Worker * Historically, however, libpng uses numbers derived from the ITU-R Rec 709
2967*a67afe4dSAndroid Build Coastguard Worker * end point chromaticities and the D65 white point. Depending on the
2968*a67afe4dSAndroid Build Coastguard Worker * precision used for the D65 white point this produces a variety of different
2969*a67afe4dSAndroid Build Coastguard Worker * numbers, however if the four decimal place value used in ITU-R Rec 709 is
2970*a67afe4dSAndroid Build Coastguard Worker * used (0.3127,0.3290) the Y calculation would be:
2971*a67afe4dSAndroid Build Coastguard Worker *
2972*a67afe4dSAndroid Build Coastguard Worker * Y = (6968 * R + 23435 * G + 2366 * B)/32768
2973*a67afe4dSAndroid Build Coastguard Worker *
2974*a67afe4dSAndroid Build Coastguard Worker * While this is correct the rounding results in an overflow for white, because
2975*a67afe4dSAndroid Build Coastguard Worker * the sum of the rounded coefficients is 32769, not 32768. Consequently
2976*a67afe4dSAndroid Build Coastguard Worker * libpng uses, instead, the closest non-overflowing approximation:
2977*a67afe4dSAndroid Build Coastguard Worker *
2978*a67afe4dSAndroid Build Coastguard Worker * Y = (6968 * R + 23434 * G + 2366 * B)/32768
2979*a67afe4dSAndroid Build Coastguard Worker *
2980*a67afe4dSAndroid Build Coastguard Worker * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk
2981*a67afe4dSAndroid Build Coastguard Worker * (including an sRGB chunk) then the chromaticities are used to calculate the
2982*a67afe4dSAndroid Build Coastguard Worker * coefficients. See the chunk handling in pngrutil.c for more information.
2983*a67afe4dSAndroid Build Coastguard Worker *
2984*a67afe4dSAndroid Build Coastguard Worker * In all cases the calculation is to be done in a linear colorspace. If no
2985*a67afe4dSAndroid Build Coastguard Worker * gamma information is available to correct the encoding of the original RGB
2986*a67afe4dSAndroid Build Coastguard Worker * values this results in an implicit assumption that the original PNG RGB
2987*a67afe4dSAndroid Build Coastguard Worker * values were linear.
2988*a67afe4dSAndroid Build Coastguard Worker *
2989*a67afe4dSAndroid Build Coastguard Worker * Other integer coefficients can be used via png_set_rgb_to_gray(). Because
2990*a67afe4dSAndroid Build Coastguard Worker * the API takes just red and green coefficients the blue coefficient is
2991*a67afe4dSAndroid Build Coastguard Worker * calculated to make the sum 32768. This will result in different rounding
2992*a67afe4dSAndroid Build Coastguard Worker * to that used above.
2993*a67afe4dSAndroid Build Coastguard Worker */
2994*a67afe4dSAndroid Build Coastguard Worker static int
png_do_rgb_to_gray(png_structrp png_ptr,png_row_infop row_info,png_bytep row)2995*a67afe4dSAndroid Build Coastguard Worker png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
2996*a67afe4dSAndroid Build Coastguard Worker {
2997*a67afe4dSAndroid Build Coastguard Worker int rgb_error = 0;
2998*a67afe4dSAndroid Build Coastguard Worker
2999*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_rgb_to_gray");
3000*a67afe4dSAndroid Build Coastguard Worker
3001*a67afe4dSAndroid Build Coastguard Worker if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
3002*a67afe4dSAndroid Build Coastguard Worker (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
3003*a67afe4dSAndroid Build Coastguard Worker {
3004*a67afe4dSAndroid Build Coastguard Worker png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
3005*a67afe4dSAndroid Build Coastguard Worker png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
3006*a67afe4dSAndroid Build Coastguard Worker png_uint_32 bc = 32768 - rc - gc;
3007*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
3008*a67afe4dSAndroid Build Coastguard Worker int have_alpha = (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
3009*a67afe4dSAndroid Build Coastguard Worker
3010*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
3011*a67afe4dSAndroid Build Coastguard Worker {
3012*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3013*a67afe4dSAndroid Build Coastguard Worker /* Notice that gamma to/from 1 are not necessarily inverses (if
3014*a67afe4dSAndroid Build Coastguard Worker * there is an overall gamma correction). Prior to 1.5.5 this code
3015*a67afe4dSAndroid Build Coastguard Worker * checked the linearized values for equality; this doesn't match
3016*a67afe4dSAndroid Build Coastguard Worker * the documentation, the original values must be checked.
3017*a67afe4dSAndroid Build Coastguard Worker */
3018*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
3019*a67afe4dSAndroid Build Coastguard Worker {
3020*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row;
3021*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = row;
3022*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
3023*a67afe4dSAndroid Build Coastguard Worker
3024*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
3025*a67afe4dSAndroid Build Coastguard Worker {
3026*a67afe4dSAndroid Build Coastguard Worker png_byte red = *(sp++);
3027*a67afe4dSAndroid Build Coastguard Worker png_byte green = *(sp++);
3028*a67afe4dSAndroid Build Coastguard Worker png_byte blue = *(sp++);
3029*a67afe4dSAndroid Build Coastguard Worker
3030*a67afe4dSAndroid Build Coastguard Worker if (red != green || red != blue)
3031*a67afe4dSAndroid Build Coastguard Worker {
3032*a67afe4dSAndroid Build Coastguard Worker red = png_ptr->gamma_to_1[red];
3033*a67afe4dSAndroid Build Coastguard Worker green = png_ptr->gamma_to_1[green];
3034*a67afe4dSAndroid Build Coastguard Worker blue = png_ptr->gamma_to_1[blue];
3035*a67afe4dSAndroid Build Coastguard Worker
3036*a67afe4dSAndroid Build Coastguard Worker rgb_error |= 1;
3037*a67afe4dSAndroid Build Coastguard Worker *(dp++) = png_ptr->gamma_from_1[
3038*a67afe4dSAndroid Build Coastguard Worker (rc*red + gc*green + bc*blue + 16384)>>15];
3039*a67afe4dSAndroid Build Coastguard Worker }
3040*a67afe4dSAndroid Build Coastguard Worker
3041*a67afe4dSAndroid Build Coastguard Worker else
3042*a67afe4dSAndroid Build Coastguard Worker {
3043*a67afe4dSAndroid Build Coastguard Worker /* If there is no overall correction the table will not be
3044*a67afe4dSAndroid Build Coastguard Worker * set.
3045*a67afe4dSAndroid Build Coastguard Worker */
3046*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->gamma_table != NULL)
3047*a67afe4dSAndroid Build Coastguard Worker red = png_ptr->gamma_table[red];
3048*a67afe4dSAndroid Build Coastguard Worker
3049*a67afe4dSAndroid Build Coastguard Worker *(dp++) = red;
3050*a67afe4dSAndroid Build Coastguard Worker }
3051*a67afe4dSAndroid Build Coastguard Worker
3052*a67afe4dSAndroid Build Coastguard Worker if (have_alpha != 0)
3053*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
3054*a67afe4dSAndroid Build Coastguard Worker }
3055*a67afe4dSAndroid Build Coastguard Worker }
3056*a67afe4dSAndroid Build Coastguard Worker else
3057*a67afe4dSAndroid Build Coastguard Worker #endif
3058*a67afe4dSAndroid Build Coastguard Worker {
3059*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row;
3060*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = row;
3061*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
3062*a67afe4dSAndroid Build Coastguard Worker
3063*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
3064*a67afe4dSAndroid Build Coastguard Worker {
3065*a67afe4dSAndroid Build Coastguard Worker png_byte red = *(sp++);
3066*a67afe4dSAndroid Build Coastguard Worker png_byte green = *(sp++);
3067*a67afe4dSAndroid Build Coastguard Worker png_byte blue = *(sp++);
3068*a67afe4dSAndroid Build Coastguard Worker
3069*a67afe4dSAndroid Build Coastguard Worker if (red != green || red != blue)
3070*a67afe4dSAndroid Build Coastguard Worker {
3071*a67afe4dSAndroid Build Coastguard Worker rgb_error |= 1;
3072*a67afe4dSAndroid Build Coastguard Worker /* NOTE: this is the historical approach which simply
3073*a67afe4dSAndroid Build Coastguard Worker * truncates the results.
3074*a67afe4dSAndroid Build Coastguard Worker */
3075*a67afe4dSAndroid Build Coastguard Worker *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
3076*a67afe4dSAndroid Build Coastguard Worker }
3077*a67afe4dSAndroid Build Coastguard Worker
3078*a67afe4dSAndroid Build Coastguard Worker else
3079*a67afe4dSAndroid Build Coastguard Worker *(dp++) = red;
3080*a67afe4dSAndroid Build Coastguard Worker
3081*a67afe4dSAndroid Build Coastguard Worker if (have_alpha != 0)
3082*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
3083*a67afe4dSAndroid Build Coastguard Worker }
3084*a67afe4dSAndroid Build Coastguard Worker }
3085*a67afe4dSAndroid Build Coastguard Worker }
3086*a67afe4dSAndroid Build Coastguard Worker
3087*a67afe4dSAndroid Build Coastguard Worker else /* RGB bit_depth == 16 */
3088*a67afe4dSAndroid Build Coastguard Worker {
3089*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3090*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
3091*a67afe4dSAndroid Build Coastguard Worker {
3092*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row;
3093*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = row;
3094*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
3095*a67afe4dSAndroid Build Coastguard Worker
3096*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
3097*a67afe4dSAndroid Build Coastguard Worker {
3098*a67afe4dSAndroid Build Coastguard Worker png_uint_16 red, green, blue, w;
3099*a67afe4dSAndroid Build Coastguard Worker png_byte hi,lo;
3100*a67afe4dSAndroid Build Coastguard Worker
3101*a67afe4dSAndroid Build Coastguard Worker hi=*(sp)++; lo=*(sp)++; red = (png_uint_16)((hi << 8) | (lo));
3102*a67afe4dSAndroid Build Coastguard Worker hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
3103*a67afe4dSAndroid Build Coastguard Worker hi=*(sp)++; lo=*(sp)++; blue = (png_uint_16)((hi << 8) | (lo));
3104*a67afe4dSAndroid Build Coastguard Worker
3105*a67afe4dSAndroid Build Coastguard Worker if (red == green && red == blue)
3106*a67afe4dSAndroid Build Coastguard Worker {
3107*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->gamma_16_table != NULL)
3108*a67afe4dSAndroid Build Coastguard Worker w = png_ptr->gamma_16_table[(red & 0xff)
3109*a67afe4dSAndroid Build Coastguard Worker >> png_ptr->gamma_shift][red >> 8];
3110*a67afe4dSAndroid Build Coastguard Worker
3111*a67afe4dSAndroid Build Coastguard Worker else
3112*a67afe4dSAndroid Build Coastguard Worker w = red;
3113*a67afe4dSAndroid Build Coastguard Worker }
3114*a67afe4dSAndroid Build Coastguard Worker
3115*a67afe4dSAndroid Build Coastguard Worker else
3116*a67afe4dSAndroid Build Coastguard Worker {
3117*a67afe4dSAndroid Build Coastguard Worker png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red & 0xff)
3118*a67afe4dSAndroid Build Coastguard Worker >> png_ptr->gamma_shift][red>>8];
3119*a67afe4dSAndroid Build Coastguard Worker png_uint_16 green_1 =
3120*a67afe4dSAndroid Build Coastguard Worker png_ptr->gamma_16_to_1[(green & 0xff) >>
3121*a67afe4dSAndroid Build Coastguard Worker png_ptr->gamma_shift][green>>8];
3122*a67afe4dSAndroid Build Coastguard Worker png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue & 0xff)
3123*a67afe4dSAndroid Build Coastguard Worker >> png_ptr->gamma_shift][blue>>8];
3124*a67afe4dSAndroid Build Coastguard Worker png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
3125*a67afe4dSAndroid Build Coastguard Worker + bc*blue_1 + 16384)>>15);
3126*a67afe4dSAndroid Build Coastguard Worker w = png_ptr->gamma_16_from_1[(gray16 & 0xff) >>
3127*a67afe4dSAndroid Build Coastguard Worker png_ptr->gamma_shift][gray16 >> 8];
3128*a67afe4dSAndroid Build Coastguard Worker rgb_error |= 1;
3129*a67afe4dSAndroid Build Coastguard Worker }
3130*a67afe4dSAndroid Build Coastguard Worker
3131*a67afe4dSAndroid Build Coastguard Worker *(dp++) = (png_byte)((w>>8) & 0xff);
3132*a67afe4dSAndroid Build Coastguard Worker *(dp++) = (png_byte)(w & 0xff);
3133*a67afe4dSAndroid Build Coastguard Worker
3134*a67afe4dSAndroid Build Coastguard Worker if (have_alpha != 0)
3135*a67afe4dSAndroid Build Coastguard Worker {
3136*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
3137*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
3138*a67afe4dSAndroid Build Coastguard Worker }
3139*a67afe4dSAndroid Build Coastguard Worker }
3140*a67afe4dSAndroid Build Coastguard Worker }
3141*a67afe4dSAndroid Build Coastguard Worker else
3142*a67afe4dSAndroid Build Coastguard Worker #endif
3143*a67afe4dSAndroid Build Coastguard Worker {
3144*a67afe4dSAndroid Build Coastguard Worker png_bytep sp = row;
3145*a67afe4dSAndroid Build Coastguard Worker png_bytep dp = row;
3146*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
3147*a67afe4dSAndroid Build Coastguard Worker
3148*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
3149*a67afe4dSAndroid Build Coastguard Worker {
3150*a67afe4dSAndroid Build Coastguard Worker png_uint_16 red, green, blue, gray16;
3151*a67afe4dSAndroid Build Coastguard Worker png_byte hi,lo;
3152*a67afe4dSAndroid Build Coastguard Worker
3153*a67afe4dSAndroid Build Coastguard Worker hi=*(sp)++; lo=*(sp)++; red = (png_uint_16)((hi << 8) | (lo));
3154*a67afe4dSAndroid Build Coastguard Worker hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
3155*a67afe4dSAndroid Build Coastguard Worker hi=*(sp)++; lo=*(sp)++; blue = (png_uint_16)((hi << 8) | (lo));
3156*a67afe4dSAndroid Build Coastguard Worker
3157*a67afe4dSAndroid Build Coastguard Worker if (red != green || red != blue)
3158*a67afe4dSAndroid Build Coastguard Worker rgb_error |= 1;
3159*a67afe4dSAndroid Build Coastguard Worker
3160*a67afe4dSAndroid Build Coastguard Worker /* From 1.5.5 in the 16-bit case do the accurate conversion even
3161*a67afe4dSAndroid Build Coastguard Worker * in the 'fast' case - this is because this is where the code
3162*a67afe4dSAndroid Build Coastguard Worker * ends up when handling linear 16-bit data.
3163*a67afe4dSAndroid Build Coastguard Worker */
3164*a67afe4dSAndroid Build Coastguard Worker gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
3165*a67afe4dSAndroid Build Coastguard Worker 15);
3166*a67afe4dSAndroid Build Coastguard Worker *(dp++) = (png_byte)((gray16 >> 8) & 0xff);
3167*a67afe4dSAndroid Build Coastguard Worker *(dp++) = (png_byte)(gray16 & 0xff);
3168*a67afe4dSAndroid Build Coastguard Worker
3169*a67afe4dSAndroid Build Coastguard Worker if (have_alpha != 0)
3170*a67afe4dSAndroid Build Coastguard Worker {
3171*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
3172*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
3173*a67afe4dSAndroid Build Coastguard Worker }
3174*a67afe4dSAndroid Build Coastguard Worker }
3175*a67afe4dSAndroid Build Coastguard Worker }
3176*a67afe4dSAndroid Build Coastguard Worker }
3177*a67afe4dSAndroid Build Coastguard Worker
3178*a67afe4dSAndroid Build Coastguard Worker row_info->channels = (png_byte)(row_info->channels - 2);
3179*a67afe4dSAndroid Build Coastguard Worker row_info->color_type = (png_byte)(row_info->color_type &
3180*a67afe4dSAndroid Build Coastguard Worker ~PNG_COLOR_MASK_COLOR);
3181*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = (png_byte)(row_info->channels *
3182*a67afe4dSAndroid Build Coastguard Worker row_info->bit_depth);
3183*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3184*a67afe4dSAndroid Build Coastguard Worker }
3185*a67afe4dSAndroid Build Coastguard Worker return rgb_error;
3186*a67afe4dSAndroid Build Coastguard Worker }
3187*a67afe4dSAndroid Build Coastguard Worker #endif
3188*a67afe4dSAndroid Build Coastguard Worker
3189*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
3190*a67afe4dSAndroid Build Coastguard Worker defined(PNG_READ_ALPHA_MODE_SUPPORTED)
3191*a67afe4dSAndroid Build Coastguard Worker /* Replace any alpha or transparency with the supplied background color.
3192*a67afe4dSAndroid Build Coastguard Worker * "background" is already in the screen gamma, while "background_1" is
3193*a67afe4dSAndroid Build Coastguard Worker * at a gamma of 1.0. Paletted files have already been taken care of.
3194*a67afe4dSAndroid Build Coastguard Worker */
3195*a67afe4dSAndroid Build Coastguard Worker static void
png_do_compose(png_row_infop row_info,png_bytep row,png_structrp png_ptr)3196*a67afe4dSAndroid Build Coastguard Worker png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
3197*a67afe4dSAndroid Build Coastguard Worker {
3198*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3199*a67afe4dSAndroid Build Coastguard Worker png_const_bytep gamma_table = png_ptr->gamma_table;
3200*a67afe4dSAndroid Build Coastguard Worker png_const_bytep gamma_from_1 = png_ptr->gamma_from_1;
3201*a67afe4dSAndroid Build Coastguard Worker png_const_bytep gamma_to_1 = png_ptr->gamma_to_1;
3202*a67afe4dSAndroid Build Coastguard Worker png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table;
3203*a67afe4dSAndroid Build Coastguard Worker png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
3204*a67afe4dSAndroid Build Coastguard Worker png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
3205*a67afe4dSAndroid Build Coastguard Worker int gamma_shift = png_ptr->gamma_shift;
3206*a67afe4dSAndroid Build Coastguard Worker int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
3207*a67afe4dSAndroid Build Coastguard Worker #endif
3208*a67afe4dSAndroid Build Coastguard Worker
3209*a67afe4dSAndroid Build Coastguard Worker png_bytep sp;
3210*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
3211*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
3212*a67afe4dSAndroid Build Coastguard Worker int shift;
3213*a67afe4dSAndroid Build Coastguard Worker
3214*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_compose");
3215*a67afe4dSAndroid Build Coastguard Worker
3216*a67afe4dSAndroid Build Coastguard Worker switch (row_info->color_type)
3217*a67afe4dSAndroid Build Coastguard Worker {
3218*a67afe4dSAndroid Build Coastguard Worker case PNG_COLOR_TYPE_GRAY:
3219*a67afe4dSAndroid Build Coastguard Worker {
3220*a67afe4dSAndroid Build Coastguard Worker switch (row_info->bit_depth)
3221*a67afe4dSAndroid Build Coastguard Worker {
3222*a67afe4dSAndroid Build Coastguard Worker case 1:
3223*a67afe4dSAndroid Build Coastguard Worker {
3224*a67afe4dSAndroid Build Coastguard Worker sp = row;
3225*a67afe4dSAndroid Build Coastguard Worker shift = 7;
3226*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
3227*a67afe4dSAndroid Build Coastguard Worker {
3228*a67afe4dSAndroid Build Coastguard Worker if ((png_uint_16)((*sp >> shift) & 0x01)
3229*a67afe4dSAndroid Build Coastguard Worker == png_ptr->trans_color.gray)
3230*a67afe4dSAndroid Build Coastguard Worker {
3231*a67afe4dSAndroid Build Coastguard Worker unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
3232*a67afe4dSAndroid Build Coastguard Worker tmp |=
3233*a67afe4dSAndroid Build Coastguard Worker (unsigned int)(png_ptr->background.gray << shift);
3234*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)(tmp & 0xff);
3235*a67afe4dSAndroid Build Coastguard Worker }
3236*a67afe4dSAndroid Build Coastguard Worker
3237*a67afe4dSAndroid Build Coastguard Worker if (shift == 0)
3238*a67afe4dSAndroid Build Coastguard Worker {
3239*a67afe4dSAndroid Build Coastguard Worker shift = 7;
3240*a67afe4dSAndroid Build Coastguard Worker sp++;
3241*a67afe4dSAndroid Build Coastguard Worker }
3242*a67afe4dSAndroid Build Coastguard Worker
3243*a67afe4dSAndroid Build Coastguard Worker else
3244*a67afe4dSAndroid Build Coastguard Worker shift--;
3245*a67afe4dSAndroid Build Coastguard Worker }
3246*a67afe4dSAndroid Build Coastguard Worker break;
3247*a67afe4dSAndroid Build Coastguard Worker }
3248*a67afe4dSAndroid Build Coastguard Worker
3249*a67afe4dSAndroid Build Coastguard Worker case 2:
3250*a67afe4dSAndroid Build Coastguard Worker {
3251*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3252*a67afe4dSAndroid Build Coastguard Worker if (gamma_table != NULL)
3253*a67afe4dSAndroid Build Coastguard Worker {
3254*a67afe4dSAndroid Build Coastguard Worker sp = row;
3255*a67afe4dSAndroid Build Coastguard Worker shift = 6;
3256*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
3257*a67afe4dSAndroid Build Coastguard Worker {
3258*a67afe4dSAndroid Build Coastguard Worker if ((png_uint_16)((*sp >> shift) & 0x03)
3259*a67afe4dSAndroid Build Coastguard Worker == png_ptr->trans_color.gray)
3260*a67afe4dSAndroid Build Coastguard Worker {
3261*a67afe4dSAndroid Build Coastguard Worker unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3262*a67afe4dSAndroid Build Coastguard Worker tmp |=
3263*a67afe4dSAndroid Build Coastguard Worker (unsigned int)png_ptr->background.gray << shift;
3264*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)(tmp & 0xff);
3265*a67afe4dSAndroid Build Coastguard Worker }
3266*a67afe4dSAndroid Build Coastguard Worker
3267*a67afe4dSAndroid Build Coastguard Worker else
3268*a67afe4dSAndroid Build Coastguard Worker {
3269*a67afe4dSAndroid Build Coastguard Worker unsigned int p = (*sp >> shift) & 0x03;
3270*a67afe4dSAndroid Build Coastguard Worker unsigned int g = (gamma_table [p | (p << 2) |
3271*a67afe4dSAndroid Build Coastguard Worker (p << 4) | (p << 6)] >> 6) & 0x03;
3272*a67afe4dSAndroid Build Coastguard Worker unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3273*a67afe4dSAndroid Build Coastguard Worker tmp |= (unsigned int)(g << shift);
3274*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)(tmp & 0xff);
3275*a67afe4dSAndroid Build Coastguard Worker }
3276*a67afe4dSAndroid Build Coastguard Worker
3277*a67afe4dSAndroid Build Coastguard Worker if (shift == 0)
3278*a67afe4dSAndroid Build Coastguard Worker {
3279*a67afe4dSAndroid Build Coastguard Worker shift = 6;
3280*a67afe4dSAndroid Build Coastguard Worker sp++;
3281*a67afe4dSAndroid Build Coastguard Worker }
3282*a67afe4dSAndroid Build Coastguard Worker
3283*a67afe4dSAndroid Build Coastguard Worker else
3284*a67afe4dSAndroid Build Coastguard Worker shift -= 2;
3285*a67afe4dSAndroid Build Coastguard Worker }
3286*a67afe4dSAndroid Build Coastguard Worker }
3287*a67afe4dSAndroid Build Coastguard Worker
3288*a67afe4dSAndroid Build Coastguard Worker else
3289*a67afe4dSAndroid Build Coastguard Worker #endif
3290*a67afe4dSAndroid Build Coastguard Worker {
3291*a67afe4dSAndroid Build Coastguard Worker sp = row;
3292*a67afe4dSAndroid Build Coastguard Worker shift = 6;
3293*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
3294*a67afe4dSAndroid Build Coastguard Worker {
3295*a67afe4dSAndroid Build Coastguard Worker if ((png_uint_16)((*sp >> shift) & 0x03)
3296*a67afe4dSAndroid Build Coastguard Worker == png_ptr->trans_color.gray)
3297*a67afe4dSAndroid Build Coastguard Worker {
3298*a67afe4dSAndroid Build Coastguard Worker unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
3299*a67afe4dSAndroid Build Coastguard Worker tmp |=
3300*a67afe4dSAndroid Build Coastguard Worker (unsigned int)png_ptr->background.gray << shift;
3301*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)(tmp & 0xff);
3302*a67afe4dSAndroid Build Coastguard Worker }
3303*a67afe4dSAndroid Build Coastguard Worker
3304*a67afe4dSAndroid Build Coastguard Worker if (shift == 0)
3305*a67afe4dSAndroid Build Coastguard Worker {
3306*a67afe4dSAndroid Build Coastguard Worker shift = 6;
3307*a67afe4dSAndroid Build Coastguard Worker sp++;
3308*a67afe4dSAndroid Build Coastguard Worker }
3309*a67afe4dSAndroid Build Coastguard Worker
3310*a67afe4dSAndroid Build Coastguard Worker else
3311*a67afe4dSAndroid Build Coastguard Worker shift -= 2;
3312*a67afe4dSAndroid Build Coastguard Worker }
3313*a67afe4dSAndroid Build Coastguard Worker }
3314*a67afe4dSAndroid Build Coastguard Worker break;
3315*a67afe4dSAndroid Build Coastguard Worker }
3316*a67afe4dSAndroid Build Coastguard Worker
3317*a67afe4dSAndroid Build Coastguard Worker case 4:
3318*a67afe4dSAndroid Build Coastguard Worker {
3319*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3320*a67afe4dSAndroid Build Coastguard Worker if (gamma_table != NULL)
3321*a67afe4dSAndroid Build Coastguard Worker {
3322*a67afe4dSAndroid Build Coastguard Worker sp = row;
3323*a67afe4dSAndroid Build Coastguard Worker shift = 4;
3324*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
3325*a67afe4dSAndroid Build Coastguard Worker {
3326*a67afe4dSAndroid Build Coastguard Worker if ((png_uint_16)((*sp >> shift) & 0x0f)
3327*a67afe4dSAndroid Build Coastguard Worker == png_ptr->trans_color.gray)
3328*a67afe4dSAndroid Build Coastguard Worker {
3329*a67afe4dSAndroid Build Coastguard Worker unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3330*a67afe4dSAndroid Build Coastguard Worker tmp |=
3331*a67afe4dSAndroid Build Coastguard Worker (unsigned int)(png_ptr->background.gray << shift);
3332*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)(tmp & 0xff);
3333*a67afe4dSAndroid Build Coastguard Worker }
3334*a67afe4dSAndroid Build Coastguard Worker
3335*a67afe4dSAndroid Build Coastguard Worker else
3336*a67afe4dSAndroid Build Coastguard Worker {
3337*a67afe4dSAndroid Build Coastguard Worker unsigned int p = (*sp >> shift) & 0x0f;
3338*a67afe4dSAndroid Build Coastguard Worker unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
3339*a67afe4dSAndroid Build Coastguard Worker 0x0f;
3340*a67afe4dSAndroid Build Coastguard Worker unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3341*a67afe4dSAndroid Build Coastguard Worker tmp |= (unsigned int)(g << shift);
3342*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)(tmp & 0xff);
3343*a67afe4dSAndroid Build Coastguard Worker }
3344*a67afe4dSAndroid Build Coastguard Worker
3345*a67afe4dSAndroid Build Coastguard Worker if (shift == 0)
3346*a67afe4dSAndroid Build Coastguard Worker {
3347*a67afe4dSAndroid Build Coastguard Worker shift = 4;
3348*a67afe4dSAndroid Build Coastguard Worker sp++;
3349*a67afe4dSAndroid Build Coastguard Worker }
3350*a67afe4dSAndroid Build Coastguard Worker
3351*a67afe4dSAndroid Build Coastguard Worker else
3352*a67afe4dSAndroid Build Coastguard Worker shift -= 4;
3353*a67afe4dSAndroid Build Coastguard Worker }
3354*a67afe4dSAndroid Build Coastguard Worker }
3355*a67afe4dSAndroid Build Coastguard Worker
3356*a67afe4dSAndroid Build Coastguard Worker else
3357*a67afe4dSAndroid Build Coastguard Worker #endif
3358*a67afe4dSAndroid Build Coastguard Worker {
3359*a67afe4dSAndroid Build Coastguard Worker sp = row;
3360*a67afe4dSAndroid Build Coastguard Worker shift = 4;
3361*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
3362*a67afe4dSAndroid Build Coastguard Worker {
3363*a67afe4dSAndroid Build Coastguard Worker if ((png_uint_16)((*sp >> shift) & 0x0f)
3364*a67afe4dSAndroid Build Coastguard Worker == png_ptr->trans_color.gray)
3365*a67afe4dSAndroid Build Coastguard Worker {
3366*a67afe4dSAndroid Build Coastguard Worker unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
3367*a67afe4dSAndroid Build Coastguard Worker tmp |=
3368*a67afe4dSAndroid Build Coastguard Worker (unsigned int)(png_ptr->background.gray << shift);
3369*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)(tmp & 0xff);
3370*a67afe4dSAndroid Build Coastguard Worker }
3371*a67afe4dSAndroid Build Coastguard Worker
3372*a67afe4dSAndroid Build Coastguard Worker if (shift == 0)
3373*a67afe4dSAndroid Build Coastguard Worker {
3374*a67afe4dSAndroid Build Coastguard Worker shift = 4;
3375*a67afe4dSAndroid Build Coastguard Worker sp++;
3376*a67afe4dSAndroid Build Coastguard Worker }
3377*a67afe4dSAndroid Build Coastguard Worker
3378*a67afe4dSAndroid Build Coastguard Worker else
3379*a67afe4dSAndroid Build Coastguard Worker shift -= 4;
3380*a67afe4dSAndroid Build Coastguard Worker }
3381*a67afe4dSAndroid Build Coastguard Worker }
3382*a67afe4dSAndroid Build Coastguard Worker break;
3383*a67afe4dSAndroid Build Coastguard Worker }
3384*a67afe4dSAndroid Build Coastguard Worker
3385*a67afe4dSAndroid Build Coastguard Worker case 8:
3386*a67afe4dSAndroid Build Coastguard Worker {
3387*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3388*a67afe4dSAndroid Build Coastguard Worker if (gamma_table != NULL)
3389*a67afe4dSAndroid Build Coastguard Worker {
3390*a67afe4dSAndroid Build Coastguard Worker sp = row;
3391*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp++)
3392*a67afe4dSAndroid Build Coastguard Worker {
3393*a67afe4dSAndroid Build Coastguard Worker if (*sp == png_ptr->trans_color.gray)
3394*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)png_ptr->background.gray;
3395*a67afe4dSAndroid Build Coastguard Worker
3396*a67afe4dSAndroid Build Coastguard Worker else
3397*a67afe4dSAndroid Build Coastguard Worker *sp = gamma_table[*sp];
3398*a67afe4dSAndroid Build Coastguard Worker }
3399*a67afe4dSAndroid Build Coastguard Worker }
3400*a67afe4dSAndroid Build Coastguard Worker else
3401*a67afe4dSAndroid Build Coastguard Worker #endif
3402*a67afe4dSAndroid Build Coastguard Worker {
3403*a67afe4dSAndroid Build Coastguard Worker sp = row;
3404*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp++)
3405*a67afe4dSAndroid Build Coastguard Worker {
3406*a67afe4dSAndroid Build Coastguard Worker if (*sp == png_ptr->trans_color.gray)
3407*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)png_ptr->background.gray;
3408*a67afe4dSAndroid Build Coastguard Worker }
3409*a67afe4dSAndroid Build Coastguard Worker }
3410*a67afe4dSAndroid Build Coastguard Worker break;
3411*a67afe4dSAndroid Build Coastguard Worker }
3412*a67afe4dSAndroid Build Coastguard Worker
3413*a67afe4dSAndroid Build Coastguard Worker case 16:
3414*a67afe4dSAndroid Build Coastguard Worker {
3415*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3416*a67afe4dSAndroid Build Coastguard Worker if (gamma_16 != NULL)
3417*a67afe4dSAndroid Build Coastguard Worker {
3418*a67afe4dSAndroid Build Coastguard Worker sp = row;
3419*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 2)
3420*a67afe4dSAndroid Build Coastguard Worker {
3421*a67afe4dSAndroid Build Coastguard Worker png_uint_16 v;
3422*a67afe4dSAndroid Build Coastguard Worker
3423*a67afe4dSAndroid Build Coastguard Worker v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3424*a67afe4dSAndroid Build Coastguard Worker
3425*a67afe4dSAndroid Build Coastguard Worker if (v == png_ptr->trans_color.gray)
3426*a67afe4dSAndroid Build Coastguard Worker {
3427*a67afe4dSAndroid Build Coastguard Worker /* Background is already in screen gamma */
3428*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((png_ptr->background.gray >> 8)
3429*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3430*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(png_ptr->background.gray
3431*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3432*a67afe4dSAndroid Build Coastguard Worker }
3433*a67afe4dSAndroid Build Coastguard Worker
3434*a67afe4dSAndroid Build Coastguard Worker else
3435*a67afe4dSAndroid Build Coastguard Worker {
3436*a67afe4dSAndroid Build Coastguard Worker v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3437*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
3438*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
3439*a67afe4dSAndroid Build Coastguard Worker }
3440*a67afe4dSAndroid Build Coastguard Worker }
3441*a67afe4dSAndroid Build Coastguard Worker }
3442*a67afe4dSAndroid Build Coastguard Worker else
3443*a67afe4dSAndroid Build Coastguard Worker #endif
3444*a67afe4dSAndroid Build Coastguard Worker {
3445*a67afe4dSAndroid Build Coastguard Worker sp = row;
3446*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 2)
3447*a67afe4dSAndroid Build Coastguard Worker {
3448*a67afe4dSAndroid Build Coastguard Worker png_uint_16 v;
3449*a67afe4dSAndroid Build Coastguard Worker
3450*a67afe4dSAndroid Build Coastguard Worker v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3451*a67afe4dSAndroid Build Coastguard Worker
3452*a67afe4dSAndroid Build Coastguard Worker if (v == png_ptr->trans_color.gray)
3453*a67afe4dSAndroid Build Coastguard Worker {
3454*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((png_ptr->background.gray >> 8)
3455*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3456*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(png_ptr->background.gray
3457*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3458*a67afe4dSAndroid Build Coastguard Worker }
3459*a67afe4dSAndroid Build Coastguard Worker }
3460*a67afe4dSAndroid Build Coastguard Worker }
3461*a67afe4dSAndroid Build Coastguard Worker break;
3462*a67afe4dSAndroid Build Coastguard Worker }
3463*a67afe4dSAndroid Build Coastguard Worker
3464*a67afe4dSAndroid Build Coastguard Worker default:
3465*a67afe4dSAndroid Build Coastguard Worker break;
3466*a67afe4dSAndroid Build Coastguard Worker }
3467*a67afe4dSAndroid Build Coastguard Worker break;
3468*a67afe4dSAndroid Build Coastguard Worker }
3469*a67afe4dSAndroid Build Coastguard Worker
3470*a67afe4dSAndroid Build Coastguard Worker case PNG_COLOR_TYPE_RGB:
3471*a67afe4dSAndroid Build Coastguard Worker {
3472*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
3473*a67afe4dSAndroid Build Coastguard Worker {
3474*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3475*a67afe4dSAndroid Build Coastguard Worker if (gamma_table != NULL)
3476*a67afe4dSAndroid Build Coastguard Worker {
3477*a67afe4dSAndroid Build Coastguard Worker sp = row;
3478*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 3)
3479*a67afe4dSAndroid Build Coastguard Worker {
3480*a67afe4dSAndroid Build Coastguard Worker if (*sp == png_ptr->trans_color.red &&
3481*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) == png_ptr->trans_color.green &&
3482*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) == png_ptr->trans_color.blue)
3483*a67afe4dSAndroid Build Coastguard Worker {
3484*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)png_ptr->background.red;
3485*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)png_ptr->background.green;
3486*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = (png_byte)png_ptr->background.blue;
3487*a67afe4dSAndroid Build Coastguard Worker }
3488*a67afe4dSAndroid Build Coastguard Worker
3489*a67afe4dSAndroid Build Coastguard Worker else
3490*a67afe4dSAndroid Build Coastguard Worker {
3491*a67afe4dSAndroid Build Coastguard Worker *sp = gamma_table[*sp];
3492*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = gamma_table[*(sp + 1)];
3493*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = gamma_table[*(sp + 2)];
3494*a67afe4dSAndroid Build Coastguard Worker }
3495*a67afe4dSAndroid Build Coastguard Worker }
3496*a67afe4dSAndroid Build Coastguard Worker }
3497*a67afe4dSAndroid Build Coastguard Worker else
3498*a67afe4dSAndroid Build Coastguard Worker #endif
3499*a67afe4dSAndroid Build Coastguard Worker {
3500*a67afe4dSAndroid Build Coastguard Worker sp = row;
3501*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 3)
3502*a67afe4dSAndroid Build Coastguard Worker {
3503*a67afe4dSAndroid Build Coastguard Worker if (*sp == png_ptr->trans_color.red &&
3504*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) == png_ptr->trans_color.green &&
3505*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) == png_ptr->trans_color.blue)
3506*a67afe4dSAndroid Build Coastguard Worker {
3507*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)png_ptr->background.red;
3508*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)png_ptr->background.green;
3509*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = (png_byte)png_ptr->background.blue;
3510*a67afe4dSAndroid Build Coastguard Worker }
3511*a67afe4dSAndroid Build Coastguard Worker }
3512*a67afe4dSAndroid Build Coastguard Worker }
3513*a67afe4dSAndroid Build Coastguard Worker }
3514*a67afe4dSAndroid Build Coastguard Worker else /* if (row_info->bit_depth == 16) */
3515*a67afe4dSAndroid Build Coastguard Worker {
3516*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3517*a67afe4dSAndroid Build Coastguard Worker if (gamma_16 != NULL)
3518*a67afe4dSAndroid Build Coastguard Worker {
3519*a67afe4dSAndroid Build Coastguard Worker sp = row;
3520*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 6)
3521*a67afe4dSAndroid Build Coastguard Worker {
3522*a67afe4dSAndroid Build Coastguard Worker png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3523*a67afe4dSAndroid Build Coastguard Worker
3524*a67afe4dSAndroid Build Coastguard Worker png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3525*a67afe4dSAndroid Build Coastguard Worker + *(sp + 3));
3526*a67afe4dSAndroid Build Coastguard Worker
3527*a67afe4dSAndroid Build Coastguard Worker png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3528*a67afe4dSAndroid Build Coastguard Worker + *(sp + 5));
3529*a67afe4dSAndroid Build Coastguard Worker
3530*a67afe4dSAndroid Build Coastguard Worker if (r == png_ptr->trans_color.red &&
3531*a67afe4dSAndroid Build Coastguard Worker g == png_ptr->trans_color.green &&
3532*a67afe4dSAndroid Build Coastguard Worker b == png_ptr->trans_color.blue)
3533*a67afe4dSAndroid Build Coastguard Worker {
3534*a67afe4dSAndroid Build Coastguard Worker /* Background is already in screen gamma */
3535*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3536*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3537*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3538*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3539*a67afe4dSAndroid Build Coastguard Worker *(sp + 3) = (png_byte)(png_ptr->background.green
3540*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3541*a67afe4dSAndroid Build Coastguard Worker *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3542*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3543*a67afe4dSAndroid Build Coastguard Worker *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3544*a67afe4dSAndroid Build Coastguard Worker }
3545*a67afe4dSAndroid Build Coastguard Worker
3546*a67afe4dSAndroid Build Coastguard Worker else
3547*a67afe4dSAndroid Build Coastguard Worker {
3548*a67afe4dSAndroid Build Coastguard Worker png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3549*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
3550*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
3551*a67afe4dSAndroid Build Coastguard Worker
3552*a67afe4dSAndroid Build Coastguard Worker v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3553*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3554*a67afe4dSAndroid Build Coastguard Worker *(sp + 3) = (png_byte)(v & 0xff);
3555*a67afe4dSAndroid Build Coastguard Worker
3556*a67afe4dSAndroid Build Coastguard Worker v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3557*a67afe4dSAndroid Build Coastguard Worker *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3558*a67afe4dSAndroid Build Coastguard Worker *(sp + 5) = (png_byte)(v & 0xff);
3559*a67afe4dSAndroid Build Coastguard Worker }
3560*a67afe4dSAndroid Build Coastguard Worker }
3561*a67afe4dSAndroid Build Coastguard Worker }
3562*a67afe4dSAndroid Build Coastguard Worker
3563*a67afe4dSAndroid Build Coastguard Worker else
3564*a67afe4dSAndroid Build Coastguard Worker #endif
3565*a67afe4dSAndroid Build Coastguard Worker {
3566*a67afe4dSAndroid Build Coastguard Worker sp = row;
3567*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 6)
3568*a67afe4dSAndroid Build Coastguard Worker {
3569*a67afe4dSAndroid Build Coastguard Worker png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3570*a67afe4dSAndroid Build Coastguard Worker
3571*a67afe4dSAndroid Build Coastguard Worker png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3572*a67afe4dSAndroid Build Coastguard Worker + *(sp + 3));
3573*a67afe4dSAndroid Build Coastguard Worker
3574*a67afe4dSAndroid Build Coastguard Worker png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3575*a67afe4dSAndroid Build Coastguard Worker + *(sp + 5));
3576*a67afe4dSAndroid Build Coastguard Worker
3577*a67afe4dSAndroid Build Coastguard Worker if (r == png_ptr->trans_color.red &&
3578*a67afe4dSAndroid Build Coastguard Worker g == png_ptr->trans_color.green &&
3579*a67afe4dSAndroid Build Coastguard Worker b == png_ptr->trans_color.blue)
3580*a67afe4dSAndroid Build Coastguard Worker {
3581*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3582*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3583*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3584*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3585*a67afe4dSAndroid Build Coastguard Worker *(sp + 3) = (png_byte)(png_ptr->background.green
3586*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3587*a67afe4dSAndroid Build Coastguard Worker *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3588*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3589*a67afe4dSAndroid Build Coastguard Worker *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3590*a67afe4dSAndroid Build Coastguard Worker }
3591*a67afe4dSAndroid Build Coastguard Worker }
3592*a67afe4dSAndroid Build Coastguard Worker }
3593*a67afe4dSAndroid Build Coastguard Worker }
3594*a67afe4dSAndroid Build Coastguard Worker break;
3595*a67afe4dSAndroid Build Coastguard Worker }
3596*a67afe4dSAndroid Build Coastguard Worker
3597*a67afe4dSAndroid Build Coastguard Worker case PNG_COLOR_TYPE_GRAY_ALPHA:
3598*a67afe4dSAndroid Build Coastguard Worker {
3599*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
3600*a67afe4dSAndroid Build Coastguard Worker {
3601*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3602*a67afe4dSAndroid Build Coastguard Worker if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3603*a67afe4dSAndroid Build Coastguard Worker gamma_table != NULL)
3604*a67afe4dSAndroid Build Coastguard Worker {
3605*a67afe4dSAndroid Build Coastguard Worker sp = row;
3606*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 2)
3607*a67afe4dSAndroid Build Coastguard Worker {
3608*a67afe4dSAndroid Build Coastguard Worker png_uint_16 a = *(sp + 1);
3609*a67afe4dSAndroid Build Coastguard Worker
3610*a67afe4dSAndroid Build Coastguard Worker if (a == 0xff)
3611*a67afe4dSAndroid Build Coastguard Worker *sp = gamma_table[*sp];
3612*a67afe4dSAndroid Build Coastguard Worker
3613*a67afe4dSAndroid Build Coastguard Worker else if (a == 0)
3614*a67afe4dSAndroid Build Coastguard Worker {
3615*a67afe4dSAndroid Build Coastguard Worker /* Background is already in screen gamma */
3616*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)png_ptr->background.gray;
3617*a67afe4dSAndroid Build Coastguard Worker }
3618*a67afe4dSAndroid Build Coastguard Worker
3619*a67afe4dSAndroid Build Coastguard Worker else
3620*a67afe4dSAndroid Build Coastguard Worker {
3621*a67afe4dSAndroid Build Coastguard Worker png_byte v, w;
3622*a67afe4dSAndroid Build Coastguard Worker
3623*a67afe4dSAndroid Build Coastguard Worker v = gamma_to_1[*sp];
3624*a67afe4dSAndroid Build Coastguard Worker png_composite(w, v, a, png_ptr->background_1.gray);
3625*a67afe4dSAndroid Build Coastguard Worker if (optimize == 0)
3626*a67afe4dSAndroid Build Coastguard Worker w = gamma_from_1[w];
3627*a67afe4dSAndroid Build Coastguard Worker *sp = w;
3628*a67afe4dSAndroid Build Coastguard Worker }
3629*a67afe4dSAndroid Build Coastguard Worker }
3630*a67afe4dSAndroid Build Coastguard Worker }
3631*a67afe4dSAndroid Build Coastguard Worker else
3632*a67afe4dSAndroid Build Coastguard Worker #endif
3633*a67afe4dSAndroid Build Coastguard Worker {
3634*a67afe4dSAndroid Build Coastguard Worker sp = row;
3635*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 2)
3636*a67afe4dSAndroid Build Coastguard Worker {
3637*a67afe4dSAndroid Build Coastguard Worker png_byte a = *(sp + 1);
3638*a67afe4dSAndroid Build Coastguard Worker
3639*a67afe4dSAndroid Build Coastguard Worker if (a == 0)
3640*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)png_ptr->background.gray;
3641*a67afe4dSAndroid Build Coastguard Worker
3642*a67afe4dSAndroid Build Coastguard Worker else if (a < 0xff)
3643*a67afe4dSAndroid Build Coastguard Worker png_composite(*sp, *sp, a, png_ptr->background.gray);
3644*a67afe4dSAndroid Build Coastguard Worker }
3645*a67afe4dSAndroid Build Coastguard Worker }
3646*a67afe4dSAndroid Build Coastguard Worker }
3647*a67afe4dSAndroid Build Coastguard Worker else /* if (png_ptr->bit_depth == 16) */
3648*a67afe4dSAndroid Build Coastguard Worker {
3649*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3650*a67afe4dSAndroid Build Coastguard Worker if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3651*a67afe4dSAndroid Build Coastguard Worker gamma_16_to_1 != NULL)
3652*a67afe4dSAndroid Build Coastguard Worker {
3653*a67afe4dSAndroid Build Coastguard Worker sp = row;
3654*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 4)
3655*a67afe4dSAndroid Build Coastguard Worker {
3656*a67afe4dSAndroid Build Coastguard Worker png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
3657*a67afe4dSAndroid Build Coastguard Worker + *(sp + 3));
3658*a67afe4dSAndroid Build Coastguard Worker
3659*a67afe4dSAndroid Build Coastguard Worker if (a == (png_uint_16)0xffff)
3660*a67afe4dSAndroid Build Coastguard Worker {
3661*a67afe4dSAndroid Build Coastguard Worker png_uint_16 v;
3662*a67afe4dSAndroid Build Coastguard Worker
3663*a67afe4dSAndroid Build Coastguard Worker v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3664*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
3665*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
3666*a67afe4dSAndroid Build Coastguard Worker }
3667*a67afe4dSAndroid Build Coastguard Worker
3668*a67afe4dSAndroid Build Coastguard Worker else if (a == 0)
3669*a67afe4dSAndroid Build Coastguard Worker {
3670*a67afe4dSAndroid Build Coastguard Worker /* Background is already in screen gamma */
3671*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((png_ptr->background.gray >> 8)
3672*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3673*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
3674*a67afe4dSAndroid Build Coastguard Worker }
3675*a67afe4dSAndroid Build Coastguard Worker
3676*a67afe4dSAndroid Build Coastguard Worker else
3677*a67afe4dSAndroid Build Coastguard Worker {
3678*a67afe4dSAndroid Build Coastguard Worker png_uint_16 g, v, w;
3679*a67afe4dSAndroid Build Coastguard Worker
3680*a67afe4dSAndroid Build Coastguard Worker g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3681*a67afe4dSAndroid Build Coastguard Worker png_composite_16(v, g, a, png_ptr->background_1.gray);
3682*a67afe4dSAndroid Build Coastguard Worker if (optimize != 0)
3683*a67afe4dSAndroid Build Coastguard Worker w = v;
3684*a67afe4dSAndroid Build Coastguard Worker else
3685*a67afe4dSAndroid Build Coastguard Worker w = gamma_16_from_1[(v & 0xff) >>
3686*a67afe4dSAndroid Build Coastguard Worker gamma_shift][v >> 8];
3687*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((w >> 8) & 0xff);
3688*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(w & 0xff);
3689*a67afe4dSAndroid Build Coastguard Worker }
3690*a67afe4dSAndroid Build Coastguard Worker }
3691*a67afe4dSAndroid Build Coastguard Worker }
3692*a67afe4dSAndroid Build Coastguard Worker else
3693*a67afe4dSAndroid Build Coastguard Worker #endif
3694*a67afe4dSAndroid Build Coastguard Worker {
3695*a67afe4dSAndroid Build Coastguard Worker sp = row;
3696*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 4)
3697*a67afe4dSAndroid Build Coastguard Worker {
3698*a67afe4dSAndroid Build Coastguard Worker png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
3699*a67afe4dSAndroid Build Coastguard Worker + *(sp + 3));
3700*a67afe4dSAndroid Build Coastguard Worker
3701*a67afe4dSAndroid Build Coastguard Worker if (a == 0)
3702*a67afe4dSAndroid Build Coastguard Worker {
3703*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((png_ptr->background.gray >> 8)
3704*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3705*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
3706*a67afe4dSAndroid Build Coastguard Worker }
3707*a67afe4dSAndroid Build Coastguard Worker
3708*a67afe4dSAndroid Build Coastguard Worker else if (a < 0xffff)
3709*a67afe4dSAndroid Build Coastguard Worker {
3710*a67afe4dSAndroid Build Coastguard Worker png_uint_16 g, v;
3711*a67afe4dSAndroid Build Coastguard Worker
3712*a67afe4dSAndroid Build Coastguard Worker g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3713*a67afe4dSAndroid Build Coastguard Worker png_composite_16(v, g, a, png_ptr->background.gray);
3714*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
3715*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
3716*a67afe4dSAndroid Build Coastguard Worker }
3717*a67afe4dSAndroid Build Coastguard Worker }
3718*a67afe4dSAndroid Build Coastguard Worker }
3719*a67afe4dSAndroid Build Coastguard Worker }
3720*a67afe4dSAndroid Build Coastguard Worker break;
3721*a67afe4dSAndroid Build Coastguard Worker }
3722*a67afe4dSAndroid Build Coastguard Worker
3723*a67afe4dSAndroid Build Coastguard Worker case PNG_COLOR_TYPE_RGB_ALPHA:
3724*a67afe4dSAndroid Build Coastguard Worker {
3725*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
3726*a67afe4dSAndroid Build Coastguard Worker {
3727*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3728*a67afe4dSAndroid Build Coastguard Worker if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3729*a67afe4dSAndroid Build Coastguard Worker gamma_table != NULL)
3730*a67afe4dSAndroid Build Coastguard Worker {
3731*a67afe4dSAndroid Build Coastguard Worker sp = row;
3732*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 4)
3733*a67afe4dSAndroid Build Coastguard Worker {
3734*a67afe4dSAndroid Build Coastguard Worker png_byte a = *(sp + 3);
3735*a67afe4dSAndroid Build Coastguard Worker
3736*a67afe4dSAndroid Build Coastguard Worker if (a == 0xff)
3737*a67afe4dSAndroid Build Coastguard Worker {
3738*a67afe4dSAndroid Build Coastguard Worker *sp = gamma_table[*sp];
3739*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = gamma_table[*(sp + 1)];
3740*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = gamma_table[*(sp + 2)];
3741*a67afe4dSAndroid Build Coastguard Worker }
3742*a67afe4dSAndroid Build Coastguard Worker
3743*a67afe4dSAndroid Build Coastguard Worker else if (a == 0)
3744*a67afe4dSAndroid Build Coastguard Worker {
3745*a67afe4dSAndroid Build Coastguard Worker /* Background is already in screen gamma */
3746*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)png_ptr->background.red;
3747*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)png_ptr->background.green;
3748*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = (png_byte)png_ptr->background.blue;
3749*a67afe4dSAndroid Build Coastguard Worker }
3750*a67afe4dSAndroid Build Coastguard Worker
3751*a67afe4dSAndroid Build Coastguard Worker else
3752*a67afe4dSAndroid Build Coastguard Worker {
3753*a67afe4dSAndroid Build Coastguard Worker png_byte v, w;
3754*a67afe4dSAndroid Build Coastguard Worker
3755*a67afe4dSAndroid Build Coastguard Worker v = gamma_to_1[*sp];
3756*a67afe4dSAndroid Build Coastguard Worker png_composite(w, v, a, png_ptr->background_1.red);
3757*a67afe4dSAndroid Build Coastguard Worker if (optimize == 0) w = gamma_from_1[w];
3758*a67afe4dSAndroid Build Coastguard Worker *sp = w;
3759*a67afe4dSAndroid Build Coastguard Worker
3760*a67afe4dSAndroid Build Coastguard Worker v = gamma_to_1[*(sp + 1)];
3761*a67afe4dSAndroid Build Coastguard Worker png_composite(w, v, a, png_ptr->background_1.green);
3762*a67afe4dSAndroid Build Coastguard Worker if (optimize == 0) w = gamma_from_1[w];
3763*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = w;
3764*a67afe4dSAndroid Build Coastguard Worker
3765*a67afe4dSAndroid Build Coastguard Worker v = gamma_to_1[*(sp + 2)];
3766*a67afe4dSAndroid Build Coastguard Worker png_composite(w, v, a, png_ptr->background_1.blue);
3767*a67afe4dSAndroid Build Coastguard Worker if (optimize == 0) w = gamma_from_1[w];
3768*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = w;
3769*a67afe4dSAndroid Build Coastguard Worker }
3770*a67afe4dSAndroid Build Coastguard Worker }
3771*a67afe4dSAndroid Build Coastguard Worker }
3772*a67afe4dSAndroid Build Coastguard Worker else
3773*a67afe4dSAndroid Build Coastguard Worker #endif
3774*a67afe4dSAndroid Build Coastguard Worker {
3775*a67afe4dSAndroid Build Coastguard Worker sp = row;
3776*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 4)
3777*a67afe4dSAndroid Build Coastguard Worker {
3778*a67afe4dSAndroid Build Coastguard Worker png_byte a = *(sp + 3);
3779*a67afe4dSAndroid Build Coastguard Worker
3780*a67afe4dSAndroid Build Coastguard Worker if (a == 0)
3781*a67afe4dSAndroid Build Coastguard Worker {
3782*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)png_ptr->background.red;
3783*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)png_ptr->background.green;
3784*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = (png_byte)png_ptr->background.blue;
3785*a67afe4dSAndroid Build Coastguard Worker }
3786*a67afe4dSAndroid Build Coastguard Worker
3787*a67afe4dSAndroid Build Coastguard Worker else if (a < 0xff)
3788*a67afe4dSAndroid Build Coastguard Worker {
3789*a67afe4dSAndroid Build Coastguard Worker png_composite(*sp, *sp, a, png_ptr->background.red);
3790*a67afe4dSAndroid Build Coastguard Worker
3791*a67afe4dSAndroid Build Coastguard Worker png_composite(*(sp + 1), *(sp + 1), a,
3792*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.green);
3793*a67afe4dSAndroid Build Coastguard Worker
3794*a67afe4dSAndroid Build Coastguard Worker png_composite(*(sp + 2), *(sp + 2), a,
3795*a67afe4dSAndroid Build Coastguard Worker png_ptr->background.blue);
3796*a67afe4dSAndroid Build Coastguard Worker }
3797*a67afe4dSAndroid Build Coastguard Worker }
3798*a67afe4dSAndroid Build Coastguard Worker }
3799*a67afe4dSAndroid Build Coastguard Worker }
3800*a67afe4dSAndroid Build Coastguard Worker else /* if (row_info->bit_depth == 16) */
3801*a67afe4dSAndroid Build Coastguard Worker {
3802*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3803*a67afe4dSAndroid Build Coastguard Worker if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3804*a67afe4dSAndroid Build Coastguard Worker gamma_16_to_1 != NULL)
3805*a67afe4dSAndroid Build Coastguard Worker {
3806*a67afe4dSAndroid Build Coastguard Worker sp = row;
3807*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 8)
3808*a67afe4dSAndroid Build Coastguard Worker {
3809*a67afe4dSAndroid Build Coastguard Worker png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3810*a67afe4dSAndroid Build Coastguard Worker << 8) + (png_uint_16)(*(sp + 7)));
3811*a67afe4dSAndroid Build Coastguard Worker
3812*a67afe4dSAndroid Build Coastguard Worker if (a == (png_uint_16)0xffff)
3813*a67afe4dSAndroid Build Coastguard Worker {
3814*a67afe4dSAndroid Build Coastguard Worker png_uint_16 v;
3815*a67afe4dSAndroid Build Coastguard Worker
3816*a67afe4dSAndroid Build Coastguard Worker v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3817*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
3818*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
3819*a67afe4dSAndroid Build Coastguard Worker
3820*a67afe4dSAndroid Build Coastguard Worker v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3821*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3822*a67afe4dSAndroid Build Coastguard Worker *(sp + 3) = (png_byte)(v & 0xff);
3823*a67afe4dSAndroid Build Coastguard Worker
3824*a67afe4dSAndroid Build Coastguard Worker v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3825*a67afe4dSAndroid Build Coastguard Worker *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3826*a67afe4dSAndroid Build Coastguard Worker *(sp + 5) = (png_byte)(v & 0xff);
3827*a67afe4dSAndroid Build Coastguard Worker }
3828*a67afe4dSAndroid Build Coastguard Worker
3829*a67afe4dSAndroid Build Coastguard Worker else if (a == 0)
3830*a67afe4dSAndroid Build Coastguard Worker {
3831*a67afe4dSAndroid Build Coastguard Worker /* Background is already in screen gamma */
3832*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3833*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3834*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3835*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3836*a67afe4dSAndroid Build Coastguard Worker *(sp + 3) = (png_byte)(png_ptr->background.green
3837*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3838*a67afe4dSAndroid Build Coastguard Worker *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3839*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3840*a67afe4dSAndroid Build Coastguard Worker *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3841*a67afe4dSAndroid Build Coastguard Worker }
3842*a67afe4dSAndroid Build Coastguard Worker
3843*a67afe4dSAndroid Build Coastguard Worker else
3844*a67afe4dSAndroid Build Coastguard Worker {
3845*a67afe4dSAndroid Build Coastguard Worker png_uint_16 v, w;
3846*a67afe4dSAndroid Build Coastguard Worker
3847*a67afe4dSAndroid Build Coastguard Worker v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3848*a67afe4dSAndroid Build Coastguard Worker png_composite_16(w, v, a, png_ptr->background_1.red);
3849*a67afe4dSAndroid Build Coastguard Worker if (optimize == 0)
3850*a67afe4dSAndroid Build Coastguard Worker w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3851*a67afe4dSAndroid Build Coastguard Worker 8];
3852*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((w >> 8) & 0xff);
3853*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(w & 0xff);
3854*a67afe4dSAndroid Build Coastguard Worker
3855*a67afe4dSAndroid Build Coastguard Worker v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3856*a67afe4dSAndroid Build Coastguard Worker png_composite_16(w, v, a, png_ptr->background_1.green);
3857*a67afe4dSAndroid Build Coastguard Worker if (optimize == 0)
3858*a67afe4dSAndroid Build Coastguard Worker w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3859*a67afe4dSAndroid Build Coastguard Worker 8];
3860*a67afe4dSAndroid Build Coastguard Worker
3861*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = (png_byte)((w >> 8) & 0xff);
3862*a67afe4dSAndroid Build Coastguard Worker *(sp + 3) = (png_byte)(w & 0xff);
3863*a67afe4dSAndroid Build Coastguard Worker
3864*a67afe4dSAndroid Build Coastguard Worker v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3865*a67afe4dSAndroid Build Coastguard Worker png_composite_16(w, v, a, png_ptr->background_1.blue);
3866*a67afe4dSAndroid Build Coastguard Worker if (optimize == 0)
3867*a67afe4dSAndroid Build Coastguard Worker w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
3868*a67afe4dSAndroid Build Coastguard Worker 8];
3869*a67afe4dSAndroid Build Coastguard Worker
3870*a67afe4dSAndroid Build Coastguard Worker *(sp + 4) = (png_byte)((w >> 8) & 0xff);
3871*a67afe4dSAndroid Build Coastguard Worker *(sp + 5) = (png_byte)(w & 0xff);
3872*a67afe4dSAndroid Build Coastguard Worker }
3873*a67afe4dSAndroid Build Coastguard Worker }
3874*a67afe4dSAndroid Build Coastguard Worker }
3875*a67afe4dSAndroid Build Coastguard Worker
3876*a67afe4dSAndroid Build Coastguard Worker else
3877*a67afe4dSAndroid Build Coastguard Worker #endif
3878*a67afe4dSAndroid Build Coastguard Worker {
3879*a67afe4dSAndroid Build Coastguard Worker sp = row;
3880*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp += 8)
3881*a67afe4dSAndroid Build Coastguard Worker {
3882*a67afe4dSAndroid Build Coastguard Worker png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3883*a67afe4dSAndroid Build Coastguard Worker << 8) + (png_uint_16)(*(sp + 7)));
3884*a67afe4dSAndroid Build Coastguard Worker
3885*a67afe4dSAndroid Build Coastguard Worker if (a == 0)
3886*a67afe4dSAndroid Build Coastguard Worker {
3887*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
3888*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
3889*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
3890*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3891*a67afe4dSAndroid Build Coastguard Worker *(sp + 3) = (png_byte)(png_ptr->background.green
3892*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3893*a67afe4dSAndroid Build Coastguard Worker *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
3894*a67afe4dSAndroid Build Coastguard Worker & 0xff);
3895*a67afe4dSAndroid Build Coastguard Worker *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
3896*a67afe4dSAndroid Build Coastguard Worker }
3897*a67afe4dSAndroid Build Coastguard Worker
3898*a67afe4dSAndroid Build Coastguard Worker else if (a < 0xffff)
3899*a67afe4dSAndroid Build Coastguard Worker {
3900*a67afe4dSAndroid Build Coastguard Worker png_uint_16 v;
3901*a67afe4dSAndroid Build Coastguard Worker
3902*a67afe4dSAndroid Build Coastguard Worker png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3903*a67afe4dSAndroid Build Coastguard Worker png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3904*a67afe4dSAndroid Build Coastguard Worker + *(sp + 3));
3905*a67afe4dSAndroid Build Coastguard Worker png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3906*a67afe4dSAndroid Build Coastguard Worker + *(sp + 5));
3907*a67afe4dSAndroid Build Coastguard Worker
3908*a67afe4dSAndroid Build Coastguard Worker png_composite_16(v, r, a, png_ptr->background.red);
3909*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
3910*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
3911*a67afe4dSAndroid Build Coastguard Worker
3912*a67afe4dSAndroid Build Coastguard Worker png_composite_16(v, g, a, png_ptr->background.green);
3913*a67afe4dSAndroid Build Coastguard Worker *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3914*a67afe4dSAndroid Build Coastguard Worker *(sp + 3) = (png_byte)(v & 0xff);
3915*a67afe4dSAndroid Build Coastguard Worker
3916*a67afe4dSAndroid Build Coastguard Worker png_composite_16(v, b, a, png_ptr->background.blue);
3917*a67afe4dSAndroid Build Coastguard Worker *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3918*a67afe4dSAndroid Build Coastguard Worker *(sp + 5) = (png_byte)(v & 0xff);
3919*a67afe4dSAndroid Build Coastguard Worker }
3920*a67afe4dSAndroid Build Coastguard Worker }
3921*a67afe4dSAndroid Build Coastguard Worker }
3922*a67afe4dSAndroid Build Coastguard Worker }
3923*a67afe4dSAndroid Build Coastguard Worker break;
3924*a67afe4dSAndroid Build Coastguard Worker }
3925*a67afe4dSAndroid Build Coastguard Worker
3926*a67afe4dSAndroid Build Coastguard Worker default:
3927*a67afe4dSAndroid Build Coastguard Worker break;
3928*a67afe4dSAndroid Build Coastguard Worker }
3929*a67afe4dSAndroid Build Coastguard Worker }
3930*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_BACKGROUND || READ_ALPHA_MODE */
3931*a67afe4dSAndroid Build Coastguard Worker
3932*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
3933*a67afe4dSAndroid Build Coastguard Worker /* Gamma correct the image, avoiding the alpha channel. Make sure
3934*a67afe4dSAndroid Build Coastguard Worker * you do this after you deal with the transparency issue on grayscale
3935*a67afe4dSAndroid Build Coastguard Worker * or RGB images. If your bit depth is 8, use gamma_table, if it
3936*a67afe4dSAndroid Build Coastguard Worker * is 16, use gamma_16_table and gamma_shift. Build these with
3937*a67afe4dSAndroid Build Coastguard Worker * build_gamma_table().
3938*a67afe4dSAndroid Build Coastguard Worker */
3939*a67afe4dSAndroid Build Coastguard Worker static void
png_do_gamma(png_row_infop row_info,png_bytep row,png_structrp png_ptr)3940*a67afe4dSAndroid Build Coastguard Worker png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
3941*a67afe4dSAndroid Build Coastguard Worker {
3942*a67afe4dSAndroid Build Coastguard Worker png_const_bytep gamma_table = png_ptr->gamma_table;
3943*a67afe4dSAndroid Build Coastguard Worker png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
3944*a67afe4dSAndroid Build Coastguard Worker int gamma_shift = png_ptr->gamma_shift;
3945*a67afe4dSAndroid Build Coastguard Worker
3946*a67afe4dSAndroid Build Coastguard Worker png_bytep sp;
3947*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
3948*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width=row_info->width;
3949*a67afe4dSAndroid Build Coastguard Worker
3950*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_gamma");
3951*a67afe4dSAndroid Build Coastguard Worker
3952*a67afe4dSAndroid Build Coastguard Worker if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3953*a67afe4dSAndroid Build Coastguard Worker (row_info->bit_depth == 16 && gamma_16_table != NULL)))
3954*a67afe4dSAndroid Build Coastguard Worker {
3955*a67afe4dSAndroid Build Coastguard Worker switch (row_info->color_type)
3956*a67afe4dSAndroid Build Coastguard Worker {
3957*a67afe4dSAndroid Build Coastguard Worker case PNG_COLOR_TYPE_RGB:
3958*a67afe4dSAndroid Build Coastguard Worker {
3959*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
3960*a67afe4dSAndroid Build Coastguard Worker {
3961*a67afe4dSAndroid Build Coastguard Worker sp = row;
3962*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
3963*a67afe4dSAndroid Build Coastguard Worker {
3964*a67afe4dSAndroid Build Coastguard Worker *sp = gamma_table[*sp];
3965*a67afe4dSAndroid Build Coastguard Worker sp++;
3966*a67afe4dSAndroid Build Coastguard Worker *sp = gamma_table[*sp];
3967*a67afe4dSAndroid Build Coastguard Worker sp++;
3968*a67afe4dSAndroid Build Coastguard Worker *sp = gamma_table[*sp];
3969*a67afe4dSAndroid Build Coastguard Worker sp++;
3970*a67afe4dSAndroid Build Coastguard Worker }
3971*a67afe4dSAndroid Build Coastguard Worker }
3972*a67afe4dSAndroid Build Coastguard Worker
3973*a67afe4dSAndroid Build Coastguard Worker else /* if (row_info->bit_depth == 16) */
3974*a67afe4dSAndroid Build Coastguard Worker {
3975*a67afe4dSAndroid Build Coastguard Worker sp = row;
3976*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
3977*a67afe4dSAndroid Build Coastguard Worker {
3978*a67afe4dSAndroid Build Coastguard Worker png_uint_16 v;
3979*a67afe4dSAndroid Build Coastguard Worker
3980*a67afe4dSAndroid Build Coastguard Worker v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3981*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
3982*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
3983*a67afe4dSAndroid Build Coastguard Worker sp += 2;
3984*a67afe4dSAndroid Build Coastguard Worker
3985*a67afe4dSAndroid Build Coastguard Worker v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3986*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
3987*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
3988*a67afe4dSAndroid Build Coastguard Worker sp += 2;
3989*a67afe4dSAndroid Build Coastguard Worker
3990*a67afe4dSAndroid Build Coastguard Worker v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3991*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
3992*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
3993*a67afe4dSAndroid Build Coastguard Worker sp += 2;
3994*a67afe4dSAndroid Build Coastguard Worker }
3995*a67afe4dSAndroid Build Coastguard Worker }
3996*a67afe4dSAndroid Build Coastguard Worker break;
3997*a67afe4dSAndroid Build Coastguard Worker }
3998*a67afe4dSAndroid Build Coastguard Worker
3999*a67afe4dSAndroid Build Coastguard Worker case PNG_COLOR_TYPE_RGB_ALPHA:
4000*a67afe4dSAndroid Build Coastguard Worker {
4001*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
4002*a67afe4dSAndroid Build Coastguard Worker {
4003*a67afe4dSAndroid Build Coastguard Worker sp = row;
4004*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4005*a67afe4dSAndroid Build Coastguard Worker {
4006*a67afe4dSAndroid Build Coastguard Worker *sp = gamma_table[*sp];
4007*a67afe4dSAndroid Build Coastguard Worker sp++;
4008*a67afe4dSAndroid Build Coastguard Worker
4009*a67afe4dSAndroid Build Coastguard Worker *sp = gamma_table[*sp];
4010*a67afe4dSAndroid Build Coastguard Worker sp++;
4011*a67afe4dSAndroid Build Coastguard Worker
4012*a67afe4dSAndroid Build Coastguard Worker *sp = gamma_table[*sp];
4013*a67afe4dSAndroid Build Coastguard Worker sp++;
4014*a67afe4dSAndroid Build Coastguard Worker
4015*a67afe4dSAndroid Build Coastguard Worker sp++;
4016*a67afe4dSAndroid Build Coastguard Worker }
4017*a67afe4dSAndroid Build Coastguard Worker }
4018*a67afe4dSAndroid Build Coastguard Worker
4019*a67afe4dSAndroid Build Coastguard Worker else /* if (row_info->bit_depth == 16) */
4020*a67afe4dSAndroid Build Coastguard Worker {
4021*a67afe4dSAndroid Build Coastguard Worker sp = row;
4022*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4023*a67afe4dSAndroid Build Coastguard Worker {
4024*a67afe4dSAndroid Build Coastguard Worker png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4025*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
4026*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
4027*a67afe4dSAndroid Build Coastguard Worker sp += 2;
4028*a67afe4dSAndroid Build Coastguard Worker
4029*a67afe4dSAndroid Build Coastguard Worker v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4030*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
4031*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
4032*a67afe4dSAndroid Build Coastguard Worker sp += 2;
4033*a67afe4dSAndroid Build Coastguard Worker
4034*a67afe4dSAndroid Build Coastguard Worker v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4035*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
4036*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
4037*a67afe4dSAndroid Build Coastguard Worker sp += 4;
4038*a67afe4dSAndroid Build Coastguard Worker }
4039*a67afe4dSAndroid Build Coastguard Worker }
4040*a67afe4dSAndroid Build Coastguard Worker break;
4041*a67afe4dSAndroid Build Coastguard Worker }
4042*a67afe4dSAndroid Build Coastguard Worker
4043*a67afe4dSAndroid Build Coastguard Worker case PNG_COLOR_TYPE_GRAY_ALPHA:
4044*a67afe4dSAndroid Build Coastguard Worker {
4045*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
4046*a67afe4dSAndroid Build Coastguard Worker {
4047*a67afe4dSAndroid Build Coastguard Worker sp = row;
4048*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4049*a67afe4dSAndroid Build Coastguard Worker {
4050*a67afe4dSAndroid Build Coastguard Worker *sp = gamma_table[*sp];
4051*a67afe4dSAndroid Build Coastguard Worker sp += 2;
4052*a67afe4dSAndroid Build Coastguard Worker }
4053*a67afe4dSAndroid Build Coastguard Worker }
4054*a67afe4dSAndroid Build Coastguard Worker
4055*a67afe4dSAndroid Build Coastguard Worker else /* if (row_info->bit_depth == 16) */
4056*a67afe4dSAndroid Build Coastguard Worker {
4057*a67afe4dSAndroid Build Coastguard Worker sp = row;
4058*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4059*a67afe4dSAndroid Build Coastguard Worker {
4060*a67afe4dSAndroid Build Coastguard Worker png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4061*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
4062*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
4063*a67afe4dSAndroid Build Coastguard Worker sp += 4;
4064*a67afe4dSAndroid Build Coastguard Worker }
4065*a67afe4dSAndroid Build Coastguard Worker }
4066*a67afe4dSAndroid Build Coastguard Worker break;
4067*a67afe4dSAndroid Build Coastguard Worker }
4068*a67afe4dSAndroid Build Coastguard Worker
4069*a67afe4dSAndroid Build Coastguard Worker case PNG_COLOR_TYPE_GRAY:
4070*a67afe4dSAndroid Build Coastguard Worker {
4071*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 2)
4072*a67afe4dSAndroid Build Coastguard Worker {
4073*a67afe4dSAndroid Build Coastguard Worker sp = row;
4074*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i += 4)
4075*a67afe4dSAndroid Build Coastguard Worker {
4076*a67afe4dSAndroid Build Coastguard Worker int a = *sp & 0xc0;
4077*a67afe4dSAndroid Build Coastguard Worker int b = *sp & 0x30;
4078*a67afe4dSAndroid Build Coastguard Worker int c = *sp & 0x0c;
4079*a67afe4dSAndroid Build Coastguard Worker int d = *sp & 0x03;
4080*a67afe4dSAndroid Build Coastguard Worker
4081*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)(
4082*a67afe4dSAndroid Build Coastguard Worker ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
4083*a67afe4dSAndroid Build Coastguard Worker ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
4084*a67afe4dSAndroid Build Coastguard Worker ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
4085*a67afe4dSAndroid Build Coastguard Worker ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
4086*a67afe4dSAndroid Build Coastguard Worker sp++;
4087*a67afe4dSAndroid Build Coastguard Worker }
4088*a67afe4dSAndroid Build Coastguard Worker }
4089*a67afe4dSAndroid Build Coastguard Worker
4090*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 4)
4091*a67afe4dSAndroid Build Coastguard Worker {
4092*a67afe4dSAndroid Build Coastguard Worker sp = row;
4093*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i += 2)
4094*a67afe4dSAndroid Build Coastguard Worker {
4095*a67afe4dSAndroid Build Coastguard Worker int msb = *sp & 0xf0;
4096*a67afe4dSAndroid Build Coastguard Worker int lsb = *sp & 0x0f;
4097*a67afe4dSAndroid Build Coastguard Worker
4098*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
4099*a67afe4dSAndroid Build Coastguard Worker | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
4100*a67afe4dSAndroid Build Coastguard Worker sp++;
4101*a67afe4dSAndroid Build Coastguard Worker }
4102*a67afe4dSAndroid Build Coastguard Worker }
4103*a67afe4dSAndroid Build Coastguard Worker
4104*a67afe4dSAndroid Build Coastguard Worker else if (row_info->bit_depth == 8)
4105*a67afe4dSAndroid Build Coastguard Worker {
4106*a67afe4dSAndroid Build Coastguard Worker sp = row;
4107*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4108*a67afe4dSAndroid Build Coastguard Worker {
4109*a67afe4dSAndroid Build Coastguard Worker *sp = gamma_table[*sp];
4110*a67afe4dSAndroid Build Coastguard Worker sp++;
4111*a67afe4dSAndroid Build Coastguard Worker }
4112*a67afe4dSAndroid Build Coastguard Worker }
4113*a67afe4dSAndroid Build Coastguard Worker
4114*a67afe4dSAndroid Build Coastguard Worker else if (row_info->bit_depth == 16)
4115*a67afe4dSAndroid Build Coastguard Worker {
4116*a67afe4dSAndroid Build Coastguard Worker sp = row;
4117*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4118*a67afe4dSAndroid Build Coastguard Worker {
4119*a67afe4dSAndroid Build Coastguard Worker png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
4120*a67afe4dSAndroid Build Coastguard Worker *sp = (png_byte)((v >> 8) & 0xff);
4121*a67afe4dSAndroid Build Coastguard Worker *(sp + 1) = (png_byte)(v & 0xff);
4122*a67afe4dSAndroid Build Coastguard Worker sp += 2;
4123*a67afe4dSAndroid Build Coastguard Worker }
4124*a67afe4dSAndroid Build Coastguard Worker }
4125*a67afe4dSAndroid Build Coastguard Worker break;
4126*a67afe4dSAndroid Build Coastguard Worker }
4127*a67afe4dSAndroid Build Coastguard Worker
4128*a67afe4dSAndroid Build Coastguard Worker default:
4129*a67afe4dSAndroid Build Coastguard Worker break;
4130*a67afe4dSAndroid Build Coastguard Worker }
4131*a67afe4dSAndroid Build Coastguard Worker }
4132*a67afe4dSAndroid Build Coastguard Worker }
4133*a67afe4dSAndroid Build Coastguard Worker #endif
4134*a67afe4dSAndroid Build Coastguard Worker
4135*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4136*a67afe4dSAndroid Build Coastguard Worker /* Encode the alpha channel to the output gamma (the input channel is always
4137*a67afe4dSAndroid Build Coastguard Worker * linear.) Called only with color types that have an alpha channel. Needs the
4138*a67afe4dSAndroid Build Coastguard Worker * from_1 tables.
4139*a67afe4dSAndroid Build Coastguard Worker */
4140*a67afe4dSAndroid Build Coastguard Worker static void
png_do_encode_alpha(png_row_infop row_info,png_bytep row,png_structrp png_ptr)4141*a67afe4dSAndroid Build Coastguard Worker png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
4142*a67afe4dSAndroid Build Coastguard Worker {
4143*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
4144*a67afe4dSAndroid Build Coastguard Worker
4145*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_encode_alpha");
4146*a67afe4dSAndroid Build Coastguard Worker
4147*a67afe4dSAndroid Build Coastguard Worker if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4148*a67afe4dSAndroid Build Coastguard Worker {
4149*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
4150*a67afe4dSAndroid Build Coastguard Worker {
4151*a67afe4dSAndroid Build Coastguard Worker png_bytep table = png_ptr->gamma_from_1;
4152*a67afe4dSAndroid Build Coastguard Worker
4153*a67afe4dSAndroid Build Coastguard Worker if (table != NULL)
4154*a67afe4dSAndroid Build Coastguard Worker {
4155*a67afe4dSAndroid Build Coastguard Worker int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
4156*a67afe4dSAndroid Build Coastguard Worker
4157*a67afe4dSAndroid Build Coastguard Worker /* The alpha channel is the last component: */
4158*a67afe4dSAndroid Build Coastguard Worker row += step - 1;
4159*a67afe4dSAndroid Build Coastguard Worker
4160*a67afe4dSAndroid Build Coastguard Worker for (; row_width > 0; --row_width, row += step)
4161*a67afe4dSAndroid Build Coastguard Worker *row = table[*row];
4162*a67afe4dSAndroid Build Coastguard Worker
4163*a67afe4dSAndroid Build Coastguard Worker return;
4164*a67afe4dSAndroid Build Coastguard Worker }
4165*a67afe4dSAndroid Build Coastguard Worker }
4166*a67afe4dSAndroid Build Coastguard Worker
4167*a67afe4dSAndroid Build Coastguard Worker else if (row_info->bit_depth == 16)
4168*a67afe4dSAndroid Build Coastguard Worker {
4169*a67afe4dSAndroid Build Coastguard Worker png_uint_16pp table = png_ptr->gamma_16_from_1;
4170*a67afe4dSAndroid Build Coastguard Worker int gamma_shift = png_ptr->gamma_shift;
4171*a67afe4dSAndroid Build Coastguard Worker
4172*a67afe4dSAndroid Build Coastguard Worker if (table != NULL)
4173*a67afe4dSAndroid Build Coastguard Worker {
4174*a67afe4dSAndroid Build Coastguard Worker int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
4175*a67afe4dSAndroid Build Coastguard Worker
4176*a67afe4dSAndroid Build Coastguard Worker /* The alpha channel is the last component: */
4177*a67afe4dSAndroid Build Coastguard Worker row += step - 2;
4178*a67afe4dSAndroid Build Coastguard Worker
4179*a67afe4dSAndroid Build Coastguard Worker for (; row_width > 0; --row_width, row += step)
4180*a67afe4dSAndroid Build Coastguard Worker {
4181*a67afe4dSAndroid Build Coastguard Worker png_uint_16 v;
4182*a67afe4dSAndroid Build Coastguard Worker
4183*a67afe4dSAndroid Build Coastguard Worker v = table[*(row + 1) >> gamma_shift][*row];
4184*a67afe4dSAndroid Build Coastguard Worker *row = (png_byte)((v >> 8) & 0xff);
4185*a67afe4dSAndroid Build Coastguard Worker *(row + 1) = (png_byte)(v & 0xff);
4186*a67afe4dSAndroid Build Coastguard Worker }
4187*a67afe4dSAndroid Build Coastguard Worker
4188*a67afe4dSAndroid Build Coastguard Worker return;
4189*a67afe4dSAndroid Build Coastguard Worker }
4190*a67afe4dSAndroid Build Coastguard Worker }
4191*a67afe4dSAndroid Build Coastguard Worker }
4192*a67afe4dSAndroid Build Coastguard Worker
4193*a67afe4dSAndroid Build Coastguard Worker /* Only get to here if called with a weird row_info; no harm has been done,
4194*a67afe4dSAndroid Build Coastguard Worker * so just issue a warning.
4195*a67afe4dSAndroid Build Coastguard Worker */
4196*a67afe4dSAndroid Build Coastguard Worker png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
4197*a67afe4dSAndroid Build Coastguard Worker }
4198*a67afe4dSAndroid Build Coastguard Worker #endif
4199*a67afe4dSAndroid Build Coastguard Worker
4200*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_EXPAND_SUPPORTED
4201*a67afe4dSAndroid Build Coastguard Worker /* Expands a palette row to an RGB or RGBA row depending
4202*a67afe4dSAndroid Build Coastguard Worker * upon whether you supply trans and num_trans.
4203*a67afe4dSAndroid Build Coastguard Worker */
4204*a67afe4dSAndroid Build Coastguard Worker static void
png_do_expand_palette(png_structrp png_ptr,png_row_infop row_info,png_bytep row,png_const_colorp palette,png_const_bytep trans_alpha,int num_trans)4205*a67afe4dSAndroid Build Coastguard Worker png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info,
4206*a67afe4dSAndroid Build Coastguard Worker png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha,
4207*a67afe4dSAndroid Build Coastguard Worker int num_trans)
4208*a67afe4dSAndroid Build Coastguard Worker {
4209*a67afe4dSAndroid Build Coastguard Worker int shift, value;
4210*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
4211*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
4212*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width=row_info->width;
4213*a67afe4dSAndroid Build Coastguard Worker
4214*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_expand_palette");
4215*a67afe4dSAndroid Build Coastguard Worker
4216*a67afe4dSAndroid Build Coastguard Worker if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4217*a67afe4dSAndroid Build Coastguard Worker {
4218*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth < 8)
4219*a67afe4dSAndroid Build Coastguard Worker {
4220*a67afe4dSAndroid Build Coastguard Worker switch (row_info->bit_depth)
4221*a67afe4dSAndroid Build Coastguard Worker {
4222*a67afe4dSAndroid Build Coastguard Worker case 1:
4223*a67afe4dSAndroid Build Coastguard Worker {
4224*a67afe4dSAndroid Build Coastguard Worker sp = row + (size_t)((row_width - 1) >> 3);
4225*a67afe4dSAndroid Build Coastguard Worker dp = row + (size_t)row_width - 1;
4226*a67afe4dSAndroid Build Coastguard Worker shift = 7 - (int)((row_width + 7) & 0x07);
4227*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4228*a67afe4dSAndroid Build Coastguard Worker {
4229*a67afe4dSAndroid Build Coastguard Worker if ((*sp >> shift) & 0x01)
4230*a67afe4dSAndroid Build Coastguard Worker *dp = 1;
4231*a67afe4dSAndroid Build Coastguard Worker
4232*a67afe4dSAndroid Build Coastguard Worker else
4233*a67afe4dSAndroid Build Coastguard Worker *dp = 0;
4234*a67afe4dSAndroid Build Coastguard Worker
4235*a67afe4dSAndroid Build Coastguard Worker if (shift == 7)
4236*a67afe4dSAndroid Build Coastguard Worker {
4237*a67afe4dSAndroid Build Coastguard Worker shift = 0;
4238*a67afe4dSAndroid Build Coastguard Worker sp--;
4239*a67afe4dSAndroid Build Coastguard Worker }
4240*a67afe4dSAndroid Build Coastguard Worker
4241*a67afe4dSAndroid Build Coastguard Worker else
4242*a67afe4dSAndroid Build Coastguard Worker shift++;
4243*a67afe4dSAndroid Build Coastguard Worker
4244*a67afe4dSAndroid Build Coastguard Worker dp--;
4245*a67afe4dSAndroid Build Coastguard Worker }
4246*a67afe4dSAndroid Build Coastguard Worker break;
4247*a67afe4dSAndroid Build Coastguard Worker }
4248*a67afe4dSAndroid Build Coastguard Worker
4249*a67afe4dSAndroid Build Coastguard Worker case 2:
4250*a67afe4dSAndroid Build Coastguard Worker {
4251*a67afe4dSAndroid Build Coastguard Worker sp = row + (size_t)((row_width - 1) >> 2);
4252*a67afe4dSAndroid Build Coastguard Worker dp = row + (size_t)row_width - 1;
4253*a67afe4dSAndroid Build Coastguard Worker shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4254*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4255*a67afe4dSAndroid Build Coastguard Worker {
4256*a67afe4dSAndroid Build Coastguard Worker value = (*sp >> shift) & 0x03;
4257*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)value;
4258*a67afe4dSAndroid Build Coastguard Worker if (shift == 6)
4259*a67afe4dSAndroid Build Coastguard Worker {
4260*a67afe4dSAndroid Build Coastguard Worker shift = 0;
4261*a67afe4dSAndroid Build Coastguard Worker sp--;
4262*a67afe4dSAndroid Build Coastguard Worker }
4263*a67afe4dSAndroid Build Coastguard Worker
4264*a67afe4dSAndroid Build Coastguard Worker else
4265*a67afe4dSAndroid Build Coastguard Worker shift += 2;
4266*a67afe4dSAndroid Build Coastguard Worker
4267*a67afe4dSAndroid Build Coastguard Worker dp--;
4268*a67afe4dSAndroid Build Coastguard Worker }
4269*a67afe4dSAndroid Build Coastguard Worker break;
4270*a67afe4dSAndroid Build Coastguard Worker }
4271*a67afe4dSAndroid Build Coastguard Worker
4272*a67afe4dSAndroid Build Coastguard Worker case 4:
4273*a67afe4dSAndroid Build Coastguard Worker {
4274*a67afe4dSAndroid Build Coastguard Worker sp = row + (size_t)((row_width - 1) >> 1);
4275*a67afe4dSAndroid Build Coastguard Worker dp = row + (size_t)row_width - 1;
4276*a67afe4dSAndroid Build Coastguard Worker shift = (int)((row_width & 0x01) << 2);
4277*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4278*a67afe4dSAndroid Build Coastguard Worker {
4279*a67afe4dSAndroid Build Coastguard Worker value = (*sp >> shift) & 0x0f;
4280*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)value;
4281*a67afe4dSAndroid Build Coastguard Worker if (shift == 4)
4282*a67afe4dSAndroid Build Coastguard Worker {
4283*a67afe4dSAndroid Build Coastguard Worker shift = 0;
4284*a67afe4dSAndroid Build Coastguard Worker sp--;
4285*a67afe4dSAndroid Build Coastguard Worker }
4286*a67afe4dSAndroid Build Coastguard Worker
4287*a67afe4dSAndroid Build Coastguard Worker else
4288*a67afe4dSAndroid Build Coastguard Worker shift += 4;
4289*a67afe4dSAndroid Build Coastguard Worker
4290*a67afe4dSAndroid Build Coastguard Worker dp--;
4291*a67afe4dSAndroid Build Coastguard Worker }
4292*a67afe4dSAndroid Build Coastguard Worker break;
4293*a67afe4dSAndroid Build Coastguard Worker }
4294*a67afe4dSAndroid Build Coastguard Worker
4295*a67afe4dSAndroid Build Coastguard Worker default:
4296*a67afe4dSAndroid Build Coastguard Worker break;
4297*a67afe4dSAndroid Build Coastguard Worker }
4298*a67afe4dSAndroid Build Coastguard Worker row_info->bit_depth = 8;
4299*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = 8;
4300*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width;
4301*a67afe4dSAndroid Build Coastguard Worker }
4302*a67afe4dSAndroid Build Coastguard Worker
4303*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
4304*a67afe4dSAndroid Build Coastguard Worker {
4305*a67afe4dSAndroid Build Coastguard Worker {
4306*a67afe4dSAndroid Build Coastguard Worker if (num_trans > 0)
4307*a67afe4dSAndroid Build Coastguard Worker {
4308*a67afe4dSAndroid Build Coastguard Worker sp = row + (size_t)row_width - 1;
4309*a67afe4dSAndroid Build Coastguard Worker dp = row + ((size_t)row_width << 2) - 1;
4310*a67afe4dSAndroid Build Coastguard Worker
4311*a67afe4dSAndroid Build Coastguard Worker i = 0;
4312*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
4313*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->riffled_palette != NULL)
4314*a67afe4dSAndroid Build Coastguard Worker {
4315*a67afe4dSAndroid Build Coastguard Worker /* The RGBA optimization works with png_ptr->bit_depth == 8
4316*a67afe4dSAndroid Build Coastguard Worker * but sometimes row_info->bit_depth has been changed to 8.
4317*a67afe4dSAndroid Build Coastguard Worker * In these cases, the palette hasn't been riffled.
4318*a67afe4dSAndroid Build Coastguard Worker */
4319*a67afe4dSAndroid Build Coastguard Worker i = png_do_expand_palette_rgba8_neon(png_ptr, row_info, row,
4320*a67afe4dSAndroid Build Coastguard Worker &sp, &dp);
4321*a67afe4dSAndroid Build Coastguard Worker }
4322*a67afe4dSAndroid Build Coastguard Worker #else
4323*a67afe4dSAndroid Build Coastguard Worker PNG_UNUSED(png_ptr)
4324*a67afe4dSAndroid Build Coastguard Worker #endif
4325*a67afe4dSAndroid Build Coastguard Worker
4326*a67afe4dSAndroid Build Coastguard Worker for (; i < row_width; i++)
4327*a67afe4dSAndroid Build Coastguard Worker {
4328*a67afe4dSAndroid Build Coastguard Worker if ((int)(*sp) >= num_trans)
4329*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0xff;
4330*a67afe4dSAndroid Build Coastguard Worker else
4331*a67afe4dSAndroid Build Coastguard Worker *dp-- = trans_alpha[*sp];
4332*a67afe4dSAndroid Build Coastguard Worker *dp-- = palette[*sp].blue;
4333*a67afe4dSAndroid Build Coastguard Worker *dp-- = palette[*sp].green;
4334*a67afe4dSAndroid Build Coastguard Worker *dp-- = palette[*sp].red;
4335*a67afe4dSAndroid Build Coastguard Worker sp--;
4336*a67afe4dSAndroid Build Coastguard Worker }
4337*a67afe4dSAndroid Build Coastguard Worker row_info->bit_depth = 8;
4338*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = 32;
4339*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width * 4;
4340*a67afe4dSAndroid Build Coastguard Worker row_info->color_type = 6;
4341*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 4;
4342*a67afe4dSAndroid Build Coastguard Worker }
4343*a67afe4dSAndroid Build Coastguard Worker
4344*a67afe4dSAndroid Build Coastguard Worker else
4345*a67afe4dSAndroid Build Coastguard Worker {
4346*a67afe4dSAndroid Build Coastguard Worker sp = row + (size_t)row_width - 1;
4347*a67afe4dSAndroid Build Coastguard Worker dp = row + (size_t)(row_width * 3) - 1;
4348*a67afe4dSAndroid Build Coastguard Worker i = 0;
4349*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
4350*a67afe4dSAndroid Build Coastguard Worker i = png_do_expand_palette_rgb8_neon(png_ptr, row_info, row,
4351*a67afe4dSAndroid Build Coastguard Worker &sp, &dp);
4352*a67afe4dSAndroid Build Coastguard Worker #else
4353*a67afe4dSAndroid Build Coastguard Worker PNG_UNUSED(png_ptr)
4354*a67afe4dSAndroid Build Coastguard Worker #endif
4355*a67afe4dSAndroid Build Coastguard Worker
4356*a67afe4dSAndroid Build Coastguard Worker for (; i < row_width; i++)
4357*a67afe4dSAndroid Build Coastguard Worker {
4358*a67afe4dSAndroid Build Coastguard Worker *dp-- = palette[*sp].blue;
4359*a67afe4dSAndroid Build Coastguard Worker *dp-- = palette[*sp].green;
4360*a67afe4dSAndroid Build Coastguard Worker *dp-- = palette[*sp].red;
4361*a67afe4dSAndroid Build Coastguard Worker sp--;
4362*a67afe4dSAndroid Build Coastguard Worker }
4363*a67afe4dSAndroid Build Coastguard Worker
4364*a67afe4dSAndroid Build Coastguard Worker row_info->bit_depth = 8;
4365*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = 24;
4366*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width * 3;
4367*a67afe4dSAndroid Build Coastguard Worker row_info->color_type = 2;
4368*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 3;
4369*a67afe4dSAndroid Build Coastguard Worker }
4370*a67afe4dSAndroid Build Coastguard Worker }
4371*a67afe4dSAndroid Build Coastguard Worker }
4372*a67afe4dSAndroid Build Coastguard Worker }
4373*a67afe4dSAndroid Build Coastguard Worker }
4374*a67afe4dSAndroid Build Coastguard Worker
4375*a67afe4dSAndroid Build Coastguard Worker /* If the bit depth < 8, it is expanded to 8. Also, if the already
4376*a67afe4dSAndroid Build Coastguard Worker * expanded transparency value is supplied, an alpha channel is built.
4377*a67afe4dSAndroid Build Coastguard Worker */
4378*a67afe4dSAndroid Build Coastguard Worker static void
png_do_expand(png_row_infop row_info,png_bytep row,png_const_color_16p trans_color)4379*a67afe4dSAndroid Build Coastguard Worker png_do_expand(png_row_infop row_info, png_bytep row,
4380*a67afe4dSAndroid Build Coastguard Worker png_const_color_16p trans_color)
4381*a67afe4dSAndroid Build Coastguard Worker {
4382*a67afe4dSAndroid Build Coastguard Worker int shift, value;
4383*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
4384*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
4385*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width=row_info->width;
4386*a67afe4dSAndroid Build Coastguard Worker
4387*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_expand");
4388*a67afe4dSAndroid Build Coastguard Worker
4389*a67afe4dSAndroid Build Coastguard Worker if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
4390*a67afe4dSAndroid Build Coastguard Worker {
4391*a67afe4dSAndroid Build Coastguard Worker unsigned int gray = trans_color != NULL ? trans_color->gray : 0;
4392*a67afe4dSAndroid Build Coastguard Worker
4393*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth < 8)
4394*a67afe4dSAndroid Build Coastguard Worker {
4395*a67afe4dSAndroid Build Coastguard Worker switch (row_info->bit_depth)
4396*a67afe4dSAndroid Build Coastguard Worker {
4397*a67afe4dSAndroid Build Coastguard Worker case 1:
4398*a67afe4dSAndroid Build Coastguard Worker {
4399*a67afe4dSAndroid Build Coastguard Worker gray = (gray & 0x01) * 0xff;
4400*a67afe4dSAndroid Build Coastguard Worker sp = row + (size_t)((row_width - 1) >> 3);
4401*a67afe4dSAndroid Build Coastguard Worker dp = row + (size_t)row_width - 1;
4402*a67afe4dSAndroid Build Coastguard Worker shift = 7 - (int)((row_width + 7) & 0x07);
4403*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4404*a67afe4dSAndroid Build Coastguard Worker {
4405*a67afe4dSAndroid Build Coastguard Worker if ((*sp >> shift) & 0x01)
4406*a67afe4dSAndroid Build Coastguard Worker *dp = 0xff;
4407*a67afe4dSAndroid Build Coastguard Worker
4408*a67afe4dSAndroid Build Coastguard Worker else
4409*a67afe4dSAndroid Build Coastguard Worker *dp = 0;
4410*a67afe4dSAndroid Build Coastguard Worker
4411*a67afe4dSAndroid Build Coastguard Worker if (shift == 7)
4412*a67afe4dSAndroid Build Coastguard Worker {
4413*a67afe4dSAndroid Build Coastguard Worker shift = 0;
4414*a67afe4dSAndroid Build Coastguard Worker sp--;
4415*a67afe4dSAndroid Build Coastguard Worker }
4416*a67afe4dSAndroid Build Coastguard Worker
4417*a67afe4dSAndroid Build Coastguard Worker else
4418*a67afe4dSAndroid Build Coastguard Worker shift++;
4419*a67afe4dSAndroid Build Coastguard Worker
4420*a67afe4dSAndroid Build Coastguard Worker dp--;
4421*a67afe4dSAndroid Build Coastguard Worker }
4422*a67afe4dSAndroid Build Coastguard Worker break;
4423*a67afe4dSAndroid Build Coastguard Worker }
4424*a67afe4dSAndroid Build Coastguard Worker
4425*a67afe4dSAndroid Build Coastguard Worker case 2:
4426*a67afe4dSAndroid Build Coastguard Worker {
4427*a67afe4dSAndroid Build Coastguard Worker gray = (gray & 0x03) * 0x55;
4428*a67afe4dSAndroid Build Coastguard Worker sp = row + (size_t)((row_width - 1) >> 2);
4429*a67afe4dSAndroid Build Coastguard Worker dp = row + (size_t)row_width - 1;
4430*a67afe4dSAndroid Build Coastguard Worker shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
4431*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4432*a67afe4dSAndroid Build Coastguard Worker {
4433*a67afe4dSAndroid Build Coastguard Worker value = (*sp >> shift) & 0x03;
4434*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)(value | (value << 2) | (value << 4) |
4435*a67afe4dSAndroid Build Coastguard Worker (value << 6));
4436*a67afe4dSAndroid Build Coastguard Worker if (shift == 6)
4437*a67afe4dSAndroid Build Coastguard Worker {
4438*a67afe4dSAndroid Build Coastguard Worker shift = 0;
4439*a67afe4dSAndroid Build Coastguard Worker sp--;
4440*a67afe4dSAndroid Build Coastguard Worker }
4441*a67afe4dSAndroid Build Coastguard Worker
4442*a67afe4dSAndroid Build Coastguard Worker else
4443*a67afe4dSAndroid Build Coastguard Worker shift += 2;
4444*a67afe4dSAndroid Build Coastguard Worker
4445*a67afe4dSAndroid Build Coastguard Worker dp--;
4446*a67afe4dSAndroid Build Coastguard Worker }
4447*a67afe4dSAndroid Build Coastguard Worker break;
4448*a67afe4dSAndroid Build Coastguard Worker }
4449*a67afe4dSAndroid Build Coastguard Worker
4450*a67afe4dSAndroid Build Coastguard Worker case 4:
4451*a67afe4dSAndroid Build Coastguard Worker {
4452*a67afe4dSAndroid Build Coastguard Worker gray = (gray & 0x0f) * 0x11;
4453*a67afe4dSAndroid Build Coastguard Worker sp = row + (size_t)((row_width - 1) >> 1);
4454*a67afe4dSAndroid Build Coastguard Worker dp = row + (size_t)row_width - 1;
4455*a67afe4dSAndroid Build Coastguard Worker shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
4456*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4457*a67afe4dSAndroid Build Coastguard Worker {
4458*a67afe4dSAndroid Build Coastguard Worker value = (*sp >> shift) & 0x0f;
4459*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)(value | (value << 4));
4460*a67afe4dSAndroid Build Coastguard Worker if (shift == 4)
4461*a67afe4dSAndroid Build Coastguard Worker {
4462*a67afe4dSAndroid Build Coastguard Worker shift = 0;
4463*a67afe4dSAndroid Build Coastguard Worker sp--;
4464*a67afe4dSAndroid Build Coastguard Worker }
4465*a67afe4dSAndroid Build Coastguard Worker
4466*a67afe4dSAndroid Build Coastguard Worker else
4467*a67afe4dSAndroid Build Coastguard Worker shift = 4;
4468*a67afe4dSAndroid Build Coastguard Worker
4469*a67afe4dSAndroid Build Coastguard Worker dp--;
4470*a67afe4dSAndroid Build Coastguard Worker }
4471*a67afe4dSAndroid Build Coastguard Worker break;
4472*a67afe4dSAndroid Build Coastguard Worker }
4473*a67afe4dSAndroid Build Coastguard Worker
4474*a67afe4dSAndroid Build Coastguard Worker default:
4475*a67afe4dSAndroid Build Coastguard Worker break;
4476*a67afe4dSAndroid Build Coastguard Worker }
4477*a67afe4dSAndroid Build Coastguard Worker
4478*a67afe4dSAndroid Build Coastguard Worker row_info->bit_depth = 8;
4479*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = 8;
4480*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = row_width;
4481*a67afe4dSAndroid Build Coastguard Worker }
4482*a67afe4dSAndroid Build Coastguard Worker
4483*a67afe4dSAndroid Build Coastguard Worker if (trans_color != NULL)
4484*a67afe4dSAndroid Build Coastguard Worker {
4485*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
4486*a67afe4dSAndroid Build Coastguard Worker {
4487*a67afe4dSAndroid Build Coastguard Worker gray = gray & 0xff;
4488*a67afe4dSAndroid Build Coastguard Worker sp = row + (size_t)row_width - 1;
4489*a67afe4dSAndroid Build Coastguard Worker dp = row + ((size_t)row_width << 1) - 1;
4490*a67afe4dSAndroid Build Coastguard Worker
4491*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4492*a67afe4dSAndroid Build Coastguard Worker {
4493*a67afe4dSAndroid Build Coastguard Worker if ((*sp & 0xffU) == gray)
4494*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0;
4495*a67afe4dSAndroid Build Coastguard Worker
4496*a67afe4dSAndroid Build Coastguard Worker else
4497*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0xff;
4498*a67afe4dSAndroid Build Coastguard Worker
4499*a67afe4dSAndroid Build Coastguard Worker *dp-- = *sp--;
4500*a67afe4dSAndroid Build Coastguard Worker }
4501*a67afe4dSAndroid Build Coastguard Worker }
4502*a67afe4dSAndroid Build Coastguard Worker
4503*a67afe4dSAndroid Build Coastguard Worker else if (row_info->bit_depth == 16)
4504*a67afe4dSAndroid Build Coastguard Worker {
4505*a67afe4dSAndroid Build Coastguard Worker unsigned int gray_high = (gray >> 8) & 0xff;
4506*a67afe4dSAndroid Build Coastguard Worker unsigned int gray_low = gray & 0xff;
4507*a67afe4dSAndroid Build Coastguard Worker sp = row + row_info->rowbytes - 1;
4508*a67afe4dSAndroid Build Coastguard Worker dp = row + (row_info->rowbytes << 1) - 1;
4509*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4510*a67afe4dSAndroid Build Coastguard Worker {
4511*a67afe4dSAndroid Build Coastguard Worker if ((*(sp - 1) & 0xffU) == gray_high &&
4512*a67afe4dSAndroid Build Coastguard Worker (*(sp) & 0xffU) == gray_low)
4513*a67afe4dSAndroid Build Coastguard Worker {
4514*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0;
4515*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0;
4516*a67afe4dSAndroid Build Coastguard Worker }
4517*a67afe4dSAndroid Build Coastguard Worker
4518*a67afe4dSAndroid Build Coastguard Worker else
4519*a67afe4dSAndroid Build Coastguard Worker {
4520*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0xff;
4521*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0xff;
4522*a67afe4dSAndroid Build Coastguard Worker }
4523*a67afe4dSAndroid Build Coastguard Worker
4524*a67afe4dSAndroid Build Coastguard Worker *dp-- = *sp--;
4525*a67afe4dSAndroid Build Coastguard Worker *dp-- = *sp--;
4526*a67afe4dSAndroid Build Coastguard Worker }
4527*a67afe4dSAndroid Build Coastguard Worker }
4528*a67afe4dSAndroid Build Coastguard Worker
4529*a67afe4dSAndroid Build Coastguard Worker row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
4530*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 2;
4531*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
4532*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
4533*a67afe4dSAndroid Build Coastguard Worker row_width);
4534*a67afe4dSAndroid Build Coastguard Worker }
4535*a67afe4dSAndroid Build Coastguard Worker }
4536*a67afe4dSAndroid Build Coastguard Worker else if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
4537*a67afe4dSAndroid Build Coastguard Worker trans_color != NULL)
4538*a67afe4dSAndroid Build Coastguard Worker {
4539*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
4540*a67afe4dSAndroid Build Coastguard Worker {
4541*a67afe4dSAndroid Build Coastguard Worker png_byte red = (png_byte)(trans_color->red & 0xff);
4542*a67afe4dSAndroid Build Coastguard Worker png_byte green = (png_byte)(trans_color->green & 0xff);
4543*a67afe4dSAndroid Build Coastguard Worker png_byte blue = (png_byte)(trans_color->blue & 0xff);
4544*a67afe4dSAndroid Build Coastguard Worker sp = row + (size_t)row_info->rowbytes - 1;
4545*a67afe4dSAndroid Build Coastguard Worker dp = row + ((size_t)row_width << 2) - 1;
4546*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4547*a67afe4dSAndroid Build Coastguard Worker {
4548*a67afe4dSAndroid Build Coastguard Worker if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
4549*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0;
4550*a67afe4dSAndroid Build Coastguard Worker
4551*a67afe4dSAndroid Build Coastguard Worker else
4552*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0xff;
4553*a67afe4dSAndroid Build Coastguard Worker
4554*a67afe4dSAndroid Build Coastguard Worker *dp-- = *sp--;
4555*a67afe4dSAndroid Build Coastguard Worker *dp-- = *sp--;
4556*a67afe4dSAndroid Build Coastguard Worker *dp-- = *sp--;
4557*a67afe4dSAndroid Build Coastguard Worker }
4558*a67afe4dSAndroid Build Coastguard Worker }
4559*a67afe4dSAndroid Build Coastguard Worker else if (row_info->bit_depth == 16)
4560*a67afe4dSAndroid Build Coastguard Worker {
4561*a67afe4dSAndroid Build Coastguard Worker png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff);
4562*a67afe4dSAndroid Build Coastguard Worker png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff);
4563*a67afe4dSAndroid Build Coastguard Worker png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff);
4564*a67afe4dSAndroid Build Coastguard Worker png_byte red_low = (png_byte)(trans_color->red & 0xff);
4565*a67afe4dSAndroid Build Coastguard Worker png_byte green_low = (png_byte)(trans_color->green & 0xff);
4566*a67afe4dSAndroid Build Coastguard Worker png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
4567*a67afe4dSAndroid Build Coastguard Worker sp = row + row_info->rowbytes - 1;
4568*a67afe4dSAndroid Build Coastguard Worker dp = row + ((size_t)row_width << 3) - 1;
4569*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4570*a67afe4dSAndroid Build Coastguard Worker {
4571*a67afe4dSAndroid Build Coastguard Worker if (*(sp - 5) == red_high &&
4572*a67afe4dSAndroid Build Coastguard Worker *(sp - 4) == red_low &&
4573*a67afe4dSAndroid Build Coastguard Worker *(sp - 3) == green_high &&
4574*a67afe4dSAndroid Build Coastguard Worker *(sp - 2) == green_low &&
4575*a67afe4dSAndroid Build Coastguard Worker *(sp - 1) == blue_high &&
4576*a67afe4dSAndroid Build Coastguard Worker *(sp ) == blue_low)
4577*a67afe4dSAndroid Build Coastguard Worker {
4578*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0;
4579*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0;
4580*a67afe4dSAndroid Build Coastguard Worker }
4581*a67afe4dSAndroid Build Coastguard Worker
4582*a67afe4dSAndroid Build Coastguard Worker else
4583*a67afe4dSAndroid Build Coastguard Worker {
4584*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0xff;
4585*a67afe4dSAndroid Build Coastguard Worker *dp-- = 0xff;
4586*a67afe4dSAndroid Build Coastguard Worker }
4587*a67afe4dSAndroid Build Coastguard Worker
4588*a67afe4dSAndroid Build Coastguard Worker *dp-- = *sp--;
4589*a67afe4dSAndroid Build Coastguard Worker *dp-- = *sp--;
4590*a67afe4dSAndroid Build Coastguard Worker *dp-- = *sp--;
4591*a67afe4dSAndroid Build Coastguard Worker *dp-- = *sp--;
4592*a67afe4dSAndroid Build Coastguard Worker *dp-- = *sp--;
4593*a67afe4dSAndroid Build Coastguard Worker *dp-- = *sp--;
4594*a67afe4dSAndroid Build Coastguard Worker }
4595*a67afe4dSAndroid Build Coastguard Worker }
4596*a67afe4dSAndroid Build Coastguard Worker row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
4597*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 4;
4598*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
4599*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4600*a67afe4dSAndroid Build Coastguard Worker }
4601*a67afe4dSAndroid Build Coastguard Worker }
4602*a67afe4dSAndroid Build Coastguard Worker #endif
4603*a67afe4dSAndroid Build Coastguard Worker
4604*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_EXPAND_16_SUPPORTED
4605*a67afe4dSAndroid Build Coastguard Worker /* If the bit depth is 8 and the color type is not a palette type expand the
4606*a67afe4dSAndroid Build Coastguard Worker * whole row to 16 bits. Has no effect otherwise.
4607*a67afe4dSAndroid Build Coastguard Worker */
4608*a67afe4dSAndroid Build Coastguard Worker static void
png_do_expand_16(png_row_infop row_info,png_bytep row)4609*a67afe4dSAndroid Build Coastguard Worker png_do_expand_16(png_row_infop row_info, png_bytep row)
4610*a67afe4dSAndroid Build Coastguard Worker {
4611*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8 &&
4612*a67afe4dSAndroid Build Coastguard Worker row_info->color_type != PNG_COLOR_TYPE_PALETTE)
4613*a67afe4dSAndroid Build Coastguard Worker {
4614*a67afe4dSAndroid Build Coastguard Worker /* The row have a sequence of bytes containing [0..255] and we need
4615*a67afe4dSAndroid Build Coastguard Worker * to turn it into another row containing [0..65535], to do this we
4616*a67afe4dSAndroid Build Coastguard Worker * calculate:
4617*a67afe4dSAndroid Build Coastguard Worker *
4618*a67afe4dSAndroid Build Coastguard Worker * (input / 255) * 65535
4619*a67afe4dSAndroid Build Coastguard Worker *
4620*a67afe4dSAndroid Build Coastguard Worker * Which happens to be exactly input * 257 and this can be achieved
4621*a67afe4dSAndroid Build Coastguard Worker * simply by byte replication in place (copying backwards).
4622*a67afe4dSAndroid Build Coastguard Worker */
4623*a67afe4dSAndroid Build Coastguard Worker png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
4624*a67afe4dSAndroid Build Coastguard Worker png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */
4625*a67afe4dSAndroid Build Coastguard Worker while (dp > sp)
4626*a67afe4dSAndroid Build Coastguard Worker {
4627*a67afe4dSAndroid Build Coastguard Worker dp[-2] = dp[-1] = *--sp; dp -= 2;
4628*a67afe4dSAndroid Build Coastguard Worker }
4629*a67afe4dSAndroid Build Coastguard Worker
4630*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes *= 2;
4631*a67afe4dSAndroid Build Coastguard Worker row_info->bit_depth = 16;
4632*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = (png_byte)(row_info->channels * 16);
4633*a67afe4dSAndroid Build Coastguard Worker }
4634*a67afe4dSAndroid Build Coastguard Worker }
4635*a67afe4dSAndroid Build Coastguard Worker #endif
4636*a67afe4dSAndroid Build Coastguard Worker
4637*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_QUANTIZE_SUPPORTED
4638*a67afe4dSAndroid Build Coastguard Worker static void
png_do_quantize(png_row_infop row_info,png_bytep row,png_const_bytep palette_lookup,png_const_bytep quantize_lookup)4639*a67afe4dSAndroid Build Coastguard Worker png_do_quantize(png_row_infop row_info, png_bytep row,
4640*a67afe4dSAndroid Build Coastguard Worker png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
4641*a67afe4dSAndroid Build Coastguard Worker {
4642*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
4643*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
4644*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width=row_info->width;
4645*a67afe4dSAndroid Build Coastguard Worker
4646*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_quantize");
4647*a67afe4dSAndroid Build Coastguard Worker
4648*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
4649*a67afe4dSAndroid Build Coastguard Worker {
4650*a67afe4dSAndroid Build Coastguard Worker if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
4651*a67afe4dSAndroid Build Coastguard Worker {
4652*a67afe4dSAndroid Build Coastguard Worker int r, g, b, p;
4653*a67afe4dSAndroid Build Coastguard Worker sp = row;
4654*a67afe4dSAndroid Build Coastguard Worker dp = row;
4655*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4656*a67afe4dSAndroid Build Coastguard Worker {
4657*a67afe4dSAndroid Build Coastguard Worker r = *sp++;
4658*a67afe4dSAndroid Build Coastguard Worker g = *sp++;
4659*a67afe4dSAndroid Build Coastguard Worker b = *sp++;
4660*a67afe4dSAndroid Build Coastguard Worker
4661*a67afe4dSAndroid Build Coastguard Worker /* This looks real messy, but the compiler will reduce
4662*a67afe4dSAndroid Build Coastguard Worker * it down to a reasonable formula. For example, with
4663*a67afe4dSAndroid Build Coastguard Worker * 5 bits per color, we get:
4664*a67afe4dSAndroid Build Coastguard Worker * p = (((r >> 3) & 0x1f) << 10) |
4665*a67afe4dSAndroid Build Coastguard Worker * (((g >> 3) & 0x1f) << 5) |
4666*a67afe4dSAndroid Build Coastguard Worker * ((b >> 3) & 0x1f);
4667*a67afe4dSAndroid Build Coastguard Worker */
4668*a67afe4dSAndroid Build Coastguard Worker p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
4669*a67afe4dSAndroid Build Coastguard Worker ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
4670*a67afe4dSAndroid Build Coastguard Worker (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
4671*a67afe4dSAndroid Build Coastguard Worker (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
4672*a67afe4dSAndroid Build Coastguard Worker ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
4673*a67afe4dSAndroid Build Coastguard Worker (PNG_QUANTIZE_BLUE_BITS)) |
4674*a67afe4dSAndroid Build Coastguard Worker ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
4675*a67afe4dSAndroid Build Coastguard Worker ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
4676*a67afe4dSAndroid Build Coastguard Worker
4677*a67afe4dSAndroid Build Coastguard Worker *dp++ = palette_lookup[p];
4678*a67afe4dSAndroid Build Coastguard Worker }
4679*a67afe4dSAndroid Build Coastguard Worker
4680*a67afe4dSAndroid Build Coastguard Worker row_info->color_type = PNG_COLOR_TYPE_PALETTE;
4681*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 1;
4682*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = row_info->bit_depth;
4683*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4684*a67afe4dSAndroid Build Coastguard Worker }
4685*a67afe4dSAndroid Build Coastguard Worker
4686*a67afe4dSAndroid Build Coastguard Worker else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
4687*a67afe4dSAndroid Build Coastguard Worker palette_lookup != NULL)
4688*a67afe4dSAndroid Build Coastguard Worker {
4689*a67afe4dSAndroid Build Coastguard Worker int r, g, b, p;
4690*a67afe4dSAndroid Build Coastguard Worker sp = row;
4691*a67afe4dSAndroid Build Coastguard Worker dp = row;
4692*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
4693*a67afe4dSAndroid Build Coastguard Worker {
4694*a67afe4dSAndroid Build Coastguard Worker r = *sp++;
4695*a67afe4dSAndroid Build Coastguard Worker g = *sp++;
4696*a67afe4dSAndroid Build Coastguard Worker b = *sp++;
4697*a67afe4dSAndroid Build Coastguard Worker sp++;
4698*a67afe4dSAndroid Build Coastguard Worker
4699*a67afe4dSAndroid Build Coastguard Worker p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
4700*a67afe4dSAndroid Build Coastguard Worker ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
4701*a67afe4dSAndroid Build Coastguard Worker (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
4702*a67afe4dSAndroid Build Coastguard Worker (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
4703*a67afe4dSAndroid Build Coastguard Worker ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
4704*a67afe4dSAndroid Build Coastguard Worker (PNG_QUANTIZE_BLUE_BITS)) |
4705*a67afe4dSAndroid Build Coastguard Worker ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
4706*a67afe4dSAndroid Build Coastguard Worker ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
4707*a67afe4dSAndroid Build Coastguard Worker
4708*a67afe4dSAndroid Build Coastguard Worker *dp++ = palette_lookup[p];
4709*a67afe4dSAndroid Build Coastguard Worker }
4710*a67afe4dSAndroid Build Coastguard Worker
4711*a67afe4dSAndroid Build Coastguard Worker row_info->color_type = PNG_COLOR_TYPE_PALETTE;
4712*a67afe4dSAndroid Build Coastguard Worker row_info->channels = 1;
4713*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = row_info->bit_depth;
4714*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4715*a67afe4dSAndroid Build Coastguard Worker }
4716*a67afe4dSAndroid Build Coastguard Worker
4717*a67afe4dSAndroid Build Coastguard Worker else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4718*a67afe4dSAndroid Build Coastguard Worker quantize_lookup)
4719*a67afe4dSAndroid Build Coastguard Worker {
4720*a67afe4dSAndroid Build Coastguard Worker sp = row;
4721*a67afe4dSAndroid Build Coastguard Worker
4722*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++, sp++)
4723*a67afe4dSAndroid Build Coastguard Worker {
4724*a67afe4dSAndroid Build Coastguard Worker *sp = quantize_lookup[*sp];
4725*a67afe4dSAndroid Build Coastguard Worker }
4726*a67afe4dSAndroid Build Coastguard Worker }
4727*a67afe4dSAndroid Build Coastguard Worker }
4728*a67afe4dSAndroid Build Coastguard Worker }
4729*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_QUANTIZE */
4730*a67afe4dSAndroid Build Coastguard Worker
4731*a67afe4dSAndroid Build Coastguard Worker /* Transform the row. The order of transformations is significant,
4732*a67afe4dSAndroid Build Coastguard Worker * and is very touchy. If you add a transformation, take care to
4733*a67afe4dSAndroid Build Coastguard Worker * decide how it fits in with the other transformations here.
4734*a67afe4dSAndroid Build Coastguard Worker */
4735*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_do_read_transformations(png_structrp png_ptr,png_row_infop row_info)4736*a67afe4dSAndroid Build Coastguard Worker png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
4737*a67afe4dSAndroid Build Coastguard Worker {
4738*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_read_transformations");
4739*a67afe4dSAndroid Build Coastguard Worker
4740*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->row_buf == NULL)
4741*a67afe4dSAndroid Build Coastguard Worker {
4742*a67afe4dSAndroid Build Coastguard Worker /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
4743*a67afe4dSAndroid Build Coastguard Worker * error is incredibly rare and incredibly easy to debug without this
4744*a67afe4dSAndroid Build Coastguard Worker * information.
4745*a67afe4dSAndroid Build Coastguard Worker */
4746*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "NULL row buffer");
4747*a67afe4dSAndroid Build Coastguard Worker }
4748*a67afe4dSAndroid Build Coastguard Worker
4749*a67afe4dSAndroid Build Coastguard Worker /* The following is debugging; prior to 1.5.4 the code was never compiled in;
4750*a67afe4dSAndroid Build Coastguard Worker * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
4751*a67afe4dSAndroid Build Coastguard Worker * PNG_WARN_UNINITIALIZED_ROW removed. In 1.6 the new flag is set only for
4752*a67afe4dSAndroid Build Coastguard Worker * all transformations, however in practice the ROW_INIT always gets done on
4753*a67afe4dSAndroid Build Coastguard Worker * demand, if necessary.
4754*a67afe4dSAndroid Build Coastguard Worker */
4755*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
4756*a67afe4dSAndroid Build Coastguard Worker (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
4757*a67afe4dSAndroid Build Coastguard Worker {
4758*a67afe4dSAndroid Build Coastguard Worker /* Application has failed to call either png_read_start_image() or
4759*a67afe4dSAndroid Build Coastguard Worker * png_read_update_info() after setting transforms that expand pixels.
4760*a67afe4dSAndroid Build Coastguard Worker * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
4761*a67afe4dSAndroid Build Coastguard Worker */
4762*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Uninitialized row");
4763*a67afe4dSAndroid Build Coastguard Worker }
4764*a67afe4dSAndroid Build Coastguard Worker
4765*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_EXPAND_SUPPORTED
4766*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_EXPAND) != 0)
4767*a67afe4dSAndroid Build Coastguard Worker {
4768*a67afe4dSAndroid Build Coastguard Worker if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
4769*a67afe4dSAndroid Build Coastguard Worker {
4770*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
4771*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8))
4772*a67afe4dSAndroid Build Coastguard Worker {
4773*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->riffled_palette == NULL)
4774*a67afe4dSAndroid Build Coastguard Worker {
4775*a67afe4dSAndroid Build Coastguard Worker /* Initialize the accelerated palette expansion. */
4776*a67afe4dSAndroid Build Coastguard Worker png_ptr->riffled_palette =
4777*a67afe4dSAndroid Build Coastguard Worker (png_bytep)png_malloc(png_ptr, 256 * 4);
4778*a67afe4dSAndroid Build Coastguard Worker png_riffle_palette_neon(png_ptr);
4779*a67afe4dSAndroid Build Coastguard Worker }
4780*a67afe4dSAndroid Build Coastguard Worker }
4781*a67afe4dSAndroid Build Coastguard Worker #endif
4782*a67afe4dSAndroid Build Coastguard Worker png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1,
4783*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
4784*a67afe4dSAndroid Build Coastguard Worker }
4785*a67afe4dSAndroid Build Coastguard Worker
4786*a67afe4dSAndroid Build Coastguard Worker else
4787*a67afe4dSAndroid Build Coastguard Worker {
4788*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->num_trans != 0 &&
4789*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
4790*a67afe4dSAndroid Build Coastguard Worker png_do_expand(row_info, png_ptr->row_buf + 1,
4791*a67afe4dSAndroid Build Coastguard Worker &(png_ptr->trans_color));
4792*a67afe4dSAndroid Build Coastguard Worker
4793*a67afe4dSAndroid Build Coastguard Worker else
4794*a67afe4dSAndroid Build Coastguard Worker png_do_expand(row_info, png_ptr->row_buf + 1, NULL);
4795*a67afe4dSAndroid Build Coastguard Worker }
4796*a67afe4dSAndroid Build Coastguard Worker }
4797*a67afe4dSAndroid Build Coastguard Worker #endif
4798*a67afe4dSAndroid Build Coastguard Worker
4799*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4800*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
4801*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_COMPOSE) == 0 &&
4802*a67afe4dSAndroid Build Coastguard Worker (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
4803*a67afe4dSAndroid Build Coastguard Worker row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
4804*a67afe4dSAndroid Build Coastguard Worker png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4805*a67afe4dSAndroid Build Coastguard Worker 0 /* at_start == false, because SWAP_ALPHA happens later */);
4806*a67afe4dSAndroid Build Coastguard Worker #endif
4807*a67afe4dSAndroid Build Coastguard Worker
4808*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
4809*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
4810*a67afe4dSAndroid Build Coastguard Worker {
4811*a67afe4dSAndroid Build Coastguard Worker int rgb_error =
4812*a67afe4dSAndroid Build Coastguard Worker png_do_rgb_to_gray(png_ptr, row_info,
4813*a67afe4dSAndroid Build Coastguard Worker png_ptr->row_buf + 1);
4814*a67afe4dSAndroid Build Coastguard Worker
4815*a67afe4dSAndroid Build Coastguard Worker if (rgb_error != 0)
4816*a67afe4dSAndroid Build Coastguard Worker {
4817*a67afe4dSAndroid Build Coastguard Worker png_ptr->rgb_to_gray_status=1;
4818*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
4819*a67afe4dSAndroid Build Coastguard Worker PNG_RGB_TO_GRAY_WARN)
4820*a67afe4dSAndroid Build Coastguard Worker png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
4821*a67afe4dSAndroid Build Coastguard Worker
4822*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
4823*a67afe4dSAndroid Build Coastguard Worker PNG_RGB_TO_GRAY_ERR)
4824*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
4825*a67afe4dSAndroid Build Coastguard Worker }
4826*a67afe4dSAndroid Build Coastguard Worker }
4827*a67afe4dSAndroid Build Coastguard Worker #endif
4828*a67afe4dSAndroid Build Coastguard Worker
4829*a67afe4dSAndroid Build Coastguard Worker /* From Andreas Dilger e-mail to png-implement, 26 March 1998:
4830*a67afe4dSAndroid Build Coastguard Worker *
4831*a67afe4dSAndroid Build Coastguard Worker * In most cases, the "simple transparency" should be done prior to doing
4832*a67afe4dSAndroid Build Coastguard Worker * gray-to-RGB, or you will have to test 3x as many bytes to check if a
4833*a67afe4dSAndroid Build Coastguard Worker * pixel is transparent. You would also need to make sure that the
4834*a67afe4dSAndroid Build Coastguard Worker * transparency information is upgraded to RGB.
4835*a67afe4dSAndroid Build Coastguard Worker *
4836*a67afe4dSAndroid Build Coastguard Worker * To summarize, the current flow is:
4837*a67afe4dSAndroid Build Coastguard Worker * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
4838*a67afe4dSAndroid Build Coastguard Worker * with background "in place" if transparent,
4839*a67afe4dSAndroid Build Coastguard Worker * convert to RGB if necessary
4840*a67afe4dSAndroid Build Coastguard Worker * - Gray + alpha -> composite with gray background and remove alpha bytes,
4841*a67afe4dSAndroid Build Coastguard Worker * convert to RGB if necessary
4842*a67afe4dSAndroid Build Coastguard Worker *
4843*a67afe4dSAndroid Build Coastguard Worker * To support RGB backgrounds for gray images we need:
4844*a67afe4dSAndroid Build Coastguard Worker * - Gray + simple transparency -> convert to RGB + simple transparency,
4845*a67afe4dSAndroid Build Coastguard Worker * compare 3 or 6 bytes and composite with
4846*a67afe4dSAndroid Build Coastguard Worker * background "in place" if transparent
4847*a67afe4dSAndroid Build Coastguard Worker * (3x compare/pixel compared to doing
4848*a67afe4dSAndroid Build Coastguard Worker * composite with gray bkgrnd)
4849*a67afe4dSAndroid Build Coastguard Worker * - Gray + alpha -> convert to RGB + alpha, composite with background and
4850*a67afe4dSAndroid Build Coastguard Worker * remove alpha bytes (3x float
4851*a67afe4dSAndroid Build Coastguard Worker * operations/pixel compared with composite
4852*a67afe4dSAndroid Build Coastguard Worker * on gray background)
4853*a67afe4dSAndroid Build Coastguard Worker *
4854*a67afe4dSAndroid Build Coastguard Worker * Greg's change will do this. The reason it wasn't done before is for
4855*a67afe4dSAndroid Build Coastguard Worker * performance, as this increases the per-pixel operations. If we would check
4856*a67afe4dSAndroid Build Coastguard Worker * in advance if the background was gray or RGB, and position the gray-to-RGB
4857*a67afe4dSAndroid Build Coastguard Worker * transform appropriately, then it would save a lot of work/time.
4858*a67afe4dSAndroid Build Coastguard Worker */
4859*a67afe4dSAndroid Build Coastguard Worker
4860*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
4861*a67afe4dSAndroid Build Coastguard Worker /* If gray -> RGB, do so now only if background is non-gray; else do later
4862*a67afe4dSAndroid Build Coastguard Worker * for performance reasons
4863*a67afe4dSAndroid Build Coastguard Worker */
4864*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
4865*a67afe4dSAndroid Build Coastguard Worker (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
4866*a67afe4dSAndroid Build Coastguard Worker png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
4867*a67afe4dSAndroid Build Coastguard Worker #endif
4868*a67afe4dSAndroid Build Coastguard Worker
4869*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
4870*a67afe4dSAndroid Build Coastguard Worker defined(PNG_READ_ALPHA_MODE_SUPPORTED)
4871*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_COMPOSE) != 0)
4872*a67afe4dSAndroid Build Coastguard Worker png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
4873*a67afe4dSAndroid Build Coastguard Worker #endif
4874*a67afe4dSAndroid Build Coastguard Worker
4875*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GAMMA_SUPPORTED
4876*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_GAMMA) != 0 &&
4877*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
4878*a67afe4dSAndroid Build Coastguard Worker /* Because RGB_TO_GRAY does the gamma transform. */
4879*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 &&
4880*a67afe4dSAndroid Build Coastguard Worker #endif
4881*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
4882*a67afe4dSAndroid Build Coastguard Worker defined(PNG_READ_ALPHA_MODE_SUPPORTED)
4883*a67afe4dSAndroid Build Coastguard Worker /* Because PNG_COMPOSE does the gamma transform if there is something to
4884*a67afe4dSAndroid Build Coastguard Worker * do (if there is an alpha channel or transparency.)
4885*a67afe4dSAndroid Build Coastguard Worker */
4886*a67afe4dSAndroid Build Coastguard Worker !((png_ptr->transformations & PNG_COMPOSE) != 0 &&
4887*a67afe4dSAndroid Build Coastguard Worker ((png_ptr->num_trans != 0) ||
4888*a67afe4dSAndroid Build Coastguard Worker (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) &&
4889*a67afe4dSAndroid Build Coastguard Worker #endif
4890*a67afe4dSAndroid Build Coastguard Worker /* Because png_init_read_transformations transforms the palette, unless
4891*a67afe4dSAndroid Build Coastguard Worker * RGB_TO_GRAY will do the transform.
4892*a67afe4dSAndroid Build Coastguard Worker */
4893*a67afe4dSAndroid Build Coastguard Worker (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
4894*a67afe4dSAndroid Build Coastguard Worker png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
4895*a67afe4dSAndroid Build Coastguard Worker #endif
4896*a67afe4dSAndroid Build Coastguard Worker
4897*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
4898*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
4899*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_COMPOSE) != 0 &&
4900*a67afe4dSAndroid Build Coastguard Worker (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
4901*a67afe4dSAndroid Build Coastguard Worker row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
4902*a67afe4dSAndroid Build Coastguard Worker png_do_strip_channel(row_info, png_ptr->row_buf + 1,
4903*a67afe4dSAndroid Build Coastguard Worker 0 /* at_start == false, because SWAP_ALPHA happens later */);
4904*a67afe4dSAndroid Build Coastguard Worker #endif
4905*a67afe4dSAndroid Build Coastguard Worker
4906*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
4907*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
4908*a67afe4dSAndroid Build Coastguard Worker (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
4909*a67afe4dSAndroid Build Coastguard Worker png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
4910*a67afe4dSAndroid Build Coastguard Worker #endif
4911*a67afe4dSAndroid Build Coastguard Worker
4912*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
4913*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
4914*a67afe4dSAndroid Build Coastguard Worker png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
4915*a67afe4dSAndroid Build Coastguard Worker #endif
4916*a67afe4dSAndroid Build Coastguard Worker
4917*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
4918*a67afe4dSAndroid Build Coastguard Worker /* There is no harm in doing both of these because only one has any effect,
4919*a67afe4dSAndroid Build Coastguard Worker * by putting the 'scale' option first if the app asks for scale (either by
4920*a67afe4dSAndroid Build Coastguard Worker * calling the API or in a TRANSFORM flag) this is what happens.
4921*a67afe4dSAndroid Build Coastguard Worker */
4922*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_16_TO_8) != 0)
4923*a67afe4dSAndroid Build Coastguard Worker png_do_chop(row_info, png_ptr->row_buf + 1);
4924*a67afe4dSAndroid Build Coastguard Worker #endif
4925*a67afe4dSAndroid Build Coastguard Worker
4926*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_QUANTIZE_SUPPORTED
4927*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
4928*a67afe4dSAndroid Build Coastguard Worker {
4929*a67afe4dSAndroid Build Coastguard Worker png_do_quantize(row_info, png_ptr->row_buf + 1,
4930*a67afe4dSAndroid Build Coastguard Worker png_ptr->palette_lookup, png_ptr->quantize_index);
4931*a67afe4dSAndroid Build Coastguard Worker
4932*a67afe4dSAndroid Build Coastguard Worker if (row_info->rowbytes == 0)
4933*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "png_do_quantize returned rowbytes=0");
4934*a67afe4dSAndroid Build Coastguard Worker }
4935*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_QUANTIZE */
4936*a67afe4dSAndroid Build Coastguard Worker
4937*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_EXPAND_16_SUPPORTED
4938*a67afe4dSAndroid Build Coastguard Worker /* Do the expansion now, after all the arithmetic has been done. Notice
4939*a67afe4dSAndroid Build Coastguard Worker * that previous transformations can handle the PNG_EXPAND_16 flag if this
4940*a67afe4dSAndroid Build Coastguard Worker * is efficient (particularly true in the case of gamma correction, where
4941*a67afe4dSAndroid Build Coastguard Worker * better accuracy results faster!)
4942*a67afe4dSAndroid Build Coastguard Worker */
4943*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
4944*a67afe4dSAndroid Build Coastguard Worker png_do_expand_16(row_info, png_ptr->row_buf + 1);
4945*a67afe4dSAndroid Build Coastguard Worker #endif
4946*a67afe4dSAndroid Build Coastguard Worker
4947*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
4948*a67afe4dSAndroid Build Coastguard Worker /* NOTE: moved here in 1.5.4 (from much later in this list.) */
4949*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
4950*a67afe4dSAndroid Build Coastguard Worker (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0)
4951*a67afe4dSAndroid Build Coastguard Worker png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
4952*a67afe4dSAndroid Build Coastguard Worker #endif
4953*a67afe4dSAndroid Build Coastguard Worker
4954*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_INVERT_SUPPORTED
4955*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
4956*a67afe4dSAndroid Build Coastguard Worker png_do_invert(row_info, png_ptr->row_buf + 1);
4957*a67afe4dSAndroid Build Coastguard Worker #endif
4958*a67afe4dSAndroid Build Coastguard Worker
4959*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
4960*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
4961*a67afe4dSAndroid Build Coastguard Worker png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
4962*a67afe4dSAndroid Build Coastguard Worker #endif
4963*a67afe4dSAndroid Build Coastguard Worker
4964*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_SHIFT_SUPPORTED
4965*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_SHIFT) != 0)
4966*a67afe4dSAndroid Build Coastguard Worker png_do_unshift(row_info, png_ptr->row_buf + 1,
4967*a67afe4dSAndroid Build Coastguard Worker &(png_ptr->shift));
4968*a67afe4dSAndroid Build Coastguard Worker #endif
4969*a67afe4dSAndroid Build Coastguard Worker
4970*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_PACK_SUPPORTED
4971*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_PACK) != 0)
4972*a67afe4dSAndroid Build Coastguard Worker png_do_unpack(row_info, png_ptr->row_buf + 1);
4973*a67afe4dSAndroid Build Coastguard Worker #endif
4974*a67afe4dSAndroid Build Coastguard Worker
4975*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
4976*a67afe4dSAndroid Build Coastguard Worker /* Added at libpng-1.5.10 */
4977*a67afe4dSAndroid Build Coastguard Worker if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4978*a67afe4dSAndroid Build Coastguard Worker png_ptr->num_palette_max >= 0)
4979*a67afe4dSAndroid Build Coastguard Worker png_do_check_palette_indexes(png_ptr, row_info);
4980*a67afe4dSAndroid Build Coastguard Worker #endif
4981*a67afe4dSAndroid Build Coastguard Worker
4982*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_BGR_SUPPORTED
4983*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_BGR) != 0)
4984*a67afe4dSAndroid Build Coastguard Worker png_do_bgr(row_info, png_ptr->row_buf + 1);
4985*a67afe4dSAndroid Build Coastguard Worker #endif
4986*a67afe4dSAndroid Build Coastguard Worker
4987*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_PACKSWAP_SUPPORTED
4988*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
4989*a67afe4dSAndroid Build Coastguard Worker png_do_packswap(row_info, png_ptr->row_buf + 1);
4990*a67afe4dSAndroid Build Coastguard Worker #endif
4991*a67afe4dSAndroid Build Coastguard Worker
4992*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_FILLER_SUPPORTED
4993*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_FILLER) != 0)
4994*a67afe4dSAndroid Build Coastguard Worker png_do_read_filler(row_info, png_ptr->row_buf + 1,
4995*a67afe4dSAndroid Build Coastguard Worker (png_uint_32)png_ptr->filler, png_ptr->flags);
4996*a67afe4dSAndroid Build Coastguard Worker #endif
4997*a67afe4dSAndroid Build Coastguard Worker
4998*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
4999*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
5000*a67afe4dSAndroid Build Coastguard Worker png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
5001*a67afe4dSAndroid Build Coastguard Worker #endif
5002*a67afe4dSAndroid Build Coastguard Worker
5003*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_16BIT_SUPPORTED
5004*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_SWAP_SUPPORTED
5005*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
5006*a67afe4dSAndroid Build Coastguard Worker png_do_swap(row_info, png_ptr->row_buf + 1);
5007*a67afe4dSAndroid Build Coastguard Worker #endif
5008*a67afe4dSAndroid Build Coastguard Worker #endif
5009*a67afe4dSAndroid Build Coastguard Worker
5010*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
5011*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
5012*a67afe4dSAndroid Build Coastguard Worker {
5013*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->read_user_transform_fn != NULL)
5014*a67afe4dSAndroid Build Coastguard Worker (*(png_ptr->read_user_transform_fn)) /* User read transform function */
5015*a67afe4dSAndroid Build Coastguard Worker (png_ptr, /* png_ptr */
5016*a67afe4dSAndroid Build Coastguard Worker row_info, /* row_info: */
5017*a67afe4dSAndroid Build Coastguard Worker /* png_uint_32 width; width of row */
5018*a67afe4dSAndroid Build Coastguard Worker /* size_t rowbytes; number of bytes in row */
5019*a67afe4dSAndroid Build Coastguard Worker /* png_byte color_type; color type of pixels */
5020*a67afe4dSAndroid Build Coastguard Worker /* png_byte bit_depth; bit depth of samples */
5021*a67afe4dSAndroid Build Coastguard Worker /* png_byte channels; number of channels (1-4) */
5022*a67afe4dSAndroid Build Coastguard Worker /* png_byte pixel_depth; bits per pixel (depth*channels) */
5023*a67afe4dSAndroid Build Coastguard Worker png_ptr->row_buf + 1); /* start of pixel data for row */
5024*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
5025*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->user_transform_depth != 0)
5026*a67afe4dSAndroid Build Coastguard Worker row_info->bit_depth = png_ptr->user_transform_depth;
5027*a67afe4dSAndroid Build Coastguard Worker
5028*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->user_transform_channels != 0)
5029*a67afe4dSAndroid Build Coastguard Worker row_info->channels = png_ptr->user_transform_channels;
5030*a67afe4dSAndroid Build Coastguard Worker #endif
5031*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = (png_byte)(row_info->bit_depth *
5032*a67afe4dSAndroid Build Coastguard Worker row_info->channels);
5033*a67afe4dSAndroid Build Coastguard Worker
5034*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
5035*a67afe4dSAndroid Build Coastguard Worker }
5036*a67afe4dSAndroid Build Coastguard Worker #endif
5037*a67afe4dSAndroid Build Coastguard Worker }
5038*a67afe4dSAndroid Build Coastguard Worker
5039*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_TRANSFORMS */
5040*a67afe4dSAndroid Build Coastguard Worker #endif /* READ */
5041