PageRenderTime 62ms CodeModel.GetById 20ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/LibPNG/pngtrans.c

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