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