2 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
4 * Last changed in libpng 1.4.0 [January 3, 2010]
5 * Copyright (c) 1998-2010 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 #define PNG_NO_PEDANTIC_WARNINGS
16 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
19 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
20 /* Turn on BGR-to-RGB mapping */
22 png_set_bgr(png_structp png_ptr)
24 png_debug(1, "in png_set_bgr");
28 png_ptr->transformations |= PNG_BGR;
32 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
33 /* Turn on 16 bit byte swapping */
35 png_set_swap(png_structp png_ptr)
37 png_debug(1, "in png_set_swap");
41 if (png_ptr->bit_depth == 16)
42 png_ptr->transformations |= PNG_SWAP_BYTES;
46 #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
47 /* Turn on pixel packing */
49 png_set_packing(png_structp png_ptr)
51 png_debug(1, "in png_set_packing");
55 if (png_ptr->bit_depth < 8)
57 png_ptr->transformations |= PNG_PACK;
58 png_ptr->usr_bit_depth = 8;
63 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
64 /* Turn on packed pixel swapping */
66 png_set_packswap(png_structp png_ptr)
68 png_debug(1, "in png_set_packswap");
72 if (png_ptr->bit_depth < 8)
73 png_ptr->transformations |= PNG_PACKSWAP;
77 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
79 png_set_shift(png_structp png_ptr, png_color_8p true_bits)
81 png_debug(1, "in png_set_shift");
85 png_ptr->transformations |= PNG_SHIFT;
86 png_ptr->shift = *true_bits;
90 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
91 defined(PNG_WRITE_INTERLACING_SUPPORTED)
93 png_set_interlace_handling(png_structp png_ptr)
95 png_debug(1, "in png_set_interlace handling");
97 if (png_ptr && png_ptr->interlaced)
99 png_ptr->transformations |= PNG_INTERLACE;
107 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
108 /* Add a filler byte on read, or remove a filler or alpha byte on write.
109 * The filler type has changed in v0.95 to allow future 2-byte fillers
110 * for 48-bit input data, as well as to avoid problems with some compilers
111 * that don't like bytes as parameters.
114 png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
116 png_debug(1, "in png_set_filler");
120 png_ptr->transformations |= PNG_FILLER;
121 png_ptr->filler = (png_uint_16)filler;
122 if (filler_loc == PNG_FILLER_AFTER)
123 png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
125 png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
127 /* This should probably go in the "do_read_filler" routine.
128 * I attempted to do that in libpng-1.0.1a but that caused problems
129 * so I restored it in libpng-1.0.2a
132 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
134 png_ptr->usr_channels = 4;
137 /* Also I added this in libpng-1.0.2a (what happens when we expand
138 * a less-than-8-bit grayscale to GA? */
140 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
142 png_ptr->usr_channels = 2;
146 /* Added to libpng-1.2.7 */
148 png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
150 png_debug(1, "in png_set_add_alpha");
154 png_set_filler(png_ptr, filler, filler_loc);
155 png_ptr->transformations |= PNG_ADD_ALPHA;
160 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
161 defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
163 png_set_swap_alpha(png_structp png_ptr)
165 png_debug(1, "in png_set_swap_alpha");
169 png_ptr->transformations |= PNG_SWAP_ALPHA;
173 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
174 defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
176 png_set_invert_alpha(png_structp png_ptr)
178 png_debug(1, "in png_set_invert_alpha");
182 png_ptr->transformations |= PNG_INVERT_ALPHA;
186 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
188 png_set_invert_mono(png_structp png_ptr)
190 png_debug(1, "in png_set_invert_mono");
194 png_ptr->transformations |= PNG_INVERT_MONO;
197 /* Invert monochrome grayscale data */
199 png_do_invert(png_row_infop row_info, png_bytep row)
201 png_debug(1, "in png_do_invert");
203 /* This test removed from libpng version 1.0.13 and 1.2.0:
204 * if (row_info->bit_depth == 1 &&
206 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
210 png_uint_32 istop = row_info->rowbytes;
212 for (i = 0; i < istop; i++)
214 *rp = (png_byte)(~(*rp));
218 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
219 row_info->bit_depth == 8)
223 png_uint_32 istop = row_info->rowbytes;
225 for (i = 0; i < istop; i+=2)
227 *rp = (png_byte)(~(*rp));
231 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
232 row_info->bit_depth == 16)
236 png_uint_32 istop = row_info->rowbytes;
238 for (i = 0; i < istop; i+=4)
240 *rp = (png_byte)(~(*rp));
241 *(rp+1) = (png_byte)(~(*(rp+1)));
248 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
249 /* Swaps byte order on 16 bit depth images */
251 png_do_swap(png_row_infop row_info, png_bytep row)
253 png_debug(1, "in png_do_swap");
256 row_info->bit_depth == 16)
260 png_uint_32 istop= row_info->width * row_info->channels;
262 for (i = 0; i < istop; i++, rp += 2)
272 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
273 static PNG_CONST png_byte onebppswaptable[256] = {
274 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
275 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
276 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
277 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
278 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
279 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
280 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
281 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
282 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
283 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
284 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
285 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
286 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
287 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
288 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
289 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
290 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
291 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
292 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
293 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
294 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
295 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
296 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
297 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
298 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
299 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
300 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
301 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
302 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
303 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
304 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
305 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
308 static PNG_CONST png_byte twobppswaptable[256] = {
309 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
310 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
311 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
312 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
313 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
314 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
315 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
316 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
317 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
318 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
319 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
320 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
321 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
322 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
323 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
324 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
325 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
326 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
327 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
328 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
329 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
330 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
331 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
332 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
333 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
334 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
335 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
336 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
337 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
338 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
339 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
340 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
343 static PNG_CONST png_byte fourbppswaptable[256] = {
344 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
345 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
346 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
347 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
348 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
349 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
350 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
351 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
352 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
353 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
354 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
355 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
356 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
357 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
358 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
359 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
360 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
361 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
362 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
363 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
364 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
365 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
366 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
367 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
368 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
369 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
370 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
371 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
372 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
373 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
374 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
375 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
378 /* Swaps pixel packing order within bytes */
380 png_do_packswap(png_row_infop row_info, png_bytep row)
382 png_debug(1, "in png_do_packswap");
385 row_info->bit_depth < 8)
387 png_bytep rp, end, table;
389 end = row + row_info->rowbytes;
391 if (row_info->bit_depth == 1)
392 table = (png_bytep)onebppswaptable;
393 else if (row_info->bit_depth == 2)
394 table = (png_bytep)twobppswaptable;
395 else if (row_info->bit_depth == 4)
396 table = (png_bytep)fourbppswaptable;
400 for (rp = row; rp < end; rp++)
404 #endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
406 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
407 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
408 /* Remove filler or alpha byte(s) */
410 png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
412 png_debug(1, "in png_do_strip_filler");
417 png_uint_32 row_width=row_info->width;
420 if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
421 (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
422 (flags & PNG_FLAG_STRIP_ALPHA))) &&
423 row_info->channels == 4)
425 if (row_info->bit_depth == 8)
427 /* This converts from RGBX or RGBA to RGB */
428 if (flags & PNG_FLAG_FILLER_AFTER)
431 for (i = 1; i < row_width; i++)
439 /* This converts from XRGB or ARGB to RGB */
442 for (i = 0; i < row_width; i++)
450 row_info->pixel_depth = 24;
451 row_info->rowbytes = row_width * 3;
453 else /* if (row_info->bit_depth == 16) */
455 if (flags & PNG_FLAG_FILLER_AFTER)
457 /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
459 for (i = 1; i < row_width; i++)
461 /* This could be (although png_memcpy is probably slower):
462 png_memcpy(dp, sp, 6);
478 /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
479 for (i = 0; i < row_width; i++)
481 /* This could be (although png_memcpy is probably slower):
482 png_memcpy(dp, sp, 6);
496 row_info->pixel_depth = 48;
497 row_info->rowbytes = row_width * 6;
499 row_info->channels = 3;
501 else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
502 (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
503 (flags & PNG_FLAG_STRIP_ALPHA))) &&
504 row_info->channels == 2)
506 if (row_info->bit_depth == 8)
508 /* This converts from GX or GA to G */
509 if (flags & PNG_FLAG_FILLER_AFTER)
511 for (i = 0; i < row_width; i++)
517 /* This converts from XG or AG to G */
520 for (i = 0; i < row_width; i++)
526 row_info->pixel_depth = 8;
527 row_info->rowbytes = row_width;
529 else /* if (row_info->bit_depth == 16) */
531 if (flags & PNG_FLAG_FILLER_AFTER)
533 /* This converts from GGXX or GGAA to GG */
535 for (i = 1; i < row_width; i++)
544 /* This converts from XXGG or AAGG to GG */
545 for (i = 0; i < row_width; i++)
552 row_info->pixel_depth = 16;
553 row_info->rowbytes = row_width * 2;
555 row_info->channels = 1;
557 if (flags & PNG_FLAG_STRIP_ALPHA)
558 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
563 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
564 /* Swaps red and blue bytes within a pixel */
566 png_do_bgr(png_row_infop row_info, png_bytep row)
568 png_debug(1, "in png_do_bgr");
571 (row_info->color_type & PNG_COLOR_MASK_COLOR))
573 png_uint_32 row_width = row_info->width;
574 if (row_info->bit_depth == 8)
576 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
581 for (i = 0, rp = row; i < row_width; i++, rp += 3)
588 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
593 for (i = 0, rp = row; i < row_width; i++, rp += 4)
601 else if (row_info->bit_depth == 16)
603 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
608 for (i = 0, rp = row; i < row_width; i++, rp += 6)
614 *(rp + 1) = *(rp + 5);
618 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
623 for (i = 0, rp = row; i < row_width; i++, rp += 8)
629 *(rp + 1) = *(rp + 5);
636 #endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
638 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
639 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
641 png_set_user_transform_info(png_structp png_ptr, png_voidp
642 user_transform_ptr, int user_transform_depth, int user_transform_channels)
644 png_debug(1, "in png_set_user_transform_info");
648 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
649 png_ptr->user_transform_ptr = user_transform_ptr;
650 png_ptr->user_transform_depth = (png_byte)user_transform_depth;
651 png_ptr->user_transform_channels = (png_byte)user_transform_channels;
653 if (user_transform_ptr || user_transform_depth || user_transform_channels)
655 "This version of libpng does not support user transform info");
660 /* This function returns a pointer to the user_transform_ptr associated with
661 * the user transform functions. The application should free any memory
662 * associated with this pointer before png_write_destroy and png_read_destroy
666 png_get_user_transform_ptr(png_structp png_ptr)
670 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
671 return ((png_voidp)png_ptr->user_transform_ptr);
676 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */