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