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