Adding upstream version 4.00~pre54+dfsg.
[syslinux-debian/hramrach.git] / com32 / lib / libpng / pngrtran.c
blobda9ef6e8e1d41ce48a2df1ce4d86eac1814150b3
2 /* pngrtran.c - transforms the data in a row for PNG readers
4 * libpng version 1.2.8 - December 3, 2004
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2004 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"
19 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
20 void PNGAPI
21 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
23 png_debug(1, "in png_set_crc_action\n");
24 /* Tell libpng how we react to CRC errors in critical chunks */
25 switch (crit_action)
27 case PNG_CRC_NO_CHANGE: /* leave setting as is */
28 break;
29 case PNG_CRC_WARN_USE: /* warn/use data */
30 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
31 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
32 break;
33 case PNG_CRC_QUIET_USE: /* quiet/use data */
34 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
35 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
36 PNG_FLAG_CRC_CRITICAL_IGNORE;
37 break;
38 case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */
39 png_warning(png_ptr, "Can't discard critical data on CRC error.");
40 case PNG_CRC_ERROR_QUIT: /* error/quit */
41 case PNG_CRC_DEFAULT:
42 default:
43 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
44 break;
47 switch (ancil_action)
49 case PNG_CRC_NO_CHANGE: /* leave setting as is */
50 break;
51 case PNG_CRC_WARN_USE: /* warn/use data */
52 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
53 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
54 break;
55 case PNG_CRC_QUIET_USE: /* quiet/use data */
56 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
57 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
58 PNG_FLAG_CRC_ANCILLARY_NOWARN;
59 break;
60 case PNG_CRC_ERROR_QUIT: /* error/quit */
61 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
62 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
63 break;
64 case PNG_CRC_WARN_DISCARD: /* warn/discard data */
65 case PNG_CRC_DEFAULT:
66 default:
67 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
68 break;
72 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
73 defined(PNG_FLOATING_POINT_SUPPORTED)
74 /* handle alpha and tRNS via a background color */
75 void PNGAPI
76 png_set_background(png_structp png_ptr,
77 png_color_16p background_color, int background_gamma_code,
78 int need_expand, double background_gamma)
80 png_debug(1, "in png_set_background\n");
81 if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
83 png_warning(png_ptr, "Application must supply a known background gamma");
84 return;
87 png_ptr->transformations |= PNG_BACKGROUND;
88 png_memcpy(&(png_ptr->background), background_color,
89 png_sizeof(png_color_16));
90 png_ptr->background_gamma = (float)background_gamma;
91 png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
92 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
94 /* Note: if need_expand is set and color_type is either RGB or RGB_ALPHA
95 * (in which case need_expand is superfluous anyway), the background color
96 * might actually be gray yet not be flagged as such. This is not a problem
97 * for the current code, which uses PNG_BACKGROUND_IS_GRAY only to
98 * decide when to do the png_do_gray_to_rgb() transformation.
100 if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
101 (!need_expand && background_color->red == background_color->green &&
102 background_color->red == background_color->blue))
103 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
105 #endif
107 #if defined(PNG_READ_16_TO_8_SUPPORTED)
108 /* strip 16 bit depth files to 8 bit depth */
109 void PNGAPI
110 png_set_strip_16(png_structp png_ptr)
112 png_debug(1, "in png_set_strip_16\n");
113 png_ptr->transformations |= PNG_16_TO_8;
115 #endif
117 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
118 void PNGAPI
119 png_set_strip_alpha(png_structp png_ptr)
121 png_debug(1, "in png_set_strip_alpha\n");
122 png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
124 #endif
126 #if defined(PNG_READ_DITHER_SUPPORTED)
127 /* Dither file to 8 bit. Supply a palette, the current number
128 * of elements in the palette, the maximum number of elements
129 * allowed, and a histogram if possible. If the current number
130 * of colors is greater then the maximum number, the palette will be
131 * modified to fit in the maximum number. "full_dither" indicates
132 * whether we need a dithering cube set up for RGB images, or if we
133 * simply are reducing the number of colors in a paletted image.
136 typedef struct png_dsort_struct
138 struct png_dsort_struct FAR * next;
139 png_byte left;
140 png_byte right;
141 } png_dsort;
142 typedef png_dsort FAR * png_dsortp;
143 typedef png_dsort FAR * FAR * png_dsortpp;
145 void PNGAPI
146 png_set_dither(png_structp png_ptr, png_colorp palette,
147 int num_palette, int maximum_colors, png_uint_16p histogram,
148 int full_dither)
150 png_debug(1, "in png_set_dither\n");
151 png_ptr->transformations |= PNG_DITHER;
153 if (!full_dither)
155 int i;
157 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
158 (png_uint_32)(num_palette * png_sizeof (png_byte)));
159 for (i = 0; i < num_palette; i++)
160 png_ptr->dither_index[i] = (png_byte)i;
163 if (num_palette > maximum_colors)
165 if (histogram != NULL)
167 /* This is easy enough, just throw out the least used colors.
168 Perhaps not the best solution, but good enough. */
170 int i;
172 /* initialize an array to sort colors */
173 png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
174 (png_uint_32)(num_palette * png_sizeof (png_byte)));
176 /* initialize the dither_sort array */
177 for (i = 0; i < num_palette; i++)
178 png_ptr->dither_sort[i] = (png_byte)i;
180 /* Find the least used palette entries by starting a
181 bubble sort, and running it until we have sorted
182 out enough colors. Note that we don't care about
183 sorting all the colors, just finding which are
184 least used. */
186 for (i = num_palette - 1; i >= maximum_colors; i--)
188 int done; /* to stop early if the list is pre-sorted */
189 int j;
191 done = 1;
192 for (j = 0; j < i; j++)
194 if (histogram[png_ptr->dither_sort[j]]
195 < histogram[png_ptr->dither_sort[j + 1]])
197 png_byte t;
199 t = png_ptr->dither_sort[j];
200 png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
201 png_ptr->dither_sort[j + 1] = t;
202 done = 0;
205 if (done)
206 break;
209 /* swap the palette around, and set up a table, if necessary */
210 if (full_dither)
212 int j = num_palette;
214 /* put all the useful colors within the max, but don't
215 move the others */
216 for (i = 0; i < maximum_colors; i++)
218 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
221 j--;
222 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
223 palette[i] = palette[j];
227 else
229 int j = num_palette;
231 /* move all the used colors inside the max limit, and
232 develop a translation table */
233 for (i = 0; i < maximum_colors; i++)
235 /* only move the colors we need to */
236 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
238 png_color tmp_color;
241 j--;
242 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
244 tmp_color = palette[j];
245 palette[j] = palette[i];
246 palette[i] = tmp_color;
247 /* indicate where the color went */
248 png_ptr->dither_index[j] = (png_byte)i;
249 png_ptr->dither_index[i] = (png_byte)j;
253 /* find closest color for those colors we are not using */
254 for (i = 0; i < num_palette; i++)
256 if ((int)png_ptr->dither_index[i] >= maximum_colors)
258 int min_d, k, min_k, d_index;
260 /* find the closest color to one we threw out */
261 d_index = png_ptr->dither_index[i];
262 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
263 for (k = 1, min_k = 0; k < maximum_colors; k++)
265 int d;
267 d = PNG_COLOR_DIST(palette[d_index], palette[k]);
269 if (d < min_d)
271 min_d = d;
272 min_k = k;
275 /* point to closest color */
276 png_ptr->dither_index[i] = (png_byte)min_k;
280 png_free(png_ptr, png_ptr->dither_sort);
281 png_ptr->dither_sort=NULL;
283 else
285 /* This is much harder to do simply (and quickly). Perhaps
286 we need to go through a median cut routine, but those
287 don't always behave themselves with only a few colors
288 as input. So we will just find the closest two colors,
289 and throw out one of them (chosen somewhat randomly).
290 [We don't understand this at all, so if someone wants to
291 work on improving it, be our guest - AED, GRP]
293 int i;
294 int max_d;
295 int num_new_palette;
296 png_dsortp t;
297 png_dsortpp hash;
299 t=NULL;
301 /* initialize palette index arrays */
302 png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
303 (png_uint_32)(num_palette * png_sizeof (png_byte)));
304 png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
305 (png_uint_32)(num_palette * png_sizeof (png_byte)));
307 /* initialize the sort array */
308 for (i = 0; i < num_palette; i++)
310 png_ptr->index_to_palette[i] = (png_byte)i;
311 png_ptr->palette_to_index[i] = (png_byte)i;
314 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
315 png_sizeof (png_dsortp)));
316 for (i = 0; i < 769; i++)
317 hash[i] = NULL;
318 /* png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */
320 num_new_palette = num_palette;
322 /* initial wild guess at how far apart the farthest pixel
323 pair we will be eliminating will be. Larger
324 numbers mean more areas will be allocated, Smaller
325 numbers run the risk of not saving enough data, and
326 having to do this all over again.
328 I have not done extensive checking on this number.
330 max_d = 96;
332 while (num_new_palette > maximum_colors)
334 for (i = 0; i < num_new_palette - 1; i++)
336 int j;
338 for (j = i + 1; j < num_new_palette; j++)
340 int d;
342 d = PNG_COLOR_DIST(palette[i], palette[j]);
344 if (d <= max_d)
347 t = (png_dsortp)png_malloc_warn(png_ptr,
348 (png_uint_32)(png_sizeof(png_dsort)));
349 if (t == NULL)
350 break;
351 t->next = hash[d];
352 t->left = (png_byte)i;
353 t->right = (png_byte)j;
354 hash[d] = t;
357 if (t == NULL)
358 break;
361 if (t != NULL)
362 for (i = 0; i <= max_d; i++)
364 if (hash[i] != NULL)
366 png_dsortp p;
368 for (p = hash[i]; p; p = p->next)
370 if ((int)png_ptr->index_to_palette[p->left]
371 < num_new_palette &&
372 (int)png_ptr->index_to_palette[p->right]
373 < num_new_palette)
375 int j, next_j;
377 if (num_new_palette & 0x01)
379 j = p->left;
380 next_j = p->right;
382 else
384 j = p->right;
385 next_j = p->left;
388 num_new_palette--;
389 palette[png_ptr->index_to_palette[j]]
390 = palette[num_new_palette];
391 if (!full_dither)
393 int k;
395 for (k = 0; k < num_palette; k++)
397 if (png_ptr->dither_index[k] ==
398 png_ptr->index_to_palette[j])
399 png_ptr->dither_index[k] =
400 png_ptr->index_to_palette[next_j];
401 if ((int)png_ptr->dither_index[k] ==
402 num_new_palette)
403 png_ptr->dither_index[k] =
404 png_ptr->index_to_palette[j];
408 png_ptr->index_to_palette[png_ptr->palette_to_index
409 [num_new_palette]] = png_ptr->index_to_palette[j];
410 png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
411 = png_ptr->palette_to_index[num_new_palette];
413 png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
414 png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
416 if (num_new_palette <= maximum_colors)
417 break;
419 if (num_new_palette <= maximum_colors)
420 break;
424 for (i = 0; i < 769; i++)
426 if (hash[i] != NULL)
428 png_dsortp p = hash[i];
429 while (p)
431 t = p->next;
432 png_free(png_ptr, p);
433 p = t;
436 hash[i] = 0;
438 max_d += 96;
440 png_free(png_ptr, hash);
441 png_free(png_ptr, png_ptr->palette_to_index);
442 png_free(png_ptr, png_ptr->index_to_palette);
443 png_ptr->palette_to_index=NULL;
444 png_ptr->index_to_palette=NULL;
446 num_palette = maximum_colors;
448 if (png_ptr->palette == NULL)
450 png_ptr->palette = palette;
452 png_ptr->num_palette = (png_uint_16)num_palette;
454 if (full_dither)
456 int i;
457 png_bytep distance;
458 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
459 PNG_DITHER_BLUE_BITS;
460 int num_red = (1 << PNG_DITHER_RED_BITS);
461 int num_green = (1 << PNG_DITHER_GREEN_BITS);
462 int num_blue = (1 << PNG_DITHER_BLUE_BITS);
463 png_size_t num_entries = ((png_size_t)1 << total_bits);
465 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
466 (png_uint_32)(num_entries * png_sizeof (png_byte)));
468 png_memset(png_ptr->palette_lookup, 0, num_entries *
469 png_sizeof (png_byte));
471 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
472 png_sizeof(png_byte)));
474 png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
476 for (i = 0; i < num_palette; i++)
478 int ir, ig, ib;
479 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
480 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
481 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
483 for (ir = 0; ir < num_red; ir++)
485 /* int dr = abs(ir - r); */
486 int dr = ((ir > r) ? ir - r : r - ir);
487 int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
489 for (ig = 0; ig < num_green; ig++)
491 /* int dg = abs(ig - g); */
492 int dg = ((ig > g) ? ig - g : g - ig);
493 int dt = dr + dg;
494 int dm = ((dr > dg) ? dr : dg);
495 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
497 for (ib = 0; ib < num_blue; ib++)
499 int d_index = index_g | ib;
500 /* int db = abs(ib - b); */
501 int db = ((ib > b) ? ib - b : b - ib);
502 int dmax = ((dm > db) ? dm : db);
503 int d = dmax + dt + db;
505 if (d < (int)distance[d_index])
507 distance[d_index] = (png_byte)d;
508 png_ptr->palette_lookup[d_index] = (png_byte)i;
515 png_free(png_ptr, distance);
518 #endif
520 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
521 /* Transform the image from the file_gamma to the screen_gamma. We
522 * only do transformations on images where the file_gamma and screen_gamma
523 * are not close reciprocals, otherwise it slows things down slightly, and
524 * also needlessly introduces small errors.
526 * We will turn off gamma transformation later if no semitransparent entries
527 * are present in the tRNS array for palette images. We can't do it here
528 * because we don't necessarily have the tRNS chunk yet.
530 void PNGAPI
531 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
533 png_debug(1, "in png_set_gamma\n");
534 if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
535 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
536 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
537 png_ptr->transformations |= PNG_GAMMA;
538 png_ptr->gamma = (float)file_gamma;
539 png_ptr->screen_gamma = (float)scrn_gamma;
541 #endif
543 #if defined(PNG_READ_EXPAND_SUPPORTED)
544 /* Expand paletted images to RGB, expand grayscale images of
545 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
546 * to alpha channels.
548 void PNGAPI
549 png_set_expand(png_structp png_ptr)
551 png_debug(1, "in png_set_expand\n");
552 png_ptr->transformations |= PNG_EXPAND;
555 /* GRR 19990627: the following three functions currently are identical
556 * to png_set_expand(). However, it is entirely reasonable that someone
557 * might wish to expand an indexed image to RGB but *not* expand a single,
558 * fully transparent palette entry to a full alpha channel--perhaps instead
559 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
560 * the transparent color with a particular RGB value, or drop tRNS entirely.
561 * IOW, a future version of the library may make the transformations flag
562 * a bit more fine-grained, with separate bits for each of these three
563 * functions.
565 * More to the point, these functions make it obvious what libpng will be
566 * doing, whereas "expand" can (and does) mean any number of things.
569 /* Expand paletted images to RGB. */
570 void PNGAPI
571 png_set_palette_to_rgb(png_structp png_ptr)
573 png_debug(1, "in png_set_expand\n");
574 png_ptr->transformations |= PNG_EXPAND;
577 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
578 void PNGAPI
579 png_set_gray_1_2_4_to_8(png_structp png_ptr)
581 png_debug(1, "in png_set_expand\n");
582 png_ptr->transformations |= PNG_EXPAND;
585 /* Expand tRNS chunks to alpha channels. */
586 void PNGAPI
587 png_set_tRNS_to_alpha(png_structp png_ptr)
589 png_debug(1, "in png_set_expand\n");
590 png_ptr->transformations |= PNG_EXPAND;
592 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
594 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
595 void PNGAPI
596 png_set_gray_to_rgb(png_structp png_ptr)
598 png_debug(1, "in png_set_gray_to_rgb\n");
599 png_ptr->transformations |= PNG_GRAY_TO_RGB;
601 #endif
603 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
604 #if defined(PNG_FLOATING_POINT_SUPPORTED)
605 /* Convert a RGB image to a grayscale of the same width. This allows us,
606 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
609 void PNGAPI
610 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
611 double green)
613 int red_fixed = (int)((float)red*100000.0 + 0.5);
614 int green_fixed = (int)((float)green*100000.0 + 0.5);
615 png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
617 #endif
619 void PNGAPI
620 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
621 png_fixed_point red, png_fixed_point green)
623 png_debug(1, "in png_set_rgb_to_gray\n");
624 switch(error_action)
626 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
627 break;
628 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
629 break;
630 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
632 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
633 #if defined(PNG_READ_EXPAND_SUPPORTED)
634 png_ptr->transformations |= PNG_EXPAND;
635 #else
637 png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
638 png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
640 #endif
642 png_uint_16 red_int, green_int;
643 if(red < 0 || green < 0)
645 red_int = 6968; /* .212671 * 32768 + .5 */
646 green_int = 23434; /* .715160 * 32768 + .5 */
648 else if(red + green < 100000L)
650 red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
651 green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
653 else
655 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
656 red_int = 6968;
657 green_int = 23434;
659 png_ptr->rgb_to_gray_red_coeff = red_int;
660 png_ptr->rgb_to_gray_green_coeff = green_int;
661 png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int);
664 #endif
666 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
667 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
668 defined(PNG_LEGACY_SUPPORTED)
669 void PNGAPI
670 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
671 read_user_transform_fn)
673 png_debug(1, "in png_set_read_user_transform_fn\n");
674 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
675 png_ptr->transformations |= PNG_USER_TRANSFORM;
676 png_ptr->read_user_transform_fn = read_user_transform_fn;
677 #endif
678 #ifdef PNG_LEGACY_SUPPORTED
679 if(read_user_transform_fn)
680 png_warning(png_ptr,
681 "This version of libpng does not support user transforms");
682 #endif
684 #endif
686 /* Initialize everything needed for the read. This includes modifying
687 * the palette.
689 void /* PRIVATE */
690 png_init_read_transformations(png_structp png_ptr)
692 png_debug(1, "in png_init_read_transformations\n");
693 #if defined(PNG_USELESS_TESTS_SUPPORTED)
694 if(png_ptr != NULL)
695 #endif
697 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
698 || defined(PNG_READ_GAMMA_SUPPORTED)
699 int color_type = png_ptr->color_type;
700 #endif
702 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
703 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
704 (png_ptr->transformations & PNG_EXPAND))
706 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
708 /* expand background chunk. */
709 switch (png_ptr->bit_depth)
711 case 1:
712 png_ptr->background.gray *= (png_uint_16)0xff;
713 png_ptr->background.red = png_ptr->background.green
714 = png_ptr->background.blue = png_ptr->background.gray;
715 break;
716 case 2:
717 png_ptr->background.gray *= (png_uint_16)0x55;
718 png_ptr->background.red = png_ptr->background.green
719 = png_ptr->background.blue = png_ptr->background.gray;
720 break;
721 case 4:
722 png_ptr->background.gray *= (png_uint_16)0x11;
723 png_ptr->background.red = png_ptr->background.green
724 = png_ptr->background.blue = png_ptr->background.gray;
725 break;
726 case 8:
727 case 16:
728 png_ptr->background.red = png_ptr->background.green
729 = png_ptr->background.blue = png_ptr->background.gray;
730 break;
733 else if (color_type == PNG_COLOR_TYPE_PALETTE)
735 png_ptr->background.red =
736 png_ptr->palette[png_ptr->background.index].red;
737 png_ptr->background.green =
738 png_ptr->palette[png_ptr->background.index].green;
739 png_ptr->background.blue =
740 png_ptr->palette[png_ptr->background.index].blue;
742 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
743 if (png_ptr->transformations & PNG_INVERT_ALPHA)
745 #if defined(PNG_READ_EXPAND_SUPPORTED)
746 if (!(png_ptr->transformations & PNG_EXPAND))
747 #endif
749 /* invert the alpha channel (in tRNS) unless the pixels are
750 going to be expanded, in which case leave it for later */
751 int i,istop;
752 istop=(int)png_ptr->num_trans;
753 for (i=0; i<istop; i++)
754 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
757 #endif
761 #endif
763 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
764 png_ptr->background_1 = png_ptr->background;
765 #endif
766 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
768 if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
769 && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
770 < PNG_GAMMA_THRESHOLD))
772 int i,k;
773 k=0;
774 for (i=0; i<png_ptr->num_trans; i++)
776 if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
777 k=1; /* partial transparency is present */
779 if (k == 0)
780 png_ptr->transformations &= (~PNG_GAMMA);
783 if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
785 png_build_gamma_table(png_ptr);
786 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
787 if (png_ptr->transformations & PNG_BACKGROUND)
789 if (color_type == PNG_COLOR_TYPE_PALETTE)
791 /* could skip if no transparency and
793 png_color back, back_1;
794 png_colorp palette = png_ptr->palette;
795 int num_palette = png_ptr->num_palette;
796 int i;
797 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
799 back.red = png_ptr->gamma_table[png_ptr->background.red];
800 back.green = png_ptr->gamma_table[png_ptr->background.green];
801 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
803 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
804 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
805 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
807 else
809 double g, gs;
811 switch (png_ptr->background_gamma_type)
813 case PNG_BACKGROUND_GAMMA_SCREEN:
814 g = (png_ptr->screen_gamma);
815 gs = 1.0;
816 break;
817 case PNG_BACKGROUND_GAMMA_FILE:
818 g = 1.0 / (png_ptr->gamma);
819 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
820 break;
821 case PNG_BACKGROUND_GAMMA_UNIQUE:
822 g = 1.0 / (png_ptr->background_gamma);
823 gs = 1.0 / (png_ptr->background_gamma *
824 png_ptr->screen_gamma);
825 break;
826 default:
827 g = 1.0; /* back_1 */
828 gs = 1.0; /* back */
831 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
833 back.red = (png_byte)png_ptr->background.red;
834 back.green = (png_byte)png_ptr->background.green;
835 back.blue = (png_byte)png_ptr->background.blue;
837 else
839 back.red = (png_byte)(pow(
840 (double)png_ptr->background.red/255, gs) * 255.0 + .5);
841 back.green = (png_byte)(pow(
842 (double)png_ptr->background.green/255, gs) * 255.0 + .5);
843 back.blue = (png_byte)(pow(
844 (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
847 back_1.red = (png_byte)(pow(
848 (double)png_ptr->background.red/255, g) * 255.0 + .5);
849 back_1.green = (png_byte)(pow(
850 (double)png_ptr->background.green/255, g) * 255.0 + .5);
851 back_1.blue = (png_byte)(pow(
852 (double)png_ptr->background.blue/255, g) * 255.0 + .5);
854 for (i = 0; i < num_palette; i++)
856 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
858 if (png_ptr->trans[i] == 0)
860 palette[i] = back;
862 else /* if (png_ptr->trans[i] != 0xff) */
864 png_byte v, w;
866 v = png_ptr->gamma_to_1[palette[i].red];
867 png_composite(w, v, png_ptr->trans[i], back_1.red);
868 palette[i].red = png_ptr->gamma_from_1[w];
870 v = png_ptr->gamma_to_1[palette[i].green];
871 png_composite(w, v, png_ptr->trans[i], back_1.green);
872 palette[i].green = png_ptr->gamma_from_1[w];
874 v = png_ptr->gamma_to_1[palette[i].blue];
875 png_composite(w, v, png_ptr->trans[i], back_1.blue);
876 palette[i].blue = png_ptr->gamma_from_1[w];
879 else
881 palette[i].red = png_ptr->gamma_table[palette[i].red];
882 palette[i].green = png_ptr->gamma_table[palette[i].green];
883 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
887 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
888 else
889 /* color_type != PNG_COLOR_TYPE_PALETTE */
891 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
892 double g = 1.0;
893 double gs = 1.0;
895 switch (png_ptr->background_gamma_type)
897 case PNG_BACKGROUND_GAMMA_SCREEN:
898 g = (png_ptr->screen_gamma);
899 gs = 1.0;
900 break;
901 case PNG_BACKGROUND_GAMMA_FILE:
902 g = 1.0 / (png_ptr->gamma);
903 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
904 break;
905 case PNG_BACKGROUND_GAMMA_UNIQUE:
906 g = 1.0 / (png_ptr->background_gamma);
907 gs = 1.0 / (png_ptr->background_gamma *
908 png_ptr->screen_gamma);
909 break;
912 png_ptr->background_1.gray = (png_uint_16)(pow(
913 (double)png_ptr->background.gray / m, g) * m + .5);
914 png_ptr->background.gray = (png_uint_16)(pow(
915 (double)png_ptr->background.gray / m, gs) * m + .5);
917 if ((png_ptr->background.red != png_ptr->background.green) ||
918 (png_ptr->background.red != png_ptr->background.blue) ||
919 (png_ptr->background.red != png_ptr->background.gray))
921 /* RGB or RGBA with color background */
922 png_ptr->background_1.red = (png_uint_16)(pow(
923 (double)png_ptr->background.red / m, g) * m + .5);
924 png_ptr->background_1.green = (png_uint_16)(pow(
925 (double)png_ptr->background.green / m, g) * m + .5);
926 png_ptr->background_1.blue = (png_uint_16)(pow(
927 (double)png_ptr->background.blue / m, g) * m + .5);
928 png_ptr->background.red = (png_uint_16)(pow(
929 (double)png_ptr->background.red / m, gs) * m + .5);
930 png_ptr->background.green = (png_uint_16)(pow(
931 (double)png_ptr->background.green / m, gs) * m + .5);
932 png_ptr->background.blue = (png_uint_16)(pow(
933 (double)png_ptr->background.blue / m, gs) * m + .5);
935 else
937 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
938 png_ptr->background_1.red = png_ptr->background_1.green
939 = png_ptr->background_1.blue = png_ptr->background_1.gray;
940 png_ptr->background.red = png_ptr->background.green
941 = png_ptr->background.blue = png_ptr->background.gray;
945 else
946 /* transformation does not include PNG_BACKGROUND */
947 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
948 if (color_type == PNG_COLOR_TYPE_PALETTE)
950 png_colorp palette = png_ptr->palette;
951 int num_palette = png_ptr->num_palette;
952 int i;
954 for (i = 0; i < num_palette; i++)
956 palette[i].red = png_ptr->gamma_table[palette[i].red];
957 palette[i].green = png_ptr->gamma_table[palette[i].green];
958 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
962 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
963 else
964 #endif
965 #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
966 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
967 /* No GAMMA transformation */
968 if ((png_ptr->transformations & PNG_BACKGROUND) &&
969 (color_type == PNG_COLOR_TYPE_PALETTE))
971 int i;
972 int istop = (int)png_ptr->num_trans;
973 png_color back;
974 png_colorp palette = png_ptr->palette;
976 back.red = (png_byte)png_ptr->background.red;
977 back.green = (png_byte)png_ptr->background.green;
978 back.blue = (png_byte)png_ptr->background.blue;
980 for (i = 0; i < istop; i++)
982 if (png_ptr->trans[i] == 0)
984 palette[i] = back;
986 else if (png_ptr->trans[i] != 0xff)
988 /* The png_composite() macro is defined in png.h */
989 png_composite(palette[i].red, palette[i].red,
990 png_ptr->trans[i], back.red);
991 png_composite(palette[i].green, palette[i].green,
992 png_ptr->trans[i], back.green);
993 png_composite(palette[i].blue, palette[i].blue,
994 png_ptr->trans[i], back.blue);
998 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
1000 #if defined(PNG_READ_SHIFT_SUPPORTED)
1001 if ((png_ptr->transformations & PNG_SHIFT) &&
1002 (color_type == PNG_COLOR_TYPE_PALETTE))
1004 png_uint_16 i;
1005 png_uint_16 istop = png_ptr->num_palette;
1006 int sr = 8 - png_ptr->sig_bit.red;
1007 int sg = 8 - png_ptr->sig_bit.green;
1008 int sb = 8 - png_ptr->sig_bit.blue;
1010 if (sr < 0 || sr > 8)
1011 sr = 0;
1012 if (sg < 0 || sg > 8)
1013 sg = 0;
1014 if (sb < 0 || sb > 8)
1015 sb = 0;
1016 for (i = 0; i < istop; i++)
1018 png_ptr->palette[i].red >>= sr;
1019 png_ptr->palette[i].green >>= sg;
1020 png_ptr->palette[i].blue >>= sb;
1023 #endif /* PNG_READ_SHIFT_SUPPORTED */
1025 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1026 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1027 if(png_ptr)
1028 return;
1029 #endif
1032 /* Modify the info structure to reflect the transformations. The
1033 * info should be updated so a PNG file could be written with it,
1034 * assuming the transformations result in valid PNG data.
1036 void /* PRIVATE */
1037 png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
1039 png_debug(1, "in png_read_transform_info\n");
1040 #if defined(PNG_READ_EXPAND_SUPPORTED)
1041 if (png_ptr->transformations & PNG_EXPAND)
1043 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1045 if (png_ptr->num_trans)
1046 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1047 else
1048 info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1049 info_ptr->bit_depth = 8;
1050 info_ptr->num_trans = 0;
1052 else
1054 if (png_ptr->num_trans)
1055 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1056 if (info_ptr->bit_depth < 8)
1057 info_ptr->bit_depth = 8;
1058 info_ptr->num_trans = 0;
1061 #endif
1063 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1064 if (png_ptr->transformations & PNG_BACKGROUND)
1066 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1067 info_ptr->num_trans = 0;
1068 info_ptr->background = png_ptr->background;
1070 #endif
1072 #if defined(PNG_READ_GAMMA_SUPPORTED)
1073 if (png_ptr->transformations & PNG_GAMMA)
1075 #ifdef PNG_FLOATING_POINT_SUPPORTED
1076 info_ptr->gamma = png_ptr->gamma;
1077 #endif
1078 #ifdef PNG_FIXED_POINT_SUPPORTED
1079 info_ptr->int_gamma = png_ptr->int_gamma;
1080 #endif
1082 #endif
1084 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1085 if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
1086 info_ptr->bit_depth = 8;
1087 #endif
1089 #if defined(PNG_READ_DITHER_SUPPORTED)
1090 if (png_ptr->transformations & PNG_DITHER)
1092 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1093 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1094 png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1096 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1099 #endif
1101 #if defined(PNG_READ_PACK_SUPPORTED)
1102 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
1103 info_ptr->bit_depth = 8;
1104 #endif
1106 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1107 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1108 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1109 #endif
1111 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1112 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1113 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1114 #endif
1116 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1117 info_ptr->channels = 1;
1118 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1119 info_ptr->channels = 3;
1120 else
1121 info_ptr->channels = 1;
1123 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1124 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1125 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1126 #endif
1128 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1129 info_ptr->channels++;
1131 #if defined(PNG_READ_FILLER_SUPPORTED)
1132 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
1133 if ((png_ptr->transformations & PNG_FILLER) &&
1134 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1135 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1137 info_ptr->channels++;
1138 /* if adding a true alpha channel not just filler */
1139 #if !defined(PNG_1_0_X)
1140 if (png_ptr->transformations & PNG_ADD_ALPHA)
1141 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1142 #endif
1144 #endif
1146 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1147 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1148 if(png_ptr->transformations & PNG_USER_TRANSFORM)
1150 if(info_ptr->bit_depth < png_ptr->user_transform_depth)
1151 info_ptr->bit_depth = png_ptr->user_transform_depth;
1152 if(info_ptr->channels < png_ptr->user_transform_channels)
1153 info_ptr->channels = png_ptr->user_transform_channels;
1155 #endif
1157 info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1158 info_ptr->bit_depth);
1160 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width);
1162 #if !defined(PNG_READ_EXPAND_SUPPORTED)
1163 if(png_ptr)
1164 return;
1165 #endif
1168 /* Transform the row. The order of transformations is significant,
1169 * and is very touchy. If you add a transformation, take care to
1170 * decide how it fits in with the other transformations here.
1172 void /* PRIVATE */
1173 png_do_read_transformations(png_structp png_ptr)
1175 png_debug(1, "in png_do_read_transformations\n");
1176 #if !defined(PNG_USELESS_TESTS_SUPPORTED)
1177 if (png_ptr->row_buf == NULL)
1179 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1180 char msg[50];
1182 sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
1183 png_ptr->pass);
1184 png_error(png_ptr, msg);
1185 #else
1186 png_error(png_ptr, "NULL row buffer");
1187 #endif
1189 #endif
1191 #if defined(PNG_READ_EXPAND_SUPPORTED)
1192 if (png_ptr->transformations & PNG_EXPAND)
1194 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1196 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1197 png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1199 else
1201 if (png_ptr->num_trans)
1202 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1203 &(png_ptr->trans_values));
1204 else
1205 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1206 NULL);
1209 #endif
1211 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1212 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1213 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1214 PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
1215 #endif
1217 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1218 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1220 int rgb_error =
1221 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1222 if(rgb_error)
1224 png_ptr->rgb_to_gray_status=1;
1225 if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
1226 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1227 if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
1228 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1231 #endif
1234 From Andreas Dilger e-mail to png-implement, 26 March 1998:
1236 In most cases, the "simple transparency" should be done prior to doing
1237 gray-to-RGB, or you will have to test 3x as many bytes to check if a
1238 pixel is transparent. You would also need to make sure that the
1239 transparency information is upgraded to RGB.
1241 To summarize, the current flow is:
1242 - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1243 with background "in place" if transparent,
1244 convert to RGB if necessary
1245 - Gray + alpha -> composite with gray background and remove alpha bytes,
1246 convert to RGB if necessary
1248 To support RGB backgrounds for gray images we need:
1249 - Gray + simple transparency -> convert to RGB + simple transparency, compare
1250 3 or 6 bytes and composite with background
1251 "in place" if transparent (3x compare/pixel
1252 compared to doing composite with gray bkgrnd)
1253 - Gray + alpha -> convert to RGB + alpha, composite with background and
1254 remove alpha bytes (3x float operations/pixel
1255 compared with composite on gray background)
1257 Greg's change will do this. The reason it wasn't done before is for
1258 performance, as this increases the per-pixel operations. If we would check
1259 in advance if the background was gray or RGB, and position the gray-to-RGB
1260 transform appropriately, then it would save a lot of work/time.
1263 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1264 /* if gray -> RGB, do so now only if background is non-gray; else do later
1265 * for performance reasons */
1266 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1267 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1268 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1269 #endif
1271 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1272 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1273 ((png_ptr->num_trans != 0 ) ||
1274 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
1275 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1276 &(png_ptr->trans_values), &(png_ptr->background)
1277 #if defined(PNG_READ_GAMMA_SUPPORTED)
1278 , &(png_ptr->background_1),
1279 png_ptr->gamma_table, png_ptr->gamma_from_1,
1280 png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1281 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1282 png_ptr->gamma_shift
1283 #endif
1285 #endif
1287 #if defined(PNG_READ_GAMMA_SUPPORTED)
1288 if ((png_ptr->transformations & PNG_GAMMA) &&
1289 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1290 !((png_ptr->transformations & PNG_BACKGROUND) &&
1291 ((png_ptr->num_trans != 0) ||
1292 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1293 #endif
1294 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
1295 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1296 png_ptr->gamma_table, png_ptr->gamma_16_table,
1297 png_ptr->gamma_shift);
1298 #endif
1300 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1301 if (png_ptr->transformations & PNG_16_TO_8)
1302 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
1303 #endif
1305 #if defined(PNG_READ_DITHER_SUPPORTED)
1306 if (png_ptr->transformations & PNG_DITHER)
1308 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1309 png_ptr->palette_lookup, png_ptr->dither_index);
1310 if(png_ptr->row_info.rowbytes == (png_uint_32)0)
1311 png_error(png_ptr, "png_do_dither returned rowbytes=0");
1313 #endif
1315 #if defined(PNG_READ_INVERT_SUPPORTED)
1316 if (png_ptr->transformations & PNG_INVERT_MONO)
1317 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
1318 #endif
1320 #if defined(PNG_READ_SHIFT_SUPPORTED)
1321 if (png_ptr->transformations & PNG_SHIFT)
1322 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1323 &(png_ptr->shift));
1324 #endif
1326 #if defined(PNG_READ_PACK_SUPPORTED)
1327 if (png_ptr->transformations & PNG_PACK)
1328 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
1329 #endif
1331 #if defined(PNG_READ_BGR_SUPPORTED)
1332 if (png_ptr->transformations & PNG_BGR)
1333 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
1334 #endif
1336 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
1337 if (png_ptr->transformations & PNG_PACKSWAP)
1338 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1339 #endif
1341 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1342 /* if gray -> RGB, do so now only if we did not do so above */
1343 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1344 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1345 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1346 #endif
1348 #if defined(PNG_READ_FILLER_SUPPORTED)
1349 if (png_ptr->transformations & PNG_FILLER)
1350 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1351 (png_uint_32)png_ptr->filler, png_ptr->flags);
1352 #endif
1354 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1355 if (png_ptr->transformations & PNG_INVERT_ALPHA)
1356 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1357 #endif
1359 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1360 if (png_ptr->transformations & PNG_SWAP_ALPHA)
1361 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1362 #endif
1364 #if defined(PNG_READ_SWAP_SUPPORTED)
1365 if (png_ptr->transformations & PNG_SWAP_BYTES)
1366 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1367 #endif
1369 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1370 if (png_ptr->transformations & PNG_USER_TRANSFORM)
1372 if(png_ptr->read_user_transform_fn != NULL)
1373 (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1374 (png_ptr, /* png_ptr */
1375 &(png_ptr->row_info), /* row_info: */
1376 /* png_uint_32 width; width of row */
1377 /* png_uint_32 rowbytes; number of bytes in row */
1378 /* png_byte color_type; color type of pixels */
1379 /* png_byte bit_depth; bit depth of samples */
1380 /* png_byte channels; number of channels (1-4) */
1381 /* png_byte pixel_depth; bits per pixel (depth*channels) */
1382 png_ptr->row_buf + 1); /* start of pixel data for row */
1383 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
1384 if(png_ptr->user_transform_depth)
1385 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1386 if(png_ptr->user_transform_channels)
1387 png_ptr->row_info.channels = png_ptr->user_transform_channels;
1388 #endif
1389 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1390 png_ptr->row_info.channels);
1391 png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
1392 png_ptr->row_info.width);
1394 #endif
1398 #if defined(PNG_READ_PACK_SUPPORTED)
1399 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1400 * without changing the actual values. Thus, if you had a row with
1401 * a bit depth of 1, you would end up with bytes that only contained
1402 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1403 * png_do_shift() after this.
1405 void /* PRIVATE */
1406 png_do_unpack(png_row_infop row_info, png_bytep row)
1408 png_debug(1, "in png_do_unpack\n");
1409 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1410 if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1411 #else
1412 if (row_info->bit_depth < 8)
1413 #endif
1415 png_uint_32 i;
1416 png_uint_32 row_width=row_info->width;
1418 switch (row_info->bit_depth)
1420 case 1:
1422 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1423 png_bytep dp = row + (png_size_t)row_width - 1;
1424 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
1425 for (i = 0; i < row_width; i++)
1427 *dp = (png_byte)((*sp >> shift) & 0x01);
1428 if (shift == 7)
1430 shift = 0;
1431 sp--;
1433 else
1434 shift++;
1436 dp--;
1438 break;
1440 case 2:
1443 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1444 png_bytep dp = row + (png_size_t)row_width - 1;
1445 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
1446 for (i = 0; i < row_width; i++)
1448 *dp = (png_byte)((*sp >> shift) & 0x03);
1449 if (shift == 6)
1451 shift = 0;
1452 sp--;
1454 else
1455 shift += 2;
1457 dp--;
1459 break;
1461 case 4:
1463 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1464 png_bytep dp = row + (png_size_t)row_width - 1;
1465 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
1466 for (i = 0; i < row_width; i++)
1468 *dp = (png_byte)((*sp >> shift) & 0x0f);
1469 if (shift == 4)
1471 shift = 0;
1472 sp--;
1474 else
1475 shift = 4;
1477 dp--;
1479 break;
1482 row_info->bit_depth = 8;
1483 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1484 row_info->rowbytes = row_width * row_info->channels;
1487 #endif
1489 #if defined(PNG_READ_SHIFT_SUPPORTED)
1490 /* Reverse the effects of png_do_shift. This routine merely shifts the
1491 * pixels back to their significant bits values. Thus, if you have
1492 * a row of bit depth 8, but only 5 are significant, this will shift
1493 * the values back to 0 through 31.
1495 void /* PRIVATE */
1496 png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
1498 png_debug(1, "in png_do_unshift\n");
1499 if (
1500 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1501 row != NULL && row_info != NULL && sig_bits != NULL &&
1502 #endif
1503 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
1505 int shift[4];
1506 int channels = 0;
1507 int c;
1508 png_uint_16 value = 0;
1509 png_uint_32 row_width = row_info->width;
1511 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1513 shift[channels++] = row_info->bit_depth - sig_bits->red;
1514 shift[channels++] = row_info->bit_depth - sig_bits->green;
1515 shift[channels++] = row_info->bit_depth - sig_bits->blue;
1517 else
1519 shift[channels++] = row_info->bit_depth - sig_bits->gray;
1521 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1523 shift[channels++] = row_info->bit_depth - sig_bits->alpha;
1526 for (c = 0; c < channels; c++)
1528 if (shift[c] <= 0)
1529 shift[c] = 0;
1530 else
1531 value = 1;
1534 if (!value)
1535 return;
1537 switch (row_info->bit_depth)
1539 case 2:
1541 png_bytep bp;
1542 png_uint_32 i;
1543 png_uint_32 istop = row_info->rowbytes;
1545 for (bp = row, i = 0; i < istop; i++)
1547 *bp >>= 1;
1548 *bp++ &= 0x55;
1550 break;
1552 case 4:
1554 png_bytep bp = row;
1555 png_uint_32 i;
1556 png_uint_32 istop = row_info->rowbytes;
1557 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1558 (png_byte)((int)0xf >> shift[0]));
1560 for (i = 0; i < istop; i++)
1562 *bp >>= shift[0];
1563 *bp++ &= mask;
1565 break;
1567 case 8:
1569 png_bytep bp = row;
1570 png_uint_32 i;
1571 png_uint_32 istop = row_width * channels;
1573 for (i = 0; i < istop; i++)
1575 *bp++ >>= shift[i%channels];
1577 break;
1579 case 16:
1581 png_bytep bp = row;
1582 png_uint_32 i;
1583 png_uint_32 istop = channels * row_width;
1585 for (i = 0; i < istop; i++)
1587 value = (png_uint_16)((*bp << 8) + *(bp + 1));
1588 value >>= shift[i%channels];
1589 *bp++ = (png_byte)(value >> 8);
1590 *bp++ = (png_byte)(value & 0xff);
1592 break;
1597 #endif
1599 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1600 /* chop rows of bit depth 16 down to 8 */
1601 void /* PRIVATE */
1602 png_do_chop(png_row_infop row_info, png_bytep row)
1604 png_debug(1, "in png_do_chop\n");
1605 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1606 if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1607 #else
1608 if (row_info->bit_depth == 16)
1609 #endif
1611 png_bytep sp = row;
1612 png_bytep dp = row;
1613 png_uint_32 i;
1614 png_uint_32 istop = row_info->width * row_info->channels;
1616 for (i = 0; i<istop; i++, sp += 2, dp++)
1618 #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
1619 /* This does a more accurate scaling of the 16-bit color
1620 * value, rather than a simple low-byte truncation.
1622 * What the ideal calculation should be:
1623 * *dp = (((((png_uint_32)(*sp) << 8) |
1624 * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1626 * GRR: no, I think this is what it really should be:
1627 * *dp = (((((png_uint_32)(*sp) << 8) |
1628 * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1630 * GRR: here's the exact calculation with shifts:
1631 * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1632 * *dp = (temp - (temp >> 8)) >> 8;
1634 * Approximate calculation with shift/add instead of multiply/divide:
1635 * *dp = ((((png_uint_32)(*sp) << 8) |
1636 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1638 * What we actually do to avoid extra shifting and conversion:
1641 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1642 #else
1643 /* Simply discard the low order byte */
1644 *dp = *sp;
1645 #endif
1647 row_info->bit_depth = 8;
1648 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1649 row_info->rowbytes = row_info->width * row_info->channels;
1652 #endif
1654 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1655 void /* PRIVATE */
1656 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1658 png_debug(1, "in png_do_read_swap_alpha\n");
1659 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1660 if (row != NULL && row_info != NULL)
1661 #endif
1663 png_uint_32 row_width = row_info->width;
1664 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1666 /* This converts from RGBA to ARGB */
1667 if (row_info->bit_depth == 8)
1669 png_bytep sp = row + row_info->rowbytes;
1670 png_bytep dp = sp;
1671 png_byte save;
1672 png_uint_32 i;
1674 for (i = 0; i < row_width; i++)
1676 save = *(--sp);
1677 *(--dp) = *(--sp);
1678 *(--dp) = *(--sp);
1679 *(--dp) = *(--sp);
1680 *(--dp) = save;
1683 /* This converts from RRGGBBAA to AARRGGBB */
1684 else
1686 png_bytep sp = row + row_info->rowbytes;
1687 png_bytep dp = sp;
1688 png_byte save[2];
1689 png_uint_32 i;
1691 for (i = 0; i < row_width; i++)
1693 save[0] = *(--sp);
1694 save[1] = *(--sp);
1695 *(--dp) = *(--sp);
1696 *(--dp) = *(--sp);
1697 *(--dp) = *(--sp);
1698 *(--dp) = *(--sp);
1699 *(--dp) = *(--sp);
1700 *(--dp) = *(--sp);
1701 *(--dp) = save[0];
1702 *(--dp) = save[1];
1706 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1708 /* This converts from GA to AG */
1709 if (row_info->bit_depth == 8)
1711 png_bytep sp = row + row_info->rowbytes;
1712 png_bytep dp = sp;
1713 png_byte save;
1714 png_uint_32 i;
1716 for (i = 0; i < row_width; i++)
1718 save = *(--sp);
1719 *(--dp) = *(--sp);
1720 *(--dp) = save;
1723 /* This converts from GGAA to AAGG */
1724 else
1726 png_bytep sp = row + row_info->rowbytes;
1727 png_bytep dp = sp;
1728 png_byte save[2];
1729 png_uint_32 i;
1731 for (i = 0; i < row_width; i++)
1733 save[0] = *(--sp);
1734 save[1] = *(--sp);
1735 *(--dp) = *(--sp);
1736 *(--dp) = *(--sp);
1737 *(--dp) = save[0];
1738 *(--dp) = save[1];
1744 #endif
1746 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1747 void /* PRIVATE */
1748 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1750 png_debug(1, "in png_do_read_invert_alpha\n");
1751 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1752 if (row != NULL && row_info != NULL)
1753 #endif
1755 png_uint_32 row_width = row_info->width;
1756 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1758 /* This inverts the alpha channel in RGBA */
1759 if (row_info->bit_depth == 8)
1761 png_bytep sp = row + row_info->rowbytes;
1762 png_bytep dp = sp;
1763 png_uint_32 i;
1765 for (i = 0; i < row_width; i++)
1767 *(--dp) = (png_byte)(255 - *(--sp));
1769 /* This does nothing:
1770 *(--dp) = *(--sp);
1771 *(--dp) = *(--sp);
1772 *(--dp) = *(--sp);
1773 We can replace it with:
1775 sp-=3;
1776 dp=sp;
1779 /* This inverts the alpha channel in RRGGBBAA */
1780 else
1782 png_bytep sp = row + row_info->rowbytes;
1783 png_bytep dp = sp;
1784 png_uint_32 i;
1786 for (i = 0; i < row_width; i++)
1788 *(--dp) = (png_byte)(255 - *(--sp));
1789 *(--dp) = (png_byte)(255 - *(--sp));
1791 /* This does nothing:
1792 *(--dp) = *(--sp);
1793 *(--dp) = *(--sp);
1794 *(--dp) = *(--sp);
1795 *(--dp) = *(--sp);
1796 *(--dp) = *(--sp);
1797 *(--dp) = *(--sp);
1798 We can replace it with:
1800 sp-=6;
1801 dp=sp;
1805 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1807 /* This inverts the alpha channel in GA */
1808 if (row_info->bit_depth == 8)
1810 png_bytep sp = row + row_info->rowbytes;
1811 png_bytep dp = sp;
1812 png_uint_32 i;
1814 for (i = 0; i < row_width; i++)
1816 *(--dp) = (png_byte)(255 - *(--sp));
1817 *(--dp) = *(--sp);
1820 /* This inverts the alpha channel in GGAA */
1821 else
1823 png_bytep sp = row + row_info->rowbytes;
1824 png_bytep dp = sp;
1825 png_uint_32 i;
1827 for (i = 0; i < row_width; i++)
1829 *(--dp) = (png_byte)(255 - *(--sp));
1830 *(--dp) = (png_byte)(255 - *(--sp));
1832 *(--dp) = *(--sp);
1833 *(--dp) = *(--sp);
1835 sp-=2;
1836 dp=sp;
1842 #endif
1844 #if defined(PNG_READ_FILLER_SUPPORTED)
1845 /* Add filler channel if we have RGB color */
1846 void /* PRIVATE */
1847 png_do_read_filler(png_row_infop row_info, png_bytep row,
1848 png_uint_32 filler, png_uint_32 flags)
1850 png_uint_32 i;
1851 png_uint_32 row_width = row_info->width;
1853 png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
1854 png_byte lo_filler = (png_byte)(filler & 0xff);
1856 png_debug(1, "in png_do_read_filler\n");
1857 if (
1858 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1859 row != NULL && row_info != NULL &&
1860 #endif
1861 row_info->color_type == PNG_COLOR_TYPE_GRAY)
1863 if(row_info->bit_depth == 8)
1865 /* This changes the data from G to GX */
1866 if (flags & PNG_FLAG_FILLER_AFTER)
1868 png_bytep sp = row + (png_size_t)row_width;
1869 png_bytep dp = sp + (png_size_t)row_width;
1870 for (i = 1; i < row_width; i++)
1872 *(--dp) = lo_filler;
1873 *(--dp) = *(--sp);
1875 *(--dp) = lo_filler;
1876 row_info->channels = 2;
1877 row_info->pixel_depth = 16;
1878 row_info->rowbytes = row_width * 2;
1880 /* This changes the data from G to XG */
1881 else
1883 png_bytep sp = row + (png_size_t)row_width;
1884 png_bytep dp = sp + (png_size_t)row_width;
1885 for (i = 0; i < row_width; i++)
1887 *(--dp) = *(--sp);
1888 *(--dp) = lo_filler;
1890 row_info->channels = 2;
1891 row_info->pixel_depth = 16;
1892 row_info->rowbytes = row_width * 2;
1895 else if(row_info->bit_depth == 16)
1897 /* This changes the data from GG to GGXX */
1898 if (flags & PNG_FLAG_FILLER_AFTER)
1900 png_bytep sp = row + (png_size_t)row_width * 2;
1901 png_bytep dp = sp + (png_size_t)row_width * 2;
1902 for (i = 1; i < row_width; i++)
1904 *(--dp) = hi_filler;
1905 *(--dp) = lo_filler;
1906 *(--dp) = *(--sp);
1907 *(--dp) = *(--sp);
1909 *(--dp) = hi_filler;
1910 *(--dp) = lo_filler;
1911 row_info->channels = 2;
1912 row_info->pixel_depth = 32;
1913 row_info->rowbytes = row_width * 4;
1915 /* This changes the data from GG to XXGG */
1916 else
1918 png_bytep sp = row + (png_size_t)row_width * 2;
1919 png_bytep dp = sp + (png_size_t)row_width * 2;
1920 for (i = 0; i < row_width; i++)
1922 *(--dp) = *(--sp);
1923 *(--dp) = *(--sp);
1924 *(--dp) = hi_filler;
1925 *(--dp) = lo_filler;
1927 row_info->channels = 2;
1928 row_info->pixel_depth = 32;
1929 row_info->rowbytes = row_width * 4;
1932 } /* COLOR_TYPE == GRAY */
1933 else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
1935 if(row_info->bit_depth == 8)
1937 /* This changes the data from RGB to RGBX */
1938 if (flags & PNG_FLAG_FILLER_AFTER)
1940 png_bytep sp = row + (png_size_t)row_width * 3;
1941 png_bytep dp = sp + (png_size_t)row_width;
1942 for (i = 1; i < row_width; i++)
1944 *(--dp) = lo_filler;
1945 *(--dp) = *(--sp);
1946 *(--dp) = *(--sp);
1947 *(--dp) = *(--sp);
1949 *(--dp) = lo_filler;
1950 row_info->channels = 4;
1951 row_info->pixel_depth = 32;
1952 row_info->rowbytes = row_width * 4;
1954 /* This changes the data from RGB to XRGB */
1955 else
1957 png_bytep sp = row + (png_size_t)row_width * 3;
1958 png_bytep dp = sp + (png_size_t)row_width;
1959 for (i = 0; i < row_width; i++)
1961 *(--dp) = *(--sp);
1962 *(--dp) = *(--sp);
1963 *(--dp) = *(--sp);
1964 *(--dp) = lo_filler;
1966 row_info->channels = 4;
1967 row_info->pixel_depth = 32;
1968 row_info->rowbytes = row_width * 4;
1971 else if(row_info->bit_depth == 16)
1973 /* This changes the data from RRGGBB to RRGGBBXX */
1974 if (flags & PNG_FLAG_FILLER_AFTER)
1976 png_bytep sp = row + (png_size_t)row_width * 6;
1977 png_bytep dp = sp + (png_size_t)row_width * 2;
1978 for (i = 1; i < row_width; i++)
1980 *(--dp) = hi_filler;
1981 *(--dp) = lo_filler;
1982 *(--dp) = *(--sp);
1983 *(--dp) = *(--sp);
1984 *(--dp) = *(--sp);
1985 *(--dp) = *(--sp);
1986 *(--dp) = *(--sp);
1987 *(--dp) = *(--sp);
1989 *(--dp) = hi_filler;
1990 *(--dp) = lo_filler;
1991 row_info->channels = 4;
1992 row_info->pixel_depth = 64;
1993 row_info->rowbytes = row_width * 8;
1995 /* This changes the data from RRGGBB to XXRRGGBB */
1996 else
1998 png_bytep sp = row + (png_size_t)row_width * 6;
1999 png_bytep dp = sp + (png_size_t)row_width * 2;
2000 for (i = 0; i < row_width; i++)
2002 *(--dp) = *(--sp);
2003 *(--dp) = *(--sp);
2004 *(--dp) = *(--sp);
2005 *(--dp) = *(--sp);
2006 *(--dp) = *(--sp);
2007 *(--dp) = *(--sp);
2008 *(--dp) = hi_filler;
2009 *(--dp) = lo_filler;
2011 row_info->channels = 4;
2012 row_info->pixel_depth = 64;
2013 row_info->rowbytes = row_width * 8;
2016 } /* COLOR_TYPE == RGB */
2018 #endif
2020 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2021 /* expand grayscale files to RGB, with or without alpha */
2022 void /* PRIVATE */
2023 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
2025 png_uint_32 i;
2026 png_uint_32 row_width = row_info->width;
2028 png_debug(1, "in png_do_gray_to_rgb\n");
2029 if (row_info->bit_depth >= 8 &&
2030 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2031 row != NULL && row_info != NULL &&
2032 #endif
2033 !(row_info->color_type & PNG_COLOR_MASK_COLOR))
2035 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2037 if (row_info->bit_depth == 8)
2039 png_bytep sp = row + (png_size_t)row_width - 1;
2040 png_bytep dp = sp + (png_size_t)row_width * 2;
2041 for (i = 0; i < row_width; i++)
2043 *(dp--) = *sp;
2044 *(dp--) = *sp;
2045 *(dp--) = *(sp--);
2048 else
2050 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2051 png_bytep dp = sp + (png_size_t)row_width * 4;
2052 for (i = 0; i < row_width; i++)
2054 *(dp--) = *sp;
2055 *(dp--) = *(sp - 1);
2056 *(dp--) = *sp;
2057 *(dp--) = *(sp - 1);
2058 *(dp--) = *(sp--);
2059 *(dp--) = *(sp--);
2063 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2065 if (row_info->bit_depth == 8)
2067 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2068 png_bytep dp = sp + (png_size_t)row_width * 2;
2069 for (i = 0; i < row_width; i++)
2071 *(dp--) = *(sp--);
2072 *(dp--) = *sp;
2073 *(dp--) = *sp;
2074 *(dp--) = *(sp--);
2077 else
2079 png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2080 png_bytep dp = sp + (png_size_t)row_width * 4;
2081 for (i = 0; i < row_width; i++)
2083 *(dp--) = *(sp--);
2084 *(dp--) = *(sp--);
2085 *(dp--) = *sp;
2086 *(dp--) = *(sp - 1);
2087 *(dp--) = *sp;
2088 *(dp--) = *(sp - 1);
2089 *(dp--) = *(sp--);
2090 *(dp--) = *(sp--);
2094 row_info->channels += (png_byte)2;
2095 row_info->color_type |= PNG_COLOR_MASK_COLOR;
2096 row_info->pixel_depth = (png_byte)(row_info->channels *
2097 row_info->bit_depth);
2098 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
2101 #endif
2103 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
2104 /* reduce RGB files to grayscale, with or without alpha
2105 * using the equation given in Poynton's ColorFAQ at
2106 * <http://www.inforamp.net/~poynton/>
2107 * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net
2109 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2111 * We approximate this with
2113 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
2115 * which can be expressed with integers as
2117 * Y = (6969 * R + 23434 * G + 2365 * B)/32768
2119 * The calculation is to be done in a linear colorspace.
2121 * Other integer coefficents can be used via png_set_rgb_to_gray().
2123 int /* PRIVATE */
2124 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2127 png_uint_32 i;
2129 png_uint_32 row_width = row_info->width;
2130 int rgb_error = 0;
2132 png_debug(1, "in png_do_rgb_to_gray\n");
2133 if (
2134 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2135 row != NULL && row_info != NULL &&
2136 #endif
2137 (row_info->color_type & PNG_COLOR_MASK_COLOR))
2139 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2140 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2141 png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
2143 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2145 if (row_info->bit_depth == 8)
2147 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2148 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2150 png_bytep sp = row;
2151 png_bytep dp = row;
2153 for (i = 0; i < row_width; i++)
2155 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2156 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2157 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2158 if(red != green || red != blue)
2160 rgb_error |= 1;
2161 *(dp++) = png_ptr->gamma_from_1[
2162 (rc*red+gc*green+bc*blue)>>15];
2164 else
2165 *(dp++) = *(sp-1);
2168 else
2169 #endif
2171 png_bytep sp = row;
2172 png_bytep dp = row;
2173 for (i = 0; i < row_width; i++)
2175 png_byte red = *(sp++);
2176 png_byte green = *(sp++);
2177 png_byte blue = *(sp++);
2178 if(red != green || red != blue)
2180 rgb_error |= 1;
2181 *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
2183 else
2184 *(dp++) = *(sp-1);
2189 else /* RGB bit_depth == 16 */
2191 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2192 if (png_ptr->gamma_16_to_1 != NULL &&
2193 png_ptr->gamma_16_from_1 != NULL)
2195 png_bytep sp = row;
2196 png_bytep dp = row;
2197 for (i = 0; i < row_width; i++)
2199 png_uint_16 red, green, blue, w;
2201 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2202 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2203 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2205 if(red == green && red == blue)
2206 w = red;
2207 else
2209 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2210 png_ptr->gamma_shift][red>>8];
2211 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2212 png_ptr->gamma_shift][green>>8];
2213 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2214 png_ptr->gamma_shift][blue>>8];
2215 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
2216 + bc*blue_1)>>15);
2217 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2218 png_ptr->gamma_shift][gray16 >> 8];
2219 rgb_error |= 1;
2222 *(dp++) = (png_byte)((w>>8) & 0xff);
2223 *(dp++) = (png_byte)(w & 0xff);
2226 else
2227 #endif
2229 png_bytep sp = row;
2230 png_bytep dp = row;
2231 for (i = 0; i < row_width; i++)
2233 png_uint_16 red, green, blue, gray16;
2235 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2236 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2237 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2239 if(red != green || red != blue)
2240 rgb_error |= 1;
2241 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2242 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2243 *(dp++) = (png_byte)(gray16 & 0xff);
2248 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2250 if (row_info->bit_depth == 8)
2252 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2253 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2255 png_bytep sp = row;
2256 png_bytep dp = row;
2257 for (i = 0; i < row_width; i++)
2259 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2260 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2261 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2262 if(red != green || red != blue)
2263 rgb_error |= 1;
2264 *(dp++) = png_ptr->gamma_from_1
2265 [(rc*red + gc*green + bc*blue)>>15];
2266 *(dp++) = *(sp++); /* alpha */
2269 else
2270 #endif
2272 png_bytep sp = row;
2273 png_bytep dp = row;
2274 for (i = 0; i < row_width; i++)
2276 png_byte red = *(sp++);
2277 png_byte green = *(sp++);
2278 png_byte blue = *(sp++);
2279 if(red != green || red != blue)
2280 rgb_error |= 1;
2281 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
2282 *(dp++) = *(sp++); /* alpha */
2286 else /* RGBA bit_depth == 16 */
2288 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2289 if (png_ptr->gamma_16_to_1 != NULL &&
2290 png_ptr->gamma_16_from_1 != NULL)
2292 png_bytep sp = row;
2293 png_bytep dp = row;
2294 for (i = 0; i < row_width; i++)
2296 png_uint_16 red, green, blue, w;
2298 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2299 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2300 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2302 if(red == green && red == blue)
2303 w = red;
2304 else
2306 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2307 png_ptr->gamma_shift][red>>8];
2308 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2309 png_ptr->gamma_shift][green>>8];
2310 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2311 png_ptr->gamma_shift][blue>>8];
2312 png_uint_16 gray16 = (png_uint_16)((rc * red_1
2313 + gc * green_1 + bc * blue_1)>>15);
2314 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2315 png_ptr->gamma_shift][gray16 >> 8];
2316 rgb_error |= 1;
2319 *(dp++) = (png_byte)((w>>8) & 0xff);
2320 *(dp++) = (png_byte)(w & 0xff);
2321 *(dp++) = *(sp++); /* alpha */
2322 *(dp++) = *(sp++);
2325 else
2326 #endif
2328 png_bytep sp = row;
2329 png_bytep dp = row;
2330 for (i = 0; i < row_width; i++)
2332 png_uint_16 red, green, blue, gray16;
2333 red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2334 green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2335 blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2336 if(red != green || red != blue)
2337 rgb_error |= 1;
2338 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2339 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2340 *(dp++) = (png_byte)(gray16 & 0xff);
2341 *(dp++) = *(sp++); /* alpha */
2342 *(dp++) = *(sp++);
2347 row_info->channels -= (png_byte)2;
2348 row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2349 row_info->pixel_depth = (png_byte)(row_info->channels *
2350 row_info->bit_depth);
2351 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
2353 return rgb_error;
2355 #endif
2357 /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
2358 * large of png_color. This lets grayscale images be treated as
2359 * paletted. Most useful for gamma correction and simplification
2360 * of code.
2362 void PNGAPI
2363 png_build_grayscale_palette(int bit_depth, png_colorp palette)
2365 int num_palette;
2366 int color_inc;
2367 int i;
2368 int v;
2370 png_debug(1, "in png_do_build_grayscale_palette\n");
2371 if (palette == NULL)
2372 return;
2374 switch (bit_depth)
2376 case 1:
2377 num_palette = 2;
2378 color_inc = 0xff;
2379 break;
2380 case 2:
2381 num_palette = 4;
2382 color_inc = 0x55;
2383 break;
2384 case 4:
2385 num_palette = 16;
2386 color_inc = 0x11;
2387 break;
2388 case 8:
2389 num_palette = 256;
2390 color_inc = 1;
2391 break;
2392 default:
2393 num_palette = 0;
2394 color_inc = 0;
2395 break;
2398 for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2400 palette[i].red = (png_byte)v;
2401 palette[i].green = (png_byte)v;
2402 palette[i].blue = (png_byte)v;
2406 /* This function is currently unused. Do we really need it? */
2407 #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
2408 void /* PRIVATE */
2409 png_correct_palette(png_structp png_ptr, png_colorp palette,
2410 int num_palette)
2412 png_debug(1, "in png_correct_palette\n");
2413 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2414 defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
2415 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
2417 png_color back, back_1;
2419 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
2421 back.red = png_ptr->gamma_table[png_ptr->background.red];
2422 back.green = png_ptr->gamma_table[png_ptr->background.green];
2423 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
2425 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
2426 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
2427 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
2429 else
2431 double g;
2433 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
2435 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2436 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
2438 back.red = png_ptr->background.red;
2439 back.green = png_ptr->background.green;
2440 back.blue = png_ptr->background.blue;
2442 else
2444 back.red =
2445 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2446 255.0 + 0.5);
2447 back.green =
2448 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2449 255.0 + 0.5);
2450 back.blue =
2451 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2452 255.0 + 0.5);
2455 g = 1.0 / png_ptr->background_gamma;
2457 back_1.red =
2458 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2459 255.0 + 0.5);
2460 back_1.green =
2461 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2462 255.0 + 0.5);
2463 back_1.blue =
2464 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2465 255.0 + 0.5);
2468 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2470 png_uint_32 i;
2472 for (i = 0; i < (png_uint_32)num_palette; i++)
2474 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
2476 palette[i] = back;
2478 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
2480 png_byte v, w;
2482 v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
2483 png_composite(w, v, png_ptr->trans[i], back_1.red);
2484 palette[i].red = png_ptr->gamma_from_1[w];
2486 v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
2487 png_composite(w, v, png_ptr->trans[i], back_1.green);
2488 palette[i].green = png_ptr->gamma_from_1[w];
2490 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
2491 png_composite(w, v, png_ptr->trans[i], back_1.blue);
2492 palette[i].blue = png_ptr->gamma_from_1[w];
2494 else
2496 palette[i].red = png_ptr->gamma_table[palette[i].red];
2497 palette[i].green = png_ptr->gamma_table[palette[i].green];
2498 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2502 else
2504 int i;
2506 for (i = 0; i < num_palette; i++)
2508 if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
2510 palette[i] = back;
2512 else
2514 palette[i].red = png_ptr->gamma_table[palette[i].red];
2515 palette[i].green = png_ptr->gamma_table[palette[i].green];
2516 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2521 else
2522 #endif
2523 #if defined(PNG_READ_GAMMA_SUPPORTED)
2524 if (png_ptr->transformations & PNG_GAMMA)
2526 int i;
2528 for (i = 0; i < num_palette; i++)
2530 palette[i].red = png_ptr->gamma_table[palette[i].red];
2531 palette[i].green = png_ptr->gamma_table[palette[i].green];
2532 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2535 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2536 else
2537 #endif
2538 #endif
2539 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2540 if (png_ptr->transformations & PNG_BACKGROUND)
2542 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2544 png_color back;
2546 back.red = (png_byte)png_ptr->background.red;
2547 back.green = (png_byte)png_ptr->background.green;
2548 back.blue = (png_byte)png_ptr->background.blue;
2550 for (i = 0; i < (int)png_ptr->num_trans; i++)
2552 if (png_ptr->trans[i] == 0)
2554 palette[i].red = back.red;
2555 palette[i].green = back.green;
2556 palette[i].blue = back.blue;
2558 else if (png_ptr->trans[i] != 0xff)
2560 png_composite(palette[i].red, png_ptr->palette[i].red,
2561 png_ptr->trans[i], back.red);
2562 png_composite(palette[i].green, png_ptr->palette[i].green,
2563 png_ptr->trans[i], back.green);
2564 png_composite(palette[i].blue, png_ptr->palette[i].blue,
2565 png_ptr->trans[i], back.blue);
2569 else /* assume grayscale palette (what else could it be?) */
2571 int i;
2573 for (i = 0; i < num_palette; i++)
2575 if (i == (png_byte)png_ptr->trans_values.gray)
2577 palette[i].red = (png_byte)png_ptr->background.red;
2578 palette[i].green = (png_byte)png_ptr->background.green;
2579 palette[i].blue = (png_byte)png_ptr->background.blue;
2584 #endif
2586 #endif
2588 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2589 /* Replace any alpha or transparency with the supplied background color.
2590 * "background" is already in the screen gamma, while "background_1" is
2591 * at a gamma of 1.0. Paletted files have already been taken care of.
2593 void /* PRIVATE */
2594 png_do_background(png_row_infop row_info, png_bytep row,
2595 png_color_16p trans_values, png_color_16p background
2596 #if defined(PNG_READ_GAMMA_SUPPORTED)
2597 , png_color_16p background_1,
2598 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
2599 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2600 png_uint_16pp gamma_16_to_1, int gamma_shift
2601 #endif
2604 png_bytep sp, dp;
2605 png_uint_32 i;
2606 png_uint_32 row_width=row_info->width;
2607 int shift;
2609 png_debug(1, "in png_do_background\n");
2610 if (background != NULL &&
2611 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2612 row != NULL && row_info != NULL &&
2613 #endif
2614 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
2615 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
2617 switch (row_info->color_type)
2619 case PNG_COLOR_TYPE_GRAY:
2621 switch (row_info->bit_depth)
2623 case 1:
2625 sp = row;
2626 shift = 7;
2627 for (i = 0; i < row_width; i++)
2629 if ((png_uint_16)((*sp >> shift) & 0x01)
2630 == trans_values->gray)
2632 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2633 *sp |= (png_byte)(background->gray << shift);
2635 if (!shift)
2637 shift = 7;
2638 sp++;
2640 else
2641 shift--;
2643 break;
2645 case 2:
2647 #if defined(PNG_READ_GAMMA_SUPPORTED)
2648 if (gamma_table != NULL)
2650 sp = row;
2651 shift = 6;
2652 for (i = 0; i < row_width; i++)
2654 if ((png_uint_16)((*sp >> shift) & 0x03)
2655 == trans_values->gray)
2657 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2658 *sp |= (png_byte)(background->gray << shift);
2660 else
2662 png_byte p = (png_byte)((*sp >> shift) & 0x03);
2663 png_byte g = (png_byte)((gamma_table [p | (p << 2) |
2664 (p << 4) | (p << 6)] >> 6) & 0x03);
2665 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2666 *sp |= (png_byte)(g << shift);
2668 if (!shift)
2670 shift = 6;
2671 sp++;
2673 else
2674 shift -= 2;
2677 else
2678 #endif
2680 sp = row;
2681 shift = 6;
2682 for (i = 0; i < row_width; i++)
2684 if ((png_uint_16)((*sp >> shift) & 0x03)
2685 == trans_values->gray)
2687 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2688 *sp |= (png_byte)(background->gray << shift);
2690 if (!shift)
2692 shift = 6;
2693 sp++;
2695 else
2696 shift -= 2;
2699 break;
2701 case 4:
2703 #if defined(PNG_READ_GAMMA_SUPPORTED)
2704 if (gamma_table != NULL)
2706 sp = row;
2707 shift = 4;
2708 for (i = 0; i < row_width; i++)
2710 if ((png_uint_16)((*sp >> shift) & 0x0f)
2711 == trans_values->gray)
2713 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2714 *sp |= (png_byte)(background->gray << shift);
2716 else
2718 png_byte p = (png_byte)((*sp >> shift) & 0x0f);
2719 png_byte g = (png_byte)((gamma_table[p |
2720 (p << 4)] >> 4) & 0x0f);
2721 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2722 *sp |= (png_byte)(g << shift);
2724 if (!shift)
2726 shift = 4;
2727 sp++;
2729 else
2730 shift -= 4;
2733 else
2734 #endif
2736 sp = row;
2737 shift = 4;
2738 for (i = 0; i < row_width; i++)
2740 if ((png_uint_16)((*sp >> shift) & 0x0f)
2741 == trans_values->gray)
2743 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2744 *sp |= (png_byte)(background->gray << shift);
2746 if (!shift)
2748 shift = 4;
2749 sp++;
2751 else
2752 shift -= 4;
2755 break;
2757 case 8:
2759 #if defined(PNG_READ_GAMMA_SUPPORTED)
2760 if (gamma_table != NULL)
2762 sp = row;
2763 for (i = 0; i < row_width; i++, sp++)
2765 if (*sp == trans_values->gray)
2767 *sp = (png_byte)background->gray;
2769 else
2771 *sp = gamma_table[*sp];
2775 else
2776 #endif
2778 sp = row;
2779 for (i = 0; i < row_width; i++, sp++)
2781 if (*sp == trans_values->gray)
2783 *sp = (png_byte)background->gray;
2787 break;
2789 case 16:
2791 #if defined(PNG_READ_GAMMA_SUPPORTED)
2792 if (gamma_16 != NULL)
2794 sp = row;
2795 for (i = 0; i < row_width; i++, sp += 2)
2797 png_uint_16 v;
2799 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2800 if (v == trans_values->gray)
2802 /* background is already in screen gamma */
2803 *sp = (png_byte)((background->gray >> 8) & 0xff);
2804 *(sp + 1) = (png_byte)(background->gray & 0xff);
2806 else
2808 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2809 *sp = (png_byte)((v >> 8) & 0xff);
2810 *(sp + 1) = (png_byte)(v & 0xff);
2814 else
2815 #endif
2817 sp = row;
2818 for (i = 0; i < row_width; i++, sp += 2)
2820 png_uint_16 v;
2822 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2823 if (v == trans_values->gray)
2825 *sp = (png_byte)((background->gray >> 8) & 0xff);
2826 *(sp + 1) = (png_byte)(background->gray & 0xff);
2830 break;
2833 break;
2835 case PNG_COLOR_TYPE_RGB:
2837 if (row_info->bit_depth == 8)
2839 #if defined(PNG_READ_GAMMA_SUPPORTED)
2840 if (gamma_table != NULL)
2842 sp = row;
2843 for (i = 0; i < row_width; i++, sp += 3)
2845 if (*sp == trans_values->red &&
2846 *(sp + 1) == trans_values->green &&
2847 *(sp + 2) == trans_values->blue)
2849 *sp = (png_byte)background->red;
2850 *(sp + 1) = (png_byte)background->green;
2851 *(sp + 2) = (png_byte)background->blue;
2853 else
2855 *sp = gamma_table[*sp];
2856 *(sp + 1) = gamma_table[*(sp + 1)];
2857 *(sp + 2) = gamma_table[*(sp + 2)];
2861 else
2862 #endif
2864 sp = row;
2865 for (i = 0; i < row_width; i++, sp += 3)
2867 if (*sp == trans_values->red &&
2868 *(sp + 1) == trans_values->green &&
2869 *(sp + 2) == trans_values->blue)
2871 *sp = (png_byte)background->red;
2872 *(sp + 1) = (png_byte)background->green;
2873 *(sp + 2) = (png_byte)background->blue;
2878 else /* if (row_info->bit_depth == 16) */
2880 #if defined(PNG_READ_GAMMA_SUPPORTED)
2881 if (gamma_16 != NULL)
2883 sp = row;
2884 for (i = 0; i < row_width; i++, sp += 6)
2886 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2887 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2888 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
2889 if (r == trans_values->red && g == trans_values->green &&
2890 b == trans_values->blue)
2892 /* background is already in screen gamma */
2893 *sp = (png_byte)((background->red >> 8) & 0xff);
2894 *(sp + 1) = (png_byte)(background->red & 0xff);
2895 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2896 *(sp + 3) = (png_byte)(background->green & 0xff);
2897 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2898 *(sp + 5) = (png_byte)(background->blue & 0xff);
2900 else
2902 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2903 *sp = (png_byte)((v >> 8) & 0xff);
2904 *(sp + 1) = (png_byte)(v & 0xff);
2905 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
2906 *(sp + 2) = (png_byte)((v >> 8) & 0xff);
2907 *(sp + 3) = (png_byte)(v & 0xff);
2908 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
2909 *(sp + 4) = (png_byte)((v >> 8) & 0xff);
2910 *(sp + 5) = (png_byte)(v & 0xff);
2914 else
2915 #endif
2917 sp = row;
2918 for (i = 0; i < row_width; i++, sp += 6)
2920 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
2921 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2922 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
2924 if (r == trans_values->red && g == trans_values->green &&
2925 b == trans_values->blue)
2927 *sp = (png_byte)((background->red >> 8) & 0xff);
2928 *(sp + 1) = (png_byte)(background->red & 0xff);
2929 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2930 *(sp + 3) = (png_byte)(background->green & 0xff);
2931 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2932 *(sp + 5) = (png_byte)(background->blue & 0xff);
2937 break;
2939 case PNG_COLOR_TYPE_GRAY_ALPHA:
2941 if (row_info->bit_depth == 8)
2943 #if defined(PNG_READ_GAMMA_SUPPORTED)
2944 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2945 gamma_table != NULL)
2947 sp = row;
2948 dp = row;
2949 for (i = 0; i < row_width; i++, sp += 2, dp++)
2951 png_uint_16 a = *(sp + 1);
2953 if (a == 0xff)
2955 *dp = gamma_table[*sp];
2957 else if (a == 0)
2959 /* background is already in screen gamma */
2960 *dp = (png_byte)background->gray;
2962 else
2964 png_byte v, w;
2966 v = gamma_to_1[*sp];
2967 png_composite(w, v, a, background_1->gray);
2968 *dp = gamma_from_1[w];
2972 else
2973 #endif
2975 sp = row;
2976 dp = row;
2977 for (i = 0; i < row_width; i++, sp += 2, dp++)
2979 png_byte a = *(sp + 1);
2981 if (a == 0xff)
2983 *dp = *sp;
2985 #if defined(PNG_READ_GAMMA_SUPPORTED)
2986 else if (a == 0)
2988 *dp = (png_byte)background->gray;
2990 else
2992 png_composite(*dp, *sp, a, background_1->gray);
2994 #else
2995 *dp = (png_byte)background->gray;
2996 #endif
3000 else /* if (png_ptr->bit_depth == 16) */
3002 #if defined(PNG_READ_GAMMA_SUPPORTED)
3003 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3004 gamma_16_to_1 != NULL)
3006 sp = row;
3007 dp = row;
3008 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3010 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3012 if (a == (png_uint_16)0xffff)
3014 png_uint_16 v;
3016 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3017 *dp = (png_byte)((v >> 8) & 0xff);
3018 *(dp + 1) = (png_byte)(v & 0xff);
3020 #if defined(PNG_READ_GAMMA_SUPPORTED)
3021 else if (a == 0)
3022 #else
3023 else
3024 #endif
3026 /* background is already in screen gamma */
3027 *dp = (png_byte)((background->gray >> 8) & 0xff);
3028 *(dp + 1) = (png_byte)(background->gray & 0xff);
3030 #if defined(PNG_READ_GAMMA_SUPPORTED)
3031 else
3033 png_uint_16 g, v, w;
3035 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3036 png_composite_16(v, g, a, background_1->gray);
3037 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3038 *dp = (png_byte)((w >> 8) & 0xff);
3039 *(dp + 1) = (png_byte)(w & 0xff);
3041 #endif
3044 else
3045 #endif
3047 sp = row;
3048 dp = row;
3049 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3051 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3052 if (a == (png_uint_16)0xffff)
3054 png_memcpy(dp, sp, 2);
3056 #if defined(PNG_READ_GAMMA_SUPPORTED)
3057 else if (a == 0)
3058 #else
3059 else
3060 #endif
3062 *dp = (png_byte)((background->gray >> 8) & 0xff);
3063 *(dp + 1) = (png_byte)(background->gray & 0xff);
3065 #if defined(PNG_READ_GAMMA_SUPPORTED)
3066 else
3068 png_uint_16 g, v;
3070 g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3071 png_composite_16(v, g, a, background_1->gray);
3072 *dp = (png_byte)((v >> 8) & 0xff);
3073 *(dp + 1) = (png_byte)(v & 0xff);
3075 #endif
3079 break;
3081 case PNG_COLOR_TYPE_RGB_ALPHA:
3083 if (row_info->bit_depth == 8)
3085 #if defined(PNG_READ_GAMMA_SUPPORTED)
3086 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3087 gamma_table != NULL)
3089 sp = row;
3090 dp = row;
3091 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3093 png_byte a = *(sp + 3);
3095 if (a == 0xff)
3097 *dp = gamma_table[*sp];
3098 *(dp + 1) = gamma_table[*(sp + 1)];
3099 *(dp + 2) = gamma_table[*(sp + 2)];
3101 else if (a == 0)
3103 /* background is already in screen gamma */
3104 *dp = (png_byte)background->red;
3105 *(dp + 1) = (png_byte)background->green;
3106 *(dp + 2) = (png_byte)background->blue;
3108 else
3110 png_byte v, w;
3112 v = gamma_to_1[*sp];
3113 png_composite(w, v, a, background_1->red);
3114 *dp = gamma_from_1[w];
3115 v = gamma_to_1[*(sp + 1)];
3116 png_composite(w, v, a, background_1->green);
3117 *(dp + 1) = gamma_from_1[w];
3118 v = gamma_to_1[*(sp + 2)];
3119 png_composite(w, v, a, background_1->blue);
3120 *(dp + 2) = gamma_from_1[w];
3124 else
3125 #endif
3127 sp = row;
3128 dp = row;
3129 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3131 png_byte a = *(sp + 3);
3133 if (a == 0xff)
3135 *dp = *sp;
3136 *(dp + 1) = *(sp + 1);
3137 *(dp + 2) = *(sp + 2);
3139 else if (a == 0)
3141 *dp = (png_byte)background->red;
3142 *(dp + 1) = (png_byte)background->green;
3143 *(dp + 2) = (png_byte)background->blue;
3145 else
3147 png_composite(*dp, *sp, a, background->red);
3148 png_composite(*(dp + 1), *(sp + 1), a,
3149 background->green);
3150 png_composite(*(dp + 2), *(sp + 2), a,
3151 background->blue);
3156 else /* if (row_info->bit_depth == 16) */
3158 #if defined(PNG_READ_GAMMA_SUPPORTED)
3159 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3160 gamma_16_to_1 != NULL)
3162 sp = row;
3163 dp = row;
3164 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3166 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3167 << 8) + (png_uint_16)(*(sp + 7)));
3168 if (a == (png_uint_16)0xffff)
3170 png_uint_16 v;
3172 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3173 *dp = (png_byte)((v >> 8) & 0xff);
3174 *(dp + 1) = (png_byte)(v & 0xff);
3175 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3176 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3177 *(dp + 3) = (png_byte)(v & 0xff);
3178 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3179 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3180 *(dp + 5) = (png_byte)(v & 0xff);
3182 else if (a == 0)
3184 /* background is already in screen gamma */
3185 *dp = (png_byte)((background->red >> 8) & 0xff);
3186 *(dp + 1) = (png_byte)(background->red & 0xff);
3187 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3188 *(dp + 3) = (png_byte)(background->green & 0xff);
3189 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3190 *(dp + 5) = (png_byte)(background->blue & 0xff);
3192 else
3194 png_uint_16 v, w, x;
3196 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3197 png_composite_16(w, v, a, background_1->red);
3198 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3199 *dp = (png_byte)((x >> 8) & 0xff);
3200 *(dp + 1) = (png_byte)(x & 0xff);
3201 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3202 png_composite_16(w, v, a, background_1->green);
3203 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3204 *(dp + 2) = (png_byte)((x >> 8) & 0xff);
3205 *(dp + 3) = (png_byte)(x & 0xff);
3206 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3207 png_composite_16(w, v, a, background_1->blue);
3208 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3209 *(dp + 4) = (png_byte)((x >> 8) & 0xff);
3210 *(dp + 5) = (png_byte)(x & 0xff);
3214 else
3215 #endif
3217 sp = row;
3218 dp = row;
3219 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3221 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3222 << 8) + (png_uint_16)(*(sp + 7)));
3223 if (a == (png_uint_16)0xffff)
3225 png_memcpy(dp, sp, 6);
3227 else if (a == 0)
3229 *dp = (png_byte)((background->red >> 8) & 0xff);
3230 *(dp + 1) = (png_byte)(background->red & 0xff);
3231 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3232 *(dp + 3) = (png_byte)(background->green & 0xff);
3233 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3234 *(dp + 5) = (png_byte)(background->blue & 0xff);
3236 else
3238 png_uint_16 v;
3240 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3241 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3242 + *(sp + 3));
3243 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3244 + *(sp + 5));
3246 png_composite_16(v, r, a, background->red);
3247 *dp = (png_byte)((v >> 8) & 0xff);
3248 *(dp + 1) = (png_byte)(v & 0xff);
3249 png_composite_16(v, g, a, background->green);
3250 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3251 *(dp + 3) = (png_byte)(v & 0xff);
3252 png_composite_16(v, b, a, background->blue);
3253 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3254 *(dp + 5) = (png_byte)(v & 0xff);
3259 break;
3263 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3265 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
3266 row_info->channels--;
3267 row_info->pixel_depth = (png_byte)(row_info->channels *
3268 row_info->bit_depth);
3269 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3273 #endif
3275 #if defined(PNG_READ_GAMMA_SUPPORTED)
3276 /* Gamma correct the image, avoiding the alpha channel. Make sure
3277 * you do this after you deal with the transparency issue on grayscale
3278 * or RGB images. If your bit depth is 8, use gamma_table, if it
3279 * is 16, use gamma_16_table and gamma_shift. Build these with
3280 * build_gamma_table().
3282 void /* PRIVATE */
3283 png_do_gamma(png_row_infop row_info, png_bytep row,
3284 png_bytep gamma_table, png_uint_16pp gamma_16_table,
3285 int gamma_shift)
3287 png_bytep sp;
3288 png_uint_32 i;
3289 png_uint_32 row_width=row_info->width;
3291 png_debug(1, "in png_do_gamma\n");
3292 if (
3293 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3294 row != NULL && row_info != NULL &&
3295 #endif
3296 ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3297 (row_info->bit_depth == 16 && gamma_16_table != NULL)))
3299 switch (row_info->color_type)
3301 case PNG_COLOR_TYPE_RGB:
3303 if (row_info->bit_depth == 8)
3305 sp = row;
3306 for (i = 0; i < row_width; i++)
3308 *sp = gamma_table[*sp];
3309 sp++;
3310 *sp = gamma_table[*sp];
3311 sp++;
3312 *sp = gamma_table[*sp];
3313 sp++;
3316 else /* if (row_info->bit_depth == 16) */
3318 sp = row;
3319 for (i = 0; i < row_width; i++)
3321 png_uint_16 v;
3323 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3324 *sp = (png_byte)((v >> 8) & 0xff);
3325 *(sp + 1) = (png_byte)(v & 0xff);
3326 sp += 2;
3327 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3328 *sp = (png_byte)((v >> 8) & 0xff);
3329 *(sp + 1) = (png_byte)(v & 0xff);
3330 sp += 2;
3331 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3332 *sp = (png_byte)((v >> 8) & 0xff);
3333 *(sp + 1) = (png_byte)(v & 0xff);
3334 sp += 2;
3337 break;
3339 case PNG_COLOR_TYPE_RGB_ALPHA:
3341 if (row_info->bit_depth == 8)
3343 sp = row;
3344 for (i = 0; i < row_width; i++)
3346 *sp = gamma_table[*sp];
3347 sp++;
3348 *sp = gamma_table[*sp];
3349 sp++;
3350 *sp = gamma_table[*sp];
3351 sp++;
3352 sp++;
3355 else /* if (row_info->bit_depth == 16) */
3357 sp = row;
3358 for (i = 0; i < row_width; i++)
3360 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3361 *sp = (png_byte)((v >> 8) & 0xff);
3362 *(sp + 1) = (png_byte)(v & 0xff);
3363 sp += 2;
3364 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3365 *sp = (png_byte)((v >> 8) & 0xff);
3366 *(sp + 1) = (png_byte)(v & 0xff);
3367 sp += 2;
3368 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3369 *sp = (png_byte)((v >> 8) & 0xff);
3370 *(sp + 1) = (png_byte)(v & 0xff);
3371 sp += 4;
3374 break;
3376 case PNG_COLOR_TYPE_GRAY_ALPHA:
3378 if (row_info->bit_depth == 8)
3380 sp = row;
3381 for (i = 0; i < row_width; i++)
3383 *sp = gamma_table[*sp];
3384 sp += 2;
3387 else /* if (row_info->bit_depth == 16) */
3389 sp = row;
3390 for (i = 0; i < row_width; i++)
3392 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3393 *sp = (png_byte)((v >> 8) & 0xff);
3394 *(sp + 1) = (png_byte)(v & 0xff);
3395 sp += 4;
3398 break;
3400 case PNG_COLOR_TYPE_GRAY:
3402 if (row_info->bit_depth == 2)
3404 sp = row;
3405 for (i = 0; i < row_width; i += 4)
3407 int a = *sp & 0xc0;
3408 int b = *sp & 0x30;
3409 int c = *sp & 0x0c;
3410 int d = *sp & 0x03;
3412 *sp = (png_byte)(
3413 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
3414 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3415 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
3416 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
3417 sp++;
3420 if (row_info->bit_depth == 4)
3422 sp = row;
3423 for (i = 0; i < row_width; i += 2)
3425 int msb = *sp & 0xf0;
3426 int lsb = *sp & 0x0f;
3428 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3429 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
3430 sp++;
3433 else if (row_info->bit_depth == 8)
3435 sp = row;
3436 for (i = 0; i < row_width; i++)
3438 *sp = gamma_table[*sp];
3439 sp++;
3442 else if (row_info->bit_depth == 16)
3444 sp = row;
3445 for (i = 0; i < row_width; i++)
3447 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3448 *sp = (png_byte)((v >> 8) & 0xff);
3449 *(sp + 1) = (png_byte)(v & 0xff);
3450 sp += 2;
3453 break;
3458 #endif
3460 #if defined(PNG_READ_EXPAND_SUPPORTED)
3461 /* Expands a palette row to an RGB or RGBA row depending
3462 * upon whether you supply trans and num_trans.
3464 void /* PRIVATE */
3465 png_do_expand_palette(png_row_infop row_info, png_bytep row,
3466 png_colorp palette, png_bytep trans, int num_trans)
3468 int shift, value;
3469 png_bytep sp, dp;
3470 png_uint_32 i;
3471 png_uint_32 row_width=row_info->width;
3473 png_debug(1, "in png_do_expand_palette\n");
3474 if (
3475 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3476 row != NULL && row_info != NULL &&
3477 #endif
3478 row_info->color_type == PNG_COLOR_TYPE_PALETTE)
3480 if (row_info->bit_depth < 8)
3482 switch (row_info->bit_depth)
3484 case 1:
3486 sp = row + (png_size_t)((row_width - 1) >> 3);
3487 dp = row + (png_size_t)row_width - 1;
3488 shift = 7 - (int)((row_width + 7) & 0x07);
3489 for (i = 0; i < row_width; i++)
3491 if ((*sp >> shift) & 0x01)
3492 *dp = 1;
3493 else
3494 *dp = 0;
3495 if (shift == 7)
3497 shift = 0;
3498 sp--;
3500 else
3501 shift++;
3503 dp--;
3505 break;
3507 case 2:
3509 sp = row + (png_size_t)((row_width - 1) >> 2);
3510 dp = row + (png_size_t)row_width - 1;
3511 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3512 for (i = 0; i < row_width; i++)
3514 value = (*sp >> shift) & 0x03;
3515 *dp = (png_byte)value;
3516 if (shift == 6)
3518 shift = 0;
3519 sp--;
3521 else
3522 shift += 2;
3524 dp--;
3526 break;
3528 case 4:
3530 sp = row + (png_size_t)((row_width - 1) >> 1);
3531 dp = row + (png_size_t)row_width - 1;
3532 shift = (int)((row_width & 0x01) << 2);
3533 for (i = 0; i < row_width; i++)
3535 value = (*sp >> shift) & 0x0f;
3536 *dp = (png_byte)value;
3537 if (shift == 4)
3539 shift = 0;
3540 sp--;
3542 else
3543 shift += 4;
3545 dp--;
3547 break;
3550 row_info->bit_depth = 8;
3551 row_info->pixel_depth = 8;
3552 row_info->rowbytes = row_width;
3554 switch (row_info->bit_depth)
3556 case 8:
3558 if (trans != NULL)
3560 sp = row + (png_size_t)row_width - 1;
3561 dp = row + (png_size_t)(row_width << 2) - 1;
3563 for (i = 0; i < row_width; i++)
3565 if ((int)(*sp) >= num_trans)
3566 *dp-- = 0xff;
3567 else
3568 *dp-- = trans[*sp];
3569 *dp-- = palette[*sp].blue;
3570 *dp-- = palette[*sp].green;
3571 *dp-- = palette[*sp].red;
3572 sp--;
3574 row_info->bit_depth = 8;
3575 row_info->pixel_depth = 32;
3576 row_info->rowbytes = row_width * 4;
3577 row_info->color_type = 6;
3578 row_info->channels = 4;
3580 else
3582 sp = row + (png_size_t)row_width - 1;
3583 dp = row + (png_size_t)(row_width * 3) - 1;
3585 for (i = 0; i < row_width; i++)
3587 *dp-- = palette[*sp].blue;
3588 *dp-- = palette[*sp].green;
3589 *dp-- = palette[*sp].red;
3590 sp--;
3592 row_info->bit_depth = 8;
3593 row_info->pixel_depth = 24;
3594 row_info->rowbytes = row_width * 3;
3595 row_info->color_type = 2;
3596 row_info->channels = 3;
3598 break;
3604 /* If the bit depth < 8, it is expanded to 8. Also, if the
3605 * transparency value is supplied, an alpha channel is built.
3607 void /* PRIVATE */
3608 png_do_expand(png_row_infop row_info, png_bytep row,
3609 png_color_16p trans_value)
3611 int shift, value;
3612 png_bytep sp, dp;
3613 png_uint_32 i;
3614 png_uint_32 row_width=row_info->width;
3616 png_debug(1, "in png_do_expand\n");
3617 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3618 if (row != NULL && row_info != NULL)
3619 #endif
3621 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
3623 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
3625 if (row_info->bit_depth < 8)
3627 switch (row_info->bit_depth)
3629 case 1:
3631 gray = (png_uint_16)(gray*0xff);
3632 sp = row + (png_size_t)((row_width - 1) >> 3);
3633 dp = row + (png_size_t)row_width - 1;
3634 shift = 7 - (int)((row_width + 7) & 0x07);
3635 for (i = 0; i < row_width; i++)
3637 if ((*sp >> shift) & 0x01)
3638 *dp = 0xff;
3639 else
3640 *dp = 0;
3641 if (shift == 7)
3643 shift = 0;
3644 sp--;
3646 else
3647 shift++;
3649 dp--;
3651 break;
3653 case 2:
3655 gray = (png_uint_16)(gray*0x55);
3656 sp = row + (png_size_t)((row_width - 1) >> 2);
3657 dp = row + (png_size_t)row_width - 1;
3658 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3659 for (i = 0; i < row_width; i++)
3661 value = (*sp >> shift) & 0x03;
3662 *dp = (png_byte)(value | (value << 2) | (value << 4) |
3663 (value << 6));
3664 if (shift == 6)
3666 shift = 0;
3667 sp--;
3669 else
3670 shift += 2;
3672 dp--;
3674 break;
3676 case 4:
3678 gray = (png_uint_16)(gray*0x11);
3679 sp = row + (png_size_t)((row_width - 1) >> 1);
3680 dp = row + (png_size_t)row_width - 1;
3681 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
3682 for (i = 0; i < row_width; i++)
3684 value = (*sp >> shift) & 0x0f;
3685 *dp = (png_byte)(value | (value << 4));
3686 if (shift == 4)
3688 shift = 0;
3689 sp--;
3691 else
3692 shift = 4;
3694 dp--;
3696 break;
3699 row_info->bit_depth = 8;
3700 row_info->pixel_depth = 8;
3701 row_info->rowbytes = row_width;
3704 if (trans_value != NULL)
3706 if (row_info->bit_depth == 8)
3708 sp = row + (png_size_t)row_width - 1;
3709 dp = row + (png_size_t)(row_width << 1) - 1;
3710 for (i = 0; i < row_width; i++)
3712 if (*sp == gray)
3713 *dp-- = 0;
3714 else
3715 *dp-- = 0xff;
3716 *dp-- = *sp--;
3719 else if (row_info->bit_depth == 16)
3721 sp = row + row_info->rowbytes - 1;
3722 dp = row + (row_info->rowbytes << 1) - 1;
3723 for (i = 0; i < row_width; i++)
3725 if (((png_uint_16)*(sp) |
3726 ((png_uint_16)*(sp - 1) << 8)) == gray)
3728 *dp-- = 0;
3729 *dp-- = 0;
3731 else
3733 *dp-- = 0xff;
3734 *dp-- = 0xff;
3736 *dp-- = *sp--;
3737 *dp-- = *sp--;
3740 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3741 row_info->channels = 2;
3742 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3743 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
3744 row_width);
3747 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3749 if (row_info->bit_depth == 8)
3751 sp = row + (png_size_t)row_info->rowbytes - 1;
3752 dp = row + (png_size_t)(row_width << 2) - 1;
3753 for (i = 0; i < row_width; i++)
3755 if (*(sp - 2) == trans_value->red &&
3756 *(sp - 1) == trans_value->green &&
3757 *(sp - 0) == trans_value->blue)
3758 *dp-- = 0;
3759 else
3760 *dp-- = 0xff;
3761 *dp-- = *sp--;
3762 *dp-- = *sp--;
3763 *dp-- = *sp--;
3766 else if (row_info->bit_depth == 16)
3768 sp = row + row_info->rowbytes - 1;
3769 dp = row + (png_size_t)(row_width << 3) - 1;
3770 for (i = 0; i < row_width; i++)
3772 if ((((png_uint_16)*(sp - 4) |
3773 ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
3774 (((png_uint_16)*(sp - 2) |
3775 ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
3776 (((png_uint_16)*(sp - 0) |
3777 ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
3779 *dp-- = 0;
3780 *dp-- = 0;
3782 else
3784 *dp-- = 0xff;
3785 *dp-- = 0xff;
3787 *dp-- = *sp--;
3788 *dp-- = *sp--;
3789 *dp-- = *sp--;
3790 *dp-- = *sp--;
3791 *dp-- = *sp--;
3792 *dp-- = *sp--;
3795 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3796 row_info->channels = 4;
3797 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
3798 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3802 #endif
3804 #if defined(PNG_READ_DITHER_SUPPORTED)
3805 void /* PRIVATE */
3806 png_do_dither(png_row_infop row_info, png_bytep row,
3807 png_bytep palette_lookup, png_bytep dither_lookup)
3809 png_bytep sp, dp;
3810 png_uint_32 i;
3811 png_uint_32 row_width=row_info->width;
3813 png_debug(1, "in png_do_dither\n");
3814 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3815 if (row != NULL && row_info != NULL)
3816 #endif
3818 if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3819 palette_lookup && row_info->bit_depth == 8)
3821 int r, g, b, p;
3822 sp = row;
3823 dp = row;
3824 for (i = 0; i < row_width; i++)
3826 r = *sp++;
3827 g = *sp++;
3828 b = *sp++;
3830 /* this looks real messy, but the compiler will reduce
3831 it down to a reasonable formula. For example, with
3832 5 bits per color, we get:
3833 p = (((r >> 3) & 0x1f) << 10) |
3834 (((g >> 3) & 0x1f) << 5) |
3835 ((b >> 3) & 0x1f);
3837 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3838 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3839 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3840 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3841 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3842 (PNG_DITHER_BLUE_BITS)) |
3843 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3844 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3846 *dp++ = palette_lookup[p];
3848 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3849 row_info->channels = 1;
3850 row_info->pixel_depth = row_info->bit_depth;
3851 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3853 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
3854 palette_lookup != NULL && row_info->bit_depth == 8)
3856 int r, g, b, p;
3857 sp = row;
3858 dp = row;
3859 for (i = 0; i < row_width; i++)
3861 r = *sp++;
3862 g = *sp++;
3863 b = *sp++;
3864 sp++;
3866 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3867 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3868 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3869 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3870 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3871 (PNG_DITHER_BLUE_BITS)) |
3872 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3873 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3875 *dp++ = palette_lookup[p];
3877 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3878 row_info->channels = 1;
3879 row_info->pixel_depth = row_info->bit_depth;
3880 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3882 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
3883 dither_lookup && row_info->bit_depth == 8)
3885 sp = row;
3886 for (i = 0; i < row_width; i++, sp++)
3888 *sp = dither_lookup[*sp];
3893 #endif
3895 #ifdef PNG_FLOATING_POINT_SUPPORTED
3896 #if defined(PNG_READ_GAMMA_SUPPORTED)
3897 static int png_gamma_shift[] =
3898 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
3900 /* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
3901 * tables, we don't make a full table if we are reducing to 8-bit in
3902 * the future. Note also how the gamma_16 tables are segmented so that
3903 * we don't need to allocate > 64K chunks for a full 16-bit table.
3905 void /* PRIVATE */
3906 png_build_gamma_table(png_structp png_ptr)
3908 png_debug(1, "in png_build_gamma_table\n");
3909 if(png_ptr->gamma != 0.0)
3911 if (png_ptr->bit_depth <= 8)
3913 int i;
3914 double g;
3916 if (png_ptr->screen_gamma > .000001)
3917 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3918 else
3919 g = 1.0;
3921 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
3922 (png_uint_32)256);
3924 for (i = 0; i < 256; i++)
3926 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
3927 g) * 255.0 + .5);
3930 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3931 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
3932 if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
3935 g = 1.0 / (png_ptr->gamma);
3937 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
3938 (png_uint_32)256);
3940 for (i = 0; i < 256; i++)
3942 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
3943 g) * 255.0 + .5);
3947 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
3948 (png_uint_32)256);
3950 if(png_ptr->screen_gamma > 0.000001)
3951 g = 1.0 / png_ptr->screen_gamma;
3952 else
3953 g = png_ptr->gamma; /* probably doing rgb_to_gray */
3955 for (i = 0; i < 256; i++)
3957 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
3958 g) * 255.0 + .5);
3962 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
3964 else
3966 double g;
3967 int i, j, shift, num;
3968 int sig_bit;
3969 png_uint_32 ig;
3971 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
3973 sig_bit = (int)png_ptr->sig_bit.red;
3974 if ((int)png_ptr->sig_bit.green > sig_bit)
3975 sig_bit = png_ptr->sig_bit.green;
3976 if ((int)png_ptr->sig_bit.blue > sig_bit)
3977 sig_bit = png_ptr->sig_bit.blue;
3979 else
3981 sig_bit = (int)png_ptr->sig_bit.gray;
3984 if (sig_bit > 0)
3985 shift = 16 - sig_bit;
3986 else
3987 shift = 0;
3989 if (png_ptr->transformations & PNG_16_TO_8)
3991 if (shift < (16 - PNG_MAX_GAMMA_8))
3992 shift = (16 - PNG_MAX_GAMMA_8);
3995 if (shift > 8)
3996 shift = 8;
3997 if (shift < 0)
3998 shift = 0;
4000 png_ptr->gamma_shift = (png_byte)shift;
4002 num = (1 << (8 - shift));
4004 if (png_ptr->screen_gamma > .000001)
4005 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4006 else
4007 g = 1.0;
4009 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
4010 (png_uint_32)(num * png_sizeof (png_uint_16p)));
4012 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
4014 double fin, fout;
4015 png_uint_32 last, max;
4017 for (i = 0; i < num; i++)
4019 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4020 (png_uint_32)(256 * png_sizeof (png_uint_16)));
4023 g = 1.0 / g;
4024 last = 0;
4025 for (i = 0; i < 256; i++)
4027 fout = ((double)i + 0.5) / 256.0;
4028 fin = pow(fout, g);
4029 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
4030 while (last <= max)
4032 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4033 [(int)(last >> (8 - shift))] = (png_uint_16)(
4034 (png_uint_16)i | ((png_uint_16)i << 8));
4035 last++;
4038 while (last < ((png_uint_32)num << 8))
4040 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4041 [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
4042 last++;
4045 else
4047 for (i = 0; i < num; i++)
4049 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4050 (png_uint_32)(256 * png_sizeof (png_uint_16)));
4052 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
4053 for (j = 0; j < 256; j++)
4055 png_ptr->gamma_16_table[i][j] =
4056 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4057 65535.0, g) * 65535.0 + .5);
4062 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4063 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4064 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
4067 g = 1.0 / (png_ptr->gamma);
4069 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
4070 (png_uint_32)(num * png_sizeof (png_uint_16p )));
4072 for (i = 0; i < num; i++)
4074 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
4075 (png_uint_32)(256 * png_sizeof (png_uint_16)));
4077 ig = (((png_uint_32)i *
4078 (png_uint_32)png_gamma_shift[shift]) >> 4);
4079 for (j = 0; j < 256; j++)
4081 png_ptr->gamma_16_to_1[i][j] =
4082 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4083 65535.0, g) * 65535.0 + .5);
4087 if(png_ptr->screen_gamma > 0.000001)
4088 g = 1.0 / png_ptr->screen_gamma;
4089 else
4090 g = png_ptr->gamma; /* probably doing rgb_to_gray */
4092 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
4093 (png_uint_32)(num * png_sizeof (png_uint_16p)));
4095 for (i = 0; i < num; i++)
4097 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
4098 (png_uint_32)(256 * png_sizeof (png_uint_16)));
4100 ig = (((png_uint_32)i *
4101 (png_uint_32)png_gamma_shift[shift]) >> 4);
4102 for (j = 0; j < 256; j++)
4104 png_ptr->gamma_16_from_1[i][j] =
4105 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4106 65535.0, g) * 65535.0 + .5);
4110 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4114 #endif
4115 /* To do: install integer version of png_build_gamma_table here */
4116 #endif
4118 #if defined(PNG_MNG_FEATURES_SUPPORTED)
4119 /* undoes intrapixel differencing */
4120 void /* PRIVATE */
4121 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4123 png_debug(1, "in png_do_read_intrapixel\n");
4124 if (
4125 #if defined(PNG_USELESS_TESTS_SUPPORTED)
4126 row != NULL && row_info != NULL &&
4127 #endif
4128 (row_info->color_type & PNG_COLOR_MASK_COLOR))
4130 int bytes_per_pixel;
4131 png_uint_32 row_width = row_info->width;
4132 if (row_info->bit_depth == 8)
4134 png_bytep rp;
4135 png_uint_32 i;
4137 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4138 bytes_per_pixel = 3;
4139 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4140 bytes_per_pixel = 4;
4141 else
4142 return;
4144 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4146 *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
4147 *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
4150 else if (row_info->bit_depth == 16)
4152 png_bytep rp;
4153 png_uint_32 i;
4155 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4156 bytes_per_pixel = 6;
4157 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4158 bytes_per_pixel = 8;
4159 else
4160 return;
4162 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4164 png_uint_32 s0 = (*(rp ) << 8) | *(rp+1);
4165 png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3);
4166 png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5);
4167 png_uint_32 red = (png_uint_32)((s0+s1+65536L) & 0xffffL);
4168 png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL);
4169 *(rp ) = (png_byte)((red >> 8) & 0xff);
4170 *(rp+1) = (png_byte)(red & 0xff);
4171 *(rp+4) = (png_byte)((blue >> 8) & 0xff);
4172 *(rp+5) = (png_byte)(blue & 0xff);
4177 #endif /* PNG_MNG_FEATURES_SUPPORTED */