• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
3  *
4  * Last changed in libpng 1.5.11 [June 14, 2012]
5  * Copyright (c) 1998-2012 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 */
20 void PNGAPI
png_set_bgr(png_structp png_ptr)21 png_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 */
34 void PNGAPI
png_set_swap(png_structp png_ptr)35 png_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 */
49 void PNGAPI
png_set_packing(png_structp png_ptr)50 png_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 */
67 void PNGAPI
png_set_packswap(png_structp png_ptr)68 png_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)
81 void PNGAPI
png_set_shift(png_structp png_ptr,png_const_color_8p true_bits)82 png_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)
96 int PNGAPI
png_set_interlace_handling(png_structp png_ptr)97 png_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  */
117 void PNGAPI
png_set_filler(png_structp png_ptr,png_uint_32 filler,int filler_loc)118 png_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 */
154 void PNGAPI
png_set_add_alpha(png_structp png_ptr,png_uint_32 filler,int filler_loc)155 png_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)
170 void PNGAPI
png_set_swap_alpha(png_structp png_ptr)171 png_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)
184 void PNGAPI
png_set_invert_alpha(png_structp png_ptr)185 png_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)
197 void PNGAPI
png_set_invert_mono(png_structp png_ptr)198 png_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 */
209 void /* PRIVATE */
png_do_invert(png_row_infop row_info,png_bytep row)210 png_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 */
266 void /* PRIVATE */
png_do_swap(png_row_infop row_info,png_bytep row)267 png_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)
289 static 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 
324 static 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 
359 static 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 */
395 void /* PRIVATE */
png_do_packswap(png_row_infop row_info,png_bytep row)396 png_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  */
435 void /* PRIVATE */
png_do_strip_channel(png_row_infop row_info,png_bytep row,int at_start)436 png_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 */
545 void /* PRIVATE */
png_do_bgr(png_row_infop row_info,png_bytep row)546 png_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_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
623     defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
624 /* Added at libpng-1.5.10 */
625 void /* PRIVATE */
png_do_check_palette_indexes(png_structp png_ptr,png_row_infop row_info)626 png_do_check_palette_indexes(png_structp png_ptr, png_row_infop row_info)
627 {
628    if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
629       png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
630    {
631       /* Calculations moved outside switch in an attempt to stop different
632        * compiler warnings.  'padding' is in *bits* within the last byte, it is
633        * an 'int' because pixel_depth becomes an 'int' in the expression below,
634        * and this calculation is used because it avoids warnings that other
635        * forms produced on either GCC or MSVC.
636        */
637       int padding = (-row_info->pixel_depth * row_info->width) & 7;
638       png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
639 
640       switch (row_info->bit_depth)
641       {
642          case 1:
643          {
644             /* in this case, all bytes must be 0 so we don't need
645              * to unpack the pixels except for the rightmost one.
646              */
647             for (; rp > png_ptr->row_buf; rp--)
648             {
649               if (*rp >> padding != 0)
650                  png_ptr->num_palette_max = 1;
651               padding = 0;
652             }
653 
654             break;
655          }
656 
657          case 2:
658          {
659             for (; rp > png_ptr->row_buf; rp--)
660             {
661               int i = ((*rp >> padding) & 0x03);
662 
663               if (i > png_ptr->num_palette_max)
664                  png_ptr->num_palette_max = i;
665 
666               i = (((*rp >> padding) >> 2) & 0x03);
667 
668               if (i > png_ptr->num_palette_max)
669                  png_ptr->num_palette_max = i;
670 
671               i = (((*rp >> padding) >> 4) & 0x03);
672 
673               if (i > png_ptr->num_palette_max)
674                  png_ptr->num_palette_max = i;
675 
676               i = (((*rp >> padding) >> 6) & 0x03);
677 
678               if (i > png_ptr->num_palette_max)
679                  png_ptr->num_palette_max = i;
680 
681               padding = 0;
682             }
683 
684             break;
685          }
686 
687          case 4:
688          {
689             for (; rp > png_ptr->row_buf; rp--)
690             {
691               int i = ((*rp >> padding) & 0x0f);
692 
693               if (i > png_ptr->num_palette_max)
694                  png_ptr->num_palette_max = i;
695 
696               i = (((*rp >> padding) >> 4) & 0x0f);
697 
698               if (i > png_ptr->num_palette_max)
699                  png_ptr->num_palette_max = i;
700 
701               padding = 0;
702             }
703 
704             break;
705          }
706 
707          case 8:
708          {
709             for (; rp > png_ptr->row_buf; rp--)
710             {
711                if (*rp > png_ptr->num_palette_max)
712                   png_ptr->num_palette_max = (int) *rp;
713             }
714 
715             break;
716          }
717 
718          default:
719             break;
720       }
721    }
722 }
723 #endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */
724 
725 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
726     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
727 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
728 void PNGAPI
png_set_user_transform_info(png_structp png_ptr,png_voidp user_transform_ptr,int user_transform_depth,int user_transform_channels)729 png_set_user_transform_info(png_structp png_ptr, png_voidp
730    user_transform_ptr, int user_transform_depth, int user_transform_channels)
731 {
732    png_debug(1, "in png_set_user_transform_info");
733 
734    if (png_ptr == NULL)
735       return;
736    png_ptr->user_transform_ptr = user_transform_ptr;
737    png_ptr->user_transform_depth = (png_byte)user_transform_depth;
738    png_ptr->user_transform_channels = (png_byte)user_transform_channels;
739 }
740 #endif
741 
742 /* This function returns a pointer to the user_transform_ptr associated with
743  * the user transform functions.  The application should free any memory
744  * associated with this pointer before png_write_destroy and png_read_destroy
745  * are called.
746  */
747 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
748 png_voidp PNGAPI
png_get_user_transform_ptr(png_const_structp png_ptr)749 png_get_user_transform_ptr(png_const_structp png_ptr)
750 {
751    if (png_ptr == NULL)
752       return (NULL);
753 
754    return ((png_voidp)png_ptr->user_transform_ptr);
755 }
756 #endif
757 
758 #ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
759 png_uint_32 PNGAPI
png_get_current_row_number(png_const_structp png_ptr)760 png_get_current_row_number(png_const_structp png_ptr)
761 {
762    /* See the comments in png.h - this is the sub-image row when reading and
763     * interlaced image.
764     */
765    if (png_ptr != NULL)
766       return png_ptr->row_number;
767 
768    return PNG_UINT_32_MAX; /* help the app not to fail silently */
769 }
770 
771 png_byte PNGAPI
png_get_current_pass_number(png_const_structp png_ptr)772 png_get_current_pass_number(png_const_structp png_ptr)
773 {
774    if (png_ptr != NULL)
775       return png_ptr->pass;
776    return 8; /* invalid */
777 }
778 #endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */
779 #endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
780           PNG_WRITE_USER_TRANSFORM_SUPPORTED */
781 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
782