Bringing libpng-1.5.10 into the main branch
[AROS.git] / workbench / libs / png / pngtrans.c
blobfef12f1851bb0fd632432d72bd40dc716cb812df
2 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
4 * Last changed in libpng 1.5.10 [March 8, 2012]
5 * Copyright (c) 1998-2012 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.)
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
14 #include "pngpriv.h"
16 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
18 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
19 /* Turn on BGR-to-RGB mapping */
20 void PNGAPI
21 png_set_bgr(png_structp png_ptr)
23 png_debug(1, "in png_set_bgr");
25 if (png_ptr == NULL)
26 return;
28 png_ptr->transformations |= PNG_BGR;
30 #endif
32 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
33 /* Turn on 16 bit byte swapping */
34 void PNGAPI
35 png_set_swap(png_structp png_ptr)
37 png_debug(1, "in png_set_swap");
39 if (png_ptr == NULL)
40 return;
42 if (png_ptr->bit_depth == 16)
43 png_ptr->transformations |= PNG_SWAP_BYTES;
45 #endif
47 #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
48 /* Turn on pixel packing */
49 void PNGAPI
50 png_set_packing(png_structp png_ptr)
52 png_debug(1, "in png_set_packing");
54 if (png_ptr == NULL)
55 return;
57 if (png_ptr->bit_depth < 8)
59 png_ptr->transformations |= PNG_PACK;
60 png_ptr->usr_bit_depth = 8;
63 #endif
65 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
66 /* Turn on packed pixel swapping */
67 void PNGAPI
68 png_set_packswap(png_structp png_ptr)
70 png_debug(1, "in png_set_packswap");
72 if (png_ptr == NULL)
73 return;
75 if (png_ptr->bit_depth < 8)
76 png_ptr->transformations |= PNG_PACKSWAP;
78 #endif
80 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
81 void PNGAPI
82 png_set_shift(png_structp png_ptr, png_const_color_8p true_bits)
84 png_debug(1, "in png_set_shift");
86 if (png_ptr == NULL)
87 return;
89 png_ptr->transformations |= PNG_SHIFT;
90 png_ptr->shift = *true_bits;
92 #endif
94 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
95 defined(PNG_WRITE_INTERLACING_SUPPORTED)
96 int PNGAPI
97 png_set_interlace_handling(png_structp png_ptr)
99 png_debug(1, "in png_set_interlace handling");
101 if (png_ptr && png_ptr->interlaced)
103 png_ptr->transformations |= PNG_INTERLACE;
104 return (7);
107 return (1);
109 #endif
111 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
112 /* Add a filler byte on read, or remove a filler or alpha byte on write.
113 * The filler type has changed in v0.95 to allow future 2-byte fillers
114 * for 48-bit input data, as well as to avoid problems with some compilers
115 * that don't like bytes as parameters.
117 void PNGAPI
118 png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
120 png_debug(1, "in png_set_filler");
122 if (png_ptr == NULL)
123 return;
125 png_ptr->transformations |= PNG_FILLER;
126 png_ptr->filler = (png_uint_16)filler;
128 if (filler_loc == PNG_FILLER_AFTER)
129 png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
131 else
132 png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
134 /* This should probably go in the "do_read_filler" routine.
135 * I attempted to do that in libpng-1.0.1a but that caused problems
136 * so I restored it in libpng-1.0.2a
139 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
141 png_ptr->usr_channels = 4;
144 /* Also I added this in libpng-1.0.2a (what happens when we expand
145 * a less-than-8-bit grayscale to GA?) */
147 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
149 png_ptr->usr_channels = 2;
153 /* Added to libpng-1.2.7 */
154 void PNGAPI
155 png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
157 png_debug(1, "in png_set_add_alpha");
159 if (png_ptr == NULL)
160 return;
162 png_set_filler(png_ptr, filler, filler_loc);
163 png_ptr->transformations |= PNG_ADD_ALPHA;
166 #endif
168 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
169 defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
170 void PNGAPI
171 png_set_swap_alpha(png_structp png_ptr)
173 png_debug(1, "in png_set_swap_alpha");
175 if (png_ptr == NULL)
176 return;
178 png_ptr->transformations |= PNG_SWAP_ALPHA;
180 #endif
182 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
183 defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
184 void PNGAPI
185 png_set_invert_alpha(png_structp png_ptr)
187 png_debug(1, "in png_set_invert_alpha");
189 if (png_ptr == NULL)
190 return;
192 png_ptr->transformations |= PNG_INVERT_ALPHA;
194 #endif
196 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
197 void PNGAPI
198 png_set_invert_mono(png_structp png_ptr)
200 png_debug(1, "in png_set_invert_mono");
202 if (png_ptr == NULL)
203 return;
205 png_ptr->transformations |= PNG_INVERT_MONO;
208 /* Invert monochrome grayscale data */
209 void /* PRIVATE */
210 png_do_invert(png_row_infop row_info, png_bytep row)
212 png_debug(1, "in png_do_invert");
214 /* This test removed from libpng version 1.0.13 and 1.2.0:
215 * if (row_info->bit_depth == 1 &&
217 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
219 png_bytep rp = row;
220 png_size_t i;
221 png_size_t istop = row_info->rowbytes;
223 for (i = 0; i < istop; i++)
225 *rp = (png_byte)(~(*rp));
226 rp++;
230 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
231 row_info->bit_depth == 8)
233 png_bytep rp = row;
234 png_size_t i;
235 png_size_t istop = row_info->rowbytes;
237 for (i = 0; i < istop; i += 2)
239 *rp = (png_byte)(~(*rp));
240 rp += 2;
244 #ifdef PNG_16BIT_SUPPORTED
245 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
246 row_info->bit_depth == 16)
248 png_bytep rp = row;
249 png_size_t i;
250 png_size_t istop = row_info->rowbytes;
252 for (i = 0; i < istop; i += 4)
254 *rp = (png_byte)(~(*rp));
255 *(rp + 1) = (png_byte)(~(*(rp + 1)));
256 rp += 4;
259 #endif
261 #endif
263 #ifdef PNG_16BIT_SUPPORTED
264 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
265 /* Swaps byte order on 16 bit depth images */
266 void /* PRIVATE */
267 png_do_swap(png_row_infop row_info, png_bytep row)
269 png_debug(1, "in png_do_swap");
271 if (row_info->bit_depth == 16)
273 png_bytep rp = row;
274 png_uint_32 i;
275 png_uint_32 istop= row_info->width * row_info->channels;
277 for (i = 0; i < istop; i++, rp += 2)
279 png_byte t = *rp;
280 *rp = *(rp + 1);
281 *(rp + 1) = t;
285 #endif
286 #endif
288 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
289 static PNG_CONST png_byte onebppswaptable[256] = {
290 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
291 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
292 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
293 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
294 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
295 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
296 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
297 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
298 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
299 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
300 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
301 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
302 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
303 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
304 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
305 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
306 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
307 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
308 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
309 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
310 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
311 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
312 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
313 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
314 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
315 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
316 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
317 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
318 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
319 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
320 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
321 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
324 static PNG_CONST png_byte twobppswaptable[256] = {
325 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
326 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
327 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
328 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
329 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
330 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
331 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
332 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
333 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
334 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
335 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
336 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
337 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
338 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
339 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
340 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
341 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
342 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
343 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
344 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
345 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
346 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
347 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
348 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
349 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
350 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
351 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
352 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
353 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
354 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
355 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
356 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
359 static PNG_CONST png_byte fourbppswaptable[256] = {
360 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
361 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
362 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
363 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
364 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
365 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
366 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
367 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
368 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
369 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
370 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
371 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
372 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
373 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
374 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
375 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
376 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
377 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
378 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
379 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
380 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
381 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
382 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
383 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
384 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
385 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
386 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
387 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
388 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
389 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
390 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
391 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
394 /* Swaps pixel packing order within bytes */
395 void /* PRIVATE */
396 png_do_packswap(png_row_infop row_info, png_bytep row)
398 png_debug(1, "in png_do_packswap");
400 if (row_info->bit_depth < 8)
402 png_bytep rp;
403 png_const_bytep end, table;
405 end = row + row_info->rowbytes;
407 if (row_info->bit_depth == 1)
408 table = onebppswaptable;
410 else if (row_info->bit_depth == 2)
411 table = twobppswaptable;
413 else if (row_info->bit_depth == 4)
414 table = fourbppswaptable;
416 else
417 return;
419 for (rp = row; rp < end; rp++)
420 *rp = table[*rp];
423 #endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
425 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
426 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
427 /* Remove a channel - this used to be 'png_do_strip_filler' but it used a
428 * somewhat weird combination of flags to determine what to do. All the calls
429 * to png_do_strip_filler are changed in 1.5.2 to call this instead with the
430 * correct arguments.
432 * The routine isn't general - the channel must be the channel at the start or
433 * end (not in the middle) of each pixel.
435 void /* PRIVATE */
436 png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
438 png_bytep sp = row; /* source pointer */
439 png_bytep dp = row; /* destination pointer */
440 png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
442 /* At the start sp will point to the first byte to copy and dp to where
443 * it is copied to. ep always points just beyond the end of the row, so
444 * the loop simply copies (channels-1) channels until sp reaches ep.
446 * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
447 * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
450 /* GA, GX, XG cases */
451 if (row_info->channels == 2)
453 if (row_info->bit_depth == 8)
455 if (at_start) /* Skip initial filler */
456 ++sp;
457 else /* Skip initial channel and, for sp, the filler */
458 sp += 2, ++dp;
460 /* For a 1 pixel wide image there is nothing to do */
461 while (sp < ep)
462 *dp++ = *sp, sp += 2;
464 row_info->pixel_depth = 8;
467 else if (row_info->bit_depth == 16)
469 if (at_start) /* Skip initial filler */
470 sp += 2;
471 else /* Skip initial channel and, for sp, the filler */
472 sp += 4, dp += 2;
474 while (sp < ep)
475 *dp++ = *sp++, *dp++ = *sp, sp += 3;
477 row_info->pixel_depth = 16;
480 else
481 return; /* bad bit depth */
483 row_info->channels = 1;
485 /* Finally fix the color type if it records an alpha channel */
486 if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
487 row_info->color_type = PNG_COLOR_TYPE_GRAY;
490 /* RGBA, RGBX, XRGB cases */
491 else if (row_info->channels == 4)
493 if (row_info->bit_depth == 8)
495 if (at_start) /* Skip initial filler */
496 ++sp;
497 else /* Skip initial channels and, for sp, the filler */
498 sp += 4, dp += 3;
500 /* Note that the loop adds 3 to dp and 4 to sp each time. */
501 while (sp < ep)
502 *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
504 row_info->pixel_depth = 24;
507 else if (row_info->bit_depth == 16)
509 if (at_start) /* Skip initial filler */
510 sp += 2;
511 else /* Skip initial channels and, for sp, the filler */
512 sp += 8, dp += 6;
514 while (sp < ep)
516 /* Copy 6 bytes, skip 2 */
517 *dp++ = *sp++, *dp++ = *sp++;
518 *dp++ = *sp++, *dp++ = *sp++;
519 *dp++ = *sp++, *dp++ = *sp, sp += 3;
522 row_info->pixel_depth = 48;
525 else
526 return; /* bad bit depth */
528 row_info->channels = 3;
530 /* Finally fix the color type if it records an alpha channel */
531 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
532 row_info->color_type = PNG_COLOR_TYPE_RGB;
535 else
536 return; /* The filler channel has gone already */
538 /* Fix the rowbytes value. */
539 row_info->rowbytes = dp-row;
541 #endif
543 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
544 /* Swaps red and blue bytes within a pixel */
545 void /* PRIVATE */
546 png_do_bgr(png_row_infop row_info, png_bytep row)
548 png_debug(1, "in png_do_bgr");
550 if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
552 png_uint_32 row_width = row_info->width;
553 if (row_info->bit_depth == 8)
555 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
557 png_bytep rp;
558 png_uint_32 i;
560 for (i = 0, rp = row; i < row_width; i++, rp += 3)
562 png_byte save = *rp;
563 *rp = *(rp + 2);
564 *(rp + 2) = save;
568 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
570 png_bytep rp;
571 png_uint_32 i;
573 for (i = 0, rp = row; i < row_width; i++, rp += 4)
575 png_byte save = *rp;
576 *rp = *(rp + 2);
577 *(rp + 2) = save;
582 #ifdef PNG_16BIT_SUPPORTED
583 else if (row_info->bit_depth == 16)
585 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
587 png_bytep rp;
588 png_uint_32 i;
590 for (i = 0, rp = row; i < row_width; i++, rp += 6)
592 png_byte save = *rp;
593 *rp = *(rp + 4);
594 *(rp + 4) = save;
595 save = *(rp + 1);
596 *(rp + 1) = *(rp + 5);
597 *(rp + 5) = save;
601 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
603 png_bytep rp;
604 png_uint_32 i;
606 for (i = 0, rp = row; i < row_width; i++, rp += 8)
608 png_byte save = *rp;
609 *rp = *(rp + 4);
610 *(rp + 4) = save;
611 save = *(rp + 1);
612 *(rp + 1) = *(rp + 5);
613 *(rp + 5) = save;
617 #endif
620 #endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
622 #if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
623 defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
624 /* Added at libpng-1.5.10 */
625 void /* PRIVATE */
626 png_do_check_palette_indexes(png_structp png_ptr, png_row_infop row_info)
628 if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
629 png_ptr->num_palette_max >= 0)
631 /* Calculations moved outside switch in an attempt to stop different
632 * compiler warnings. 'padding' is in *bits* within the last byte, it is
633 * an 'int' because pixel_depth becomes an 'int' in the expression below,
634 * and this calculation is used because it avoids warnings that other
635 * forms produced on either GCC or MSVC.
637 int padding = (-row_info->pixel_depth * row_info->width) & 7;
638 png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
640 switch (row_info->bit_depth)
642 case 1:
644 /* in this case, all bytes must be 0 so we don't need
645 * to unpack the pixels except for the rightmost one.
647 for (; rp > png_ptr->row_buf; rp--)
649 if (*rp >> padding != 0)
650 png_ptr->num_palette_max = 1;
651 padding = 0;
654 break;
657 case 2:
659 for (; rp > png_ptr->row_buf; rp--)
661 int i = ((*rp >> padding) & 0x03);
663 if (i > png_ptr->num_palette_max)
664 png_ptr->num_palette_max = i;
666 i = (((*rp >> padding) >> 2) & 0x03);
668 if (i > png_ptr->num_palette_max)
669 png_ptr->num_palette_max = i;
671 i = (((*rp >> padding) >> 4) & 0x03);
673 if (i > png_ptr->num_palette_max)
674 png_ptr->num_palette_max = i;
676 i = (((*rp >> padding) >> 6) & 0x03);
678 if (i > png_ptr->num_palette_max)
679 png_ptr->num_palette_max = i;
681 padding = 0;
684 break;
687 case 4:
689 for (; rp > png_ptr->row_buf; rp--)
691 int i = ((*rp >> padding) & 0x0f);
693 if (i > png_ptr->num_palette_max)
694 png_ptr->num_palette_max = i;
696 i = (((*rp >> padding) >> 4) & 0x0f);
698 if (i > png_ptr->num_palette_max)
699 png_ptr->num_palette_max = i;
701 padding = 0;
704 break;
707 case 8:
709 for (; rp > png_ptr->row_buf; rp--)
711 if (*rp >= png_ptr->num_palette_max)
712 png_ptr->num_palette_max = (int) *rp;
715 break;
718 default:
719 break;
723 #endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */
725 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
726 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
727 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
728 void PNGAPI
729 png_set_user_transform_info(png_structp png_ptr, png_voidp
730 user_transform_ptr, int user_transform_depth, int user_transform_channels)
732 png_debug(1, "in png_set_user_transform_info");
734 if (png_ptr == NULL)
735 return;
736 png_ptr->user_transform_ptr = user_transform_ptr;
737 png_ptr->user_transform_depth = (png_byte)user_transform_depth;
738 png_ptr->user_transform_channels = (png_byte)user_transform_channels;
740 #endif
742 /* This function returns a pointer to the user_transform_ptr associated with
743 * the user transform functions. The application should free any memory
744 * associated with this pointer before png_write_destroy and png_read_destroy
745 * are called.
747 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
748 png_voidp PNGAPI
749 png_get_user_transform_ptr(png_const_structp png_ptr)
751 if (png_ptr == NULL)
752 return (NULL);
754 return ((png_voidp)png_ptr->user_transform_ptr);
756 #endif
758 #ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
759 png_uint_32 PNGAPI
760 png_get_current_row_number(png_const_structp png_ptr)
762 /* See the comments in png.h - this is the sub-image row when reading and
763 * interlaced image.
765 if (png_ptr != NULL)
766 return png_ptr->row_number;
768 return PNG_UINT_32_MAX; /* help the app not to fail silently */
771 png_byte PNGAPI
772 png_get_current_pass_number(png_const_structp png_ptr)
774 if (png_ptr != NULL)
775 return png_ptr->pass;
776 return 8; /* invalid */
778 #endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */
779 #endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
780 PNG_WRITE_USER_TRANSFORM_SUPPORTED */
781 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */