2
/* pngrtran.c - transforms the data in a row for PNG readers
4
* Last changed in libpng 1.4.2 [May 6, 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
13
* This file contains functions optionally called by an application
14
* in order to tell libpng how to handle data when reading a PNG.
15
* Transformations that are used in both reading and writing are
19
#define PNG_NO_PEDANTIC_WARNINGS
21
#ifdef PNG_READ_SUPPORTED
24
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
26
png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
28
png_debug(1, "in png_set_crc_action");
33
/* Tell libpng how we react to CRC errors in critical chunks */
36
case PNG_CRC_NO_CHANGE: /* Leave setting as is */
39
case PNG_CRC_WARN_USE: /* Warn/use data */
40
png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
41
png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
44
case PNG_CRC_QUIET_USE: /* Quiet/use data */
45
png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
46
png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
47
PNG_FLAG_CRC_CRITICAL_IGNORE;
50
case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */
52
"Can't discard critical data on CRC error");
53
case PNG_CRC_ERROR_QUIT: /* Error/quit */
57
png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
61
/* Tell libpng how we react to CRC errors in ancillary chunks */
64
case PNG_CRC_NO_CHANGE: /* Leave setting as is */
67
case PNG_CRC_WARN_USE: /* Warn/use data */
68
png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
69
png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
72
case PNG_CRC_QUIET_USE: /* Quiet/use data */
73
png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
74
png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
75
PNG_FLAG_CRC_ANCILLARY_NOWARN;
78
case PNG_CRC_ERROR_QUIT: /* Error/quit */
79
png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
80
png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
83
case PNG_CRC_WARN_DISCARD: /* Warn/discard data */
87
png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
92
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
93
defined(PNG_FLOATING_POINT_SUPPORTED)
94
/* Handle alpha and tRNS via a background color */
96
png_set_background(png_structp png_ptr,
97
png_color_16p background_color, int background_gamma_code,
98
int need_expand, double background_gamma)
100
png_debug(1, "in png_set_background");
104
if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
106
png_warning(png_ptr, "Application must supply a known background gamma");
110
png_ptr->transformations |= PNG_BACKGROUND;
111
png_memcpy(&(png_ptr->background), background_color,
112
png_sizeof(png_color_16));
113
png_ptr->background_gamma = (float)background_gamma;
114
png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
115
png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
119
#ifdef PNG_READ_16_TO_8_SUPPORTED
120
/* Strip 16 bit depth files to 8 bit depth */
122
png_set_strip_16(png_structp png_ptr)
124
png_debug(1, "in png_set_strip_16");
128
png_ptr->transformations |= PNG_16_TO_8;
132
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
134
png_set_strip_alpha(png_structp png_ptr)
136
png_debug(1, "in png_set_strip_alpha");
140
png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
144
#ifdef PNG_READ_QUANTIZE_SUPPORTED
145
/* Quantize file to 8 bit. Supply a palette, the current number
146
* of elements in the palette, the maximum number of elements
147
* allowed, and a histogram if possible. If the current number
148
* of colors is greater then the maximum number, the palette will be
149
* modified to fit in the maximum number. "full_quantize" indicates
150
* whether we need a quantizeing cube set up for RGB images, or if we
151
* simply are reducing the number of colors in a paletted image.
154
typedef struct png_dsort_struct
156
struct png_dsort_struct FAR * next;
160
typedef png_dsort FAR * png_dsortp;
161
typedef png_dsort FAR * FAR * png_dsortpp;
164
png_set_quantize(png_structp png_ptr, png_colorp palette,
165
int num_palette, int maximum_colors, png_uint_16p histogram,
168
png_debug(1, "in png_set_quantize");
172
png_ptr->transformations |= PNG_QUANTIZE;
178
png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
179
(png_uint_32)(num_palette * png_sizeof(png_byte)));
180
for (i = 0; i < num_palette; i++)
181
png_ptr->quantize_index[i] = (png_byte)i;
184
if (num_palette > maximum_colors)
186
if (histogram != NULL)
188
/* This is easy enough, just throw out the least used colors.
189
* Perhaps not the best solution, but good enough.
194
/* Initialize an array to sort colors */
195
png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
196
(png_uint_32)(num_palette * png_sizeof(png_byte)));
198
/* Initialize the quantize_sort array */
199
for (i = 0; i < num_palette; i++)
200
png_ptr->quantize_sort[i] = (png_byte)i;
202
/* Find the least used palette entries by starting a
203
* bubble sort, and running it until we have sorted
204
* out enough colors. Note that we don't care about
205
* sorting all the colors, just finding which are
209
for (i = num_palette - 1; i >= maximum_colors; i--)
211
int done; /* To stop early if the list is pre-sorted */
215
for (j = 0; j < i; j++)
217
if (histogram[png_ptr->quantize_sort[j]]
218
< histogram[png_ptr->quantize_sort[j + 1]])
222
t = png_ptr->quantize_sort[j];
223
png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
224
png_ptr->quantize_sort[j + 1] = t;
232
/* Swap the palette around, and set up a table, if necessary */
237
/* Put all the useful colors within the max, but don't
240
for (i = 0; i < maximum_colors; i++)
242
if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
246
while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
247
palette[i] = palette[j];
255
/* Move all the used colors inside the max limit, and
256
* develop a translation table.
258
for (i = 0; i < maximum_colors; i++)
260
/* Only move the colors we need to */
261
if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
267
while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
269
tmp_color = palette[j];
270
palette[j] = palette[i];
271
palette[i] = tmp_color;
272
/* Indicate where the color went */
273
png_ptr->quantize_index[j] = (png_byte)i;
274
png_ptr->quantize_index[i] = (png_byte)j;
278
/* Find closest color for those colors we are not using */
279
for (i = 0; i < num_palette; i++)
281
if ((int)png_ptr->quantize_index[i] >= maximum_colors)
283
int min_d, k, min_k, d_index;
285
/* Find the closest color to one we threw out */
286
d_index = png_ptr->quantize_index[i];
287
min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
288
for (k = 1, min_k = 0; k < maximum_colors; k++)
292
d = PNG_COLOR_DIST(palette[d_index], palette[k]);
300
/* Point to closest color */
301
png_ptr->quantize_index[i] = (png_byte)min_k;
305
png_free(png_ptr, png_ptr->quantize_sort);
306
png_ptr->quantize_sort = NULL;
310
/* This is much harder to do simply (and quickly). Perhaps
311
* we need to go through a median cut routine, but those
312
* don't always behave themselves with only a few colors
313
* as input. So we will just find the closest two colors,
314
* and throw out one of them (chosen somewhat randomly).
315
* [We don't understand this at all, so if someone wants to
316
* work on improving it, be our guest - AED, GRP]
326
/* Initialize palette index arrays */
327
png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
328
(png_uint_32)(num_palette * png_sizeof(png_byte)));
329
png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
330
(png_uint_32)(num_palette * png_sizeof(png_byte)));
332
/* Initialize the sort array */
333
for (i = 0; i < num_palette; i++)
335
png_ptr->index_to_palette[i] = (png_byte)i;
336
png_ptr->palette_to_index[i] = (png_byte)i;
339
hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
340
png_sizeof(png_dsortp)));
342
num_new_palette = num_palette;
344
/* Initial wild guess at how far apart the farthest pixel
345
* pair we will be eliminating will be. Larger
346
* numbers mean more areas will be allocated, Smaller
347
* numbers run the risk of not saving enough data, and
348
* having to do this all over again.
350
* I have not done extensive checking on this number.
354
while (num_new_palette > maximum_colors)
356
for (i = 0; i < num_new_palette - 1; i++)
360
for (j = i + 1; j < num_new_palette; j++)
364
d = PNG_COLOR_DIST(palette[i], palette[j]);
369
t = (png_dsortp)png_malloc_warn(png_ptr,
370
(png_uint_32)(png_sizeof(png_dsort)));
374
t->left = (png_byte)i;
375
t->right = (png_byte)j;
384
for (i = 0; i <= max_d; i++)
390
for (p = hash[i]; p; p = p->next)
392
if ((int)png_ptr->index_to_palette[p->left]
394
(int)png_ptr->index_to_palette[p->right]
399
if (num_new_palette & 0x01)
411
palette[png_ptr->index_to_palette[j]]
412
= palette[num_new_palette];
417
for (k = 0; k < num_palette; k++)
419
if (png_ptr->quantize_index[k] ==
420
png_ptr->index_to_palette[j])
421
png_ptr->quantize_index[k] =
422
png_ptr->index_to_palette[next_j];
423
if ((int)png_ptr->quantize_index[k] ==
425
png_ptr->quantize_index[k] =
426
png_ptr->index_to_palette[j];
430
png_ptr->index_to_palette[png_ptr->palette_to_index
431
[num_new_palette]] = png_ptr->index_to_palette[j];
432
png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
433
= png_ptr->palette_to_index[num_new_palette];
435
png_ptr->index_to_palette[j] =
436
(png_byte)num_new_palette;
437
png_ptr->palette_to_index[num_new_palette] =
440
if (num_new_palette <= maximum_colors)
443
if (num_new_palette <= maximum_colors)
448
for (i = 0; i < 769; i++)
452
png_dsortp p = hash[i];
456
png_free(png_ptr, p);
464
png_free(png_ptr, hash);
465
png_free(png_ptr, png_ptr->palette_to_index);
466
png_free(png_ptr, png_ptr->index_to_palette);
467
png_ptr->palette_to_index = NULL;
468
png_ptr->index_to_palette = NULL;
470
num_palette = maximum_colors;
472
if (png_ptr->palette == NULL)
474
png_ptr->palette = palette;
476
png_ptr->num_palette = (png_uint_16)num_palette;
482
int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +
483
PNG_QUANTIZE_BLUE_BITS;
484
int num_red = (1 << PNG_QUANTIZE_RED_BITS);
485
int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);
486
int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);
487
png_size_t num_entries = ((png_size_t)1 << total_bits);
489
png_ptr->palette_lookup = (png_bytep )png_calloc(png_ptr,
490
(png_uint_32)(num_entries * png_sizeof(png_byte)));
492
distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
493
png_sizeof(png_byte)));
494
png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
496
for (i = 0; i < num_palette; i++)
499
int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));
500
int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));
501
int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
503
for (ir = 0; ir < num_red; ir++)
505
/* int dr = abs(ir - r); */
506
int dr = ((ir > r) ? ir - r : r - ir);
507
int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
508
PNG_QUANTIZE_GREEN_BITS));
510
for (ig = 0; ig < num_green; ig++)
512
/* int dg = abs(ig - g); */
513
int dg = ((ig > g) ? ig - g : g - ig);
515
int dm = ((dr > dg) ? dr : dg);
516
int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
518
for (ib = 0; ib < num_blue; ib++)
520
int d_index = index_g | ib;
521
/* int db = abs(ib - b); */
522
int db = ((ib > b) ? ib - b : b - ib);
523
int dmax = ((dm > db) ? dm : db);
524
int d = dmax + dt + db;
526
if (d < (int)distance[d_index])
528
distance[d_index] = (png_byte)d;
529
png_ptr->palette_lookup[d_index] = (png_byte)i;
536
png_free(png_ptr, distance);
539
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
541
#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
542
/* Transform the image from the file_gamma to the screen_gamma. We
543
* only do transformations on images where the file_gamma and screen_gamma
544
* are not close reciprocals, otherwise it slows things down slightly, and
545
* also needlessly introduces small errors.
547
* We will turn off gamma transformation later if no semitransparent entries
548
* are present in the tRNS array for palette images. We can't do it here
549
* because we don't necessarily have the tRNS chunk yet.
552
png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
554
png_debug(1, "in png_set_gamma");
559
if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
560
(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
561
(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
562
png_ptr->transformations |= PNG_GAMMA;
563
png_ptr->gamma = (float)file_gamma;
564
png_ptr->screen_gamma = (float)scrn_gamma;
568
#ifdef PNG_READ_EXPAND_SUPPORTED
569
/* Expand paletted images to RGB, expand grayscale images of
570
* less than 8-bit depth to 8-bit depth, and expand tRNS chunks
574
png_set_expand(png_structp png_ptr)
576
png_debug(1, "in png_set_expand");
581
png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
582
png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
585
/* GRR 19990627: the following three functions currently are identical
586
* to png_set_expand(). However, it is entirely reasonable that someone
587
* might wish to expand an indexed image to RGB but *not* expand a single,
588
* fully transparent palette entry to a full alpha channel--perhaps instead
589
* convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
590
* the transparent color with a particular RGB value, or drop tRNS entirely.
591
* IOW, a future version of the library may make the transformations flag
592
* a bit more fine-grained, with separate bits for each of these three
595
* More to the point, these functions make it obvious what libpng will be
596
* doing, whereas "expand" can (and does) mean any number of things.
598
* GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
599
* to expand only the sample depth but not to expand the tRNS to alpha
600
* and its name was changed to png_set_expand_gray_1_2_4_to_8().
603
/* Expand paletted images to RGB. */
605
png_set_palette_to_rgb(png_structp png_ptr)
607
png_debug(1, "in png_set_palette_to_rgb");
612
png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
613
png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
616
/* Expand grayscale images of less than 8-bit depth to 8 bits. */
618
png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
620
png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
625
png_ptr->transformations |= PNG_EXPAND;
626
png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
631
/* Expand tRNS chunks to alpha channels. */
633
png_set_tRNS_to_alpha(png_structp png_ptr)
635
png_debug(1, "in png_set_tRNS_to_alpha");
637
png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
638
png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
640
#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
642
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
644
png_set_gray_to_rgb(png_structp png_ptr)
646
png_debug(1, "in png_set_gray_to_rgb");
648
png_ptr->transformations |= PNG_GRAY_TO_RGB;
649
png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
653
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
654
#ifdef PNG_FLOATING_POINT_SUPPORTED
655
/* Convert a RGB image to a grayscale of the same width. This allows us,
656
* for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
660
png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
663
int red_fixed = (int)((float)red*100000.0 + 0.5);
664
int green_fixed = (int)((float)green*100000.0 + 0.5);
667
png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
672
png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
673
png_fixed_point red, png_fixed_point green)
675
png_debug(1, "in png_set_rgb_to_gray");
682
case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
685
case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
688
case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
690
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
691
#ifdef PNG_READ_EXPAND_SUPPORTED
692
png_ptr->transformations |= PNG_EXPAND;
696
"Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
697
png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
701
png_uint_16 red_int, green_int;
702
if (red < 0 || green < 0)
704
red_int = 6968; /* .212671 * 32768 + .5 */
705
green_int = 23434; /* .715160 * 32768 + .5 */
707
else if (red + green < 100000L)
709
red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
710
green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
714
png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
718
png_ptr->rgb_to_gray_red_coeff = red_int;
719
png_ptr->rgb_to_gray_green_coeff = green_int;
720
png_ptr->rgb_to_gray_blue_coeff =
721
(png_uint_16)(32768 - red_int - green_int);
726
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
727
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
729
png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
730
read_user_transform_fn)
732
png_debug(1, "in png_set_read_user_transform_fn");
737
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
738
png_ptr->transformations |= PNG_USER_TRANSFORM;
739
png_ptr->read_user_transform_fn = read_user_transform_fn;
744
/* Initialize everything needed for the read. This includes modifying
748
png_init_read_transformations(png_structp png_ptr)
750
png_debug(1, "in png_init_read_transformations");
753
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
754
defined(PNG_READ_SHIFT_SUPPORTED) || \
755
defined(PNG_READ_GAMMA_SUPPORTED)
756
int color_type = png_ptr->color_type;
759
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
761
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
762
/* Detect gray background and attempt to enable optimization
763
* for gray --> RGB case
765
* Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
766
* RGB_ALPHA (in which case need_expand is superfluous anyway), the
767
* background color might actually be gray yet not be flagged as such.
768
* This is not a problem for the current code, which uses
769
* PNG_BACKGROUND_IS_GRAY only to decide when to do the
770
* png_do_gray_to_rgb() transformation.
772
if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
773
!(color_type & PNG_COLOR_MASK_COLOR))
775
png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
776
} else if ((png_ptr->transformations & PNG_BACKGROUND) &&
777
!(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
778
(png_ptr->transformations & PNG_GRAY_TO_RGB) &&
779
png_ptr->background.red == png_ptr->background.green &&
780
png_ptr->background.red == png_ptr->background.blue)
782
png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
783
png_ptr->background.gray = png_ptr->background.red;
787
if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
788
(png_ptr->transformations & PNG_EXPAND))
790
if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
792
/* Expand background and tRNS chunks */
793
switch (png_ptr->bit_depth)
796
png_ptr->background.gray *= (png_uint_16)0xff;
797
png_ptr->background.red = png_ptr->background.green
798
= png_ptr->background.blue = png_ptr->background.gray;
799
if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
801
png_ptr->trans_color.gray *= (png_uint_16)0xff;
802
png_ptr->trans_color.red = png_ptr->trans_color.green
803
= png_ptr->trans_color.blue = png_ptr->trans_color.gray;
808
png_ptr->background.gray *= (png_uint_16)0x55;
809
png_ptr->background.red = png_ptr->background.green
810
= png_ptr->background.blue = png_ptr->background.gray;
811
if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
813
png_ptr->trans_color.gray *= (png_uint_16)0x55;
814
png_ptr->trans_color.red = png_ptr->trans_color.green
815
= png_ptr->trans_color.blue = png_ptr->trans_color.gray;
820
png_ptr->background.gray *= (png_uint_16)0x11;
821
png_ptr->background.red = png_ptr->background.green
822
= png_ptr->background.blue = png_ptr->background.gray;
823
if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
825
png_ptr->trans_color.gray *= (png_uint_16)0x11;
826
png_ptr->trans_color.red = png_ptr->trans_color.green
827
= png_ptr->trans_color.blue = png_ptr->trans_color.gray;
834
png_ptr->background.red = png_ptr->background.green
835
= png_ptr->background.blue = png_ptr->background.gray;
839
else if (color_type == PNG_COLOR_TYPE_PALETTE)
841
png_ptr->background.red =
842
png_ptr->palette[png_ptr->background.index].red;
843
png_ptr->background.green =
844
png_ptr->palette[png_ptr->background.index].green;
845
png_ptr->background.blue =
846
png_ptr->palette[png_ptr->background.index].blue;
848
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
849
if (png_ptr->transformations & PNG_INVERT_ALPHA)
851
#ifdef PNG_READ_EXPAND_SUPPORTED
852
if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
855
/* Invert the alpha channel (in tRNS) unless the pixels are
856
* going to be expanded, in which case leave it for later
859
istop=(int)png_ptr->num_trans;
860
for (i=0; i<istop; i++)
861
png_ptr->trans_alpha[i] = (png_byte)(255 - png_ptr->trans_alpha[i]);
870
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
871
png_ptr->background_1 = png_ptr->background;
873
#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
875
if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
876
&& (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
877
< PNG_GAMMA_THRESHOLD))
881
for (i=0; i<png_ptr->num_trans; i++)
883
if (png_ptr->trans_alpha[i] != 0 && png_ptr->trans_alpha[i] != 0xff)
884
k=1; /* Partial transparency is present */
887
png_ptr->transformations &= ~PNG_GAMMA;
890
if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) &&
891
png_ptr->gamma != 0.0)
893
png_build_gamma_table(png_ptr, png_ptr->bit_depth);
895
#ifdef PNG_READ_BACKGROUND_SUPPORTED
896
if (png_ptr->transformations & PNG_BACKGROUND)
898
if (color_type == PNG_COLOR_TYPE_PALETTE)
900
/* Could skip if no transparency */
901
png_color back, back_1;
902
png_colorp palette = png_ptr->palette;
903
int num_palette = png_ptr->num_palette;
905
if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
907
back.red = png_ptr->gamma_table[png_ptr->background.red];
908
back.green = png_ptr->gamma_table[png_ptr->background.green];
909
back.blue = png_ptr->gamma_table[png_ptr->background.blue];
911
back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
912
back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
913
back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
919
switch (png_ptr->background_gamma_type)
921
case PNG_BACKGROUND_GAMMA_SCREEN:
922
g = (png_ptr->screen_gamma);
926
case PNG_BACKGROUND_GAMMA_FILE:
927
g = 1.0 / (png_ptr->gamma);
928
gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
931
case PNG_BACKGROUND_GAMMA_UNIQUE:
932
g = 1.0 / (png_ptr->background_gamma);
933
gs = 1.0 / (png_ptr->background_gamma *
934
png_ptr->screen_gamma);
937
g = 1.0; /* back_1 */
941
if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
943
back.red = (png_byte)png_ptr->background.red;
944
back.green = (png_byte)png_ptr->background.green;
945
back.blue = (png_byte)png_ptr->background.blue;
949
back.red = (png_byte)(pow(
950
(double)png_ptr->background.red/255.0, gs) * 255.0 + .5);
951
back.green = (png_byte)(pow(
952
(double)png_ptr->background.green/255.0, gs) * 255.0
954
back.blue = (png_byte)(pow(
955
(double)png_ptr->background.blue/255.0, gs) * 255.0 + .5);
958
back_1.red = (png_byte)(pow(
959
(double)png_ptr->background.red/255.0, g) * 255.0 + .5);
960
back_1.green = (png_byte)(pow(
961
(double)png_ptr->background.green/255.0, g) * 255.0 + .5);
962
back_1.blue = (png_byte)(pow(
963
(double)png_ptr->background.blue/255.0, g) * 255.0 + .5);
965
for (i = 0; i < num_palette; i++)
967
if (i < (int)png_ptr->num_trans && png_ptr->trans_alpha[i] != 0xff)
969
if (png_ptr->trans_alpha[i] == 0)
973
else /* if (png_ptr->trans_alpha[i] != 0xff) */
977
v = png_ptr->gamma_to_1[palette[i].red];
978
png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
979
palette[i].red = png_ptr->gamma_from_1[w];
981
v = png_ptr->gamma_to_1[palette[i].green];
982
png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
983
palette[i].green = png_ptr->gamma_from_1[w];
985
v = png_ptr->gamma_to_1[palette[i].blue];
986
png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
987
palette[i].blue = png_ptr->gamma_from_1[w];
992
palette[i].red = png_ptr->gamma_table[palette[i].red];
993
palette[i].green = png_ptr->gamma_table[palette[i].green];
994
palette[i].blue = png_ptr->gamma_table[palette[i].blue];
997
/* Prevent the transformations being done again, and make sure
998
* that the now spurious alpha channel is stripped - the code
999
* has just reduced background composition and gamma correction
1000
* to a simple alpha channel strip.
1002
png_ptr->transformations &= ~PNG_BACKGROUND;
1003
png_ptr->transformations &= ~PNG_GAMMA;
1004
png_ptr->transformations |= PNG_STRIP_ALPHA;
1006
/* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1008
/* color_type != PNG_COLOR_TYPE_PALETTE */
1010
double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
1014
switch (png_ptr->background_gamma_type)
1016
case PNG_BACKGROUND_GAMMA_SCREEN:
1017
g = (png_ptr->screen_gamma);
1021
case PNG_BACKGROUND_GAMMA_FILE:
1022
g = 1.0 / (png_ptr->gamma);
1023
gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
1026
case PNG_BACKGROUND_GAMMA_UNIQUE:
1027
g = 1.0 / (png_ptr->background_gamma);
1028
gs = 1.0 / (png_ptr->background_gamma *
1029
png_ptr->screen_gamma);
1033
png_ptr->background_1.gray = (png_uint_16)(pow(
1034
(double)png_ptr->background.gray / m, g) * m + .5);
1035
png_ptr->background.gray = (png_uint_16)(pow(
1036
(double)png_ptr->background.gray / m, gs) * m + .5);
1038
if ((png_ptr->background.red != png_ptr->background.green) ||
1039
(png_ptr->background.red != png_ptr->background.blue) ||
1040
(png_ptr->background.red != png_ptr->background.gray))
1042
/* RGB or RGBA with color background */
1043
png_ptr->background_1.red = (png_uint_16)(pow(
1044
(double)png_ptr->background.red / m, g) * m + .5);
1045
png_ptr->background_1.green = (png_uint_16)(pow(
1046
(double)png_ptr->background.green / m, g) * m + .5);
1047
png_ptr->background_1.blue = (png_uint_16)(pow(
1048
(double)png_ptr->background.blue / m, g) * m + .5);
1049
png_ptr->background.red = (png_uint_16)(pow(
1050
(double)png_ptr->background.red / m, gs) * m + .5);
1051
png_ptr->background.green = (png_uint_16)(pow(
1052
(double)png_ptr->background.green / m, gs) * m + .5);
1053
png_ptr->background.blue = (png_uint_16)(pow(
1054
(double)png_ptr->background.blue / m, gs) * m + .5);
1058
/* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
1059
png_ptr->background_1.red = png_ptr->background_1.green
1060
= png_ptr->background_1.blue = png_ptr->background_1.gray;
1061
png_ptr->background.red = png_ptr->background.green
1062
= png_ptr->background.blue = png_ptr->background.gray;
1067
/* Transformation does not include PNG_BACKGROUND */
1068
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
1069
if (color_type == PNG_COLOR_TYPE_PALETTE)
1071
png_colorp palette = png_ptr->palette;
1072
int num_palette = png_ptr->num_palette;
1075
for (i = 0; i < num_palette; i++)
1077
palette[i].red = png_ptr->gamma_table[palette[i].red];
1078
palette[i].green = png_ptr->gamma_table[palette[i].green];
1079
palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1082
/* Done the gamma correction. */
1083
png_ptr->transformations &= ~PNG_GAMMA;
1086
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1089
#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
1090
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1091
/* No GAMMA transformation */
1092
if ((png_ptr->transformations & PNG_BACKGROUND) &&
1093
(color_type == PNG_COLOR_TYPE_PALETTE))
1096
int istop = (int)png_ptr->num_trans;
1098
png_colorp palette = png_ptr->palette;
1100
back.red = (png_byte)png_ptr->background.red;
1101
back.green = (png_byte)png_ptr->background.green;
1102
back.blue = (png_byte)png_ptr->background.blue;
1104
for (i = 0; i < istop; i++)
1106
if (png_ptr->trans_alpha[i] == 0)
1110
else if (png_ptr->trans_alpha[i] != 0xff)
1112
/* The png_composite() macro is defined in png.h */
1113
png_composite(palette[i].red, palette[i].red,
1114
png_ptr->trans_alpha[i], back.red);
1115
png_composite(palette[i].green, palette[i].green,
1116
png_ptr->trans_alpha[i], back.green);
1117
png_composite(palette[i].blue, palette[i].blue,
1118
png_ptr->trans_alpha[i], back.blue);
1122
/* Handled alpha, still need to strip the channel. */
1123
png_ptr->transformations &= ~PNG_BACKGROUND;
1124
png_ptr->transformations |= PNG_STRIP_ALPHA;
1126
#endif /* PNG_READ_BACKGROUND_SUPPORTED */
1128
#ifdef PNG_READ_SHIFT_SUPPORTED
1129
if ((png_ptr->transformations & PNG_SHIFT) &&
1130
(color_type == PNG_COLOR_TYPE_PALETTE))
1133
png_uint_16 istop = png_ptr->num_palette;
1134
int sr = 8 - png_ptr->sig_bit.red;
1135
int sg = 8 - png_ptr->sig_bit.green;
1136
int sb = 8 - png_ptr->sig_bit.blue;
1138
if (sr < 0 || sr > 8)
1140
if (sg < 0 || sg > 8)
1142
if (sb < 0 || sb > 8)
1144
for (i = 0; i < istop; i++)
1146
png_ptr->palette[i].red >>= sr;
1147
png_ptr->palette[i].green >>= sg;
1148
png_ptr->palette[i].blue >>= sb;
1151
#endif /* PNG_READ_SHIFT_SUPPORTED */
1153
#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1154
&& !defined(PNG_READ_BACKGROUND_SUPPORTED)
1160
/* Modify the info structure to reflect the transformations. The
1161
* info should be updated so a PNG file could be written with it,
1162
* assuming the transformations result in valid PNG data.
1165
png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
1167
png_debug(1, "in png_read_transform_info");
1169
#ifdef PNG_READ_EXPAND_SUPPORTED
1170
if (png_ptr->transformations & PNG_EXPAND)
1172
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1174
if (png_ptr->num_trans &&
1175
(png_ptr->transformations & PNG_EXPAND_tRNS))
1176
info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1178
info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1179
info_ptr->bit_depth = 8;
1180
info_ptr->num_trans = 0;
1184
if (png_ptr->num_trans)
1186
if (png_ptr->transformations & PNG_EXPAND_tRNS)
1187
info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1189
if (info_ptr->bit_depth < 8)
1190
info_ptr->bit_depth = 8;
1191
info_ptr->num_trans = 0;
1196
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1197
if (png_ptr->transformations & PNG_BACKGROUND)
1199
info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1200
info_ptr->num_trans = 0;
1201
info_ptr->background = png_ptr->background;
1205
#ifdef PNG_READ_GAMMA_SUPPORTED
1206
if (png_ptr->transformations & PNG_GAMMA)
1208
#ifdef PNG_FLOATING_POINT_SUPPORTED
1209
info_ptr->gamma = png_ptr->gamma;
1211
#ifdef PNG_FIXED_POINT_SUPPORTED
1212
info_ptr->int_gamma = png_ptr->int_gamma;
1217
#ifdef PNG_READ_16_TO_8_SUPPORTED
1218
if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
1219
info_ptr->bit_depth = 8;
1222
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1223
if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1224
info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1227
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1228
if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1229
info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1232
#ifdef PNG_READ_QUANTIZE_SUPPORTED
1233
if (png_ptr->transformations & PNG_QUANTIZE)
1235
if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1236
(info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1237
png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1239
info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1244
#ifdef PNG_READ_PACK_SUPPORTED
1245
if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
1246
info_ptr->bit_depth = 8;
1249
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1250
info_ptr->channels = 1;
1251
else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1252
info_ptr->channels = 3;
1254
info_ptr->channels = 1;
1256
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1257
if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1258
info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1261
if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1262
info_ptr->channels++;
1264
#ifdef PNG_READ_FILLER_SUPPORTED
1265
/* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
1266
if ((png_ptr->transformations & PNG_FILLER) &&
1267
((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1268
(info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1270
info_ptr->channels++;
1271
/* If adding a true alpha channel not just filler */
1272
if (png_ptr->transformations & PNG_ADD_ALPHA)
1273
info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1277
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1278
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1279
if (png_ptr->transformations & PNG_USER_TRANSFORM)
1281
if (info_ptr->bit_depth < png_ptr->user_transform_depth)
1282
info_ptr->bit_depth = png_ptr->user_transform_depth;
1283
if (info_ptr->channels < png_ptr->user_transform_channels)
1284
info_ptr->channels = png_ptr->user_transform_channels;
1288
info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1289
info_ptr->bit_depth);
1291
info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
1293
#ifndef PNG_READ_EXPAND_SUPPORTED
1299
/* Transform the row. The order of transformations is significant,
1300
* and is very touchy. If you add a transformation, take care to
1301
* decide how it fits in with the other transformations here.
1304
png_do_read_transformations(png_structp png_ptr)
1306
png_debug(1, "in png_do_read_transformations");
1308
if (png_ptr->row_buf == NULL)
1310
#ifdef PNG_STDIO_SUPPORTED
1313
png_snprintf2(msg, 50,
1314
"NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number,
1316
png_error(png_ptr, msg);
1318
png_error(png_ptr, "NULL row buffer");
1321
#ifdef PNG_WARN_UNINITIALIZED_ROW
1322
if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
1323
/* Application has failed to call either png_read_start_image()
1324
* or png_read_update_info() after setting transforms that expand
1325
* pixels. This check added to libpng-1.2.19
1327
#if (PNG_WARN_UNINITIALIZED_ROW==1)
1328
png_error(png_ptr, "Uninitialized row");
1330
png_warning(png_ptr, "Uninitialized row");
1334
#ifdef PNG_READ_EXPAND_SUPPORTED
1335
if (png_ptr->transformations & PNG_EXPAND)
1337
if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1339
png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1340
png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
1344
if (png_ptr->num_trans &&
1345
(png_ptr->transformations & PNG_EXPAND_tRNS))
1346
png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1347
&(png_ptr->trans_color));
1349
png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1355
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1356
if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1357
png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1358
PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
1361
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1362
if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1365
png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info),
1366
png_ptr->row_buf + 1);
1369
png_ptr->rgb_to_gray_status=1;
1370
if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
1371
PNG_RGB_TO_GRAY_WARN)
1372
png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1373
if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
1374
PNG_RGB_TO_GRAY_ERR)
1375
png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1380
/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
1382
* In most cases, the "simple transparency" should be done prior to doing
1383
* gray-to-RGB, or you will have to test 3x as many bytes to check if a
1384
* pixel is transparent. You would also need to make sure that the
1385
* transparency information is upgraded to RGB.
1387
* To summarize, the current flow is:
1388
* - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1389
* with background "in place" if transparent,
1390
* convert to RGB if necessary
1391
* - Gray + alpha -> composite with gray background and remove alpha bytes,
1392
* convert to RGB if necessary
1394
* To support RGB backgrounds for gray images we need:
1395
* - Gray + simple transparency -> convert to RGB + simple transparency,
1396
* compare 3 or 6 bytes and composite with
1397
* background "in place" if transparent
1398
* (3x compare/pixel compared to doing
1399
* composite with gray bkgrnd)
1400
* - Gray + alpha -> convert to RGB + alpha, composite with background and
1401
* remove alpha bytes (3x float
1402
* operations/pixel compared with composite
1403
* on gray background)
1405
* Greg's change will do this. The reason it wasn't done before is for
1406
* performance, as this increases the per-pixel operations. If we would check
1407
* in advance if the background was gray or RGB, and position the gray-to-RGB
1408
* transform appropriately, then it would save a lot of work/time.
1411
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1412
/* If gray -> RGB, do so now only if background is non-gray; else do later
1413
* for performance reasons
1415
if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1416
!(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1417
png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1420
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1421
if ((png_ptr->transformations & PNG_BACKGROUND) &&
1422
((png_ptr->num_trans != 0 ) ||
1423
(png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
1424
png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1425
&(png_ptr->trans_color), &(png_ptr->background)
1426
#ifdef PNG_READ_GAMMA_SUPPORTED
1427
, &(png_ptr->background_1),
1428
png_ptr->gamma_table, png_ptr->gamma_from_1,
1429
png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1430
png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1431
png_ptr->gamma_shift
1436
#ifdef PNG_READ_GAMMA_SUPPORTED
1437
if ((png_ptr->transformations & PNG_GAMMA) &&
1438
#ifdef PNG_READ_BACKGROUND_SUPPORTED
1439
!((png_ptr->transformations & PNG_BACKGROUND) &&
1440
((png_ptr->num_trans != 0) ||
1441
(png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1443
(png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
1444
png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1445
png_ptr->gamma_table, png_ptr->gamma_16_table,
1446
png_ptr->gamma_shift);
1449
#ifdef PNG_READ_16_TO_8_SUPPORTED
1450
if (png_ptr->transformations & PNG_16_TO_8)
1451
png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
1454
#ifdef PNG_READ_QUANTIZE_SUPPORTED
1455
if (png_ptr->transformations & PNG_QUANTIZE)
1457
png_do_quantize((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1458
png_ptr->palette_lookup, png_ptr->quantize_index);
1459
if (png_ptr->row_info.rowbytes == (png_uint_32)0)
1460
png_error(png_ptr, "png_do_quantize returned rowbytes=0");
1464
#ifdef PNG_READ_INVERT_SUPPORTED
1465
if (png_ptr->transformations & PNG_INVERT_MONO)
1466
png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
1469
#ifdef PNG_READ_SHIFT_SUPPORTED
1470
if (png_ptr->transformations & PNG_SHIFT)
1471
png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1475
#ifdef PNG_READ_PACK_SUPPORTED
1476
if (png_ptr->transformations & PNG_PACK)
1477
png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
1480
#ifdef PNG_READ_BGR_SUPPORTED
1481
if (png_ptr->transformations & PNG_BGR)
1482
png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
1485
#ifdef PNG_READ_PACKSWAP_SUPPORTED
1486
if (png_ptr->transformations & PNG_PACKSWAP)
1487
png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1490
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1491
/* If gray -> RGB, do so now only if we did not do so above */
1492
if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1493
(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1494
png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1497
#ifdef PNG_READ_FILLER_SUPPORTED
1498
if (png_ptr->transformations & PNG_FILLER)
1499
png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1500
(png_uint_32)png_ptr->filler, png_ptr->flags);
1503
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
1504
if (png_ptr->transformations & PNG_INVERT_ALPHA)
1505
png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1508
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
1509
if (png_ptr->transformations & PNG_SWAP_ALPHA)
1510
png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1513
#ifdef PNG_READ_SWAP_SUPPORTED
1514
if (png_ptr->transformations & PNG_SWAP_BYTES)
1515
png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1518
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
1519
if (png_ptr->transformations & PNG_USER_TRANSFORM)
1521
if (png_ptr->read_user_transform_fn != NULL)
1522
(*(png_ptr->read_user_transform_fn)) /* User read transform function */
1523
(png_ptr, /* png_ptr */
1524
&(png_ptr->row_info), /* row_info: */
1525
/* png_uint_32 width; width of row */
1526
/* png_uint_32 rowbytes; number of bytes in row */
1527
/* png_byte color_type; color type of pixels */
1528
/* png_byte bit_depth; bit depth of samples */
1529
/* png_byte channels; number of channels (1-4) */
1530
/* png_byte pixel_depth; bits per pixel (depth*channels) */
1531
png_ptr->row_buf + 1); /* start of pixel data for row */
1532
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
1533
if (png_ptr->user_transform_depth)
1534
png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1535
if (png_ptr->user_transform_channels)
1536
png_ptr->row_info.channels = png_ptr->user_transform_channels;
1538
png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1539
png_ptr->row_info.channels);
1540
png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
1541
png_ptr->row_info.width);
1547
#ifdef PNG_READ_PACK_SUPPORTED
1548
/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1549
* without changing the actual values. Thus, if you had a row with
1550
* a bit depth of 1, you would end up with bytes that only contained
1551
* the numbers 0 or 1. If you would rather they contain 0 and 255, use
1552
* png_do_shift() after this.
1555
png_do_unpack(png_row_infop row_info, png_bytep row)
1557
png_debug(1, "in png_do_unpack");
1559
if (row_info->bit_depth < 8)
1562
png_uint_32 row_width=row_info->width;
1564
switch (row_info->bit_depth)
1568
png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1569
png_bytep dp = row + (png_size_t)row_width - 1;
1570
png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
1571
for (i = 0; i < row_width; i++)
1573
*dp = (png_byte)((*sp >> shift) & 0x01);
1590
png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1591
png_bytep dp = row + (png_size_t)row_width - 1;
1592
png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
1593
for (i = 0; i < row_width; i++)
1595
*dp = (png_byte)((*sp >> shift) & 0x03);
1611
png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1612
png_bytep dp = row + (png_size_t)row_width - 1;
1613
png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
1614
for (i = 0; i < row_width; i++)
1616
*dp = (png_byte)((*sp >> shift) & 0x0f);
1630
row_info->bit_depth = 8;
1631
row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1632
row_info->rowbytes = row_width * row_info->channels;
1637
#ifdef PNG_READ_SHIFT_SUPPORTED
1638
/* Reverse the effects of png_do_shift. This routine merely shifts the
1639
* pixels back to their significant bits values. Thus, if you have
1640
* a row of bit depth 8, but only 5 are significant, this will shift
1641
* the values back to 0 through 31.
1644
png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
1646
png_debug(1, "in png_do_unshift");
1649
row_info->color_type != PNG_COLOR_TYPE_PALETTE)
1654
png_uint_16 value = 0;
1655
png_uint_32 row_width = row_info->width;
1657
if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1659
shift[channels++] = row_info->bit_depth - sig_bits->red;
1660
shift[channels++] = row_info->bit_depth - sig_bits->green;
1661
shift[channels++] = row_info->bit_depth - sig_bits->blue;
1665
shift[channels++] = row_info->bit_depth - sig_bits->gray;
1667
if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1669
shift[channels++] = row_info->bit_depth - sig_bits->alpha;
1672
for (c = 0; c < channels; c++)
1683
switch (row_info->bit_depth)
1689
png_uint_32 istop = row_info->rowbytes;
1691
for (bp = row, i = 0; i < istop; i++)
1703
png_uint_32 istop = row_info->rowbytes;
1704
png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1705
(png_byte)((int)0xf >> shift[0]));
1707
for (i = 0; i < istop; i++)
1719
png_uint_32 istop = row_width * channels;
1721
for (i = 0; i < istop; i++)
1723
*bp++ >>= shift[i%channels];
1732
png_uint_32 istop = channels * row_width;
1734
for (i = 0; i < istop; i++)
1736
value = (png_uint_16)((*bp << 8) + *(bp + 1));
1737
value >>= shift[i%channels];
1738
*bp++ = (png_byte)(value >> 8);
1739
*bp++ = (png_byte)(value & 0xff);
1748
#ifdef PNG_READ_16_TO_8_SUPPORTED
1749
/* Chop rows of bit depth 16 down to 8 */
1751
png_do_chop(png_row_infop row_info, png_bytep row)
1753
png_debug(1, "in png_do_chop");
1755
if (row_info->bit_depth == 16)
1760
png_uint_32 istop = row_info->width * row_info->channels;
1762
for (i = 0; i<istop; i++, sp += 2, dp++)
1764
#ifdef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
1765
/* This does a more accurate scaling of the 16-bit color
1766
* value, rather than a simple low-byte truncation.
1768
* What the ideal calculation should be:
1769
* *dp = (((((png_uint_32)(*sp) << 8) |
1770
* (png_uint_32)(*(sp + 1))) * 255 + 127)
1771
* / (png_uint_32)65535L;
1773
* GRR: no, I think this is what it really should be:
1774
* *dp = (((((png_uint_32)(*sp) << 8) |
1775
* (png_uint_32)(*(sp + 1))) + 128L)
1776
* / (png_uint_32)257L;
1778
* GRR: here's the exact calculation with shifts:
1779
* temp = (((png_uint_32)(*sp) << 8) |
1780
* (png_uint_32)(*(sp + 1))) + 128L;
1781
* *dp = (temp - (temp >> 8)) >> 8;
1783
* Approximate calculation with shift/add instead of multiply/divide:
1784
* *dp = ((((png_uint_32)(*sp) << 8) |
1785
* (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1787
* What we actually do to avoid extra shifting and conversion:
1790
*dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1792
/* Simply discard the low order byte */
1796
row_info->bit_depth = 8;
1797
row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1798
row_info->rowbytes = row_info->width * row_info->channels;
1803
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
1805
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1807
png_debug(1, "in png_do_read_swap_alpha");
1810
png_uint_32 row_width = row_info->width;
1811
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1813
/* This converts from RGBA to ARGB */
1814
if (row_info->bit_depth == 8)
1816
png_bytep sp = row + row_info->rowbytes;
1821
for (i = 0; i < row_width; i++)
1830
/* This converts from RRGGBBAA to AARRGGBB */
1833
png_bytep sp = row + row_info->rowbytes;
1838
for (i = 0; i < row_width; i++)
1853
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1855
/* This converts from GA to AG */
1856
if (row_info->bit_depth == 8)
1858
png_bytep sp = row + row_info->rowbytes;
1863
for (i = 0; i < row_width; i++)
1870
/* This converts from GGAA to AAGG */
1873
png_bytep sp = row + row_info->rowbytes;
1878
for (i = 0; i < row_width; i++)
1893
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
1895
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1897
png_debug(1, "in png_do_read_invert_alpha");
1900
png_uint_32 row_width = row_info->width;
1901
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1903
/* This inverts the alpha channel in RGBA */
1904
if (row_info->bit_depth == 8)
1906
png_bytep sp = row + row_info->rowbytes;
1910
for (i = 0; i < row_width; i++)
1912
*(--dp) = (png_byte)(255 - *(--sp));
1914
/* This does nothing:
1918
We can replace it with:
1924
/* This inverts the alpha channel in RRGGBBAA */
1927
png_bytep sp = row + row_info->rowbytes;
1931
for (i = 0; i < row_width; i++)
1933
*(--dp) = (png_byte)(255 - *(--sp));
1934
*(--dp) = (png_byte)(255 - *(--sp));
1936
/* This does nothing:
1943
We can replace it with:
1950
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1952
/* This inverts the alpha channel in GA */
1953
if (row_info->bit_depth == 8)
1955
png_bytep sp = row + row_info->rowbytes;
1959
for (i = 0; i < row_width; i++)
1961
*(--dp) = (png_byte)(255 - *(--sp));
1965
/* This inverts the alpha channel in GGAA */
1968
png_bytep sp = row + row_info->rowbytes;
1972
for (i = 0; i < row_width; i++)
1974
*(--dp) = (png_byte)(255 - *(--sp));
1975
*(--dp) = (png_byte)(255 - *(--sp));
1989
#ifdef PNG_READ_FILLER_SUPPORTED
1990
/* Add filler channel if we have RGB color */
1992
png_do_read_filler(png_row_infop row_info, png_bytep row,
1993
png_uint_32 filler, png_uint_32 flags)
1996
png_uint_32 row_width = row_info->width;
1998
png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
1999
png_byte lo_filler = (png_byte)(filler & 0xff);
2001
png_debug(1, "in png_do_read_filler");
2004
row_info->color_type == PNG_COLOR_TYPE_GRAY)
2006
if (row_info->bit_depth == 8)
2008
/* This changes the data from G to GX */
2009
if (flags & PNG_FLAG_FILLER_AFTER)
2011
png_bytep sp = row + (png_size_t)row_width;
2012
png_bytep dp = sp + (png_size_t)row_width;
2013
for (i = 1; i < row_width; i++)
2015
*(--dp) = lo_filler;
2018
*(--dp) = lo_filler;
2019
row_info->channels = 2;
2020
row_info->pixel_depth = 16;
2021
row_info->rowbytes = row_width * 2;
2023
/* This changes the data from G to XG */
2026
png_bytep sp = row + (png_size_t)row_width;
2027
png_bytep dp = sp + (png_size_t)row_width;
2028
for (i = 0; i < row_width; i++)
2031
*(--dp) = lo_filler;
2033
row_info->channels = 2;
2034
row_info->pixel_depth = 16;
2035
row_info->rowbytes = row_width * 2;
2038
else if (row_info->bit_depth == 16)
2040
/* This changes the data from GG to GGXX */
2041
if (flags & PNG_FLAG_FILLER_AFTER)
2043
png_bytep sp = row + (png_size_t)row_width * 2;
2044
png_bytep dp = sp + (png_size_t)row_width * 2;
2045
for (i = 1; i < row_width; i++)
2047
*(--dp) = hi_filler;
2048
*(--dp) = lo_filler;
2052
*(--dp) = hi_filler;
2053
*(--dp) = lo_filler;
2054
row_info->channels = 2;
2055
row_info->pixel_depth = 32;
2056
row_info->rowbytes = row_width * 4;
2058
/* This changes the data from GG to XXGG */
2061
png_bytep sp = row + (png_size_t)row_width * 2;
2062
png_bytep dp = sp + (png_size_t)row_width * 2;
2063
for (i = 0; i < row_width; i++)
2067
*(--dp) = hi_filler;
2068
*(--dp) = lo_filler;
2070
row_info->channels = 2;
2071
row_info->pixel_depth = 32;
2072
row_info->rowbytes = row_width * 4;
2075
} /* COLOR_TYPE == GRAY */
2076
else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2078
if (row_info->bit_depth == 8)
2080
/* This changes the data from RGB to RGBX */
2081
if (flags & PNG_FLAG_FILLER_AFTER)
2083
png_bytep sp = row + (png_size_t)row_width * 3;
2084
png_bytep dp = sp + (png_size_t)row_width;
2085
for (i = 1; i < row_width; i++)
2087
*(--dp) = lo_filler;
2092
*(--dp) = lo_filler;
2093
row_info->channels = 4;
2094
row_info->pixel_depth = 32;
2095
row_info->rowbytes = row_width * 4;
2097
/* This changes the data from RGB to XRGB */
2100
png_bytep sp = row + (png_size_t)row_width * 3;
2101
png_bytep dp = sp + (png_size_t)row_width;
2102
for (i = 0; i < row_width; i++)
2107
*(--dp) = lo_filler;
2109
row_info->channels = 4;
2110
row_info->pixel_depth = 32;
2111
row_info->rowbytes = row_width * 4;
2114
else if (row_info->bit_depth == 16)
2116
/* This changes the data from RRGGBB to RRGGBBXX */
2117
if (flags & PNG_FLAG_FILLER_AFTER)
2119
png_bytep sp = row + (png_size_t)row_width * 6;
2120
png_bytep dp = sp + (png_size_t)row_width * 2;
2121
for (i = 1; i < row_width; i++)
2123
*(--dp) = hi_filler;
2124
*(--dp) = lo_filler;
2132
*(--dp) = hi_filler;
2133
*(--dp) = lo_filler;
2134
row_info->channels = 4;
2135
row_info->pixel_depth = 64;
2136
row_info->rowbytes = row_width * 8;
2138
/* This changes the data from RRGGBB to XXRRGGBB */
2141
png_bytep sp = row + (png_size_t)row_width * 6;
2142
png_bytep dp = sp + (png_size_t)row_width * 2;
2143
for (i = 0; i < row_width; i++)
2151
*(--dp) = hi_filler;
2152
*(--dp) = lo_filler;
2154
row_info->channels = 4;
2155
row_info->pixel_depth = 64;
2156
row_info->rowbytes = row_width * 8;
2159
} /* COLOR_TYPE == RGB */
2163
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
2164
/* Expand grayscale files to RGB, with or without alpha */
2166
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
2169
png_uint_32 row_width = row_info->width;
2171
png_debug(1, "in png_do_gray_to_rgb");
2173
if (row_info->bit_depth >= 8 &&
2174
!(row_info->color_type & PNG_COLOR_MASK_COLOR))
2176
if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2178
if (row_info->bit_depth == 8)
2180
png_bytep sp = row + (png_size_t)row_width - 1;
2181
png_bytep dp = sp + (png_size_t)row_width * 2;
2182
for (i = 0; i < row_width; i++)
2191
png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2192
png_bytep dp = sp + (png_size_t)row_width * 4;
2193
for (i = 0; i < row_width; i++)
2196
*(dp--) = *(sp - 1);
2198
*(dp--) = *(sp - 1);
2204
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2206
if (row_info->bit_depth == 8)
2208
png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2209
png_bytep dp = sp + (png_size_t)row_width * 2;
2210
for (i = 0; i < row_width; i++)
2220
png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2221
png_bytep dp = sp + (png_size_t)row_width * 4;
2222
for (i = 0; i < row_width; i++)
2227
*(dp--) = *(sp - 1);
2229
*(dp--) = *(sp - 1);
2235
row_info->channels += (png_byte)2;
2236
row_info->color_type |= PNG_COLOR_MASK_COLOR;
2237
row_info->pixel_depth = (png_byte)(row_info->channels *
2238
row_info->bit_depth);
2239
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2244
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2245
/* Reduce RGB files to grayscale, with or without alpha
2246
* using the equation given in Poynton's ColorFAQ at
2247
* <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008)
2249
* <http://www.poynton.com/notes/colour_and_gamma/>
2250
* Charles Poynton poynton at poynton.com
2252
* Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2254
* We approximate this with
2256
* Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
2258
* which can be expressed with integers as
2260
* Y = (6969 * R + 23434 * G + 2365 * B)/32768
2262
* The calculation is to be done in a linear colorspace.
2264
* Other integer coefficents can be used via png_set_rgb_to_gray().
2267
png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2272
png_uint_32 row_width = row_info->width;
2275
png_debug(1, "in png_do_rgb_to_gray");
2278
(row_info->color_type & PNG_COLOR_MASK_COLOR))
2280
png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2281
png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2282
png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
2284
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2286
if (row_info->bit_depth == 8)
2288
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2289
if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2294
for (i = 0; i < row_width; i++)
2296
png_byte red = png_ptr->gamma_to_1[*(sp++)];
2297
png_byte green = png_ptr->gamma_to_1[*(sp++)];
2298
png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2299
if (red != green || red != blue)
2302
*(dp++) = png_ptr->gamma_from_1[
2303
(rc*red + gc*green + bc*blue)>>15];
2306
*(dp++) = *(sp - 1);
2314
for (i = 0; i < row_width; i++)
2316
png_byte red = *(sp++);
2317
png_byte green = *(sp++);
2318
png_byte blue = *(sp++);
2319
if (red != green || red != blue)
2322
*(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
2325
*(dp++) = *(sp - 1);
2330
else /* RGB bit_depth == 16 */
2332
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2333
if (png_ptr->gamma_16_to_1 != NULL &&
2334
png_ptr->gamma_16_from_1 != NULL)
2338
for (i = 0; i < row_width; i++)
2340
png_uint_16 red, green, blue, w;
2342
red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2343
green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2344
blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2346
if (red == green && red == blue)
2350
png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2351
png_ptr->gamma_shift][red>>8];
2352
png_uint_16 green_1 =
2353
png_ptr->gamma_16_to_1[(green&0xff) >>
2354
png_ptr->gamma_shift][green>>8];
2355
png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2356
png_ptr->gamma_shift][blue>>8];
2357
png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
2359
w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2360
png_ptr->gamma_shift][gray16 >> 8];
2364
*(dp++) = (png_byte)((w>>8) & 0xff);
2365
*(dp++) = (png_byte)(w & 0xff);
2373
for (i = 0; i < row_width; i++)
2375
png_uint_16 red, green, blue, gray16;
2377
red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2378
green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2379
blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2381
if (red != green || red != blue)
2383
gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2384
*(dp++) = (png_byte)((gray16>>8) & 0xff);
2385
*(dp++) = (png_byte)(gray16 & 0xff);
2390
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2392
if (row_info->bit_depth == 8)
2394
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2395
if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2399
for (i = 0; i < row_width; i++)
2401
png_byte red = png_ptr->gamma_to_1[*(sp++)];
2402
png_byte green = png_ptr->gamma_to_1[*(sp++)];
2403
png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2404
if (red != green || red != blue)
2406
*(dp++) = png_ptr->gamma_from_1
2407
[(rc*red + gc*green + bc*blue)>>15];
2408
*(dp++) = *(sp++); /* alpha */
2416
for (i = 0; i < row_width; i++)
2418
png_byte red = *(sp++);
2419
png_byte green = *(sp++);
2420
png_byte blue = *(sp++);
2421
if (red != green || red != blue)
2423
*(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
2424
*(dp++) = *(sp++); /* alpha */
2428
else /* RGBA bit_depth == 16 */
2430
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2431
if (png_ptr->gamma_16_to_1 != NULL &&
2432
png_ptr->gamma_16_from_1 != NULL)
2436
for (i = 0; i < row_width; i++)
2438
png_uint_16 red, green, blue, w;
2440
red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2441
green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2442
blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2444
if (red == green && red == blue)
2448
png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2449
png_ptr->gamma_shift][red>>8];
2450
png_uint_16 green_1 =
2451
png_ptr->gamma_16_to_1[(green&0xff) >>
2452
png_ptr->gamma_shift][green>>8];
2453
png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2454
png_ptr->gamma_shift][blue>>8];
2455
png_uint_16 gray16 = (png_uint_16)((rc * red_1
2456
+ gc * green_1 + bc * blue_1)>>15);
2457
w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2458
png_ptr->gamma_shift][gray16 >> 8];
2462
*(dp++) = (png_byte)((w>>8) & 0xff);
2463
*(dp++) = (png_byte)(w & 0xff);
2464
*(dp++) = *(sp++); /* alpha */
2473
for (i = 0; i < row_width; i++)
2475
png_uint_16 red, green, blue, gray16;
2476
red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2477
green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2478
blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2479
if (red != green || red != blue)
2481
gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2482
*(dp++) = (png_byte)((gray16>>8) & 0xff);
2483
*(dp++) = (png_byte)(gray16 & 0xff);
2484
*(dp++) = *(sp++); /* alpha */
2490
row_info->channels -= (png_byte)2;
2491
row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2492
row_info->pixel_depth = (png_byte)(row_info->channels *
2493
row_info->bit_depth);
2494
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2500
/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
2501
* large of png_color. This lets grayscale images be treated as
2502
* paletted. Most useful for gamma correction and simplification
2506
png_build_grayscale_palette(int bit_depth, png_colorp palette)
2513
png_debug(1, "in png_do_build_grayscale_palette");
2515
if (palette == NULL)
2546
for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2548
palette[i].red = (png_byte)v;
2549
palette[i].green = (png_byte)v;
2550
palette[i].blue = (png_byte)v;
2555
#ifdef PNG_READ_BACKGROUND_SUPPORTED
2556
/* Replace any alpha or transparency with the supplied background color.
2557
* "background" is already in the screen gamma, while "background_1" is
2558
* at a gamma of 1.0. Paletted files have already been taken care of.
2561
png_do_background(png_row_infop row_info, png_bytep row,
2562
png_color_16p trans_color, png_color_16p background
2563
#ifdef PNG_READ_GAMMA_SUPPORTED
2564
, png_color_16p background_1,
2565
png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
2566
png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2567
png_uint_16pp gamma_16_to_1, int gamma_shift
2573
png_uint_32 row_width=row_info->width;
2576
png_debug(1, "in png_do_background");
2578
if (background != NULL &&
2579
(!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
2580
(row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_color)))
2582
switch (row_info->color_type)
2584
case PNG_COLOR_TYPE_GRAY:
2586
switch (row_info->bit_depth)
2592
for (i = 0; i < row_width; i++)
2594
if ((png_uint_16)((*sp >> shift) & 0x01)
2595
== trans_color->gray)
2597
*sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2598
*sp |= (png_byte)(background->gray << shift);
2613
#ifdef PNG_READ_GAMMA_SUPPORTED
2614
if (gamma_table != NULL)
2618
for (i = 0; i < row_width; i++)
2620
if ((png_uint_16)((*sp >> shift) & 0x03)
2621
== trans_color->gray)
2623
*sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2624
*sp |= (png_byte)(background->gray << shift);
2628
png_byte p = (png_byte)((*sp >> shift) & 0x03);
2629
png_byte g = (png_byte)((gamma_table [p | (p << 2) |
2630
(p << 4) | (p << 6)] >> 6) & 0x03);
2631
*sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2632
*sp |= (png_byte)(g << shift);
2648
for (i = 0; i < row_width; i++)
2650
if ((png_uint_16)((*sp >> shift) & 0x03)
2651
== trans_color->gray)
2653
*sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2654
*sp |= (png_byte)(background->gray << shift);
2670
#ifdef PNG_READ_GAMMA_SUPPORTED
2671
if (gamma_table != NULL)
2675
for (i = 0; i < row_width; i++)
2677
if ((png_uint_16)((*sp >> shift) & 0x0f)
2678
== trans_color->gray)
2680
*sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2681
*sp |= (png_byte)(background->gray << shift);
2685
png_byte p = (png_byte)((*sp >> shift) & 0x0f);
2686
png_byte g = (png_byte)((gamma_table[p |
2687
(p << 4)] >> 4) & 0x0f);
2688
*sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2689
*sp |= (png_byte)(g << shift);
2705
for (i = 0; i < row_width; i++)
2707
if ((png_uint_16)((*sp >> shift) & 0x0f)
2708
== trans_color->gray)
2710
*sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2711
*sp |= (png_byte)(background->gray << shift);
2727
#ifdef PNG_READ_GAMMA_SUPPORTED
2728
if (gamma_table != NULL)
2731
for (i = 0; i < row_width; i++, sp++)
2733
if (*sp == trans_color->gray)
2735
*sp = (png_byte)background->gray;
2739
*sp = gamma_table[*sp];
2747
for (i = 0; i < row_width; i++, sp++)
2749
if (*sp == trans_color->gray)
2751
*sp = (png_byte)background->gray;
2760
#ifdef PNG_READ_GAMMA_SUPPORTED
2761
if (gamma_16 != NULL)
2764
for (i = 0; i < row_width; i++, sp += 2)
2768
v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2769
if (v == trans_color->gray)
2771
/* Background is already in screen gamma */
2772
*sp = (png_byte)((background->gray >> 8) & 0xff);
2773
*(sp + 1) = (png_byte)(background->gray & 0xff);
2777
v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2778
*sp = (png_byte)((v >> 8) & 0xff);
2779
*(sp + 1) = (png_byte)(v & 0xff);
2787
for (i = 0; i < row_width; i++, sp += 2)
2791
v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2792
if (v == trans_color->gray)
2794
*sp = (png_byte)((background->gray >> 8) & 0xff);
2795
*(sp + 1) = (png_byte)(background->gray & 0xff);
2805
case PNG_COLOR_TYPE_RGB:
2807
if (row_info->bit_depth == 8)
2809
#ifdef PNG_READ_GAMMA_SUPPORTED
2810
if (gamma_table != NULL)
2813
for (i = 0; i < row_width; i++, sp += 3)
2815
if (*sp == trans_color->red &&
2816
*(sp + 1) == trans_color->green &&
2817
*(sp + 2) == trans_color->blue)
2819
*sp = (png_byte)background->red;
2820
*(sp + 1) = (png_byte)background->green;
2821
*(sp + 2) = (png_byte)background->blue;
2825
*sp = gamma_table[*sp];
2826
*(sp + 1) = gamma_table[*(sp + 1)];
2827
*(sp + 2) = gamma_table[*(sp + 2)];
2835
for (i = 0; i < row_width; i++, sp += 3)
2837
if (*sp == trans_color->red &&
2838
*(sp + 1) == trans_color->green &&
2839
*(sp + 2) == trans_color->blue)
2841
*sp = (png_byte)background->red;
2842
*(sp + 1) = (png_byte)background->green;
2843
*(sp + 2) = (png_byte)background->blue;
2848
else /* if (row_info->bit_depth == 16) */
2850
#ifdef PNG_READ_GAMMA_SUPPORTED
2851
if (gamma_16 != NULL)
2854
for (i = 0; i < row_width; i++, sp += 6)
2856
png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2857
png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2858
png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
2859
if (r == trans_color->red && g == trans_color->green &&
2860
b == trans_color->blue)
2862
/* Background is already in screen gamma */
2863
*sp = (png_byte)((background->red >> 8) & 0xff);
2864
*(sp + 1) = (png_byte)(background->red & 0xff);
2865
*(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2866
*(sp + 3) = (png_byte)(background->green & 0xff);
2867
*(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2868
*(sp + 5) = (png_byte)(background->blue & 0xff);
2872
png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2873
*sp = (png_byte)((v >> 8) & 0xff);
2874
*(sp + 1) = (png_byte)(v & 0xff);
2875
v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
2876
*(sp + 2) = (png_byte)((v >> 8) & 0xff);
2877
*(sp + 3) = (png_byte)(v & 0xff);
2878
v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
2879
*(sp + 4) = (png_byte)((v >> 8) & 0xff);
2880
*(sp + 5) = (png_byte)(v & 0xff);
2888
for (i = 0; i < row_width; i++, sp += 6)
2890
png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
2891
png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2892
png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
2894
if (r == trans_color->red && g == trans_color->green &&
2895
b == trans_color->blue)
2897
*sp = (png_byte)((background->red >> 8) & 0xff);
2898
*(sp + 1) = (png_byte)(background->red & 0xff);
2899
*(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2900
*(sp + 3) = (png_byte)(background->green & 0xff);
2901
*(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2902
*(sp + 5) = (png_byte)(background->blue & 0xff);
2910
case PNG_COLOR_TYPE_GRAY_ALPHA:
2912
if (row_info->bit_depth == 8)
2914
#ifdef PNG_READ_GAMMA_SUPPORTED
2915
if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2916
gamma_table != NULL)
2920
for (i = 0; i < row_width; i++, sp += 2, dp++)
2922
png_uint_16 a = *(sp + 1);
2926
*dp = gamma_table[*sp];
2930
/* Background is already in screen gamma */
2931
*dp = (png_byte)background->gray;
2937
v = gamma_to_1[*sp];
2938
png_composite(w, v, a, background_1->gray);
2939
*dp = gamma_from_1[w];
2948
for (i = 0; i < row_width; i++, sp += 2, dp++)
2950
png_byte a = *(sp + 1);
2956
#ifdef PNG_READ_GAMMA_SUPPORTED
2959
*dp = (png_byte)background->gray;
2963
png_composite(*dp, *sp, a, background_1->gray);
2966
*dp = (png_byte)background->gray;
2971
else /* if (png_ptr->bit_depth == 16) */
2973
#ifdef PNG_READ_GAMMA_SUPPORTED
2974
if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
2975
gamma_16_to_1 != NULL)
2979
for (i = 0; i < row_width; i++, sp += 4, dp += 2)
2981
png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2983
if (a == (png_uint_16)0xffff)
2987
v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2988
*dp = (png_byte)((v >> 8) & 0xff);
2989
*(dp + 1) = (png_byte)(v & 0xff);
2991
#ifdef PNG_READ_GAMMA_SUPPORTED
2997
/* Background is already in screen gamma */
2998
*dp = (png_byte)((background->gray >> 8) & 0xff);
2999
*(dp + 1) = (png_byte)(background->gray & 0xff);
3001
#ifdef PNG_READ_GAMMA_SUPPORTED
3004
png_uint_16 g, v, w;
3006
g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3007
png_composite_16(v, g, a, background_1->gray);
3008
w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3009
*dp = (png_byte)((w >> 8) & 0xff);
3010
*(dp + 1) = (png_byte)(w & 0xff);
3020
for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3022
png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3023
if (a == (png_uint_16)0xffff)
3025
png_memcpy(dp, sp, 2);
3027
#ifdef PNG_READ_GAMMA_SUPPORTED
3033
*dp = (png_byte)((background->gray >> 8) & 0xff);
3034
*(dp + 1) = (png_byte)(background->gray & 0xff);
3036
#ifdef PNG_READ_GAMMA_SUPPORTED
3041
g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3042
png_composite_16(v, g, a, background_1->gray);
3043
*dp = (png_byte)((v >> 8) & 0xff);
3044
*(dp + 1) = (png_byte)(v & 0xff);
3053
case PNG_COLOR_TYPE_RGB_ALPHA:
3055
if (row_info->bit_depth == 8)
3057
#ifdef PNG_READ_GAMMA_SUPPORTED
3058
if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3059
gamma_table != NULL)
3063
for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3065
png_byte a = *(sp + 3);
3069
*dp = gamma_table[*sp];
3070
*(dp + 1) = gamma_table[*(sp + 1)];
3071
*(dp + 2) = gamma_table[*(sp + 2)];
3075
/* Background is already in screen gamma */
3076
*dp = (png_byte)background->red;
3077
*(dp + 1) = (png_byte)background->green;
3078
*(dp + 2) = (png_byte)background->blue;
3084
v = gamma_to_1[*sp];
3085
png_composite(w, v, a, background_1->red);
3086
*dp = gamma_from_1[w];
3087
v = gamma_to_1[*(sp + 1)];
3088
png_composite(w, v, a, background_1->green);
3089
*(dp + 1) = gamma_from_1[w];
3090
v = gamma_to_1[*(sp + 2)];
3091
png_composite(w, v, a, background_1->blue);
3092
*(dp + 2) = gamma_from_1[w];
3101
for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3103
png_byte a = *(sp + 3);
3108
*(dp + 1) = *(sp + 1);
3109
*(dp + 2) = *(sp + 2);
3113
*dp = (png_byte)background->red;
3114
*(dp + 1) = (png_byte)background->green;
3115
*(dp + 2) = (png_byte)background->blue;
3119
png_composite(*dp, *sp, a, background->red);
3120
png_composite(*(dp + 1), *(sp + 1), a,
3122
png_composite(*(dp + 2), *(sp + 2), a,
3128
else /* if (row_info->bit_depth == 16) */
3130
#ifdef PNG_READ_GAMMA_SUPPORTED
3131
if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3132
gamma_16_to_1 != NULL)
3136
for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3138
png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3139
<< 8) + (png_uint_16)(*(sp + 7)));
3140
if (a == (png_uint_16)0xffff)
3144
v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3145
*dp = (png_byte)((v >> 8) & 0xff);
3146
*(dp + 1) = (png_byte)(v & 0xff);
3147
v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3148
*(dp + 2) = (png_byte)((v >> 8) & 0xff);
3149
*(dp + 3) = (png_byte)(v & 0xff);
3150
v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3151
*(dp + 4) = (png_byte)((v >> 8) & 0xff);
3152
*(dp + 5) = (png_byte)(v & 0xff);
3156
/* Background is already in screen gamma */
3157
*dp = (png_byte)((background->red >> 8) & 0xff);
3158
*(dp + 1) = (png_byte)(background->red & 0xff);
3159
*(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3160
*(dp + 3) = (png_byte)(background->green & 0xff);
3161
*(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3162
*(dp + 5) = (png_byte)(background->blue & 0xff);
3166
png_uint_16 v, w, x;
3168
v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3169
png_composite_16(w, v, a, background_1->red);
3170
x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3171
*dp = (png_byte)((x >> 8) & 0xff);
3172
*(dp + 1) = (png_byte)(x & 0xff);
3173
v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3174
png_composite_16(w, v, a, background_1->green);
3175
x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3176
*(dp + 2) = (png_byte)((x >> 8) & 0xff);
3177
*(dp + 3) = (png_byte)(x & 0xff);
3178
v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3179
png_composite_16(w, v, a, background_1->blue);
3180
x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3181
*(dp + 4) = (png_byte)((x >> 8) & 0xff);
3182
*(dp + 5) = (png_byte)(x & 0xff);
3191
for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3193
png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3194
<< 8) + (png_uint_16)(*(sp + 7)));
3195
if (a == (png_uint_16)0xffff)
3197
png_memcpy(dp, sp, 6);
3201
*dp = (png_byte)((background->red >> 8) & 0xff);
3202
*(dp + 1) = (png_byte)(background->red & 0xff);
3203
*(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3204
*(dp + 3) = (png_byte)(background->green & 0xff);
3205
*(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3206
*(dp + 5) = (png_byte)(background->blue & 0xff);
3212
png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3213
png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3215
png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3218
png_composite_16(v, r, a, background->red);
3219
*dp = (png_byte)((v >> 8) & 0xff);
3220
*(dp + 1) = (png_byte)(v & 0xff);
3221
png_composite_16(v, g, a, background->green);
3222
*(dp + 2) = (png_byte)((v >> 8) & 0xff);
3223
*(dp + 3) = (png_byte)(v & 0xff);
3224
png_composite_16(v, b, a, background->blue);
3225
*(dp + 4) = (png_byte)((v >> 8) & 0xff);
3226
*(dp + 5) = (png_byte)(v & 0xff);
3235
if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3237
row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
3238
row_info->channels--;
3239
row_info->pixel_depth = (png_byte)(row_info->channels *
3240
row_info->bit_depth);
3241
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3247
#ifdef PNG_READ_GAMMA_SUPPORTED
3248
/* Gamma correct the image, avoiding the alpha channel. Make sure
3249
* you do this after you deal with the transparency issue on grayscale
3250
* or RGB images. If your bit depth is 8, use gamma_table, if it
3251
* is 16, use gamma_16_table and gamma_shift. Build these with
3252
* build_gamma_table().
3255
png_do_gamma(png_row_infop row_info, png_bytep row,
3256
png_bytep gamma_table, png_uint_16pp gamma_16_table,
3261
png_uint_32 row_width=row_info->width;
3263
png_debug(1, "in png_do_gamma");
3266
((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3267
(row_info->bit_depth == 16 && gamma_16_table != NULL)))
3269
switch (row_info->color_type)
3271
case PNG_COLOR_TYPE_RGB:
3273
if (row_info->bit_depth == 8)
3276
for (i = 0; i < row_width; i++)
3278
*sp = gamma_table[*sp];
3280
*sp = gamma_table[*sp];
3282
*sp = gamma_table[*sp];
3286
else /* if (row_info->bit_depth == 16) */
3289
for (i = 0; i < row_width; i++)
3293
v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3294
*sp = (png_byte)((v >> 8) & 0xff);
3295
*(sp + 1) = (png_byte)(v & 0xff);
3297
v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3298
*sp = (png_byte)((v >> 8) & 0xff);
3299
*(sp + 1) = (png_byte)(v & 0xff);
3301
v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3302
*sp = (png_byte)((v >> 8) & 0xff);
3303
*(sp + 1) = (png_byte)(v & 0xff);
3310
case PNG_COLOR_TYPE_RGB_ALPHA:
3312
if (row_info->bit_depth == 8)
3315
for (i = 0; i < row_width; i++)
3317
*sp = gamma_table[*sp];
3319
*sp = gamma_table[*sp];
3321
*sp = gamma_table[*sp];
3326
else /* if (row_info->bit_depth == 16) */
3329
for (i = 0; i < row_width; i++)
3331
png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3332
*sp = (png_byte)((v >> 8) & 0xff);
3333
*(sp + 1) = (png_byte)(v & 0xff);
3335
v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3336
*sp = (png_byte)((v >> 8) & 0xff);
3337
*(sp + 1) = (png_byte)(v & 0xff);
3339
v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3340
*sp = (png_byte)((v >> 8) & 0xff);
3341
*(sp + 1) = (png_byte)(v & 0xff);
3348
case PNG_COLOR_TYPE_GRAY_ALPHA:
3350
if (row_info->bit_depth == 8)
3353
for (i = 0; i < row_width; i++)
3355
*sp = gamma_table[*sp];
3359
else /* if (row_info->bit_depth == 16) */
3362
for (i = 0; i < row_width; i++)
3364
png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3365
*sp = (png_byte)((v >> 8) & 0xff);
3366
*(sp + 1) = (png_byte)(v & 0xff);
3373
case PNG_COLOR_TYPE_GRAY:
3375
if (row_info->bit_depth == 2)
3378
for (i = 0; i < row_width; i += 4)
3386
((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
3387
((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3388
((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
3389
((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
3394
if (row_info->bit_depth == 4)
3397
for (i = 0; i < row_width; i += 2)
3399
int msb = *sp & 0xf0;
3400
int lsb = *sp & 0x0f;
3402
*sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3403
| (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
3408
else if (row_info->bit_depth == 8)
3411
for (i = 0; i < row_width; i++)
3413
*sp = gamma_table[*sp];
3418
else if (row_info->bit_depth == 16)
3421
for (i = 0; i < row_width; i++)
3423
png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3424
*sp = (png_byte)((v >> 8) & 0xff);
3425
*(sp + 1) = (png_byte)(v & 0xff);
3436
#ifdef PNG_READ_EXPAND_SUPPORTED
3437
/* Expands a palette row to an RGB or RGBA row depending
3438
* upon whether you supply trans and num_trans.
3441
png_do_expand_palette(png_row_infop row_info, png_bytep row,
3442
png_colorp palette, png_bytep trans_alpha, int num_trans)
3447
png_uint_32 row_width=row_info->width;
3449
png_debug(1, "in png_do_expand_palette");
3452
row_info->color_type == PNG_COLOR_TYPE_PALETTE)
3454
if (row_info->bit_depth < 8)
3456
switch (row_info->bit_depth)
3460
sp = row + (png_size_t)((row_width - 1) >> 3);
3461
dp = row + (png_size_t)row_width - 1;
3462
shift = 7 - (int)((row_width + 7) & 0x07);
3463
for (i = 0; i < row_width; i++)
3465
if ((*sp >> shift) & 0x01)
3484
sp = row + (png_size_t)((row_width - 1) >> 2);
3485
dp = row + (png_size_t)row_width - 1;
3486
shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3487
for (i = 0; i < row_width; i++)
3489
value = (*sp >> shift) & 0x03;
3490
*dp = (png_byte)value;
3506
sp = row + (png_size_t)((row_width - 1) >> 1);
3507
dp = row + (png_size_t)row_width - 1;
3508
shift = (int)((row_width & 0x01) << 2);
3509
for (i = 0; i < row_width; i++)
3511
value = (*sp >> shift) & 0x0f;
3512
*dp = (png_byte)value;
3526
row_info->bit_depth = 8;
3527
row_info->pixel_depth = 8;
3528
row_info->rowbytes = row_width;
3530
switch (row_info->bit_depth)
3534
if (trans_alpha != NULL)
3536
sp = row + (png_size_t)row_width - 1;
3537
dp = row + (png_size_t)(row_width << 2) - 1;
3539
for (i = 0; i < row_width; i++)
3541
if ((int)(*sp) >= num_trans)
3544
*dp-- = trans_alpha[*sp];
3545
*dp-- = palette[*sp].blue;
3546
*dp-- = palette[*sp].green;
3547
*dp-- = palette[*sp].red;
3550
row_info->bit_depth = 8;
3551
row_info->pixel_depth = 32;
3552
row_info->rowbytes = row_width * 4;
3553
row_info->color_type = 6;
3554
row_info->channels = 4;
3558
sp = row + (png_size_t)row_width - 1;
3559
dp = row + (png_size_t)(row_width * 3) - 1;
3561
for (i = 0; i < row_width; i++)
3563
*dp-- = palette[*sp].blue;
3564
*dp-- = palette[*sp].green;
3565
*dp-- = palette[*sp].red;
3569
row_info->bit_depth = 8;
3570
row_info->pixel_depth = 24;
3571
row_info->rowbytes = row_width * 3;
3572
row_info->color_type = 2;
3573
row_info->channels = 3;
3581
/* If the bit depth < 8, it is expanded to 8. Also, if the already
3582
* expanded transparency value is supplied, an alpha channel is built.
3585
png_do_expand(png_row_infop row_info, png_bytep row,
3586
png_color_16p trans_value)
3591
png_uint_32 row_width=row_info->width;
3593
png_debug(1, "in png_do_expand");
3596
if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
3598
png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
3600
if (row_info->bit_depth < 8)
3602
switch (row_info->bit_depth)
3606
gray = (png_uint_16)((gray&0x01)*0xff);
3607
sp = row + (png_size_t)((row_width - 1) >> 3);
3608
dp = row + (png_size_t)row_width - 1;
3609
shift = 7 - (int)((row_width + 7) & 0x07);
3610
for (i = 0; i < row_width; i++)
3612
if ((*sp >> shift) & 0x01)
3631
gray = (png_uint_16)((gray&0x03)*0x55);
3632
sp = row + (png_size_t)((row_width - 1) >> 2);
3633
dp = row + (png_size_t)row_width - 1;
3634
shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3635
for (i = 0; i < row_width; i++)
3637
value = (*sp >> shift) & 0x03;
3638
*dp = (png_byte)(value | (value << 2) | (value << 4) |
3655
gray = (png_uint_16)((gray&0x0f)*0x11);
3656
sp = row + (png_size_t)((row_width - 1) >> 1);
3657
dp = row + (png_size_t)row_width - 1;
3658
shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
3659
for (i = 0; i < row_width; i++)
3661
value = (*sp >> shift) & 0x0f;
3662
*dp = (png_byte)(value | (value << 4));
3677
row_info->bit_depth = 8;
3678
row_info->pixel_depth = 8;
3679
row_info->rowbytes = row_width;
3682
if (trans_value != NULL)
3684
if (row_info->bit_depth == 8)
3687
sp = row + (png_size_t)row_width - 1;
3688
dp = row + (png_size_t)(row_width << 1) - 1;
3689
for (i = 0; i < row_width; i++)
3699
else if (row_info->bit_depth == 16)
3701
png_byte gray_high = (gray >> 8) & 0xff;
3702
png_byte gray_low = gray & 0xff;
3703
sp = row + row_info->rowbytes - 1;
3704
dp = row + (row_info->rowbytes << 1) - 1;
3705
for (i = 0; i < row_width; i++)
3707
if (*(sp - 1) == gray_high && *(sp) == gray_low)
3722
row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3723
row_info->channels = 2;
3724
row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3725
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
3729
else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3731
if (row_info->bit_depth == 8)
3733
png_byte red = trans_value->red & 0xff;
3734
png_byte green = trans_value->green & 0xff;
3735
png_byte blue = trans_value->blue & 0xff;
3736
sp = row + (png_size_t)row_info->rowbytes - 1;
3737
dp = row + (png_size_t)(row_width << 2) - 1;
3738
for (i = 0; i < row_width; i++)
3740
if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
3749
else if (row_info->bit_depth == 16)
3751
png_byte red_high = (trans_value->red >> 8) & 0xff;
3752
png_byte green_high = (trans_value->green >> 8) & 0xff;
3753
png_byte blue_high = (trans_value->blue >> 8) & 0xff;
3754
png_byte red_low = trans_value->red & 0xff;
3755
png_byte green_low = trans_value->green & 0xff;
3756
png_byte blue_low = trans_value->blue & 0xff;
3757
sp = row + row_info->rowbytes - 1;
3758
dp = row + (png_size_t)(row_width << 3) - 1;
3759
for (i = 0; i < row_width; i++)
3761
if (*(sp - 5) == red_high &&
3762
*(sp - 4) == red_low &&
3763
*(sp - 3) == green_high &&
3764
*(sp - 2) == green_low &&
3765
*(sp - 1) == blue_high &&
3784
row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3785
row_info->channels = 4;
3786
row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
3787
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3793
#ifdef PNG_READ_QUANTIZE_SUPPORTED
3795
png_do_quantize(png_row_infop row_info, png_bytep row,
3796
png_bytep palette_lookup, png_bytep quantize_lookup)
3800
png_uint_32 row_width=row_info->width;
3802
png_debug(1, "in png_do_quantize");
3805
if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3806
palette_lookup && row_info->bit_depth == 8)
3811
for (i = 0; i < row_width; i++)
3817
/* This looks real messy, but the compiler will reduce
3818
* it down to a reasonable formula. For example, with
3819
* 5 bits per color, we get:
3820
* p = (((r >> 3) & 0x1f) << 10) |
3821
* (((g >> 3) & 0x1f) << 5) |
3822
* ((b >> 3) & 0x1f);
3824
p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
3825
((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
3826
(PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
3827
(((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
3828
((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
3829
(PNG_QUANTIZE_BLUE_BITS)) |
3830
((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
3831
((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
3833
*dp++ = palette_lookup[p];
3835
row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3836
row_info->channels = 1;
3837
row_info->pixel_depth = row_info->bit_depth;
3838
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3840
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
3841
palette_lookup != NULL && row_info->bit_depth == 8)
3846
for (i = 0; i < row_width; i++)
3853
p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
3854
((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
3855
(PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
3856
(((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
3857
((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
3858
(PNG_QUANTIZE_BLUE_BITS)) |
3859
((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
3860
((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
3862
*dp++ = palette_lookup[p];
3864
row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3865
row_info->channels = 1;
3866
row_info->pixel_depth = row_info->bit_depth;
3867
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3869
else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
3870
quantize_lookup && row_info->bit_depth == 8)
3873
for (i = 0; i < row_width; i++, sp++)
3875
*sp = quantize_lookup[*sp];
3882
#ifdef PNG_FLOATING_POINT_SUPPORTED
3883
#ifdef PNG_READ_GAMMA_SUPPORTED
3884
static PNG_CONST int png_gamma_shift[] =
3885
{0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
3887
/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
3888
* tables, we don't make a full table if we are reducing to 8-bit in
3889
* the future. Note also how the gamma_16 tables are segmented so that
3890
* we don't need to allocate > 64K chunks for a full 16-bit table.
3892
* See the PNG extensions document for an integer algorithm for creating
3893
* the gamma tables. Maybe we will implement that here someday.
3895
* We should only reach this point if
3897
* the file_gamma is known (i.e., the gAMA or sRGB chunk is present,
3898
* or the application has provided a file_gamma)
3902
* the screen_gamma is known
3906
* RGB_to_gray transformation is being performed
3911
* the screen_gamma is different from the reciprocal of the
3912
* file_gamma by more than the specified threshold
3916
* a background color has been specified and the file_gamma
3917
* and screen_gamma are not 1.0, within the specified threshold.
3922
png_build_gamma_table(png_structp png_ptr, png_byte bit_depth)
3924
png_debug(1, "in png_build_gamma_table");
3931
if (png_ptr->screen_gamma > .000001)
3932
g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3937
png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
3940
for (i = 0; i < 256; i++)
3942
png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
3946
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3947
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
3948
if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
3951
g = 1.0 / (png_ptr->gamma);
3953
png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
3956
for (i = 0; i < 256; i++)
3958
png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
3963
png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
3966
if (png_ptr->screen_gamma > 0.000001)
3967
g = 1.0 / png_ptr->screen_gamma;
3970
g = png_ptr->gamma; /* Probably doing rgb_to_gray */
3972
for (i = 0; i < 256; i++)
3974
png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
3979
#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
3984
int i, j, shift, num;
3988
if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
3990
sig_bit = (int)png_ptr->sig_bit.red;
3992
if ((int)png_ptr->sig_bit.green > sig_bit)
3993
sig_bit = png_ptr->sig_bit.green;
3995
if ((int)png_ptr->sig_bit.blue > sig_bit)
3996
sig_bit = png_ptr->sig_bit.blue;
4000
sig_bit = (int)png_ptr->sig_bit.gray;
4004
shift = 16 - sig_bit;
4009
if (png_ptr->transformations & PNG_16_TO_8)
4011
if (shift < (16 - PNG_MAX_GAMMA_8))
4012
shift = (16 - PNG_MAX_GAMMA_8);
4021
png_ptr->gamma_shift = (png_byte)shift;
4023
num = (1 << (8 - shift));
4025
if (png_ptr->screen_gamma > .000001)
4026
g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4030
png_ptr->gamma_16_table = (png_uint_16pp)png_calloc(png_ptr,
4031
(png_uint_32)(num * png_sizeof(png_uint_16p)));
4033
if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
4036
png_uint_32 last, max;
4038
for (i = 0; i < num; i++)
4040
png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4041
(png_uint_32)(256 * png_sizeof(png_uint_16)));
4046
for (i = 0; i < 256; i++)
4048
fout = ((double)i + 0.5) / 256.0;
4050
max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
4053
png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4054
[(int)(last >> (8 - shift))] = (png_uint_16)(
4055
(png_uint_16)i | ((png_uint_16)i << 8));
4059
while (last < ((png_uint_32)num << 8))
4061
png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4062
[(int)(last >> (8 - shift))] = (png_uint_16)65535L;
4068
for (i = 0; i < num; i++)
4070
png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4071
(png_uint_32)(256 * png_sizeof(png_uint_16)));
4073
ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
4075
for (j = 0; j < 256; j++)
4077
png_ptr->gamma_16_table[i][j] =
4078
(png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4079
65535.0, g) * 65535.0 + .5);
4084
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4085
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4086
if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
4089
g = 1.0 / (png_ptr->gamma);
4091
png_ptr->gamma_16_to_1 = (png_uint_16pp)png_calloc(png_ptr,
4092
(png_uint_32)(num * png_sizeof(png_uint_16p )));
4094
for (i = 0; i < num; i++)
4096
png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
4097
(png_uint_32)(256 * png_sizeof(png_uint_16)));
4099
ig = (((png_uint_32)i *
4100
(png_uint_32)png_gamma_shift[shift]) >> 4);
4101
for (j = 0; j < 256; j++)
4103
png_ptr->gamma_16_to_1[i][j] =
4104
(png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4105
65535.0, g) * 65535.0 + .5);
4109
if (png_ptr->screen_gamma > 0.000001)
4110
g = 1.0 / png_ptr->screen_gamma;
4113
g = png_ptr->gamma; /* Probably doing rgb_to_gray */
4115
png_ptr->gamma_16_from_1 = (png_uint_16pp)png_calloc(png_ptr,
4116
(png_uint_32)(num * png_sizeof(png_uint_16p)));
4118
for (i = 0; i < num; i++)
4120
png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
4121
(png_uint_32)(256 * png_sizeof(png_uint_16)));
4123
ig = (((png_uint_32)i *
4124
(png_uint_32)png_gamma_shift[shift]) >> 4);
4126
for (j = 0; j < 256; j++)
4128
png_ptr->gamma_16_from_1[i][j] =
4129
(png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4130
65535.0, g) * 65535.0 + .5);
4134
#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4138
/* To do: install integer version of png_build_gamma_table here */
4141
#ifdef PNG_MNG_FEATURES_SUPPORTED
4142
/* Undoes intrapixel differencing */
4144
png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4146
png_debug(1, "in png_do_read_intrapixel");
4149
(row_info->color_type & PNG_COLOR_MASK_COLOR))
4151
int bytes_per_pixel;
4152
png_uint_32 row_width = row_info->width;
4153
if (row_info->bit_depth == 8)
4158
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4159
bytes_per_pixel = 3;
4161
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4162
bytes_per_pixel = 4;
4167
for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4169
*(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
4170
*(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
4173
else if (row_info->bit_depth == 16)
4178
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4179
bytes_per_pixel = 6;
4181
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4182
bytes_per_pixel = 8;
4187
for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4189
png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
4190
png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
4191
png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
4192
png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL);
4193
png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL);
4194
*(rp ) = (png_byte)((red >> 8) & 0xff);
4195
*(rp+1) = (png_byte)(red & 0xff);
4196
*(rp+4) = (png_byte)((blue >> 8) & 0xff);
4197
*(rp+5) = (png_byte)(blue & 0xff);
4202
#endif /* PNG_MNG_FEATURES_SUPPORTED */
4203
#endif /* PNG_READ_SUPPORTED */