1*a67afe4dSAndroid Build Coastguard Worker
2*a67afe4dSAndroid Build Coastguard Worker /* pngwtran.c - transforms the data in a row for PNG writers
3*a67afe4dSAndroid Build Coastguard Worker *
4*a67afe4dSAndroid Build Coastguard Worker * Copyright (c) 2018 Cosmin Truta
5*a67afe4dSAndroid Build Coastguard Worker * Copyright (c) 1998-2002,2004,2006-2016,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
14*a67afe4dSAndroid Build Coastguard Worker #include "pngpriv.h"
15*a67afe4dSAndroid Build Coastguard Worker
16*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_SUPPORTED
17*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
18*a67afe4dSAndroid Build Coastguard Worker
19*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_PACK_SUPPORTED
20*a67afe4dSAndroid Build Coastguard Worker /* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
21*a67afe4dSAndroid Build Coastguard Worker * row_info bit depth should be 8 (one pixel per byte). The channels
22*a67afe4dSAndroid Build Coastguard Worker * should be 1 (this only happens on grayscale and paletted images).
23*a67afe4dSAndroid Build Coastguard Worker */
24*a67afe4dSAndroid Build Coastguard Worker static void
png_do_pack(png_row_infop row_info,png_bytep row,png_uint_32 bit_depth)25*a67afe4dSAndroid Build Coastguard Worker png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
26*a67afe4dSAndroid Build Coastguard Worker {
27*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_pack");
28*a67afe4dSAndroid Build Coastguard Worker
29*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8 &&
30*a67afe4dSAndroid Build Coastguard Worker row_info->channels == 1)
31*a67afe4dSAndroid Build Coastguard Worker {
32*a67afe4dSAndroid Build Coastguard Worker switch ((int)bit_depth)
33*a67afe4dSAndroid Build Coastguard Worker {
34*a67afe4dSAndroid Build Coastguard Worker case 1:
35*a67afe4dSAndroid Build Coastguard Worker {
36*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
37*a67afe4dSAndroid Build Coastguard Worker int mask, v;
38*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
39*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
40*a67afe4dSAndroid Build Coastguard Worker
41*a67afe4dSAndroid Build Coastguard Worker sp = row;
42*a67afe4dSAndroid Build Coastguard Worker dp = row;
43*a67afe4dSAndroid Build Coastguard Worker mask = 0x80;
44*a67afe4dSAndroid Build Coastguard Worker v = 0;
45*a67afe4dSAndroid Build Coastguard Worker
46*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
47*a67afe4dSAndroid Build Coastguard Worker {
48*a67afe4dSAndroid Build Coastguard Worker if (*sp != 0)
49*a67afe4dSAndroid Build Coastguard Worker v |= mask;
50*a67afe4dSAndroid Build Coastguard Worker
51*a67afe4dSAndroid Build Coastguard Worker sp++;
52*a67afe4dSAndroid Build Coastguard Worker
53*a67afe4dSAndroid Build Coastguard Worker if (mask > 1)
54*a67afe4dSAndroid Build Coastguard Worker mask >>= 1;
55*a67afe4dSAndroid Build Coastguard Worker
56*a67afe4dSAndroid Build Coastguard Worker else
57*a67afe4dSAndroid Build Coastguard Worker {
58*a67afe4dSAndroid Build Coastguard Worker mask = 0x80;
59*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)v;
60*a67afe4dSAndroid Build Coastguard Worker dp++;
61*a67afe4dSAndroid Build Coastguard Worker v = 0;
62*a67afe4dSAndroid Build Coastguard Worker }
63*a67afe4dSAndroid Build Coastguard Worker }
64*a67afe4dSAndroid Build Coastguard Worker
65*a67afe4dSAndroid Build Coastguard Worker if (mask != 0x80)
66*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)v;
67*a67afe4dSAndroid Build Coastguard Worker
68*a67afe4dSAndroid Build Coastguard Worker break;
69*a67afe4dSAndroid Build Coastguard Worker }
70*a67afe4dSAndroid Build Coastguard Worker
71*a67afe4dSAndroid Build Coastguard Worker case 2:
72*a67afe4dSAndroid Build Coastguard Worker {
73*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
74*a67afe4dSAndroid Build Coastguard Worker unsigned int shift;
75*a67afe4dSAndroid Build Coastguard Worker int v;
76*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
77*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
78*a67afe4dSAndroid Build Coastguard Worker
79*a67afe4dSAndroid Build Coastguard Worker sp = row;
80*a67afe4dSAndroid Build Coastguard Worker dp = row;
81*a67afe4dSAndroid Build Coastguard Worker shift = 6;
82*a67afe4dSAndroid Build Coastguard Worker v = 0;
83*a67afe4dSAndroid Build Coastguard Worker
84*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
85*a67afe4dSAndroid Build Coastguard Worker {
86*a67afe4dSAndroid Build Coastguard Worker png_byte value;
87*a67afe4dSAndroid Build Coastguard Worker
88*a67afe4dSAndroid Build Coastguard Worker value = (png_byte)(*sp & 0x03);
89*a67afe4dSAndroid Build Coastguard Worker v |= (value << shift);
90*a67afe4dSAndroid Build Coastguard Worker
91*a67afe4dSAndroid Build Coastguard Worker if (shift == 0)
92*a67afe4dSAndroid Build Coastguard Worker {
93*a67afe4dSAndroid Build Coastguard Worker shift = 6;
94*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)v;
95*a67afe4dSAndroid Build Coastguard Worker dp++;
96*a67afe4dSAndroid Build Coastguard Worker v = 0;
97*a67afe4dSAndroid Build Coastguard Worker }
98*a67afe4dSAndroid Build Coastguard Worker
99*a67afe4dSAndroid Build Coastguard Worker else
100*a67afe4dSAndroid Build Coastguard Worker shift -= 2;
101*a67afe4dSAndroid Build Coastguard Worker
102*a67afe4dSAndroid Build Coastguard Worker sp++;
103*a67afe4dSAndroid Build Coastguard Worker }
104*a67afe4dSAndroid Build Coastguard Worker
105*a67afe4dSAndroid Build Coastguard Worker if (shift != 6)
106*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)v;
107*a67afe4dSAndroid Build Coastguard Worker
108*a67afe4dSAndroid Build Coastguard Worker break;
109*a67afe4dSAndroid Build Coastguard Worker }
110*a67afe4dSAndroid Build Coastguard Worker
111*a67afe4dSAndroid Build Coastguard Worker case 4:
112*a67afe4dSAndroid Build Coastguard Worker {
113*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
114*a67afe4dSAndroid Build Coastguard Worker unsigned int shift;
115*a67afe4dSAndroid Build Coastguard Worker int v;
116*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
117*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
118*a67afe4dSAndroid Build Coastguard Worker
119*a67afe4dSAndroid Build Coastguard Worker sp = row;
120*a67afe4dSAndroid Build Coastguard Worker dp = row;
121*a67afe4dSAndroid Build Coastguard Worker shift = 4;
122*a67afe4dSAndroid Build Coastguard Worker v = 0;
123*a67afe4dSAndroid Build Coastguard Worker
124*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_width; i++)
125*a67afe4dSAndroid Build Coastguard Worker {
126*a67afe4dSAndroid Build Coastguard Worker png_byte value;
127*a67afe4dSAndroid Build Coastguard Worker
128*a67afe4dSAndroid Build Coastguard Worker value = (png_byte)(*sp & 0x0f);
129*a67afe4dSAndroid Build Coastguard Worker v |= (value << shift);
130*a67afe4dSAndroid Build Coastguard Worker
131*a67afe4dSAndroid Build Coastguard Worker if (shift == 0)
132*a67afe4dSAndroid Build Coastguard Worker {
133*a67afe4dSAndroid Build Coastguard Worker shift = 4;
134*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)v;
135*a67afe4dSAndroid Build Coastguard Worker dp++;
136*a67afe4dSAndroid Build Coastguard Worker v = 0;
137*a67afe4dSAndroid Build Coastguard Worker }
138*a67afe4dSAndroid Build Coastguard Worker
139*a67afe4dSAndroid Build Coastguard Worker else
140*a67afe4dSAndroid Build Coastguard Worker shift -= 4;
141*a67afe4dSAndroid Build Coastguard Worker
142*a67afe4dSAndroid Build Coastguard Worker sp++;
143*a67afe4dSAndroid Build Coastguard Worker }
144*a67afe4dSAndroid Build Coastguard Worker
145*a67afe4dSAndroid Build Coastguard Worker if (shift != 4)
146*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)v;
147*a67afe4dSAndroid Build Coastguard Worker
148*a67afe4dSAndroid Build Coastguard Worker break;
149*a67afe4dSAndroid Build Coastguard Worker }
150*a67afe4dSAndroid Build Coastguard Worker
151*a67afe4dSAndroid Build Coastguard Worker default:
152*a67afe4dSAndroid Build Coastguard Worker break;
153*a67afe4dSAndroid Build Coastguard Worker }
154*a67afe4dSAndroid Build Coastguard Worker
155*a67afe4dSAndroid Build Coastguard Worker row_info->bit_depth = (png_byte)bit_depth;
156*a67afe4dSAndroid Build Coastguard Worker row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
157*a67afe4dSAndroid Build Coastguard Worker row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
158*a67afe4dSAndroid Build Coastguard Worker row_info->width);
159*a67afe4dSAndroid Build Coastguard Worker }
160*a67afe4dSAndroid Build Coastguard Worker }
161*a67afe4dSAndroid Build Coastguard Worker #endif
162*a67afe4dSAndroid Build Coastguard Worker
163*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_SHIFT_SUPPORTED
164*a67afe4dSAndroid Build Coastguard Worker /* Shift pixel values to take advantage of whole range. Pass the
165*a67afe4dSAndroid Build Coastguard Worker * true number of bits in bit_depth. The row should be packed
166*a67afe4dSAndroid Build Coastguard Worker * according to row_info->bit_depth. Thus, if you had a row of
167*a67afe4dSAndroid Build Coastguard Worker * bit depth 4, but the pixels only had values from 0 to 7, you
168*a67afe4dSAndroid Build Coastguard Worker * would pass 3 as bit_depth, and this routine would translate the
169*a67afe4dSAndroid Build Coastguard Worker * data to 0 to 15.
170*a67afe4dSAndroid Build Coastguard Worker */
171*a67afe4dSAndroid Build Coastguard Worker static void
png_do_shift(png_row_infop row_info,png_bytep row,png_const_color_8p bit_depth)172*a67afe4dSAndroid Build Coastguard Worker png_do_shift(png_row_infop row_info, png_bytep row,
173*a67afe4dSAndroid Build Coastguard Worker png_const_color_8p bit_depth)
174*a67afe4dSAndroid Build Coastguard Worker {
175*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_shift");
176*a67afe4dSAndroid Build Coastguard Worker
177*a67afe4dSAndroid Build Coastguard Worker if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
178*a67afe4dSAndroid Build Coastguard Worker {
179*a67afe4dSAndroid Build Coastguard Worker int shift_start[4], shift_dec[4];
180*a67afe4dSAndroid Build Coastguard Worker unsigned int channels = 0;
181*a67afe4dSAndroid Build Coastguard Worker
182*a67afe4dSAndroid Build Coastguard Worker if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
183*a67afe4dSAndroid Build Coastguard Worker {
184*a67afe4dSAndroid Build Coastguard Worker shift_start[channels] = row_info->bit_depth - bit_depth->red;
185*a67afe4dSAndroid Build Coastguard Worker shift_dec[channels] = bit_depth->red;
186*a67afe4dSAndroid Build Coastguard Worker channels++;
187*a67afe4dSAndroid Build Coastguard Worker
188*a67afe4dSAndroid Build Coastguard Worker shift_start[channels] = row_info->bit_depth - bit_depth->green;
189*a67afe4dSAndroid Build Coastguard Worker shift_dec[channels] = bit_depth->green;
190*a67afe4dSAndroid Build Coastguard Worker channels++;
191*a67afe4dSAndroid Build Coastguard Worker
192*a67afe4dSAndroid Build Coastguard Worker shift_start[channels] = row_info->bit_depth - bit_depth->blue;
193*a67afe4dSAndroid Build Coastguard Worker shift_dec[channels] = bit_depth->blue;
194*a67afe4dSAndroid Build Coastguard Worker channels++;
195*a67afe4dSAndroid Build Coastguard Worker }
196*a67afe4dSAndroid Build Coastguard Worker
197*a67afe4dSAndroid Build Coastguard Worker else
198*a67afe4dSAndroid Build Coastguard Worker {
199*a67afe4dSAndroid Build Coastguard Worker shift_start[channels] = row_info->bit_depth - bit_depth->gray;
200*a67afe4dSAndroid Build Coastguard Worker shift_dec[channels] = bit_depth->gray;
201*a67afe4dSAndroid Build Coastguard Worker channels++;
202*a67afe4dSAndroid Build Coastguard Worker }
203*a67afe4dSAndroid Build Coastguard Worker
204*a67afe4dSAndroid Build Coastguard Worker if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
205*a67afe4dSAndroid Build Coastguard Worker {
206*a67afe4dSAndroid Build Coastguard Worker shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
207*a67afe4dSAndroid Build Coastguard Worker shift_dec[channels] = bit_depth->alpha;
208*a67afe4dSAndroid Build Coastguard Worker channels++;
209*a67afe4dSAndroid Build Coastguard Worker }
210*a67afe4dSAndroid Build Coastguard Worker
211*a67afe4dSAndroid Build Coastguard Worker /* With low row depths, could only be grayscale, so one channel */
212*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth < 8)
213*a67afe4dSAndroid Build Coastguard Worker {
214*a67afe4dSAndroid Build Coastguard Worker png_bytep bp = row;
215*a67afe4dSAndroid Build Coastguard Worker size_t i;
216*a67afe4dSAndroid Build Coastguard Worker unsigned int mask;
217*a67afe4dSAndroid Build Coastguard Worker size_t row_bytes = row_info->rowbytes;
218*a67afe4dSAndroid Build Coastguard Worker
219*a67afe4dSAndroid Build Coastguard Worker if (bit_depth->gray == 1 && row_info->bit_depth == 2)
220*a67afe4dSAndroid Build Coastguard Worker mask = 0x55;
221*a67afe4dSAndroid Build Coastguard Worker
222*a67afe4dSAndroid Build Coastguard Worker else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
223*a67afe4dSAndroid Build Coastguard Worker mask = 0x11;
224*a67afe4dSAndroid Build Coastguard Worker
225*a67afe4dSAndroid Build Coastguard Worker else
226*a67afe4dSAndroid Build Coastguard Worker mask = 0xff;
227*a67afe4dSAndroid Build Coastguard Worker
228*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < row_bytes; i++, bp++)
229*a67afe4dSAndroid Build Coastguard Worker {
230*a67afe4dSAndroid Build Coastguard Worker int j;
231*a67afe4dSAndroid Build Coastguard Worker unsigned int v, out;
232*a67afe4dSAndroid Build Coastguard Worker
233*a67afe4dSAndroid Build Coastguard Worker v = *bp;
234*a67afe4dSAndroid Build Coastguard Worker out = 0;
235*a67afe4dSAndroid Build Coastguard Worker
236*a67afe4dSAndroid Build Coastguard Worker for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
237*a67afe4dSAndroid Build Coastguard Worker {
238*a67afe4dSAndroid Build Coastguard Worker if (j > 0)
239*a67afe4dSAndroid Build Coastguard Worker out |= v << j;
240*a67afe4dSAndroid Build Coastguard Worker
241*a67afe4dSAndroid Build Coastguard Worker else
242*a67afe4dSAndroid Build Coastguard Worker out |= (v >> (-j)) & mask;
243*a67afe4dSAndroid Build Coastguard Worker }
244*a67afe4dSAndroid Build Coastguard Worker
245*a67afe4dSAndroid Build Coastguard Worker *bp = (png_byte)(out & 0xff);
246*a67afe4dSAndroid Build Coastguard Worker }
247*a67afe4dSAndroid Build Coastguard Worker }
248*a67afe4dSAndroid Build Coastguard Worker
249*a67afe4dSAndroid Build Coastguard Worker else if (row_info->bit_depth == 8)
250*a67afe4dSAndroid Build Coastguard Worker {
251*a67afe4dSAndroid Build Coastguard Worker png_bytep bp = row;
252*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
253*a67afe4dSAndroid Build Coastguard Worker png_uint_32 istop = channels * row_info->width;
254*a67afe4dSAndroid Build Coastguard Worker
255*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < istop; i++, bp++)
256*a67afe4dSAndroid Build Coastguard Worker {
257*a67afe4dSAndroid Build Coastguard Worker unsigned int c = i%channels;
258*a67afe4dSAndroid Build Coastguard Worker int j;
259*a67afe4dSAndroid Build Coastguard Worker unsigned int v, out;
260*a67afe4dSAndroid Build Coastguard Worker
261*a67afe4dSAndroid Build Coastguard Worker v = *bp;
262*a67afe4dSAndroid Build Coastguard Worker out = 0;
263*a67afe4dSAndroid Build Coastguard Worker
264*a67afe4dSAndroid Build Coastguard Worker for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
265*a67afe4dSAndroid Build Coastguard Worker {
266*a67afe4dSAndroid Build Coastguard Worker if (j > 0)
267*a67afe4dSAndroid Build Coastguard Worker out |= v << j;
268*a67afe4dSAndroid Build Coastguard Worker
269*a67afe4dSAndroid Build Coastguard Worker else
270*a67afe4dSAndroid Build Coastguard Worker out |= v >> (-j);
271*a67afe4dSAndroid Build Coastguard Worker }
272*a67afe4dSAndroid Build Coastguard Worker
273*a67afe4dSAndroid Build Coastguard Worker *bp = (png_byte)(out & 0xff);
274*a67afe4dSAndroid Build Coastguard Worker }
275*a67afe4dSAndroid Build Coastguard Worker }
276*a67afe4dSAndroid Build Coastguard Worker
277*a67afe4dSAndroid Build Coastguard Worker else
278*a67afe4dSAndroid Build Coastguard Worker {
279*a67afe4dSAndroid Build Coastguard Worker png_bytep bp;
280*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
281*a67afe4dSAndroid Build Coastguard Worker png_uint_32 istop = channels * row_info->width;
282*a67afe4dSAndroid Build Coastguard Worker
283*a67afe4dSAndroid Build Coastguard Worker for (bp = row, i = 0; i < istop; i++)
284*a67afe4dSAndroid Build Coastguard Worker {
285*a67afe4dSAndroid Build Coastguard Worker unsigned int c = i%channels;
286*a67afe4dSAndroid Build Coastguard Worker int j;
287*a67afe4dSAndroid Build Coastguard Worker unsigned int value, v;
288*a67afe4dSAndroid Build Coastguard Worker
289*a67afe4dSAndroid Build Coastguard Worker v = png_get_uint_16(bp);
290*a67afe4dSAndroid Build Coastguard Worker value = 0;
291*a67afe4dSAndroid Build Coastguard Worker
292*a67afe4dSAndroid Build Coastguard Worker for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
293*a67afe4dSAndroid Build Coastguard Worker {
294*a67afe4dSAndroid Build Coastguard Worker if (j > 0)
295*a67afe4dSAndroid Build Coastguard Worker value |= v << j;
296*a67afe4dSAndroid Build Coastguard Worker
297*a67afe4dSAndroid Build Coastguard Worker else
298*a67afe4dSAndroid Build Coastguard Worker value |= v >> (-j);
299*a67afe4dSAndroid Build Coastguard Worker }
300*a67afe4dSAndroid Build Coastguard Worker *bp++ = (png_byte)((value >> 8) & 0xff);
301*a67afe4dSAndroid Build Coastguard Worker *bp++ = (png_byte)(value & 0xff);
302*a67afe4dSAndroid Build Coastguard Worker }
303*a67afe4dSAndroid Build Coastguard Worker }
304*a67afe4dSAndroid Build Coastguard Worker }
305*a67afe4dSAndroid Build Coastguard Worker }
306*a67afe4dSAndroid Build Coastguard Worker #endif
307*a67afe4dSAndroid Build Coastguard Worker
308*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
309*a67afe4dSAndroid Build Coastguard Worker static void
png_do_write_swap_alpha(png_row_infop row_info,png_bytep row)310*a67afe4dSAndroid Build Coastguard Worker png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
311*a67afe4dSAndroid Build Coastguard Worker {
312*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_write_swap_alpha");
313*a67afe4dSAndroid Build Coastguard Worker
314*a67afe4dSAndroid Build Coastguard Worker {
315*a67afe4dSAndroid Build Coastguard Worker if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
316*a67afe4dSAndroid Build Coastguard Worker {
317*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
318*a67afe4dSAndroid Build Coastguard Worker {
319*a67afe4dSAndroid Build Coastguard Worker /* This converts from ARGB to RGBA */
320*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
321*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
322*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
323*a67afe4dSAndroid Build Coastguard Worker
324*a67afe4dSAndroid Build Coastguard Worker for (i = 0, sp = dp = row; i < row_width; i++)
325*a67afe4dSAndroid Build Coastguard Worker {
326*a67afe4dSAndroid Build Coastguard Worker png_byte save = *(sp++);
327*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
328*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
329*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
330*a67afe4dSAndroid Build Coastguard Worker *(dp++) = save;
331*a67afe4dSAndroid Build Coastguard Worker }
332*a67afe4dSAndroid Build Coastguard Worker }
333*a67afe4dSAndroid Build Coastguard Worker
334*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_16BIT_SUPPORTED
335*a67afe4dSAndroid Build Coastguard Worker else
336*a67afe4dSAndroid Build Coastguard Worker {
337*a67afe4dSAndroid Build Coastguard Worker /* This converts from AARRGGBB to RRGGBBAA */
338*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
339*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
340*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
341*a67afe4dSAndroid Build Coastguard Worker
342*a67afe4dSAndroid Build Coastguard Worker for (i = 0, sp = dp = row; i < row_width; i++)
343*a67afe4dSAndroid Build Coastguard Worker {
344*a67afe4dSAndroid Build Coastguard Worker png_byte save[2];
345*a67afe4dSAndroid Build Coastguard Worker save[0] = *(sp++);
346*a67afe4dSAndroid Build Coastguard Worker save[1] = *(sp++);
347*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
348*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
349*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
350*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
351*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
352*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
353*a67afe4dSAndroid Build Coastguard Worker *(dp++) = save[0];
354*a67afe4dSAndroid Build Coastguard Worker *(dp++) = save[1];
355*a67afe4dSAndroid Build Coastguard Worker }
356*a67afe4dSAndroid Build Coastguard Worker }
357*a67afe4dSAndroid Build Coastguard Worker #endif /* WRITE_16BIT */
358*a67afe4dSAndroid Build Coastguard Worker }
359*a67afe4dSAndroid Build Coastguard Worker
360*a67afe4dSAndroid Build Coastguard Worker else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
361*a67afe4dSAndroid Build Coastguard Worker {
362*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
363*a67afe4dSAndroid Build Coastguard Worker {
364*a67afe4dSAndroid Build Coastguard Worker /* This converts from AG to GA */
365*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
366*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
367*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
368*a67afe4dSAndroid Build Coastguard Worker
369*a67afe4dSAndroid Build Coastguard Worker for (i = 0, sp = dp = row; i < row_width; i++)
370*a67afe4dSAndroid Build Coastguard Worker {
371*a67afe4dSAndroid Build Coastguard Worker png_byte save = *(sp++);
372*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
373*a67afe4dSAndroid Build Coastguard Worker *(dp++) = save;
374*a67afe4dSAndroid Build Coastguard Worker }
375*a67afe4dSAndroid Build Coastguard Worker }
376*a67afe4dSAndroid Build Coastguard Worker
377*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_16BIT_SUPPORTED
378*a67afe4dSAndroid Build Coastguard Worker else
379*a67afe4dSAndroid Build Coastguard Worker {
380*a67afe4dSAndroid Build Coastguard Worker /* This converts from AAGG to GGAA */
381*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
382*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
383*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
384*a67afe4dSAndroid Build Coastguard Worker
385*a67afe4dSAndroid Build Coastguard Worker for (i = 0, sp = dp = row; i < row_width; i++)
386*a67afe4dSAndroid Build Coastguard Worker {
387*a67afe4dSAndroid Build Coastguard Worker png_byte save[2];
388*a67afe4dSAndroid Build Coastguard Worker save[0] = *(sp++);
389*a67afe4dSAndroid Build Coastguard Worker save[1] = *(sp++);
390*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
391*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
392*a67afe4dSAndroid Build Coastguard Worker *(dp++) = save[0];
393*a67afe4dSAndroid Build Coastguard Worker *(dp++) = save[1];
394*a67afe4dSAndroid Build Coastguard Worker }
395*a67afe4dSAndroid Build Coastguard Worker }
396*a67afe4dSAndroid Build Coastguard Worker #endif /* WRITE_16BIT */
397*a67afe4dSAndroid Build Coastguard Worker }
398*a67afe4dSAndroid Build Coastguard Worker }
399*a67afe4dSAndroid Build Coastguard Worker }
400*a67afe4dSAndroid Build Coastguard Worker #endif
401*a67afe4dSAndroid Build Coastguard Worker
402*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
403*a67afe4dSAndroid Build Coastguard Worker static void
png_do_write_invert_alpha(png_row_infop row_info,png_bytep row)404*a67afe4dSAndroid Build Coastguard Worker png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
405*a67afe4dSAndroid Build Coastguard Worker {
406*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_write_invert_alpha");
407*a67afe4dSAndroid Build Coastguard Worker
408*a67afe4dSAndroid Build Coastguard Worker {
409*a67afe4dSAndroid Build Coastguard Worker if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
410*a67afe4dSAndroid Build Coastguard Worker {
411*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
412*a67afe4dSAndroid Build Coastguard Worker {
413*a67afe4dSAndroid Build Coastguard Worker /* This inverts the alpha channel in RGBA */
414*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
415*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
416*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
417*a67afe4dSAndroid Build Coastguard Worker
418*a67afe4dSAndroid Build Coastguard Worker for (i = 0, sp = dp = row; i < row_width; i++)
419*a67afe4dSAndroid Build Coastguard Worker {
420*a67afe4dSAndroid Build Coastguard Worker /* Does nothing
421*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
422*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
423*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
424*a67afe4dSAndroid Build Coastguard Worker */
425*a67afe4dSAndroid Build Coastguard Worker sp+=3; dp = sp;
426*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)(255 - *(sp++));
427*a67afe4dSAndroid Build Coastguard Worker }
428*a67afe4dSAndroid Build Coastguard Worker }
429*a67afe4dSAndroid Build Coastguard Worker
430*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_16BIT_SUPPORTED
431*a67afe4dSAndroid Build Coastguard Worker else
432*a67afe4dSAndroid Build Coastguard Worker {
433*a67afe4dSAndroid Build Coastguard Worker /* This inverts the alpha channel in RRGGBBAA */
434*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
435*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
436*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
437*a67afe4dSAndroid Build Coastguard Worker
438*a67afe4dSAndroid Build Coastguard Worker for (i = 0, sp = dp = row; i < row_width; i++)
439*a67afe4dSAndroid Build Coastguard Worker {
440*a67afe4dSAndroid Build Coastguard Worker /* Does nothing
441*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
442*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
443*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
444*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
445*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
446*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
447*a67afe4dSAndroid Build Coastguard Worker */
448*a67afe4dSAndroid Build Coastguard Worker sp+=6; dp = sp;
449*a67afe4dSAndroid Build Coastguard Worker *(dp++) = (png_byte)(255 - *(sp++));
450*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)(255 - *(sp++));
451*a67afe4dSAndroid Build Coastguard Worker }
452*a67afe4dSAndroid Build Coastguard Worker }
453*a67afe4dSAndroid Build Coastguard Worker #endif /* WRITE_16BIT */
454*a67afe4dSAndroid Build Coastguard Worker }
455*a67afe4dSAndroid Build Coastguard Worker
456*a67afe4dSAndroid Build Coastguard Worker else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
457*a67afe4dSAndroid Build Coastguard Worker {
458*a67afe4dSAndroid Build Coastguard Worker if (row_info->bit_depth == 8)
459*a67afe4dSAndroid Build Coastguard Worker {
460*a67afe4dSAndroid Build Coastguard Worker /* This inverts the alpha channel in GA */
461*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
462*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
463*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
464*a67afe4dSAndroid Build Coastguard Worker
465*a67afe4dSAndroid Build Coastguard Worker for (i = 0, sp = dp = row; i < row_width; i++)
466*a67afe4dSAndroid Build Coastguard Worker {
467*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
468*a67afe4dSAndroid Build Coastguard Worker *(dp++) = (png_byte)(255 - *(sp++));
469*a67afe4dSAndroid Build Coastguard Worker }
470*a67afe4dSAndroid Build Coastguard Worker }
471*a67afe4dSAndroid Build Coastguard Worker
472*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_16BIT_SUPPORTED
473*a67afe4dSAndroid Build Coastguard Worker else
474*a67afe4dSAndroid Build Coastguard Worker {
475*a67afe4dSAndroid Build Coastguard Worker /* This inverts the alpha channel in GGAA */
476*a67afe4dSAndroid Build Coastguard Worker png_bytep sp, dp;
477*a67afe4dSAndroid Build Coastguard Worker png_uint_32 i;
478*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row_width = row_info->width;
479*a67afe4dSAndroid Build Coastguard Worker
480*a67afe4dSAndroid Build Coastguard Worker for (i = 0, sp = dp = row; i < row_width; i++)
481*a67afe4dSAndroid Build Coastguard Worker {
482*a67afe4dSAndroid Build Coastguard Worker /* Does nothing
483*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
484*a67afe4dSAndroid Build Coastguard Worker *(dp++) = *(sp++);
485*a67afe4dSAndroid Build Coastguard Worker */
486*a67afe4dSAndroid Build Coastguard Worker sp+=2; dp = sp;
487*a67afe4dSAndroid Build Coastguard Worker *(dp++) = (png_byte)(255 - *(sp++));
488*a67afe4dSAndroid Build Coastguard Worker *dp = (png_byte)(255 - *(sp++));
489*a67afe4dSAndroid Build Coastguard Worker }
490*a67afe4dSAndroid Build Coastguard Worker }
491*a67afe4dSAndroid Build Coastguard Worker #endif /* WRITE_16BIT */
492*a67afe4dSAndroid Build Coastguard Worker }
493*a67afe4dSAndroid Build Coastguard Worker }
494*a67afe4dSAndroid Build Coastguard Worker }
495*a67afe4dSAndroid Build Coastguard Worker #endif
496*a67afe4dSAndroid Build Coastguard Worker
497*a67afe4dSAndroid Build Coastguard Worker /* Transform the data according to the user's wishes. The order of
498*a67afe4dSAndroid Build Coastguard Worker * transformations is significant.
499*a67afe4dSAndroid Build Coastguard Worker */
500*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_do_write_transformations(png_structrp png_ptr,png_row_infop row_info)501*a67afe4dSAndroid Build Coastguard Worker png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
502*a67afe4dSAndroid Build Coastguard Worker {
503*a67afe4dSAndroid Build Coastguard Worker png_debug(1, "in png_do_write_transformations");
504*a67afe4dSAndroid Build Coastguard Worker
505*a67afe4dSAndroid Build Coastguard Worker if (png_ptr == NULL)
506*a67afe4dSAndroid Build Coastguard Worker return;
507*a67afe4dSAndroid Build Coastguard Worker
508*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
509*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
510*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->write_user_transform_fn != NULL)
511*a67afe4dSAndroid Build Coastguard Worker (*(png_ptr->write_user_transform_fn)) /* User write transform
512*a67afe4dSAndroid Build Coastguard Worker function */
513*a67afe4dSAndroid Build Coastguard Worker (png_ptr, /* png_ptr */
514*a67afe4dSAndroid Build Coastguard Worker row_info, /* row_info: */
515*a67afe4dSAndroid Build Coastguard Worker /* png_uint_32 width; width of row */
516*a67afe4dSAndroid Build Coastguard Worker /* size_t rowbytes; number of bytes in row */
517*a67afe4dSAndroid Build Coastguard Worker /* png_byte color_type; color type of pixels */
518*a67afe4dSAndroid Build Coastguard Worker /* png_byte bit_depth; bit depth of samples */
519*a67afe4dSAndroid Build Coastguard Worker /* png_byte channels; number of channels (1-4) */
520*a67afe4dSAndroid Build Coastguard Worker /* png_byte pixel_depth; bits per pixel (depth*channels) */
521*a67afe4dSAndroid Build Coastguard Worker png_ptr->row_buf + 1); /* start of pixel data for row */
522*a67afe4dSAndroid Build Coastguard Worker #endif
523*a67afe4dSAndroid Build Coastguard Worker
524*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_FILLER_SUPPORTED
525*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_FILLER) != 0)
526*a67afe4dSAndroid Build Coastguard Worker png_do_strip_channel(row_info, png_ptr->row_buf + 1,
527*a67afe4dSAndroid Build Coastguard Worker !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
528*a67afe4dSAndroid Build Coastguard Worker #endif
529*a67afe4dSAndroid Build Coastguard Worker
530*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_PACKSWAP_SUPPORTED
531*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
532*a67afe4dSAndroid Build Coastguard Worker png_do_packswap(row_info, png_ptr->row_buf + 1);
533*a67afe4dSAndroid Build Coastguard Worker #endif
534*a67afe4dSAndroid Build Coastguard Worker
535*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_PACK_SUPPORTED
536*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_PACK) != 0)
537*a67afe4dSAndroid Build Coastguard Worker png_do_pack(row_info, png_ptr->row_buf + 1,
538*a67afe4dSAndroid Build Coastguard Worker (png_uint_32)png_ptr->bit_depth);
539*a67afe4dSAndroid Build Coastguard Worker #endif
540*a67afe4dSAndroid Build Coastguard Worker
541*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_SWAP_SUPPORTED
542*a67afe4dSAndroid Build Coastguard Worker # ifdef PNG_16BIT_SUPPORTED
543*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
544*a67afe4dSAndroid Build Coastguard Worker png_do_swap(row_info, png_ptr->row_buf + 1);
545*a67afe4dSAndroid Build Coastguard Worker # endif
546*a67afe4dSAndroid Build Coastguard Worker #endif
547*a67afe4dSAndroid Build Coastguard Worker
548*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_SHIFT_SUPPORTED
549*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_SHIFT) != 0)
550*a67afe4dSAndroid Build Coastguard Worker png_do_shift(row_info, png_ptr->row_buf + 1,
551*a67afe4dSAndroid Build Coastguard Worker &(png_ptr->shift));
552*a67afe4dSAndroid Build Coastguard Worker #endif
553*a67afe4dSAndroid Build Coastguard Worker
554*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
555*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
556*a67afe4dSAndroid Build Coastguard Worker png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
557*a67afe4dSAndroid Build Coastguard Worker #endif
558*a67afe4dSAndroid Build Coastguard Worker
559*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
560*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
561*a67afe4dSAndroid Build Coastguard Worker png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
562*a67afe4dSAndroid Build Coastguard Worker #endif
563*a67afe4dSAndroid Build Coastguard Worker
564*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_BGR_SUPPORTED
565*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_BGR) != 0)
566*a67afe4dSAndroid Build Coastguard Worker png_do_bgr(row_info, png_ptr->row_buf + 1);
567*a67afe4dSAndroid Build Coastguard Worker #endif
568*a67afe4dSAndroid Build Coastguard Worker
569*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WRITE_INVERT_SUPPORTED
570*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
571*a67afe4dSAndroid Build Coastguard Worker png_do_invert(row_info, png_ptr->row_buf + 1);
572*a67afe4dSAndroid Build Coastguard Worker #endif
573*a67afe4dSAndroid Build Coastguard Worker }
574*a67afe4dSAndroid Build Coastguard Worker #endif /* WRITE_TRANSFORMS */
575*a67afe4dSAndroid Build Coastguard Worker #endif /* WRITE */
576