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