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