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