• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
3  *
4  * Last changed in libpng 1.2.36 [May 14, 2009]
5  * Copyright (c) 1998-2009 Glenn Randers-Pehrson
6  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8  *
9  * This code is released under the libpng license.
10  * For conditions of distribution and use, see the disclaimer
11  * and license in png.h
12  */
13 
14 #define PNG_INTERNAL
15 #include "png.h"
16 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
17 
18 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
19 /* Turn on BGR-to-RGB mapping */
20 void PNGAPI
png_set_bgr(png_structp png_ptr)21 png_set_bgr(png_structp png_ptr)
22 {
23    png_debug(1, "in png_set_bgr");
24    if (png_ptr == NULL)
25       return;
26    png_ptr->transformations |= PNG_BGR;
27 }
28 #endif
29 
30 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
31 /* Turn on 16 bit byte swapping */
32 void PNGAPI
png_set_swap(png_structp png_ptr)33 png_set_swap(png_structp png_ptr)
34 {
35    png_debug(1, "in png_set_swap");
36    if (png_ptr == NULL)
37       return;
38    if (png_ptr->bit_depth == 16)
39       png_ptr->transformations |= PNG_SWAP_BYTES;
40 }
41 #endif
42 
43 #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
44 /* Turn on pixel packing */
45 void PNGAPI
png_set_packing(png_structp png_ptr)46 png_set_packing(png_structp png_ptr)
47 {
48    png_debug(1, "in png_set_packing");
49    if (png_ptr == NULL)
50       return;
51    if (png_ptr->bit_depth < 8)
52    {
53       png_ptr->transformations |= PNG_PACK;
54       png_ptr->usr_bit_depth = 8;
55    }
56 }
57 #endif
58 
59 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
60 /* Turn on packed pixel swapping */
61 void PNGAPI
png_set_packswap(png_structp png_ptr)62 png_set_packswap(png_structp png_ptr)
63 {
64    png_debug(1, "in png_set_packswap");
65    if (png_ptr == NULL)
66       return;
67    if (png_ptr->bit_depth < 8)
68       png_ptr->transformations |= PNG_PACKSWAP;
69 }
70 #endif
71 
72 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
73 void PNGAPI
png_set_shift(png_structp png_ptr,png_color_8p true_bits)74 png_set_shift(png_structp png_ptr, png_color_8p true_bits)
75 {
76    png_debug(1, "in png_set_shift");
77    if (png_ptr == NULL)
78       return;
79    png_ptr->transformations |= PNG_SHIFT;
80    png_ptr->shift = *true_bits;
81 }
82 #endif
83 
84 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
85     defined(PNG_WRITE_INTERLACING_SUPPORTED)
86 int PNGAPI
png_set_interlace_handling(png_structp png_ptr)87 png_set_interlace_handling(png_structp png_ptr)
88 {
89    png_debug(1, "in png_set_interlace handling");
90    if (png_ptr && png_ptr->interlaced)
91    {
92       png_ptr->transformations |= PNG_INTERLACE;
93       return (7);
94    }
95 
96    return (1);
97 }
98 #endif
99 
100 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
101 /* Add a filler byte on read, or remove a filler or alpha byte on write.
102  * The filler type has changed in v0.95 to allow future 2-byte fillers
103  * for 48-bit input data, as well as to avoid problems with some compilers
104  * that don't like bytes as parameters.
105  */
106 void PNGAPI
png_set_filler(png_structp png_ptr,png_uint_32 filler,int filler_loc)107 png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
108 {
109    png_debug(1, "in png_set_filler");
110    if (png_ptr == NULL)
111       return;
112    png_ptr->transformations |= PNG_FILLER;
113    png_ptr->filler = (png_byte)filler;
114    if (filler_loc == PNG_FILLER_AFTER)
115       png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
116    else
117       png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
118 
119    /* This should probably go in the "do_read_filler" routine.
120     * I attempted to do that in libpng-1.0.1a but that caused problems
121     * so I restored it in libpng-1.0.2a
122    */
123 
124    if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
125    {
126       png_ptr->usr_channels = 4;
127    }
128 
129    /* Also I added this in libpng-1.0.2a (what happens when we expand
130     * a less-than-8-bit grayscale to GA? */
131 
132    if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
133    {
134       png_ptr->usr_channels = 2;
135    }
136 }
137 
138 #if !defined(PNG_1_0_X)
139 /* Added to libpng-1.2.7 */
140 void PNGAPI
png_set_add_alpha(png_structp png_ptr,png_uint_32 filler,int filler_loc)141 png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
142 {
143    png_debug(1, "in png_set_add_alpha");
144    if (png_ptr == NULL)
145       return;
146    png_set_filler(png_ptr, filler, filler_loc);
147    png_ptr->transformations |= PNG_ADD_ALPHA;
148 }
149 #endif
150 
151 #endif
152 
153 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
154     defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
155 void PNGAPI
png_set_swap_alpha(png_structp png_ptr)156 png_set_swap_alpha(png_structp png_ptr)
157 {
158    png_debug(1, "in png_set_swap_alpha");
159    if (png_ptr == NULL)
160       return;
161    png_ptr->transformations |= PNG_SWAP_ALPHA;
162 }
163 #endif
164 
165 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
166     defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
167 void PNGAPI
png_set_invert_alpha(png_structp png_ptr)168 png_set_invert_alpha(png_structp png_ptr)
169 {
170    png_debug(1, "in png_set_invert_alpha");
171    if (png_ptr == NULL)
172       return;
173    png_ptr->transformations |= PNG_INVERT_ALPHA;
174 }
175 #endif
176 
177 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
178 void PNGAPI
png_set_invert_mono(png_structp png_ptr)179 png_set_invert_mono(png_structp png_ptr)
180 {
181    png_debug(1, "in png_set_invert_mono");
182    if (png_ptr == NULL)
183       return;
184    png_ptr->transformations |= PNG_INVERT_MONO;
185 }
186 
187 /* Invert monochrome grayscale data */
188 void /* PRIVATE */
png_do_invert(png_row_infop row_info,png_bytep row)189 png_do_invert(png_row_infop row_info, png_bytep row)
190 {
191    png_debug(1, "in png_do_invert");
192   /* This test removed from libpng version 1.0.13 and 1.2.0:
193    *   if (row_info->bit_depth == 1 &&
194    */
195 #if defined(PNG_USELESS_TESTS_SUPPORTED)
196    if (row == NULL || row_info == NULL)
197      return;
198 #endif
199    if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
200    {
201       png_bytep rp = row;
202       png_uint_32 i;
203       png_uint_32 istop = row_info->rowbytes;
204 
205       for (i = 0; i < istop; i++)
206       {
207          *rp = (png_byte)(~(*rp));
208          rp++;
209       }
210    }
211    else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
212       row_info->bit_depth == 8)
213    {
214       png_bytep rp = row;
215       png_uint_32 i;
216       png_uint_32 istop = row_info->rowbytes;
217 
218       for (i = 0; i < istop; i+=2)
219       {
220          *rp = (png_byte)(~(*rp));
221          rp+=2;
222       }
223    }
224    else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
225       row_info->bit_depth == 16)
226    {
227       png_bytep rp = row;
228       png_uint_32 i;
229       png_uint_32 istop = row_info->rowbytes;
230 
231       for (i = 0; i < istop; i+=4)
232       {
233          *rp = (png_byte)(~(*rp));
234          *(rp+1) = (png_byte)(~(*(rp+1)));
235          rp+=4;
236       }
237    }
238 }
239 #endif
240 
241 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
242 /* Swaps byte order on 16 bit depth images */
243 void /* PRIVATE */
png_do_swap(png_row_infop row_info,png_bytep row)244 png_do_swap(png_row_infop row_info, png_bytep row)
245 {
246    png_debug(1, "in png_do_swap");
247    if (
248 #if defined(PNG_USELESS_TESTS_SUPPORTED)
249        row != NULL && row_info != NULL &&
250 #endif
251        row_info->bit_depth == 16)
252    {
253       png_bytep rp = row;
254       png_uint_32 i;
255       png_uint_32 istop= row_info->width * row_info->channels;
256 
257       for (i = 0; i < istop; i++, rp += 2)
258       {
259          png_byte t = *rp;
260          *rp = *(rp + 1);
261          *(rp + 1) = t;
262       }
263    }
264 }
265 #endif
266 
267 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
268 static PNG_CONST png_byte onebppswaptable[256] = {
269    0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
270    0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
271    0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
272    0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
273    0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
274    0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
275    0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
276    0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
277    0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
278    0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
279    0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
280    0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
281    0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
282    0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
283    0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
284    0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
285    0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
286    0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
287    0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
288    0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
289    0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
290    0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
291    0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
292    0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
293    0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
294    0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
295    0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
296    0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
297    0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
298    0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
299    0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
300    0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
301 };
302 
303 static PNG_CONST png_byte twobppswaptable[256] = {
304    0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
305    0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
306    0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
307    0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
308    0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
309    0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
310    0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
311    0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
312    0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
313    0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
314    0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
315    0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
316    0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
317    0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
318    0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
319    0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
320    0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
321    0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
322    0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
323    0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
324    0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
325    0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
326    0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
327    0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
328    0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
329    0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
330    0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
331    0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
332    0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
333    0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
334    0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
335    0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
336 };
337 
338 static PNG_CONST png_byte fourbppswaptable[256] = {
339    0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
340    0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
341    0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
342    0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
343    0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
344    0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
345    0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
346    0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
347    0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
348    0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
349    0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
350    0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
351    0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
352    0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
353    0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
354    0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
355    0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
356    0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
357    0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
358    0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
359    0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
360    0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
361    0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
362    0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
363    0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
364    0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
365    0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
366    0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
367    0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
368    0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
369    0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
370    0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
371 };
372 
373 /* Swaps pixel packing order within bytes */
374 void /* PRIVATE */
png_do_packswap(png_row_infop row_info,png_bytep row)375 png_do_packswap(png_row_infop row_info, png_bytep row)
376 {
377    png_debug(1, "in png_do_packswap");
378    if (
379 #if defined(PNG_USELESS_TESTS_SUPPORTED)
380        row != NULL && row_info != NULL &&
381 #endif
382        row_info->bit_depth < 8)
383    {
384       png_bytep rp, end, table;
385 
386       end = row + row_info->rowbytes;
387 
388       if (row_info->bit_depth == 1)
389          table = (png_bytep)onebppswaptable;
390       else if (row_info->bit_depth == 2)
391          table = (png_bytep)twobppswaptable;
392       else if (row_info->bit_depth == 4)
393          table = (png_bytep)fourbppswaptable;
394       else
395          return;
396 
397       for (rp = row; rp < end; rp++)
398          *rp = table[*rp];
399    }
400 }
401 #endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
402 
403 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
404     defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
405 /* Remove filler or alpha byte(s) */
406 void /* PRIVATE */
png_do_strip_filler(png_row_infop row_info,png_bytep row,png_uint_32 flags)407 png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
408 {
409    png_debug(1, "in png_do_strip_filler");
410 #if defined(PNG_USELESS_TESTS_SUPPORTED)
411    if (row != NULL && row_info != NULL)
412 #endif
413    {
414       png_bytep sp=row;
415       png_bytep dp=row;
416       png_uint_32 row_width=row_info->width;
417       png_uint_32 i;
418 
419       if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
420           (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
421           (flags & PNG_FLAG_STRIP_ALPHA))) &&
422           row_info->channels == 4)
423       {
424          if (row_info->bit_depth == 8)
425          {
426             /* This converts from RGBX or RGBA to RGB */
427             if (flags & PNG_FLAG_FILLER_AFTER)
428             {
429                dp+=3; sp+=4;
430                for (i = 1; i < row_width; i++)
431                {
432                   *dp++ = *sp++;
433                   *dp++ = *sp++;
434                   *dp++ = *sp++;
435                   sp++;
436                }
437             }
438             /* This converts from XRGB or ARGB to RGB */
439             else
440             {
441                for (i = 0; i < row_width; i++)
442                {
443                   sp++;
444                   *dp++ = *sp++;
445                   *dp++ = *sp++;
446                   *dp++ = *sp++;
447                }
448             }
449             row_info->pixel_depth = 24;
450             row_info->rowbytes = row_width * 3;
451          }
452          else /* if (row_info->bit_depth == 16) */
453          {
454             if (flags & PNG_FLAG_FILLER_AFTER)
455             {
456                /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
457                sp += 8; dp += 6;
458                for (i = 1; i < row_width; i++)
459                {
460                   /* This could be (although png_memcpy is probably slower):
461                   png_memcpy(dp, sp, 6);
462                   sp += 8;
463                   dp += 6;
464                   */
465 
466                   *dp++ = *sp++;
467                   *dp++ = *sp++;
468                   *dp++ = *sp++;
469                   *dp++ = *sp++;
470                   *dp++ = *sp++;
471                   *dp++ = *sp++;
472                   sp += 2;
473                }
474             }
475             else
476             {
477                /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
478                for (i = 0; i < row_width; i++)
479                {
480                   /* This could be (although png_memcpy is probably slower):
481                   png_memcpy(dp, sp, 6);
482                   sp += 8;
483                   dp += 6;
484                   */
485 
486                   sp+=2;
487                   *dp++ = *sp++;
488                   *dp++ = *sp++;
489                   *dp++ = *sp++;
490                   *dp++ = *sp++;
491                   *dp++ = *sp++;
492                   *dp++ = *sp++;
493                }
494             }
495             row_info->pixel_depth = 48;
496             row_info->rowbytes = row_width * 6;
497          }
498          row_info->channels = 3;
499       }
500       else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
501          (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
502          (flags & PNG_FLAG_STRIP_ALPHA))) &&
503           row_info->channels == 2)
504       {
505          if (row_info->bit_depth == 8)
506          {
507             /* This converts from GX or GA to G */
508             if (flags & PNG_FLAG_FILLER_AFTER)
509             {
510                for (i = 0; i < row_width; i++)
511                {
512                   *dp++ = *sp++;
513                   sp++;
514                }
515             }
516             /* This converts from XG or AG to G */
517             else
518             {
519                for (i = 0; i < row_width; i++)
520                {
521                   sp++;
522                   *dp++ = *sp++;
523                }
524             }
525             row_info->pixel_depth = 8;
526             row_info->rowbytes = row_width;
527          }
528          else /* if (row_info->bit_depth == 16) */
529          {
530             if (flags & PNG_FLAG_FILLER_AFTER)
531             {
532                /* This converts from GGXX or GGAA to GG */
533                sp += 4; dp += 2;
534                for (i = 1; i < row_width; i++)
535                {
536                   *dp++ = *sp++;
537                   *dp++ = *sp++;
538                   sp += 2;
539                }
540             }
541             else
542             {
543                /* This converts from XXGG or AAGG to GG */
544                for (i = 0; i < row_width; i++)
545                {
546                   sp += 2;
547                   *dp++ = *sp++;
548                   *dp++ = *sp++;
549                }
550             }
551             row_info->pixel_depth = 16;
552             row_info->rowbytes = row_width * 2;
553          }
554          row_info->channels = 1;
555       }
556       if (flags & PNG_FLAG_STRIP_ALPHA)
557         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
558    }
559 }
560 #endif
561 
562 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
563 /* Swaps red and blue bytes within a pixel */
564 void /* PRIVATE */
png_do_bgr(png_row_infop row_info,png_bytep row)565 png_do_bgr(png_row_infop row_info, png_bytep row)
566 {
567    png_debug(1, "in png_do_bgr");
568    if (
569 #if defined(PNG_USELESS_TESTS_SUPPORTED)
570        row != NULL && row_info != NULL &&
571 #endif
572        (row_info->color_type & PNG_COLOR_MASK_COLOR))
573    {
574       png_uint_32 row_width = row_info->width;
575       if (row_info->bit_depth == 8)
576       {
577          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
578          {
579             png_bytep rp;
580             png_uint_32 i;
581 
582             for (i = 0, rp = row; i < row_width; i++, rp += 3)
583             {
584                png_byte save = *rp;
585                *rp = *(rp + 2);
586                *(rp + 2) = save;
587             }
588          }
589          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
590          {
591             png_bytep rp;
592             png_uint_32 i;
593 
594             for (i = 0, rp = row; i < row_width; i++, rp += 4)
595             {
596                png_byte save = *rp;
597                *rp = *(rp + 2);
598                *(rp + 2) = save;
599             }
600          }
601       }
602       else if (row_info->bit_depth == 16)
603       {
604          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
605          {
606             png_bytep rp;
607             png_uint_32 i;
608 
609             for (i = 0, rp = row; i < row_width; i++, rp += 6)
610             {
611                png_byte save = *rp;
612                *rp = *(rp + 4);
613                *(rp + 4) = save;
614                save = *(rp + 1);
615                *(rp + 1) = *(rp + 5);
616                *(rp + 5) = save;
617             }
618          }
619          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
620          {
621             png_bytep rp;
622             png_uint_32 i;
623 
624             for (i = 0, rp = row; i < row_width; i++, rp += 8)
625             {
626                png_byte save = *rp;
627                *rp = *(rp + 4);
628                *(rp + 4) = save;
629                save = *(rp + 1);
630                *(rp + 1) = *(rp + 5);
631                *(rp + 5) = save;
632             }
633          }
634       }
635    }
636 }
637 #endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
638 
639 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
640     defined(PNG_LEGACY_SUPPORTED) || \
641     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
642 void PNGAPI
png_set_user_transform_info(png_structp png_ptr,png_voidp user_transform_ptr,int user_transform_depth,int user_transform_channels)643 png_set_user_transform_info(png_structp png_ptr, png_voidp
644    user_transform_ptr, int user_transform_depth, int user_transform_channels)
645 {
646    png_debug(1, "in png_set_user_transform_info");
647    if (png_ptr == NULL)
648       return;
649 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
650    png_ptr->user_transform_ptr = user_transform_ptr;
651    png_ptr->user_transform_depth = (png_byte)user_transform_depth;
652    png_ptr->user_transform_channels = (png_byte)user_transform_channels;
653 #else
654    if (user_transform_ptr || user_transform_depth || user_transform_channels)
655       png_warning(png_ptr,
656         "This version of libpng does not support user transform info");
657 #endif
658 }
659 #endif
660 
661 /* This function returns a pointer to the user_transform_ptr associated with
662  * the user transform functions.  The application should free any memory
663  * associated with this pointer before png_write_destroy and png_read_destroy
664  * are called.
665  */
666 png_voidp PNGAPI
png_get_user_transform_ptr(png_structp png_ptr)667 png_get_user_transform_ptr(png_structp png_ptr)
668 {
669    if (png_ptr == NULL)
670       return (NULL);
671 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
672    return ((png_voidp)png_ptr->user_transform_ptr);
673 #else
674    return (NULL);
675 #endif
676 }
677 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
678