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