2 /* pngrtran.c - transforms the data in a row for PNG readers
\r
4 * Last changed in libpng 1.2.30 [August 15, 2008]
\r
5 * For conditions of distribution and use, see copyright notice in png.h
\r
6 * Copyright (c) 1998-2008 Glenn Randers-Pehrson
\r
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
\r
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
\r
10 * This file contains functions optionally called by an application
\r
11 * in order to tell libpng how to handle data when reading a PNG.
\r
12 * Transformations that are used in both reading and writing are
\r
16 #define PNG_INTERNAL
\r
18 #if defined(PNG_READ_SUPPORTED)
\r
20 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
\r
22 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
\r
24 png_debug(1, "in png_set_crc_action\n");
\r
25 /* Tell libpng how we react to CRC errors in critical chunks */
\r
26 if (png_ptr == NULL) return;
\r
27 switch (crit_action)
\r
29 case PNG_CRC_NO_CHANGE: /* leave setting as is */
\r
31 case PNG_CRC_WARN_USE: /* warn/use data */
\r
32 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
\r
33 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
\r
35 case PNG_CRC_QUIET_USE: /* quiet/use data */
\r
36 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
\r
37 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
\r
38 PNG_FLAG_CRC_CRITICAL_IGNORE;
\r
40 case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */
\r
41 png_warning(png_ptr,
\r
42 "Can't discard critical data on CRC error.");
\r
43 case PNG_CRC_ERROR_QUIT: /* error/quit */
\r
44 case PNG_CRC_DEFAULT:
\r
46 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
\r
50 switch (ancil_action)
\r
52 case PNG_CRC_NO_CHANGE: /* leave setting as is */
\r
54 case PNG_CRC_WARN_USE: /* warn/use data */
\r
55 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
\r
56 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
\r
58 case PNG_CRC_QUIET_USE: /* quiet/use data */
\r
59 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
\r
60 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
\r
61 PNG_FLAG_CRC_ANCILLARY_NOWARN;
\r
63 case PNG_CRC_ERROR_QUIT: /* error/quit */
\r
64 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
\r
65 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
\r
67 case PNG_CRC_WARN_DISCARD: /* warn/discard data */
\r
68 case PNG_CRC_DEFAULT:
\r
70 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
\r
75 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
\r
76 defined(PNG_FLOATING_POINT_SUPPORTED)
\r
77 /* handle alpha and tRNS via a background color */
\r
79 png_set_background(png_structp png_ptr,
\r
80 png_color_16p background_color, int background_gamma_code,
\r
81 int need_expand, double background_gamma)
\r
83 png_debug(1, "in png_set_background\n");
\r
84 if (png_ptr == NULL) return;
\r
85 if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
\r
87 png_warning(png_ptr, "Application must supply a known background gamma");
\r
91 png_ptr->transformations |= PNG_BACKGROUND;
\r
92 png_memcpy(&(png_ptr->background), background_color,
\r
93 png_sizeof(png_color_16));
\r
94 png_ptr->background_gamma = (float)background_gamma;
\r
95 png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
\r
96 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
\r
100 #if defined(PNG_READ_16_TO_8_SUPPORTED)
\r
101 /* strip 16 bit depth files to 8 bit depth */
\r
103 png_set_strip_16(png_structp png_ptr)
\r
105 png_debug(1, "in png_set_strip_16\n");
\r
106 if (png_ptr == NULL) return;
\r
107 png_ptr->transformations |= PNG_16_TO_8;
\r
111 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
\r
113 png_set_strip_alpha(png_structp png_ptr)
\r
115 png_debug(1, "in png_set_strip_alpha\n");
\r
116 if (png_ptr == NULL) return;
\r
117 png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
\r
121 #if defined(PNG_READ_DITHER_SUPPORTED)
\r
122 /* Dither file to 8 bit. Supply a palette, the current number
\r
123 * of elements in the palette, the maximum number of elements
\r
124 * allowed, and a histogram if possible. If the current number
\r
125 * of colors is greater then the maximum number, the palette will be
\r
126 * modified to fit in the maximum number. "full_dither" indicates
\r
127 * whether we need a dithering cube set up for RGB images, or if we
\r
128 * simply are reducing the number of colors in a paletted image.
\r
131 typedef struct png_dsort_struct
\r
133 struct png_dsort_struct FAR * next;
\r
137 typedef png_dsort FAR * png_dsortp;
\r
138 typedef png_dsort FAR * FAR * png_dsortpp;
\r
141 png_set_dither(png_structp png_ptr, png_colorp palette,
\r
142 int num_palette, int maximum_colors, png_uint_16p histogram,
\r
145 png_debug(1, "in png_set_dither\n");
\r
146 if (png_ptr == NULL) return;
\r
147 png_ptr->transformations |= PNG_DITHER;
\r
153 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
\r
154 (png_uint_32)(num_palette * png_sizeof(png_byte)));
\r
155 for (i = 0; i < num_palette; i++)
\r
156 png_ptr->dither_index[i] = (png_byte)i;
\r
159 if (num_palette > maximum_colors)
\r
161 if (histogram != NULL)
\r
163 /* This is easy enough, just throw out the least used colors.
\r
164 Perhaps not the best solution, but good enough. */
\r
168 /* initialize an array to sort colors */
\r
169 png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
\r
170 (png_uint_32)(num_palette * png_sizeof(png_byte)));
\r
172 /* initialize the dither_sort array */
\r
173 for (i = 0; i < num_palette; i++)
\r
174 png_ptr->dither_sort[i] = (png_byte)i;
\r
176 /* Find the least used palette entries by starting a
\r
177 bubble sort, and running it until we have sorted
\r
178 out enough colors. Note that we don't care about
\r
179 sorting all the colors, just finding which are
\r
182 for (i = num_palette - 1; i >= maximum_colors; i--)
\r
184 int done; /* to stop early if the list is pre-sorted */
\r
188 for (j = 0; j < i; j++)
\r
190 if (histogram[png_ptr->dither_sort[j]]
\r
191 < histogram[png_ptr->dither_sort[j + 1]])
\r
195 t = png_ptr->dither_sort[j];
\r
196 png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
\r
197 png_ptr->dither_sort[j + 1] = t;
\r
205 /* swap the palette around, and set up a table, if necessary */
\r
208 int j = num_palette;
\r
210 /* put all the useful colors within the max, but don't
\r
212 for (i = 0; i < maximum_colors; i++)
\r
214 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
\r
218 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
\r
219 palette[i] = palette[j];
\r
225 int j = num_palette;
\r
227 /* move all the used colors inside the max limit, and
\r
228 develop a translation table */
\r
229 for (i = 0; i < maximum_colors; i++)
\r
231 /* only move the colors we need to */
\r
232 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
\r
234 png_color tmp_color;
\r
238 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
\r
240 tmp_color = palette[j];
\r
241 palette[j] = palette[i];
\r
242 palette[i] = tmp_color;
\r
243 /* indicate where the color went */
\r
244 png_ptr->dither_index[j] = (png_byte)i;
\r
245 png_ptr->dither_index[i] = (png_byte)j;
\r
249 /* find closest color for those colors we are not using */
\r
250 for (i = 0; i < num_palette; i++)
\r
252 if ((int)png_ptr->dither_index[i] >= maximum_colors)
\r
254 int min_d, k, min_k, d_index;
\r
256 /* find the closest color to one we threw out */
\r
257 d_index = png_ptr->dither_index[i];
\r
258 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
\r
259 for (k = 1, min_k = 0; k < maximum_colors; k++)
\r
263 d = PNG_COLOR_DIST(palette[d_index], palette[k]);
\r
271 /* point to closest color */
\r
272 png_ptr->dither_index[i] = (png_byte)min_k;
\r
276 png_free(png_ptr, png_ptr->dither_sort);
\r
277 png_ptr->dither_sort = NULL;
\r
281 /* This is much harder to do simply (and quickly). Perhaps
\r
282 we need to go through a median cut routine, but those
\r
283 don't always behave themselves with only a few colors
\r
284 as input. So we will just find the closest two colors,
\r
285 and throw out one of them (chosen somewhat randomly).
\r
286 [We don't understand this at all, so if someone wants to
\r
287 work on improving it, be our guest - AED, GRP]
\r
291 int num_new_palette;
\r
297 /* initialize palette index arrays */
\r
298 png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
\r
299 (png_uint_32)(num_palette * png_sizeof(png_byte)));
\r
300 png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
\r
301 (png_uint_32)(num_palette * png_sizeof(png_byte)));
\r
303 /* initialize the sort array */
\r
304 for (i = 0; i < num_palette; i++)
\r
306 png_ptr->index_to_palette[i] = (png_byte)i;
\r
307 png_ptr->palette_to_index[i] = (png_byte)i;
\r
310 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
\r
311 png_sizeof(png_dsortp)));
\r
312 for (i = 0; i < 769; i++)
\r
314 /* png_memset(hash, 0, 769 * png_sizeof(png_dsortp)); */
\r
316 num_new_palette = num_palette;
\r
318 /* initial wild guess at how far apart the farthest pixel
\r
319 pair we will be eliminating will be. Larger
\r
320 numbers mean more areas will be allocated, Smaller
\r
321 numbers run the risk of not saving enough data, and
\r
322 having to do this all over again.
\r
324 I have not done extensive checking on this number.
\r
328 while (num_new_palette > maximum_colors)
\r
330 for (i = 0; i < num_new_palette - 1; i++)
\r
334 for (j = i + 1; j < num_new_palette; j++)
\r
338 d = PNG_COLOR_DIST(palette[i], palette[j]);
\r
343 t = (png_dsortp)png_malloc_warn(png_ptr,
\r
344 (png_uint_32)(png_sizeof(png_dsort)));
\r
348 t->left = (png_byte)i;
\r
349 t->right = (png_byte)j;
\r
358 for (i = 0; i <= max_d; i++)
\r
360 if (hash[i] != NULL)
\r
364 for (p = hash[i]; p; p = p->next)
\r
366 if ((int)png_ptr->index_to_palette[p->left]
\r
367 < num_new_palette &&
\r
368 (int)png_ptr->index_to_palette[p->right]
\r
373 if (num_new_palette & 0x01)
\r
385 palette[png_ptr->index_to_palette[j]]
\r
386 = palette[num_new_palette];
\r
391 for (k = 0; k < num_palette; k++)
\r
393 if (png_ptr->dither_index[k] ==
\r
394 png_ptr->index_to_palette[j])
\r
395 png_ptr->dither_index[k] =
\r
396 png_ptr->index_to_palette[next_j];
\r
397 if ((int)png_ptr->dither_index[k] ==
\r
399 png_ptr->dither_index[k] =
\r
400 png_ptr->index_to_palette[j];
\r
404 png_ptr->index_to_palette[png_ptr->palette_to_index
\r
405 [num_new_palette]] = png_ptr->index_to_palette[j];
\r
406 png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
\r
407 = png_ptr->palette_to_index[num_new_palette];
\r
409 png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
\r
410 png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
\r
412 if (num_new_palette <= maximum_colors)
\r
415 if (num_new_palette <= maximum_colors)
\r
420 for (i = 0; i < 769; i++)
\r
422 if (hash[i] != NULL)
\r
424 png_dsortp p = hash[i];
\r
428 png_free(png_ptr, p);
\r
436 png_free(png_ptr, hash);
\r
437 png_free(png_ptr, png_ptr->palette_to_index);
\r
438 png_free(png_ptr, png_ptr->index_to_palette);
\r
439 png_ptr->palette_to_index = NULL;
\r
440 png_ptr->index_to_palette = NULL;
\r
442 num_palette = maximum_colors;
\r
444 if (png_ptr->palette == NULL)
\r
446 png_ptr->palette = palette;
\r
448 png_ptr->num_palette = (png_uint_16)num_palette;
\r
453 png_bytep distance;
\r
454 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
\r
455 PNG_DITHER_BLUE_BITS;
\r
456 int num_red = (1 << PNG_DITHER_RED_BITS);
\r
457 int num_green = (1 << PNG_DITHER_GREEN_BITS);
\r
458 int num_blue = (1 << PNG_DITHER_BLUE_BITS);
\r
459 png_size_t num_entries = ((png_size_t)1 << total_bits);
\r
461 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
\r
462 (png_uint_32)(num_entries * png_sizeof(png_byte)));
\r
464 png_memset(png_ptr->palette_lookup, 0, num_entries *
\r
465 png_sizeof(png_byte));
\r
467 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
\r
468 png_sizeof(png_byte)));
\r
470 png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
\r
472 for (i = 0; i < num_palette; i++)
\r
475 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
\r
476 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
\r
477 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
\r
479 for (ir = 0; ir < num_red; ir++)
\r
481 /* int dr = abs(ir - r); */
\r
482 int dr = ((ir > r) ? ir - r : r - ir);
\r
483 int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
\r
485 for (ig = 0; ig < num_green; ig++)
\r
487 /* int dg = abs(ig - g); */
\r
488 int dg = ((ig > g) ? ig - g : g - ig);
\r
490 int dm = ((dr > dg) ? dr : dg);
\r
491 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
\r
493 for (ib = 0; ib < num_blue; ib++)
\r
495 int d_index = index_g | ib;
\r
496 /* int db = abs(ib - b); */
\r
497 int db = ((ib > b) ? ib - b : b - ib);
\r
498 int dmax = ((dm > db) ? dm : db);
\r
499 int d = dmax + dt + db;
\r
501 if (d < (int)distance[d_index])
\r
503 distance[d_index] = (png_byte)d;
\r
504 png_ptr->palette_lookup[d_index] = (png_byte)i;
\r
511 png_free(png_ptr, distance);
\r
516 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
\r
517 /* Transform the image from the file_gamma to the screen_gamma. We
\r
518 * only do transformations on images where the file_gamma and screen_gamma
\r
519 * are not close reciprocals, otherwise it slows things down slightly, and
\r
520 * also needlessly introduces small errors.
\r
522 * We will turn off gamma transformation later if no semitransparent entries
\r
523 * are present in the tRNS array for palette images. We can't do it here
\r
524 * because we don't necessarily have the tRNS chunk yet.
\r
527 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
\r
529 png_debug(1, "in png_set_gamma\n");
\r
530 if (png_ptr == NULL) return;
\r
531 if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
\r
532 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
\r
533 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
\r
534 png_ptr->transformations |= PNG_GAMMA;
\r
535 png_ptr->gamma = (float)file_gamma;
\r
536 png_ptr->screen_gamma = (float)scrn_gamma;
\r
540 #if defined(PNG_READ_EXPAND_SUPPORTED)
\r
541 /* Expand paletted images to RGB, expand grayscale images of
\r
542 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
\r
543 * to alpha channels.
\r
546 png_set_expand(png_structp png_ptr)
\r
548 png_debug(1, "in png_set_expand\n");
\r
549 if (png_ptr == NULL) return;
\r
550 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
\r
551 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
\r
554 /* GRR 19990627: the following three functions currently are identical
\r
555 * to png_set_expand(). However, it is entirely reasonable that someone
\r
556 * might wish to expand an indexed image to RGB but *not* expand a single,
\r
557 * fully transparent palette entry to a full alpha channel--perhaps instead
\r
558 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
\r
559 * the transparent color with a particular RGB value, or drop tRNS entirely.
\r
560 * IOW, a future version of the library may make the transformations flag
\r
561 * a bit more fine-grained, with separate bits for each of these three
\r
564 * More to the point, these functions make it obvious what libpng will be
\r
565 * doing, whereas "expand" can (and does) mean any number of things.
\r
567 * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified
\r
568 * to expand only the sample depth but not to expand the tRNS to alpha.
\r
571 /* Expand paletted images to RGB. */
\r
573 png_set_palette_to_rgb(png_structp png_ptr)
\r
575 png_debug(1, "in png_set_palette_to_rgb\n");
\r
576 if (png_ptr == NULL) return;
\r
577 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
\r
578 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
\r
581 #if !defined(PNG_1_0_X)
\r
582 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
\r
584 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
\r
586 png_debug(1, "in png_set_expand_gray_1_2_4_to_8\n");
\r
587 if (png_ptr == NULL) return;
\r
588 png_ptr->transformations |= PNG_EXPAND;
\r
589 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
\r
593 #if defined(PNG_1_0_X) || defined(PNG_1_2_X)
\r
594 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
\r
595 /* Deprecated as of libpng-1.2.9 */
\r
597 png_set_gray_1_2_4_to_8(png_structp png_ptr)
\r
599 png_debug(1, "in png_set_gray_1_2_4_to_8\n");
\r
600 if (png_ptr == NULL) return;
\r
601 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
\r
606 /* Expand tRNS chunks to alpha channels. */
\r
608 png_set_tRNS_to_alpha(png_structp png_ptr)
\r
610 png_debug(1, "in png_set_tRNS_to_alpha\n");
\r
611 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
\r
612 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
\r
614 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
\r
616 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
\r
618 png_set_gray_to_rgb(png_structp png_ptr)
\r
620 png_debug(1, "in png_set_gray_to_rgb\n");
\r
621 png_ptr->transformations |= PNG_GRAY_TO_RGB;
\r
622 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
\r
626 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
\r
627 #if defined(PNG_FLOATING_POINT_SUPPORTED)
\r
628 /* Convert a RGB image to a grayscale of the same width. This allows us,
\r
629 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
\r
633 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
\r
636 int red_fixed = (int)((float)red*100000.0 + 0.5);
\r
637 int green_fixed = (int)((float)green*100000.0 + 0.5);
\r
638 if (png_ptr == NULL) return;
\r
639 png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
\r
644 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
\r
645 png_fixed_point red, png_fixed_point green)
\r
647 png_debug(1, "in png_set_rgb_to_gray\n");
\r
648 if (png_ptr == NULL) return;
\r
649 switch(error_action)
\r
651 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
\r
653 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
\r
655 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
\r
657 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
658 #if defined(PNG_READ_EXPAND_SUPPORTED)
\r
659 png_ptr->transformations |= PNG_EXPAND;
\r
662 png_warning(png_ptr,
\r
663 "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
\r
664 png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
\r
668 png_uint_16 red_int, green_int;
\r
669 if (red < 0 || green < 0)
\r
671 red_int = 6968; /* .212671 * 32768 + .5 */
\r
672 green_int = 23434; /* .715160 * 32768 + .5 */
\r
674 else if (red + green < 100000L)
\r
676 red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
\r
677 green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
\r
681 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
\r
685 png_ptr->rgb_to_gray_red_coeff = red_int;
\r
686 png_ptr->rgb_to_gray_green_coeff = green_int;
\r
687 png_ptr->rgb_to_gray_blue_coeff =
\r
688 (png_uint_16)(32768 - red_int - green_int);
\r
693 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
\r
694 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
\r
695 defined(PNG_LEGACY_SUPPORTED)
\r
697 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
\r
698 read_user_transform_fn)
\r
700 png_debug(1, "in png_set_read_user_transform_fn\n");
\r
701 if (png_ptr == NULL) return;
\r
702 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
\r
703 png_ptr->transformations |= PNG_USER_TRANSFORM;
\r
704 png_ptr->read_user_transform_fn = read_user_transform_fn;
\r
706 #ifdef PNG_LEGACY_SUPPORTED
\r
707 if (read_user_transform_fn)
\r
708 png_warning(png_ptr,
\r
709 "This version of libpng does not support user transforms");
\r
714 /* Initialize everything needed for the read. This includes modifying
\r
718 png_init_read_transformations(png_structp png_ptr)
\r
720 png_debug(1, "in png_init_read_transformations\n");
\r
721 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
722 if (png_ptr != NULL)
\r
725 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
\r
726 || defined(PNG_READ_GAMMA_SUPPORTED)
\r
727 int color_type = png_ptr->color_type;
\r
730 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
732 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
\r
733 /* Detect gray background and attempt to enable optimization
\r
734 * for gray --> RGB case */
\r
735 /* Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
\r
736 * RGB_ALPHA (in which case need_expand is superfluous anyway), the
\r
737 * background color might actually be gray yet not be flagged as such.
\r
738 * This is not a problem for the current code, which uses
\r
739 * PNG_BACKGROUND_IS_GRAY only to decide when to do the
\r
740 * png_do_gray_to_rgb() transformation.
\r
742 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
\r
743 !(color_type & PNG_COLOR_MASK_COLOR))
\r
745 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
\r
746 } else if ((png_ptr->transformations & PNG_BACKGROUND) &&
\r
747 !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
\r
748 (png_ptr->transformations & PNG_GRAY_TO_RGB) &&
\r
749 png_ptr->background.red == png_ptr->background.green &&
\r
750 png_ptr->background.red == png_ptr->background.blue)
\r
752 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
\r
753 png_ptr->background.gray = png_ptr->background.red;
\r
757 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
\r
758 (png_ptr->transformations & PNG_EXPAND))
\r
760 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
\r
762 /* expand background and tRNS chunks */
\r
763 switch (png_ptr->bit_depth)
\r
766 png_ptr->background.gray *= (png_uint_16)0xff;
\r
767 png_ptr->background.red = png_ptr->background.green
\r
768 = png_ptr->background.blue = png_ptr->background.gray;
\r
769 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
\r
771 png_ptr->trans_values.gray *= (png_uint_16)0xff;
\r
772 png_ptr->trans_values.red = png_ptr->trans_values.green
\r
773 = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
\r
777 png_ptr->background.gray *= (png_uint_16)0x55;
\r
778 png_ptr->background.red = png_ptr->background.green
\r
779 = png_ptr->background.blue = png_ptr->background.gray;
\r
780 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
\r
782 png_ptr->trans_values.gray *= (png_uint_16)0x55;
\r
783 png_ptr->trans_values.red = png_ptr->trans_values.green
\r
784 = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
\r
788 png_ptr->background.gray *= (png_uint_16)0x11;
\r
789 png_ptr->background.red = png_ptr->background.green
\r
790 = png_ptr->background.blue = png_ptr->background.gray;
\r
791 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
\r
793 png_ptr->trans_values.gray *= (png_uint_16)0x11;
\r
794 png_ptr->trans_values.red = png_ptr->trans_values.green
\r
795 = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
\r
800 png_ptr->background.red = png_ptr->background.green
\r
801 = png_ptr->background.blue = png_ptr->background.gray;
\r
805 else if (color_type == PNG_COLOR_TYPE_PALETTE)
\r
807 png_ptr->background.red =
\r
808 png_ptr->palette[png_ptr->background.index].red;
\r
809 png_ptr->background.green =
\r
810 png_ptr->palette[png_ptr->background.index].green;
\r
811 png_ptr->background.blue =
\r
812 png_ptr->palette[png_ptr->background.index].blue;
\r
814 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
\r
815 if (png_ptr->transformations & PNG_INVERT_ALPHA)
\r
817 #if defined(PNG_READ_EXPAND_SUPPORTED)
\r
818 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
\r
821 /* invert the alpha channel (in tRNS) unless the pixels are
\r
822 going to be expanded, in which case leave it for later */
\r
824 istop=(int)png_ptr->num_trans;
\r
825 for (i=0; i<istop; i++)
\r
826 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
\r
835 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
\r
836 png_ptr->background_1 = png_ptr->background;
\r
838 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
\r
840 if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
\r
841 && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
\r
842 < PNG_GAMMA_THRESHOLD))
\r
846 for (i=0; i<png_ptr->num_trans; i++)
\r
848 if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
\r
849 k=1; /* partial transparency is present */
\r
852 png_ptr->transformations &= ~PNG_GAMMA;
\r
855 if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) &&
\r
856 png_ptr->gamma != 0.0)
\r
858 png_build_gamma_table(png_ptr);
\r
859 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
860 if (png_ptr->transformations & PNG_BACKGROUND)
\r
862 if (color_type == PNG_COLOR_TYPE_PALETTE)
\r
864 /* could skip if no transparency and
\r
866 png_color back, back_1;
\r
867 png_colorp palette = png_ptr->palette;
\r
868 int num_palette = png_ptr->num_palette;
\r
870 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
\r
872 back.red = png_ptr->gamma_table[png_ptr->background.red];
\r
873 back.green = png_ptr->gamma_table[png_ptr->background.green];
\r
874 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
\r
876 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
\r
877 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
\r
878 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
\r
884 switch (png_ptr->background_gamma_type)
\r
886 case PNG_BACKGROUND_GAMMA_SCREEN:
\r
887 g = (png_ptr->screen_gamma);
\r
890 case PNG_BACKGROUND_GAMMA_FILE:
\r
891 g = 1.0 / (png_ptr->gamma);
\r
892 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
\r
894 case PNG_BACKGROUND_GAMMA_UNIQUE:
\r
895 g = 1.0 / (png_ptr->background_gamma);
\r
896 gs = 1.0 / (png_ptr->background_gamma *
\r
897 png_ptr->screen_gamma);
\r
900 g = 1.0; /* back_1 */
\r
901 gs = 1.0; /* back */
\r
904 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
\r
906 back.red = (png_byte)png_ptr->background.red;
\r
907 back.green = (png_byte)png_ptr->background.green;
\r
908 back.blue = (png_byte)png_ptr->background.blue;
\r
912 back.red = (png_byte)(pow(
\r
913 (double)png_ptr->background.red/255, gs) * 255.0 + .5);
\r
914 back.green = (png_byte)(pow(
\r
915 (double)png_ptr->background.green/255, gs) * 255.0 + .5);
\r
916 back.blue = (png_byte)(pow(
\r
917 (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
\r
920 back_1.red = (png_byte)(pow(
\r
921 (double)png_ptr->background.red/255, g) * 255.0 + .5);
\r
922 back_1.green = (png_byte)(pow(
\r
923 (double)png_ptr->background.green/255, g) * 255.0 + .5);
\r
924 back_1.blue = (png_byte)(pow(
\r
925 (double)png_ptr->background.blue/255, g) * 255.0 + .5);
\r
927 for (i = 0; i < num_palette; i++)
\r
929 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
\r
931 if (png_ptr->trans[i] == 0)
\r
935 else /* if (png_ptr->trans[i] != 0xff) */
\r
939 v = png_ptr->gamma_to_1[palette[i].red];
\r
940 png_composite(w, v, png_ptr->trans[i], back_1.red);
\r
941 palette[i].red = png_ptr->gamma_from_1[w];
\r
943 v = png_ptr->gamma_to_1[palette[i].green];
\r
944 png_composite(w, v, png_ptr->trans[i], back_1.green);
\r
945 palette[i].green = png_ptr->gamma_from_1[w];
\r
947 v = png_ptr->gamma_to_1[palette[i].blue];
\r
948 png_composite(w, v, png_ptr->trans[i], back_1.blue);
\r
949 palette[i].blue = png_ptr->gamma_from_1[w];
\r
954 palette[i].red = png_ptr->gamma_table[palette[i].red];
\r
955 palette[i].green = png_ptr->gamma_table[palette[i].green];
\r
956 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
\r
959 /* Prevent the transformations being done again, and make sure
\r
960 * that the now spurious alpha channel is stripped - the code
\r
961 * has just reduced background composition and gamma correction
\r
962 * to a simple alpha channel strip.
\r
964 png_ptr->transformations &= ~PNG_BACKGROUND;
\r
965 png_ptr->transformations &= ~PNG_GAMMA;
\r
966 png_ptr->transformations |= PNG_STRIP_ALPHA;
\r
968 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
\r
970 /* color_type != PNG_COLOR_TYPE_PALETTE */
\r
972 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
\r
976 switch (png_ptr->background_gamma_type)
\r
978 case PNG_BACKGROUND_GAMMA_SCREEN:
\r
979 g = (png_ptr->screen_gamma);
\r
982 case PNG_BACKGROUND_GAMMA_FILE:
\r
983 g = 1.0 / (png_ptr->gamma);
\r
984 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
\r
986 case PNG_BACKGROUND_GAMMA_UNIQUE:
\r
987 g = 1.0 / (png_ptr->background_gamma);
\r
988 gs = 1.0 / (png_ptr->background_gamma *
\r
989 png_ptr->screen_gamma);
\r
993 png_ptr->background_1.gray = (png_uint_16)(pow(
\r
994 (double)png_ptr->background.gray / m, g) * m + .5);
\r
995 png_ptr->background.gray = (png_uint_16)(pow(
\r
996 (double)png_ptr->background.gray / m, gs) * m + .5);
\r
998 if ((png_ptr->background.red != png_ptr->background.green) ||
\r
999 (png_ptr->background.red != png_ptr->background.blue) ||
\r
1000 (png_ptr->background.red != png_ptr->background.gray))
\r
1002 /* RGB or RGBA with color background */
\r
1003 png_ptr->background_1.red = (png_uint_16)(pow(
\r
1004 (double)png_ptr->background.red / m, g) * m + .5);
\r
1005 png_ptr->background_1.green = (png_uint_16)(pow(
\r
1006 (double)png_ptr->background.green / m, g) * m + .5);
\r
1007 png_ptr->background_1.blue = (png_uint_16)(pow(
\r
1008 (double)png_ptr->background.blue / m, g) * m + .5);
\r
1009 png_ptr->background.red = (png_uint_16)(pow(
\r
1010 (double)png_ptr->background.red / m, gs) * m + .5);
\r
1011 png_ptr->background.green = (png_uint_16)(pow(
\r
1012 (double)png_ptr->background.green / m, gs) * m + .5);
\r
1013 png_ptr->background.blue = (png_uint_16)(pow(
\r
1014 (double)png_ptr->background.blue / m, gs) * m + .5);
\r
1018 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
\r
1019 png_ptr->background_1.red = png_ptr->background_1.green
\r
1020 = png_ptr->background_1.blue = png_ptr->background_1.gray;
\r
1021 png_ptr->background.red = png_ptr->background.green
\r
1022 = png_ptr->background.blue = png_ptr->background.gray;
\r
1027 /* transformation does not include PNG_BACKGROUND */
\r
1028 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
\r
1029 if (color_type == PNG_COLOR_TYPE_PALETTE)
\r
1031 png_colorp palette = png_ptr->palette;
\r
1032 int num_palette = png_ptr->num_palette;
\r
1035 for (i = 0; i < num_palette; i++)
\r
1037 palette[i].red = png_ptr->gamma_table[palette[i].red];
\r
1038 palette[i].green = png_ptr->gamma_table[palette[i].green];
\r
1039 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
\r
1042 /* Done the gamma correction. */
\r
1043 png_ptr->transformations &= ~PNG_GAMMA;
\r
1046 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
1049 #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
\r
1050 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
1051 /* No GAMMA transformation */
\r
1052 if ((png_ptr->transformations & PNG_BACKGROUND) &&
\r
1053 (color_type == PNG_COLOR_TYPE_PALETTE))
\r
1056 int istop = (int)png_ptr->num_trans;
\r
1058 png_colorp palette = png_ptr->palette;
\r
1060 back.red = (png_byte)png_ptr->background.red;
\r
1061 back.green = (png_byte)png_ptr->background.green;
\r
1062 back.blue = (png_byte)png_ptr->background.blue;
\r
1064 for (i = 0; i < istop; i++)
\r
1066 if (png_ptr->trans[i] == 0)
\r
1068 palette[i] = back;
\r
1070 else if (png_ptr->trans[i] != 0xff)
\r
1072 /* The png_composite() macro is defined in png.h */
\r
1073 png_composite(palette[i].red, palette[i].red,
\r
1074 png_ptr->trans[i], back.red);
\r
1075 png_composite(palette[i].green, palette[i].green,
\r
1076 png_ptr->trans[i], back.green);
\r
1077 png_composite(palette[i].blue, palette[i].blue,
\r
1078 png_ptr->trans[i], back.blue);
\r
1082 /* Handled alpha, still need to strip the channel. */
\r
1083 png_ptr->transformations &= ~PNG_BACKGROUND;
\r
1084 png_ptr->transformations |= PNG_STRIP_ALPHA;
\r
1086 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
\r
1088 #if defined(PNG_READ_SHIFT_SUPPORTED)
\r
1089 if ((png_ptr->transformations & PNG_SHIFT) &&
\r
1090 (color_type == PNG_COLOR_TYPE_PALETTE))
\r
1093 png_uint_16 istop = png_ptr->num_palette;
\r
1094 int sr = 8 - png_ptr->sig_bit.red;
\r
1095 int sg = 8 - png_ptr->sig_bit.green;
\r
1096 int sb = 8 - png_ptr->sig_bit.blue;
\r
1098 if (sr < 0 || sr > 8)
\r
1100 if (sg < 0 || sg > 8)
\r
1102 if (sb < 0 || sb > 8)
\r
1104 for (i = 0; i < istop; i++)
\r
1106 png_ptr->palette[i].red >>= sr;
\r
1107 png_ptr->palette[i].green >>= sg;
\r
1108 png_ptr->palette[i].blue >>= sb;
\r
1111 #endif /* PNG_READ_SHIFT_SUPPORTED */
\r
1113 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
\r
1114 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
1120 /* Modify the info structure to reflect the transformations. The
\r
1121 * info should be updated so a PNG file could be written with it,
\r
1122 * assuming the transformations result in valid PNG data.
\r
1124 void /* PRIVATE */
\r
1125 png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
\r
1127 png_debug(1, "in png_read_transform_info\n");
\r
1128 #if defined(PNG_READ_EXPAND_SUPPORTED)
\r
1129 if (png_ptr->transformations & PNG_EXPAND)
\r
1131 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
1133 if (png_ptr->num_trans &&
\r
1134 (png_ptr->transformations & PNG_EXPAND_tRNS))
\r
1135 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
\r
1137 info_ptr->color_type = PNG_COLOR_TYPE_RGB;
\r
1138 info_ptr->bit_depth = 8;
\r
1139 info_ptr->num_trans = 0;
\r
1143 if (png_ptr->num_trans)
\r
1145 if (png_ptr->transformations & PNG_EXPAND_tRNS)
\r
1146 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
\r
1147 #if 0 /* Removed from libpng-1.2.27 */
\r
1149 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
\r
1152 if (info_ptr->bit_depth < 8)
\r
1153 info_ptr->bit_depth = 8;
\r
1154 info_ptr->num_trans = 0;
\r
1159 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
1160 if (png_ptr->transformations & PNG_BACKGROUND)
\r
1162 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
\r
1163 info_ptr->num_trans = 0;
\r
1164 info_ptr->background = png_ptr->background;
\r
1168 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
1169 if (png_ptr->transformations & PNG_GAMMA)
\r
1171 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
1172 info_ptr->gamma = png_ptr->gamma;
\r
1174 #ifdef PNG_FIXED_POINT_SUPPORTED
\r
1175 info_ptr->int_gamma = png_ptr->int_gamma;
\r
1180 #if defined(PNG_READ_16_TO_8_SUPPORTED)
\r
1181 if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
\r
1182 info_ptr->bit_depth = 8;
\r
1185 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
\r
1186 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
\r
1187 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
\r
1190 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
\r
1191 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
\r
1192 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
\r
1195 #if defined(PNG_READ_DITHER_SUPPORTED)
\r
1196 if (png_ptr->transformations & PNG_DITHER)
\r
1198 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
\r
1199 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
\r
1200 png_ptr->palette_lookup && info_ptr->bit_depth == 8)
\r
1202 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
\r
1207 #if defined(PNG_READ_PACK_SUPPORTED)
\r
1208 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
\r
1209 info_ptr->bit_depth = 8;
\r
1212 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
1213 info_ptr->channels = 1;
\r
1214 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
\r
1215 info_ptr->channels = 3;
\r
1217 info_ptr->channels = 1;
\r
1219 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
\r
1220 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
\r
1221 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
\r
1224 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
\r
1225 info_ptr->channels++;
\r
1227 #if defined(PNG_READ_FILLER_SUPPORTED)
\r
1228 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
\r
1229 if ((png_ptr->transformations & PNG_FILLER) &&
\r
1230 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
\r
1231 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
\r
1233 info_ptr->channels++;
\r
1234 /* if adding a true alpha channel not just filler */
\r
1235 #if !defined(PNG_1_0_X)
\r
1236 if (png_ptr->transformations & PNG_ADD_ALPHA)
\r
1237 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
\r
1242 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
\r
1243 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
\r
1244 if (png_ptr->transformations & PNG_USER_TRANSFORM)
\r
1246 if (info_ptr->bit_depth < png_ptr->user_transform_depth)
\r
1247 info_ptr->bit_depth = png_ptr->user_transform_depth;
\r
1248 if (info_ptr->channels < png_ptr->user_transform_channels)
\r
1249 info_ptr->channels = png_ptr->user_transform_channels;
\r
1253 info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
\r
1254 info_ptr->bit_depth);
\r
1256 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
\r
1258 #if !defined(PNG_READ_EXPAND_SUPPORTED)
\r
1264 /* Transform the row. The order of transformations is significant,
\r
1265 * and is very touchy. If you add a transformation, take care to
\r
1266 * decide how it fits in with the other transformations here.
\r
1268 void /* PRIVATE */
\r
1269 png_do_read_transformations(png_structp png_ptr)
\r
1271 png_debug(1, "in png_do_read_transformations\n");
\r
1272 if (png_ptr->row_buf == NULL)
\r
1274 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
\r
1277 png_snprintf2(msg, 50,
\r
1278 "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number,
\r
1280 png_error(png_ptr, msg);
\r
1282 png_error(png_ptr, "NULL row buffer");
\r
1285 #ifdef PNG_WARN_UNINITIALIZED_ROW
\r
1286 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
\r
1287 /* Application has failed to call either png_read_start_image()
\r
1288 * or png_read_update_info() after setting transforms that expand
\r
1289 * pixels. This check added to libpng-1.2.19 */
\r
1290 #if (PNG_WARN_UNINITIALIZED_ROW==1)
\r
1291 png_error(png_ptr, "Uninitialized row");
\r
1293 png_warning(png_ptr, "Uninitialized row");
\r
1297 #if defined(PNG_READ_EXPAND_SUPPORTED)
\r
1298 if (png_ptr->transformations & PNG_EXPAND)
\r
1300 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
\r
1302 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
\r
1303 png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
\r
1307 if (png_ptr->num_trans &&
\r
1308 (png_ptr->transformations & PNG_EXPAND_tRNS))
\r
1309 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
\r
1310 &(png_ptr->trans_values));
\r
1312 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
\r
1318 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
\r
1319 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
\r
1320 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
\r
1321 PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
\r
1324 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
\r
1325 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
\r
1328 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
\r
1331 png_ptr->rgb_to_gray_status=1;
\r
1332 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
\r
1333 PNG_RGB_TO_GRAY_WARN)
\r
1334 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
\r
1335 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
\r
1336 PNG_RGB_TO_GRAY_ERR)
\r
1337 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
\r
1343 From Andreas Dilger e-mail to png-implement, 26 March 1998:
\r
1345 In most cases, the "simple transparency" should be done prior to doing
\r
1346 gray-to-RGB, or you will have to test 3x as many bytes to check if a
\r
1347 pixel is transparent. You would also need to make sure that the
\r
1348 transparency information is upgraded to RGB.
\r
1350 To summarize, the current flow is:
\r
1351 - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
\r
1352 with background "in place" if transparent,
\r
1353 convert to RGB if necessary
\r
1354 - Gray + alpha -> composite with gray background and remove alpha bytes,
\r
1355 convert to RGB if necessary
\r
1357 To support RGB backgrounds for gray images we need:
\r
1358 - Gray + simple transparency -> convert to RGB + simple transparency, compare
\r
1359 3 or 6 bytes and composite with background
\r
1360 "in place" if transparent (3x compare/pixel
\r
1361 compared to doing composite with gray bkgrnd)
\r
1362 - Gray + alpha -> convert to RGB + alpha, composite with background and
\r
1363 remove alpha bytes (3x float operations/pixel
\r
1364 compared with composite on gray background)
\r
1366 Greg's change will do this. The reason it wasn't done before is for
\r
1367 performance, as this increases the per-pixel operations. If we would check
\r
1368 in advance if the background was gray or RGB, and position the gray-to-RGB
\r
1369 transform appropriately, then it would save a lot of work/time.
\r
1372 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
\r
1373 /* if gray -> RGB, do so now only if background is non-gray; else do later
\r
1374 * for performance reasons */
\r
1375 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
\r
1376 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
\r
1377 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
\r
1380 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
1381 if ((png_ptr->transformations & PNG_BACKGROUND) &&
\r
1382 ((png_ptr->num_trans != 0 ) ||
\r
1383 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
\r
1384 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
\r
1385 &(png_ptr->trans_values), &(png_ptr->background)
\r
1386 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
1387 , &(png_ptr->background_1),
\r
1388 png_ptr->gamma_table, png_ptr->gamma_from_1,
\r
1389 png_ptr->gamma_to_1, png_ptr->gamma_16_table,
\r
1390 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
\r
1391 png_ptr->gamma_shift
\r
1396 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
1397 if ((png_ptr->transformations & PNG_GAMMA) &&
\r
1398 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
1399 !((png_ptr->transformations & PNG_BACKGROUND) &&
\r
1400 ((png_ptr->num_trans != 0) ||
\r
1401 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
\r
1403 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
\r
1404 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
\r
1405 png_ptr->gamma_table, png_ptr->gamma_16_table,
\r
1406 png_ptr->gamma_shift);
\r
1409 #if defined(PNG_READ_16_TO_8_SUPPORTED)
\r
1410 if (png_ptr->transformations & PNG_16_TO_8)
\r
1411 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
\r
1414 #if defined(PNG_READ_DITHER_SUPPORTED)
\r
1415 if (png_ptr->transformations & PNG_DITHER)
\r
1417 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
\r
1418 png_ptr->palette_lookup, png_ptr->dither_index);
\r
1419 if (png_ptr->row_info.rowbytes == (png_uint_32)0)
\r
1420 png_error(png_ptr, "png_do_dither returned rowbytes=0");
\r
1424 #if defined(PNG_READ_INVERT_SUPPORTED)
\r
1425 if (png_ptr->transformations & PNG_INVERT_MONO)
\r
1426 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
\r
1429 #if defined(PNG_READ_SHIFT_SUPPORTED)
\r
1430 if (png_ptr->transformations & PNG_SHIFT)
\r
1431 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
\r
1432 &(png_ptr->shift));
\r
1435 #if defined(PNG_READ_PACK_SUPPORTED)
\r
1436 if (png_ptr->transformations & PNG_PACK)
\r
1437 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
\r
1440 #if defined(PNG_READ_BGR_SUPPORTED)
\r
1441 if (png_ptr->transformations & PNG_BGR)
\r
1442 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
\r
1445 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
\r
1446 if (png_ptr->transformations & PNG_PACKSWAP)
\r
1447 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
\r
1450 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
\r
1451 /* if gray -> RGB, do so now only if we did not do so above */
\r
1452 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
\r
1453 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
\r
1454 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
\r
1457 #if defined(PNG_READ_FILLER_SUPPORTED)
\r
1458 if (png_ptr->transformations & PNG_FILLER)
\r
1459 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
\r
1460 (png_uint_32)png_ptr->filler, png_ptr->flags);
\r
1463 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
\r
1464 if (png_ptr->transformations & PNG_INVERT_ALPHA)
\r
1465 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
\r
1468 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
\r
1469 if (png_ptr->transformations & PNG_SWAP_ALPHA)
\r
1470 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
\r
1473 #if defined(PNG_READ_SWAP_SUPPORTED)
\r
1474 if (png_ptr->transformations & PNG_SWAP_BYTES)
\r
1475 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
\r
1478 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
\r
1479 if (png_ptr->transformations & PNG_USER_TRANSFORM)
\r
1481 if (png_ptr->read_user_transform_fn != NULL)
\r
1482 (*(png_ptr->read_user_transform_fn)) /* user read transform function */
\r
1483 (png_ptr, /* png_ptr */
\r
1484 &(png_ptr->row_info), /* row_info: */
\r
1485 /* png_uint_32 width; width of row */
\r
1486 /* png_uint_32 rowbytes; number of bytes in row */
\r
1487 /* png_byte color_type; color type of pixels */
\r
1488 /* png_byte bit_depth; bit depth of samples */
\r
1489 /* png_byte channels; number of channels (1-4) */
\r
1490 /* png_byte pixel_depth; bits per pixel (depth*channels) */
\r
1491 png_ptr->row_buf + 1); /* start of pixel data for row */
\r
1492 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
\r
1493 if (png_ptr->user_transform_depth)
\r
1494 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
\r
1495 if (png_ptr->user_transform_channels)
\r
1496 png_ptr->row_info.channels = png_ptr->user_transform_channels;
\r
1498 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
\r
1499 png_ptr->row_info.channels);
\r
1500 png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
\r
1501 png_ptr->row_info.width);
\r
1507 #if defined(PNG_READ_PACK_SUPPORTED)
\r
1508 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
\r
1509 * without changing the actual values. Thus, if you had a row with
\r
1510 * a bit depth of 1, you would end up with bytes that only contained
\r
1511 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
\r
1512 * png_do_shift() after this.
\r
1514 void /* PRIVATE */
\r
1515 png_do_unpack(png_row_infop row_info, png_bytep row)
\r
1517 png_debug(1, "in png_do_unpack\n");
\r
1518 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
1519 if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
\r
1521 if (row_info->bit_depth < 8)
\r
1525 png_uint_32 row_width=row_info->width;
\r
1527 switch (row_info->bit_depth)
\r
1531 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
\r
1532 png_bytep dp = row + (png_size_t)row_width - 1;
\r
1533 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
\r
1534 for (i = 0; i < row_width; i++)
\r
1536 *dp = (png_byte)((*sp >> shift) & 0x01);
\r
1552 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
\r
1553 png_bytep dp = row + (png_size_t)row_width - 1;
\r
1554 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
\r
1555 for (i = 0; i < row_width; i++)
\r
1557 *dp = (png_byte)((*sp >> shift) & 0x03);
\r
1572 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
\r
1573 png_bytep dp = row + (png_size_t)row_width - 1;
\r
1574 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
\r
1575 for (i = 0; i < row_width; i++)
\r
1577 *dp = (png_byte)((*sp >> shift) & 0x0f);
\r
1591 row_info->bit_depth = 8;
\r
1592 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
\r
1593 row_info->rowbytes = row_width * row_info->channels;
\r
1598 #if defined(PNG_READ_SHIFT_SUPPORTED)
\r
1599 /* Reverse the effects of png_do_shift. This routine merely shifts the
\r
1600 * pixels back to their significant bits values. Thus, if you have
\r
1601 * a row of bit depth 8, but only 5 are significant, this will shift
\r
1602 * the values back to 0 through 31.
\r
1604 void /* PRIVATE */
\r
1605 png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
\r
1607 png_debug(1, "in png_do_unshift\n");
\r
1609 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
1610 row != NULL && row_info != NULL && sig_bits != NULL &&
\r
1612 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
\r
1617 png_uint_16 value = 0;
\r
1618 png_uint_32 row_width = row_info->width;
\r
1620 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
\r
1622 shift[channels++] = row_info->bit_depth - sig_bits->red;
\r
1623 shift[channels++] = row_info->bit_depth - sig_bits->green;
\r
1624 shift[channels++] = row_info->bit_depth - sig_bits->blue;
\r
1628 shift[channels++] = row_info->bit_depth - sig_bits->gray;
\r
1630 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
\r
1632 shift[channels++] = row_info->bit_depth - sig_bits->alpha;
\r
1635 for (c = 0; c < channels; c++)
\r
1637 if (shift[c] <= 0)
\r
1646 switch (row_info->bit_depth)
\r
1652 png_uint_32 istop = row_info->rowbytes;
\r
1654 for (bp = row, i = 0; i < istop; i++)
\r
1663 png_bytep bp = row;
\r
1665 png_uint_32 istop = row_info->rowbytes;
\r
1666 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
\r
1667 (png_byte)((int)0xf >> shift[0]));
\r
1669 for (i = 0; i < istop; i++)
\r
1678 png_bytep bp = row;
\r
1680 png_uint_32 istop = row_width * channels;
\r
1682 for (i = 0; i < istop; i++)
\r
1684 *bp++ >>= shift[i%channels];
\r
1690 png_bytep bp = row;
\r
1692 png_uint_32 istop = channels * row_width;
\r
1694 for (i = 0; i < istop; i++)
\r
1696 value = (png_uint_16)((*bp << 8) + *(bp + 1));
\r
1697 value >>= shift[i%channels];
\r
1698 *bp++ = (png_byte)(value >> 8);
\r
1699 *bp++ = (png_byte)(value & 0xff);
\r
1708 #if defined(PNG_READ_16_TO_8_SUPPORTED)
\r
1709 /* chop rows of bit depth 16 down to 8 */
\r
1710 void /* PRIVATE */
\r
1711 png_do_chop(png_row_infop row_info, png_bytep row)
\r
1713 png_debug(1, "in png_do_chop\n");
\r
1714 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
1715 if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
\r
1717 if (row_info->bit_depth == 16)
\r
1720 png_bytep sp = row;
\r
1721 png_bytep dp = row;
\r
1723 png_uint_32 istop = row_info->width * row_info->channels;
\r
1725 for (i = 0; i<istop; i++, sp += 2, dp++)
\r
1727 #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
\r
1728 /* This does a more accurate scaling of the 16-bit color
\r
1729 * value, rather than a simple low-byte truncation.
\r
1731 * What the ideal calculation should be:
\r
1732 * *dp = (((((png_uint_32)(*sp) << 8) |
\r
1733 * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
\r
1735 * GRR: no, I think this is what it really should be:
\r
1736 * *dp = (((((png_uint_32)(*sp) << 8) |
\r
1737 * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
\r
1739 * GRR: here's the exact calculation with shifts:
\r
1740 * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
\r
1741 * *dp = (temp - (temp >> 8)) >> 8;
\r
1743 * Approximate calculation with shift/add instead of multiply/divide:
\r
1744 * *dp = ((((png_uint_32)(*sp) << 8) |
\r
1745 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
\r
1747 * What we actually do to avoid extra shifting and conversion:
\r
1750 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
\r
1752 /* Simply discard the low order byte */
\r
1756 row_info->bit_depth = 8;
\r
1757 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
\r
1758 row_info->rowbytes = row_info->width * row_info->channels;
\r
1763 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
\r
1764 void /* PRIVATE */
\r
1765 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
\r
1767 png_debug(1, "in png_do_read_swap_alpha\n");
\r
1768 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
1769 if (row != NULL && row_info != NULL)
\r
1772 png_uint_32 row_width = row_info->width;
\r
1773 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
\r
1775 /* This converts from RGBA to ARGB */
\r
1776 if (row_info->bit_depth == 8)
\r
1778 png_bytep sp = row + row_info->rowbytes;
\r
1779 png_bytep dp = sp;
\r
1783 for (i = 0; i < row_width; i++)
\r
1786 *(--dp) = *(--sp);
\r
1787 *(--dp) = *(--sp);
\r
1788 *(--dp) = *(--sp);
\r
1792 /* This converts from RRGGBBAA to AARRGGBB */
\r
1795 png_bytep sp = row + row_info->rowbytes;
\r
1796 png_bytep dp = sp;
\r
1800 for (i = 0; i < row_width; i++)
\r
1802 save[0] = *(--sp);
\r
1803 save[1] = *(--sp);
\r
1804 *(--dp) = *(--sp);
\r
1805 *(--dp) = *(--sp);
\r
1806 *(--dp) = *(--sp);
\r
1807 *(--dp) = *(--sp);
\r
1808 *(--dp) = *(--sp);
\r
1809 *(--dp) = *(--sp);
\r
1810 *(--dp) = save[0];
\r
1811 *(--dp) = save[1];
\r
1815 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
\r
1817 /* This converts from GA to AG */
\r
1818 if (row_info->bit_depth == 8)
\r
1820 png_bytep sp = row + row_info->rowbytes;
\r
1821 png_bytep dp = sp;
\r
1825 for (i = 0; i < row_width; i++)
\r
1828 *(--dp) = *(--sp);
\r
1832 /* This converts from GGAA to AAGG */
\r
1835 png_bytep sp = row + row_info->rowbytes;
\r
1836 png_bytep dp = sp;
\r
1840 for (i = 0; i < row_width; i++)
\r
1842 save[0] = *(--sp);
\r
1843 save[1] = *(--sp);
\r
1844 *(--dp) = *(--sp);
\r
1845 *(--dp) = *(--sp);
\r
1846 *(--dp) = save[0];
\r
1847 *(--dp) = save[1];
\r
1855 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
\r
1856 void /* PRIVATE */
\r
1857 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
\r
1859 png_debug(1, "in png_do_read_invert_alpha\n");
\r
1860 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
1861 if (row != NULL && row_info != NULL)
\r
1864 png_uint_32 row_width = row_info->width;
\r
1865 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
\r
1867 /* This inverts the alpha channel in RGBA */
\r
1868 if (row_info->bit_depth == 8)
\r
1870 png_bytep sp = row + row_info->rowbytes;
\r
1871 png_bytep dp = sp;
\r
1874 for (i = 0; i < row_width; i++)
\r
1876 *(--dp) = (png_byte)(255 - *(--sp));
\r
1878 /* This does nothing:
\r
1879 *(--dp) = *(--sp);
\r
1880 *(--dp) = *(--sp);
\r
1881 *(--dp) = *(--sp);
\r
1882 We can replace it with:
\r
1888 /* This inverts the alpha channel in RRGGBBAA */
\r
1891 png_bytep sp = row + row_info->rowbytes;
\r
1892 png_bytep dp = sp;
\r
1895 for (i = 0; i < row_width; i++)
\r
1897 *(--dp) = (png_byte)(255 - *(--sp));
\r
1898 *(--dp) = (png_byte)(255 - *(--sp));
\r
1900 /* This does nothing:
\r
1901 *(--dp) = *(--sp);
\r
1902 *(--dp) = *(--sp);
\r
1903 *(--dp) = *(--sp);
\r
1904 *(--dp) = *(--sp);
\r
1905 *(--dp) = *(--sp);
\r
1906 *(--dp) = *(--sp);
\r
1907 We can replace it with:
\r
1914 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
\r
1916 /* This inverts the alpha channel in GA */
\r
1917 if (row_info->bit_depth == 8)
\r
1919 png_bytep sp = row + row_info->rowbytes;
\r
1920 png_bytep dp = sp;
\r
1923 for (i = 0; i < row_width; i++)
\r
1925 *(--dp) = (png_byte)(255 - *(--sp));
\r
1926 *(--dp) = *(--sp);
\r
1929 /* This inverts the alpha channel in GGAA */
\r
1932 png_bytep sp = row + row_info->rowbytes;
\r
1933 png_bytep dp = sp;
\r
1936 for (i = 0; i < row_width; i++)
\r
1938 *(--dp) = (png_byte)(255 - *(--sp));
\r
1939 *(--dp) = (png_byte)(255 - *(--sp));
\r
1941 *(--dp) = *(--sp);
\r
1942 *(--dp) = *(--sp);
\r
1953 #if defined(PNG_READ_FILLER_SUPPORTED)
\r
1954 /* Add filler channel if we have RGB color */
\r
1955 void /* PRIVATE */
\r
1956 png_do_read_filler(png_row_infop row_info, png_bytep row,
\r
1957 png_uint_32 filler, png_uint_32 flags)
\r
1960 png_uint_32 row_width = row_info->width;
\r
1962 png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
\r
1963 png_byte lo_filler = (png_byte)(filler & 0xff);
\r
1965 png_debug(1, "in png_do_read_filler\n");
\r
1967 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
1968 row != NULL && row_info != NULL &&
\r
1970 row_info->color_type == PNG_COLOR_TYPE_GRAY)
\r
1972 if (row_info->bit_depth == 8)
\r
1974 /* This changes the data from G to GX */
\r
1975 if (flags & PNG_FLAG_FILLER_AFTER)
\r
1977 png_bytep sp = row + (png_size_t)row_width;
\r
1978 png_bytep dp = sp + (png_size_t)row_width;
\r
1979 for (i = 1; i < row_width; i++)
\r
1981 *(--dp) = lo_filler;
\r
1982 *(--dp) = *(--sp);
\r
1984 *(--dp) = lo_filler;
\r
1985 row_info->channels = 2;
\r
1986 row_info->pixel_depth = 16;
\r
1987 row_info->rowbytes = row_width * 2;
\r
1989 /* This changes the data from G to XG */
\r
1992 png_bytep sp = row + (png_size_t)row_width;
\r
1993 png_bytep dp = sp + (png_size_t)row_width;
\r
1994 for (i = 0; i < row_width; i++)
\r
1996 *(--dp) = *(--sp);
\r
1997 *(--dp) = lo_filler;
\r
1999 row_info->channels = 2;
\r
2000 row_info->pixel_depth = 16;
\r
2001 row_info->rowbytes = row_width * 2;
\r
2004 else if (row_info->bit_depth == 16)
\r
2006 /* This changes the data from GG to GGXX */
\r
2007 if (flags & PNG_FLAG_FILLER_AFTER)
\r
2009 png_bytep sp = row + (png_size_t)row_width * 2;
\r
2010 png_bytep dp = sp + (png_size_t)row_width * 2;
\r
2011 for (i = 1; i < row_width; i++)
\r
2013 *(--dp) = hi_filler;
\r
2014 *(--dp) = lo_filler;
\r
2015 *(--dp) = *(--sp);
\r
2016 *(--dp) = *(--sp);
\r
2018 *(--dp) = hi_filler;
\r
2019 *(--dp) = lo_filler;
\r
2020 row_info->channels = 2;
\r
2021 row_info->pixel_depth = 32;
\r
2022 row_info->rowbytes = row_width * 4;
\r
2024 /* This changes the data from GG to XXGG */
\r
2027 png_bytep sp = row + (png_size_t)row_width * 2;
\r
2028 png_bytep dp = sp + (png_size_t)row_width * 2;
\r
2029 for (i = 0; i < row_width; i++)
\r
2031 *(--dp) = *(--sp);
\r
2032 *(--dp) = *(--sp);
\r
2033 *(--dp) = hi_filler;
\r
2034 *(--dp) = lo_filler;
\r
2036 row_info->channels = 2;
\r
2037 row_info->pixel_depth = 32;
\r
2038 row_info->rowbytes = row_width * 4;
\r
2041 } /* COLOR_TYPE == GRAY */
\r
2042 else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
\r
2044 if (row_info->bit_depth == 8)
\r
2046 /* This changes the data from RGB to RGBX */
\r
2047 if (flags & PNG_FLAG_FILLER_AFTER)
\r
2049 png_bytep sp = row + (png_size_t)row_width * 3;
\r
2050 png_bytep dp = sp + (png_size_t)row_width;
\r
2051 for (i = 1; i < row_width; i++)
\r
2053 *(--dp) = lo_filler;
\r
2054 *(--dp) = *(--sp);
\r
2055 *(--dp) = *(--sp);
\r
2056 *(--dp) = *(--sp);
\r
2058 *(--dp) = lo_filler;
\r
2059 row_info->channels = 4;
\r
2060 row_info->pixel_depth = 32;
\r
2061 row_info->rowbytes = row_width * 4;
\r
2063 /* This changes the data from RGB to XRGB */
\r
2066 png_bytep sp = row + (png_size_t)row_width * 3;
\r
2067 png_bytep dp = sp + (png_size_t)row_width;
\r
2068 for (i = 0; i < row_width; i++)
\r
2070 *(--dp) = *(--sp);
\r
2071 *(--dp) = *(--sp);
\r
2072 *(--dp) = *(--sp);
\r
2073 *(--dp) = lo_filler;
\r
2075 row_info->channels = 4;
\r
2076 row_info->pixel_depth = 32;
\r
2077 row_info->rowbytes = row_width * 4;
\r
2080 else if (row_info->bit_depth == 16)
\r
2082 /* This changes the data from RRGGBB to RRGGBBXX */
\r
2083 if (flags & PNG_FLAG_FILLER_AFTER)
\r
2085 png_bytep sp = row + (png_size_t)row_width * 6;
\r
2086 png_bytep dp = sp + (png_size_t)row_width * 2;
\r
2087 for (i = 1; i < row_width; i++)
\r
2089 *(--dp) = hi_filler;
\r
2090 *(--dp) = lo_filler;
\r
2091 *(--dp) = *(--sp);
\r
2092 *(--dp) = *(--sp);
\r
2093 *(--dp) = *(--sp);
\r
2094 *(--dp) = *(--sp);
\r
2095 *(--dp) = *(--sp);
\r
2096 *(--dp) = *(--sp);
\r
2098 *(--dp) = hi_filler;
\r
2099 *(--dp) = lo_filler;
\r
2100 row_info->channels = 4;
\r
2101 row_info->pixel_depth = 64;
\r
2102 row_info->rowbytes = row_width * 8;
\r
2104 /* This changes the data from RRGGBB to XXRRGGBB */
\r
2107 png_bytep sp = row + (png_size_t)row_width * 6;
\r
2108 png_bytep dp = sp + (png_size_t)row_width * 2;
\r
2109 for (i = 0; i < row_width; i++)
\r
2111 *(--dp) = *(--sp);
\r
2112 *(--dp) = *(--sp);
\r
2113 *(--dp) = *(--sp);
\r
2114 *(--dp) = *(--sp);
\r
2115 *(--dp) = *(--sp);
\r
2116 *(--dp) = *(--sp);
\r
2117 *(--dp) = hi_filler;
\r
2118 *(--dp) = lo_filler;
\r
2120 row_info->channels = 4;
\r
2121 row_info->pixel_depth = 64;
\r
2122 row_info->rowbytes = row_width * 8;
\r
2125 } /* COLOR_TYPE == RGB */
\r
2129 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
\r
2130 /* expand grayscale files to RGB, with or without alpha */
\r
2131 void /* PRIVATE */
\r
2132 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
\r
2135 png_uint_32 row_width = row_info->width;
\r
2137 png_debug(1, "in png_do_gray_to_rgb\n");
\r
2138 if (row_info->bit_depth >= 8 &&
\r
2139 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
2140 row != NULL && row_info != NULL &&
\r
2142 !(row_info->color_type & PNG_COLOR_MASK_COLOR))
\r
2144 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
\r
2146 if (row_info->bit_depth == 8)
\r
2148 png_bytep sp = row + (png_size_t)row_width - 1;
\r
2149 png_bytep dp = sp + (png_size_t)row_width * 2;
\r
2150 for (i = 0; i < row_width; i++)
\r
2154 *(dp--) = *(sp--);
\r
2159 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
\r
2160 png_bytep dp = sp + (png_size_t)row_width * 4;
\r
2161 for (i = 0; i < row_width; i++)
\r
2164 *(dp--) = *(sp - 1);
\r
2166 *(dp--) = *(sp - 1);
\r
2167 *(dp--) = *(sp--);
\r
2168 *(dp--) = *(sp--);
\r
2172 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
\r
2174 if (row_info->bit_depth == 8)
\r
2176 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
\r
2177 png_bytep dp = sp + (png_size_t)row_width * 2;
\r
2178 for (i = 0; i < row_width; i++)
\r
2180 *(dp--) = *(sp--);
\r
2183 *(dp--) = *(sp--);
\r
2188 png_bytep sp = row + (png_size_t)row_width * 4 - 1;
\r
2189 png_bytep dp = sp + (png_size_t)row_width * 4;
\r
2190 for (i = 0; i < row_width; i++)
\r
2192 *(dp--) = *(sp--);
\r
2193 *(dp--) = *(sp--);
\r
2195 *(dp--) = *(sp - 1);
\r
2197 *(dp--) = *(sp - 1);
\r
2198 *(dp--) = *(sp--);
\r
2199 *(dp--) = *(sp--);
\r
2203 row_info->channels += (png_byte)2;
\r
2204 row_info->color_type |= PNG_COLOR_MASK_COLOR;
\r
2205 row_info->pixel_depth = (png_byte)(row_info->channels *
\r
2206 row_info->bit_depth);
\r
2207 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
\r
2212 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
\r
2213 /* reduce RGB files to grayscale, with or without alpha
\r
2214 * using the equation given in Poynton's ColorFAQ at
\r
2215 * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008)
\r
2217 * <http://www.poynton.com/notes/colour_and_gamma/>
\r
2218 * Charles Poynton poynton at poynton.com
\r
2220 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
\r
2222 * We approximate this with
\r
2224 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
\r
2226 * which can be expressed with integers as
\r
2228 * Y = (6969 * R + 23434 * G + 2365 * B)/32768
\r
2230 * The calculation is to be done in a linear colorspace.
\r
2232 * Other integer coefficents can be used via png_set_rgb_to_gray().
\r
2235 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
\r
2240 png_uint_32 row_width = row_info->width;
\r
2241 int rgb_error = 0;
\r
2243 png_debug(1, "in png_do_rgb_to_gray\n");
\r
2245 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
2246 row != NULL && row_info != NULL &&
\r
2248 (row_info->color_type & PNG_COLOR_MASK_COLOR))
\r
2250 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
\r
2251 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
\r
2252 png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
\r
2254 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
\r
2256 if (row_info->bit_depth == 8)
\r
2258 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
2259 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
\r
2261 png_bytep sp = row;
\r
2262 png_bytep dp = row;
\r
2264 for (i = 0; i < row_width; i++)
\r
2266 png_byte red = png_ptr->gamma_to_1[*(sp++)];
\r
2267 png_byte green = png_ptr->gamma_to_1[*(sp++)];
\r
2268 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
\r
2269 if (red != green || red != blue)
\r
2272 *(dp++) = png_ptr->gamma_from_1[
\r
2273 (rc*red + gc*green + bc*blue)>>15];
\r
2276 *(dp++) = *(sp - 1);
\r
2282 png_bytep sp = row;
\r
2283 png_bytep dp = row;
\r
2284 for (i = 0; i < row_width; i++)
\r
2286 png_byte red = *(sp++);
\r
2287 png_byte green = *(sp++);
\r
2288 png_byte blue = *(sp++);
\r
2289 if (red != green || red != blue)
\r
2292 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
\r
2295 *(dp++) = *(sp - 1);
\r
2300 else /* RGB bit_depth == 16 */
\r
2302 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
2303 if (png_ptr->gamma_16_to_1 != NULL &&
\r
2304 png_ptr->gamma_16_from_1 != NULL)
\r
2306 png_bytep sp = row;
\r
2307 png_bytep dp = row;
\r
2308 for (i = 0; i < row_width; i++)
\r
2310 png_uint_16 red, green, blue, w;
\r
2312 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
\r
2313 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
\r
2314 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
\r
2316 if (red == green && red == blue)
\r
2320 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
\r
2321 png_ptr->gamma_shift][red>>8];
\r
2322 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
\r
2323 png_ptr->gamma_shift][green>>8];
\r
2324 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
\r
2325 png_ptr->gamma_shift][blue>>8];
\r
2326 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
\r
2327 + bc*blue_1)>>15);
\r
2328 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
\r
2329 png_ptr->gamma_shift][gray16 >> 8];
\r
2333 *(dp++) = (png_byte)((w>>8) & 0xff);
\r
2334 *(dp++) = (png_byte)(w & 0xff);
\r
2340 png_bytep sp = row;
\r
2341 png_bytep dp = row;
\r
2342 for (i = 0; i < row_width; i++)
\r
2344 png_uint_16 red, green, blue, gray16;
\r
2346 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
\r
2347 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
\r
2348 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
\r
2350 if (red != green || red != blue)
\r
2352 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
\r
2353 *(dp++) = (png_byte)((gray16>>8) & 0xff);
\r
2354 *(dp++) = (png_byte)(gray16 & 0xff);
\r
2359 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
\r
2361 if (row_info->bit_depth == 8)
\r
2363 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
2364 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
\r
2366 png_bytep sp = row;
\r
2367 png_bytep dp = row;
\r
2368 for (i = 0; i < row_width; i++)
\r
2370 png_byte red = png_ptr->gamma_to_1[*(sp++)];
\r
2371 png_byte green = png_ptr->gamma_to_1[*(sp++)];
\r
2372 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
\r
2373 if (red != green || red != blue)
\r
2375 *(dp++) = png_ptr->gamma_from_1
\r
2376 [(rc*red + gc*green + bc*blue)>>15];
\r
2377 *(dp++) = *(sp++); /* alpha */
\r
2383 png_bytep sp = row;
\r
2384 png_bytep dp = row;
\r
2385 for (i = 0; i < row_width; i++)
\r
2387 png_byte red = *(sp++);
\r
2388 png_byte green = *(sp++);
\r
2389 png_byte blue = *(sp++);
\r
2390 if (red != green || red != blue)
\r
2392 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
\r
2393 *(dp++) = *(sp++); /* alpha */
\r
2397 else /* RGBA bit_depth == 16 */
\r
2399 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
2400 if (png_ptr->gamma_16_to_1 != NULL &&
\r
2401 png_ptr->gamma_16_from_1 != NULL)
\r
2403 png_bytep sp = row;
\r
2404 png_bytep dp = row;
\r
2405 for (i = 0; i < row_width; i++)
\r
2407 png_uint_16 red, green, blue, w;
\r
2409 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
\r
2410 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
\r
2411 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
\r
2413 if (red == green && red == blue)
\r
2417 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
\r
2418 png_ptr->gamma_shift][red>>8];
\r
2419 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
\r
2420 png_ptr->gamma_shift][green>>8];
\r
2421 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
\r
2422 png_ptr->gamma_shift][blue>>8];
\r
2423 png_uint_16 gray16 = (png_uint_16)((rc * red_1
\r
2424 + gc * green_1 + bc * blue_1)>>15);
\r
2425 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
\r
2426 png_ptr->gamma_shift][gray16 >> 8];
\r
2430 *(dp++) = (png_byte)((w>>8) & 0xff);
\r
2431 *(dp++) = (png_byte)(w & 0xff);
\r
2432 *(dp++) = *(sp++); /* alpha */
\r
2433 *(dp++) = *(sp++);
\r
2439 png_bytep sp = row;
\r
2440 png_bytep dp = row;
\r
2441 for (i = 0; i < row_width; i++)
\r
2443 png_uint_16 red, green, blue, gray16;
\r
2444 red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
\r
2445 green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
\r
2446 blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
\r
2447 if (red != green || red != blue)
\r
2449 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
\r
2450 *(dp++) = (png_byte)((gray16>>8) & 0xff);
\r
2451 *(dp++) = (png_byte)(gray16 & 0xff);
\r
2452 *(dp++) = *(sp++); /* alpha */
\r
2453 *(dp++) = *(sp++);
\r
2458 row_info->channels -= (png_byte)2;
\r
2459 row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
\r
2460 row_info->pixel_depth = (png_byte)(row_info->channels *
\r
2461 row_info->bit_depth);
\r
2462 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
\r
2468 /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
\r
2469 * large of png_color. This lets grayscale images be treated as
\r
2470 * paletted. Most useful for gamma correction and simplification
\r
2474 png_build_grayscale_palette(int bit_depth, png_colorp palette)
\r
2481 png_debug(1, "in png_do_build_grayscale_palette\n");
\r
2482 if (palette == NULL)
\r
2485 switch (bit_depth)
\r
2500 num_palette = 256;
\r
2509 for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
\r
2511 palette[i].red = (png_byte)v;
\r
2512 palette[i].green = (png_byte)v;
\r
2513 palette[i].blue = (png_byte)v;
\r
2517 /* This function is currently unused. Do we really need it? */
\r
2518 #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
\r
2519 void /* PRIVATE */
\r
2520 png_correct_palette(png_structp png_ptr, png_colorp palette,
\r
2523 png_debug(1, "in png_correct_palette\n");
\r
2524 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
\r
2525 defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
\r
2526 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
\r
2528 png_color back, back_1;
\r
2530 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
\r
2532 back.red = png_ptr->gamma_table[png_ptr->background.red];
\r
2533 back.green = png_ptr->gamma_table[png_ptr->background.green];
\r
2534 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
\r
2536 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
\r
2537 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
\r
2538 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
\r
2544 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
\r
2546 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
\r
2547 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
\r
2549 back.red = png_ptr->background.red;
\r
2550 back.green = png_ptr->background.green;
\r
2551 back.blue = png_ptr->background.blue;
\r
2556 (png_byte)(pow((double)png_ptr->background.red/255, g) *
\r
2559 (png_byte)(pow((double)png_ptr->background.green/255, g) *
\r
2562 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
\r
2566 g = 1.0 / png_ptr->background_gamma;
\r
2569 (png_byte)(pow((double)png_ptr->background.red/255, g) *
\r
2572 (png_byte)(pow((double)png_ptr->background.green/255, g) *
\r
2575 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
\r
2579 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
2583 for (i = 0; i < (png_uint_32)num_palette; i++)
\r
2585 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
\r
2587 palette[i] = back;
\r
2589 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
\r
2593 v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
\r
2594 png_composite(w, v, png_ptr->trans[i], back_1.red);
\r
2595 palette[i].red = png_ptr->gamma_from_1[w];
\r
2597 v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
\r
2598 png_composite(w, v, png_ptr->trans[i], back_1.green);
\r
2599 palette[i].green = png_ptr->gamma_from_1[w];
\r
2601 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
\r
2602 png_composite(w, v, png_ptr->trans[i], back_1.blue);
\r
2603 palette[i].blue = png_ptr->gamma_from_1[w];
\r
2607 palette[i].red = png_ptr->gamma_table[palette[i].red];
\r
2608 palette[i].green = png_ptr->gamma_table[palette[i].green];
\r
2609 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
\r
2617 for (i = 0; i < num_palette; i++)
\r
2619 if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
\r
2621 palette[i] = back;
\r
2625 palette[i].red = png_ptr->gamma_table[palette[i].red];
\r
2626 palette[i].green = png_ptr->gamma_table[palette[i].green];
\r
2627 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
\r
2634 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
2635 if (png_ptr->transformations & PNG_GAMMA)
\r
2639 for (i = 0; i < num_palette; i++)
\r
2641 palette[i].red = png_ptr->gamma_table[palette[i].red];
\r
2642 palette[i].green = png_ptr->gamma_table[palette[i].green];
\r
2643 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
\r
2646 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
2650 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
2651 if (png_ptr->transformations & PNG_BACKGROUND)
\r
2653 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
2657 back.red = (png_byte)png_ptr->background.red;
\r
2658 back.green = (png_byte)png_ptr->background.green;
\r
2659 back.blue = (png_byte)png_ptr->background.blue;
\r
2661 for (i = 0; i < (int)png_ptr->num_trans; i++)
\r
2663 if (png_ptr->trans[i] == 0)
\r
2665 palette[i].red = back.red;
\r
2666 palette[i].green = back.green;
\r
2667 palette[i].blue = back.blue;
\r
2669 else if (png_ptr->trans[i] != 0xff)
\r
2671 png_composite(palette[i].red, png_ptr->palette[i].red,
\r
2672 png_ptr->trans[i], back.red);
\r
2673 png_composite(palette[i].green, png_ptr->palette[i].green,
\r
2674 png_ptr->trans[i], back.green);
\r
2675 png_composite(palette[i].blue, png_ptr->palette[i].blue,
\r
2676 png_ptr->trans[i], back.blue);
\r
2680 else /* assume grayscale palette (what else could it be?) */
\r
2684 for (i = 0; i < num_palette; i++)
\r
2686 if (i == (png_byte)png_ptr->trans_values.gray)
\r
2688 palette[i].red = (png_byte)png_ptr->background.red;
\r
2689 palette[i].green = (png_byte)png_ptr->background.green;
\r
2690 palette[i].blue = (png_byte)png_ptr->background.blue;
\r
2699 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
\r
2700 /* Replace any alpha or transparency with the supplied background color.
\r
2701 * "background" is already in the screen gamma, while "background_1" is
\r
2702 * at a gamma of 1.0. Paletted files have already been taken care of.
\r
2704 void /* PRIVATE */
\r
2705 png_do_background(png_row_infop row_info, png_bytep row,
\r
2706 png_color_16p trans_values, png_color_16p background
\r
2707 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
2708 , png_color_16p background_1,
\r
2709 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
\r
2710 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
\r
2711 png_uint_16pp gamma_16_to_1, int gamma_shift
\r
2717 png_uint_32 row_width=row_info->width;
\r
2720 png_debug(1, "in png_do_background\n");
\r
2721 if (background != NULL &&
\r
2722 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
2723 row != NULL && row_info != NULL &&
\r
2725 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
\r
2726 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
\r
2728 switch (row_info->color_type)
\r
2730 case PNG_COLOR_TYPE_GRAY:
\r
2732 switch (row_info->bit_depth)
\r
2738 for (i = 0; i < row_width; i++)
\r
2740 if ((png_uint_16)((*sp >> shift) & 0x01)
\r
2741 == trans_values->gray)
\r
2743 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
\r
2744 *sp |= (png_byte)(background->gray << shift);
\r
2758 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
2759 if (gamma_table != NULL)
\r
2763 for (i = 0; i < row_width; i++)
\r
2765 if ((png_uint_16)((*sp >> shift) & 0x03)
\r
2766 == trans_values->gray)
\r
2768 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
\r
2769 *sp |= (png_byte)(background->gray << shift);
\r
2773 png_byte p = (png_byte)((*sp >> shift) & 0x03);
\r
2774 png_byte g = (png_byte)((gamma_table [p | (p << 2) |
\r
2775 (p << 4) | (p << 6)] >> 6) & 0x03);
\r
2776 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
\r
2777 *sp |= (png_byte)(g << shift);
\r
2793 for (i = 0; i < row_width; i++)
\r
2795 if ((png_uint_16)((*sp >> shift) & 0x03)
\r
2796 == trans_values->gray)
\r
2798 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
\r
2799 *sp |= (png_byte)(background->gray << shift);
\r
2814 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
2815 if (gamma_table != NULL)
\r
2819 for (i = 0; i < row_width; i++)
\r
2821 if ((png_uint_16)((*sp >> shift) & 0x0f)
\r
2822 == trans_values->gray)
\r
2824 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
\r
2825 *sp |= (png_byte)(background->gray << shift);
\r
2829 png_byte p = (png_byte)((*sp >> shift) & 0x0f);
\r
2830 png_byte g = (png_byte)((gamma_table[p |
\r
2831 (p << 4)] >> 4) & 0x0f);
\r
2832 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
\r
2833 *sp |= (png_byte)(g << shift);
\r
2849 for (i = 0; i < row_width; i++)
\r
2851 if ((png_uint_16)((*sp >> shift) & 0x0f)
\r
2852 == trans_values->gray)
\r
2854 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
\r
2855 *sp |= (png_byte)(background->gray << shift);
\r
2870 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
2871 if (gamma_table != NULL)
\r
2874 for (i = 0; i < row_width; i++, sp++)
\r
2876 if (*sp == trans_values->gray)
\r
2878 *sp = (png_byte)background->gray;
\r
2882 *sp = gamma_table[*sp];
\r
2890 for (i = 0; i < row_width; i++, sp++)
\r
2892 if (*sp == trans_values->gray)
\r
2894 *sp = (png_byte)background->gray;
\r
2902 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
2903 if (gamma_16 != NULL)
\r
2906 for (i = 0; i < row_width; i++, sp += 2)
\r
2910 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
\r
2911 if (v == trans_values->gray)
\r
2913 /* background is already in screen gamma */
\r
2914 *sp = (png_byte)((background->gray >> 8) & 0xff);
\r
2915 *(sp + 1) = (png_byte)(background->gray & 0xff);
\r
2919 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
\r
2920 *sp = (png_byte)((v >> 8) & 0xff);
\r
2921 *(sp + 1) = (png_byte)(v & 0xff);
\r
2929 for (i = 0; i < row_width; i++, sp += 2)
\r
2933 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
\r
2934 if (v == trans_values->gray)
\r
2936 *sp = (png_byte)((background->gray >> 8) & 0xff);
\r
2937 *(sp + 1) = (png_byte)(background->gray & 0xff);
\r
2946 case PNG_COLOR_TYPE_RGB:
\r
2948 if (row_info->bit_depth == 8)
\r
2950 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
2951 if (gamma_table != NULL)
\r
2954 for (i = 0; i < row_width; i++, sp += 3)
\r
2956 if (*sp == trans_values->red &&
\r
2957 *(sp + 1) == trans_values->green &&
\r
2958 *(sp + 2) == trans_values->blue)
\r
2960 *sp = (png_byte)background->red;
\r
2961 *(sp + 1) = (png_byte)background->green;
\r
2962 *(sp + 2) = (png_byte)background->blue;
\r
2966 *sp = gamma_table[*sp];
\r
2967 *(sp + 1) = gamma_table[*(sp + 1)];
\r
2968 *(sp + 2) = gamma_table[*(sp + 2)];
\r
2976 for (i = 0; i < row_width; i++, sp += 3)
\r
2978 if (*sp == trans_values->red &&
\r
2979 *(sp + 1) == trans_values->green &&
\r
2980 *(sp + 2) == trans_values->blue)
\r
2982 *sp = (png_byte)background->red;
\r
2983 *(sp + 1) = (png_byte)background->green;
\r
2984 *(sp + 2) = (png_byte)background->blue;
\r
2989 else /* if (row_info->bit_depth == 16) */
\r
2991 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
2992 if (gamma_16 != NULL)
\r
2995 for (i = 0; i < row_width; i++, sp += 6)
\r
2997 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
\r
2998 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
\r
2999 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
\r
3000 if (r == trans_values->red && g == trans_values->green &&
\r
3001 b == trans_values->blue)
\r
3003 /* background is already in screen gamma */
\r
3004 *sp = (png_byte)((background->red >> 8) & 0xff);
\r
3005 *(sp + 1) = (png_byte)(background->red & 0xff);
\r
3006 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
\r
3007 *(sp + 3) = (png_byte)(background->green & 0xff);
\r
3008 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
\r
3009 *(sp + 5) = (png_byte)(background->blue & 0xff);
\r
3013 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
\r
3014 *sp = (png_byte)((v >> 8) & 0xff);
\r
3015 *(sp + 1) = (png_byte)(v & 0xff);
\r
3016 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
\r
3017 *(sp + 2) = (png_byte)((v >> 8) & 0xff);
\r
3018 *(sp + 3) = (png_byte)(v & 0xff);
\r
3019 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
\r
3020 *(sp + 4) = (png_byte)((v >> 8) & 0xff);
\r
3021 *(sp + 5) = (png_byte)(v & 0xff);
\r
3029 for (i = 0; i < row_width; i++, sp += 6)
\r
3031 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
\r
3032 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
\r
3033 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
\r
3035 if (r == trans_values->red && g == trans_values->green &&
\r
3036 b == trans_values->blue)
\r
3038 *sp = (png_byte)((background->red >> 8) & 0xff);
\r
3039 *(sp + 1) = (png_byte)(background->red & 0xff);
\r
3040 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
\r
3041 *(sp + 3) = (png_byte)(background->green & 0xff);
\r
3042 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
\r
3043 *(sp + 5) = (png_byte)(background->blue & 0xff);
\r
3050 case PNG_COLOR_TYPE_GRAY_ALPHA:
\r
3052 if (row_info->bit_depth == 8)
\r
3054 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
3055 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
\r
3056 gamma_table != NULL)
\r
3060 for (i = 0; i < row_width; i++, sp += 2, dp++)
\r
3062 png_uint_16 a = *(sp + 1);
\r
3066 *dp = gamma_table[*sp];
\r
3070 /* background is already in screen gamma */
\r
3071 *dp = (png_byte)background->gray;
\r
3077 v = gamma_to_1[*sp];
\r
3078 png_composite(w, v, a, background_1->gray);
\r
3079 *dp = gamma_from_1[w];
\r
3088 for (i = 0; i < row_width; i++, sp += 2, dp++)
\r
3090 png_byte a = *(sp + 1);
\r
3096 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
3099 *dp = (png_byte)background->gray;
\r
3103 png_composite(*dp, *sp, a, background_1->gray);
\r
3106 *dp = (png_byte)background->gray;
\r
3111 else /* if (png_ptr->bit_depth == 16) */
\r
3113 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
3114 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
\r
3115 gamma_16_to_1 != NULL)
\r
3119 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
\r
3121 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
\r
3123 if (a == (png_uint_16)0xffff)
\r
3127 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
\r
3128 *dp = (png_byte)((v >> 8) & 0xff);
\r
3129 *(dp + 1) = (png_byte)(v & 0xff);
\r
3131 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
3137 /* background is already in screen gamma */
\r
3138 *dp = (png_byte)((background->gray >> 8) & 0xff);
\r
3139 *(dp + 1) = (png_byte)(background->gray & 0xff);
\r
3141 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
3144 png_uint_16 g, v, w;
\r
3146 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
\r
3147 png_composite_16(v, g, a, background_1->gray);
\r
3148 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
\r
3149 *dp = (png_byte)((w >> 8) & 0xff);
\r
3150 *(dp + 1) = (png_byte)(w & 0xff);
\r
3160 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
\r
3162 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
\r
3163 if (a == (png_uint_16)0xffff)
\r
3165 png_memcpy(dp, sp, 2);
\r
3167 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
3173 *dp = (png_byte)((background->gray >> 8) & 0xff);
\r
3174 *(dp + 1) = (png_byte)(background->gray & 0xff);
\r
3176 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
3181 g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
\r
3182 png_composite_16(v, g, a, background_1->gray);
\r
3183 *dp = (png_byte)((v >> 8) & 0xff);
\r
3184 *(dp + 1) = (png_byte)(v & 0xff);
\r
3192 case PNG_COLOR_TYPE_RGB_ALPHA:
\r
3194 if (row_info->bit_depth == 8)
\r
3196 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
3197 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
\r
3198 gamma_table != NULL)
\r
3202 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
\r
3204 png_byte a = *(sp + 3);
\r
3208 *dp = gamma_table[*sp];
\r
3209 *(dp + 1) = gamma_table[*(sp + 1)];
\r
3210 *(dp + 2) = gamma_table[*(sp + 2)];
\r
3214 /* background is already in screen gamma */
\r
3215 *dp = (png_byte)background->red;
\r
3216 *(dp + 1) = (png_byte)background->green;
\r
3217 *(dp + 2) = (png_byte)background->blue;
\r
3223 v = gamma_to_1[*sp];
\r
3224 png_composite(w, v, a, background_1->red);
\r
3225 *dp = gamma_from_1[w];
\r
3226 v = gamma_to_1[*(sp + 1)];
\r
3227 png_composite(w, v, a, background_1->green);
\r
3228 *(dp + 1) = gamma_from_1[w];
\r
3229 v = gamma_to_1[*(sp + 2)];
\r
3230 png_composite(w, v, a, background_1->blue);
\r
3231 *(dp + 2) = gamma_from_1[w];
\r
3240 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
\r
3242 png_byte a = *(sp + 3);
\r
3247 *(dp + 1) = *(sp + 1);
\r
3248 *(dp + 2) = *(sp + 2);
\r
3252 *dp = (png_byte)background->red;
\r
3253 *(dp + 1) = (png_byte)background->green;
\r
3254 *(dp + 2) = (png_byte)background->blue;
\r
3258 png_composite(*dp, *sp, a, background->red);
\r
3259 png_composite(*(dp + 1), *(sp + 1), a,
\r
3260 background->green);
\r
3261 png_composite(*(dp + 2), *(sp + 2), a,
\r
3262 background->blue);
\r
3267 else /* if (row_info->bit_depth == 16) */
\r
3269 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
3270 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
\r
3271 gamma_16_to_1 != NULL)
\r
3275 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
\r
3277 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
\r
3278 << 8) + (png_uint_16)(*(sp + 7)));
\r
3279 if (a == (png_uint_16)0xffff)
\r
3283 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
\r
3284 *dp = (png_byte)((v >> 8) & 0xff);
\r
3285 *(dp + 1) = (png_byte)(v & 0xff);
\r
3286 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
\r
3287 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
\r
3288 *(dp + 3) = (png_byte)(v & 0xff);
\r
3289 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
\r
3290 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
\r
3291 *(dp + 5) = (png_byte)(v & 0xff);
\r
3295 /* background is already in screen gamma */
\r
3296 *dp = (png_byte)((background->red >> 8) & 0xff);
\r
3297 *(dp + 1) = (png_byte)(background->red & 0xff);
\r
3298 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
\r
3299 *(dp + 3) = (png_byte)(background->green & 0xff);
\r
3300 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
\r
3301 *(dp + 5) = (png_byte)(background->blue & 0xff);
\r
3305 png_uint_16 v, w, x;
\r
3307 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
\r
3308 png_composite_16(w, v, a, background_1->red);
\r
3309 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
\r
3310 *dp = (png_byte)((x >> 8) & 0xff);
\r
3311 *(dp + 1) = (png_byte)(x & 0xff);
\r
3312 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
\r
3313 png_composite_16(w, v, a, background_1->green);
\r
3314 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
\r
3315 *(dp + 2) = (png_byte)((x >> 8) & 0xff);
\r
3316 *(dp + 3) = (png_byte)(x & 0xff);
\r
3317 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
\r
3318 png_composite_16(w, v, a, background_1->blue);
\r
3319 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
\r
3320 *(dp + 4) = (png_byte)((x >> 8) & 0xff);
\r
3321 *(dp + 5) = (png_byte)(x & 0xff);
\r
3330 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
\r
3332 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
\r
3333 << 8) + (png_uint_16)(*(sp + 7)));
\r
3334 if (a == (png_uint_16)0xffff)
\r
3336 png_memcpy(dp, sp, 6);
\r
3340 *dp = (png_byte)((background->red >> 8) & 0xff);
\r
3341 *(dp + 1) = (png_byte)(background->red & 0xff);
\r
3342 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
\r
3343 *(dp + 3) = (png_byte)(background->green & 0xff);
\r
3344 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
\r
3345 *(dp + 5) = (png_byte)(background->blue & 0xff);
\r
3351 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
\r
3352 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
\r
3354 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
\r
3357 png_composite_16(v, r, a, background->red);
\r
3358 *dp = (png_byte)((v >> 8) & 0xff);
\r
3359 *(dp + 1) = (png_byte)(v & 0xff);
\r
3360 png_composite_16(v, g, a, background->green);
\r
3361 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
\r
3362 *(dp + 3) = (png_byte)(v & 0xff);
\r
3363 png_composite_16(v, b, a, background->blue);
\r
3364 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
\r
3365 *(dp + 5) = (png_byte)(v & 0xff);
\r
3374 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
\r
3376 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
\r
3377 row_info->channels--;
\r
3378 row_info->pixel_depth = (png_byte)(row_info->channels *
\r
3379 row_info->bit_depth);
\r
3380 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
\r
3386 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
3387 /* Gamma correct the image, avoiding the alpha channel. Make sure
\r
3388 * you do this after you deal with the transparency issue on grayscale
\r
3389 * or RGB images. If your bit depth is 8, use gamma_table, if it
\r
3390 * is 16, use gamma_16_table and gamma_shift. Build these with
\r
3391 * build_gamma_table().
\r
3393 void /* PRIVATE */
\r
3394 png_do_gamma(png_row_infop row_info, png_bytep row,
\r
3395 png_bytep gamma_table, png_uint_16pp gamma_16_table,
\r
3400 png_uint_32 row_width=row_info->width;
\r
3402 png_debug(1, "in png_do_gamma\n");
\r
3404 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
3405 row != NULL && row_info != NULL &&
\r
3407 ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
\r
3408 (row_info->bit_depth == 16 && gamma_16_table != NULL)))
\r
3410 switch (row_info->color_type)
\r
3412 case PNG_COLOR_TYPE_RGB:
\r
3414 if (row_info->bit_depth == 8)
\r
3417 for (i = 0; i < row_width; i++)
\r
3419 *sp = gamma_table[*sp];
\r
3421 *sp = gamma_table[*sp];
\r
3423 *sp = gamma_table[*sp];
\r
3427 else /* if (row_info->bit_depth == 16) */
\r
3430 for (i = 0; i < row_width; i++)
\r
3434 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
\r
3435 *sp = (png_byte)((v >> 8) & 0xff);
\r
3436 *(sp + 1) = (png_byte)(v & 0xff);
\r
3438 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
\r
3439 *sp = (png_byte)((v >> 8) & 0xff);
\r
3440 *(sp + 1) = (png_byte)(v & 0xff);
\r
3442 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
\r
3443 *sp = (png_byte)((v >> 8) & 0xff);
\r
3444 *(sp + 1) = (png_byte)(v & 0xff);
\r
3450 case PNG_COLOR_TYPE_RGB_ALPHA:
\r
3452 if (row_info->bit_depth == 8)
\r
3455 for (i = 0; i < row_width; i++)
\r
3457 *sp = gamma_table[*sp];
\r
3459 *sp = gamma_table[*sp];
\r
3461 *sp = gamma_table[*sp];
\r
3466 else /* if (row_info->bit_depth == 16) */
\r
3469 for (i = 0; i < row_width; i++)
\r
3471 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
\r
3472 *sp = (png_byte)((v >> 8) & 0xff);
\r
3473 *(sp + 1) = (png_byte)(v & 0xff);
\r
3475 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
\r
3476 *sp = (png_byte)((v >> 8) & 0xff);
\r
3477 *(sp + 1) = (png_byte)(v & 0xff);
\r
3479 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
\r
3480 *sp = (png_byte)((v >> 8) & 0xff);
\r
3481 *(sp + 1) = (png_byte)(v & 0xff);
\r
3487 case PNG_COLOR_TYPE_GRAY_ALPHA:
\r
3489 if (row_info->bit_depth == 8)
\r
3492 for (i = 0; i < row_width; i++)
\r
3494 *sp = gamma_table[*sp];
\r
3498 else /* if (row_info->bit_depth == 16) */
\r
3501 for (i = 0; i < row_width; i++)
\r
3503 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
\r
3504 *sp = (png_byte)((v >> 8) & 0xff);
\r
3505 *(sp + 1) = (png_byte)(v & 0xff);
\r
3511 case PNG_COLOR_TYPE_GRAY:
\r
3513 if (row_info->bit_depth == 2)
\r
3516 for (i = 0; i < row_width; i += 4)
\r
3518 int a = *sp & 0xc0;
\r
3519 int b = *sp & 0x30;
\r
3520 int c = *sp & 0x0c;
\r
3521 int d = *sp & 0x03;
\r
3524 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
\r
3525 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
\r
3526 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
\r
3527 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
\r
3531 if (row_info->bit_depth == 4)
\r
3534 for (i = 0; i < row_width; i += 2)
\r
3536 int msb = *sp & 0xf0;
\r
3537 int lsb = *sp & 0x0f;
\r
3539 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
\r
3540 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
\r
3544 else if (row_info->bit_depth == 8)
\r
3547 for (i = 0; i < row_width; i++)
\r
3549 *sp = gamma_table[*sp];
\r
3553 else if (row_info->bit_depth == 16)
\r
3556 for (i = 0; i < row_width; i++)
\r
3558 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
\r
3559 *sp = (png_byte)((v >> 8) & 0xff);
\r
3560 *(sp + 1) = (png_byte)(v & 0xff);
\r
3571 #if defined(PNG_READ_EXPAND_SUPPORTED)
\r
3572 /* Expands a palette row to an RGB or RGBA row depending
\r
3573 * upon whether you supply trans and num_trans.
\r
3575 void /* PRIVATE */
\r
3576 png_do_expand_palette(png_row_infop row_info, png_bytep row,
\r
3577 png_colorp palette, png_bytep trans, int num_trans)
\r
3582 png_uint_32 row_width=row_info->width;
\r
3584 png_debug(1, "in png_do_expand_palette\n");
\r
3586 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
3587 row != NULL && row_info != NULL &&
\r
3589 row_info->color_type == PNG_COLOR_TYPE_PALETTE)
\r
3591 if (row_info->bit_depth < 8)
\r
3593 switch (row_info->bit_depth)
\r
3597 sp = row + (png_size_t)((row_width - 1) >> 3);
\r
3598 dp = row + (png_size_t)row_width - 1;
\r
3599 shift = 7 - (int)((row_width + 7) & 0x07);
\r
3600 for (i = 0; i < row_width; i++)
\r
3602 if ((*sp >> shift) & 0x01)
\r
3620 sp = row + (png_size_t)((row_width - 1) >> 2);
\r
3621 dp = row + (png_size_t)row_width - 1;
\r
3622 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
\r
3623 for (i = 0; i < row_width; i++)
\r
3625 value = (*sp >> shift) & 0x03;
\r
3626 *dp = (png_byte)value;
\r
3641 sp = row + (png_size_t)((row_width - 1) >> 1);
\r
3642 dp = row + (png_size_t)row_width - 1;
\r
3643 shift = (int)((row_width & 0x01) << 2);
\r
3644 for (i = 0; i < row_width; i++)
\r
3646 value = (*sp >> shift) & 0x0f;
\r
3647 *dp = (png_byte)value;
\r
3661 row_info->bit_depth = 8;
\r
3662 row_info->pixel_depth = 8;
\r
3663 row_info->rowbytes = row_width;
\r
3665 switch (row_info->bit_depth)
\r
3669 if (trans != NULL)
\r
3671 sp = row + (png_size_t)row_width - 1;
\r
3672 dp = row + (png_size_t)(row_width << 2) - 1;
\r
3674 for (i = 0; i < row_width; i++)
\r
3676 if ((int)(*sp) >= num_trans)
\r
3679 *dp-- = trans[*sp];
\r
3680 *dp-- = palette[*sp].blue;
\r
3681 *dp-- = palette[*sp].green;
\r
3682 *dp-- = palette[*sp].red;
\r
3685 row_info->bit_depth = 8;
\r
3686 row_info->pixel_depth = 32;
\r
3687 row_info->rowbytes = row_width * 4;
\r
3688 row_info->color_type = 6;
\r
3689 row_info->channels = 4;
\r
3693 sp = row + (png_size_t)row_width - 1;
\r
3694 dp = row + (png_size_t)(row_width * 3) - 1;
\r
3696 for (i = 0; i < row_width; i++)
\r
3698 *dp-- = palette[*sp].blue;
\r
3699 *dp-- = palette[*sp].green;
\r
3700 *dp-- = palette[*sp].red;
\r
3703 row_info->bit_depth = 8;
\r
3704 row_info->pixel_depth = 24;
\r
3705 row_info->rowbytes = row_width * 3;
\r
3706 row_info->color_type = 2;
\r
3707 row_info->channels = 3;
\r
3715 /* If the bit depth < 8, it is expanded to 8. Also, if the already
\r
3716 * expanded transparency value is supplied, an alpha channel is built.
\r
3718 void /* PRIVATE */
\r
3719 png_do_expand(png_row_infop row_info, png_bytep row,
\r
3720 png_color_16p trans_value)
\r
3725 png_uint_32 row_width=row_info->width;
\r
3727 png_debug(1, "in png_do_expand\n");
\r
3728 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
3729 if (row != NULL && row_info != NULL)
\r
3732 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
\r
3734 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
\r
3736 if (row_info->bit_depth < 8)
\r
3738 switch (row_info->bit_depth)
\r
3742 gray = (png_uint_16)((gray&0x01)*0xff);
\r
3743 sp = row + (png_size_t)((row_width - 1) >> 3);
\r
3744 dp = row + (png_size_t)row_width - 1;
\r
3745 shift = 7 - (int)((row_width + 7) & 0x07);
\r
3746 for (i = 0; i < row_width; i++)
\r
3748 if ((*sp >> shift) & 0x01)
\r
3766 gray = (png_uint_16)((gray&0x03)*0x55);
\r
3767 sp = row + (png_size_t)((row_width - 1) >> 2);
\r
3768 dp = row + (png_size_t)row_width - 1;
\r
3769 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
\r
3770 for (i = 0; i < row_width; i++)
\r
3772 value = (*sp >> shift) & 0x03;
\r
3773 *dp = (png_byte)(value | (value << 2) | (value << 4) |
\r
3789 gray = (png_uint_16)((gray&0x0f)*0x11);
\r
3790 sp = row + (png_size_t)((row_width - 1) >> 1);
\r
3791 dp = row + (png_size_t)row_width - 1;
\r
3792 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
\r
3793 for (i = 0; i < row_width; i++)
\r
3795 value = (*sp >> shift) & 0x0f;
\r
3796 *dp = (png_byte)(value | (value << 4));
\r
3810 row_info->bit_depth = 8;
\r
3811 row_info->pixel_depth = 8;
\r
3812 row_info->rowbytes = row_width;
\r
3815 if (trans_value != NULL)
\r
3817 if (row_info->bit_depth == 8)
\r
3819 gray = gray & 0xff;
\r
3820 sp = row + (png_size_t)row_width - 1;
\r
3821 dp = row + (png_size_t)(row_width << 1) - 1;
\r
3822 for (i = 0; i < row_width; i++)
\r
3831 else if (row_info->bit_depth == 16)
\r
3833 png_byte gray_high = (gray >> 8) & 0xff;
\r
3834 png_byte gray_low = gray & 0xff;
\r
3835 sp = row + row_info->rowbytes - 1;
\r
3836 dp = row + (row_info->rowbytes << 1) - 1;
\r
3837 for (i = 0; i < row_width; i++)
\r
3839 if (*(sp - 1) == gray_high && *(sp) == gray_low)
\r
3853 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
\r
3854 row_info->channels = 2;
\r
3855 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
\r
3856 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
\r
3860 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
\r
3862 if (row_info->bit_depth == 8)
\r
3864 png_byte red = trans_value->red & 0xff;
\r
3865 png_byte green = trans_value->green & 0xff;
\r
3866 png_byte blue = trans_value->blue & 0xff;
\r
3867 sp = row + (png_size_t)row_info->rowbytes - 1;
\r
3868 dp = row + (png_size_t)(row_width << 2) - 1;
\r
3869 for (i = 0; i < row_width; i++)
\r
3871 if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
\r
3880 else if (row_info->bit_depth == 16)
\r
3882 png_byte red_high = (trans_value->red >> 8) & 0xff;
\r
3883 png_byte green_high = (trans_value->green >> 8) & 0xff;
\r
3884 png_byte blue_high = (trans_value->blue >> 8) & 0xff;
\r
3885 png_byte red_low = trans_value->red & 0xff;
\r
3886 png_byte green_low = trans_value->green & 0xff;
\r
3887 png_byte blue_low = trans_value->blue & 0xff;
\r
3888 sp = row + row_info->rowbytes - 1;
\r
3889 dp = row + (png_size_t)(row_width << 3) - 1;
\r
3890 for (i = 0; i < row_width; i++)
\r
3892 if (*(sp - 5) == red_high &&
\r
3893 *(sp - 4) == red_low &&
\r
3894 *(sp - 3) == green_high &&
\r
3895 *(sp - 2) == green_low &&
\r
3896 *(sp - 1) == blue_high &&
\r
3897 *(sp ) == blue_low)
\r
3915 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
\r
3916 row_info->channels = 4;
\r
3917 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
\r
3918 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
\r
3924 #if defined(PNG_READ_DITHER_SUPPORTED)
\r
3925 void /* PRIVATE */
\r
3926 png_do_dither(png_row_infop row_info, png_bytep row,
\r
3927 png_bytep palette_lookup, png_bytep dither_lookup)
\r
3931 png_uint_32 row_width=row_info->width;
\r
3933 png_debug(1, "in png_do_dither\n");
\r
3934 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
3935 if (row != NULL && row_info != NULL)
\r
3938 if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
\r
3939 palette_lookup && row_info->bit_depth == 8)
\r
3944 for (i = 0; i < row_width; i++)
\r
3950 /* this looks real messy, but the compiler will reduce
\r
3951 it down to a reasonable formula. For example, with
\r
3952 5 bits per color, we get:
\r
3953 p = (((r >> 3) & 0x1f) << 10) |
\r
3954 (((g >> 3) & 0x1f) << 5) |
\r
3955 ((b >> 3) & 0x1f);
\r
3957 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
\r
3958 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
\r
3959 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
\r
3960 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
\r
3961 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
\r
3962 (PNG_DITHER_BLUE_BITS)) |
\r
3963 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
\r
3964 ((1 << PNG_DITHER_BLUE_BITS) - 1));
\r
3966 *dp++ = palette_lookup[p];
\r
3968 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
\r
3969 row_info->channels = 1;
\r
3970 row_info->pixel_depth = row_info->bit_depth;
\r
3971 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
\r
3973 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
\r
3974 palette_lookup != NULL && row_info->bit_depth == 8)
\r
3979 for (i = 0; i < row_width; i++)
\r
3986 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
\r
3987 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
\r
3988 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
\r
3989 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
\r
3990 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
\r
3991 (PNG_DITHER_BLUE_BITS)) |
\r
3992 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
\r
3993 ((1 << PNG_DITHER_BLUE_BITS) - 1));
\r
3995 *dp++ = palette_lookup[p];
\r
3997 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
\r
3998 row_info->channels = 1;
\r
3999 row_info->pixel_depth = row_info->bit_depth;
\r
4000 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
\r
4002 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
\r
4003 dither_lookup && row_info->bit_depth == 8)
\r
4006 for (i = 0; i < row_width; i++, sp++)
\r
4008 *sp = dither_lookup[*sp];
\r
4015 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
4016 #if defined(PNG_READ_GAMMA_SUPPORTED)
\r
4017 static PNG_CONST int png_gamma_shift[] =
\r
4018 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
\r
4020 /* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
\r
4021 * tables, we don't make a full table if we are reducing to 8-bit in
\r
4022 * the future. Note also how the gamma_16 tables are segmented so that
\r
4023 * we don't need to allocate > 64K chunks for a full 16-bit table.
\r
4025 void /* PRIVATE */
\r
4026 png_build_gamma_table(png_structp png_ptr)
\r
4028 png_debug(1, "in png_build_gamma_table\n");
\r
4030 if (png_ptr->bit_depth <= 8)
\r
4035 if (png_ptr->screen_gamma > .000001)
\r
4036 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
\r
4040 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
\r
4041 (png_uint_32)256);
\r
4043 for (i = 0; i < 256; i++)
\r
4045 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
\r
4049 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
\r
4050 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
\r
4051 if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
\r
4054 g = 1.0 / (png_ptr->gamma);
\r
4056 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
\r
4057 (png_uint_32)256);
\r
4059 for (i = 0; i < 256; i++)
\r
4061 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
\r
4066 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
\r
4067 (png_uint_32)256);
\r
4069 if (png_ptr->screen_gamma > 0.000001)
\r
4070 g = 1.0 / png_ptr->screen_gamma;
\r
4072 g = png_ptr->gamma; /* probably doing rgb_to_gray */
\r
4074 for (i = 0; i < 256; i++)
\r
4076 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
\r
4081 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
\r
4086 int i, j, shift, num;
\r
4090 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
\r
4092 sig_bit = (int)png_ptr->sig_bit.red;
\r
4093 if ((int)png_ptr->sig_bit.green > sig_bit)
\r
4094 sig_bit = png_ptr->sig_bit.green;
\r
4095 if ((int)png_ptr->sig_bit.blue > sig_bit)
\r
4096 sig_bit = png_ptr->sig_bit.blue;
\r
4100 sig_bit = (int)png_ptr->sig_bit.gray;
\r
4104 shift = 16 - sig_bit;
\r
4108 if (png_ptr->transformations & PNG_16_TO_8)
\r
4110 if (shift < (16 - PNG_MAX_GAMMA_8))
\r
4111 shift = (16 - PNG_MAX_GAMMA_8);
\r
4119 png_ptr->gamma_shift = (png_byte)shift;
\r
4121 num = (1 << (8 - shift));
\r
4123 if (png_ptr->screen_gamma > .000001)
\r
4124 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
\r
4128 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
\r
4129 (png_uint_32)(num * png_sizeof(png_uint_16p)));
\r
4131 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
\r
4134 png_uint_32 last, max;
\r
4136 for (i = 0; i < num; i++)
\r
4138 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
\r
4139 (png_uint_32)(256 * png_sizeof(png_uint_16)));
\r
4144 for (i = 0; i < 256; i++)
\r
4146 fout = ((double)i + 0.5) / 256.0;
\r
4147 fin = pow(fout, g);
\r
4148 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
\r
4149 while (last <= max)
\r
4151 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
\r
4152 [(int)(last >> (8 - shift))] = (png_uint_16)(
\r
4153 (png_uint_16)i | ((png_uint_16)i << 8));
\r
4157 while (last < ((png_uint_32)num << 8))
\r
4159 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
\r
4160 [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
\r
4166 for (i = 0; i < num; i++)
\r
4168 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
\r
4169 (png_uint_32)(256 * png_sizeof(png_uint_16)));
\r
4171 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
\r
4172 for (j = 0; j < 256; j++)
\r
4174 png_ptr->gamma_16_table[i][j] =
\r
4175 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
\r
4176 65535.0, g) * 65535.0 + .5);
\r
4181 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
\r
4182 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
\r
4183 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
\r
4186 g = 1.0 / (png_ptr->gamma);
\r
4188 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
\r
4189 (png_uint_32)(num * png_sizeof(png_uint_16p )));
\r
4191 for (i = 0; i < num; i++)
\r
4193 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
\r
4194 (png_uint_32)(256 * png_sizeof(png_uint_16)));
\r
4196 ig = (((png_uint_32)i *
\r
4197 (png_uint_32)png_gamma_shift[shift]) >> 4);
\r
4198 for (j = 0; j < 256; j++)
\r
4200 png_ptr->gamma_16_to_1[i][j] =
\r
4201 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
\r
4202 65535.0, g) * 65535.0 + .5);
\r
4206 if (png_ptr->screen_gamma > 0.000001)
\r
4207 g = 1.0 / png_ptr->screen_gamma;
\r
4209 g = png_ptr->gamma; /* probably doing rgb_to_gray */
\r
4211 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
\r
4212 (png_uint_32)(num * png_sizeof(png_uint_16p)));
\r
4214 for (i = 0; i < num; i++)
\r
4216 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
\r
4217 (png_uint_32)(256 * png_sizeof(png_uint_16)));
\r
4219 ig = (((png_uint_32)i *
\r
4220 (png_uint_32)png_gamma_shift[shift]) >> 4);
\r
4221 for (j = 0; j < 256; j++)
\r
4223 png_ptr->gamma_16_from_1[i][j] =
\r
4224 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
\r
4225 65535.0, g) * 65535.0 + .5);
\r
4229 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
\r
4233 /* To do: install integer version of png_build_gamma_table here */
\r
4236 #if defined(PNG_MNG_FEATURES_SUPPORTED)
\r
4237 /* undoes intrapixel differencing */
\r
4238 void /* PRIVATE */
\r
4239 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
\r
4241 png_debug(1, "in png_do_read_intrapixel\n");
\r
4243 #if defined(PNG_USELESS_TESTS_SUPPORTED)
\r
4244 row != NULL && row_info != NULL &&
\r
4246 (row_info->color_type & PNG_COLOR_MASK_COLOR))
\r
4248 int bytes_per_pixel;
\r
4249 png_uint_32 row_width = row_info->width;
\r
4250 if (row_info->bit_depth == 8)
\r
4255 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
\r
4256 bytes_per_pixel = 3;
\r
4257 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
\r
4258 bytes_per_pixel = 4;
\r
4262 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
\r
4264 *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
\r
4265 *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
\r
4268 else if (row_info->bit_depth == 16)
\r
4273 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
\r
4274 bytes_per_pixel = 6;
\r
4275 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
\r
4276 bytes_per_pixel = 8;
\r
4280 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
\r
4282 png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
\r
4283 png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
\r
4284 png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
\r
4285 png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL);
\r
4286 png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL);
\r
4287 *(rp ) = (png_byte)((red >> 8) & 0xff);
\r
4288 *(rp+1) = (png_byte)(red & 0xff);
\r
4289 *(rp+4) = (png_byte)((blue >> 8) & 0xff);
\r
4290 *(rp+5) = (png_byte)(blue & 0xff);
\r
4295 #endif /* PNG_MNG_FEATURES_SUPPORTED */
\r
4296 #endif /* PNG_READ_SUPPORTED */
\r