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