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