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