2 /* pngrtran.c - transforms the data in a row for PNG readers
4 * Last changed in libpng 1.2.27 [April 29, 2008]
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2008 Glenn Randers-Pehrson
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
10 * This file contains functions optionally called by an application
11 * in order to tell libpng how to handle data when reading a PNG.
12 * Transformations that are used in both reading and writing are
19 #if defined(PNG_READ_SUPPORTED)
21 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
23 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
25 png_debug(1, "in png_set_crc_action\n");
26 /* Tell libpng how we react to CRC errors in critical chunks */
27 if(png_ptr == NULL) return;
30 case PNG_CRC_NO_CHANGE: /* leave setting as is */
32 case PNG_CRC_WARN_USE: /* warn/use data */
33 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
34 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
36 case PNG_CRC_QUIET_USE: /* quiet/use data */
37 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
38 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
39 PNG_FLAG_CRC_CRITICAL_IGNORE;
41 case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */
42 png_warning(png_ptr, "Can't discard critical data on CRC error.");
43 case PNG_CRC_ERROR_QUIT: /* error/quit */
46 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
52 case PNG_CRC_NO_CHANGE: /* leave setting as is */
54 case PNG_CRC_WARN_USE: /* warn/use data */
55 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
56 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
58 case PNG_CRC_QUIET_USE: /* quiet/use data */
59 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
60 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
61 PNG_FLAG_CRC_ANCILLARY_NOWARN;
63 case PNG_CRC_ERROR_QUIT: /* error/quit */
64 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
65 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
67 case PNG_CRC_WARN_DISCARD: /* warn/discard data */
70 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
75 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
76 defined(PNG_FLOATING_POINT_SUPPORTED)
77 /* handle alpha and tRNS via a background color */
79 png_set_background(png_structp png_ptr,
80 png_color_16p background_color, int background_gamma_code,
81 int need_expand, double background_gamma)
83 png_debug(1, "in png_set_background\n");
84 if(png_ptr == NULL) return;
85 if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
87 png_warning(png_ptr, "Application must supply a known background gamma");
91 png_ptr->transformations |= PNG_BACKGROUND;
92 png_memcpy(&(png_ptr->background), background_color,
93 png_sizeof(png_color_16));
94 png_ptr->background_gamma = (float)background_gamma;
95 png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
96 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
100 #if defined(PNG_READ_16_TO_8_SUPPORTED)
101 /* strip 16 bit depth files to 8 bit depth */
103 png_set_strip_16(png_structp png_ptr)
105 png_debug(1, "in png_set_strip_16\n");
106 if(png_ptr == NULL) return;
107 png_ptr->transformations |= PNG_16_TO_8;
111 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
113 png_set_strip_alpha(png_structp png_ptr)
115 png_debug(1, "in png_set_strip_alpha\n");
116 if(png_ptr == NULL) return;
117 png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
121 #if defined(PNG_READ_DITHER_SUPPORTED)
122 /* Dither file to 8 bit. Supply a palette, the current number
123 * of elements in the palette, the maximum number of elements
124 * allowed, and a histogram if possible. If the current number
125 * of colors is greater then the maximum number, the palette will be
126 * modified to fit in the maximum number. "full_dither" indicates
127 * whether we need a dithering cube set up for RGB images, or if we
128 * simply are reducing the number of colors in a paletted image.
131 typedef struct png_dsort_struct
133 struct png_dsort_struct FAR * next;
137 typedef png_dsort FAR * png_dsortp;
138 typedef png_dsort FAR * FAR * png_dsortpp;
141 png_set_dither(png_structp png_ptr, png_colorp palette,
142 int num_palette, int maximum_colors, png_uint_16p histogram,
145 png_debug(1, "in png_set_dither\n");
146 if(png_ptr == NULL) return;
147 png_ptr->transformations |= PNG_DITHER;
153 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
154 (png_uint_32)(num_palette * png_sizeof (png_byte)));
155 for (i = 0; i < num_palette; i++)
156 png_ptr->dither_index[i] = (png_byte)i;
159 if (num_palette > maximum_colors)
161 if (histogram != NULL)
163 /* This is easy enough, just throw out the least used colors.
164 Perhaps not the best solution, but good enough. */
168 /* initialize an array to sort colors */
169 png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
170 (png_uint_32)(num_palette * png_sizeof (png_byte)));
172 /* initialize the dither_sort array */
173 for (i = 0; i < num_palette; i++)
174 png_ptr->dither_sort[i] = (png_byte)i;
176 /* Find the least used palette entries by starting a
177 bubble sort, and running it until we have sorted
178 out enough colors. Note that we don't care about
179 sorting all the colors, just finding which are
182 for (i = num_palette - 1; i >= maximum_colors; i--)
184 int done; /* to stop early if the list is pre-sorted */
188 for (j = 0; j < i; j++)
190 if (histogram[png_ptr->dither_sort[j]]
191 < histogram[png_ptr->dither_sort[j + 1]])
195 t = png_ptr->dither_sort[j];
196 png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
197 png_ptr->dither_sort[j + 1] = t;
205 /* swap the palette around, and set up a table, if necessary */
210 /* put all the useful colors within the max, but don't
212 for (i = 0; i < maximum_colors; i++)
214 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
218 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
219 palette[i] = palette[j];
227 /* move all the used colors inside the max limit, and
228 develop a translation table */
229 for (i = 0; i < maximum_colors; i++)
231 /* only move the colors we need to */
232 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
238 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
240 tmp_color = palette[j];
241 palette[j] = palette[i];
242 palette[i] = tmp_color;
243 /* indicate where the color went */
244 png_ptr->dither_index[j] = (png_byte)i;
245 png_ptr->dither_index[i] = (png_byte)j;
249 /* find closest color for those colors we are not using */
250 for (i = 0; i < num_palette; i++)
252 if ((int)png_ptr->dither_index[i] >= maximum_colors)
254 int min_d, k, min_k, d_index;
256 /* find the closest color to one we threw out */
257 d_index = png_ptr->dither_index[i];
258 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
259 for (k = 1, min_k = 0; k < maximum_colors; k++)
263 d = PNG_COLOR_DIST(palette[d_index], palette[k]);
271 /* point to closest color */
272 png_ptr->dither_index[i] = (png_byte)min_k;
276 png_free(png_ptr, png_ptr->dither_sort);
277 png_ptr->dither_sort=NULL;
281 /* This is much harder to do simply (and quickly). Perhaps
282 we need to go through a median cut routine, but those
283 don't always behave themselves with only a few colors
284 as input. So we will just find the closest two colors,
285 and throw out one of them (chosen somewhat randomly).
286 [We don't understand this at all, so if someone wants to
287 work on improving it, be our guest - AED, GRP]
297 /* initialize palette index arrays */
298 png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
299 (png_uint_32)(num_palette * png_sizeof (png_byte)));
300 png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
301 (png_uint_32)(num_palette * png_sizeof (png_byte)));
303 /* initialize the sort array */
304 for (i = 0; i < num_palette; i++)
306 png_ptr->index_to_palette[i] = (png_byte)i;
307 png_ptr->palette_to_index[i] = (png_byte)i;
310 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
311 png_sizeof (png_dsortp)));
312 for (i = 0; i < 769; i++)
314 /* png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */
316 num_new_palette = num_palette;
318 /* initial wild guess at how far apart the farthest pixel
319 pair we will be eliminating will be. Larger
320 numbers mean more areas will be allocated, Smaller
321 numbers run the risk of not saving enough data, and
322 having to do this all over again.
324 I have not done extensive checking on this number.
328 while (num_new_palette > maximum_colors)
330 for (i = 0; i < num_new_palette - 1; i++)
334 for (j = i + 1; j < num_new_palette; j++)
338 d = PNG_COLOR_DIST(palette[i], palette[j]);
343 t = (png_dsortp)png_malloc_warn(png_ptr,
344 (png_uint_32)(png_sizeof(png_dsort)));
348 t->left = (png_byte)i;
349 t->right = (png_byte)j;
358 for (i = 0; i <= max_d; i++)
364 for (p = hash[i]; p; p = p->next)
366 if ((int)png_ptr->index_to_palette[p->left]
368 (int)png_ptr->index_to_palette[p->right]
373 if (num_new_palette & 0x01)
385 palette[png_ptr->index_to_palette[j]]
386 = palette[num_new_palette];
391 for (k = 0; k < num_palette; k++)
393 if (png_ptr->dither_index[k] ==
394 png_ptr->index_to_palette[j])
395 png_ptr->dither_index[k] =
396 png_ptr->index_to_palette[next_j];
397 if ((int)png_ptr->dither_index[k] ==
399 png_ptr->dither_index[k] =
400 png_ptr->index_to_palette[j];
404 png_ptr->index_to_palette[png_ptr->palette_to_index
405 [num_new_palette]] = png_ptr->index_to_palette[j];
406 png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
407 = png_ptr->palette_to_index[num_new_palette];
409 png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
410 png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
412 if (num_new_palette <= maximum_colors)
415 if (num_new_palette <= maximum_colors)
420 for (i = 0; i < 769; i++)
424 png_dsortp p = hash[i];
428 png_free(png_ptr, p);
436 png_free(png_ptr, hash);
437 png_free(png_ptr, png_ptr->palette_to_index);
438 png_free(png_ptr, png_ptr->index_to_palette);
439 png_ptr->palette_to_index=NULL;
440 png_ptr->index_to_palette=NULL;
442 num_palette = maximum_colors;
444 if (png_ptr->palette == NULL)
446 png_ptr->palette = palette;
448 png_ptr->num_palette = (png_uint_16)num_palette;
454 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
455 PNG_DITHER_BLUE_BITS;
456 int num_red = (1 << PNG_DITHER_RED_BITS);
457 int num_green = (1 << PNG_DITHER_GREEN_BITS);
458 int num_blue = (1 << PNG_DITHER_BLUE_BITS);
459 png_size_t num_entries = ((png_size_t)1 << total_bits);
461 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
462 (png_uint_32)(num_entries * png_sizeof (png_byte)));
464 png_memset(png_ptr->palette_lookup, 0, num_entries *
465 png_sizeof (png_byte));
467 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
468 png_sizeof(png_byte)));
470 png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
472 for (i = 0; i < num_palette; i++)
475 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
476 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
477 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
479 for (ir = 0; ir < num_red; ir++)
481 /* int dr = abs(ir - r); */
482 int dr = ((ir > r) ? ir - r : r - ir);
483 int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
485 for (ig = 0; ig < num_green; ig++)
487 /* int dg = abs(ig - g); */
488 int dg = ((ig > g) ? ig - g : g - ig);
490 int dm = ((dr > dg) ? dr : dg);
491 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
493 for (ib = 0; ib < num_blue; ib++)
495 int d_index = index_g | ib;
496 /* int db = abs(ib - b); */
497 int db = ((ib > b) ? ib - b : b - ib);
498 int dmax = ((dm > db) ? dm : db);
499 int d = dmax + dt + db;
501 if (d < (int)distance[d_index])
503 distance[d_index] = (png_byte)d;
504 png_ptr->palette_lookup[d_index] = (png_byte)i;
511 png_free(png_ptr, distance);
516 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
517 /* Transform the image from the file_gamma to the screen_gamma. We
518 * only do transformations on images where the file_gamma and screen_gamma
519 * are not close reciprocals, otherwise it slows things down slightly, and
520 * also needlessly introduces small errors.
522 * We will turn off gamma transformation later if no semitransparent entries
523 * are present in the tRNS array for palette images. We can't do it here
524 * because we don't necessarily have the tRNS chunk yet.
527 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
529 png_debug(1, "in png_set_gamma\n");
530 if(png_ptr == NULL) return;
531 if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
532 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
533 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
534 png_ptr->transformations |= PNG_GAMMA;
535 png_ptr->gamma = (float)file_gamma;
536 png_ptr->screen_gamma = (float)scrn_gamma;
540 #if defined(PNG_READ_EXPAND_SUPPORTED)
541 /* Expand paletted images to RGB, expand grayscale images of
542 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
546 png_set_expand(png_structp png_ptr)
548 png_debug(1, "in png_set_expand\n");
549 if(png_ptr == NULL) return;
550 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
551 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
554 /* GRR 19990627: the following three functions currently are identical
555 * to png_set_expand(). However, it is entirely reasonable that someone
556 * might wish to expand an indexed image to RGB but *not* expand a single,
557 * fully transparent palette entry to a full alpha channel--perhaps instead
558 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
559 * the transparent color with a particular RGB value, or drop tRNS entirely.
560 * IOW, a future version of the library may make the transformations flag
561 * a bit more fine-grained, with separate bits for each of these three
564 * More to the point, these functions make it obvious what libpng will be
565 * doing, whereas "expand" can (and does) mean any number of things.
567 * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified
568 * to expand only the sample depth but not to expand the tRNS to alpha.
571 /* Expand paletted images to RGB. */
573 png_set_palette_to_rgb(png_structp png_ptr)
575 png_debug(1, "in png_set_palette_to_rgb\n");
576 if(png_ptr == NULL) return;
577 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
578 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
581 #if !defined(PNG_1_0_X)
582 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
584 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
586 png_debug(1, "in png_set_expand_gray_1_2_4_to_8\n");
587 if(png_ptr == NULL) return;
588 png_ptr->transformations |= PNG_EXPAND;
589 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
593 #if defined(PNG_1_0_X) || defined(PNG_1_2_X)
594 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
595 /* Deprecated as of libpng-1.2.9 */
597 png_set_gray_1_2_4_to_8(png_structp png_ptr)
599 png_debug(1, "in png_set_gray_1_2_4_to_8\n");
600 if(png_ptr == NULL) return;
601 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
606 /* Expand tRNS chunks to alpha channels. */
608 png_set_tRNS_to_alpha(png_structp png_ptr)
610 png_debug(1, "in png_set_tRNS_to_alpha\n");
611 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
612 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
614 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
616 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
618 png_set_gray_to_rgb(png_structp png_ptr)
620 png_debug(1, "in png_set_gray_to_rgb\n");
621 png_ptr->transformations |= PNG_GRAY_TO_RGB;
622 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
626 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
627 #if defined(PNG_FLOATING_POINT_SUPPORTED)
628 /* Convert a RGB image to a grayscale of the same width. This allows us,
629 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
633 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
636 int red_fixed = (int)((float)red*100000.0 + 0.5);
637 int green_fixed = (int)((float)green*100000.0 + 0.5);
638 if(png_ptr == NULL) return;
639 png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
644 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
645 png_fixed_point red, png_fixed_point green)
647 png_debug(1, "in png_set_rgb_to_gray\n");
648 if(png_ptr == NULL) return;
651 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
653 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
655 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
657 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
658 #if defined(PNG_READ_EXPAND_SUPPORTED)
659 png_ptr->transformations |= PNG_EXPAND;
662 png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
663 png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
667 png_uint_16 red_int, green_int;
668 if(red < 0 || green < 0)
670 red_int = 6968; /* .212671 * 32768 + .5 */
671 green_int = 23434; /* .715160 * 32768 + .5 */
673 else if(red + green < 100000L)
675 red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
676 green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
680 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
684 png_ptr->rgb_to_gray_red_coeff = red_int;
685 png_ptr->rgb_to_gray_green_coeff = green_int;
686 png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int);
691 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
692 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
693 defined(PNG_LEGACY_SUPPORTED)
695 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
696 read_user_transform_fn)
698 png_debug(1, "in png_set_read_user_transform_fn\n");
699 if(png_ptr == NULL) return;
700 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
701 png_ptr->transformations |= PNG_USER_TRANSFORM;
702 png_ptr->read_user_transform_fn = read_user_transform_fn;
704 #ifdef PNG_LEGACY_SUPPORTED
705 if(read_user_transform_fn)
707 "This version of libpng does not support user transforms");
712 /* Initialize everything needed for the read. This includes modifying
716 png_init_read_transformations(png_structp png_ptr)
718 png_debug(1, "in png_init_read_transformations\n");
719 #if defined(PNG_USELESS_TESTS_SUPPORTED)
723 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
724 || defined(PNG_READ_GAMMA_SUPPORTED)
725 int color_type = png_ptr->color_type;
728 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
730 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
731 /* Detect gray background and attempt to enable optimization
732 * for gray --> RGB case */
733 /* Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
734 * RGB_ALPHA (in which case need_expand is superfluous anyway), the
735 * background color might actually be gray yet not be flagged as such.
736 * This is not a problem for the current code, which uses
737 * PNG_BACKGROUND_IS_GRAY only to decide when to do the
738 * png_do_gray_to_rgb() transformation.
740 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
741 !(color_type & PNG_COLOR_MASK_COLOR))
743 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
744 } else if ((png_ptr->transformations & PNG_BACKGROUND) &&
745 !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
746 (png_ptr->transformations & PNG_GRAY_TO_RGB) &&
747 png_ptr->background.red == png_ptr->background.green &&
748 png_ptr->background.red == png_ptr->background.blue)
750 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
751 png_ptr->background.gray = png_ptr->background.red;
755 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
756 (png_ptr->transformations & PNG_EXPAND))
758 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
760 /* expand background and tRNS chunks */
761 switch (png_ptr->bit_depth)
764 png_ptr->background.gray *= (png_uint_16)0xff;
765 png_ptr->background.red = png_ptr->background.green
766 = png_ptr->background.blue = png_ptr->background.gray;
767 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
769 png_ptr->trans_values.gray *= (png_uint_16)0xff;
770 png_ptr->trans_values.red = png_ptr->trans_values.green
771 = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
775 png_ptr->background.gray *= (png_uint_16)0x55;
776 png_ptr->background.red = png_ptr->background.green
777 = png_ptr->background.blue = png_ptr->background.gray;
778 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
780 png_ptr->trans_values.gray *= (png_uint_16)0x55;
781 png_ptr->trans_values.red = png_ptr->trans_values.green
782 = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
786 png_ptr->background.gray *= (png_uint_16)0x11;
787 png_ptr->background.red = png_ptr->background.green
788 = png_ptr->background.blue = png_ptr->background.gray;
789 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
791 png_ptr->trans_values.gray *= (png_uint_16)0x11;
792 png_ptr->trans_values.red = png_ptr->trans_values.green
793 = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
798 png_ptr->background.red = png_ptr->background.green
799 = png_ptr->background.blue = png_ptr->background.gray;
803 else if (color_type == PNG_COLOR_TYPE_PALETTE)
805 png_ptr->background.red =
806 png_ptr->palette[png_ptr->background.index].red;
807 png_ptr->background.green =
808 png_ptr->palette[png_ptr->background.index].green;
809 png_ptr->background.blue =
810 png_ptr->palette[png_ptr->background.index].blue;
812 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
813 if (png_ptr->transformations & PNG_INVERT_ALPHA)
815 #if defined(PNG_READ_EXPAND_SUPPORTED)
816 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
819 /* invert the alpha channel (in tRNS) unless the pixels are
820 going to be expanded, in which case leave it for later */
822 istop=(int)png_ptr->num_trans;
823 for (i=0; i<istop; i++)
824 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
833 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
834 png_ptr->background_1 = png_ptr->background;
836 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
838 if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
839 && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
840 < PNG_GAMMA_THRESHOLD))
844 for (i=0; i<png_ptr->num_trans; i++)
846 if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
847 k=1; /* partial transparency is present */
850 png_ptr->transformations &= ~PNG_GAMMA;
853 if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) &&
854 png_ptr->gamma != 0.0)
856 png_build_gamma_table(png_ptr);
857 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
858 if (png_ptr->transformations & PNG_BACKGROUND)
860 if (color_type == PNG_COLOR_TYPE_PALETTE)
862 /* could skip if no transparency and
864 png_color back, back_1;
865 png_colorp palette = png_ptr->palette;
866 int num_palette = png_ptr->num_palette;
868 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
870 back.red = png_ptr->gamma_table[png_ptr->background.red];
871 back.green = png_ptr->gamma_table[png_ptr->background.green];
872 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
874 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
875 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
876 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
882 switch (png_ptr->background_gamma_type)
884 case PNG_BACKGROUND_GAMMA_SCREEN:
885 g = (png_ptr->screen_gamma);
888 case PNG_BACKGROUND_GAMMA_FILE:
889 g = 1.0 / (png_ptr->gamma);
890 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
892 case PNG_BACKGROUND_GAMMA_UNIQUE:
893 g = 1.0 / (png_ptr->background_gamma);
894 gs = 1.0 / (png_ptr->background_gamma *
895 png_ptr->screen_gamma);
898 g = 1.0; /* back_1 */
902 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
904 back.red = (png_byte)png_ptr->background.red;
905 back.green = (png_byte)png_ptr->background.green;
906 back.blue = (png_byte)png_ptr->background.blue;
910 back.red = (png_byte)(pow(
911 (double)png_ptr->background.red/255, gs) * 255.0 + .5);
912 back.green = (png_byte)(pow(
913 (double)png_ptr->background.green/255, gs) * 255.0 + .5);
914 back.blue = (png_byte)(pow(
915 (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
918 back_1.red = (png_byte)(pow(
919 (double)png_ptr->background.red/255, g) * 255.0 + .5);
920 back_1.green = (png_byte)(pow(
921 (double)png_ptr->background.green/255, g) * 255.0 + .5);
922 back_1.blue = (png_byte)(pow(
923 (double)png_ptr->background.blue/255, g) * 255.0 + .5);
925 for (i = 0; i < num_palette; i++)
927 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
929 if (png_ptr->trans[i] == 0)
933 else /* if (png_ptr->trans[i] != 0xff) */
937 v = png_ptr->gamma_to_1[palette[i].red];
938 png_composite(w, v, png_ptr->trans[i], back_1.red);
939 palette[i].red = png_ptr->gamma_from_1[w];
941 v = png_ptr->gamma_to_1[palette[i].green];
942 png_composite(w, v, png_ptr->trans[i], back_1.green);
943 palette[i].green = png_ptr->gamma_from_1[w];
945 v = png_ptr->gamma_to_1[palette[i].blue];
946 png_composite(w, v, png_ptr->trans[i], back_1.blue);
947 palette[i].blue = png_ptr->gamma_from_1[w];
952 palette[i].red = png_ptr->gamma_table[palette[i].red];
953 palette[i].green = png_ptr->gamma_table[palette[i].green];
954 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
957 /* Prevent the transformations being done again, and make sure
958 * that the now spurious alpha channel is stripped - the code
959 * has just reduced background composition and gamma correction
960 * to a simple alpha channel strip.
962 png_ptr->transformations &= ~PNG_BACKGROUND;
963 png_ptr->transformations &= ~PNG_GAMMA;
964 png_ptr->transformations |= PNG_STRIP_ALPHA;
966 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
968 /* color_type != PNG_COLOR_TYPE_PALETTE */
970 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
974 switch (png_ptr->background_gamma_type)
976 case PNG_BACKGROUND_GAMMA_SCREEN:
977 g = (png_ptr->screen_gamma);
980 case PNG_BACKGROUND_GAMMA_FILE:
981 g = 1.0 / (png_ptr->gamma);
982 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
984 case PNG_BACKGROUND_GAMMA_UNIQUE:
985 g = 1.0 / (png_ptr->background_gamma);
986 gs = 1.0 / (png_ptr->background_gamma *
987 png_ptr->screen_gamma);
991 png_ptr->background_1.gray = (png_uint_16)(pow(
992 (double)png_ptr->background.gray / m, g) * m + .5);
993 png_ptr->background.gray = (png_uint_16)(pow(
994 (double)png_ptr->background.gray / m, gs) * m + .5);
996 if ((png_ptr->background.red != png_ptr->background.green) ||
997 (png_ptr->background.red != png_ptr->background.blue) ||
998 (png_ptr->background.red != png_ptr->background.gray))
1000 /* RGB or RGBA with color background */
1001 png_ptr->background_1.red = (png_uint_16)(pow(
1002 (double)png_ptr->background.red / m, g) * m + .5);
1003 png_ptr->background_1.green = (png_uint_16)(pow(
1004 (double)png_ptr->background.green / m, g) * m + .5);
1005 png_ptr->background_1.blue = (png_uint_16)(pow(
1006 (double)png_ptr->background.blue / m, g) * m + .5);
1007 png_ptr->background.red = (png_uint_16)(pow(
1008 (double)png_ptr->background.red / m, gs) * m + .5);
1009 png_ptr->background.green = (png_uint_16)(pow(
1010 (double)png_ptr->background.green / m, gs) * m + .5);
1011 png_ptr->background.blue = (png_uint_16)(pow(
1012 (double)png_ptr->background.blue / m, gs) * m + .5);
1016 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
1017 png_ptr->background_1.red = png_ptr->background_1.green
1018 = png_ptr->background_1.blue = png_ptr->background_1.gray;
1019 png_ptr->background.red = png_ptr->background.green
1020 = png_ptr->background.blue = png_ptr->background.gray;
1025 /* transformation does not include PNG_BACKGROUND */
1026 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
1027 if (color_type == PNG_COLOR_TYPE_PALETTE)
1029 png_colorp palette = png_ptr->palette;
1030 int num_palette = png_ptr->num_palette;
1033 for (i = 0; i < num_palette; i++)
1035 palette[i].red = png_ptr->gamma_table[palette[i].red];
1036 palette[i].green = png_ptr->gamma_table[palette[i].green];
1037 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1040 /* Done the gamma correction. */
1041 png_ptr->transformations &= ~PNG_GAMMA;
1044 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1047 #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
1048 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1049 /* No GAMMA transformation */
1050 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1051 (color_type == PNG_COLOR_TYPE_PALETTE))
1054 int istop = (int)png_ptr->num_trans;
1056 png_colorp palette = png_ptr->palette;
1058 back.red = (png_byte)png_ptr->background.red;
1059 back.green = (png_byte)png_ptr->background.green;
1060 back.blue = (png_byte)png_ptr->background.blue;
1062 for (i = 0; i < istop; i++)
1064 if (png_ptr->trans[i] == 0)
1068 else if (png_ptr->trans[i] != 0xff)
1070 /* The png_composite() macro is defined in png.h */
1071 png_composite(palette[i].red, palette[i].red,
1072 png_ptr->trans[i], back.red);
1073 png_composite(palette[i].green, palette[i].green,
1074 png_ptr->trans[i], back.green);
1075 png_composite(palette[i].blue, palette[i].blue,
1076 png_ptr->trans[i], back.blue);
1080 /* Handled alpha, still need to strip the channel. */
1081 png_ptr->transformations &= ~PNG_BACKGROUND;
1082 png_ptr->transformations |= PNG_STRIP_ALPHA;
1084 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
1086 #if defined(PNG_READ_SHIFT_SUPPORTED)
1087 if ((png_ptr->transformations & PNG_SHIFT) &&
1088 (color_type == PNG_COLOR_TYPE_PALETTE))
1091 png_uint_16 istop = png_ptr->num_palette;
1092 int sr = 8 - png_ptr->sig_bit.red;
1093 int sg = 8 - png_ptr->sig_bit.green;
1094 int sb = 8 - png_ptr->sig_bit.blue;
1096 if (sr < 0 || sr > 8)
1098 if (sg < 0 || sg > 8)
1100 if (sb < 0 || sb > 8)
1102 for (i = 0; i < istop; i++)
1104 png_ptr->palette[i].red >>= sr;
1105 png_ptr->palette[i].green >>= sg;
1106 png_ptr->palette[i].blue >>= sb;
1109 #endif /* PNG_READ_SHIFT_SUPPORTED */
1111 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1112 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1118 /* Modify the info structure to reflect the transformations. The
1119 * info should be updated so a PNG file could be written with it,
1120 * assuming the transformations result in valid PNG data.
1123 png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
1125 png_debug(1, "in png_read_transform_info\n");
1126 #if defined(PNG_READ_EXPAND_SUPPORTED)
1127 if (png_ptr->transformations & PNG_EXPAND)
1129 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1131 if (png_ptr->num_trans &&
1132 (png_ptr->transformations & PNG_EXPAND_tRNS))
1133 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1135 info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1136 info_ptr->bit_depth = 8;
1137 info_ptr->num_trans = 0;
1141 if (png_ptr->num_trans)
1143 if (png_ptr->transformations & PNG_EXPAND_tRNS)
1144 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1145 #if 0 /* Removed from libpng-1.2.27 */
1147 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1150 if (info_ptr->bit_depth < 8)
1151 info_ptr->bit_depth = 8;
1152 info_ptr->num_trans = 0;
1157 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1158 if (png_ptr->transformations & PNG_BACKGROUND)
1160 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1161 info_ptr->num_trans = 0;
1162 info_ptr->background = png_ptr->background;
1166 #if defined(PNG_READ_GAMMA_SUPPORTED)
1167 if (png_ptr->transformations & PNG_GAMMA)
1169 #ifdef PNG_FLOATING_POINT_SUPPORTED
1170 info_ptr->gamma = png_ptr->gamma;
1172 #ifdef PNG_FIXED_POINT_SUPPORTED
1173 info_ptr->int_gamma = png_ptr->int_gamma;
1178 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1179 if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
1180 info_ptr->bit_depth = 8;
1183 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1184 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1185 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1188 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1189 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1190 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1193 #if defined(PNG_READ_DITHER_SUPPORTED)
1194 if (png_ptr->transformations & PNG_DITHER)
1196 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1197 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1198 png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1200 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1205 #if defined(PNG_READ_PACK_SUPPORTED)
1206 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
1207 info_ptr->bit_depth = 8;
1210 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1211 info_ptr->channels = 1;
1212 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1213 info_ptr->channels = 3;
1215 info_ptr->channels = 1;
1217 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1218 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1219 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1222 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1223 info_ptr->channels++;
1225 #if defined(PNG_READ_FILLER_SUPPORTED)
1226 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
1227 if ((png_ptr->transformations & PNG_FILLER) &&
1228 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1229 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1231 info_ptr->channels++;
1232 /* if adding a true alpha channel not just filler */
1233 #if !defined(PNG_1_0_X)
1234 if (png_ptr->transformations & PNG_ADD_ALPHA)
1235 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1240 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1241 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1242 if(png_ptr->transformations & PNG_USER_TRANSFORM)
1244 if(info_ptr->bit_depth < png_ptr->user_transform_depth)
1245 info_ptr->bit_depth = png_ptr->user_transform_depth;
1246 if(info_ptr->channels < png_ptr->user_transform_channels)
1247 info_ptr->channels = png_ptr->user_transform_channels;
1251 info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1252 info_ptr->bit_depth);
1254 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width);
1256 #if !defined(PNG_READ_EXPAND_SUPPORTED)
1262 /* Transform the row. The order of transformations is significant,
1263 * and is very touchy. If you add a transformation, take care to
1264 * decide how it fits in with the other transformations here.
1267 png_do_read_transformations(png_structp png_ptr)
1269 png_debug(1, "in png_do_read_transformations\n");
1270 if (png_ptr->row_buf == NULL)
1272 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1275 png_snprintf2(msg, 50,
1276 "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
1278 png_error(png_ptr, msg);
1280 png_error(png_ptr, "NULL row buffer");
1283 #ifdef PNG_WARN_UNINITIALIZED_ROW
1284 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
1285 /* Application has failed to call either png_read_start_image()
1286 * or png_read_update_info() after setting transforms that expand
1287 * pixels. This check added to libpng-1.2.19 */
1288 #if (PNG_WARN_UNINITIALIZED_ROW==1)
1289 png_error(png_ptr, "Uninitialized row");
1291 png_warning(png_ptr, "Uninitialized row");
1295 #if defined(PNG_READ_EXPAND_SUPPORTED)
1296 if (png_ptr->transformations & PNG_EXPAND)
1298 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1300 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1301 png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1305 if (png_ptr->num_trans &&
1306 (png_ptr->transformations & PNG_EXPAND_tRNS))
1307 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1308 &(png_ptr->trans_values));
1310 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1316 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1317 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1318 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1319 PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
1322 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1323 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1326 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1329 png_ptr->rgb_to_gray_status=1;
1330 if((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
1331 PNG_RGB_TO_GRAY_WARN)
1332 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1333 if((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
1334 PNG_RGB_TO_GRAY_ERR)
1335 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1341 From Andreas Dilger e-mail to png-implement, 26 March 1998:
1343 In most cases, the "simple transparency" should be done prior to doing
1344 gray-to-RGB, or you will have to test 3x as many bytes to check if a
1345 pixel is transparent. You would also need to make sure that the
1346 transparency information is upgraded to RGB.
1348 To summarize, the current flow is:
1349 - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1350 with background "in place" if transparent,
1351 convert to RGB if necessary
1352 - Gray + alpha -> composite with gray background and remove alpha bytes,
1353 convert to RGB if necessary
1355 To support RGB backgrounds for gray images we need:
1356 - Gray + simple transparency -> convert to RGB + simple transparency, compare
1357 3 or 6 bytes and composite with background
1358 "in place" if transparent (3x compare/pixel
1359 compared to doing composite with gray bkgrnd)
1360 - Gray + alpha -> convert to RGB + alpha, composite with background and
1361 remove alpha bytes (3x float operations/pixel
1362 compared with composite on gray background)
1364 Greg's change will do this. The reason it wasn't done before is for
1365 performance, as this increases the per-pixel operations. If we would check
1366 in advance if the background was gray or RGB, and position the gray-to-RGB
1367 transform appropriately, then it would save a lot of work/time.
1370 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1371 /* if gray -> RGB, do so now only if background is non-gray; else do later
1372 * for performance reasons */
1373 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1374 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1375 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1378 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1379 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1380 ((png_ptr->num_trans != 0 ) ||
1381 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
1382 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1383 &(png_ptr->trans_values), &(png_ptr->background)
1384 #if defined(PNG_READ_GAMMA_SUPPORTED)
1385 , &(png_ptr->background_1),
1386 png_ptr->gamma_table, png_ptr->gamma_from_1,
1387 png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1388 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1389 png_ptr->gamma_shift
1394 #if defined(PNG_READ_GAMMA_SUPPORTED)
1395 if ((png_ptr->transformations & PNG_GAMMA) &&
1396 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1397 !((png_ptr->transformations & PNG_BACKGROUND) &&
1398 ((png_ptr->num_trans != 0) ||
1399 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1401 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
1402 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1403 png_ptr->gamma_table, png_ptr->gamma_16_table,
1404 png_ptr->gamma_shift);
1407 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1408 if (png_ptr->transformations & PNG_16_TO_8)
1409 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
1412 #if defined(PNG_READ_DITHER_SUPPORTED)
1413 if (png_ptr->transformations & PNG_DITHER)
1415 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1416 png_ptr->palette_lookup, png_ptr->dither_index);
1417 if(png_ptr->row_info.rowbytes == (png_uint_32)0)
1418 png_error(png_ptr, "png_do_dither returned rowbytes=0");
1422 #if defined(PNG_READ_INVERT_SUPPORTED)
1423 if (png_ptr->transformations & PNG_INVERT_MONO)
1424 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
1427 #if defined(PNG_READ_SHIFT_SUPPORTED)
1428 if (png_ptr->transformations & PNG_SHIFT)
1429 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1433 #if defined(PNG_READ_PACK_SUPPORTED)
1434 if (png_ptr->transformations & PNG_PACK)
1435 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
1438 #if defined(PNG_READ_BGR_SUPPORTED)
1439 if (png_ptr->transformations & PNG_BGR)
1440 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
1443 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
1444 if (png_ptr->transformations & PNG_PACKSWAP)
1445 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1448 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1449 /* if gray -> RGB, do so now only if we did not do so above */
1450 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1451 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1452 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1455 #if defined(PNG_READ_FILLER_SUPPORTED)
1456 if (png_ptr->transformations & PNG_FILLER)
1457 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1458 (png_uint_32)png_ptr->filler, png_ptr->flags);
1461 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1462 if (png_ptr->transformations & PNG_INVERT_ALPHA)
1463 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1466 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1467 if (png_ptr->transformations & PNG_SWAP_ALPHA)
1468 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1471 #if defined(PNG_READ_SWAP_SUPPORTED)
1472 if (png_ptr->transformations & PNG_SWAP_BYTES)
1473 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1476 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1477 if (png_ptr->transformations & PNG_USER_TRANSFORM)
1479 if(png_ptr->read_user_transform_fn != NULL)
1480 (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1481 (png_ptr, /* png_ptr */
1482 &(png_ptr->row_info), /* row_info: */
1483 /* png_uint_32 width; width of row */
1484 /* png_uint_32 rowbytes; number of bytes in row */
1485 /* png_byte color_type; color type of pixels */
1486 /* png_byte bit_depth; bit depth of samples */
1487 /* png_byte channels; number of channels (1-4) */
1488 /* png_byte pixel_depth; bits per pixel (depth*channels) */
1489 png_ptr->row_buf + 1); /* start of pixel data for row */
1490 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
1491 if(png_ptr->user_transform_depth)
1492 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1493 if(png_ptr->user_transform_channels)
1494 png_ptr->row_info.channels = png_ptr->user_transform_channels;
1496 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1497 png_ptr->row_info.channels);
1498 png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
1499 png_ptr->row_info.width);
1505 #if defined(PNG_READ_PACK_SUPPORTED)
1506 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1507 * without changing the actual values. Thus, if you had a row with
1508 * a bit depth of 1, you would end up with bytes that only contained
1509 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1510 * png_do_shift() after this.
1513 png_do_unpack(png_row_infop row_info, png_bytep row)
1515 png_debug(1, "in png_do_unpack\n");
1516 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1517 if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1519 if (row_info->bit_depth < 8)
1523 png_uint_32 row_width=row_info->width;
1525 switch (row_info->bit_depth)
1529 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1530 png_bytep dp = row + (png_size_t)row_width - 1;
1531 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
1532 for (i = 0; i < row_width; i++)
1534 *dp = (png_byte)((*sp >> shift) & 0x01);
1550 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1551 png_bytep dp = row + (png_size_t)row_width - 1;
1552 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
1553 for (i = 0; i < row_width; i++)
1555 *dp = (png_byte)((*sp >> shift) & 0x03);
1570 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1571 png_bytep dp = row + (png_size_t)row_width - 1;
1572 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
1573 for (i = 0; i < row_width; i++)
1575 *dp = (png_byte)((*sp >> shift) & 0x0f);
1589 row_info->bit_depth = 8;
1590 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1591 row_info->rowbytes = row_width * row_info->channels;
1596 #if defined(PNG_READ_SHIFT_SUPPORTED)
1597 /* Reverse the effects of png_do_shift. This routine merely shifts the
1598 * pixels back to their significant bits values. Thus, if you have
1599 * a row of bit depth 8, but only 5 are significant, this will shift
1600 * the values back to 0 through 31.
1603 png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
1605 png_debug(1, "in png_do_unshift\n");
1607 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1608 row != NULL && row_info != NULL && sig_bits != NULL &&
1610 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
1615 png_uint_16 value = 0;
1616 png_uint_32 row_width = row_info->width;
1618 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1620 shift[channels++] = row_info->bit_depth - sig_bits->red;
1621 shift[channels++] = row_info->bit_depth - sig_bits->green;
1622 shift[channels++] = row_info->bit_depth - sig_bits->blue;
1626 shift[channels++] = row_info->bit_depth - sig_bits->gray;
1628 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1630 shift[channels++] = row_info->bit_depth - sig_bits->alpha;
1633 for (c = 0; c < channels; c++)
1644 switch (row_info->bit_depth)
1650 png_uint_32 istop = row_info->rowbytes;
1652 for (bp = row, i = 0; i < istop; i++)
1663 png_uint_32 istop = row_info->rowbytes;
1664 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1665 (png_byte)((int)0xf >> shift[0]));
1667 for (i = 0; i < istop; i++)
1678 png_uint_32 istop = row_width * channels;
1680 for (i = 0; i < istop; i++)
1682 *bp++ >>= shift[i%channels];
1690 png_uint_32 istop = channels * row_width;
1692 for (i = 0; i < istop; i++)
1694 value = (png_uint_16)((*bp << 8) + *(bp + 1));
1695 value >>= shift[i%channels];
1696 *bp++ = (png_byte)(value >> 8);
1697 *bp++ = (png_byte)(value & 0xff);
1706 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1707 /* chop rows of bit depth 16 down to 8 */
1709 png_do_chop(png_row_infop row_info, png_bytep row)
1711 png_debug(1, "in png_do_chop\n");
1712 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1713 if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1715 if (row_info->bit_depth == 16)
1721 png_uint_32 istop = row_info->width * row_info->channels;
1723 for (i = 0; i<istop; i++, sp += 2, dp++)
1725 #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
1726 /* This does a more accurate scaling of the 16-bit color
1727 * value, rather than a simple low-byte truncation.
1729 * What the ideal calculation should be:
1730 * *dp = (((((png_uint_32)(*sp) << 8) |
1731 * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1733 * GRR: no, I think this is what it really should be:
1734 * *dp = (((((png_uint_32)(*sp) << 8) |
1735 * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1737 * GRR: here's the exact calculation with shifts:
1738 * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1739 * *dp = (temp - (temp >> 8)) >> 8;
1741 * Approximate calculation with shift/add instead of multiply/divide:
1742 * *dp = ((((png_uint_32)(*sp) << 8) |
1743 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1745 * What we actually do to avoid extra shifting and conversion:
1748 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1750 /* Simply discard the low order byte */
1754 row_info->bit_depth = 8;
1755 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1756 row_info->rowbytes = row_info->width * row_info->channels;
1761 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1763 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1765 png_debug(1, "in png_do_read_swap_alpha\n");
1766 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1767 if (row != NULL && row_info != NULL)
1770 png_uint_32 row_width = row_info->width;
1771 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1773 /* This converts from RGBA to ARGB */
1774 if (row_info->bit_depth == 8)
1776 png_bytep sp = row + row_info->rowbytes;
1781 for (i = 0; i < row_width; i++)
1790 /* This converts from RRGGBBAA to AARRGGBB */
1793 png_bytep sp = row + row_info->rowbytes;
1798 for (i = 0; i < row_width; i++)
1813 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1815 /* This converts from GA to AG */
1816 if (row_info->bit_depth == 8)
1818 png_bytep sp = row + row_info->rowbytes;
1823 for (i = 0; i < row_width; i++)
1830 /* This converts from GGAA to AAGG */
1833 png_bytep sp = row + row_info->rowbytes;
1838 for (i = 0; i < row_width; i++)
1853 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1855 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1857 png_debug(1, "in png_do_read_invert_alpha\n");
1858 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1859 if (row != NULL && row_info != NULL)
1862 png_uint_32 row_width = row_info->width;
1863 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1865 /* This inverts the alpha channel in RGBA */
1866 if (row_info->bit_depth == 8)
1868 png_bytep sp = row + row_info->rowbytes;
1872 for (i = 0; i < row_width; i++)
1874 *(--dp) = (png_byte)(255 - *(--sp));
1876 /* This does nothing:
1880 We can replace it with:
1886 /* This inverts the alpha channel in RRGGBBAA */
1889 png_bytep sp = row + row_info->rowbytes;
1893 for (i = 0; i < row_width; i++)
1895 *(--dp) = (png_byte)(255 - *(--sp));
1896 *(--dp) = (png_byte)(255 - *(--sp));
1898 /* This does nothing:
1905 We can replace it with:
1912 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1914 /* This inverts the alpha channel in GA */
1915 if (row_info->bit_depth == 8)
1917 png_bytep sp = row + row_info->rowbytes;
1921 for (i = 0; i < row_width; i++)
1923 *(--dp) = (png_byte)(255 - *(--sp));
1927 /* This inverts the alpha channel in GGAA */
1930 png_bytep sp = row + row_info->rowbytes;
1934 for (i = 0; i < row_width; i++)
1936 *(--dp) = (png_byte)(255 - *(--sp));
1937 *(--dp) = (png_byte)(255 - *(--sp));
1951 #if defined(PNG_READ_FILLER_SUPPORTED)
1952 /* Add filler channel if we have RGB color */
1954 png_do_read_filler(png_row_infop row_info, png_bytep row,
1955 png_uint_32 filler, png_uint_32 flags)
1958 png_uint_32 row_width = row_info->width;
1960 png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
1961 png_byte lo_filler = (png_byte)(filler & 0xff);
1963 png_debug(1, "in png_do_read_filler\n");
1965 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1966 row != NULL && row_info != NULL &&
1968 row_info->color_type == PNG_COLOR_TYPE_GRAY)
1970 if(row_info->bit_depth == 8)
1972 /* This changes the data from G to GX */
1973 if (flags & PNG_FLAG_FILLER_AFTER)
1975 png_bytep sp = row + (png_size_t)row_width;
1976 png_bytep dp = sp + (png_size_t)row_width;
1977 for (i = 1; i < row_width; i++)
1979 *(--dp) = lo_filler;
1982 *(--dp) = lo_filler;
1983 row_info->channels = 2;
1984 row_info->pixel_depth = 16;
1985 row_info->rowbytes = row_width * 2;
1987 /* This changes the data from G to XG */
1990 png_bytep sp = row + (png_size_t)row_width;
1991 png_bytep dp = sp + (png_size_t)row_width;
1992 for (i = 0; i < row_width; i++)
1995 *(--dp) = lo_filler;
1997 row_info->channels = 2;
1998 row_info->pixel_depth = 16;
1999 row_info->rowbytes = row_width * 2;
2002 else if(row_info->bit_depth == 16)
2004 /* This changes the data from GG to GGXX */
2005 if (flags & PNG_FLAG_FILLER_AFTER)
2007 png_bytep sp = row + (png_size_t)row_width * 2;
2008 png_bytep dp = sp + (png_size_t)row_width * 2;
2009 for (i = 1; i < row_width; i++)
2011 *(--dp) = hi_filler;
2012 *(--dp) = lo_filler;
2016 *(--dp) = hi_filler;
2017 *(--dp) = lo_filler;
2018 row_info->channels = 2;
2019 row_info->pixel_depth = 32;
2020 row_info->rowbytes = row_width * 4;
2022 /* This changes the data from GG to XXGG */
2025 png_bytep sp = row + (png_size_t)row_width * 2;
2026 png_bytep dp = sp + (png_size_t)row_width * 2;
2027 for (i = 0; i < row_width; i++)
2031 *(--dp) = hi_filler;
2032 *(--dp) = lo_filler;
2034 row_info->channels = 2;
2035 row_info->pixel_depth = 32;
2036 row_info->rowbytes = row_width * 4;
2039 } /* COLOR_TYPE == GRAY */
2040 else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2042 if(row_info->bit_depth == 8)
2044 /* This changes the data from RGB to RGBX */
2045 if (flags & PNG_FLAG_FILLER_AFTER)
2047 png_bytep sp = row + (png_size_t)row_width * 3;
2048 png_bytep dp = sp + (png_size_t)row_width;
2049 for (i = 1; i < row_width; i++)
2051 *(--dp) = lo_filler;
2056 *(--dp) = lo_filler;
2057 row_info->channels = 4;
2058 row_info->pixel_depth = 32;
2059 row_info->rowbytes = row_width * 4;
2061 /* This changes the data from RGB to XRGB */
2064 png_bytep sp = row + (png_size_t)row_width * 3;
2065 png_bytep dp = sp + (png_size_t)row_width;
2066 for (i = 0; i < row_width; i++)
2071 *(--dp) = lo_filler;
2073 row_info->channels = 4;
2074 row_info->pixel_depth = 32;
2075 row_info->rowbytes = row_width * 4;
2078 else if(row_info->bit_depth == 16)
2080 /* This changes the data from RRGGBB to RRGGBBXX */
2081 if (flags & PNG_FLAG_FILLER_AFTER)
2083 png_bytep sp = row + (png_size_t)row_width * 6;
2084 png_bytep dp = sp + (png_size_t)row_width * 2;
2085 for (i = 1; i < row_width; i++)
2087 *(--dp) = hi_filler;
2088 *(--dp) = lo_filler;
2096 *(--dp) = hi_filler;
2097 *(--dp) = lo_filler;
2098 row_info->channels = 4;
2099 row_info->pixel_depth = 64;
2100 row_info->rowbytes = row_width * 8;
2102 /* This changes the data from RRGGBB to XXRRGGBB */
2105 png_bytep sp = row + (png_size_t)row_width * 6;
2106 png_bytep dp = sp + (png_size_t)row_width * 2;
2107 for (i = 0; i < row_width; i++)
2115 *(--dp) = hi_filler;
2116 *(--dp) = lo_filler;
2118 row_info->channels = 4;
2119 row_info->pixel_depth = 64;
2120 row_info->rowbytes = row_width * 8;
2123 } /* COLOR_TYPE == RGB */
2127 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2128 /* expand grayscale files to RGB, with or without alpha */
2130 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
2133 png_uint_32 row_width = row_info->width;
2135 png_debug(1, "in png_do_gray_to_rgb\n");
2136 if (row_info->bit_depth >= 8 &&
2137 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2138 row != NULL && row_info != NULL &&
2140 !(row_info->color_type & PNG_COLOR_MASK_COLOR))
2142 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2144 if (row_info->bit_depth == 8)
2146 png_bytep sp = row + (png_size_t)row_width - 1;
2147 png_bytep dp = sp + (png_size_t)row_width * 2;
2148 for (i = 0; i < row_width; i++)
2157 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2158 png_bytep dp = sp + (png_size_t)row_width * 4;
2159 for (i = 0; i < row_width; i++)
2162 *(dp--) = *(sp - 1);
2164 *(dp--) = *(sp - 1);
2170 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2172 if (row_info->bit_depth == 8)
2174 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2175 png_bytep dp = sp + (png_size_t)row_width * 2;
2176 for (i = 0; i < row_width; i++)
2186 png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2187 png_bytep dp = sp + (png_size_t)row_width * 4;
2188 for (i = 0; i < row_width; i++)
2193 *(dp--) = *(sp - 1);
2195 *(dp--) = *(sp - 1);
2201 row_info->channels += (png_byte)2;
2202 row_info->color_type |= PNG_COLOR_MASK_COLOR;
2203 row_info->pixel_depth = (png_byte)(row_info->channels *
2204 row_info->bit_depth);
2205 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
2210 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
2211 /* reduce RGB files to grayscale, with or without alpha
2212 * using the equation given in Poynton's ColorFAQ at
2213 * <http://www.inforamp.net/~poynton/>
2214 * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net
2216 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2218 * We approximate this with
2220 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
2222 * which can be expressed with integers as
2224 * Y = (6969 * R + 23434 * G + 2365 * B)/32768
2226 * The calculation is to be done in a linear colorspace.
2228 * Other integer coefficents can be used via png_set_rgb_to_gray().
2231 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2236 png_uint_32 row_width = row_info->width;
2239 png_debug(1, "in png_do_rgb_to_gray\n");
2241 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2242 row != NULL && row_info != NULL &&
2244 (row_info->color_type & PNG_COLOR_MASK_COLOR))
2246 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2247 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2248 png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
2250 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2252 if (row_info->bit_depth == 8)
2254 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2255 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2260 for (i = 0; i < row_width; i++)
2262 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2263 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2264 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2265 if(red != green || red != blue)
2268 *(dp++) = png_ptr->gamma_from_1[
2269 (rc*red+gc*green+bc*blue)>>15];
2280 for (i = 0; i < row_width; i++)
2282 png_byte red = *(sp++);
2283 png_byte green = *(sp++);
2284 png_byte blue = *(sp++);
2285 if(red != green || red != blue)
2288 *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
2296 else /* RGB bit_depth == 16 */
2298 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2299 if (png_ptr->gamma_16_to_1 != NULL &&
2300 png_ptr->gamma_16_from_1 != NULL)
2304 for (i = 0; i < row_width; i++)
2306 png_uint_16 red, green, blue, w;
2308 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2309 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2310 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2312 if(red == green && red == blue)
2316 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2317 png_ptr->gamma_shift][red>>8];
2318 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2319 png_ptr->gamma_shift][green>>8];
2320 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2321 png_ptr->gamma_shift][blue>>8];
2322 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
2324 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2325 png_ptr->gamma_shift][gray16 >> 8];
2329 *(dp++) = (png_byte)((w>>8) & 0xff);
2330 *(dp++) = (png_byte)(w & 0xff);
2338 for (i = 0; i < row_width; i++)
2340 png_uint_16 red, green, blue, gray16;
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)
2348 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2349 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2350 *(dp++) = (png_byte)(gray16 & 0xff);
2355 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2357 if (row_info->bit_depth == 8)
2359 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2360 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2364 for (i = 0; i < row_width; i++)
2366 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2367 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2368 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2369 if(red != green || red != blue)
2371 *(dp++) = png_ptr->gamma_from_1
2372 [(rc*red + gc*green + bc*blue)>>15];
2373 *(dp++) = *(sp++); /* alpha */
2381 for (i = 0; i < row_width; i++)
2383 png_byte red = *(sp++);
2384 png_byte green = *(sp++);
2385 png_byte blue = *(sp++);
2386 if(red != green || red != blue)
2388 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
2389 *(dp++) = *(sp++); /* alpha */
2393 else /* RGBA bit_depth == 16 */
2395 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2396 if (png_ptr->gamma_16_to_1 != NULL &&
2397 png_ptr->gamma_16_from_1 != NULL)
2401 for (i = 0; i < row_width; i++)
2403 png_uint_16 red, green, blue, w;
2405 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2406 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2407 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2409 if(red == green && red == blue)
2413 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2414 png_ptr->gamma_shift][red>>8];
2415 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2416 png_ptr->gamma_shift][green>>8];
2417 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2418 png_ptr->gamma_shift][blue>>8];
2419 png_uint_16 gray16 = (png_uint_16)((rc * red_1
2420 + gc * green_1 + bc * blue_1)>>15);
2421 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2422 png_ptr->gamma_shift][gray16 >> 8];
2426 *(dp++) = (png_byte)((w>>8) & 0xff);
2427 *(dp++) = (png_byte)(w & 0xff);
2428 *(dp++) = *(sp++); /* alpha */
2437 for (i = 0; i < row_width; i++)
2439 png_uint_16 red, green, blue, gray16;
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;
2443 if(red != green || red != blue)
2445 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2446 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2447 *(dp++) = (png_byte)(gray16 & 0xff);
2448 *(dp++) = *(sp++); /* alpha */
2454 row_info->channels -= (png_byte)2;
2455 row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2456 row_info->pixel_depth = (png_byte)(row_info->channels *
2457 row_info->bit_depth);
2458 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
2464 /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
2465 * large of png_color. This lets grayscale images be treated as
2466 * paletted. Most useful for gamma correction and simplification
2470 png_build_grayscale_palette(int bit_depth, png_colorp palette)
2477 png_debug(1, "in png_do_build_grayscale_palette\n");
2478 if (palette == NULL)
2505 for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2507 palette[i].red = (png_byte)v;
2508 palette[i].green = (png_byte)v;
2509 palette[i].blue = (png_byte)v;
2513 /* This function is currently unused. Do we really need it? */
2514 #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
2516 png_correct_palette(png_structp png_ptr, png_colorp palette,
2519 png_debug(1, "in png_correct_palette\n");
2520 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2521 defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
2522 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
2524 png_color back, back_1;
2526 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
2528 back.red = png_ptr->gamma_table[png_ptr->background.red];
2529 back.green = png_ptr->gamma_table[png_ptr->background.green];
2530 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
2532 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
2533 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
2534 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
2540 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
2542 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2543 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
2545 back.red = png_ptr->background.red;
2546 back.green = png_ptr->background.green;
2547 back.blue = png_ptr->background.blue;
2552 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2555 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2558 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2562 g = 1.0 / png_ptr->background_gamma;
2565 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2568 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2571 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2575 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2579 for (i = 0; i < (png_uint_32)num_palette; i++)
2581 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
2585 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
2589 v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
2590 png_composite(w, v, png_ptr->trans[i], back_1.red);
2591 palette[i].red = png_ptr->gamma_from_1[w];
2593 v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
2594 png_composite(w, v, png_ptr->trans[i], back_1.green);
2595 palette[i].green = png_ptr->gamma_from_1[w];
2597 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
2598 png_composite(w, v, png_ptr->trans[i], back_1.blue);
2599 palette[i].blue = png_ptr->gamma_from_1[w];
2603 palette[i].red = png_ptr->gamma_table[palette[i].red];
2604 palette[i].green = png_ptr->gamma_table[palette[i].green];
2605 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2613 for (i = 0; i < num_palette; i++)
2615 if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
2621 palette[i].red = png_ptr->gamma_table[palette[i].red];
2622 palette[i].green = png_ptr->gamma_table[palette[i].green];
2623 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2630 #if defined(PNG_READ_GAMMA_SUPPORTED)
2631 if (png_ptr->transformations & PNG_GAMMA)
2635 for (i = 0; i < num_palette; i++)
2637 palette[i].red = png_ptr->gamma_table[palette[i].red];
2638 palette[i].green = png_ptr->gamma_table[palette[i].green];
2639 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2642 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2646 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2647 if (png_ptr->transformations & PNG_BACKGROUND)
2649 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2653 back.red = (png_byte)png_ptr->background.red;
2654 back.green = (png_byte)png_ptr->background.green;
2655 back.blue = (png_byte)png_ptr->background.blue;
2657 for (i = 0; i < (int)png_ptr->num_trans; i++)
2659 if (png_ptr->trans[i] == 0)
2661 palette[i].red = back.red;
2662 palette[i].green = back.green;
2663 palette[i].blue = back.blue;
2665 else if (png_ptr->trans[i] != 0xff)
2667 png_composite(palette[i].red, png_ptr->palette[i].red,
2668 png_ptr->trans[i], back.red);
2669 png_composite(palette[i].green, png_ptr->palette[i].green,
2670 png_ptr->trans[i], back.green);
2671 png_composite(palette[i].blue, png_ptr->palette[i].blue,
2672 png_ptr->trans[i], back.blue);
2676 else /* assume grayscale palette (what else could it be?) */
2680 for (i = 0; i < num_palette; i++)
2682 if (i == (png_byte)png_ptr->trans_values.gray)
2684 palette[i].red = (png_byte)png_ptr->background.red;
2685 palette[i].green = (png_byte)png_ptr->background.green;
2686 palette[i].blue = (png_byte)png_ptr->background.blue;
2695 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2696 /* Replace any alpha or transparency with the supplied background color.
2697 * "background" is already in the screen gamma, while "background_1" is
2698 * at a gamma of 1.0. Paletted files have already been taken care of.
2701 png_do_background(png_row_infop row_info, png_bytep row,
2702 png_color_16p trans_values, png_color_16p background
2703 #if defined(PNG_READ_GAMMA_SUPPORTED)
2704 , png_color_16p background_1,
2705 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
2706 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2707 png_uint_16pp gamma_16_to_1, int gamma_shift
2713 png_uint_32 row_width=row_info->width;
2716 png_debug(1, "in png_do_background\n");
2717 if (background != NULL &&
2718 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2719 row != NULL && row_info != NULL &&
2721 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
2722 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
2724 switch (row_info->color_type)
2726 case PNG_COLOR_TYPE_GRAY:
2728 switch (row_info->bit_depth)
2734 for (i = 0; i < row_width; i++)
2736 if ((png_uint_16)((*sp >> shift) & 0x01)
2737 == trans_values->gray)
2739 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2740 *sp |= (png_byte)(background->gray << shift);
2754 #if defined(PNG_READ_GAMMA_SUPPORTED)
2755 if (gamma_table != NULL)
2759 for (i = 0; i < row_width; i++)
2761 if ((png_uint_16)((*sp >> shift) & 0x03)
2762 == trans_values->gray)
2764 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2765 *sp |= (png_byte)(background->gray << shift);
2769 png_byte p = (png_byte)((*sp >> shift) & 0x03);
2770 png_byte g = (png_byte)((gamma_table [p | (p << 2) |
2771 (p << 4) | (p << 6)] >> 6) & 0x03);
2772 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2773 *sp |= (png_byte)(g << shift);
2789 for (i = 0; i < row_width; i++)
2791 if ((png_uint_16)((*sp >> shift) & 0x03)
2792 == trans_values->gray)
2794 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2795 *sp |= (png_byte)(background->gray << shift);
2810 #if defined(PNG_READ_GAMMA_SUPPORTED)
2811 if (gamma_table != NULL)
2815 for (i = 0; i < row_width; i++)
2817 if ((png_uint_16)((*sp >> shift) & 0x0f)
2818 == trans_values->gray)
2820 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2821 *sp |= (png_byte)(background->gray << shift);
2825 png_byte p = (png_byte)((*sp >> shift) & 0x0f);
2826 png_byte g = (png_byte)((gamma_table[p |
2827 (p << 4)] >> 4) & 0x0f);
2828 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2829 *sp |= (png_byte)(g << shift);
2845 for (i = 0; i < row_width; i++)
2847 if ((png_uint_16)((*sp >> shift) & 0x0f)
2848 == trans_values->gray)
2850 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2851 *sp |= (png_byte)(background->gray << shift);
2866 #if defined(PNG_READ_GAMMA_SUPPORTED)
2867 if (gamma_table != NULL)
2870 for (i = 0; i < row_width; i++, sp++)
2872 if (*sp == trans_values->gray)
2874 *sp = (png_byte)background->gray;
2878 *sp = gamma_table[*sp];
2886 for (i = 0; i < row_width; i++, sp++)
2888 if (*sp == trans_values->gray)
2890 *sp = (png_byte)background->gray;
2898 #if defined(PNG_READ_GAMMA_SUPPORTED)
2899 if (gamma_16 != NULL)
2902 for (i = 0; i < row_width; i++, sp += 2)
2906 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2907 if (v == trans_values->gray)
2909 /* background is already in screen gamma */
2910 *sp = (png_byte)((background->gray >> 8) & 0xff);
2911 *(sp + 1) = (png_byte)(background->gray & 0xff);
2915 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2916 *sp = (png_byte)((v >> 8) & 0xff);
2917 *(sp + 1) = (png_byte)(v & 0xff);
2925 for (i = 0; i < row_width; i++, sp += 2)
2929 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2930 if (v == trans_values->gray)
2932 *sp = (png_byte)((background->gray >> 8) & 0xff);
2933 *(sp + 1) = (png_byte)(background->gray & 0xff);
2942 case PNG_COLOR_TYPE_RGB:
2944 if (row_info->bit_depth == 8)
2946 #if defined(PNG_READ_GAMMA_SUPPORTED)
2947 if (gamma_table != NULL)
2950 for (i = 0; i < row_width; i++, sp += 3)
2952 if (*sp == trans_values->red &&
2953 *(sp + 1) == trans_values->green &&
2954 *(sp + 2) == trans_values->blue)
2956 *sp = (png_byte)background->red;
2957 *(sp + 1) = (png_byte)background->green;
2958 *(sp + 2) = (png_byte)background->blue;
2962 *sp = gamma_table[*sp];
2963 *(sp + 1) = gamma_table[*(sp + 1)];
2964 *(sp + 2) = gamma_table[*(sp + 2)];
2972 for (i = 0; i < row_width; i++, sp += 3)
2974 if (*sp == trans_values->red &&
2975 *(sp + 1) == trans_values->green &&
2976 *(sp + 2) == trans_values->blue)
2978 *sp = (png_byte)background->red;
2979 *(sp + 1) = (png_byte)background->green;
2980 *(sp + 2) = (png_byte)background->blue;
2985 else /* if (row_info->bit_depth == 16) */
2987 #if defined(PNG_READ_GAMMA_SUPPORTED)
2988 if (gamma_16 != NULL)
2991 for (i = 0; i < row_width; i++, sp += 6)
2993 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2994 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2995 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
2996 if (r == trans_values->red && g == trans_values->green &&
2997 b == trans_values->blue)
2999 /* background is already in screen gamma */
3000 *sp = (png_byte)((background->red >> 8) & 0xff);
3001 *(sp + 1) = (png_byte)(background->red & 0xff);
3002 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
3003 *(sp + 3) = (png_byte)(background->green & 0xff);
3004 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3005 *(sp + 5) = (png_byte)(background->blue & 0xff);
3009 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3010 *sp = (png_byte)((v >> 8) & 0xff);
3011 *(sp + 1) = (png_byte)(v & 0xff);
3012 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3013 *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3014 *(sp + 3) = (png_byte)(v & 0xff);
3015 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3016 *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3017 *(sp + 5) = (png_byte)(v & 0xff);
3025 for (i = 0; i < row_width; i++, sp += 6)
3027 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
3028 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3029 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
3031 if (r == trans_values->red && g == trans_values->green &&
3032 b == trans_values->blue)
3034 *sp = (png_byte)((background->red >> 8) & 0xff);
3035 *(sp + 1) = (png_byte)(background->red & 0xff);
3036 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
3037 *(sp + 3) = (png_byte)(background->green & 0xff);
3038 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3039 *(sp + 5) = (png_byte)(background->blue & 0xff);
3046 case PNG_COLOR_TYPE_GRAY_ALPHA:
3048 if (row_info->bit_depth == 8)
3050 #if defined(PNG_READ_GAMMA_SUPPORTED)
3051 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3052 gamma_table != NULL)
3056 for (i = 0; i < row_width; i++, sp += 2, dp++)
3058 png_uint_16 a = *(sp + 1);
3062 *dp = gamma_table[*sp];
3066 /* background is already in screen gamma */
3067 *dp = (png_byte)background->gray;
3073 v = gamma_to_1[*sp];
3074 png_composite(w, v, a, background_1->gray);
3075 *dp = gamma_from_1[w];
3084 for (i = 0; i < row_width; i++, sp += 2, dp++)
3086 png_byte a = *(sp + 1);
3092 #if defined(PNG_READ_GAMMA_SUPPORTED)
3095 *dp = (png_byte)background->gray;
3099 png_composite(*dp, *sp, a, background_1->gray);
3102 *dp = (png_byte)background->gray;
3107 else /* if (png_ptr->bit_depth == 16) */
3109 #if defined(PNG_READ_GAMMA_SUPPORTED)
3110 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3111 gamma_16_to_1 != NULL)
3115 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3117 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3119 if (a == (png_uint_16)0xffff)
3123 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3124 *dp = (png_byte)((v >> 8) & 0xff);
3125 *(dp + 1) = (png_byte)(v & 0xff);
3127 #if defined(PNG_READ_GAMMA_SUPPORTED)
3133 /* background is already in screen gamma */
3134 *dp = (png_byte)((background->gray >> 8) & 0xff);
3135 *(dp + 1) = (png_byte)(background->gray & 0xff);
3137 #if defined(PNG_READ_GAMMA_SUPPORTED)
3140 png_uint_16 g, v, w;
3142 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3143 png_composite_16(v, g, a, background_1->gray);
3144 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3145 *dp = (png_byte)((w >> 8) & 0xff);
3146 *(dp + 1) = (png_byte)(w & 0xff);
3156 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3158 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3159 if (a == (png_uint_16)0xffff)
3161 png_memcpy(dp, sp, 2);
3163 #if defined(PNG_READ_GAMMA_SUPPORTED)
3169 *dp = (png_byte)((background->gray >> 8) & 0xff);
3170 *(dp + 1) = (png_byte)(background->gray & 0xff);
3172 #if defined(PNG_READ_GAMMA_SUPPORTED)
3177 g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3178 png_composite_16(v, g, a, background_1->gray);
3179 *dp = (png_byte)((v >> 8) & 0xff);
3180 *(dp + 1) = (png_byte)(v & 0xff);
3188 case PNG_COLOR_TYPE_RGB_ALPHA:
3190 if (row_info->bit_depth == 8)
3192 #if defined(PNG_READ_GAMMA_SUPPORTED)
3193 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3194 gamma_table != NULL)
3198 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3200 png_byte a = *(sp + 3);
3204 *dp = gamma_table[*sp];
3205 *(dp + 1) = gamma_table[*(sp + 1)];
3206 *(dp + 2) = gamma_table[*(sp + 2)];
3210 /* background is already in screen gamma */
3211 *dp = (png_byte)background->red;
3212 *(dp + 1) = (png_byte)background->green;
3213 *(dp + 2) = (png_byte)background->blue;
3219 v = gamma_to_1[*sp];
3220 png_composite(w, v, a, background_1->red);
3221 *dp = gamma_from_1[w];
3222 v = gamma_to_1[*(sp + 1)];
3223 png_composite(w, v, a, background_1->green);
3224 *(dp + 1) = gamma_from_1[w];
3225 v = gamma_to_1[*(sp + 2)];
3226 png_composite(w, v, a, background_1->blue);
3227 *(dp + 2) = gamma_from_1[w];
3236 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3238 png_byte a = *(sp + 3);
3243 *(dp + 1) = *(sp + 1);
3244 *(dp + 2) = *(sp + 2);
3248 *dp = (png_byte)background->red;
3249 *(dp + 1) = (png_byte)background->green;
3250 *(dp + 2) = (png_byte)background->blue;
3254 png_composite(*dp, *sp, a, background->red);
3255 png_composite(*(dp + 1), *(sp + 1), a,
3257 png_composite(*(dp + 2), *(sp + 2), a,
3263 else /* if (row_info->bit_depth == 16) */
3265 #if defined(PNG_READ_GAMMA_SUPPORTED)
3266 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3267 gamma_16_to_1 != NULL)
3271 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3273 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3274 << 8) + (png_uint_16)(*(sp + 7)));
3275 if (a == (png_uint_16)0xffff)
3279 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3280 *dp = (png_byte)((v >> 8) & 0xff);
3281 *(dp + 1) = (png_byte)(v & 0xff);
3282 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3283 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3284 *(dp + 3) = (png_byte)(v & 0xff);
3285 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3286 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3287 *(dp + 5) = (png_byte)(v & 0xff);
3291 /* background is already in screen gamma */
3292 *dp = (png_byte)((background->red >> 8) & 0xff);
3293 *(dp + 1) = (png_byte)(background->red & 0xff);
3294 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3295 *(dp + 3) = (png_byte)(background->green & 0xff);
3296 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3297 *(dp + 5) = (png_byte)(background->blue & 0xff);
3301 png_uint_16 v, w, x;
3303 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3304 png_composite_16(w, v, a, background_1->red);
3305 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3306 *dp = (png_byte)((x >> 8) & 0xff);
3307 *(dp + 1) = (png_byte)(x & 0xff);
3308 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3309 png_composite_16(w, v, a, background_1->green);
3310 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3311 *(dp + 2) = (png_byte)((x >> 8) & 0xff);
3312 *(dp + 3) = (png_byte)(x & 0xff);
3313 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3314 png_composite_16(w, v, a, background_1->blue);
3315 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3316 *(dp + 4) = (png_byte)((x >> 8) & 0xff);
3317 *(dp + 5) = (png_byte)(x & 0xff);
3326 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3328 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3329 << 8) + (png_uint_16)(*(sp + 7)));
3330 if (a == (png_uint_16)0xffff)
3332 png_memcpy(dp, sp, 6);
3336 *dp = (png_byte)((background->red >> 8) & 0xff);
3337 *(dp + 1) = (png_byte)(background->red & 0xff);
3338 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3339 *(dp + 3) = (png_byte)(background->green & 0xff);
3340 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3341 *(dp + 5) = (png_byte)(background->blue & 0xff);
3347 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3348 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3350 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3353 png_composite_16(v, r, a, background->red);
3354 *dp = (png_byte)((v >> 8) & 0xff);
3355 *(dp + 1) = (png_byte)(v & 0xff);
3356 png_composite_16(v, g, a, background->green);
3357 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3358 *(dp + 3) = (png_byte)(v & 0xff);
3359 png_composite_16(v, b, a, background->blue);
3360 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3361 *(dp + 5) = (png_byte)(v & 0xff);
3370 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3372 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
3373 row_info->channels--;
3374 row_info->pixel_depth = (png_byte)(row_info->channels *
3375 row_info->bit_depth);
3376 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3382 #if defined(PNG_READ_GAMMA_SUPPORTED)
3383 /* Gamma correct the image, avoiding the alpha channel. Make sure
3384 * you do this after you deal with the transparency issue on grayscale
3385 * or RGB images. If your bit depth is 8, use gamma_table, if it
3386 * is 16, use gamma_16_table and gamma_shift. Build these with
3387 * build_gamma_table().
3390 png_do_gamma(png_row_infop row_info, png_bytep row,
3391 png_bytep gamma_table, png_uint_16pp gamma_16_table,
3396 png_uint_32 row_width=row_info->width;
3398 png_debug(1, "in png_do_gamma\n");
3400 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3401 row != NULL && row_info != NULL &&
3403 ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3404 (row_info->bit_depth == 16 && gamma_16_table != NULL)))
3406 switch (row_info->color_type)
3408 case PNG_COLOR_TYPE_RGB:
3410 if (row_info->bit_depth == 8)
3413 for (i = 0; i < row_width; i++)
3415 *sp = gamma_table[*sp];
3417 *sp = gamma_table[*sp];
3419 *sp = gamma_table[*sp];
3423 else /* if (row_info->bit_depth == 16) */
3426 for (i = 0; i < row_width; i++)
3430 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3431 *sp = (png_byte)((v >> 8) & 0xff);
3432 *(sp + 1) = (png_byte)(v & 0xff);
3434 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3435 *sp = (png_byte)((v >> 8) & 0xff);
3436 *(sp + 1) = (png_byte)(v & 0xff);
3438 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3439 *sp = (png_byte)((v >> 8) & 0xff);
3440 *(sp + 1) = (png_byte)(v & 0xff);
3446 case PNG_COLOR_TYPE_RGB_ALPHA:
3448 if (row_info->bit_depth == 8)
3451 for (i = 0; i < row_width; i++)
3453 *sp = gamma_table[*sp];
3455 *sp = gamma_table[*sp];
3457 *sp = gamma_table[*sp];
3462 else /* if (row_info->bit_depth == 16) */
3465 for (i = 0; i < row_width; i++)
3467 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3468 *sp = (png_byte)((v >> 8) & 0xff);
3469 *(sp + 1) = (png_byte)(v & 0xff);
3471 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3472 *sp = (png_byte)((v >> 8) & 0xff);
3473 *(sp + 1) = (png_byte)(v & 0xff);
3475 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3476 *sp = (png_byte)((v >> 8) & 0xff);
3477 *(sp + 1) = (png_byte)(v & 0xff);
3483 case PNG_COLOR_TYPE_GRAY_ALPHA:
3485 if (row_info->bit_depth == 8)
3488 for (i = 0; i < row_width; i++)
3490 *sp = gamma_table[*sp];
3494 else /* if (row_info->bit_depth == 16) */
3497 for (i = 0; i < row_width; i++)
3499 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3500 *sp = (png_byte)((v >> 8) & 0xff);
3501 *(sp + 1) = (png_byte)(v & 0xff);
3507 case PNG_COLOR_TYPE_GRAY:
3509 if (row_info->bit_depth == 2)
3512 for (i = 0; i < row_width; i += 4)
3520 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
3521 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3522 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
3523 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
3527 if (row_info->bit_depth == 4)
3530 for (i = 0; i < row_width; i += 2)
3532 int msb = *sp & 0xf0;
3533 int lsb = *sp & 0x0f;
3535 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3536 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
3540 else if (row_info->bit_depth == 8)
3543 for (i = 0; i < row_width; i++)
3545 *sp = gamma_table[*sp];
3549 else if (row_info->bit_depth == 16)
3552 for (i = 0; i < row_width; i++)
3554 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3555 *sp = (png_byte)((v >> 8) & 0xff);
3556 *(sp + 1) = (png_byte)(v & 0xff);
3567 #if defined(PNG_READ_EXPAND_SUPPORTED)
3568 /* Expands a palette row to an RGB or RGBA row depending
3569 * upon whether you supply trans and num_trans.
3572 png_do_expand_palette(png_row_infop row_info, png_bytep row,
3573 png_colorp palette, png_bytep trans, int num_trans)
3578 png_uint_32 row_width=row_info->width;
3580 png_debug(1, "in png_do_expand_palette\n");
3582 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3583 row != NULL && row_info != NULL &&
3585 row_info->color_type == PNG_COLOR_TYPE_PALETTE)
3587 if (row_info->bit_depth < 8)
3589 switch (row_info->bit_depth)
3593 sp = row + (png_size_t)((row_width - 1) >> 3);
3594 dp = row + (png_size_t)row_width - 1;
3595 shift = 7 - (int)((row_width + 7) & 0x07);
3596 for (i = 0; i < row_width; i++)
3598 if ((*sp >> shift) & 0x01)
3616 sp = row + (png_size_t)((row_width - 1) >> 2);
3617 dp = row + (png_size_t)row_width - 1;
3618 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3619 for (i = 0; i < row_width; i++)
3621 value = (*sp >> shift) & 0x03;
3622 *dp = (png_byte)value;
3637 sp = row + (png_size_t)((row_width - 1) >> 1);
3638 dp = row + (png_size_t)row_width - 1;
3639 shift = (int)((row_width & 0x01) << 2);
3640 for (i = 0; i < row_width; i++)
3642 value = (*sp >> shift) & 0x0f;
3643 *dp = (png_byte)value;
3657 row_info->bit_depth = 8;
3658 row_info->pixel_depth = 8;
3659 row_info->rowbytes = row_width;
3661 switch (row_info->bit_depth)
3667 sp = row + (png_size_t)row_width - 1;
3668 dp = row + (png_size_t)(row_width << 2) - 1;
3670 for (i = 0; i < row_width; i++)
3672 if ((int)(*sp) >= num_trans)
3676 *dp-- = palette[*sp].blue;
3677 *dp-- = palette[*sp].green;
3678 *dp-- = palette[*sp].red;
3681 row_info->bit_depth = 8;
3682 row_info->pixel_depth = 32;
3683 row_info->rowbytes = row_width * 4;
3684 row_info->color_type = 6;
3685 row_info->channels = 4;
3689 sp = row + (png_size_t)row_width - 1;
3690 dp = row + (png_size_t)(row_width * 3) - 1;
3692 for (i = 0; i < row_width; i++)
3694 *dp-- = palette[*sp].blue;
3695 *dp-- = palette[*sp].green;
3696 *dp-- = palette[*sp].red;
3699 row_info->bit_depth = 8;
3700 row_info->pixel_depth = 24;
3701 row_info->rowbytes = row_width * 3;
3702 row_info->color_type = 2;
3703 row_info->channels = 3;
3711 /* If the bit depth < 8, it is expanded to 8. Also, if the already
3712 * expanded transparency value is supplied, an alpha channel is built.
3715 png_do_expand(png_row_infop row_info, png_bytep row,
3716 png_color_16p trans_value)
3721 png_uint_32 row_width=row_info->width;
3723 png_debug(1, "in png_do_expand\n");
3724 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3725 if (row != NULL && row_info != NULL)
3728 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
3730 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
3732 if (row_info->bit_depth < 8)
3734 switch (row_info->bit_depth)
3738 gray = (png_uint_16)((gray&0x01)*0xff);
3739 sp = row + (png_size_t)((row_width - 1) >> 3);
3740 dp = row + (png_size_t)row_width - 1;
3741 shift = 7 - (int)((row_width + 7) & 0x07);
3742 for (i = 0; i < row_width; i++)
3744 if ((*sp >> shift) & 0x01)
3762 gray = (png_uint_16)((gray&0x03)*0x55);
3763 sp = row + (png_size_t)((row_width - 1) >> 2);
3764 dp = row + (png_size_t)row_width - 1;
3765 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3766 for (i = 0; i < row_width; i++)
3768 value = (*sp >> shift) & 0x03;
3769 *dp = (png_byte)(value | (value << 2) | (value << 4) |
3785 gray = (png_uint_16)((gray&0x0f)*0x11);
3786 sp = row + (png_size_t)((row_width - 1) >> 1);
3787 dp = row + (png_size_t)row_width - 1;
3788 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
3789 for (i = 0; i < row_width; i++)
3791 value = (*sp >> shift) & 0x0f;
3792 *dp = (png_byte)(value | (value << 4));
3806 row_info->bit_depth = 8;
3807 row_info->pixel_depth = 8;
3808 row_info->rowbytes = row_width;
3811 if (trans_value != NULL)
3813 if (row_info->bit_depth == 8)
3816 sp = row + (png_size_t)row_width - 1;
3817 dp = row + (png_size_t)(row_width << 1) - 1;
3818 for (i = 0; i < row_width; i++)
3827 else if (row_info->bit_depth == 16)
3829 png_byte gray_high = (gray >> 8) & 0xff;
3830 png_byte gray_low = gray & 0xff;
3831 sp = row + row_info->rowbytes - 1;
3832 dp = row + (row_info->rowbytes << 1) - 1;
3833 for (i = 0; i < row_width; i++)
3835 if (*(sp-1) == gray_high && *(sp) == gray_low)
3849 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3850 row_info->channels = 2;
3851 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3852 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
3856 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3858 if (row_info->bit_depth == 8)
3860 png_byte red = trans_value->red & 0xff;
3861 png_byte green = trans_value->green & 0xff;
3862 png_byte blue = trans_value->blue & 0xff;
3863 sp = row + (png_size_t)row_info->rowbytes - 1;
3864 dp = row + (png_size_t)(row_width << 2) - 1;
3865 for (i = 0; i < row_width; i++)
3867 if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
3876 else if (row_info->bit_depth == 16)
3878 png_byte red_high = (trans_value->red >> 8) & 0xff;
3879 png_byte green_high = (trans_value->green >> 8) & 0xff;
3880 png_byte blue_high = (trans_value->blue >> 8) & 0xff;
3881 png_byte red_low = trans_value->red & 0xff;
3882 png_byte green_low = trans_value->green & 0xff;
3883 png_byte blue_low = trans_value->blue & 0xff;
3884 sp = row + row_info->rowbytes - 1;
3885 dp = row + (png_size_t)(row_width << 3) - 1;
3886 for (i = 0; i < row_width; i++)
3888 if (*(sp - 5) == red_high &&
3889 *(sp - 4) == red_low &&
3890 *(sp - 3) == green_high &&
3891 *(sp - 2) == green_low &&
3892 *(sp - 1) == blue_high &&
3911 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3912 row_info->channels = 4;
3913 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
3914 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3920 #if defined(PNG_READ_DITHER_SUPPORTED)
3922 png_do_dither(png_row_infop row_info, png_bytep row,
3923 png_bytep palette_lookup, png_bytep dither_lookup)
3927 png_uint_32 row_width=row_info->width;
3929 png_debug(1, "in png_do_dither\n");
3930 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3931 if (row != NULL && row_info != NULL)
3934 if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3935 palette_lookup && row_info->bit_depth == 8)
3940 for (i = 0; i < row_width; i++)
3946 /* this looks real messy, but the compiler will reduce
3947 it down to a reasonable formula. For example, with
3948 5 bits per color, we get:
3949 p = (((r >> 3) & 0x1f) << 10) |
3950 (((g >> 3) & 0x1f) << 5) |
3953 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3954 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3955 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3956 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3957 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3958 (PNG_DITHER_BLUE_BITS)) |
3959 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3960 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3962 *dp++ = palette_lookup[p];
3964 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3965 row_info->channels = 1;
3966 row_info->pixel_depth = row_info->bit_depth;
3967 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3969 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
3970 palette_lookup != NULL && row_info->bit_depth == 8)
3975 for (i = 0; i < row_width; i++)
3982 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3983 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3984 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3985 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3986 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3987 (PNG_DITHER_BLUE_BITS)) |
3988 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3989 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3991 *dp++ = palette_lookup[p];
3993 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3994 row_info->channels = 1;
3995 row_info->pixel_depth = row_info->bit_depth;
3996 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3998 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
3999 dither_lookup && row_info->bit_depth == 8)
4002 for (i = 0; i < row_width; i++, sp++)
4004 *sp = dither_lookup[*sp];
4011 #ifdef PNG_FLOATING_POINT_SUPPORTED
4012 #if defined(PNG_READ_GAMMA_SUPPORTED)
4013 static PNG_CONST int png_gamma_shift[] =
4014 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
4016 /* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
4017 * tables, we don't make a full table if we are reducing to 8-bit in
4018 * the future. Note also how the gamma_16 tables are segmented so that
4019 * we don't need to allocate > 64K chunks for a full 16-bit table.
4022 png_build_gamma_table(png_structp png_ptr)
4024 png_debug(1, "in png_build_gamma_table\n");
4026 if (png_ptr->bit_depth <= 8)
4031 if (png_ptr->screen_gamma > .000001)
4032 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4036 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
4039 for (i = 0; i < 256; i++)
4041 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
4045 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4046 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4047 if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
4050 g = 1.0 / (png_ptr->gamma);
4052 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
4055 for (i = 0; i < 256; i++)
4057 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
4062 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
4065 if(png_ptr->screen_gamma > 0.000001)
4066 g = 1.0 / png_ptr->screen_gamma;
4068 g = png_ptr->gamma; /* probably doing rgb_to_gray */
4070 for (i = 0; i < 256; i++)
4072 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
4077 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4082 int i, j, shift, num;
4086 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
4088 sig_bit = (int)png_ptr->sig_bit.red;
4089 if ((int)png_ptr->sig_bit.green > sig_bit)
4090 sig_bit = png_ptr->sig_bit.green;
4091 if ((int)png_ptr->sig_bit.blue > sig_bit)
4092 sig_bit = png_ptr->sig_bit.blue;
4096 sig_bit = (int)png_ptr->sig_bit.gray;
4100 shift = 16 - sig_bit;
4104 if (png_ptr->transformations & PNG_16_TO_8)
4106 if (shift < (16 - PNG_MAX_GAMMA_8))
4107 shift = (16 - PNG_MAX_GAMMA_8);
4115 png_ptr->gamma_shift = (png_byte)shift;
4117 num = (1 << (8 - shift));
4119 if (png_ptr->screen_gamma > .000001)
4120 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4124 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
4125 (png_uint_32)(num * png_sizeof (png_uint_16p)));
4127 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
4130 png_uint_32 last, max;
4132 for (i = 0; i < num; i++)
4134 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4135 (png_uint_32)(256 * png_sizeof (png_uint_16)));
4140 for (i = 0; i < 256; i++)
4142 fout = ((double)i + 0.5) / 256.0;
4144 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
4147 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4148 [(int)(last >> (8 - shift))] = (png_uint_16)(
4149 (png_uint_16)i | ((png_uint_16)i << 8));
4153 while (last < ((png_uint_32)num << 8))
4155 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4156 [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
4162 for (i = 0; i < num; i++)
4164 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4165 (png_uint_32)(256 * png_sizeof (png_uint_16)));
4167 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
4168 for (j = 0; j < 256; j++)
4170 png_ptr->gamma_16_table[i][j] =
4171 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4172 65535.0, g) * 65535.0 + .5);
4177 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4178 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4179 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
4182 g = 1.0 / (png_ptr->gamma);
4184 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
4185 (png_uint_32)(num * png_sizeof (png_uint_16p )));
4187 for (i = 0; i < num; i++)
4189 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
4190 (png_uint_32)(256 * png_sizeof (png_uint_16)));
4192 ig = (((png_uint_32)i *
4193 (png_uint_32)png_gamma_shift[shift]) >> 4);
4194 for (j = 0; j < 256; j++)
4196 png_ptr->gamma_16_to_1[i][j] =
4197 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4198 65535.0, g) * 65535.0 + .5);
4202 if(png_ptr->screen_gamma > 0.000001)
4203 g = 1.0 / png_ptr->screen_gamma;
4205 g = png_ptr->gamma; /* probably doing rgb_to_gray */
4207 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
4208 (png_uint_32)(num * png_sizeof (png_uint_16p)));
4210 for (i = 0; i < num; i++)
4212 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
4213 (png_uint_32)(256 * png_sizeof (png_uint_16)));
4215 ig = (((png_uint_32)i *
4216 (png_uint_32)png_gamma_shift[shift]) >> 4);
4217 for (j = 0; j < 256; j++)
4219 png_ptr->gamma_16_from_1[i][j] =
4220 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4221 65535.0, g) * 65535.0 + .5);
4225 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4229 /* To do: install integer version of png_build_gamma_table here */
4232 #if defined(PNG_MNG_FEATURES_SUPPORTED)
4233 /* undoes intrapixel differencing */
4235 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4237 png_debug(1, "in png_do_read_intrapixel\n");
4239 #if defined(PNG_USELESS_TESTS_SUPPORTED)
4240 row != NULL && row_info != NULL &&
4242 (row_info->color_type & PNG_COLOR_MASK_COLOR))
4244 int bytes_per_pixel;
4245 png_uint_32 row_width = row_info->width;
4246 if (row_info->bit_depth == 8)
4251 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4252 bytes_per_pixel = 3;
4253 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4254 bytes_per_pixel = 4;
4258 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4260 *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
4261 *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
4264 else if (row_info->bit_depth == 16)
4269 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4270 bytes_per_pixel = 6;
4271 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4272 bytes_per_pixel = 8;
4276 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4278 png_uint_32 s0 = (*(rp ) << 8) | *(rp+1);
4279 png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3);
4280 png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5);
4281 png_uint_32 red = (png_uint_32)((s0+s1+65536L) & 0xffffL);
4282 png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL);
4283 *(rp ) = (png_byte)((red >> 8) & 0xff);
4284 *(rp+1) = (png_byte)(red & 0xff);
4285 *(rp+4) = (png_byte)((blue >> 8) & 0xff);
4286 *(rp+5) = (png_byte)(blue & 0xff);
4291 #endif /* PNG_MNG_FEATURES_SUPPORTED */
4292 #endif /* PNG_READ_SUPPORTED */