]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libpng/lib/dist/pngtrans.c
8f8bc5d9e74b8891b9cbc7aa367f6f3d1e6c4285
[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.6.2 [April 25, 2013]
5  * Copyright (c) 1998-2013 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_structrp 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_structrp 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_structrp 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_structrp 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_structrp 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_structrp 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_structrp 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    /* In libpng 1.6 it is possible to determine whether this is a read or write
126     * operation and therefore to do more checking here for a valid call.
127     */
128    if (png_ptr->mode & PNG_IS_READ_STRUCT)
129    {
130 #     ifdef PNG_READ_FILLER_SUPPORTED
131          /* On read png_set_filler is always valid, regardless of the base PNG
132           * format, because other transformations can give a format where the
133           * filler code can execute (basically an 8 or 16-bit component RGB or G
134           * format.)
135           *
136           * NOTE: usr_channels is not used by the read code!  (This has led to
137           * confusion in the past.)  The filler is only used in the read code.
138           */
139          png_ptr->filler = (png_uint_16)filler;
140 #     else
141          png_app_error(png_ptr, "png_set_filler not supported on read");
142          PNG_UNUSED(filler) /* not used in the write case */
143          return;
144 #     endif
145    }
146
147    else /* write */
148    {
149 #     ifdef PNG_WRITE_FILLER_SUPPORTED
150          /* On write the usr_channels parameter must be set correctly at the
151           * start to record the number of channels in the app-supplied data.
152           */
153          switch (png_ptr->color_type)
154          {
155             case PNG_COLOR_TYPE_RGB:
156                png_ptr->usr_channels = 4;
157                break;
158
159             case PNG_COLOR_TYPE_GRAY:
160                if (png_ptr->bit_depth >= 8)
161                {
162                   png_ptr->usr_channels = 2;
163                   break;
164                }
165
166                else
167                {
168                   /* There simply isn't any code in libpng to strip out bits
169                    * from bytes when the components are less than a byte in
170                    * size!
171                    */
172                   png_app_error(png_ptr,
173                      "png_set_filler is invalid for low bit depth gray output");
174                   return;
175                }
176
177             default:
178                png_app_error(png_ptr,
179                   "png_set_filler: inappropriate color type");
180                return;
181          }
182 #     else
183          png_app_error(png_ptr, "png_set_filler not supported on write");
184          return;
185 #     endif
186    }
187
188    /* Here on success - libpng supports the operation, set the transformation
189     * and the flag to say where the filler channel is.
190     */
191    png_ptr->transformations |= PNG_FILLER;
192
193    if (filler_loc == PNG_FILLER_AFTER)
194       png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
195
196    else
197       png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
198 }
199
200 /* Added to libpng-1.2.7 */
201 void PNGAPI
202 png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
203 {
204    png_debug(1, "in png_set_add_alpha");
205
206    if (png_ptr == NULL)
207       return;
208
209    png_set_filler(png_ptr, filler, filler_loc);
210    /* The above may fail to do anything. */
211    if (png_ptr->transformations & PNG_FILLER)
212       png_ptr->transformations |= PNG_ADD_ALPHA;
213 }
214
215 #endif
216
217 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
218     defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
219 void PNGAPI
220 png_set_swap_alpha(png_structrp png_ptr)
221 {
222    png_debug(1, "in png_set_swap_alpha");
223
224    if (png_ptr == NULL)
225       return;
226
227    png_ptr->transformations |= PNG_SWAP_ALPHA;
228 }
229 #endif
230
231 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
232     defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
233 void PNGAPI
234 png_set_invert_alpha(png_structrp png_ptr)
235 {
236    png_debug(1, "in png_set_invert_alpha");
237
238    if (png_ptr == NULL)
239       return;
240
241    png_ptr->transformations |= PNG_INVERT_ALPHA;
242 }
243 #endif
244
245 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
246 void PNGAPI
247 png_set_invert_mono(png_structrp png_ptr)
248 {
249    png_debug(1, "in png_set_invert_mono");
250
251    if (png_ptr == NULL)
252       return;
253
254    png_ptr->transformations |= PNG_INVERT_MONO;
255 }
256
257 /* Invert monochrome grayscale data */
258 void /* PRIVATE */
259 png_do_invert(png_row_infop row_info, png_bytep row)
260 {
261    png_debug(1, "in png_do_invert");
262
263   /* This test removed from libpng version 1.0.13 and 1.2.0:
264    *   if (row_info->bit_depth == 1 &&
265    */
266    if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
267    {
268       png_bytep rp = row;
269       png_size_t i;
270       png_size_t istop = row_info->rowbytes;
271
272       for (i = 0; i < istop; i++)
273       {
274          *rp = (png_byte)(~(*rp));
275          rp++;
276       }
277    }
278
279    else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
280       row_info->bit_depth == 8)
281    {
282       png_bytep rp = row;
283       png_size_t i;
284       png_size_t istop = row_info->rowbytes;
285
286       for (i = 0; i < istop; i += 2)
287       {
288          *rp = (png_byte)(~(*rp));
289          rp += 2;
290       }
291    }
292
293 #ifdef PNG_16BIT_SUPPORTED
294    else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
295       row_info->bit_depth == 16)
296    {
297       png_bytep rp = row;
298       png_size_t i;
299       png_size_t istop = row_info->rowbytes;
300
301       for (i = 0; i < istop; i += 4)
302       {
303          *rp = (png_byte)(~(*rp));
304          *(rp + 1) = (png_byte)(~(*(rp + 1)));
305          rp += 4;
306       }
307    }
308 #endif
309 }
310 #endif
311
312 #ifdef PNG_16BIT_SUPPORTED
313 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
314 /* Swaps byte order on 16 bit depth images */
315 void /* PRIVATE */
316 png_do_swap(png_row_infop row_info, png_bytep row)
317 {
318    png_debug(1, "in png_do_swap");
319
320    if (row_info->bit_depth == 16)
321    {
322       png_bytep rp = row;
323       png_uint_32 i;
324       png_uint_32 istop= row_info->width * row_info->channels;
325
326       for (i = 0; i < istop; i++, rp += 2)
327       {
328          png_byte t = *rp;
329          *rp = *(rp + 1);
330          *(rp + 1) = t;
331       }
332    }
333 }
334 #endif
335 #endif
336
337 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
338 static PNG_CONST png_byte onebppswaptable[256] = {
339    0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
340    0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
341    0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
342    0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
343    0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
344    0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
345    0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
346    0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
347    0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
348    0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
349    0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
350    0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
351    0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
352    0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
353    0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
354    0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
355    0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
356    0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
357    0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
358    0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
359    0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
360    0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
361    0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
362    0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
363    0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
364    0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
365    0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
366    0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
367    0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
368    0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
369    0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
370    0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
371 };
372
373 static PNG_CONST png_byte twobppswaptable[256] = {
374    0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
375    0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
376    0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
377    0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
378    0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
379    0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
380    0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
381    0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
382    0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
383    0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
384    0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
385    0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
386    0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
387    0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
388    0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
389    0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
390    0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
391    0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
392    0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
393    0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
394    0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
395    0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
396    0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
397    0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
398    0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
399    0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
400    0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
401    0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
402    0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
403    0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
404    0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
405    0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
406 };
407
408 static PNG_CONST png_byte fourbppswaptable[256] = {
409    0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
410    0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
411    0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
412    0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
413    0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
414    0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
415    0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
416    0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
417    0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
418    0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
419    0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
420    0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
421    0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
422    0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
423    0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
424    0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
425    0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
426    0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
427    0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
428    0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
429    0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
430    0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
431    0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
432    0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
433    0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
434    0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
435    0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
436    0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
437    0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
438    0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
439    0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
440    0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
441 };
442
443 /* Swaps pixel packing order within bytes */
444 void /* PRIVATE */
445 png_do_packswap(png_row_infop row_info, png_bytep row)
446 {
447    png_debug(1, "in png_do_packswap");
448
449    if (row_info->bit_depth < 8)
450    {
451       png_bytep rp;
452       png_const_bytep end, table;
453
454       end = row + row_info->rowbytes;
455
456       if (row_info->bit_depth == 1)
457          table = onebppswaptable;
458
459       else if (row_info->bit_depth == 2)
460          table = twobppswaptable;
461
462       else if (row_info->bit_depth == 4)
463          table = fourbppswaptable;
464
465       else
466          return;
467
468       for (rp = row; rp < end; rp++)
469          *rp = table[*rp];
470    }
471 }
472 #endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
473
474 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
475     defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
476 /* Remove a channel - this used to be 'png_do_strip_filler' but it used a
477  * somewhat weird combination of flags to determine what to do.  All the calls
478  * to png_do_strip_filler are changed in 1.5.2 to call this instead with the
479  * correct arguments.
480  *
481  * The routine isn't general - the channel must be the channel at the start or
482  * end (not in the middle) of each pixel.
483  */
484 void /* PRIVATE */
485 png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
486 {
487    png_bytep sp = row; /* source pointer */
488    png_bytep dp = row; /* destination pointer */
489    png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
490
491    /* At the start sp will point to the first byte to copy and dp to where
492     * it is copied to.  ep always points just beyond the end of the row, so
493     * the loop simply copies (channels-1) channels until sp reaches ep.
494     *
495     * at_start:        0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
496     *            nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
497     */
498
499    /* GA, GX, XG cases */
500    if (row_info->channels == 2)
501    {
502       if (row_info->bit_depth == 8)
503       {
504          if (at_start) /* Skip initial filler */
505             ++sp;
506          else          /* Skip initial channel and, for sp, the filler */
507             sp += 2, ++dp;
508
509          /* For a 1 pixel wide image there is nothing to do */
510          while (sp < ep)
511             *dp++ = *sp, sp += 2;
512
513          row_info->pixel_depth = 8;
514       }
515
516       else if (row_info->bit_depth == 16)
517       {
518          if (at_start) /* Skip initial filler */
519             sp += 2;
520          else          /* Skip initial channel and, for sp, the filler */
521             sp += 4, dp += 2;
522
523          while (sp < ep)
524             *dp++ = *sp++, *dp++ = *sp, sp += 3;
525
526          row_info->pixel_depth = 16;
527       }
528
529       else
530          return; /* bad bit depth */
531
532       row_info->channels = 1;
533
534       /* Finally fix the color type if it records an alpha channel */
535       if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
536          row_info->color_type = PNG_COLOR_TYPE_GRAY;
537    }
538
539    /* RGBA, RGBX, XRGB cases */
540    else if (row_info->channels == 4)
541    {
542       if (row_info->bit_depth == 8)
543       {
544          if (at_start) /* Skip initial filler */
545             ++sp;
546          else          /* Skip initial channels and, for sp, the filler */
547             sp += 4, dp += 3;
548
549          /* Note that the loop adds 3 to dp and 4 to sp each time. */
550          while (sp < ep)
551             *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
552
553          row_info->pixel_depth = 24;
554       }
555
556       else if (row_info->bit_depth == 16)
557       {
558          if (at_start) /* Skip initial filler */
559             sp += 2;
560          else          /* Skip initial channels and, for sp, the filler */
561             sp += 8, dp += 6;
562
563          while (sp < ep)
564          {
565             /* Copy 6 bytes, skip 2 */
566             *dp++ = *sp++, *dp++ = *sp++;
567             *dp++ = *sp++, *dp++ = *sp++;
568             *dp++ = *sp++, *dp++ = *sp, sp += 3;
569          }
570
571          row_info->pixel_depth = 48;
572       }
573
574       else
575          return; /* bad bit depth */
576
577       row_info->channels = 3;
578
579       /* Finally fix the color type if it records an alpha channel */
580       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
581          row_info->color_type = PNG_COLOR_TYPE_RGB;
582    }
583
584    else
585       return; /* The filler channel has gone already */
586
587    /* Fix the rowbytes value. */
588    row_info->rowbytes = dp-row;
589 }
590 #endif
591
592 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
593 /* Swaps red and blue bytes within a pixel */
594 void /* PRIVATE */
595 png_do_bgr(png_row_infop row_info, png_bytep row)
596 {
597    png_debug(1, "in png_do_bgr");
598
599    if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
600    {
601       png_uint_32 row_width = row_info->width;
602       if (row_info->bit_depth == 8)
603       {
604          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
605          {
606             png_bytep rp;
607             png_uint_32 i;
608
609             for (i = 0, rp = row; i < row_width; i++, rp += 3)
610             {
611                png_byte save = *rp;
612                *rp = *(rp + 2);
613                *(rp + 2) = save;
614             }
615          }
616
617          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
618          {
619             png_bytep rp;
620             png_uint_32 i;
621
622             for (i = 0, rp = row; i < row_width; i++, rp += 4)
623             {
624                png_byte save = *rp;
625                *rp = *(rp + 2);
626                *(rp + 2) = save;
627             }
628          }
629       }
630
631 #ifdef PNG_16BIT_SUPPORTED
632       else if (row_info->bit_depth == 16)
633       {
634          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
635          {
636             png_bytep rp;
637             png_uint_32 i;
638
639             for (i = 0, rp = row; i < row_width; i++, rp += 6)
640             {
641                png_byte save = *rp;
642                *rp = *(rp + 4);
643                *(rp + 4) = save;
644                save = *(rp + 1);
645                *(rp + 1) = *(rp + 5);
646                *(rp + 5) = save;
647             }
648          }
649
650          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
651          {
652             png_bytep rp;
653             png_uint_32 i;
654
655             for (i = 0, rp = row; i < row_width; i++, rp += 8)
656             {
657                png_byte save = *rp;
658                *rp = *(rp + 4);
659                *(rp + 4) = save;
660                save = *(rp + 1);
661                *(rp + 1) = *(rp + 5);
662                *(rp + 5) = save;
663             }
664          }
665       }
666 #endif
667    }
668 }
669 #endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
670
671 #if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
672     defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
673 /* Added at libpng-1.5.10 */
674 void /* PRIVATE */
675 png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
676 {
677    if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
678       png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
679    {
680       /* Calculations moved outside switch in an attempt to stop different
681        * compiler warnings.  'padding' is in *bits* within the last byte, it is
682        * an 'int' because pixel_depth becomes an 'int' in the expression below,
683        * and this calculation is used because it avoids warnings that other
684        * forms produced on either GCC or MSVC.
685        */
686       int padding = (-row_info->pixel_depth * row_info->width) & 7;
687       png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
688
689       switch (row_info->bit_depth)
690       {
691          case 1:
692          {
693             /* in this case, all bytes must be 0 so we don't need
694              * to unpack the pixels except for the rightmost one.
695              */
696             for (; rp > png_ptr->row_buf; rp--)
697             {
698               if (*rp >> padding != 0)
699                  png_ptr->num_palette_max = 1;
700               padding = 0;
701             }
702
703             break;
704          }
705
706          case 2:
707          {
708             for (; rp > png_ptr->row_buf; rp--)
709             {
710               int i = ((*rp >> padding) & 0x03);
711
712               if (i > png_ptr->num_palette_max)
713                  png_ptr->num_palette_max = i;
714
715               i = (((*rp >> padding) >> 2) & 0x03);
716
717               if (i > png_ptr->num_palette_max)
718                  png_ptr->num_palette_max = i;
719
720               i = (((*rp >> padding) >> 4) & 0x03);
721
722               if (i > png_ptr->num_palette_max)
723                  png_ptr->num_palette_max = i;
724
725               i = (((*rp >> padding) >> 6) & 0x03);
726
727               if (i > png_ptr->num_palette_max)
728                  png_ptr->num_palette_max = i;
729
730               padding = 0;
731             }
732
733             break;
734          }
735
736          case 4:
737          {
738             for (; rp > png_ptr->row_buf; rp--)
739             {
740               int i = ((*rp >> padding) & 0x0f);
741
742               if (i > png_ptr->num_palette_max)
743                  png_ptr->num_palette_max = i;
744
745               i = (((*rp >> padding) >> 4) & 0x0f);
746
747               if (i > png_ptr->num_palette_max)
748                  png_ptr->num_palette_max = i;
749
750               padding = 0;
751             }
752
753             break;
754          }
755
756          case 8:
757          {
758             for (; rp > png_ptr->row_buf; rp--)
759             {
760                if (*rp > png_ptr->num_palette_max)
761                   png_ptr->num_palette_max = (int) *rp;
762             }
763
764             break;
765          }
766
767          default:
768             break;
769       }
770    }
771 }
772 #endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */
773
774 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
775     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
776 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
777 void PNGAPI
778 png_set_user_transform_info(png_structrp png_ptr, png_voidp
779    user_transform_ptr, int user_transform_depth, int user_transform_channels)
780 {
781    png_debug(1, "in png_set_user_transform_info");
782
783    if (png_ptr == NULL)
784       return;
785
786 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
787    if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
788       (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
789    {
790       png_app_error(png_ptr,
791             "info change after png_start_read_image or png_read_update_info");
792       return;
793    }
794 #endif
795
796    png_ptr->user_transform_ptr = user_transform_ptr;
797    png_ptr->user_transform_depth = (png_byte)user_transform_depth;
798    png_ptr->user_transform_channels = (png_byte)user_transform_channels;
799 }
800 #endif
801
802 /* This function returns a pointer to the user_transform_ptr associated with
803  * the user transform functions.  The application should free any memory
804  * associated with this pointer before png_write_destroy and png_read_destroy
805  * are called.
806  */
807 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
808 png_voidp PNGAPI
809 png_get_user_transform_ptr(png_const_structrp png_ptr)
810 {
811    if (png_ptr == NULL)
812       return (NULL);
813
814    return png_ptr->user_transform_ptr;
815 }
816 #endif
817
818 #ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
819 png_uint_32 PNGAPI
820 png_get_current_row_number(png_const_structrp png_ptr)
821 {
822    /* See the comments in png.h - this is the sub-image row when reading and
823     * interlaced image.
824     */
825    if (png_ptr != NULL)
826       return png_ptr->row_number;
827
828    return PNG_UINT_32_MAX; /* help the app not to fail silently */
829 }
830
831 png_byte PNGAPI
832 png_get_current_pass_number(png_const_structrp png_ptr)
833 {
834    if (png_ptr != NULL)
835       return png_ptr->pass;
836    return 8; /* invalid */
837 }
838 #endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */
839 #endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
840           PNG_WRITE_USER_TRANSFORM_SUPPORTED */
841 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */