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