2 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
4 * Last changed in libpng 1.6.2 [April 25, 2013]
5 * Copyright (c) 1998-2013 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
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 */
21 png_set_bgr(png_structrp png_ptr
)
23 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_structrp png_ptr
)
37 png_debug(1, "in png_set_swap");
42 if (png_ptr
->bit_depth
== 16)
43 png_ptr
->transformations
|= PNG_SWAP_BYTES
;
47 #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
48 /* Turn on pixel packing */
50 png_set_packing(png_structrp png_ptr
)
52 png_debug(1, "in png_set_packing");
57 if (png_ptr
->bit_depth
< 8)
59 png_ptr
->transformations
|= PNG_PACK
;
60 png_ptr
->usr_bit_depth
= 8;
65 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
66 /* Turn on packed pixel swapping */
68 png_set_packswap(png_structrp png_ptr
)
70 png_debug(1, "in png_set_packswap");
75 if (png_ptr
->bit_depth
< 8)
76 png_ptr
->transformations
|= PNG_PACKSWAP
;
80 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
82 png_set_shift(png_structrp png_ptr
, png_const_color_8p true_bits
)
84 png_debug(1, "in png_set_shift");
89 png_ptr
->transformations
|= PNG_SHIFT
;
90 png_ptr
->shift
= *true_bits
;
94 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
95 defined(PNG_WRITE_INTERLACING_SUPPORTED)
97 png_set_interlace_handling(png_structrp png_ptr
)
99 png_debug(1, "in png_set_interlace handling");
101 if (png_ptr
&& png_ptr
->interlaced
)
103 png_ptr
->transformations
|= PNG_INTERLACE
;
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.
118 png_set_filler(png_structrp png_ptr
, png_uint_32 filler
, int filler_loc
)
120 png_debug(1, "in png_set_filler");
125 /* In libpng 1.6 it is possible to determine whether this is a read or write
126 * operation and therefore to do more checking here for a valid call.
128 if (png_ptr
->mode
& PNG_IS_READ_STRUCT
)
130 # ifdef PNG_READ_FILLER_SUPPORTED
131 /* On read png_set_filler is always valid, regardless of the base PNG
132 * format, because other transformations can give a format where the
133 * filler code can execute (basically an 8 or 16-bit component RGB or G
136 * NOTE: usr_channels is not used by the read code! (This has led to
137 * confusion in the past.) The filler is only used in the read code.
139 png_ptr
->filler
= (png_uint_16
)filler
;
141 png_app_error(png_ptr
, "png_set_filler not supported on read");
142 PNG_UNUSED(filler
) /* not used in the write case */
149 # ifdef PNG_WRITE_FILLER_SUPPORTED
150 /* On write the usr_channels parameter must be set correctly at the
151 * start to record the number of channels in the app-supplied data.
153 switch (png_ptr
->color_type
)
155 case PNG_COLOR_TYPE_RGB
:
156 png_ptr
->usr_channels
= 4;
159 case PNG_COLOR_TYPE_GRAY
:
160 if (png_ptr
->bit_depth
>= 8)
162 png_ptr
->usr_channels
= 2;
168 /* There simply isn't any code in libpng to strip out bits
169 * from bytes when the components are less than a byte in
172 png_app_error(png_ptr
,
173 "png_set_filler is invalid for low bit depth gray output");
178 png_app_error(png_ptr
,
179 "png_set_filler: inappropriate color type");
183 png_app_error(png_ptr
, "png_set_filler not supported on write");
188 /* Here on success - libpng supports the operation, set the transformation
189 * and the flag to say where the filler channel is.
191 png_ptr
->transformations
|= PNG_FILLER
;
193 if (filler_loc
== PNG_FILLER_AFTER
)
194 png_ptr
->flags
|= PNG_FLAG_FILLER_AFTER
;
197 png_ptr
->flags
&= ~PNG_FLAG_FILLER_AFTER
;
200 /* Added to libpng-1.2.7 */
202 png_set_add_alpha(png_structrp png_ptr
, png_uint_32 filler
, int filler_loc
)
204 png_debug(1, "in png_set_add_alpha");
209 png_set_filler(png_ptr
, filler
, filler_loc
);
210 /* The above may fail to do anything. */
211 if (png_ptr
->transformations
& PNG_FILLER
)
212 png_ptr
->transformations
|= PNG_ADD_ALPHA
;
217 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
218 defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
220 png_set_swap_alpha(png_structrp png_ptr
)
222 png_debug(1, "in png_set_swap_alpha");
227 png_ptr
->transformations
|= PNG_SWAP_ALPHA
;
231 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
232 defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
234 png_set_invert_alpha(png_structrp png_ptr
)
236 png_debug(1, "in png_set_invert_alpha");
241 png_ptr
->transformations
|= PNG_INVERT_ALPHA
;
245 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
247 png_set_invert_mono(png_structrp png_ptr
)
249 png_debug(1, "in png_set_invert_mono");
254 png_ptr
->transformations
|= PNG_INVERT_MONO
;
257 /* Invert monochrome grayscale data */
259 png_do_invert(png_row_infop row_info
, png_bytep row
)
261 png_debug(1, "in png_do_invert");
263 /* This test removed from libpng version 1.0.13 and 1.2.0:
264 * if (row_info->bit_depth == 1 &&
266 if (row_info
->color_type
== PNG_COLOR_TYPE_GRAY
)
270 png_size_t istop
= row_info
->rowbytes
;
272 for (i
= 0; i
< istop
; i
++)
274 *rp
= (png_byte
)(~(*rp
));
279 else if (row_info
->color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
&&
280 row_info
->bit_depth
== 8)
284 png_size_t istop
= row_info
->rowbytes
;
286 for (i
= 0; i
< istop
; i
+= 2)
288 *rp
= (png_byte
)(~(*rp
));
293 #ifdef PNG_16BIT_SUPPORTED
294 else if (row_info
->color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
&&
295 row_info
->bit_depth
== 16)
299 png_size_t istop
= row_info
->rowbytes
;
301 for (i
= 0; i
< istop
; i
+= 4)
303 *rp
= (png_byte
)(~(*rp
));
304 *(rp
+ 1) = (png_byte
)(~(*(rp
+ 1)));
312 #ifdef PNG_16BIT_SUPPORTED
313 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
314 /* Swaps byte order on 16 bit depth images */
316 png_do_swap(png_row_infop row_info
, png_bytep row
)
318 png_debug(1, "in png_do_swap");
320 if (row_info
->bit_depth
== 16)
324 png_uint_32 istop
= row_info
->width
* row_info
->channels
;
326 for (i
= 0; i
< istop
; i
++, rp
+= 2)
337 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
338 static PNG_CONST png_byte onebppswaptable
[256] = {
339 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
340 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
341 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
342 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
343 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
344 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
345 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
346 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
347 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
348 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
349 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
350 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
351 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
352 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
353 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
354 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
355 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
356 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
357 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
358 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
359 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
360 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
361 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
362 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
363 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
364 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
365 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
366 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
367 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
368 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
369 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
370 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
373 static PNG_CONST png_byte twobppswaptable
[256] = {
374 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
375 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
376 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
377 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
378 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
379 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
380 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
381 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
382 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
383 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
384 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
385 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
386 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
387 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
388 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
389 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
390 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
391 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
392 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
393 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
394 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
395 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
396 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
397 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
398 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
399 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
400 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
401 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
402 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
403 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
404 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
405 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
408 static PNG_CONST png_byte fourbppswaptable
[256] = {
409 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
410 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
411 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
412 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
413 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
414 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
415 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
416 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
417 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
418 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
419 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
420 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
421 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
422 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
423 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
424 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
425 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
426 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
427 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
428 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
429 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
430 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
431 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
432 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
433 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
434 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
435 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
436 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
437 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
438 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
439 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
440 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
443 /* Swaps pixel packing order within bytes */
445 png_do_packswap(png_row_infop row_info
, png_bytep row
)
447 png_debug(1, "in png_do_packswap");
449 if (row_info
->bit_depth
< 8)
452 png_const_bytep end
, table
;
454 end
= row
+ row_info
->rowbytes
;
456 if (row_info
->bit_depth
== 1)
457 table
= onebppswaptable
;
459 else if (row_info
->bit_depth
== 2)
460 table
= twobppswaptable
;
462 else if (row_info
->bit_depth
== 4)
463 table
= fourbppswaptable
;
468 for (rp
= row
; rp
< end
; rp
++)
472 #endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
474 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
475 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
476 /* Remove a channel - this used to be 'png_do_strip_filler' but it used a
477 * somewhat weird combination of flags to determine what to do. All the calls
478 * to png_do_strip_filler are changed in 1.5.2 to call this instead with the
481 * The routine isn't general - the channel must be the channel at the start or
482 * end (not in the middle) of each pixel.
485 png_do_strip_channel(png_row_infop row_info
, png_bytep row
, int at_start
)
487 png_bytep sp
= row
; /* source pointer */
488 png_bytep dp
= row
; /* destination pointer */
489 png_bytep ep
= row
+ row_info
->rowbytes
; /* One beyond end of row */
491 /* At the start sp will point to the first byte to copy and dp to where
492 * it is copied to. ep always points just beyond the end of the row, so
493 * the loop simply copies (channels-1) channels until sp reaches ep.
495 * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
496 * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
499 /* GA, GX, XG cases */
500 if (row_info
->channels
== 2)
502 if (row_info
->bit_depth
== 8)
504 if (at_start
) /* Skip initial filler */
506 else /* Skip initial channel and, for sp, the filler */
509 /* For a 1 pixel wide image there is nothing to do */
511 *dp
++ = *sp
, sp
+= 2;
513 row_info
->pixel_depth
= 8;
516 else if (row_info
->bit_depth
== 16)
518 if (at_start
) /* Skip initial filler */
520 else /* Skip initial channel and, for sp, the filler */
524 *dp
++ = *sp
++, *dp
++ = *sp
, sp
+= 3;
526 row_info
->pixel_depth
= 16;
530 return; /* bad bit depth */
532 row_info
->channels
= 1;
534 /* Finally fix the color type if it records an alpha channel */
535 if (row_info
->color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
536 row_info
->color_type
= PNG_COLOR_TYPE_GRAY
;
539 /* RGBA, RGBX, XRGB cases */
540 else if (row_info
->channels
== 4)
542 if (row_info
->bit_depth
== 8)
544 if (at_start
) /* Skip initial filler */
546 else /* Skip initial channels and, for sp, the filler */
549 /* Note that the loop adds 3 to dp and 4 to sp each time. */
551 *dp
++ = *sp
++, *dp
++ = *sp
++, *dp
++ = *sp
, sp
+= 2;
553 row_info
->pixel_depth
= 24;
556 else if (row_info
->bit_depth
== 16)
558 if (at_start
) /* Skip initial filler */
560 else /* Skip initial channels and, for sp, the filler */
565 /* Copy 6 bytes, skip 2 */
566 *dp
++ = *sp
++, *dp
++ = *sp
++;
567 *dp
++ = *sp
++, *dp
++ = *sp
++;
568 *dp
++ = *sp
++, *dp
++ = *sp
, sp
+= 3;
571 row_info
->pixel_depth
= 48;
575 return; /* bad bit depth */
577 row_info
->channels
= 3;
579 /* Finally fix the color type if it records an alpha channel */
580 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
581 row_info
->color_type
= PNG_COLOR_TYPE_RGB
;
585 return; /* The filler channel has gone already */
587 /* Fix the rowbytes value. */
588 row_info
->rowbytes
= dp
-row
;
592 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
593 /* Swaps red and blue bytes within a pixel */
595 png_do_bgr(png_row_infop row_info
, png_bytep row
)
597 png_debug(1, "in png_do_bgr");
599 if ((row_info
->color_type
& PNG_COLOR_MASK_COLOR
))
601 png_uint_32 row_width
= row_info
->width
;
602 if (row_info
->bit_depth
== 8)
604 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB
)
609 for (i
= 0, rp
= row
; i
< row_width
; i
++, rp
+= 3)
617 else if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
622 for (i
= 0, rp
= row
; i
< row_width
; i
++, rp
+= 4)
631 #ifdef PNG_16BIT_SUPPORTED
632 else if (row_info
->bit_depth
== 16)
634 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB
)
639 for (i
= 0, rp
= row
; i
< row_width
; i
++, rp
+= 6)
645 *(rp
+ 1) = *(rp
+ 5);
650 else if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
655 for (i
= 0, rp
= row
; i
< row_width
; i
++, rp
+= 8)
661 *(rp
+ 1) = *(rp
+ 5);
669 #endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
671 #if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
672 defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
673 /* Added at libpng-1.5.10 */
675 png_do_check_palette_indexes(png_structrp png_ptr
, png_row_infop row_info
)
677 if (png_ptr
->num_palette
< (1 << row_info
->bit_depth
) &&
678 png_ptr
->num_palette
> 0) /* num_palette can be 0 in MNG files */
680 /* Calculations moved outside switch in an attempt to stop different
681 * compiler warnings. 'padding' is in *bits* within the last byte, it is
682 * an 'int' because pixel_depth becomes an 'int' in the expression below,
683 * and this calculation is used because it avoids warnings that other
684 * forms produced on either GCC or MSVC.
686 int padding
= (-row_info
->pixel_depth
* row_info
->width
) & 7;
687 png_bytep rp
= png_ptr
->row_buf
+ row_info
->rowbytes
;
689 switch (row_info
->bit_depth
)
693 /* in this case, all bytes must be 0 so we don't need
694 * to unpack the pixels except for the rightmost one.
696 for (; rp
> png_ptr
->row_buf
; rp
--)
698 if (*rp
>> padding
!= 0)
699 png_ptr
->num_palette_max
= 1;
708 for (; rp
> png_ptr
->row_buf
; rp
--)
710 int i
= ((*rp
>> padding
) & 0x03);
712 if (i
> png_ptr
->num_palette_max
)
713 png_ptr
->num_palette_max
= i
;
715 i
= (((*rp
>> padding
) >> 2) & 0x03);
717 if (i
> png_ptr
->num_palette_max
)
718 png_ptr
->num_palette_max
= i
;
720 i
= (((*rp
>> padding
) >> 4) & 0x03);
722 if (i
> png_ptr
->num_palette_max
)
723 png_ptr
->num_palette_max
= i
;
725 i
= (((*rp
>> padding
) >> 6) & 0x03);
727 if (i
> png_ptr
->num_palette_max
)
728 png_ptr
->num_palette_max
= i
;
738 for (; rp
> png_ptr
->row_buf
; rp
--)
740 int i
= ((*rp
>> padding
) & 0x0f);
742 if (i
> png_ptr
->num_palette_max
)
743 png_ptr
->num_palette_max
= i
;
745 i
= (((*rp
>> padding
) >> 4) & 0x0f);
747 if (i
> png_ptr
->num_palette_max
)
748 png_ptr
->num_palette_max
= i
;
758 for (; rp
> png_ptr
->row_buf
; rp
--)
760 if (*rp
> png_ptr
->num_palette_max
)
761 png_ptr
->num_palette_max
= (int) *rp
;
772 #endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */
774 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
775 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
776 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
778 png_set_user_transform_info(png_structrp png_ptr
, png_voidp
779 user_transform_ptr
, int user_transform_depth
, int user_transform_channels
)
781 png_debug(1, "in png_set_user_transform_info");
786 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
787 if ((png_ptr
->mode
& PNG_IS_READ_STRUCT
) != 0 &&
788 (png_ptr
->flags
& PNG_FLAG_ROW_INIT
) != 0)
790 png_app_error(png_ptr
,
791 "info change after png_start_read_image or png_read_update_info");
796 png_ptr
->user_transform_ptr
= user_transform_ptr
;
797 png_ptr
->user_transform_depth
= (png_byte
)user_transform_depth
;
798 png_ptr
->user_transform_channels
= (png_byte
)user_transform_channels
;
802 /* This function returns a pointer to the user_transform_ptr associated with
803 * the user transform functions. The application should free any memory
804 * associated with this pointer before png_write_destroy and png_read_destroy
807 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
809 png_get_user_transform_ptr(png_const_structrp png_ptr
)
814 return png_ptr
->user_transform_ptr
;
818 #ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
820 png_get_current_row_number(png_const_structrp png_ptr
)
822 /* See the comments in png.h - this is the sub-image row when reading and
826 return png_ptr
->row_number
;
828 return PNG_UINT_32_MAX
; /* help the app not to fail silently */
832 png_get_current_pass_number(png_const_structrp png_ptr
)
835 return png_ptr
->pass
;
836 return 8; /* invalid */
838 #endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */
839 #endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
840 PNG_WRITE_USER_TRANSFORM_SUPPORTED */
841 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */