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