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