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 */
21void PNGAPI
22png_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 */
34void PNGAPI
35png_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 */
48void PNGAPI
49png_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 */
65void PNGAPI
66png_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)
78void PNGAPI
79png_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)
92int PNGAPI
93png_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 */
113void PNGAPI
114png_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 */
147void PNGAPI
148png_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)
162void PNGAPI
163png_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)
175void PNGAPI
176png_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)
187void PNGAPI
188png_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 */
198void /* PRIVATE */
199png_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 */
250void /* PRIVATE */
251png_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)
273static 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
308static 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
343static 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 */
379void /* PRIVATE */
380png_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) */
409void /* PRIVATE */
410png_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 */
565void /* PRIVATE */
566png_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)
640void PNGAPI
641png_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 */
664png_voidp PNGAPI
665png_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 */
678