Support unrar64.dll
[xy_vsfilter.git] / src / libpng / pngrtran.c
blob1c7f474b416c87c4744cdf7dfe04478defc481ca
2 /* pngrtran.c - transforms the data in a row for PNG readers
4 * Last changed in libpng 1.2.37 [June 4, 2009]
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2009 Glenn Randers-Pehrson
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
10 * This file contains functions optionally called by an application
11 * in order to tell libpng how to handle data when reading a PNG.
12 * Transformations that are used in both reading and writing are
13 * in pngtrans.c.
16 #define PNG_INTERNAL
17 #include "png.h"
18 #if defined(PNG_READ_SUPPORTED)
20 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
21 void PNGAPI
22 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
24 png_debug(1, "in png_set_crc_action");
25 /* Tell libpng how we react to CRC errors in critical chunks */
26 if (png_ptr == NULL)
27 return;
28 switch (crit_action)
30 case PNG_CRC_NO_CHANGE: /* Leave setting as is */
31 break;
33 case PNG_CRC_WARN_USE: /* Warn/use data */
34 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
35 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
36 break;
38 case PNG_CRC_QUIET_USE: /* Quiet/use data */
39 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
40 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
41 PNG_FLAG_CRC_CRITICAL_IGNORE;
42 break;
44 case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */
45 png_warning(png_ptr,
46 "Can't discard critical data on CRC error.");
47 case PNG_CRC_ERROR_QUIT: /* Error/quit */
49 case PNG_CRC_DEFAULT:
50 default:
51 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
52 break;
55 switch (ancil_action)
57 case PNG_CRC_NO_CHANGE: /* Leave setting as is */
58 break;
60 case PNG_CRC_WARN_USE: /* Warn/use data */
61 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
62 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
63 break;
65 case PNG_CRC_QUIET_USE: /* Quiet/use data */
66 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
67 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
68 PNG_FLAG_CRC_ANCILLARY_NOWARN;
69 break;
71 case PNG_CRC_ERROR_QUIT: /* Error/quit */
72 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
73 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
74 break;
76 case PNG_CRC_WARN_DISCARD: /* Warn/discard data */
78 case PNG_CRC_DEFAULT:
79 default:
80 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
81 break;
85 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
86 defined(PNG_FLOATING_POINT_SUPPORTED)
87 /* Handle alpha and tRNS via a background color */
88 void PNGAPI
89 png_set_background(png_structp png_ptr,
90 png_color_16p background_color, int background_gamma_code,
91 int need_expand, double background_gamma)
93 png_debug(1, "in png_set_background");
94 if (png_ptr == NULL)
95 return;
96 if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
98 png_warning(png_ptr, "Application must supply a known background gamma");
99 return;
102 png_ptr->transformations |= PNG_BACKGROUND;
103 png_memcpy(&(png_ptr->background), background_color,
104 png_sizeof(png_color_16));
105 png_ptr->background_gamma = (float)background_gamma;
106 png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
107 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
109 #endif
111 #if defined(PNG_READ_16_TO_8_SUPPORTED)
112 /* Strip 16 bit depth files to 8 bit depth */
113 void PNGAPI
114 png_set_strip_16(png_structp png_ptr)
116 png_debug(1, "in png_set_strip_16");
117 if (png_ptr == NULL)
118 return;
119 png_ptr->transformations |= PNG_16_TO_8;
121 #endif
123 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
124 void PNGAPI
125 png_set_strip_alpha(png_structp png_ptr)
127 png_debug(1, "in png_set_strip_alpha");
128 if (png_ptr == NULL)
129 return;
130 png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
132 #endif
134 #if defined(PNG_READ_DITHER_SUPPORTED)
135 /* Dither file to 8 bit. Supply a palette, the current number
136 * of elements in the palette, the maximum number of elements
137 * allowed, and a histogram if possible. If the current number
138 * of colors is greater then the maximum number, the palette will be
139 * modified to fit in the maximum number. "full_dither" indicates
140 * whether we need a dithering cube set up for RGB images, or if we
141 * simply are reducing the number of colors in a paletted image.
144 typedef struct png_dsort_struct
146 struct png_dsort_struct FAR * next;
147 png_byte left;
148 png_byte right;
149 } png_dsort;
150 typedef png_dsort FAR * png_dsortp;
151 typedef png_dsort FAR * FAR * png_dsortpp;
153 void PNGAPI
154 png_set_dither(png_structp png_ptr, png_colorp palette,
155 int num_palette, int maximum_colors, png_uint_16p histogram,
156 int full_dither)
158 png_debug(1, "in png_set_dither");
159 if (png_ptr == NULL)
160 return;
161 png_ptr->transformations |= PNG_DITHER;
163 if (!full_dither)
165 int i;
167 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
168 (png_uint_32)(num_palette * png_sizeof(png_byte)));
169 for (i = 0; i < num_palette; i++)
170 png_ptr->dither_index[i] = (png_byte)i;
173 if (num_palette > maximum_colors)
175 if (histogram != NULL)
177 /* This is easy enough, just throw out the least used colors.
178 * Perhaps not the best solution, but good enough.
181 int i;
183 /* Initialize an array to sort colors */
184 png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
185 (png_uint_32)(num_palette * png_sizeof(png_byte)));
187 /* Initialize the dither_sort array */
188 for (i = 0; i < num_palette; i++)
189 png_ptr->dither_sort[i] = (png_byte)i;
191 /* Find the least used palette entries by starting a
192 * bubble sort, and running it until we have sorted
193 * out enough colors. Note that we don't care about
194 * sorting all the colors, just finding which are
195 * least used.
198 for (i = num_palette - 1; i >= maximum_colors; i--)
200 int done; /* To stop early if the list is pre-sorted */
201 int j;
203 done = 1;
204 for (j = 0; j < i; j++)
206 if (histogram[png_ptr->dither_sort[j]]
207 < histogram[png_ptr->dither_sort[j + 1]])
209 png_byte t;
211 t = png_ptr->dither_sort[j];
212 png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
213 png_ptr->dither_sort[j + 1] = t;
214 done = 0;
217 if (done)
218 break;
221 /* Swap the palette around, and set up a table, if necessary */
222 if (full_dither)
224 int j = num_palette;
226 /* Put all the useful colors within the max, but don't
227 * move the others.
229 for (i = 0; i < maximum_colors; i++)
231 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
234 j--;
235 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
236 palette[i] = palette[j];
240 else
242 int j = num_palette;
244 /* Move all the used colors inside the max limit, and
245 * develop a translation table.
247 for (i = 0; i < maximum_colors; i++)
249 /* Only move the colors we need to */
250 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
252 png_color tmp_color;
255 j--;
256 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
258 tmp_color = palette[j];
259 palette[j] = palette[i];
260 palette[i] = tmp_color;
261 /* Indicate where the color went */
262 png_ptr->dither_index[j] = (png_byte)i;
263 png_ptr->dither_index[i] = (png_byte)j;
267 /* Find closest color for those colors we are not using */
268 for (i = 0; i < num_palette; i++)
270 if ((int)png_ptr->dither_index[i] >= maximum_colors)
272 int min_d, k, min_k, d_index;
274 /* Find the closest color to one we threw out */
275 d_index = png_ptr->dither_index[i];
276 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
277 for (k = 1, min_k = 0; k < maximum_colors; k++)
279 int d;
281 d = PNG_COLOR_DIST(palette[d_index], palette[k]);
283 if (d < min_d)
285 min_d = d;
286 min_k = k;
289 /* Point to closest color */
290 png_ptr->dither_index[i] = (png_byte)min_k;
294 png_free(png_ptr, png_ptr->dither_sort);
295 png_ptr->dither_sort = NULL;
297 else
299 /* This is much harder to do simply (and quickly). Perhaps
300 * we need to go through a median cut routine, but those
301 * don't always behave themselves with only a few colors
302 * as input. So we will just find the closest two colors,
303 * and throw out one of them (chosen somewhat randomly).
304 * [We don't understand this at all, so if someone wants to
305 * work on improving it, be our guest - AED, GRP]
307 int i;
308 int max_d;
309 int num_new_palette;
310 png_dsortp t;
311 png_dsortpp hash;
313 t = NULL;
315 /* Initialize palette index arrays */
316 png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
317 (png_uint_32)(num_palette * png_sizeof(png_byte)));
318 png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
319 (png_uint_32)(num_palette * png_sizeof(png_byte)));
321 /* Initialize the sort array */
322 for (i = 0; i < num_palette; i++)
324 png_ptr->index_to_palette[i] = (png_byte)i;
325 png_ptr->palette_to_index[i] = (png_byte)i;
328 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
329 png_sizeof(png_dsortp)));
330 png_memset(hash, 0, 769 * png_sizeof(png_dsortp));
332 num_new_palette = num_palette;
334 /* Initial wild guess at how far apart the farthest pixel
335 * pair we will be eliminating will be. Larger
336 * numbers mean more areas will be allocated, Smaller
337 * numbers run the risk of not saving enough data, and
338 * having to do this all over again.
340 * I have not done extensive checking on this number.
342 max_d = 96;
344 while (num_new_palette > maximum_colors)
346 for (i = 0; i < num_new_palette - 1; i++)
348 int j;
350 for (j = i + 1; j < num_new_palette; j++)
352 int d;
354 d = PNG_COLOR_DIST(palette[i], palette[j]);
356 if (d <= max_d)
359 t = (png_dsortp)png_malloc_warn(png_ptr,
360 (png_uint_32)(png_sizeof(png_dsort)));
361 if (t == NULL)
362 break;
363 t->next = hash[d];
364 t->left = (png_byte)i;
365 t->right = (png_byte)j;
366 hash[d] = t;
369 if (t == NULL)
370 break;
373 if (t != NULL)
374 for (i = 0; i <= max_d; i++)
376 if (hash[i] != NULL)
378 png_dsortp p;
380 for (p = hash[i]; p; p = p->next)
382 if ((int)png_ptr->index_to_palette[p->left]
383 < num_new_palette &&
384 (int)png_ptr->index_to_palette[p->right]
385 < num_new_palette)
387 int j, next_j;
389 if (num_new_palette & 0x01)
391 j = p->left;
392 next_j = p->right;
394 else
396 j = p->right;
397 next_j = p->left;
400 num_new_palette--;
401 palette[png_ptr->index_to_palette[j]]
402 = palette[num_new_palette];
403 if (!full_dither)
405 int k;
407 for (k = 0; k < num_palette; k++)
409 if (png_ptr->dither_index[k] ==
410 png_ptr->index_to_palette[j])
411 png_ptr->dither_index[k] =
412 png_ptr->index_to_palette[next_j];
413 if ((int)png_ptr->dither_index[k] ==
414 num_new_palette)
415 png_ptr->dither_index[k] =
416 png_ptr->index_to_palette[j];
420 png_ptr->index_to_palette[png_ptr->palette_to_index
421 [num_new_palette]] = png_ptr->index_to_palette[j];
422 png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
423 = png_ptr->palette_to_index[num_new_palette];
425 png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
426 png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
428 if (num_new_palette <= maximum_colors)
429 break;
431 if (num_new_palette <= maximum_colors)
432 break;
436 for (i = 0; i < 769; i++)
438 if (hash[i] != NULL)
440 png_dsortp p = hash[i];
441 while (p)
443 t = p->next;
444 png_free(png_ptr, p);
445 p = t;
448 hash[i] = 0;
450 max_d += 96;
452 png_free(png_ptr, hash);
453 png_free(png_ptr, png_ptr->palette_to_index);
454 png_free(png_ptr, png_ptr->index_to_palette);
455 png_ptr->palette_to_index = NULL;
456 png_ptr->index_to_palette = NULL;
458 num_palette = maximum_colors;
460 if (png_ptr->palette == NULL)
462 png_ptr->palette = palette;
464 png_ptr->num_palette = (png_uint_16)num_palette;
466 if (full_dither)
468 int i;
469 png_bytep distance;
470 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
471 PNG_DITHER_BLUE_BITS;
472 int num_red = (1 << PNG_DITHER_RED_BITS);
473 int num_green = (1 << PNG_DITHER_GREEN_BITS);
474 int num_blue = (1 << PNG_DITHER_BLUE_BITS);
475 png_size_t num_entries = ((png_size_t)1 << total_bits);
476 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
477 (png_uint_32)(num_entries * png_sizeof(png_byte)));
478 png_memset(png_ptr->palette_lookup, 0, num_entries *
479 png_sizeof(png_byte));
481 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
482 png_sizeof(png_byte)));
484 png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
486 for (i = 0; i < num_palette; i++)
488 int ir, ig, ib;
489 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
490 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
491 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
493 for (ir = 0; ir < num_red; ir++)
495 /* int dr = abs(ir - r); */
496 int dr = ((ir > r) ? ir - r : r - ir);
497 int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
499 for (ig = 0; ig < num_green; ig++)
501 /* int dg = abs(ig - g); */
502 int dg = ((ig > g) ? ig - g : g - ig);
503 int dt = dr + dg;
504 int dm = ((dr > dg) ? dr : dg);
505 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
507 for (ib = 0; ib < num_blue; ib++)
509 int d_index = index_g | ib;
510 /* int db = abs(ib - b); */
511 int db = ((ib > b) ? ib - b : b - ib);
512 int dmax = ((dm > db) ? dm : db);
513 int d = dmax + dt + db;
515 if (d < (int)distance[d_index])
517 distance[d_index] = (png_byte)d;
518 png_ptr->palette_lookup[d_index] = (png_byte)i;
525 png_free(png_ptr, distance);
528 #endif
530 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
531 /* Transform the image from the file_gamma to the screen_gamma. We
532 * only do transformations on images where the file_gamma and screen_gamma
533 * are not close reciprocals, otherwise it slows things down slightly, and
534 * also needlessly introduces small errors.
536 * We will turn off gamma transformation later if no semitransparent entries
537 * are present in the tRNS array for palette images. We can't do it here
538 * because we don't necessarily have the tRNS chunk yet.
540 void PNGAPI
541 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
543 png_debug(1, "in png_set_gamma");
544 if (png_ptr == NULL)
545 return;
546 if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
547 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
548 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
549 png_ptr->transformations |= PNG_GAMMA;
550 png_ptr->gamma = (float)file_gamma;
551 png_ptr->screen_gamma = (float)scrn_gamma;
553 #endif
555 #if defined(PNG_READ_EXPAND_SUPPORTED)
556 /* Expand paletted images to RGB, expand grayscale images of
557 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
558 * to alpha channels.
560 void PNGAPI
561 png_set_expand(png_structp png_ptr)
563 png_debug(1, "in png_set_expand");
564 if (png_ptr == NULL)
565 return;
566 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
567 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
570 /* GRR 19990627: the following three functions currently are identical
571 * to png_set_expand(). However, it is entirely reasonable that someone
572 * might wish to expand an indexed image to RGB but *not* expand a single,
573 * fully transparent palette entry to a full alpha channel--perhaps instead
574 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
575 * the transparent color with a particular RGB value, or drop tRNS entirely.
576 * IOW, a future version of the library may make the transformations flag
577 * a bit more fine-grained, with separate bits for each of these three
578 * functions.
580 * More to the point, these functions make it obvious what libpng will be
581 * doing, whereas "expand" can (and does) mean any number of things.
583 * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified
584 * to expand only the sample depth but not to expand the tRNS to alpha.
587 /* Expand paletted images to RGB. */
588 void PNGAPI
589 png_set_palette_to_rgb(png_structp png_ptr)
591 png_debug(1, "in png_set_palette_to_rgb");
592 if (png_ptr == NULL)
593 return;
594 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
595 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
598 #if !defined(PNG_1_0_X)
599 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
600 void PNGAPI
601 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
603 png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
604 if (png_ptr == NULL)
605 return;
606 png_ptr->transformations |= PNG_EXPAND;
607 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
609 #endif
611 #if defined(PNG_1_0_X) || defined(PNG_1_2_X)
612 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
613 /* Deprecated as of libpng-1.2.9 */
614 void PNGAPI
615 png_set_gray_1_2_4_to_8(png_structp png_ptr)
617 png_debug(1, "in png_set_gray_1_2_4_to_8");
618 if (png_ptr == NULL)
619 return;
620 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
622 #endif
625 /* Expand tRNS chunks to alpha channels. */
626 void PNGAPI
627 png_set_tRNS_to_alpha(png_structp png_ptr)
629 png_debug(1, "in png_set_tRNS_to_alpha");
630 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
631 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
633 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
635 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
636 void PNGAPI
637 png_set_gray_to_rgb(png_structp png_ptr)
639 png_debug(1, "in png_set_gray_to_rgb");
640 png_ptr->transformations |= PNG_GRAY_TO_RGB;
641 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
643 #endif
645 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
646 #if defined(PNG_FLOATING_POINT_SUPPORTED)
647 /* Convert a RGB image to a grayscale of the same width. This allows us,
648 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
651 void PNGAPI
652 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
653 double green)
655 int red_fixed = (int)((float)red*100000.0 + 0.5);
656 int green_fixed = (int)((float)green*100000.0 + 0.5);
657 if (png_ptr == NULL)
658 return;
659 png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
661 #endif
663 void PNGAPI
664 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
665 png_fixed_point red, png_fixed_point green)
667 png_debug(1, "in png_set_rgb_to_gray");
668 if (png_ptr == NULL)
669 return;
670 switch(error_action)
672 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
673 break;
675 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
676 break;
678 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
680 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
681 #if defined(PNG_READ_EXPAND_SUPPORTED)
682 png_ptr->transformations |= PNG_EXPAND;
683 #else
685 png_warning(png_ptr,
686 "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
687 png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
689 #endif
691 png_uint_16 red_int, green_int;
692 if (red < 0 || green < 0)
694 red_int = 6968; /* .212671 * 32768 + .5 */
695 green_int = 23434; /* .715160 * 32768 + .5 */
697 else if (red + green < 100000L)
699 red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
700 green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
702 else
704 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
705 red_int = 6968;
706 green_int = 23434;
708 png_ptr->rgb_to_gray_red_coeff = red_int;
709 png_ptr->rgb_to_gray_green_coeff = green_int;
710 png_ptr->rgb_to_gray_blue_coeff =
711 (png_uint_16)(32768 - red_int - green_int);
714 #endif
716 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
717 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
718 defined(PNG_LEGACY_SUPPORTED)
719 void PNGAPI
720 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
721 read_user_transform_fn)
723 png_debug(1, "in png_set_read_user_transform_fn");
724 if (png_ptr == NULL)
725 return;
726 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
727 png_ptr->transformations |= PNG_USER_TRANSFORM;
728 png_ptr->read_user_transform_fn = read_user_transform_fn;
729 #endif
730 #ifdef PNG_LEGACY_SUPPORTED
731 if (read_user_transform_fn)
732 png_warning(png_ptr,
733 "This version of libpng does not support user transforms");
734 #endif
736 #endif
738 /* Initialize everything needed for the read. This includes modifying
739 * the palette.
741 void /* PRIVATE */
742 png_init_read_transformations(png_structp png_ptr)
744 png_debug(1, "in png_init_read_transformations");
745 #if defined(PNG_USELESS_TESTS_SUPPORTED)
746 if (png_ptr != NULL)
747 #endif
749 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
750 || defined(PNG_READ_GAMMA_SUPPORTED)
751 int color_type = png_ptr->color_type;
752 #endif
754 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
756 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
757 /* Detect gray background and attempt to enable optimization
758 * for gray --> RGB case
760 * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
761 * RGB_ALPHA (in which case need_expand is superfluous anyway), the
762 * background color might actually be gray yet not be flagged as such.
763 * This is not a problem for the current code, which uses
764 * PNG_BACKGROUND_IS_GRAY only to decide when to do the
765 * png_do_gray_to_rgb() transformation.
767 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
768 !(color_type & PNG_COLOR_MASK_COLOR))
770 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
771 } else if ((png_ptr->transformations & PNG_BACKGROUND) &&
772 !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
773 (png_ptr->transformations & PNG_GRAY_TO_RGB) &&
774 png_ptr->background.red == png_ptr->background.green &&
775 png_ptr->background.red == png_ptr->background.blue)
777 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
778 png_ptr->background.gray = png_ptr->background.red;
780 #endif
782 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
783 (png_ptr->transformations & PNG_EXPAND))
785 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
787 /* Expand background and tRNS chunks */
788 switch (png_ptr->bit_depth)
790 case 1:
791 png_ptr->background.gray *= (png_uint_16)0xff;
792 png_ptr->background.red = png_ptr->background.green
793 = png_ptr->background.blue = png_ptr->background.gray;
794 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
796 png_ptr->trans_values.gray *= (png_uint_16)0xff;
797 png_ptr->trans_values.red = png_ptr->trans_values.green
798 = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
800 break;
802 case 2:
803 png_ptr->background.gray *= (png_uint_16)0x55;
804 png_ptr->background.red = png_ptr->background.green
805 = png_ptr->background.blue = png_ptr->background.gray;
806 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
808 png_ptr->trans_values.gray *= (png_uint_16)0x55;
809 png_ptr->trans_values.red = png_ptr->trans_values.green
810 = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
812 break;
814 case 4:
815 png_ptr->background.gray *= (png_uint_16)0x11;
816 png_ptr->background.red = png_ptr->background.green
817 = png_ptr->background.blue = png_ptr->background.gray;
818 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
820 png_ptr->trans_values.gray *= (png_uint_16)0x11;
821 png_ptr->trans_values.red = png_ptr->trans_values.green
822 = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
824 break;
826 case 8:
828 case 16:
829 png_ptr->background.red = png_ptr->background.green
830 = png_ptr->background.blue = png_ptr->background.gray;
831 break;
834 else if (color_type == PNG_COLOR_TYPE_PALETTE)
836 png_ptr->background.red =
837 png_ptr->palette[png_ptr->background.index].red;
838 png_ptr->background.green =
839 png_ptr->palette[png_ptr->background.index].green;
840 png_ptr->background.blue =
841 png_ptr->palette[png_ptr->background.index].blue;
843 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
844 if (png_ptr->transformations & PNG_INVERT_ALPHA)
846 #if defined(PNG_READ_EXPAND_SUPPORTED)
847 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
848 #endif
850 /* Invert the alpha channel (in tRNS) unless the pixels are
851 * going to be expanded, in which case leave it for later
853 int i, istop;
854 istop=(int)png_ptr->num_trans;
855 for (i=0; i<istop; i++)
856 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
859 #endif
863 #endif
865 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
866 png_ptr->background_1 = png_ptr->background;
867 #endif
868 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
870 if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
871 && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
872 < PNG_GAMMA_THRESHOLD))
874 int i, k;
875 k=0;
876 for (i=0; i<png_ptr->num_trans; i++)
878 if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
879 k=1; /* Partial transparency is present */
881 if (k == 0)
882 png_ptr->transformations &= ~PNG_GAMMA;
885 if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) &&
886 png_ptr->gamma != 0.0)
888 png_build_gamma_table(png_ptr);
889 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
890 if (png_ptr->transformations & PNG_BACKGROUND)
892 if (color_type == PNG_COLOR_TYPE_PALETTE)
894 /* Could skip if no transparency */
895 png_color back, back_1;
896 png_colorp palette = png_ptr->palette;
897 int num_palette = png_ptr->num_palette;
898 int i;
899 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
901 back.red = png_ptr->gamma_table[png_ptr->background.red];
902 back.green = png_ptr->gamma_table[png_ptr->background.green];
903 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
905 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
906 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
907 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
909 else
911 double g, gs;
913 switch (png_ptr->background_gamma_type)
915 case PNG_BACKGROUND_GAMMA_SCREEN:
916 g = (png_ptr->screen_gamma);
917 gs = 1.0;
918 break;
920 case PNG_BACKGROUND_GAMMA_FILE:
921 g = 1.0 / (png_ptr->gamma);
922 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
923 break;
925 case PNG_BACKGROUND_GAMMA_UNIQUE:
926 g = 1.0 / (png_ptr->background_gamma);
927 gs = 1.0 / (png_ptr->background_gamma *
928 png_ptr->screen_gamma);
929 break;
930 default:
931 g = 1.0; /* back_1 */
932 gs = 1.0; /* back */
935 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
937 back.red = (png_byte)png_ptr->background.red;
938 back.green = (png_byte)png_ptr->background.green;
939 back.blue = (png_byte)png_ptr->background.blue;
941 else
943 back.red = (png_byte)(pow(
944 (double)png_ptr->background.red/255, gs) * 255.0 + .5);
945 back.green = (png_byte)(pow(
946 (double)png_ptr->background.green/255, gs) * 255.0 + .5);
947 back.blue = (png_byte)(pow(
948 (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
951 back_1.red = (png_byte)(pow(
952 (double)png_ptr->background.red/255, g) * 255.0 + .5);
953 back_1.green = (png_byte)(pow(
954 (double)png_ptr->background.green/255, g) * 255.0 + .5);
955 back_1.blue = (png_byte)(pow(
956 (double)png_ptr->background.blue/255, g) * 255.0 + .5);
958 for (i = 0; i < num_palette; i++)
960 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
962 if (png_ptr->trans[i] == 0)
964 palette[i] = back;
966 else /* if (png_ptr->trans[i] != 0xff) */
968 png_byte v, w;
970 v = png_ptr->gamma_to_1[palette[i].red];
971 png_composite(w, v, png_ptr->trans[i], back_1.red);
972 palette[i].red = png_ptr->gamma_from_1[w];
974 v = png_ptr->gamma_to_1[palette[i].green];
975 png_composite(w, v, png_ptr->trans[i], back_1.green);
976 palette[i].green = png_ptr->gamma_from_1[w];
978 v = png_ptr->gamma_to_1[palette[i].blue];
979 png_composite(w, v, png_ptr->trans[i], back_1.blue);
980 palette[i].blue = png_ptr->gamma_from_1[w];
983 else
985 palette[i].red = png_ptr->gamma_table[palette[i].red];
986 palette[i].green = png_ptr->gamma_table[palette[i].green];
987 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
990 /* Prevent the transformations being done again, and make sure
991 * that the now spurious alpha channel is stripped - the code
992 * has just reduced background composition and gamma correction
993 * to a simple alpha channel strip.
995 png_ptr->transformations &= ~PNG_BACKGROUND;
996 png_ptr->transformations &= ~PNG_GAMMA;
997 png_ptr->transformations |= PNG_STRIP_ALPHA;
999 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
1000 else
1001 /* color_type != PNG_COLOR_TYPE_PALETTE */
1003 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
1004 double g = 1.0;
1005 double gs = 1.0;
1007 switch (png_ptr->background_gamma_type)
1009 case PNG_BACKGROUND_GAMMA_SCREEN:
1010 g = (png_ptr->screen_gamma);
1011 gs = 1.0;
1012 break;
1014 case PNG_BACKGROUND_GAMMA_FILE:
1015 g = 1.0 / (png_ptr->gamma);
1016 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
1017 break;
1019 case PNG_BACKGROUND_GAMMA_UNIQUE:
1020 g = 1.0 / (png_ptr->background_gamma);
1021 gs = 1.0 / (png_ptr->background_gamma *
1022 png_ptr->screen_gamma);
1023 break;
1026 png_ptr->background_1.gray = (png_uint_16)(pow(
1027 (double)png_ptr->background.gray / m, g) * m + .5);
1028 png_ptr->background.gray = (png_uint_16)(pow(
1029 (double)png_ptr->background.gray / m, gs) * m + .5);
1031 if ((png_ptr->background.red != png_ptr->background.green) ||
1032 (png_ptr->background.red != png_ptr->background.blue) ||
1033 (png_ptr->background.red != png_ptr->background.gray))
1035 /* RGB or RGBA with color background */
1036 png_ptr->background_1.red = (png_uint_16)(pow(
1037 (double)png_ptr->background.red / m, g) * m + .5);
1038 png_ptr->background_1.green = (png_uint_16)(pow(
1039 (double)png_ptr->background.green / m, g) * m + .5);
1040 png_ptr->background_1.blue = (png_uint_16)(pow(
1041 (double)png_ptr->background.blue / m, g) * m + .5);
1042 png_ptr->background.red = (png_uint_16)(pow(
1043 (double)png_ptr->background.red / m, gs) * m + .5);
1044 png_ptr->background.green = (png_uint_16)(pow(
1045 (double)png_ptr->background.green / m, gs) * m + .5);
1046 png_ptr->background.blue = (png_uint_16)(pow(
1047 (double)png_ptr->background.blue / m, gs) * m + .5);
1049 else
1051 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
1052 png_ptr->background_1.red = png_ptr->background_1.green
1053 = png_ptr->background_1.blue = png_ptr->background_1.gray;
1054 png_ptr->background.red = png_ptr->background.green
1055 = png_ptr->background.blue = png_ptr->background.gray;
1059 else
1060 /* Transformation does not include PNG_BACKGROUND */
1061 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
1062 if (color_type == PNG_COLOR_TYPE_PALETTE)
1064 png_colorp palette = png_ptr->palette;
1065 int num_palette = png_ptr->num_palette;
1066 int i;
1068 for (i = 0; i < num_palette; i++)
1070 palette[i].red = png_ptr->gamma_table[palette[i].red];
1071 palette[i].green = png_ptr->gamma_table[palette[i].green];
1072 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1075 /* Done the gamma correction. */
1076 png_ptr->transformations &= ~PNG_GAMMA;
1079 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1080 else
1081 #endif
1082 #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
1083 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1084 /* No GAMMA transformation */
1085 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1086 (color_type == PNG_COLOR_TYPE_PALETTE))
1088 int i;
1089 int istop = (int)png_ptr->num_trans;
1090 png_color back;
1091 png_colorp palette = png_ptr->palette;
1093 back.red = (png_byte)png_ptr->background.red;
1094 back.green = (png_byte)png_ptr->background.green;
1095 back.blue = (png_byte)png_ptr->background.blue;
1097 for (i = 0; i < istop; i++)
1099 if (png_ptr->trans[i] == 0)
1101 palette[i] = back;
1103 else if (png_ptr->trans[i] != 0xff)
1105 /* The png_composite() macro is defined in png.h */
1106 png_composite(palette[i].red, palette[i].red,
1107 png_ptr->trans[i], back.red);
1108 png_composite(palette[i].green, palette[i].green,
1109 png_ptr->trans[i], back.green);
1110 png_composite(palette[i].blue, palette[i].blue,
1111 png_ptr->trans[i], back.blue);
1115 /* Handled alpha, still need to strip the channel. */
1116 png_ptr->transformations &= ~PNG_BACKGROUND;
1117 png_ptr->transformations |= PNG_STRIP_ALPHA;
1119 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
1121 #if defined(PNG_READ_SHIFT_SUPPORTED)
1122 if ((png_ptr->transformations & PNG_SHIFT) &&
1123 (color_type == PNG_COLOR_TYPE_PALETTE))
1125 png_uint_16 i;
1126 png_uint_16 istop = png_ptr->num_palette;
1127 int sr = 8 - png_ptr->sig_bit.red;
1128 int sg = 8 - png_ptr->sig_bit.green;
1129 int sb = 8 - png_ptr->sig_bit.blue;
1131 if (sr < 0 || sr > 8)
1132 sr = 0;
1133 if (sg < 0 || sg > 8)
1134 sg = 0;
1135 if (sb < 0 || sb > 8)
1136 sb = 0;
1137 for (i = 0; i < istop; i++)
1139 png_ptr->palette[i].red >>= sr;
1140 png_ptr->palette[i].green >>= sg;
1141 png_ptr->palette[i].blue >>= sb;
1144 #endif /* PNG_READ_SHIFT_SUPPORTED */
1146 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1147 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1148 if (png_ptr)
1149 return;
1150 #endif
1153 /* Modify the info structure to reflect the transformations. The
1154 * info should be updated so a PNG file could be written with it,
1155 * assuming the transformations result in valid PNG data.
1157 void /* PRIVATE */
1158 png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
1160 png_debug(1, "in png_read_transform_info");
1161 #if defined(PNG_READ_EXPAND_SUPPORTED)
1162 if (png_ptr->transformations & PNG_EXPAND)
1164 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1166 if (png_ptr->num_trans &&
1167 (png_ptr->transformations & PNG_EXPAND_tRNS))
1168 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1169 else
1170 info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1171 info_ptr->bit_depth = 8;
1172 info_ptr->num_trans = 0;
1174 else
1176 if (png_ptr->num_trans)
1178 if (png_ptr->transformations & PNG_EXPAND_tRNS)
1179 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1180 #if 0 /* Removed from libpng-1.2.27 */
1181 else
1182 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1183 #endif
1185 if (info_ptr->bit_depth < 8)
1186 info_ptr->bit_depth = 8;
1187 info_ptr->num_trans = 0;
1190 #endif
1192 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1193 if (png_ptr->transformations & PNG_BACKGROUND)
1195 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1196 info_ptr->num_trans = 0;
1197 info_ptr->background = png_ptr->background;
1199 #endif
1201 #if defined(PNG_READ_GAMMA_SUPPORTED)
1202 if (png_ptr->transformations & PNG_GAMMA)
1204 #ifdef PNG_FLOATING_POINT_SUPPORTED
1205 info_ptr->gamma = png_ptr->gamma;
1206 #endif
1207 #ifdef PNG_FIXED_POINT_SUPPORTED
1208 info_ptr->int_gamma = png_ptr->int_gamma;
1209 #endif
1211 #endif
1213 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1214 if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
1215 info_ptr->bit_depth = 8;
1216 #endif
1218 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1219 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1220 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1221 #endif
1223 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1224 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1225 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1226 #endif
1228 #if defined(PNG_READ_DITHER_SUPPORTED)
1229 if (png_ptr->transformations & PNG_DITHER)
1231 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1232 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1233 png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1235 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1238 #endif
1240 #if defined(PNG_READ_PACK_SUPPORTED)
1241 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
1242 info_ptr->bit_depth = 8;
1243 #endif
1245 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1246 info_ptr->channels = 1;
1247 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1248 info_ptr->channels = 3;
1249 else
1250 info_ptr->channels = 1;
1252 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1253 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1254 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1255 #endif
1257 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1258 info_ptr->channels++;
1260 #if defined(PNG_READ_FILLER_SUPPORTED)
1261 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
1262 if ((png_ptr->transformations & PNG_FILLER) &&
1263 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1264 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1266 info_ptr->channels++;
1267 /* If adding a true alpha channel not just filler */
1268 #if !defined(PNG_1_0_X)
1269 if (png_ptr->transformations & PNG_ADD_ALPHA)
1270 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1271 #endif
1273 #endif
1275 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1276 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1277 if (png_ptr->transformations & PNG_USER_TRANSFORM)
1279 if (info_ptr->bit_depth < png_ptr->user_transform_depth)
1280 info_ptr->bit_depth = png_ptr->user_transform_depth;
1281 if (info_ptr->channels < png_ptr->user_transform_channels)
1282 info_ptr->channels = png_ptr->user_transform_channels;
1284 #endif
1286 info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1287 info_ptr->bit_depth);
1289 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
1291 #if !defined(PNG_READ_EXPAND_SUPPORTED)
1292 if (png_ptr)
1293 return;
1294 #endif
1297 /* Transform the row. The order of transformations is significant,
1298 * and is very touchy. If you add a transformation, take care to
1299 * decide how it fits in with the other transformations here.
1301 void /* PRIVATE */
1302 png_do_read_transformations(png_structp png_ptr)
1304 png_debug(1, "in png_do_read_transformations");
1305 if (png_ptr->row_buf == NULL)
1307 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1308 char msg[50];
1310 png_snprintf2(msg, 50,
1311 "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number,
1312 png_ptr->pass);
1313 png_error(png_ptr, msg);
1314 #else
1315 png_error(png_ptr, "NULL row buffer");
1316 #endif
1318 #ifdef PNG_WARN_UNINITIALIZED_ROW
1319 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
1320 /* Application has failed to call either png_read_start_image()
1321 * or png_read_update_info() after setting transforms that expand
1322 * pixels. This check added to libpng-1.2.19
1324 #if (PNG_WARN_UNINITIALIZED_ROW==1)
1325 png_error(png_ptr, "Uninitialized row");
1326 #else
1327 png_warning(png_ptr, "Uninitialized row");
1328 #endif
1329 #endif
1331 #if defined(PNG_READ_EXPAND_SUPPORTED)
1332 if (png_ptr->transformations & PNG_EXPAND)
1334 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1336 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1337 png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1339 else
1341 if (png_ptr->num_trans &&
1342 (png_ptr->transformations & PNG_EXPAND_tRNS))
1343 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1344 &(png_ptr->trans_values));
1345 else
1346 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1347 NULL);
1350 #endif
1352 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1353 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1354 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1355 PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
1356 #endif
1358 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1359 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1361 int rgb_error =
1362 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1363 if (rgb_error)
1365 png_ptr->rgb_to_gray_status=1;
1366 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
1367 PNG_RGB_TO_GRAY_WARN)
1368 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1369 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
1370 PNG_RGB_TO_GRAY_ERR)
1371 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1374 #endif
1376 /* From Andreas Dilger e-mail to png-implement, 26 March 1998:
1378 * In most cases, the "simple transparency" should be done prior to doing
1379 * gray-to-RGB, or you will have to test 3x as many bytes to check if a
1380 * pixel is transparent. You would also need to make sure that the
1381 * transparency information is upgraded to RGB.
1383 * To summarize, the current flow is:
1384 * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1385 * with background "in place" if transparent,
1386 * convert to RGB if necessary
1387 * - Gray + alpha -> composite with gray background and remove alpha bytes,
1388 * convert to RGB if necessary
1390 * To support RGB backgrounds for gray images we need:
1391 * - Gray + simple transparency -> convert to RGB + simple transparency,
1392 * compare 3 or 6 bytes and composite with
1393 * background "in place" if transparent
1394 * (3x compare/pixel compared to doing
1395 * composite with gray bkgrnd)
1396 * - Gray + alpha -> convert to RGB + alpha, composite with background and
1397 * remove alpha bytes (3x float
1398 * operations/pixel compared with composite
1399 * on gray background)
1401 * Greg's change will do this. The reason it wasn't done before is for
1402 * performance, as this increases the per-pixel operations. If we would check
1403 * in advance if the background was gray or RGB, and position the gray-to-RGB
1404 * transform appropriately, then it would save a lot of work/time.
1407 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1408 /* If gray -> RGB, do so now only if background is non-gray; else do later
1409 * for performance reasons
1411 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1412 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1413 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1414 #endif
1416 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1417 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1418 ((png_ptr->num_trans != 0 ) ||
1419 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
1420 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1421 &(png_ptr->trans_values), &(png_ptr->background)
1422 #if defined(PNG_READ_GAMMA_SUPPORTED)
1423 , &(png_ptr->background_1),
1424 png_ptr->gamma_table, png_ptr->gamma_from_1,
1425 png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1426 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1427 png_ptr->gamma_shift
1428 #endif
1430 #endif
1432 #if defined(PNG_READ_GAMMA_SUPPORTED)
1433 if ((png_ptr->transformations & PNG_GAMMA) &&
1434 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1435 !((png_ptr->transformations & PNG_BACKGROUND) &&
1436 ((png_ptr->num_trans != 0) ||
1437 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1438 #endif
1439 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
1440 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1441 png_ptr->gamma_table, png_ptr->gamma_16_table,
1442 png_ptr->gamma_shift);
1443 #endif
1445 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1446 if (png_ptr->transformations & PNG_16_TO_8)
1447 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
1448 #endif
1450 #if defined(PNG_READ_DITHER_SUPPORTED)
1451 if (png_ptr->transformations & PNG_DITHER)
1453 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1454 png_ptr->palette_lookup, png_ptr->dither_index);
1455 if (png_ptr->row_info.rowbytes == (png_uint_32)0)
1456 png_error(png_ptr, "png_do_dither returned rowbytes=0");
1458 #endif
1460 #if defined(PNG_READ_INVERT_SUPPORTED)
1461 if (png_ptr->transformations & PNG_INVERT_MONO)
1462 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
1463 #endif
1465 #if defined(PNG_READ_SHIFT_SUPPORTED)
1466 if (png_ptr->transformations & PNG_SHIFT)
1467 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1468 &(png_ptr->shift));
1469 #endif
1471 #if defined(PNG_READ_PACK_SUPPORTED)
1472 if (png_ptr->transformations & PNG_PACK)
1473 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
1474 #endif
1476 #if defined(PNG_READ_BGR_SUPPORTED)
1477 if (png_ptr->transformations & PNG_BGR)
1478 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
1479 #endif
1481 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
1482 if (png_ptr->transformations & PNG_PACKSWAP)
1483 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1484 #endif
1486 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1487 /* If gray -> RGB, do so now only if we did not do so above */
1488 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1489 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1490 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1491 #endif
1493 #if defined(PNG_READ_FILLER_SUPPORTED)
1494 if (png_ptr->transformations & PNG_FILLER)
1495 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1496 (png_uint_32)png_ptr->filler, png_ptr->flags);
1497 #endif
1499 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1500 if (png_ptr->transformations & PNG_INVERT_ALPHA)
1501 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1502 #endif
1504 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1505 if (png_ptr->transformations & PNG_SWAP_ALPHA)
1506 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1507 #endif
1509 #if defined(PNG_READ_SWAP_SUPPORTED)
1510 if (png_ptr->transformations & PNG_SWAP_BYTES)
1511 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1512 #endif
1514 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1515 if (png_ptr->transformations & PNG_USER_TRANSFORM)
1517 if (png_ptr->read_user_transform_fn != NULL)
1518 (*(png_ptr->read_user_transform_fn)) /* User read transform function */
1519 (png_ptr, /* png_ptr */
1520 &(png_ptr->row_info), /* row_info: */
1521 /* png_uint_32 width; width of row */
1522 /* png_uint_32 rowbytes; number of bytes in row */
1523 /* png_byte color_type; color type of pixels */
1524 /* png_byte bit_depth; bit depth of samples */
1525 /* png_byte channels; number of channels (1-4) */
1526 /* png_byte pixel_depth; bits per pixel (depth*channels) */
1527 png_ptr->row_buf + 1); /* start of pixel data for row */
1528 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
1529 if (png_ptr->user_transform_depth)
1530 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1531 if (png_ptr->user_transform_channels)
1532 png_ptr->row_info.channels = png_ptr->user_transform_channels;
1533 #endif
1534 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1535 png_ptr->row_info.channels);
1536 png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
1537 png_ptr->row_info.width);
1539 #endif
1543 #if defined(PNG_READ_PACK_SUPPORTED)
1544 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1545 * without changing the actual values. Thus, if you had a row with
1546 * a bit depth of 1, you would end up with bytes that only contained
1547 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1548 * png_do_shift() after this.
1550 void /* PRIVATE */
1551 png_do_unpack(png_row_infop row_info, png_bytep row)
1553 png_debug(1, "in png_do_unpack");
1554 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1555 if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1556 #else
1557 if (row_info->bit_depth < 8)
1558 #endif
1560 png_uint_32 i;
1561 png_uint_32 row_width=row_info->width;
1563 switch (row_info->bit_depth)
1565 case 1:
1567 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1568 png_bytep dp = row + (png_size_t)row_width - 1;
1569 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
1570 for (i = 0; i < row_width; i++)
1572 *dp = (png_byte)((*sp >> shift) & 0x01);
1573 if (shift == 7)
1575 shift = 0;
1576 sp--;
1578 else
1579 shift++;
1581 dp--;
1583 break;
1586 case 2:
1589 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1590 png_bytep dp = row + (png_size_t)row_width - 1;
1591 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
1592 for (i = 0; i < row_width; i++)
1594 *dp = (png_byte)((*sp >> shift) & 0x03);
1595 if (shift == 6)
1597 shift = 0;
1598 sp--;
1600 else
1601 shift += 2;
1603 dp--;
1605 break;
1608 case 4:
1610 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1611 png_bytep dp = row + (png_size_t)row_width - 1;
1612 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
1613 for (i = 0; i < row_width; i++)
1615 *dp = (png_byte)((*sp >> shift) & 0x0f);
1616 if (shift == 4)
1618 shift = 0;
1619 sp--;
1621 else
1622 shift = 4;
1624 dp--;
1626 break;
1629 row_info->bit_depth = 8;
1630 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1631 row_info->rowbytes = row_width * row_info->channels;
1634 #endif
1636 #if defined(PNG_READ_SHIFT_SUPPORTED)
1637 /* Reverse the effects of png_do_shift. This routine merely shifts the
1638 * pixels back to their significant bits values. Thus, if you have
1639 * a row of bit depth 8, but only 5 are significant, this will shift
1640 * the values back to 0 through 31.
1642 void /* PRIVATE */
1643 png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
1645 png_debug(1, "in png_do_unshift");
1646 if (
1647 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1648 row != NULL && row_info != NULL && sig_bits != NULL &&
1649 #endif
1650 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
1652 int shift[4];
1653 int channels = 0;
1654 int c;
1655 png_uint_16 value = 0;
1656 png_uint_32 row_width = row_info->width;
1658 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1660 shift[channels++] = row_info->bit_depth - sig_bits->red;
1661 shift[channels++] = row_info->bit_depth - sig_bits->green;
1662 shift[channels++] = row_info->bit_depth - sig_bits->blue;
1664 else
1666 shift[channels++] = row_info->bit_depth - sig_bits->gray;
1668 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1670 shift[channels++] = row_info->bit_depth - sig_bits->alpha;
1673 for (c = 0; c < channels; c++)
1675 if (shift[c] <= 0)
1676 shift[c] = 0;
1677 else
1678 value = 1;
1681 if (!value)
1682 return;
1684 switch (row_info->bit_depth)
1686 case 2:
1688 png_bytep bp;
1689 png_uint_32 i;
1690 png_uint_32 istop = row_info->rowbytes;
1692 for (bp = row, i = 0; i < istop; i++)
1694 *bp >>= 1;
1695 *bp++ &= 0x55;
1697 break;
1700 case 4:
1702 png_bytep bp = row;
1703 png_uint_32 i;
1704 png_uint_32 istop = row_info->rowbytes;
1705 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1706 (png_byte)((int)0xf >> shift[0]));
1708 for (i = 0; i < istop; i++)
1710 *bp >>= shift[0];
1711 *bp++ &= mask;
1713 break;
1716 case 8:
1718 png_bytep bp = row;
1719 png_uint_32 i;
1720 png_uint_32 istop = row_width * channels;
1722 for (i = 0; i < istop; i++)
1724 *bp++ >>= shift[i%channels];
1726 break;
1729 case 16:
1731 png_bytep bp = row;
1732 png_uint_32 i;
1733 png_uint_32 istop = channels * row_width;
1735 for (i = 0; i < istop; i++)
1737 value = (png_uint_16)((*bp << 8) + *(bp + 1));
1738 value >>= shift[i%channels];
1739 *bp++ = (png_byte)(value >> 8);
1740 *bp++ = (png_byte)(value & 0xff);
1742 break;
1747 #endif
1749 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1750 /* Chop rows of bit depth 16 down to 8 */
1751 void /* PRIVATE */
1752 png_do_chop(png_row_infop row_info, png_bytep row)
1754 png_debug(1, "in png_do_chop");
1755 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1756 if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1757 #else
1758 if (row_info->bit_depth == 16)
1759 #endif
1761 png_bytep sp = row;
1762 png_bytep dp = row;
1763 png_uint_32 i;
1764 png_uint_32 istop = row_info->width * row_info->channels;
1766 for (i = 0; i<istop; i++, sp += 2, dp++)
1768 #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
1769 /* This does a more accurate scaling of the 16-bit color
1770 * value, rather than a simple low-byte truncation.
1772 * What the ideal calculation should be:
1773 * *dp = (((((png_uint_32)(*sp) << 8) |
1774 * (png_uint_32)(*(sp + 1))) * 255 + 127)
1775 * / (png_uint_32)65535L;
1777 * GRR: no, I think this is what it really should be:
1778 * *dp = (((((png_uint_32)(*sp) << 8) |
1779 * (png_uint_32)(*(sp + 1))) + 128L)
1780 * / (png_uint_32)257L;
1782 * GRR: here's the exact calculation with shifts:
1783 * temp = (((png_uint_32)(*sp) << 8) |
1784 * (png_uint_32)(*(sp + 1))) + 128L;
1785 * *dp = (temp - (temp >> 8)) >> 8;
1787 * Approximate calculation with shift/add instead of multiply/divide:
1788 * *dp = ((((png_uint_32)(*sp) << 8) |
1789 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1791 * What we actually do to avoid extra shifting and conversion:
1794 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1795 #else
1796 /* Simply discard the low order byte */
1797 *dp = *sp;
1798 #endif
1800 row_info->bit_depth = 8;
1801 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1802 row_info->rowbytes = row_info->width * row_info->channels;
1805 #endif
1807 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1808 void /* PRIVATE */
1809 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1811 png_debug(1, "in png_do_read_swap_alpha");
1812 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1813 if (row != NULL && row_info != NULL)
1814 #endif
1816 png_uint_32 row_width = row_info->width;
1817 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1819 /* This converts from RGBA to ARGB */
1820 if (row_info->bit_depth == 8)
1822 png_bytep sp = row + row_info->rowbytes;
1823 png_bytep dp = sp;
1824 png_byte save;
1825 png_uint_32 i;
1827 for (i = 0; i < row_width; i++)
1829 save = *(--sp);
1830 *(--dp) = *(--sp);
1831 *(--dp) = *(--sp);
1832 *(--dp) = *(--sp);
1833 *(--dp) = save;
1836 /* This converts from RRGGBBAA to AARRGGBB */
1837 else
1839 png_bytep sp = row + row_info->rowbytes;
1840 png_bytep dp = sp;
1841 png_byte save[2];
1842 png_uint_32 i;
1844 for (i = 0; i < row_width; i++)
1846 save[0] = *(--sp);
1847 save[1] = *(--sp);
1848 *(--dp) = *(--sp);
1849 *(--dp) = *(--sp);
1850 *(--dp) = *(--sp);
1851 *(--dp) = *(--sp);
1852 *(--dp) = *(--sp);
1853 *(--dp) = *(--sp);
1854 *(--dp) = save[0];
1855 *(--dp) = save[1];
1859 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1861 /* This converts from GA to AG */
1862 if (row_info->bit_depth == 8)
1864 png_bytep sp = row + row_info->rowbytes;
1865 png_bytep dp = sp;
1866 png_byte save;
1867 png_uint_32 i;
1869 for (i = 0; i < row_width; i++)
1871 save = *(--sp);
1872 *(--dp) = *(--sp);
1873 *(--dp) = save;
1876 /* This converts from GGAA to AAGG */
1877 else
1879 png_bytep sp = row + row_info->rowbytes;
1880 png_bytep dp = sp;
1881 png_byte save[2];
1882 png_uint_32 i;
1884 for (i = 0; i < row_width; i++)
1886 save[0] = *(--sp);
1887 save[1] = *(--sp);
1888 *(--dp) = *(--sp);
1889 *(--dp) = *(--sp);
1890 *(--dp) = save[0];
1891 *(--dp) = save[1];
1897 #endif
1899 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1900 void /* PRIVATE */
1901 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1903 png_debug(1, "in png_do_read_invert_alpha");
1904 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1905 if (row != NULL && row_info != NULL)
1906 #endif
1908 png_uint_32 row_width = row_info->width;
1909 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1911 /* This inverts the alpha channel in RGBA */
1912 if (row_info->bit_depth == 8)
1914 png_bytep sp = row + row_info->rowbytes;
1915 png_bytep dp = sp;
1916 png_uint_32 i;
1918 for (i = 0; i < row_width; i++)
1920 *(--dp) = (png_byte)(255 - *(--sp));
1922 /* This does nothing:
1923 *(--dp) = *(--sp);
1924 *(--dp) = *(--sp);
1925 *(--dp) = *(--sp);
1926 We can replace it with:
1928 sp-=3;
1929 dp=sp;
1932 /* This inverts the alpha channel in RRGGBBAA */
1933 else
1935 png_bytep sp = row + row_info->rowbytes;
1936 png_bytep dp = sp;
1937 png_uint_32 i;
1939 for (i = 0; i < row_width; i++)
1941 *(--dp) = (png_byte)(255 - *(--sp));
1942 *(--dp) = (png_byte)(255 - *(--sp));
1944 /* This does nothing:
1945 *(--dp) = *(--sp);
1946 *(--dp) = *(--sp);
1947 *(--dp) = *(--sp);
1948 *(--dp) = *(--sp);
1949 *(--dp) = *(--sp);
1950 *(--dp) = *(--sp);
1951 We can replace it with:
1953 sp-=6;
1954 dp=sp;
1958 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1960 /* This inverts the alpha channel in GA */
1961 if (row_info->bit_depth == 8)
1963 png_bytep sp = row + row_info->rowbytes;
1964 png_bytep dp = sp;
1965 png_uint_32 i;
1967 for (i = 0; i < row_width; i++)
1969 *(--dp) = (png_byte)(255 - *(--sp));
1970 *(--dp) = *(--sp);
1973 /* This inverts the alpha channel in GGAA */
1974 else
1976 png_bytep sp = row + row_info->rowbytes;
1977 png_bytep dp = sp;
1978 png_uint_32 i;
1980 for (i = 0; i < row_width; i++)
1982 *(--dp) = (png_byte)(255 - *(--sp));
1983 *(--dp) = (png_byte)(255 - *(--sp));
1985 *(--dp) = *(--sp);
1986 *(--dp) = *(--sp);
1988 sp-=2;
1989 dp=sp;
1995 #endif
1997 #if defined(PNG_READ_FILLER_SUPPORTED)
1998 /* Add filler channel if we have RGB color */
1999 void /* PRIVATE */
2000 png_do_read_filler(png_row_infop row_info, png_bytep row,
2001 png_uint_32 filler, png_uint_32 flags)
2003 png_uint_32 i;
2004 png_uint_32 row_width = row_info->width;
2006 png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
2007 png_byte lo_filler = (png_byte)(filler & 0xff);
2009 png_debug(1, "in png_do_read_filler");
2010 if (
2011 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2012 row != NULL && row_info != NULL &&
2013 #endif
2014 row_info->color_type == PNG_COLOR_TYPE_GRAY)
2016 if (row_info->bit_depth == 8)
2018 /* This changes the data from G to GX */
2019 if (flags & PNG_FLAG_FILLER_AFTER)
2021 png_bytep sp = row + (png_size_t)row_width;
2022 png_bytep dp = sp + (png_size_t)row_width;
2023 for (i = 1; i < row_width; i++)
2025 *(--dp) = lo_filler;
2026 *(--dp) = *(--sp);
2028 *(--dp) = lo_filler;
2029 row_info->channels = 2;
2030 row_info->pixel_depth = 16;
2031 row_info->rowbytes = row_width * 2;
2033 /* This changes the data from G to XG */
2034 else
2036 png_bytep sp = row + (png_size_t)row_width;
2037 png_bytep dp = sp + (png_size_t)row_width;
2038 for (i = 0; i < row_width; i++)
2040 *(--dp) = *(--sp);
2041 *(--dp) = lo_filler;
2043 row_info->channels = 2;
2044 row_info->pixel_depth = 16;
2045 row_info->rowbytes = row_width * 2;
2048 else if (row_info->bit_depth == 16)
2050 /* This changes the data from GG to GGXX */
2051 if (flags & PNG_FLAG_FILLER_AFTER)
2053 png_bytep sp = row + (png_size_t)row_width * 2;
2054 png_bytep dp = sp + (png_size_t)row_width * 2;
2055 for (i = 1; i < row_width; i++)
2057 *(--dp) = hi_filler;
2058 *(--dp) = lo_filler;
2059 *(--dp) = *(--sp);
2060 *(--dp) = *(--sp);
2062 *(--dp) = hi_filler;
2063 *(--dp) = lo_filler;
2064 row_info->channels = 2;
2065 row_info->pixel_depth = 32;
2066 row_info->rowbytes = row_width * 4;
2068 /* This changes the data from GG to XXGG */
2069 else
2071 png_bytep sp = row + (png_size_t)row_width * 2;
2072 png_bytep dp = sp + (png_size_t)row_width * 2;
2073 for (i = 0; i < row_width; i++)
2075 *(--dp) = *(--sp);
2076 *(--dp) = *(--sp);
2077 *(--dp) = hi_filler;
2078 *(--dp) = lo_filler;
2080 row_info->channels = 2;
2081 row_info->pixel_depth = 32;
2082 row_info->rowbytes = row_width * 4;
2085 } /* COLOR_TYPE == GRAY */
2086 else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2088 if (row_info->bit_depth == 8)
2090 /* This changes the data from RGB to RGBX */
2091 if (flags & PNG_FLAG_FILLER_AFTER)
2093 png_bytep sp = row + (png_size_t)row_width * 3;
2094 png_bytep dp = sp + (png_size_t)row_width;
2095 for (i = 1; i < row_width; i++)
2097 *(--dp) = lo_filler;
2098 *(--dp) = *(--sp);
2099 *(--dp) = *(--sp);
2100 *(--dp) = *(--sp);
2102 *(--dp) = lo_filler;
2103 row_info->channels = 4;
2104 row_info->pixel_depth = 32;
2105 row_info->rowbytes = row_width * 4;
2107 /* This changes the data from RGB to XRGB */
2108 else
2110 png_bytep sp = row + (png_size_t)row_width * 3;
2111 png_bytep dp = sp + (png_size_t)row_width;
2112 for (i = 0; i < row_width; i++)
2114 *(--dp) = *(--sp);
2115 *(--dp) = *(--sp);
2116 *(--dp) = *(--sp);
2117 *(--dp) = lo_filler;
2119 row_info->channels = 4;
2120 row_info->pixel_depth = 32;
2121 row_info->rowbytes = row_width * 4;
2124 else if (row_info->bit_depth == 16)
2126 /* This changes the data from RRGGBB to RRGGBBXX */
2127 if (flags & PNG_FLAG_FILLER_AFTER)
2129 png_bytep sp = row + (png_size_t)row_width * 6;
2130 png_bytep dp = sp + (png_size_t)row_width * 2;
2131 for (i = 1; i < row_width; i++)
2133 *(--dp) = hi_filler;
2134 *(--dp) = lo_filler;
2135 *(--dp) = *(--sp);
2136 *(--dp) = *(--sp);
2137 *(--dp) = *(--sp);
2138 *(--dp) = *(--sp);
2139 *(--dp) = *(--sp);
2140 *(--dp) = *(--sp);
2142 *(--dp) = hi_filler;
2143 *(--dp) = lo_filler;
2144 row_info->channels = 4;
2145 row_info->pixel_depth = 64;
2146 row_info->rowbytes = row_width * 8;
2148 /* This changes the data from RRGGBB to XXRRGGBB */
2149 else
2151 png_bytep sp = row + (png_size_t)row_width * 6;
2152 png_bytep dp = sp + (png_size_t)row_width * 2;
2153 for (i = 0; i < row_width; i++)
2155 *(--dp) = *(--sp);
2156 *(--dp) = *(--sp);
2157 *(--dp) = *(--sp);
2158 *(--dp) = *(--sp);
2159 *(--dp) = *(--sp);
2160 *(--dp) = *(--sp);
2161 *(--dp) = hi_filler;
2162 *(--dp) = lo_filler;
2164 row_info->channels = 4;
2165 row_info->pixel_depth = 64;
2166 row_info->rowbytes = row_width * 8;
2169 } /* COLOR_TYPE == RGB */
2171 #endif
2173 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2174 /* Expand grayscale files to RGB, with or without alpha */
2175 void /* PRIVATE */
2176 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
2178 png_uint_32 i;
2179 png_uint_32 row_width = row_info->width;
2181 png_debug(1, "in png_do_gray_to_rgb");
2182 if (row_info->bit_depth >= 8 &&
2183 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2184 row != NULL && row_info != NULL &&
2185 #endif
2186 !(row_info->color_type & PNG_COLOR_MASK_COLOR))
2188 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2190 if (row_info->bit_depth == 8)
2192 png_bytep sp = row + (png_size_t)row_width - 1;
2193 png_bytep dp = sp + (png_size_t)row_width * 2;
2194 for (i = 0; i < row_width; i++)
2196 *(dp--) = *sp;
2197 *(dp--) = *sp;
2198 *(dp--) = *(sp--);
2201 else
2203 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2204 png_bytep dp = sp + (png_size_t)row_width * 4;
2205 for (i = 0; i < row_width; i++)
2207 *(dp--) = *sp;
2208 *(dp--) = *(sp - 1);
2209 *(dp--) = *sp;
2210 *(dp--) = *(sp - 1);
2211 *(dp--) = *(sp--);
2212 *(dp--) = *(sp--);
2216 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2218 if (row_info->bit_depth == 8)
2220 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2221 png_bytep dp = sp + (png_size_t)row_width * 2;
2222 for (i = 0; i < row_width; i++)
2224 *(dp--) = *(sp--);
2225 *(dp--) = *sp;
2226 *(dp--) = *sp;
2227 *(dp--) = *(sp--);
2230 else
2232 png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2233 png_bytep dp = sp + (png_size_t)row_width * 4;
2234 for (i = 0; i < row_width; i++)
2236 *(dp--) = *(sp--);
2237 *(dp--) = *(sp--);
2238 *(dp--) = *sp;
2239 *(dp--) = *(sp - 1);
2240 *(dp--) = *sp;
2241 *(dp--) = *(sp - 1);
2242 *(dp--) = *(sp--);
2243 *(dp--) = *(sp--);
2247 row_info->channels += (png_byte)2;
2248 row_info->color_type |= PNG_COLOR_MASK_COLOR;
2249 row_info->pixel_depth = (png_byte)(row_info->channels *
2250 row_info->bit_depth);
2251 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2254 #endif
2256 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
2257 /* Reduce RGB files to grayscale, with or without alpha
2258 * using the equation given in Poynton's ColorFAQ at
2259 * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008)
2260 * New link:
2261 * <http://www.poynton.com/notes/colour_and_gamma/>
2262 * Charles Poynton poynton at poynton.com
2264 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2266 * We approximate this with
2268 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
2270 * which can be expressed with integers as
2272 * Y = (6969 * R + 23434 * G + 2365 * B)/32768
2274 * The calculation is to be done in a linear colorspace.
2276 * Other integer coefficents can be used via png_set_rgb_to_gray().
2278 int /* PRIVATE */
2279 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2282 png_uint_32 i;
2284 png_uint_32 row_width = row_info->width;
2285 int rgb_error = 0;
2287 png_debug(1, "in png_do_rgb_to_gray");
2288 if (
2289 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2290 row != NULL && row_info != NULL &&
2291 #endif
2292 (row_info->color_type & PNG_COLOR_MASK_COLOR))
2294 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2295 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2296 png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
2298 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2300 if (row_info->bit_depth == 8)
2302 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2303 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2305 png_bytep sp = row;
2306 png_bytep dp = row;
2308 for (i = 0; i < row_width; i++)
2310 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2311 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2312 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2313 if (red != green || red != blue)
2315 rgb_error |= 1;
2316 *(dp++) = png_ptr->gamma_from_1[
2317 (rc*red + gc*green + bc*blue)>>15];
2319 else
2320 *(dp++) = *(sp - 1);
2323 else
2324 #endif
2326 png_bytep sp = row;
2327 png_bytep dp = row;
2328 for (i = 0; i < row_width; i++)
2330 png_byte red = *(sp++);
2331 png_byte green = *(sp++);
2332 png_byte blue = *(sp++);
2333 if (red != green || red != blue)
2335 rgb_error |= 1;
2336 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
2338 else
2339 *(dp++) = *(sp - 1);
2344 else /* RGB bit_depth == 16 */
2346 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2347 if (png_ptr->gamma_16_to_1 != NULL &&
2348 png_ptr->gamma_16_from_1 != NULL)
2350 png_bytep sp = row;
2351 png_bytep dp = row;
2352 for (i = 0; i < row_width; i++)
2354 png_uint_16 red, green, blue, w;
2356 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2357 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2358 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2360 if (red == green && red == blue)
2361 w = red;
2362 else
2364 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2365 png_ptr->gamma_shift][red>>8];
2366 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2367 png_ptr->gamma_shift][green>>8];
2368 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2369 png_ptr->gamma_shift][blue>>8];
2370 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
2371 + bc*blue_1)>>15);
2372 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2373 png_ptr->gamma_shift][gray16 >> 8];
2374 rgb_error |= 1;
2377 *(dp++) = (png_byte)((w>>8) & 0xff);
2378 *(dp++) = (png_byte)(w & 0xff);
2381 else
2382 #endif
2384 png_bytep sp = row;
2385 png_bytep dp = row;
2386 for (i = 0; i < row_width; i++)
2388 png_uint_16 red, green, blue, gray16;
2390 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2391 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2392 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2394 if (red != green || red != blue)
2395 rgb_error |= 1;
2396 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2397 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2398 *(dp++) = (png_byte)(gray16 & 0xff);
2403 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2405 if (row_info->bit_depth == 8)
2407 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2408 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2410 png_bytep sp = row;
2411 png_bytep dp = row;
2412 for (i = 0; i < row_width; i++)
2414 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2415 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2416 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2417 if (red != green || red != blue)
2418 rgb_error |= 1;
2419 *(dp++) = png_ptr->gamma_from_1
2420 [(rc*red + gc*green + bc*blue)>>15];
2421 *(dp++) = *(sp++); /* alpha */
2424 else
2425 #endif
2427 png_bytep sp = row;
2428 png_bytep dp = row;
2429 for (i = 0; i < row_width; i++)
2431 png_byte red = *(sp++);
2432 png_byte green = *(sp++);
2433 png_byte blue = *(sp++);
2434 if (red != green || red != blue)
2435 rgb_error |= 1;
2436 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
2437 *(dp++) = *(sp++); /* alpha */
2441 else /* RGBA bit_depth == 16 */
2443 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2444 if (png_ptr->gamma_16_to_1 != NULL &&
2445 png_ptr->gamma_16_from_1 != NULL)
2447 png_bytep sp = row;
2448 png_bytep dp = row;
2449 for (i = 0; i < row_width; i++)
2451 png_uint_16 red, green, blue, w;
2453 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2454 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2455 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2457 if (red == green && red == blue)
2458 w = red;
2459 else
2461 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2462 png_ptr->gamma_shift][red>>8];
2463 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2464 png_ptr->gamma_shift][green>>8];
2465 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2466 png_ptr->gamma_shift][blue>>8];
2467 png_uint_16 gray16 = (png_uint_16)((rc * red_1
2468 + gc * green_1 + bc * blue_1)>>15);
2469 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2470 png_ptr->gamma_shift][gray16 >> 8];
2471 rgb_error |= 1;
2474 *(dp++) = (png_byte)((w>>8) & 0xff);
2475 *(dp++) = (png_byte)(w & 0xff);
2476 *(dp++) = *(sp++); /* alpha */
2477 *(dp++) = *(sp++);
2480 else
2481 #endif
2483 png_bytep sp = row;
2484 png_bytep dp = row;
2485 for (i = 0; i < row_width; i++)
2487 png_uint_16 red, green, blue, gray16;
2488 red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2489 green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2490 blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2491 if (red != green || red != blue)
2492 rgb_error |= 1;
2493 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2494 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2495 *(dp++) = (png_byte)(gray16 & 0xff);
2496 *(dp++) = *(sp++); /* alpha */
2497 *(dp++) = *(sp++);
2502 row_info->channels -= (png_byte)2;
2503 row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2504 row_info->pixel_depth = (png_byte)(row_info->channels *
2505 row_info->bit_depth);
2506 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2508 return rgb_error;
2510 #endif
2512 /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
2513 * large of png_color. This lets grayscale images be treated as
2514 * paletted. Most useful for gamma correction and simplification
2515 * of code.
2517 void PNGAPI
2518 png_build_grayscale_palette(int bit_depth, png_colorp palette)
2520 int num_palette;
2521 int color_inc;
2522 int i;
2523 int v;
2525 png_debug(1, "in png_do_build_grayscale_palette");
2526 if (palette == NULL)
2527 return;
2529 switch (bit_depth)
2531 case 1:
2532 num_palette = 2;
2533 color_inc = 0xff;
2534 break;
2536 case 2:
2537 num_palette = 4;
2538 color_inc = 0x55;
2539 break;
2541 case 4:
2542 num_palette = 16;
2543 color_inc = 0x11;
2544 break;
2546 case 8:
2547 num_palette = 256;
2548 color_inc = 1;
2549 break;
2551 default:
2552 num_palette = 0;
2553 color_inc = 0;
2554 break;
2557 for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2559 palette[i].red = (png_byte)v;
2560 palette[i].green = (png_byte)v;
2561 palette[i].blue = (png_byte)v;
2565 /* This function is currently unused. Do we really need it? */
2566 #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
2567 void /* PRIVATE */
2568 png_correct_palette(png_structp png_ptr, png_colorp palette,
2569 int num_palette)
2571 png_debug(1, "in png_correct_palette");
2572 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2573 defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
2574 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
2576 png_color back, back_1;
2578 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
2580 back.red = png_ptr->gamma_table[png_ptr->background.red];
2581 back.green = png_ptr->gamma_table[png_ptr->background.green];
2582 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
2584 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
2585 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
2586 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
2588 else
2590 double g;
2592 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
2594 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2595 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
2597 back.red = png_ptr->background.red;
2598 back.green = png_ptr->background.green;
2599 back.blue = png_ptr->background.blue;
2601 else
2603 back.red =
2604 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2605 255.0 + 0.5);
2606 back.green =
2607 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2608 255.0 + 0.5);
2609 back.blue =
2610 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2611 255.0 + 0.5);
2614 g = 1.0 / png_ptr->background_gamma;
2616 back_1.red =
2617 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2618 255.0 + 0.5);
2619 back_1.green =
2620 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2621 255.0 + 0.5);
2622 back_1.blue =
2623 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2624 255.0 + 0.5);
2627 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2629 png_uint_32 i;
2631 for (i = 0; i < (png_uint_32)num_palette; i++)
2633 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
2635 palette[i] = back;
2637 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
2639 png_byte v, w;
2641 v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
2642 png_composite(w, v, png_ptr->trans[i], back_1.red);
2643 palette[i].red = png_ptr->gamma_from_1[w];
2645 v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
2646 png_composite(w, v, png_ptr->trans[i], back_1.green);
2647 palette[i].green = png_ptr->gamma_from_1[w];
2649 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
2650 png_composite(w, v, png_ptr->trans[i], back_1.blue);
2651 palette[i].blue = png_ptr->gamma_from_1[w];
2653 else
2655 palette[i].red = png_ptr->gamma_table[palette[i].red];
2656 palette[i].green = png_ptr->gamma_table[palette[i].green];
2657 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2661 else
2663 int i;
2665 for (i = 0; i < num_palette; i++)
2667 if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
2669 palette[i] = back;
2671 else
2673 palette[i].red = png_ptr->gamma_table[palette[i].red];
2674 palette[i].green = png_ptr->gamma_table[palette[i].green];
2675 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2680 else
2681 #endif
2682 #if defined(PNG_READ_GAMMA_SUPPORTED)
2683 if (png_ptr->transformations & PNG_GAMMA)
2685 int i;
2687 for (i = 0; i < num_palette; i++)
2689 palette[i].red = png_ptr->gamma_table[palette[i].red];
2690 palette[i].green = png_ptr->gamma_table[palette[i].green];
2691 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2694 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2695 else
2696 #endif
2697 #endif
2698 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2699 if (png_ptr->transformations & PNG_BACKGROUND)
2701 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2703 png_color back;
2705 back.red = (png_byte)png_ptr->background.red;
2706 back.green = (png_byte)png_ptr->background.green;
2707 back.blue = (png_byte)png_ptr->background.blue;
2709 for (i = 0; i < (int)png_ptr->num_trans; i++)
2711 if (png_ptr->trans[i] == 0)
2713 palette[i].red = back.red;
2714 palette[i].green = back.green;
2715 palette[i].blue = back.blue;
2717 else if (png_ptr->trans[i] != 0xff)
2719 png_composite(palette[i].red, png_ptr->palette[i].red,
2720 png_ptr->trans[i], back.red);
2721 png_composite(palette[i].green, png_ptr->palette[i].green,
2722 png_ptr->trans[i], back.green);
2723 png_composite(palette[i].blue, png_ptr->palette[i].blue,
2724 png_ptr->trans[i], back.blue);
2728 else /* Assume grayscale palette (what else could it be?) */
2730 int i;
2732 for (i = 0; i < num_palette; i++)
2734 if (i == (png_byte)png_ptr->trans_values.gray)
2736 palette[i].red = (png_byte)png_ptr->background.red;
2737 palette[i].green = (png_byte)png_ptr->background.green;
2738 palette[i].blue = (png_byte)png_ptr->background.blue;
2743 #endif
2745 #endif
2747 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2748 /* Replace any alpha or transparency with the supplied background color.
2749 * "background" is already in the screen gamma, while "background_1" is
2750 * at a gamma of 1.0. Paletted files have already been taken care of.
2752 void /* PRIVATE */
2753 png_do_background(png_row_infop row_info, png_bytep row,
2754 png_color_16p trans_values, png_color_16p background
2755 #if defined(PNG_READ_GAMMA_SUPPORTED)
2756 , png_color_16p background_1,
2757 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
2758 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2759 png_uint_16pp gamma_16_to_1, int gamma_shift
2760 #endif
2763 png_bytep sp, dp;
2764 png_uint_32 i;
2765 png_uint_32 row_width=row_info->width;
2766 int shift;
2768 png_debug(1, "in png_do_background");
2769 if (background != NULL &&
2770 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2771 row != NULL && row_info != NULL &&
2772 #endif
2773 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
2774 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
2776 switch (row_info->color_type)
2778 case PNG_COLOR_TYPE_GRAY:
2780 switch (row_info->bit_depth)
2782 case 1:
2784 sp = row;
2785 shift = 7;
2786 for (i = 0; i < row_width; i++)
2788 if ((png_uint_16)((*sp >> shift) & 0x01)
2789 == trans_values->gray)
2791 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2792 *sp |= (png_byte)(background->gray << shift);
2794 if (!shift)
2796 shift = 7;
2797 sp++;
2799 else
2800 shift--;
2802 break;
2805 case 2:
2807 #if defined(PNG_READ_GAMMA_SUPPORTED)
2808 if (gamma_table != NULL)
2810 sp = row;
2811 shift = 6;
2812 for (i = 0; i < row_width; i++)
2814 if ((png_uint_16)((*sp >> shift) & 0x03)
2815 == trans_values->gray)
2817 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2818 *sp |= (png_byte)(background->gray << shift);
2820 else
2822 png_byte p = (png_byte)((*sp >> shift) & 0x03);
2823 png_byte g = (png_byte)((gamma_table [p | (p << 2) |
2824 (p << 4) | (p << 6)] >> 6) & 0x03);
2825 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2826 *sp |= (png_byte)(g << shift);
2828 if (!shift)
2830 shift = 6;
2831 sp++;
2833 else
2834 shift -= 2;
2837 else
2838 #endif
2840 sp = row;
2841 shift = 6;
2842 for (i = 0; i < row_width; i++)
2844 if ((png_uint_16)((*sp >> shift) & 0x03)
2845 == trans_values->gray)
2847 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2848 *sp |= (png_byte)(background->gray << shift);
2850 if (!shift)
2852 shift = 6;
2853 sp++;
2855 else
2856 shift -= 2;
2859 break;
2862 case 4:
2864 #if defined(PNG_READ_GAMMA_SUPPORTED)
2865 if (gamma_table != NULL)
2867 sp = row;
2868 shift = 4;
2869 for (i = 0; i < row_width; i++)
2871 if ((png_uint_16)((*sp >> shift) & 0x0f)
2872 == trans_values->gray)
2874 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2875 *sp |= (png_byte)(background->gray << shift);
2877 else
2879 png_byte p = (png_byte)((*sp >> shift) & 0x0f);
2880 png_byte g = (png_byte)((gamma_table[p |
2881 (p << 4)] >> 4) & 0x0f);
2882 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2883 *sp |= (png_byte)(g << shift);
2885 if (!shift)
2887 shift = 4;
2888 sp++;
2890 else
2891 shift -= 4;
2894 else
2895 #endif
2897 sp = row;
2898 shift = 4;
2899 for (i = 0; i < row_width; i++)
2901 if ((png_uint_16)((*sp >> shift) & 0x0f)
2902 == trans_values->gray)
2904 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2905 *sp |= (png_byte)(background->gray << shift);
2907 if (!shift)
2909 shift = 4;
2910 sp++;
2912 else
2913 shift -= 4;
2916 break;
2919 case 8:
2921 #if defined(PNG_READ_GAMMA_SUPPORTED)
2922 if (gamma_table != NULL)
2924 sp = row;
2925 for (i = 0; i < row_width; i++, sp++)
2927 if (*sp == trans_values->gray)
2929 *sp = (png_byte)background->gray;
2931 else
2933 *sp = gamma_table[*sp];
2937 else
2938 #endif
2940 sp = row;
2941 for (i = 0; i < row_width; i++, sp++)
2943 if (*sp == trans_values->gray)
2945 *sp = (png_byte)background->gray;
2949 break;
2952 case 16:
2954 #if defined(PNG_READ_GAMMA_SUPPORTED)
2955 if (gamma_16 != NULL)
2957 sp = row;
2958 for (i = 0; i < row_width; i++, sp += 2)
2960 png_uint_16 v;
2962 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2963 if (v == trans_values->gray)
2965 /* Background is already in screen gamma */
2966 *sp = (png_byte)((background->gray >> 8) & 0xff);
2967 *(sp + 1) = (png_byte)(background->gray & 0xff);
2969 else
2971 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2972 *sp = (png_byte)((v >> 8) & 0xff);
2973 *(sp + 1) = (png_byte)(v & 0xff);
2977 else
2978 #endif
2980 sp = row;
2981 for (i = 0; i < row_width; i++, sp += 2)
2983 png_uint_16 v;
2985 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2986 if (v == trans_values->gray)
2988 *sp = (png_byte)((background->gray >> 8) & 0xff);
2989 *(sp + 1) = (png_byte)(background->gray & 0xff);
2993 break;
2996 break;
2999 case PNG_COLOR_TYPE_RGB:
3001 if (row_info->bit_depth == 8)
3003 #if defined(PNG_READ_GAMMA_SUPPORTED)
3004 if (gamma_table != NULL)
3006 sp = row;
3007 for (i = 0; i < row_width; i++, sp += 3)
3009 if (*sp == trans_values->red &&
3010 *(sp + 1) == trans_values->green &&
3011 *(sp + 2) == trans_values->blue)
3013 *sp = (png_byte)background->red;
3014 *(sp + 1) = (png_byte)background->green;
3015 *(sp + 2) = (png_byte)background->blue;
3017 else
3019 *sp = gamma_table[*sp];
3020 *(sp + 1) = gamma_table[*(sp + 1)];
3021 *(sp + 2) = gamma_table[*(sp + 2)];
3025 else
3026 #endif
3028 sp = row;
3029 for (i = 0; i < row_width; i++, sp += 3)
3031 if (*sp == trans_values->red &&
3032 *(sp + 1) == trans_values->green &&
3033 *(sp + 2) == trans_values->blue)
3035 *sp = (png_byte)background->red;
3036 *(sp + 1) = (png_byte)background->green;
3037 *(sp + 2) = (png_byte)background->blue;
3042 else /* if (row_info->bit_depth == 16) */
3044 #if defined(PNG_READ_GAMMA_SUPPORTED)
3045 if (gamma_16 != NULL)
3047 sp = row;
3048 for (i = 0; i < row_width; i++, sp += 6)
3050 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3051 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3052 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
3053 if (r == trans_values->red && g == trans_values->green &&
3054 b == trans_values->blue)
3056 /* Background is already in screen gamma */
3057 *sp = (png_byte)((background->red >> 8) & 0xff);
3058 *(sp + 1) = (png_byte)(background->red & 0xff);
3059 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
3060 *(sp + 3) = (png_byte)(background->green & 0xff);
3061 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3062 *(sp + 5) = (png_byte)(background->blue & 0xff);
3064 else
3066 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3067 *sp = (png_byte)((v >> 8) & 0xff);
3068 *(sp + 1) = (png_byte)(v & 0xff);
3069 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3070 *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3071 *(sp + 3) = (png_byte)(v & 0xff);
3072 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3073 *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3074 *(sp + 5) = (png_byte)(v & 0xff);
3078 else
3079 #endif
3081 sp = row;
3082 for (i = 0; i < row_width; i++, sp += 6)
3084 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
3085 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3086 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
3088 if (r == trans_values->red && g == trans_values->green &&
3089 b == trans_values->blue)
3091 *sp = (png_byte)((background->red >> 8) & 0xff);
3092 *(sp + 1) = (png_byte)(background->red & 0xff);
3093 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
3094 *(sp + 3) = (png_byte)(background->green & 0xff);
3095 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3096 *(sp + 5) = (png_byte)(background->blue & 0xff);
3101 break;
3104 case PNG_COLOR_TYPE_GRAY_ALPHA:
3106 if (row_info->bit_depth == 8)
3108 #if defined(PNG_READ_GAMMA_SUPPORTED)
3109 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3110 gamma_table != NULL)
3112 sp = row;
3113 dp = row;
3114 for (i = 0; i < row_width; i++, sp += 2, dp++)
3116 png_uint_16 a = *(sp + 1);
3118 if (a == 0xff)
3120 *dp = gamma_table[*sp];
3122 else if (a == 0)
3124 /* Background is already in screen gamma */
3125 *dp = (png_byte)background->gray;
3127 else
3129 png_byte v, w;
3131 v = gamma_to_1[*sp];
3132 png_composite(w, v, a, background_1->gray);
3133 *dp = gamma_from_1[w];
3137 else
3138 #endif
3140 sp = row;
3141 dp = row;
3142 for (i = 0; i < row_width; i++, sp += 2, dp++)
3144 png_byte a = *(sp + 1);
3146 if (a == 0xff)
3148 *dp = *sp;
3150 #if defined(PNG_READ_GAMMA_SUPPORTED)
3151 else if (a == 0)
3153 *dp = (png_byte)background->gray;
3155 else
3157 png_composite(*dp, *sp, a, background_1->gray);
3159 #else
3160 *dp = (png_byte)background->gray;
3161 #endif
3165 else /* if (png_ptr->bit_depth == 16) */
3167 #if defined(PNG_READ_GAMMA_SUPPORTED)
3168 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3169 gamma_16_to_1 != NULL)
3171 sp = row;
3172 dp = row;
3173 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3175 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3177 if (a == (png_uint_16)0xffff)
3179 png_uint_16 v;
3181 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3182 *dp = (png_byte)((v >> 8) & 0xff);
3183 *(dp + 1) = (png_byte)(v & 0xff);
3185 #if defined(PNG_READ_GAMMA_SUPPORTED)
3186 else if (a == 0)
3187 #else
3188 else
3189 #endif
3191 /* Background is already in screen gamma */
3192 *dp = (png_byte)((background->gray >> 8) & 0xff);
3193 *(dp + 1) = (png_byte)(background->gray & 0xff);
3195 #if defined(PNG_READ_GAMMA_SUPPORTED)
3196 else
3198 png_uint_16 g, v, w;
3200 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3201 png_composite_16(v, g, a, background_1->gray);
3202 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3203 *dp = (png_byte)((w >> 8) & 0xff);
3204 *(dp + 1) = (png_byte)(w & 0xff);
3206 #endif
3209 else
3210 #endif
3212 sp = row;
3213 dp = row;
3214 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3216 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3217 if (a == (png_uint_16)0xffff)
3219 png_memcpy(dp, sp, 2);
3221 #if defined(PNG_READ_GAMMA_SUPPORTED)
3222 else if (a == 0)
3223 #else
3224 else
3225 #endif
3227 *dp = (png_byte)((background->gray >> 8) & 0xff);
3228 *(dp + 1) = (png_byte)(background->gray & 0xff);
3230 #if defined(PNG_READ_GAMMA_SUPPORTED)
3231 else
3233 png_uint_16 g, v;
3235 g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3236 png_composite_16(v, g, a, background_1->gray);
3237 *dp = (png_byte)((v >> 8) & 0xff);
3238 *(dp + 1) = (png_byte)(v & 0xff);
3240 #endif
3244 break;
3247 case PNG_COLOR_TYPE_RGB_ALPHA:
3249 if (row_info->bit_depth == 8)
3251 #if defined(PNG_READ_GAMMA_SUPPORTED)
3252 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3253 gamma_table != NULL)
3255 sp = row;
3256 dp = row;
3257 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3259 png_byte a = *(sp + 3);
3261 if (a == 0xff)
3263 *dp = gamma_table[*sp];
3264 *(dp + 1) = gamma_table[*(sp + 1)];
3265 *(dp + 2) = gamma_table[*(sp + 2)];
3267 else if (a == 0)
3269 /* Background is already in screen gamma */
3270 *dp = (png_byte)background->red;
3271 *(dp + 1) = (png_byte)background->green;
3272 *(dp + 2) = (png_byte)background->blue;
3274 else
3276 png_byte v, w;
3278 v = gamma_to_1[*sp];
3279 png_composite(w, v, a, background_1->red);
3280 *dp = gamma_from_1[w];
3281 v = gamma_to_1[*(sp + 1)];
3282 png_composite(w, v, a, background_1->green);
3283 *(dp + 1) = gamma_from_1[w];
3284 v = gamma_to_1[*(sp + 2)];
3285 png_composite(w, v, a, background_1->blue);
3286 *(dp + 2) = gamma_from_1[w];
3290 else
3291 #endif
3293 sp = row;
3294 dp = row;
3295 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3297 png_byte a = *(sp + 3);
3299 if (a == 0xff)
3301 *dp = *sp;
3302 *(dp + 1) = *(sp + 1);
3303 *(dp + 2) = *(sp + 2);
3305 else if (a == 0)
3307 *dp = (png_byte)background->red;
3308 *(dp + 1) = (png_byte)background->green;
3309 *(dp + 2) = (png_byte)background->blue;
3311 else
3313 png_composite(*dp, *sp, a, background->red);
3314 png_composite(*(dp + 1), *(sp + 1), a,
3315 background->green);
3316 png_composite(*(dp + 2), *(sp + 2), a,
3317 background->blue);
3322 else /* if (row_info->bit_depth == 16) */
3324 #if defined(PNG_READ_GAMMA_SUPPORTED)
3325 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3326 gamma_16_to_1 != NULL)
3328 sp = row;
3329 dp = row;
3330 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3332 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3333 << 8) + (png_uint_16)(*(sp + 7)));
3334 if (a == (png_uint_16)0xffff)
3336 png_uint_16 v;
3338 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3339 *dp = (png_byte)((v >> 8) & 0xff);
3340 *(dp + 1) = (png_byte)(v & 0xff);
3341 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3342 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3343 *(dp + 3) = (png_byte)(v & 0xff);
3344 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3345 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3346 *(dp + 5) = (png_byte)(v & 0xff);
3348 else if (a == 0)
3350 /* Background is already in screen gamma */
3351 *dp = (png_byte)((background->red >> 8) & 0xff);
3352 *(dp + 1) = (png_byte)(background->red & 0xff);
3353 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3354 *(dp + 3) = (png_byte)(background->green & 0xff);
3355 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3356 *(dp + 5) = (png_byte)(background->blue & 0xff);
3358 else
3360 png_uint_16 v, w, x;
3362 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3363 png_composite_16(w, v, a, background_1->red);
3364 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3365 *dp = (png_byte)((x >> 8) & 0xff);
3366 *(dp + 1) = (png_byte)(x & 0xff);
3367 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3368 png_composite_16(w, v, a, background_1->green);
3369 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3370 *(dp + 2) = (png_byte)((x >> 8) & 0xff);
3371 *(dp + 3) = (png_byte)(x & 0xff);
3372 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3373 png_composite_16(w, v, a, background_1->blue);
3374 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3375 *(dp + 4) = (png_byte)((x >> 8) & 0xff);
3376 *(dp + 5) = (png_byte)(x & 0xff);
3380 else
3381 #endif
3383 sp = row;
3384 dp = row;
3385 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3387 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3388 << 8) + (png_uint_16)(*(sp + 7)));
3389 if (a == (png_uint_16)0xffff)
3391 png_memcpy(dp, sp, 6);
3393 else if (a == 0)
3395 *dp = (png_byte)((background->red >> 8) & 0xff);
3396 *(dp + 1) = (png_byte)(background->red & 0xff);
3397 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3398 *(dp + 3) = (png_byte)(background->green & 0xff);
3399 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3400 *(dp + 5) = (png_byte)(background->blue & 0xff);
3402 else
3404 png_uint_16 v;
3406 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3407 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3408 + *(sp + 3));
3409 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3410 + *(sp + 5));
3412 png_composite_16(v, r, a, background->red);
3413 *dp = (png_byte)((v >> 8) & 0xff);
3414 *(dp + 1) = (png_byte)(v & 0xff);
3415 png_composite_16(v, g, a, background->green);
3416 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3417 *(dp + 3) = (png_byte)(v & 0xff);
3418 png_composite_16(v, b, a, background->blue);
3419 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3420 *(dp + 5) = (png_byte)(v & 0xff);
3425 break;
3429 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3431 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
3432 row_info->channels--;
3433 row_info->pixel_depth = (png_byte)(row_info->channels *
3434 row_info->bit_depth);
3435 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3439 #endif
3441 #if defined(PNG_READ_GAMMA_SUPPORTED)
3442 /* Gamma correct the image, avoiding the alpha channel. Make sure
3443 * you do this after you deal with the transparency issue on grayscale
3444 * or RGB images. If your bit depth is 8, use gamma_table, if it
3445 * is 16, use gamma_16_table and gamma_shift. Build these with
3446 * build_gamma_table().
3448 void /* PRIVATE */
3449 png_do_gamma(png_row_infop row_info, png_bytep row,
3450 png_bytep gamma_table, png_uint_16pp gamma_16_table,
3451 int gamma_shift)
3453 png_bytep sp;
3454 png_uint_32 i;
3455 png_uint_32 row_width=row_info->width;
3457 png_debug(1, "in png_do_gamma");
3458 if (
3459 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3460 row != NULL && row_info != NULL &&
3461 #endif
3462 ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3463 (row_info->bit_depth == 16 && gamma_16_table != NULL)))
3465 switch (row_info->color_type)
3467 case PNG_COLOR_TYPE_RGB:
3469 if (row_info->bit_depth == 8)
3471 sp = row;
3472 for (i = 0; i < row_width; i++)
3474 *sp = gamma_table[*sp];
3475 sp++;
3476 *sp = gamma_table[*sp];
3477 sp++;
3478 *sp = gamma_table[*sp];
3479 sp++;
3482 else /* if (row_info->bit_depth == 16) */
3484 sp = row;
3485 for (i = 0; i < row_width; i++)
3487 png_uint_16 v;
3489 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3490 *sp = (png_byte)((v >> 8) & 0xff);
3491 *(sp + 1) = (png_byte)(v & 0xff);
3492 sp += 2;
3493 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3494 *sp = (png_byte)((v >> 8) & 0xff);
3495 *(sp + 1) = (png_byte)(v & 0xff);
3496 sp += 2;
3497 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3498 *sp = (png_byte)((v >> 8) & 0xff);
3499 *(sp + 1) = (png_byte)(v & 0xff);
3500 sp += 2;
3503 break;
3506 case PNG_COLOR_TYPE_RGB_ALPHA:
3508 if (row_info->bit_depth == 8)
3510 sp = row;
3511 for (i = 0; i < row_width; i++)
3513 *sp = gamma_table[*sp];
3514 sp++;
3515 *sp = gamma_table[*sp];
3516 sp++;
3517 *sp = gamma_table[*sp];
3518 sp++;
3519 sp++;
3522 else /* if (row_info->bit_depth == 16) */
3524 sp = row;
3525 for (i = 0; i < row_width; i++)
3527 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3528 *sp = (png_byte)((v >> 8) & 0xff);
3529 *(sp + 1) = (png_byte)(v & 0xff);
3530 sp += 2;
3531 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3532 *sp = (png_byte)((v >> 8) & 0xff);
3533 *(sp + 1) = (png_byte)(v & 0xff);
3534 sp += 2;
3535 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3536 *sp = (png_byte)((v >> 8) & 0xff);
3537 *(sp + 1) = (png_byte)(v & 0xff);
3538 sp += 4;
3541 break;
3544 case PNG_COLOR_TYPE_GRAY_ALPHA:
3546 if (row_info->bit_depth == 8)
3548 sp = row;
3549 for (i = 0; i < row_width; i++)
3551 *sp = gamma_table[*sp];
3552 sp += 2;
3555 else /* if (row_info->bit_depth == 16) */
3557 sp = row;
3558 for (i = 0; i < row_width; i++)
3560 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3561 *sp = (png_byte)((v >> 8) & 0xff);
3562 *(sp + 1) = (png_byte)(v & 0xff);
3563 sp += 4;
3566 break;
3569 case PNG_COLOR_TYPE_GRAY:
3571 if (row_info->bit_depth == 2)
3573 sp = row;
3574 for (i = 0; i < row_width; i += 4)
3576 int a = *sp & 0xc0;
3577 int b = *sp & 0x30;
3578 int c = *sp & 0x0c;
3579 int d = *sp & 0x03;
3581 *sp = (png_byte)(
3582 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
3583 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3584 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
3585 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
3586 sp++;
3590 if (row_info->bit_depth == 4)
3592 sp = row;
3593 for (i = 0; i < row_width; i += 2)
3595 int msb = *sp & 0xf0;
3596 int lsb = *sp & 0x0f;
3598 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3599 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
3600 sp++;
3604 else if (row_info->bit_depth == 8)
3606 sp = row;
3607 for (i = 0; i < row_width; i++)
3609 *sp = gamma_table[*sp];
3610 sp++;
3614 else if (row_info->bit_depth == 16)
3616 sp = row;
3617 for (i = 0; i < row_width; i++)
3619 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3620 *sp = (png_byte)((v >> 8) & 0xff);
3621 *(sp + 1) = (png_byte)(v & 0xff);
3622 sp += 2;
3625 break;
3630 #endif
3632 #if defined(PNG_READ_EXPAND_SUPPORTED)
3633 /* Expands a palette row to an RGB or RGBA row depending
3634 * upon whether you supply trans and num_trans.
3636 void /* PRIVATE */
3637 png_do_expand_palette(png_row_infop row_info, png_bytep row,
3638 png_colorp palette, png_bytep trans, int num_trans)
3640 int shift, value;
3641 png_bytep sp, dp;
3642 png_uint_32 i;
3643 png_uint_32 row_width=row_info->width;
3645 png_debug(1, "in png_do_expand_palette");
3646 if (
3647 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3648 row != NULL && row_info != NULL &&
3649 #endif
3650 row_info->color_type == PNG_COLOR_TYPE_PALETTE)
3652 if (row_info->bit_depth < 8)
3654 switch (row_info->bit_depth)
3656 case 1:
3658 sp = row + (png_size_t)((row_width - 1) >> 3);
3659 dp = row + (png_size_t)row_width - 1;
3660 shift = 7 - (int)((row_width + 7) & 0x07);
3661 for (i = 0; i < row_width; i++)
3663 if ((*sp >> shift) & 0x01)
3664 *dp = 1;
3665 else
3666 *dp = 0;
3667 if (shift == 7)
3669 shift = 0;
3670 sp--;
3672 else
3673 shift++;
3675 dp--;
3677 break;
3680 case 2:
3682 sp = row + (png_size_t)((row_width - 1) >> 2);
3683 dp = row + (png_size_t)row_width - 1;
3684 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3685 for (i = 0; i < row_width; i++)
3687 value = (*sp >> shift) & 0x03;
3688 *dp = (png_byte)value;
3689 if (shift == 6)
3691 shift = 0;
3692 sp--;
3694 else
3695 shift += 2;
3697 dp--;
3699 break;
3702 case 4:
3704 sp = row + (png_size_t)((row_width - 1) >> 1);
3705 dp = row + (png_size_t)row_width - 1;
3706 shift = (int)((row_width & 0x01) << 2);
3707 for (i = 0; i < row_width; i++)
3709 value = (*sp >> shift) & 0x0f;
3710 *dp = (png_byte)value;
3711 if (shift == 4)
3713 shift = 0;
3714 sp--;
3716 else
3717 shift += 4;
3719 dp--;
3721 break;
3724 row_info->bit_depth = 8;
3725 row_info->pixel_depth = 8;
3726 row_info->rowbytes = row_width;
3728 switch (row_info->bit_depth)
3730 case 8:
3732 if (trans != NULL)
3734 sp = row + (png_size_t)row_width - 1;
3735 dp = row + (png_size_t)(row_width << 2) - 1;
3737 for (i = 0; i < row_width; i++)
3739 if ((int)(*sp) >= num_trans)
3740 *dp-- = 0xff;
3741 else
3742 *dp-- = trans[*sp];
3743 *dp-- = palette[*sp].blue;
3744 *dp-- = palette[*sp].green;
3745 *dp-- = palette[*sp].red;
3746 sp--;
3748 row_info->bit_depth = 8;
3749 row_info->pixel_depth = 32;
3750 row_info->rowbytes = row_width * 4;
3751 row_info->color_type = 6;
3752 row_info->channels = 4;
3754 else
3756 sp = row + (png_size_t)row_width - 1;
3757 dp = row + (png_size_t)(row_width * 3) - 1;
3759 for (i = 0; i < row_width; i++)
3761 *dp-- = palette[*sp].blue;
3762 *dp-- = palette[*sp].green;
3763 *dp-- = palette[*sp].red;
3764 sp--;
3767 row_info->bit_depth = 8;
3768 row_info->pixel_depth = 24;
3769 row_info->rowbytes = row_width * 3;
3770 row_info->color_type = 2;
3771 row_info->channels = 3;
3773 break;
3779 /* If the bit depth < 8, it is expanded to 8. Also, if the already
3780 * expanded transparency value is supplied, an alpha channel is built.
3782 void /* PRIVATE */
3783 png_do_expand(png_row_infop row_info, png_bytep row,
3784 png_color_16p trans_value)
3786 int shift, value;
3787 png_bytep sp, dp;
3788 png_uint_32 i;
3789 png_uint_32 row_width=row_info->width;
3791 png_debug(1, "in png_do_expand");
3792 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3793 if (row != NULL && row_info != NULL)
3794 #endif
3796 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
3798 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
3800 if (row_info->bit_depth < 8)
3802 switch (row_info->bit_depth)
3804 case 1:
3806 gray = (png_uint_16)((gray&0x01)*0xff);
3807 sp = row + (png_size_t)((row_width - 1) >> 3);
3808 dp = row + (png_size_t)row_width - 1;
3809 shift = 7 - (int)((row_width + 7) & 0x07);
3810 for (i = 0; i < row_width; i++)
3812 if ((*sp >> shift) & 0x01)
3813 *dp = 0xff;
3814 else
3815 *dp = 0;
3816 if (shift == 7)
3818 shift = 0;
3819 sp--;
3821 else
3822 shift++;
3824 dp--;
3826 break;
3829 case 2:
3831 gray = (png_uint_16)((gray&0x03)*0x55);
3832 sp = row + (png_size_t)((row_width - 1) >> 2);
3833 dp = row + (png_size_t)row_width - 1;
3834 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3835 for (i = 0; i < row_width; i++)
3837 value = (*sp >> shift) & 0x03;
3838 *dp = (png_byte)(value | (value << 2) | (value << 4) |
3839 (value << 6));
3840 if (shift == 6)
3842 shift = 0;
3843 sp--;
3845 else
3846 shift += 2;
3848 dp--;
3850 break;
3853 case 4:
3855 gray = (png_uint_16)((gray&0x0f)*0x11);
3856 sp = row + (png_size_t)((row_width - 1) >> 1);
3857 dp = row + (png_size_t)row_width - 1;
3858 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
3859 for (i = 0; i < row_width; i++)
3861 value = (*sp >> shift) & 0x0f;
3862 *dp = (png_byte)(value | (value << 4));
3863 if (shift == 4)
3865 shift = 0;
3866 sp--;
3868 else
3869 shift = 4;
3871 dp--;
3873 break;
3877 row_info->bit_depth = 8;
3878 row_info->pixel_depth = 8;
3879 row_info->rowbytes = row_width;
3882 if (trans_value != NULL)
3884 if (row_info->bit_depth == 8)
3886 gray = gray & 0xff;
3887 sp = row + (png_size_t)row_width - 1;
3888 dp = row + (png_size_t)(row_width << 1) - 1;
3889 for (i = 0; i < row_width; i++)
3891 if (*sp == gray)
3892 *dp-- = 0;
3893 else
3894 *dp-- = 0xff;
3895 *dp-- = *sp--;
3899 else if (row_info->bit_depth == 16)
3901 png_byte gray_high = (gray >> 8) & 0xff;
3902 png_byte gray_low = gray & 0xff;
3903 sp = row + row_info->rowbytes - 1;
3904 dp = row + (row_info->rowbytes << 1) - 1;
3905 for (i = 0; i < row_width; i++)
3907 if (*(sp - 1) == gray_high && *(sp) == gray_low)
3909 *dp-- = 0;
3910 *dp-- = 0;
3912 else
3914 *dp-- = 0xff;
3915 *dp-- = 0xff;
3917 *dp-- = *sp--;
3918 *dp-- = *sp--;
3922 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3923 row_info->channels = 2;
3924 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3925 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
3926 row_width);
3929 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3931 if (row_info->bit_depth == 8)
3933 png_byte red = trans_value->red & 0xff;
3934 png_byte green = trans_value->green & 0xff;
3935 png_byte blue = trans_value->blue & 0xff;
3936 sp = row + (png_size_t)row_info->rowbytes - 1;
3937 dp = row + (png_size_t)(row_width << 2) - 1;
3938 for (i = 0; i < row_width; i++)
3940 if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
3941 *dp-- = 0;
3942 else
3943 *dp-- = 0xff;
3944 *dp-- = *sp--;
3945 *dp-- = *sp--;
3946 *dp-- = *sp--;
3949 else if (row_info->bit_depth == 16)
3951 png_byte red_high = (trans_value->red >> 8) & 0xff;
3952 png_byte green_high = (trans_value->green >> 8) & 0xff;
3953 png_byte blue_high = (trans_value->blue >> 8) & 0xff;
3954 png_byte red_low = trans_value->red & 0xff;
3955 png_byte green_low = trans_value->green & 0xff;
3956 png_byte blue_low = trans_value->blue & 0xff;
3957 sp = row + row_info->rowbytes - 1;
3958 dp = row + (png_size_t)(row_width << 3) - 1;
3959 for (i = 0; i < row_width; i++)
3961 if (*(sp - 5) == red_high &&
3962 *(sp - 4) == red_low &&
3963 *(sp - 3) == green_high &&
3964 *(sp - 2) == green_low &&
3965 *(sp - 1) == blue_high &&
3966 *(sp ) == blue_low)
3968 *dp-- = 0;
3969 *dp-- = 0;
3971 else
3973 *dp-- = 0xff;
3974 *dp-- = 0xff;
3976 *dp-- = *sp--;
3977 *dp-- = *sp--;
3978 *dp-- = *sp--;
3979 *dp-- = *sp--;
3980 *dp-- = *sp--;
3981 *dp-- = *sp--;
3984 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3985 row_info->channels = 4;
3986 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
3987 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3991 #endif
3993 #if defined(PNG_READ_DITHER_SUPPORTED)
3994 void /* PRIVATE */
3995 png_do_dither(png_row_infop row_info, png_bytep row,
3996 png_bytep palette_lookup, png_bytep dither_lookup)
3998 png_bytep sp, dp;
3999 png_uint_32 i;
4000 png_uint_32 row_width=row_info->width;
4002 png_debug(1, "in png_do_dither");
4003 #if defined(PNG_USELESS_TESTS_SUPPORTED)
4004 if (row != NULL && row_info != NULL)
4005 #endif
4007 if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
4008 palette_lookup && row_info->bit_depth == 8)
4010 int r, g, b, p;
4011 sp = row;
4012 dp = row;
4013 for (i = 0; i < row_width; i++)
4015 r = *sp++;
4016 g = *sp++;
4017 b = *sp++;
4019 /* This looks real messy, but the compiler will reduce
4020 * it down to a reasonable formula. For example, with
4021 * 5 bits per color, we get:
4022 * p = (((r >> 3) & 0x1f) << 10) |
4023 * (((g >> 3) & 0x1f) << 5) |
4024 * ((b >> 3) & 0x1f);
4026 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
4027 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
4028 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
4029 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
4030 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
4031 (PNG_DITHER_BLUE_BITS)) |
4032 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
4033 ((1 << PNG_DITHER_BLUE_BITS) - 1));
4035 *dp++ = palette_lookup[p];
4037 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
4038 row_info->channels = 1;
4039 row_info->pixel_depth = row_info->bit_depth;
4040 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4042 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
4043 palette_lookup != NULL && row_info->bit_depth == 8)
4045 int r, g, b, p;
4046 sp = row;
4047 dp = row;
4048 for (i = 0; i < row_width; i++)
4050 r = *sp++;
4051 g = *sp++;
4052 b = *sp++;
4053 sp++;
4055 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
4056 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
4057 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
4058 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
4059 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
4060 (PNG_DITHER_BLUE_BITS)) |
4061 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
4062 ((1 << PNG_DITHER_BLUE_BITS) - 1));
4064 *dp++ = palette_lookup[p];
4066 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
4067 row_info->channels = 1;
4068 row_info->pixel_depth = row_info->bit_depth;
4069 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4071 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4072 dither_lookup && row_info->bit_depth == 8)
4074 sp = row;
4075 for (i = 0; i < row_width; i++, sp++)
4077 *sp = dither_lookup[*sp];
4082 #endif
4084 #ifdef PNG_FLOATING_POINT_SUPPORTED
4085 #if defined(PNG_READ_GAMMA_SUPPORTED)
4086 static PNG_CONST int png_gamma_shift[] =
4087 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
4089 /* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
4090 * tables, we don't make a full table if we are reducing to 8-bit in
4091 * the future. Note also how the gamma_16 tables are segmented so that
4092 * we don't need to allocate > 64K chunks for a full 16-bit table.
4094 void /* PRIVATE */
4095 png_build_gamma_table(png_structp png_ptr)
4097 png_debug(1, "in png_build_gamma_table");
4099 if (png_ptr->bit_depth <= 8)
4101 int i;
4102 double g;
4104 if (png_ptr->screen_gamma > .000001)
4105 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4107 else
4108 g = 1.0;
4110 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
4111 (png_uint_32)256);
4113 for (i = 0; i < 256; i++)
4115 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
4116 g) * 255.0 + .5);
4119 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4120 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4121 if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
4124 g = 1.0 / (png_ptr->gamma);
4126 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
4127 (png_uint_32)256);
4129 for (i = 0; i < 256; i++)
4131 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
4132 g) * 255.0 + .5);
4136 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
4137 (png_uint_32)256);
4139 if (png_ptr->screen_gamma > 0.000001)
4140 g = 1.0 / png_ptr->screen_gamma;
4142 else
4143 g = png_ptr->gamma; /* Probably doing rgb_to_gray */
4145 for (i = 0; i < 256; i++)
4147 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
4148 g) * 255.0 + .5);
4152 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4154 else
4156 double g;
4157 int i, j, shift, num;
4158 int sig_bit;
4159 png_uint_32 ig;
4161 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
4163 sig_bit = (int)png_ptr->sig_bit.red;
4165 if ((int)png_ptr->sig_bit.green > sig_bit)
4166 sig_bit = png_ptr->sig_bit.green;
4168 if ((int)png_ptr->sig_bit.blue > sig_bit)
4169 sig_bit = png_ptr->sig_bit.blue;
4171 else
4173 sig_bit = (int)png_ptr->sig_bit.gray;
4176 if (sig_bit > 0)
4177 shift = 16 - sig_bit;
4179 else
4180 shift = 0;
4182 if (png_ptr->transformations & PNG_16_TO_8)
4184 if (shift < (16 - PNG_MAX_GAMMA_8))
4185 shift = (16 - PNG_MAX_GAMMA_8);
4188 if (shift > 8)
4189 shift = 8;
4191 if (shift < 0)
4192 shift = 0;
4194 png_ptr->gamma_shift = (png_byte)shift;
4196 num = (1 << (8 - shift));
4198 if (png_ptr->screen_gamma > .000001)
4199 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4200 else
4201 g = 1.0;
4203 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
4204 (png_uint_32)(num * png_sizeof(png_uint_16p)));
4205 png_memset(png_ptr->gamma_16_table, 0, num * png_sizeof(png_uint_16p));
4207 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
4209 double fin, fout;
4210 png_uint_32 last, max;
4212 for (i = 0; i < num; i++)
4214 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4215 (png_uint_32)(256 * png_sizeof(png_uint_16)));
4218 g = 1.0 / g;
4219 last = 0;
4220 for (i = 0; i < 256; i++)
4222 fout = ((double)i + 0.5) / 256.0;
4223 fin = pow(fout, g);
4224 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
4225 while (last <= max)
4227 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4228 [(int)(last >> (8 - shift))] = (png_uint_16)(
4229 (png_uint_16)i | ((png_uint_16)i << 8));
4230 last++;
4233 while (last < ((png_uint_32)num << 8))
4235 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4236 [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
4237 last++;
4240 else
4242 for (i = 0; i < num; i++)
4244 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4245 (png_uint_32)(256 * png_sizeof(png_uint_16)));
4247 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
4249 for (j = 0; j < 256; j++)
4251 png_ptr->gamma_16_table[i][j] =
4252 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4253 65535.0, g) * 65535.0 + .5);
4258 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4259 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4260 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
4263 g = 1.0 / (png_ptr->gamma);
4265 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
4266 (png_uint_32)(num * png_sizeof(png_uint_16p )));
4267 png_memset(png_ptr->gamma_16_to_1, 0, num * png_sizeof(png_uint_16p));
4269 for (i = 0; i < num; i++)
4271 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
4272 (png_uint_32)(256 * png_sizeof(png_uint_16)));
4274 ig = (((png_uint_32)i *
4275 (png_uint_32)png_gamma_shift[shift]) >> 4);
4276 for (j = 0; j < 256; j++)
4278 png_ptr->gamma_16_to_1[i][j] =
4279 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4280 65535.0, g) * 65535.0 + .5);
4284 if (png_ptr->screen_gamma > 0.000001)
4285 g = 1.0 / png_ptr->screen_gamma;
4287 else
4288 g = png_ptr->gamma; /* Probably doing rgb_to_gray */
4290 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
4291 (png_uint_32)(num * png_sizeof(png_uint_16p)));
4292 png_memset(png_ptr->gamma_16_from_1, 0,
4293 num * png_sizeof(png_uint_16p));
4295 for (i = 0; i < num; i++)
4297 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
4298 (png_uint_32)(256 * png_sizeof(png_uint_16)));
4300 ig = (((png_uint_32)i *
4301 (png_uint_32)png_gamma_shift[shift]) >> 4);
4303 for (j = 0; j < 256; j++)
4305 png_ptr->gamma_16_from_1[i][j] =
4306 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4307 65535.0, g) * 65535.0 + .5);
4311 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4314 #endif
4315 /* To do: install integer version of png_build_gamma_table here */
4316 #endif
4318 #if defined(PNG_MNG_FEATURES_SUPPORTED)
4319 /* Undoes intrapixel differencing */
4320 void /* PRIVATE */
4321 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4323 png_debug(1, "in png_do_read_intrapixel");
4324 if (
4325 #if defined(PNG_USELESS_TESTS_SUPPORTED)
4326 row != NULL && row_info != NULL &&
4327 #endif
4328 (row_info->color_type & PNG_COLOR_MASK_COLOR))
4330 int bytes_per_pixel;
4331 png_uint_32 row_width = row_info->width;
4332 if (row_info->bit_depth == 8)
4334 png_bytep rp;
4335 png_uint_32 i;
4337 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4338 bytes_per_pixel = 3;
4340 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4341 bytes_per_pixel = 4;
4343 else
4344 return;
4346 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4348 *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
4349 *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
4352 else if (row_info->bit_depth == 16)
4354 png_bytep rp;
4355 png_uint_32 i;
4357 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4358 bytes_per_pixel = 6;
4360 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4361 bytes_per_pixel = 8;
4363 else
4364 return;
4366 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4368 png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
4369 png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
4370 png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
4371 png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL);
4372 png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL);
4373 *(rp ) = (png_byte)((red >> 8) & 0xff);
4374 *(rp+1) = (png_byte)(red & 0xff);
4375 *(rp+4) = (png_byte)((blue >> 8) & 0xff);
4376 *(rp+5) = (png_byte)(blue & 0xff);
4381 #endif /* PNG_MNG_FEATURES_SUPPORTED */
4382 #endif /* PNG_READ_SUPPORTED */