add a missing section header table index conversion
[tangerine.git] / compiler / libpng / pngrtran.c
blobcd12505b4a919e24407f87475bc44a9d2caedf8e
2 /* pngrtran.c - transforms the data in a row for PNG readers
4 * libpng 1.0.10 - March 30, 2001
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2001 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, sizeof(png_color_16));
89 png_ptr->background_gamma = (float)background_gamma;
90 png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
91 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
93 /* Note: if need_expand is set and color_type is either RGB or RGB_ALPHA
94 * (in which case need_expand is superfluous anyway), the background color
95 * might actually be gray yet not be flagged as such. This is not a problem
96 * for the current code, which uses PNG_BACKGROUND_IS_GRAY only to
97 * decide when to do the png_do_gray_to_rgb() transformation.
99 if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
100 (!need_expand && background_color->red == background_color->green &&
101 background_color->red == background_color->blue))
102 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
104 #endif
106 #if defined(PNG_READ_16_TO_8_SUPPORTED)
107 /* strip 16 bit depth files to 8 bit depth */
108 void PNGAPI
109 png_set_strip_16(png_structp png_ptr)
111 png_debug(1, "in png_set_strip_16\n");
112 png_ptr->transformations |= PNG_16_TO_8;
114 #endif
116 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
117 void PNGAPI
118 png_set_strip_alpha(png_structp png_ptr)
120 png_debug(1, "in png_set_strip_alpha\n");
121 png_ptr->transformations |= PNG_STRIP_ALPHA;
123 #endif
125 #if defined(PNG_READ_DITHER_SUPPORTED)
126 /* Dither file to 8 bit. Supply a palette, the current number
127 * of elements in the palette, the maximum number of elements
128 * allowed, and a histogram if possible. If the current number
129 * of colors is greater then the maximum number, the palette will be
130 * modified to fit in the maximum number. "full_dither" indicates
131 * whether we need a dithering cube set up for RGB images, or if we
132 * simply are reducing the number of colors in a paletted image.
135 typedef struct png_dsort_struct
137 struct png_dsort_struct FAR * next;
138 png_byte left;
139 png_byte right;
140 } png_dsort;
141 typedef png_dsort FAR * png_dsortp;
142 typedef png_dsort FAR * FAR * png_dsortpp;
144 void PNGAPI
145 png_set_dither(png_structp png_ptr, png_colorp palette,
146 int num_palette, int maximum_colors, png_uint_16p histogram,
147 int full_dither)
149 png_debug(1, "in png_set_dither\n");
150 png_ptr->transformations |= PNG_DITHER;
152 if (!full_dither)
154 int i;
156 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
157 (png_uint_32)(num_palette * sizeof (png_byte)));
158 for (i = 0; i < num_palette; i++)
159 png_ptr->dither_index[i] = (png_byte)i;
162 if (num_palette > maximum_colors)
164 if (histogram != NULL)
166 /* This is easy enough, just throw out the least used colors.
167 Perhaps not the best solution, but good enough. */
169 int i;
170 png_bytep sort;
172 /* initialize an array to sort colors */
173 sort = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_palette
174 * sizeof (png_byte)));
176 /* initialize the sort array */
177 for (i = 0; i < num_palette; i++)
178 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[sort[j]] < histogram[sort[j + 1]])
196 png_byte t;
198 t = sort[j];
199 sort[j] = sort[j + 1];
200 sort[j + 1] = t;
201 done = 0;
204 if (done)
205 break;
208 /* swap the palette around, and set up a table, if necessary */
209 if (full_dither)
211 int j = num_palette;
213 /* put all the useful colors within the max, but don't
214 move the others */
215 for (i = 0; i < maximum_colors; i++)
217 if ((int)sort[i] >= maximum_colors)
220 j--;
221 while ((int)sort[j] >= maximum_colors);
222 palette[i] = palette[j];
226 else
228 int j = num_palette;
230 /* move all the used colors inside the max limit, and
231 develop a translation table */
232 for (i = 0; i < maximum_colors; i++)
234 /* only move the colors we need to */
235 if ((int)sort[i] >= maximum_colors)
237 png_color tmp_color;
240 j--;
241 while ((int)sort[j] >= maximum_colors);
243 tmp_color = palette[j];
244 palette[j] = palette[i];
245 palette[i] = tmp_color;
246 /* indicate where the color went */
247 png_ptr->dither_index[j] = (png_byte)i;
248 png_ptr->dither_index[i] = (png_byte)j;
252 /* find closest color for those colors we are not using */
253 for (i = 0; i < num_palette; i++)
255 if ((int)png_ptr->dither_index[i] >= maximum_colors)
257 int min_d, k, min_k, d_index;
259 /* find the closest color to one we threw out */
260 d_index = png_ptr->dither_index[i];
261 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
262 for (k = 1, min_k = 0; k < maximum_colors; k++)
264 int d;
266 d = PNG_COLOR_DIST(palette[d_index], palette[k]);
268 if (d < min_d)
270 min_d = d;
271 min_k = k;
274 /* point to closest color */
275 png_ptr->dither_index[i] = (png_byte)min_k;
279 png_free(png_ptr, sort);
281 else
283 /* This is much harder to do simply (and quickly). Perhaps
284 we need to go through a median cut routine, but those
285 don't always behave themselves with only a few colors
286 as input. So we will just find the closest two colors,
287 and throw out one of them (chosen somewhat randomly).
288 [We don't understand this at all, so if someone wants to
289 work on improving it, be our guest - AED, GRP]
291 int i;
292 int max_d;
293 int num_new_palette;
294 png_dsortpp hash;
295 png_bytep index_to_palette;
296 /* where the original index currently is in the palette */
297 png_bytep palette_to_index;
298 /* which original index points to this palette color */
300 /* initialize palette index arrays */
301 index_to_palette = (png_bytep)png_malloc(png_ptr,
302 (png_uint_32)(num_palette * sizeof (png_byte)));
303 palette_to_index = (png_bytep)png_malloc(png_ptr,
304 (png_uint_32)(num_palette * sizeof (png_byte)));
306 /* initialize the sort array */
307 for (i = 0; i < num_palette; i++)
309 index_to_palette[i] = (png_byte)i;
310 palette_to_index[i] = (png_byte)i;
313 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
314 sizeof (png_dsortp)));
315 for (i = 0; i < 769; i++)
316 hash[i] = NULL;
317 /* png_memset(hash, 0, 769 * sizeof (png_dsortp)); */
319 num_new_palette = num_palette;
321 /* initial wild guess at how far apart the farthest pixel
322 pair we will be eliminating will be. Larger
323 numbers mean more areas will be allocated, Smaller
324 numbers run the risk of not saving enough data, and
325 having to do this all over again.
327 I have not done extensive checking on this number.
329 max_d = 96;
331 while (num_new_palette > maximum_colors)
333 for (i = 0; i < num_new_palette - 1; i++)
335 int j;
337 for (j = i + 1; j < num_new_palette; j++)
339 int d;
341 d = PNG_COLOR_DIST(palette[i], palette[j]);
343 if (d <= max_d)
345 png_dsortp t;
347 t = (png_dsortp)png_malloc(png_ptr, (png_uint_32)(sizeof
348 (png_dsort)));
349 t->next = hash[d];
350 t->left = (png_byte)i;
351 t->right = (png_byte)j;
352 hash[d] = t;
357 for (i = 0; i <= max_d; i++)
359 if (hash[i] != NULL)
361 png_dsortp p;
363 for (p = hash[i]; p; p = p->next)
365 if ((int)index_to_palette[p->left] < num_new_palette &&
366 (int)index_to_palette[p->right] < num_new_palette)
368 int j, next_j;
370 if (num_new_palette & 0x01)
372 j = p->left;
373 next_j = p->right;
375 else
377 j = p->right;
378 next_j = p->left;
381 num_new_palette--;
382 palette[index_to_palette[j]] = palette[num_new_palette];
383 if (!full_dither)
385 int k;
387 for (k = 0; k < num_palette; k++)
389 if (png_ptr->dither_index[k] ==
390 index_to_palette[j])
391 png_ptr->dither_index[k] =
392 index_to_palette[next_j];
393 if ((int)png_ptr->dither_index[k] ==
394 num_new_palette)
395 png_ptr->dither_index[k] =
396 index_to_palette[j];
400 index_to_palette[palette_to_index[num_new_palette]] =
401 index_to_palette[j];
402 palette_to_index[index_to_palette[j]] =
403 palette_to_index[num_new_palette];
405 index_to_palette[j] = (png_byte)num_new_palette;
406 palette_to_index[num_new_palette] = (png_byte)j;
408 if (num_new_palette <= maximum_colors)
409 break;
411 if (num_new_palette <= maximum_colors)
412 break;
416 for (i = 0; i < 769; i++)
418 if (hash[i] != NULL)
420 png_dsortp p = hash[i];
421 while (p)
423 png_dsortp t;
425 t = p->next;
426 png_free(png_ptr, p);
427 p = t;
430 hash[i] = 0;
432 max_d += 96;
434 png_free(png_ptr, hash);
435 png_free(png_ptr, palette_to_index);
436 png_free(png_ptr, index_to_palette);
438 num_palette = maximum_colors;
440 if (png_ptr->palette == NULL)
442 png_ptr->palette = palette;
444 png_ptr->num_palette = (png_uint_16)num_palette;
446 if (full_dither)
448 int i;
449 png_bytep distance;
450 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
451 PNG_DITHER_BLUE_BITS;
452 int num_red = (1 << PNG_DITHER_RED_BITS);
453 int num_green = (1 << PNG_DITHER_GREEN_BITS);
454 int num_blue = (1 << PNG_DITHER_BLUE_BITS);
455 png_size_t num_entries = ((png_size_t)1 << total_bits);
457 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
458 (png_uint_32)(num_entries * sizeof (png_byte)));
460 png_memset(png_ptr->palette_lookup, 0, num_entries * sizeof (png_byte));
462 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
463 sizeof(png_byte)));
465 png_memset(distance, 0xff, num_entries * sizeof(png_byte));
467 for (i = 0; i < num_palette; i++)
469 int ir, ig, ib;
470 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
471 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
472 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
474 for (ir = 0; ir < num_red; ir++)
476 int dr = abs(ir - r);
477 int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
479 for (ig = 0; ig < num_green; ig++)
481 int dg = abs(ig - g);
482 int dt = dr + dg;
483 int dm = ((dr > dg) ? dr : dg);
484 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
486 for (ib = 0; ib < num_blue; ib++)
488 int d_index = index_g | ib;
489 int db = abs(ib - b);
490 int dmax = ((dm > db) ? dm : db);
491 int d = dmax + dt + db;
493 if (d < (int)distance[d_index])
495 distance[d_index] = (png_byte)d;
496 png_ptr->palette_lookup[d_index] = (png_byte)i;
503 png_free(png_ptr, distance);
506 #endif
508 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
509 /* Transform the image from the file_gamma to the screen_gamma. We
510 * only do transformations on images where the file_gamma and screen_gamma
511 * are not close reciprocals, otherwise it slows things down slightly, and
512 * also needlessly introduces small errors.
514 void PNGAPI
515 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
517 png_debug(1, "in png_set_gamma\n");
518 if (fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD)
519 png_ptr->transformations |= PNG_GAMMA;
520 png_ptr->gamma = (float)file_gamma;
521 png_ptr->screen_gamma = (float)scrn_gamma;
523 #endif
525 #if defined(PNG_READ_EXPAND_SUPPORTED)
526 /* Expand paletted images to RGB, expand grayscale images of
527 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
528 * to alpha channels.
530 void PNGAPI
531 png_set_expand(png_structp png_ptr)
533 png_debug(1, "in png_set_expand\n");
534 png_ptr->transformations |= PNG_EXPAND;
537 /* GRR 19990627: the following three functions currently are identical
538 * to png_set_expand(). However, it is entirely reasonable that someone
539 * might wish to expand an indexed image to RGB but *not* expand a single,
540 * fully transparent palette entry to a full alpha channel--perhaps instead
541 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
542 * the transparent color with a particular RGB value, or drop tRNS entirely.
543 * IOW, a future version of the library may make the transformations flag
544 * a bit more fine-grained, with separate bits for each of these three
545 * functions.
547 * More to the point, these functions make it obvious what libpng will be
548 * doing, whereas "expand" can (and does) mean any number of things.
551 /* Expand paletted images to RGB. */
552 void PNGAPI
553 png_set_palette_to_rgb(png_structp png_ptr)
555 png_debug(1, "in png_set_expand\n");
556 png_ptr->transformations |= PNG_EXPAND;
559 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
560 void PNGAPI
561 png_set_gray_1_2_4_to_8(png_structp png_ptr)
563 png_debug(1, "in png_set_expand\n");
564 png_ptr->transformations |= PNG_EXPAND;
567 /* Expand tRNS chunks to alpha channels. */
568 void PNGAPI
569 png_set_tRNS_to_alpha(png_structp png_ptr)
571 png_debug(1, "in png_set_expand\n");
572 png_ptr->transformations |= PNG_EXPAND;
574 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
576 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
577 void PNGAPI
578 png_set_gray_to_rgb(png_structp png_ptr)
580 png_debug(1, "in png_set_gray_to_rgb\n");
581 png_ptr->transformations |= PNG_GRAY_TO_RGB;
583 #endif
585 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
586 #if defined(PNG_FLOATING_POINT_SUPPORTED)
587 /* Convert a RGB image to a grayscale of the same width. This allows us,
588 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
591 void PNGAPI
592 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
593 double green)
595 int red_fixed = (int)((float)red*100000.0 + 0.5);
596 int green_fixed = (int)((float)green*100000.0 + 0.5);
597 png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
599 #endif
601 void PNGAPI
602 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
603 png_fixed_point red, png_fixed_point green)
605 png_debug(1, "in png_set_rgb_to_gray\n");
606 switch(error_action)
608 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
609 break;
610 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
611 break;
612 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
614 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
615 #if defined(PNG_READ_EXPAND_SUPPORTED)
616 png_ptr->transformations |= PNG_EXPAND;
617 #else
619 png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
620 png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
622 #endif
624 png_uint_16 red_int, green_int;
625 if(red < 0 || green < 0)
627 red_int = 6968; /* .212671 * 32768 + .5 */
628 green_int = 23434; /* .715160 * 32768 + .5 */
630 else if(red + green < 100000L)
632 red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
633 green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
635 else
637 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
638 red_int = 6968;
639 green_int = 23434;
641 png_ptr->rgb_to_gray_red_coeff = red_int;
642 png_ptr->rgb_to_gray_green_coeff = green_int;
643 png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int);
646 #endif
648 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
649 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
650 defined(PNG_LEGACY_SUPPORTED)
651 void PNGAPI
652 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
653 read_user_transform_fn)
655 png_debug(1, "in png_set_read_user_transform_fn\n");
656 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
657 png_ptr->transformations |= PNG_USER_TRANSFORM;
658 png_ptr->read_user_transform_fn = read_user_transform_fn;
659 #endif
660 #ifdef PNG_LEGACY_SUPPORTED
661 if(read_user_transform_fn)
662 png_warning(png_ptr,
663 "This version of libpng does not support user transforms");
664 #endif
666 #endif
668 /* Initialize everything needed for the read. This includes modifying
669 * the palette.
671 void /* PRIVATE */
672 png_init_read_transformations(png_structp png_ptr)
674 png_debug(1, "in png_init_read_transformations\n");
675 #if defined(PNG_USELESS_TESTS_SUPPORTED)
676 if(png_ptr != NULL)
677 #endif
679 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
680 || defined(PNG_READ_GAMMA_SUPPORTED)
681 int color_type = png_ptr->color_type;
682 #endif
684 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
685 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
686 (png_ptr->transformations & PNG_EXPAND))
688 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
690 /* expand background chunk. */
691 switch (png_ptr->bit_depth)
693 case 1:
694 png_ptr->background.gray *= (png_uint_16)0xff;
695 png_ptr->background.red = png_ptr->background.green =
696 png_ptr->background.blue = png_ptr->background.gray;
697 break;
698 case 2:
699 png_ptr->background.gray *= (png_uint_16)0x55;
700 png_ptr->background.red = png_ptr->background.green =
701 png_ptr->background.blue = png_ptr->background.gray;
702 break;
703 case 4:
704 png_ptr->background.gray *= (png_uint_16)0x11;
705 png_ptr->background.red = png_ptr->background.green =
706 png_ptr->background.blue = png_ptr->background.gray;
707 break;
708 case 8:
709 case 16:
710 png_ptr->background.red = png_ptr->background.green =
711 png_ptr->background.blue = png_ptr->background.gray;
712 break;
715 else if (color_type == PNG_COLOR_TYPE_PALETTE)
717 png_ptr->background.red =
718 png_ptr->palette[png_ptr->background.index].red;
719 png_ptr->background.green =
720 png_ptr->palette[png_ptr->background.index].green;
721 png_ptr->background.blue =
722 png_ptr->palette[png_ptr->background.index].blue;
724 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
725 if (png_ptr->transformations & PNG_INVERT_ALPHA)
727 #if defined(PNG_READ_EXPAND_SUPPORTED)
728 if (!(png_ptr->transformations & PNG_EXPAND))
729 #endif
731 /* invert the alpha channel (in tRNS) unless the pixels are
732 going to be expanded, in which case leave it for later */
733 int i,istop;
734 istop=(int)png_ptr->num_trans;
735 for (i=0; i<istop; i++)
736 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
739 #endif
743 #endif
745 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
746 png_ptr->background_1 = png_ptr->background;
747 #endif
748 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
749 if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
751 png_build_gamma_table(png_ptr);
752 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
753 if (png_ptr->transformations & PNG_BACKGROUND)
755 if (color_type == PNG_COLOR_TYPE_PALETTE)
757 png_color back, back_1;
758 png_colorp palette = png_ptr->palette;
759 int num_palette = png_ptr->num_palette;
760 int i;
761 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
763 back.red = png_ptr->gamma_table[png_ptr->background.red];
764 back.green = png_ptr->gamma_table[png_ptr->background.green];
765 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
767 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
768 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
769 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
771 else
773 double g, gs;
775 switch (png_ptr->background_gamma_type)
777 case PNG_BACKGROUND_GAMMA_SCREEN:
778 g = (png_ptr->screen_gamma);
779 gs = 1.0;
780 break;
781 case PNG_BACKGROUND_GAMMA_FILE:
782 g = 1.0 / (png_ptr->gamma);
783 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
784 break;
785 case PNG_BACKGROUND_GAMMA_UNIQUE:
786 g = 1.0 / (png_ptr->background_gamma);
787 gs = 1.0 / (png_ptr->background_gamma *
788 png_ptr->screen_gamma);
789 break;
790 default:
791 g = 1.0; /* back_1 */
792 gs = 1.0; /* back */
795 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
797 back.red = (png_byte)png_ptr->background.red;
798 back.green = (png_byte)png_ptr->background.green;
799 back.blue = (png_byte)png_ptr->background.blue;
801 else
803 back.red = (png_byte)(pow(
804 (double)png_ptr->background.red/255, gs) * 255.0 + .5);
805 back.green = (png_byte)(pow(
806 (double)png_ptr->background.green/255, gs) * 255.0 + .5);
807 back.blue = (png_byte)(pow(
808 (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
811 back_1.red = (png_byte)(pow(
812 (double)png_ptr->background.red/255, g) * 255.0 + .5);
813 back_1.green = (png_byte)(pow(
814 (double)png_ptr->background.green/255, g) * 255.0 + .5);
815 back_1.blue = (png_byte)(pow(
816 (double)png_ptr->background.blue/255, g) * 255.0 + .5);
818 for (i = 0; i < num_palette; i++)
820 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
822 if (png_ptr->trans[i] == 0)
824 palette[i] = back;
826 else /* if (png_ptr->trans[i] != 0xff) */
828 png_byte v, w;
830 v = png_ptr->gamma_to_1[palette[i].red];
831 png_composite(w, v, png_ptr->trans[i], back_1.red);
832 palette[i].red = png_ptr->gamma_from_1[w];
834 v = png_ptr->gamma_to_1[palette[i].green];
835 png_composite(w, v, png_ptr->trans[i], back_1.green);
836 palette[i].green = png_ptr->gamma_from_1[w];
838 v = png_ptr->gamma_to_1[palette[i].blue];
839 png_composite(w, v, png_ptr->trans[i], back_1.blue);
840 palette[i].blue = png_ptr->gamma_from_1[w];
843 else
845 palette[i].red = png_ptr->gamma_table[palette[i].red];
846 palette[i].green = png_ptr->gamma_table[palette[i].green];
847 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
851 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN)*/
852 else
853 /* color_type != PNG_COLOR_TYPE_PALETTE */
855 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
856 double g = 1.0;
857 double gs = 1.0;
859 switch (png_ptr->background_gamma_type)
861 case PNG_BACKGROUND_GAMMA_SCREEN:
862 g = (png_ptr->screen_gamma);
863 gs = 1.0;
864 break;
865 case PNG_BACKGROUND_GAMMA_FILE:
866 g = 1.0 / (png_ptr->gamma);
867 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
868 break;
869 case PNG_BACKGROUND_GAMMA_UNIQUE:
870 g = 1.0 / (png_ptr->background_gamma);
871 gs = 1.0 / (png_ptr->background_gamma *
872 png_ptr->screen_gamma);
873 break;
876 if (color_type & PNG_COLOR_MASK_COLOR)
878 /* RGB or RGBA */
879 png_ptr->background_1.red = (png_uint_16)(pow(
880 (double)png_ptr->background.red / m, g) * m + .5);
881 png_ptr->background_1.green = (png_uint_16)(pow(
882 (double)png_ptr->background.green / m, g) * m + .5);
883 png_ptr->background_1.blue = (png_uint_16)(pow(
884 (double)png_ptr->background.blue / m, g) * m + .5);
885 png_ptr->background.red = (png_uint_16)(pow(
886 (double)png_ptr->background.red / m, gs) * m + .5);
887 png_ptr->background.green = (png_uint_16)(pow(
888 (double)png_ptr->background.green / m, gs) * m + .5);
889 png_ptr->background.blue = (png_uint_16)(pow(
890 (double)png_ptr->background.blue / m, gs) * m + .5);
892 else
894 /* GRAY or GRAY ALPHA */
895 png_ptr->background_1.gray = (png_uint_16)(pow(
896 (double)png_ptr->background.gray / m, g) * m + .5);
897 png_ptr->background.gray = (png_uint_16)(pow(
898 (double)png_ptr->background.gray / m, gs) * m + .5);
902 else
903 /* transformation does not include PNG_BACKGROUND */
904 #endif
905 if (color_type == PNG_COLOR_TYPE_PALETTE)
907 png_colorp palette = png_ptr->palette;
908 int num_palette = png_ptr->num_palette;
909 int i;
911 for (i = 0; i < num_palette; i++)
913 palette[i].red = png_ptr->gamma_table[palette[i].red];
914 palette[i].green = png_ptr->gamma_table[palette[i].green];
915 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
919 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
920 else
921 #endif
922 #endif
923 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
924 /* No GAMMA transformation */
925 if ((png_ptr->transformations & PNG_BACKGROUND) &&
926 (color_type == PNG_COLOR_TYPE_PALETTE))
928 int i;
929 int istop = (int)png_ptr->num_trans;
930 png_color back;
931 png_colorp palette = png_ptr->palette;
933 back.red = (png_byte)png_ptr->background.red;
934 back.green = (png_byte)png_ptr->background.green;
935 back.blue = (png_byte)png_ptr->background.blue;
937 for (i = 0; i < istop; i++)
939 if (png_ptr->trans[i] == 0)
941 palette[i] = back;
943 else if (png_ptr->trans[i] != 0xff)
945 /* The png_composite() macro is defined in png.h */
946 png_composite(palette[i].red, palette[i].red,
947 png_ptr->trans[i], back.red);
948 png_composite(palette[i].green, palette[i].green,
949 png_ptr->trans[i], back.green);
950 png_composite(palette[i].blue, palette[i].blue,
951 png_ptr->trans[i], back.blue);
955 #endif
957 #if defined(PNG_READ_SHIFT_SUPPORTED)
958 if ((png_ptr->transformations & PNG_SHIFT) &&
959 (color_type == PNG_COLOR_TYPE_PALETTE))
961 png_uint_16 i;
962 png_uint_16 istop = png_ptr->num_palette;
963 int sr = 8 - png_ptr->sig_bit.red;
964 int sg = 8 - png_ptr->sig_bit.green;
965 int sb = 8 - png_ptr->sig_bit.blue;
967 if (sr < 0 || sr > 8)
968 sr = 0;
969 if (sg < 0 || sg > 8)
970 sg = 0;
971 if (sb < 0 || sb > 8)
972 sb = 0;
973 for (i = 0; i < istop; i++)
975 png_ptr->palette[i].red >>= sr;
976 png_ptr->palette[i].green >>= sg;
977 png_ptr->palette[i].blue >>= sb;
980 #endif
982 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
983 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
984 if(png_ptr)
985 return;
986 #endif
989 /* Modify the info structure to reflect the transformations. The
990 * info should be updated so a PNG file could be written with it,
991 * assuming the transformations result in valid PNG data.
993 void /* PRIVATE */
994 png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
996 png_debug(1, "in png_read_transform_info\n");
997 #if defined(PNG_READ_EXPAND_SUPPORTED)
998 if (png_ptr->transformations & PNG_EXPAND)
1000 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1002 if (png_ptr->num_trans)
1003 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1004 else
1005 info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1006 info_ptr->bit_depth = 8;
1007 info_ptr->num_trans = 0;
1009 else
1011 if (png_ptr->num_trans)
1012 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1013 if (info_ptr->bit_depth < 8)
1014 info_ptr->bit_depth = 8;
1015 info_ptr->num_trans = 0;
1018 #endif
1020 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1021 if (png_ptr->transformations & PNG_BACKGROUND)
1023 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1024 info_ptr->num_trans = 0;
1025 info_ptr->background = png_ptr->background;
1027 #endif
1029 #if defined(PNG_READ_GAMMA_SUPPORTED)
1030 if (png_ptr->transformations & PNG_GAMMA)
1032 #ifdef PNG_FLOATING_POINT_SUPPORTED
1033 info_ptr->gamma = png_ptr->gamma;
1034 #endif
1035 #ifdef PNG_FIXED_POINT_SUPPORTED
1036 info_ptr->int_gamma = png_ptr->int_gamma;
1037 #endif
1039 #endif
1041 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1042 if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
1043 info_ptr->bit_depth = 8;
1044 #endif
1046 #if defined(PNG_READ_DITHER_SUPPORTED)
1047 if (png_ptr->transformations & PNG_DITHER)
1049 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1050 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1051 png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1053 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1056 #endif
1058 #if defined(PNG_READ_PACK_SUPPORTED)
1059 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
1060 info_ptr->bit_depth = 8;
1061 #endif
1063 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1064 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1065 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1066 #endif
1068 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1069 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1070 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1071 #endif
1073 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1074 info_ptr->channels = 1;
1075 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1076 info_ptr->channels = 3;
1077 else
1078 info_ptr->channels = 1;
1080 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1081 if (png_ptr->transformations & PNG_STRIP_ALPHA)
1082 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1083 #endif
1085 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1086 info_ptr->channels++;
1088 #if defined(PNG_READ_FILLER_SUPPORTED)
1089 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
1090 if ((png_ptr->transformations & PNG_FILLER) &&
1091 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1092 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1094 info_ptr->channels++;
1095 #if 0 /* if adding a true alpha channel not just filler */
1096 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1097 #endif
1099 #endif
1101 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1102 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1103 if(png_ptr->transformations & PNG_USER_TRANSFORM)
1105 if(info_ptr->bit_depth < png_ptr->user_transform_depth)
1106 info_ptr->bit_depth = png_ptr->user_transform_depth;
1107 if(info_ptr->channels < png_ptr->user_transform_channels)
1108 info_ptr->channels = png_ptr->user_transform_channels;
1110 #endif
1112 info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1113 info_ptr->bit_depth);
1114 info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3);
1116 #if !defined(PNG_READ_EXPAND_SUPPORTED)
1117 if(png_ptr)
1118 return;
1119 #endif
1122 /* Transform the row. The order of transformations is significant,
1123 * and is very touchy. If you add a transformation, take care to
1124 * decide how it fits in with the other transformations here.
1126 void /* PRIVATE */
1127 png_do_read_transformations(png_structp png_ptr)
1129 png_debug(1, "in png_do_read_transformations\n");
1130 #if !defined(PNG_USELESS_TESTS_SUPPORTED)
1131 if (png_ptr->row_buf == NULL)
1133 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1134 char msg[50];
1136 sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
1137 png_ptr->pass);
1138 png_error(png_ptr, msg);
1139 #else
1140 png_error(png_ptr, "NULL row buffer");
1141 #endif
1143 #endif
1145 #if defined(PNG_READ_EXPAND_SUPPORTED)
1146 if (png_ptr->transformations & PNG_EXPAND)
1148 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1150 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1151 png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1153 else
1155 if (png_ptr->num_trans)
1156 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1157 &(png_ptr->trans_values));
1158 else
1159 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1160 NULL);
1163 #endif
1165 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1166 if (png_ptr->transformations & PNG_STRIP_ALPHA)
1167 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1168 PNG_FLAG_FILLER_AFTER);
1169 #endif
1171 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1172 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1174 int rgb_error =
1175 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1176 if(rgb_error)
1178 png_ptr->rgb_to_gray_status=1;
1179 if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
1180 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1181 if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
1182 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1185 #endif
1188 From Andreas Dilger e-mail to png-implement, 26 March 1998:
1190 In most cases, the "simple transparency" should be done prior to doing
1191 gray-to-RGB, or you will have to test 3x as many bytes to check if a
1192 pixel is transparent. You would also need to make sure that the
1193 transparency information is upgraded to RGB.
1195 To summarize, the current flow is:
1196 - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1197 with background "in place" if transparent,
1198 convert to RGB if necessary
1199 - Gray + alpha -> composite with gray background and remove alpha bytes,
1200 convert to RGB if necessary
1202 To support RGB backgrounds for gray images we need:
1203 - Gray + simple transparency -> convert to RGB + simple transparency, compare
1204 3 or 6 bytes and composite with background
1205 "in place" if transparent (3x compare/pixel
1206 compared to doing composite with gray bkgrnd)
1207 - Gray + alpha -> convert to RGB + alpha, composite with background and
1208 remove alpha bytes (3x float operations/pixel
1209 compared with composite on gray background)
1211 Greg's change will do this. The reason it wasn't done before is for
1212 performance, as this increases the per-pixel operations. If we would check
1213 in advance if the background was gray or RGB, and position the gray-to-RGB
1214 transform appropriately, then it would save a lot of work/time.
1217 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1218 /* if gray -> RGB, do so now only if background is non-gray; else do later
1219 * for performance reasons */
1220 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1221 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1222 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1223 #endif
1225 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1226 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1227 ((png_ptr->num_trans != 0 ) ||
1228 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
1229 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1230 &(png_ptr->trans_values), &(png_ptr->background),
1231 &(png_ptr->background_1),
1232 png_ptr->gamma_table, png_ptr->gamma_from_1,
1233 png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1234 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1235 png_ptr->gamma_shift);
1236 #endif
1238 #if defined(PNG_READ_GAMMA_SUPPORTED)
1239 if ((png_ptr->transformations & PNG_GAMMA) &&
1240 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1241 !((png_ptr->transformations & PNG_BACKGROUND) &&
1242 ((png_ptr->num_trans != 0) ||
1243 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1244 #endif
1245 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
1246 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1247 png_ptr->gamma_table, png_ptr->gamma_16_table,
1248 png_ptr->gamma_shift);
1249 #endif
1251 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1252 if (png_ptr->transformations & PNG_16_TO_8)
1253 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
1254 #endif
1256 #if defined(PNG_READ_DITHER_SUPPORTED)
1257 if (png_ptr->transformations & PNG_DITHER)
1259 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1260 png_ptr->palette_lookup, png_ptr->dither_index);
1261 if(png_ptr->row_info.rowbytes == (png_uint_32)0)
1262 png_error(png_ptr, "png_do_dither returned rowbytes=0");
1264 #endif
1266 #if defined(PNG_READ_INVERT_SUPPORTED)
1267 if (png_ptr->transformations & PNG_INVERT_MONO)
1268 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
1269 #endif
1271 #if defined(PNG_READ_SHIFT_SUPPORTED)
1272 if (png_ptr->transformations & PNG_SHIFT)
1273 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1274 &(png_ptr->shift));
1275 #endif
1277 #if defined(PNG_READ_PACK_SUPPORTED)
1278 if (png_ptr->transformations & PNG_PACK)
1279 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
1280 #endif
1282 #if defined(PNG_READ_BGR_SUPPORTED)
1283 if (png_ptr->transformations & PNG_BGR)
1284 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
1285 #endif
1287 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
1288 if (png_ptr->transformations & PNG_PACKSWAP)
1289 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1290 #endif
1292 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1293 /* if gray -> RGB, do so now only if we did not do so above */
1294 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1295 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1296 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1297 #endif
1299 #if defined(PNG_READ_FILLER_SUPPORTED)
1300 if (png_ptr->transformations & PNG_FILLER)
1301 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1302 (png_uint_32)png_ptr->filler, png_ptr->flags);
1303 #endif
1305 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1306 if (png_ptr->transformations & PNG_INVERT_ALPHA)
1307 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1308 #endif
1310 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1311 if (png_ptr->transformations & PNG_SWAP_ALPHA)
1312 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1313 #endif
1315 #if defined(PNG_READ_SWAP_SUPPORTED)
1316 if (png_ptr->transformations & PNG_SWAP_BYTES)
1317 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1318 #endif
1320 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1321 if (png_ptr->transformations & PNG_USER_TRANSFORM)
1323 if(png_ptr->read_user_transform_fn != NULL)
1324 (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1325 (png_ptr, /* png_ptr */
1326 &(png_ptr->row_info), /* row_info: */
1327 /* png_uint_32 width; width of row */
1328 /* png_uint_32 rowbytes; number of bytes in row */
1329 /* png_byte color_type; color type of pixels */
1330 /* png_byte bit_depth; bit depth of samples */
1331 /* png_byte channels; number of channels (1-4) */
1332 /* png_byte pixel_depth; bits per pixel (depth*channels) */
1333 png_ptr->row_buf + 1); /* start of pixel data for row */
1334 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
1335 if(png_ptr->user_transform_depth)
1336 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1337 if(png_ptr->user_transform_channels)
1338 png_ptr->row_info.channels = png_ptr->user_transform_channels;
1339 #endif
1340 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1341 png_ptr->row_info.channels);
1342 png_ptr->row_info.rowbytes = (png_ptr->row_info.width *
1343 png_ptr->row_info.pixel_depth+7)>>3;
1345 #endif
1349 #if defined(PNG_READ_PACK_SUPPORTED)
1350 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1351 * without changing the actual values. Thus, if you had a row with
1352 * a bit depth of 1, you would end up with bytes that only contained
1353 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1354 * png_do_shift() after this.
1356 void /* PRIVATE */
1357 png_do_unpack(png_row_infop row_info, png_bytep row)
1359 png_debug(1, "in png_do_unpack\n");
1360 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1361 if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1362 #else
1363 if (row_info->bit_depth < 8)
1364 #endif
1366 png_uint_32 i;
1367 png_uint_32 row_width=row_info->width;
1369 switch (row_info->bit_depth)
1371 case 1:
1373 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1374 png_bytep dp = row + (png_size_t)row_width - 1;
1375 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
1376 for (i = 0; i < row_width; i++)
1378 *dp = (png_byte)((*sp >> shift) & 0x01);
1379 if (shift == 7)
1381 shift = 0;
1382 sp--;
1384 else
1385 shift++;
1387 dp--;
1389 break;
1391 case 2:
1394 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1395 png_bytep dp = row + (png_size_t)row_width - 1;
1396 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
1397 for (i = 0; i < row_width; i++)
1399 *dp = (png_byte)((*sp >> shift) & 0x03);
1400 if (shift == 6)
1402 shift = 0;
1403 sp--;
1405 else
1406 shift += 2;
1408 dp--;
1410 break;
1412 case 4:
1414 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1415 png_bytep dp = row + (png_size_t)row_width - 1;
1416 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
1417 for (i = 0; i < row_width; i++)
1419 *dp = (png_byte)((*sp >> shift) & 0x0f);
1420 if (shift == 4)
1422 shift = 0;
1423 sp--;
1425 else
1426 shift = 4;
1428 dp--;
1430 break;
1433 row_info->bit_depth = 8;
1434 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1435 row_info->rowbytes = row_width * row_info->channels;
1438 #endif
1440 #if defined(PNG_READ_SHIFT_SUPPORTED)
1441 /* Reverse the effects of png_do_shift. This routine merely shifts the
1442 * pixels back to their significant bits values. Thus, if you have
1443 * a row of bit depth 8, but only 5 are significant, this will shift
1444 * the values back to 0 through 31.
1446 void /* PRIVATE */
1447 png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
1449 png_debug(1, "in png_do_unshift\n");
1450 if (
1451 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1452 row != NULL && row_info != NULL && sig_bits != NULL &&
1453 #endif
1454 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
1456 int shift[4];
1457 int channels = 0;
1458 int c;
1459 png_uint_16 value = 0;
1460 png_uint_32 row_width = row_info->width;
1462 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1464 shift[channels++] = row_info->bit_depth - sig_bits->red;
1465 shift[channels++] = row_info->bit_depth - sig_bits->green;
1466 shift[channels++] = row_info->bit_depth - sig_bits->blue;
1468 else
1470 shift[channels++] = row_info->bit_depth - sig_bits->gray;
1472 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1474 shift[channels++] = row_info->bit_depth - sig_bits->alpha;
1477 for (c = 0; c < channels; c++)
1479 if (shift[c] <= 0)
1480 shift[c] = 0;
1481 else
1482 value = 1;
1485 if (!value)
1486 return;
1488 switch (row_info->bit_depth)
1490 case 2:
1492 png_bytep bp;
1493 png_uint_32 i;
1494 png_uint_32 istop = row_info->rowbytes;
1496 for (bp = row, i = 0; i < istop; i++)
1498 *bp >>= 1;
1499 *bp++ &= 0x55;
1501 break;
1503 case 4:
1505 png_bytep bp = row;
1506 png_uint_32 i;
1507 png_uint_32 istop = row_info->rowbytes;
1508 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1509 (png_byte)((int)0xf >> shift[0]));
1511 for (i = 0; i < istop; i++)
1513 *bp >>= shift[0];
1514 *bp++ &= mask;
1516 break;
1518 case 8:
1520 png_bytep bp = row;
1521 png_uint_32 i;
1522 png_uint_32 istop = row_width * channels;
1524 for (i = 0; i < istop; i++)
1526 *bp++ >>= shift[i%channels];
1528 break;
1530 case 16:
1532 png_bytep bp = row;
1533 png_uint_32 i;
1534 png_uint_32 istop = channels * row_width;
1536 for (i = 0; i < istop; i++)
1538 value = (png_uint_16)((*bp << 8) + *(bp + 1));
1539 value >>= shift[i%channels];
1540 *bp++ = (png_byte)(value >> 8);
1541 *bp++ = (png_byte)(value & 0xff);
1543 break;
1548 #endif
1550 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1551 /* chop rows of bit depth 16 down to 8 */
1552 void /* PRIVATE */
1553 png_do_chop(png_row_infop row_info, png_bytep row)
1555 png_debug(1, "in png_do_chop\n");
1556 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1557 if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1558 #else
1559 if (row_info->bit_depth == 16)
1560 #endif
1562 png_bytep sp = row;
1563 png_bytep dp = row;
1564 png_uint_32 i;
1565 png_uint_32 istop = row_info->width * row_info->channels;
1567 for (i = 0; i<istop; i++, sp += 2, dp++)
1569 #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
1570 /* This does a more accurate scaling of the 16-bit color
1571 * value, rather than a simple low-byte truncation.
1573 * What the ideal calculation should be:
1574 * *dp = (((((png_uint_32)(*sp) << 8) |
1575 * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1577 * GRR: no, I think this is what it really should be:
1578 * *dp = (((((png_uint_32)(*sp) << 8) |
1579 * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1581 * GRR: here's the exact calculation with shifts:
1582 * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1583 * *dp = (temp - (temp >> 8)) >> 8;
1585 * Approximate calculation with shift/add instead of multiply/divide:
1586 * *dp = ((((png_uint_32)(*sp) << 8) |
1587 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1589 * What we actually do to avoid extra shifting and conversion:
1592 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1593 #else
1594 /* Simply discard the low order byte */
1595 *dp = *sp;
1596 #endif
1598 row_info->bit_depth = 8;
1599 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1600 row_info->rowbytes = row_info->width * row_info->channels;
1603 #endif
1605 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1606 void /* PRIVATE */
1607 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1609 png_debug(1, "in png_do_read_swap_alpha\n");
1610 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1611 if (row != NULL && row_info != NULL)
1612 #endif
1614 png_uint_32 row_width = row_info->width;
1615 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1617 /* This converts from RGBA to ARGB */
1618 if (row_info->bit_depth == 8)
1620 png_bytep sp = row + row_info->rowbytes;
1621 png_bytep dp = sp;
1622 png_byte save;
1623 png_uint_32 i;
1625 for (i = 0; i < row_width; i++)
1627 save = *(--sp);
1628 *(--dp) = *(--sp);
1629 *(--dp) = *(--sp);
1630 *(--dp) = *(--sp);
1631 *(--dp) = save;
1634 /* This converts from RRGGBBAA to AARRGGBB */
1635 else
1637 png_bytep sp = row + row_info->rowbytes;
1638 png_bytep dp = sp;
1639 png_byte save[2];
1640 png_uint_32 i;
1642 for (i = 0; i < row_width; i++)
1644 save[0] = *(--sp);
1645 save[1] = *(--sp);
1646 *(--dp) = *(--sp);
1647 *(--dp) = *(--sp);
1648 *(--dp) = *(--sp);
1649 *(--dp) = *(--sp);
1650 *(--dp) = *(--sp);
1651 *(--dp) = *(--sp);
1652 *(--dp) = save[0];
1653 *(--dp) = save[1];
1657 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1659 /* This converts from GA to AG */
1660 if (row_info->bit_depth == 8)
1662 png_bytep sp = row + row_info->rowbytes;
1663 png_bytep dp = sp;
1664 png_byte save;
1665 png_uint_32 i;
1667 for (i = 0; i < row_width; i++)
1669 save = *(--sp);
1670 *(--dp) = *(--sp);
1671 *(--dp) = save;
1674 /* This converts from GGAA to AAGG */
1675 else
1677 png_bytep sp = row + row_info->rowbytes;
1678 png_bytep dp = sp;
1679 png_byte save[2];
1680 png_uint_32 i;
1682 for (i = 0; i < row_width; i++)
1684 save[0] = *(--sp);
1685 save[1] = *(--sp);
1686 *(--dp) = *(--sp);
1687 *(--dp) = *(--sp);
1688 *(--dp) = save[0];
1689 *(--dp) = save[1];
1695 #endif
1697 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1698 void /* PRIVATE */
1699 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1701 png_debug(1, "in png_do_read_invert_alpha\n");
1702 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1703 if (row != NULL && row_info != NULL)
1704 #endif
1706 png_uint_32 row_width = row_info->width;
1707 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1709 /* This inverts the alpha channel in RGBA */
1710 if (row_info->bit_depth == 8)
1712 png_bytep sp = row + row_info->rowbytes;
1713 png_bytep dp = sp;
1714 png_uint_32 i;
1716 for (i = 0; i < row_width; i++)
1718 *(--dp) = (png_byte)(255 - *(--sp));
1720 /* This does nothing:
1721 *(--dp) = *(--sp);
1722 *(--dp) = *(--sp);
1723 *(--dp) = *(--sp);
1724 We can replace it with:
1726 sp-=3;
1727 dp=sp;
1730 /* This inverts the alpha channel in RRGGBBAA */
1731 else
1733 png_bytep sp = row + row_info->rowbytes;
1734 png_bytep dp = sp;
1735 png_uint_32 i;
1737 for (i = 0; i < row_width; i++)
1739 *(--dp) = (png_byte)(255 - *(--sp));
1740 *(--dp) = (png_byte)(255 - *(--sp));
1742 /* This does nothing:
1743 *(--dp) = *(--sp);
1744 *(--dp) = *(--sp);
1745 *(--dp) = *(--sp);
1746 *(--dp) = *(--sp);
1747 *(--dp) = *(--sp);
1748 *(--dp) = *(--sp);
1749 We can replace it with:
1751 sp-=6;
1752 dp=sp;
1756 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1758 /* This inverts the alpha channel in GA */
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));
1768 *(--dp) = *(--sp);
1771 /* This inverts the alpha channel in GGAA */
1772 else
1774 png_bytep sp = row + row_info->rowbytes;
1775 png_bytep dp = sp;
1776 png_uint_32 i;
1778 for (i = 0; i < row_width; i++)
1780 *(--dp) = (png_byte)(255 - *(--sp));
1781 *(--dp) = (png_byte)(255 - *(--sp));
1783 *(--dp) = *(--sp);
1784 *(--dp) = *(--sp);
1786 sp-=2;
1787 dp=sp;
1793 #endif
1795 #if defined(PNG_READ_FILLER_SUPPORTED)
1796 /* Add filler channel if we have RGB color */
1797 void /* PRIVATE */
1798 png_do_read_filler(png_row_infop row_info, png_bytep row,
1799 png_uint_32 filler, png_uint_32 flags)
1801 png_uint_32 i;
1802 png_uint_32 row_width = row_info->width;
1804 png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
1805 png_byte lo_filler = (png_byte)(filler & 0xff);
1807 png_debug(1, "in png_do_read_filler\n");
1808 if (
1809 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1810 row != NULL && row_info != NULL &&
1811 #endif
1812 row_info->color_type == PNG_COLOR_TYPE_GRAY)
1814 if(row_info->bit_depth == 8)
1816 /* This changes the data from G to GX */
1817 if (flags & PNG_FLAG_FILLER_AFTER)
1819 png_bytep sp = row + (png_size_t)row_width;
1820 png_bytep dp = sp + (png_size_t)row_width;
1821 for (i = 1; i < row_width; i++)
1823 *(--dp) = lo_filler;
1824 *(--dp) = *(--sp);
1826 *(--dp) = lo_filler;
1827 row_info->channels = 2;
1828 row_info->pixel_depth = 16;
1829 row_info->rowbytes = row_width * 2;
1831 /* This changes the data from G to XG */
1832 else
1834 png_bytep sp = row + (png_size_t)row_width;
1835 png_bytep dp = sp + (png_size_t)row_width;
1836 for (i = 0; i < row_width; i++)
1838 *(--dp) = *(--sp);
1839 *(--dp) = lo_filler;
1841 row_info->channels = 2;
1842 row_info->pixel_depth = 16;
1843 row_info->rowbytes = row_width * 2;
1846 else if(row_info->bit_depth == 16)
1848 /* This changes the data from GG to GGXX */
1849 if (flags & PNG_FLAG_FILLER_AFTER)
1851 png_bytep sp = row + (png_size_t)row_width;
1852 png_bytep dp = sp + (png_size_t)row_width;
1853 for (i = 1; i < row_width; i++)
1855 *(--dp) = hi_filler;
1856 *(--dp) = lo_filler;
1857 *(--dp) = *(--sp);
1858 *(--dp) = *(--sp);
1860 *(--dp) = hi_filler;
1861 *(--dp) = lo_filler;
1862 row_info->channels = 2;
1863 row_info->pixel_depth = 32;
1864 row_info->rowbytes = row_width * 4;
1866 /* This changes the data from GG to XXGG */
1867 else
1869 png_bytep sp = row + (png_size_t)row_width;
1870 png_bytep dp = sp + (png_size_t)row_width;
1871 for (i = 0; i < row_width; i++)
1873 *(--dp) = *(--sp);
1874 *(--dp) = *(--sp);
1875 *(--dp) = hi_filler;
1876 *(--dp) = lo_filler;
1878 row_info->channels = 2;
1879 row_info->pixel_depth = 32;
1880 row_info->rowbytes = row_width * 4;
1883 } /* COLOR_TYPE == GRAY */
1884 else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
1886 if(row_info->bit_depth == 8)
1888 /* This changes the data from RGB to RGBX */
1889 if (flags & PNG_FLAG_FILLER_AFTER)
1891 png_bytep sp = row + (png_size_t)row_width * 3;
1892 png_bytep dp = sp + (png_size_t)row_width;
1893 for (i = 1; i < row_width; i++)
1895 *(--dp) = lo_filler;
1896 *(--dp) = *(--sp);
1897 *(--dp) = *(--sp);
1898 *(--dp) = *(--sp);
1900 *(--dp) = lo_filler;
1901 row_info->channels = 4;
1902 row_info->pixel_depth = 32;
1903 row_info->rowbytes = row_width * 4;
1905 /* This changes the data from RGB to XRGB */
1906 else
1908 png_bytep sp = row + (png_size_t)row_width * 3;
1909 png_bytep dp = sp + (png_size_t)row_width;
1910 for (i = 0; i < row_width; i++)
1912 *(--dp) = *(--sp);
1913 *(--dp) = *(--sp);
1914 *(--dp) = *(--sp);
1915 *(--dp) = lo_filler;
1917 row_info->channels = 4;
1918 row_info->pixel_depth = 32;
1919 row_info->rowbytes = row_width * 4;
1922 else if(row_info->bit_depth == 16)
1924 /* This changes the data from RRGGBB to RRGGBBXX */
1925 if (flags & PNG_FLAG_FILLER_AFTER)
1927 png_bytep sp = row + (png_size_t)row_width * 3;
1928 png_bytep dp = sp + (png_size_t)row_width;
1929 for (i = 1; i < row_width; i++)
1931 *(--dp) = hi_filler;
1932 *(--dp) = lo_filler;
1933 *(--dp) = *(--sp);
1934 *(--dp) = *(--sp);
1935 *(--dp) = *(--sp);
1936 *(--dp) = *(--sp);
1937 *(--dp) = *(--sp);
1938 *(--dp) = *(--sp);
1940 *(--dp) = hi_filler;
1941 *(--dp) = lo_filler;
1942 row_info->channels = 4;
1943 row_info->pixel_depth = 64;
1944 row_info->rowbytes = row_width * 8;
1946 /* This changes the data from RRGGBB to XXRRGGBB */
1947 else
1949 png_bytep sp = row + (png_size_t)row_width * 3;
1950 png_bytep dp = sp + (png_size_t)row_width;
1951 for (i = 0; i < row_width; i++)
1953 *(--dp) = *(--sp);
1954 *(--dp) = *(--sp);
1955 *(--dp) = *(--sp);
1956 *(--dp) = *(--sp);
1957 *(--dp) = *(--sp);
1958 *(--dp) = *(--sp);
1959 *(--dp) = hi_filler;
1960 *(--dp) = lo_filler;
1962 row_info->channels = 4;
1963 row_info->pixel_depth = 64;
1964 row_info->rowbytes = row_width * 8;
1967 } /* COLOR_TYPE == RGB */
1969 #endif
1971 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1972 /* expand grayscale files to RGB, with or without alpha */
1973 void /* PRIVATE */
1974 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
1976 png_uint_32 i;
1977 png_uint_32 row_width = row_info->width;
1979 png_debug(1, "in png_do_gray_to_rgb\n");
1980 if (row_info->bit_depth >= 8 &&
1981 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1982 row != NULL && row_info != NULL &&
1983 #endif
1984 !(row_info->color_type & PNG_COLOR_MASK_COLOR))
1986 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
1988 if (row_info->bit_depth == 8)
1990 png_bytep sp = row + (png_size_t)row_width - 1;
1991 png_bytep dp = sp + (png_size_t)row_width * 2;
1992 for (i = 0; i < row_width; i++)
1994 *(dp--) = *sp;
1995 *(dp--) = *sp;
1996 *(dp--) = *(sp--);
1999 else
2001 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2002 png_bytep dp = sp + (png_size_t)row_width * 4;
2003 for (i = 0; i < row_width; i++)
2005 *(dp--) = *sp;
2006 *(dp--) = *(sp - 1);
2007 *(dp--) = *sp;
2008 *(dp--) = *(sp - 1);
2009 *(dp--) = *(sp--);
2010 *(dp--) = *(sp--);
2014 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2016 if (row_info->bit_depth == 8)
2018 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2019 png_bytep dp = sp + (png_size_t)row_width * 2;
2020 for (i = 0; i < row_width; i++)
2022 *(dp--) = *(sp--);
2023 *(dp--) = *sp;
2024 *(dp--) = *sp;
2025 *(dp--) = *(sp--);
2028 else
2030 png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2031 png_bytep dp = sp + (png_size_t)row_width * 4;
2032 for (i = 0; i < row_width; i++)
2034 *(dp--) = *(sp--);
2035 *(dp--) = *(sp--);
2036 *(dp--) = *sp;
2037 *(dp--) = *(sp - 1);
2038 *(dp--) = *sp;
2039 *(dp--) = *(sp - 1);
2040 *(dp--) = *(sp--);
2041 *(dp--) = *(sp--);
2045 row_info->channels += (png_byte)2;
2046 row_info->color_type |= PNG_COLOR_MASK_COLOR;
2047 row_info->pixel_depth = (png_byte)(row_info->channels *
2048 row_info->bit_depth);
2049 row_info->rowbytes = ((row_width *
2050 row_info->pixel_depth + 7) >> 3);
2053 #endif
2055 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
2056 /* reduce RGB files to grayscale, with or without alpha
2057 * using the equation given in Poynton's ColorFAQ at
2058 * <http://www.inforamp.net/~poynton/>
2059 * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
2061 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2063 * We approximate this with
2065 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
2067 * which can be expressed with integers as
2069 * Y = (6969 * R + 23434 * G + 2365 * B)/32768
2071 * The calculation is to be done in a linear colorspace.
2073 * Other integer coefficents can be used via png_set_rgb_to_gray().
2075 int /* PRIVATE */
2076 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2079 png_uint_32 i;
2081 png_uint_32 row_width = row_info->width;
2082 int rgb_error = 0;
2084 png_debug(1, "in png_do_rgb_to_gray\n");
2085 if (
2086 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2087 row != NULL && row_info != NULL &&
2088 #endif
2089 (row_info->color_type & PNG_COLOR_MASK_COLOR))
2091 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2092 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2093 png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
2095 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2097 if (row_info->bit_depth == 8)
2099 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2100 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2102 png_bytep sp = row;
2103 png_bytep dp = row;
2105 for (i = 0; i < row_width; i++)
2107 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2108 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2109 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2110 if(red != green || red != blue)
2112 rgb_error |= 1;
2113 *(dp++) = png_ptr->gamma_from_1[
2114 (rc*red+gc*green+bc*blue)>>15];
2116 else
2117 *(dp++) = *(sp-1);
2120 else
2121 #endif
2123 png_bytep sp = row;
2124 png_bytep dp = row;
2125 for (i = 0; i < row_width; i++)
2127 png_byte red = *(sp++);
2128 png_byte green = *(sp++);
2129 png_byte blue = *(sp++);
2130 if(red != green || red != blue)
2132 rgb_error |= 1;
2133 *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
2135 else
2136 *(dp++) = *(sp-1);
2141 else /* RGB bit_depth == 16 */
2143 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2144 if (png_ptr->gamma_16_to_1 != NULL &&
2145 png_ptr->gamma_16_from_1 != NULL)
2147 png_bytep sp = row;
2148 png_bytep dp = row;
2149 for (i = 0; i < row_width; i++)
2151 png_uint_16 red, green, blue, w;
2153 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2154 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2155 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2157 if(red == green && red == blue)
2158 w = red;
2159 else
2161 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2162 png_ptr->gamma_shift][red>>8];
2163 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2164 png_ptr->gamma_shift][green>>8];
2165 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2166 png_ptr->gamma_shift][blue>>8];
2167 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
2168 + bc*blue_1)>>15);
2169 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2170 png_ptr->gamma_shift][gray16 >> 8];
2171 rgb_error |= 1;
2174 *(dp++) = (png_byte)((w>>8) & 0xff);
2175 *(dp++) = (png_byte)(w & 0xff);
2178 else
2179 #endif
2181 png_bytep sp = row;
2182 png_bytep dp = row;
2183 for (i = 0; i < row_width; i++)
2185 png_uint_16 red, green, blue, gray16;
2187 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2188 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2189 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2191 if(red != green || red != blue)
2192 rgb_error |= 1;
2193 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2194 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2195 *(dp++) = (png_byte)(gray16 & 0xff);
2200 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2202 if (row_info->bit_depth == 8)
2204 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2205 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2207 png_bytep sp = row;
2208 png_bytep dp = row;
2209 for (i = 0; i < row_width; i++)
2211 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2212 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2213 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2214 if(red != green || red != blue)
2215 rgb_error |= 1;
2216 *(dp++) = png_ptr->gamma_from_1
2217 [(rc*red + gc*green + bc*blue)>>15];
2218 *(dp++) = *(sp++); /* alpha */
2221 else
2222 #endif
2224 png_bytep sp = row;
2225 png_bytep dp = row;
2226 for (i = 0; i < row_width; i++)
2228 png_byte red = *(sp++);
2229 png_byte green = *(sp++);
2230 png_byte blue = *(sp++);
2231 if(red != green || red != blue)
2232 rgb_error |= 1;
2233 *(dp++) = (png_byte)((gc*red + gc*green + bc*blue)>>8);
2234 *(dp++) = *(sp++); /* alpha */
2238 else /* RGBA bit_depth == 16 */
2240 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2241 if (png_ptr->gamma_16_to_1 != NULL &&
2242 png_ptr->gamma_16_from_1 != NULL)
2244 png_bytep sp = row;
2245 png_bytep dp = row;
2246 for (i = 0; i < row_width; i++)
2248 png_uint_16 red, green, blue, w;
2250 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2251 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2252 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2254 if(red == green && red == blue)
2255 w = red;
2256 else
2258 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2259 png_ptr->gamma_shift][red>>8];
2260 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2261 png_ptr->gamma_shift][green>>8];
2262 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2263 png_ptr->gamma_shift][blue>>8];
2264 png_uint_16 gray16 = (png_uint_16)((rc * red_1
2265 + gc * green_1 + bc * blue_1)>>15);
2266 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2267 png_ptr->gamma_shift][gray16 >> 8];
2268 rgb_error |= 1;
2271 *(dp++) = (png_byte)((w>>8) & 0xff);
2272 *(dp++) = (png_byte)(w & 0xff);
2273 *(dp++) = *(sp++); /* alpha */
2274 *(dp++) = *(sp++);
2277 else
2278 #endif
2280 png_bytep sp = row;
2281 png_bytep dp = row;
2282 for (i = 0; i < row_width; i++)
2284 png_uint_16 red, green, blue, gray16;
2285 red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2286 green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2287 blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2288 if(red != green || red != blue)
2289 rgb_error |= 1;
2290 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2291 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2292 *(dp++) = (png_byte)(gray16 & 0xff);
2293 *(dp++) = *(sp++); /* alpha */
2294 *(dp++) = *(sp++);
2299 row_info->channels -= (png_byte)2;
2300 row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2301 row_info->pixel_depth = (png_byte)(row_info->channels *
2302 row_info->bit_depth);
2303 row_info->rowbytes = ((row_width *
2304 row_info->pixel_depth + 7) >> 3);
2306 return rgb_error;
2308 #endif
2310 /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
2311 * large of png_color. This lets grayscale images be treated as
2312 * paletted. Most useful for gamma correction and simplification
2313 * of code.
2315 void /* PRIVATE */
2316 png_build_grayscale_palette(int bit_depth, png_colorp palette)
2318 int num_palette;
2319 int color_inc;
2320 int i;
2321 int v;
2323 png_debug(1, "in png_do_build_grayscale_palette\n");
2324 if (palette == NULL)
2325 return;
2327 switch (bit_depth)
2329 case 1:
2330 num_palette = 2;
2331 color_inc = 0xff;
2332 break;
2333 case 2:
2334 num_palette = 4;
2335 color_inc = 0x55;
2336 break;
2337 case 4:
2338 num_palette = 16;
2339 color_inc = 0x11;
2340 break;
2341 case 8:
2342 num_palette = 256;
2343 color_inc = 1;
2344 break;
2345 default:
2346 num_palette = 0;
2347 color_inc = 0;
2348 break;
2351 for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2353 palette[i].red = (png_byte)v;
2354 palette[i].green = (png_byte)v;
2355 palette[i].blue = (png_byte)v;
2359 /* This function is currently unused. Do we really need it? */
2360 #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
2361 void /* PRIVATE */
2362 png_correct_palette(png_structp png_ptr, png_colorp palette,
2363 int num_palette)
2365 png_debug(1, "in png_correct_palette\n");
2366 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2367 defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
2368 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
2370 png_color back, back_1;
2372 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
2374 back.red = png_ptr->gamma_table[png_ptr->background.red];
2375 back.green = png_ptr->gamma_table[png_ptr->background.green];
2376 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
2378 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
2379 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
2380 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
2382 else
2384 double g;
2386 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
2388 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2389 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
2391 back.red = png_ptr->background.red;
2392 back.green = png_ptr->background.green;
2393 back.blue = png_ptr->background.blue;
2395 else
2397 back.red =
2398 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2399 255.0 + 0.5);
2400 back.green =
2401 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2402 255.0 + 0.5);
2403 back.blue =
2404 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2405 255.0 + 0.5);
2408 g = 1.0 / png_ptr->background_gamma;
2410 back_1.red =
2411 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2412 255.0 + 0.5);
2413 back_1.green =
2414 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2415 255.0 + 0.5);
2416 back_1.blue =
2417 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2418 255.0 + 0.5);
2421 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2423 png_uint_32 i;
2425 for (i = 0; i < (png_uint_32)num_palette; i++)
2427 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
2429 palette[i] = back;
2431 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
2433 png_byte v, w;
2435 v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
2436 png_composite(w, v, png_ptr->trans[i], back_1.red);
2437 palette[i].red = png_ptr->gamma_from_1[w];
2439 v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
2440 png_composite(w, v, png_ptr->trans[i], back_1.green);
2441 palette[i].green = png_ptr->gamma_from_1[w];
2443 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
2444 png_composite(w, v, png_ptr->trans[i], back_1.blue);
2445 palette[i].blue = png_ptr->gamma_from_1[w];
2447 else
2449 palette[i].red = png_ptr->gamma_table[palette[i].red];
2450 palette[i].green = png_ptr->gamma_table[palette[i].green];
2451 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2455 else
2457 int i;
2459 for (i = 0; i < num_palette; i++)
2461 if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
2463 palette[i] = back;
2465 else
2467 palette[i].red = png_ptr->gamma_table[palette[i].red];
2468 palette[i].green = png_ptr->gamma_table[palette[i].green];
2469 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2474 else
2475 #endif
2476 #if defined(PNG_READ_GAMMA_SUPPORTED)
2477 if (png_ptr->transformations & PNG_GAMMA)
2479 int i;
2481 for (i = 0; i < num_palette; i++)
2483 palette[i].red = png_ptr->gamma_table[palette[i].red];
2484 palette[i].green = png_ptr->gamma_table[palette[i].green];
2485 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2488 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2489 else
2490 #endif
2491 #endif
2492 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2493 if (png_ptr->transformations & PNG_BACKGROUND)
2495 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2497 png_color back;
2499 back.red = (png_byte)png_ptr->background.red;
2500 back.green = (png_byte)png_ptr->background.green;
2501 back.blue = (png_byte)png_ptr->background.blue;
2503 for (i = 0; i < (int)png_ptr->num_trans; i++)
2505 if (png_ptr->trans[i] == 0)
2507 palette[i].red = back.red;
2508 palette[i].green = back.green;
2509 palette[i].blue = back.blue;
2511 else if (png_ptr->trans[i] != 0xff)
2513 png_composite(palette[i].red, png_ptr->palette[i].red,
2514 png_ptr->trans[i], back.red);
2515 png_composite(palette[i].green, png_ptr->palette[i].green,
2516 png_ptr->trans[i], back.green);
2517 png_composite(palette[i].blue, png_ptr->palette[i].blue,
2518 png_ptr->trans[i], back.blue);
2522 else /* assume grayscale palette (what else could it be?) */
2524 int i;
2526 for (i = 0; i < num_palette; i++)
2528 if (i == (png_byte)png_ptr->trans_values.gray)
2530 palette[i].red = (png_byte)png_ptr->background.red;
2531 palette[i].green = (png_byte)png_ptr->background.green;
2532 palette[i].blue = (png_byte)png_ptr->background.blue;
2537 #endif
2539 #endif
2541 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2542 /* Replace any alpha or transparency with the supplied background color.
2543 * "background" is already in the screen gamma, while "background_1" is
2544 * at a gamma of 1.0. Paletted files have already been taken care of.
2546 void /* PRIVATE */
2547 png_do_background(png_row_infop row_info, png_bytep row,
2548 png_color_16p trans_values, png_color_16p background,
2549 png_color_16p background_1,
2550 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
2551 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2552 png_uint_16pp gamma_16_to_1, int gamma_shift)
2554 png_bytep sp, dp;
2555 png_uint_32 i;
2556 png_uint_32 row_width=row_info->width;
2557 int shift;
2559 png_debug(1, "in png_do_background\n");
2560 if (background != NULL &&
2561 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2562 row != NULL && row_info != NULL &&
2563 #endif
2564 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
2565 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
2567 switch (row_info->color_type)
2569 case PNG_COLOR_TYPE_GRAY:
2571 switch (row_info->bit_depth)
2573 case 1:
2575 sp = row;
2576 shift = 7;
2577 for (i = 0; i < row_width; i++)
2579 if ((png_uint_16)((*sp >> shift) & 0x01)
2580 == trans_values->gray)
2582 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2583 *sp |= (png_byte)(background->gray << shift);
2585 if (!shift)
2587 shift = 7;
2588 sp++;
2590 else
2591 shift--;
2593 break;
2595 case 2:
2597 #if defined(PNG_READ_GAMMA_SUPPORTED)
2598 if (gamma_table != NULL)
2600 sp = row;
2601 shift = 6;
2602 for (i = 0; i < row_width; i++)
2604 if ((png_uint_16)((*sp >> shift) & 0x03)
2605 == trans_values->gray)
2607 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2608 *sp |= (png_byte)(background->gray << shift);
2610 else
2612 png_byte p = (png_byte)((*sp >> shift) & 0x03);
2613 png_byte g = (png_byte)((gamma_table [p | (p << 2) |
2614 (p << 4) | (p << 6)] >> 6) & 0x03);
2615 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2616 *sp |= (png_byte)(g << shift);
2618 if (!shift)
2620 shift = 6;
2621 sp++;
2623 else
2624 shift -= 2;
2627 else
2628 #endif
2630 sp = row;
2631 shift = 6;
2632 for (i = 0; i < row_width; i++)
2634 if ((png_uint_16)((*sp >> shift) & 0x03)
2635 == trans_values->gray)
2637 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2638 *sp |= (png_byte)(background->gray << shift);
2640 if (!shift)
2642 shift = 6;
2643 sp++;
2645 else
2646 shift -= 2;
2649 break;
2651 case 4:
2653 #if defined(PNG_READ_GAMMA_SUPPORTED)
2654 if (gamma_table != NULL)
2656 sp = row;
2657 shift = 4;
2658 for (i = 0; i < row_width; i++)
2660 if ((png_uint_16)((*sp >> shift) & 0x0f)
2661 == trans_values->gray)
2663 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2664 *sp |= (png_byte)(background->gray << shift);
2666 else
2668 png_byte p = (png_byte)((*sp >> shift) & 0x0f);
2669 png_byte g = (png_byte)((gamma_table[p |
2670 (p << 4)] >> 4) & 0x0f);
2671 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2672 *sp |= (png_byte)(g << shift);
2674 if (!shift)
2676 shift = 4;
2677 sp++;
2679 else
2680 shift -= 4;
2683 else
2684 #endif
2686 sp = row;
2687 shift = 4;
2688 for (i = 0; i < row_width; i++)
2690 if ((png_uint_16)((*sp >> shift) & 0x0f)
2691 == trans_values->gray)
2693 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2694 *sp |= (png_byte)(background->gray << shift);
2696 if (!shift)
2698 shift = 4;
2699 sp++;
2701 else
2702 shift -= 4;
2705 break;
2707 case 8:
2709 #if defined(PNG_READ_GAMMA_SUPPORTED)
2710 if (gamma_table != NULL)
2712 sp = row;
2713 for (i = 0; i < row_width; i++, sp++)
2715 if (*sp == trans_values->gray)
2717 *sp = (png_byte)background->gray;
2719 else
2721 *sp = gamma_table[*sp];
2725 else
2726 #endif
2728 sp = row;
2729 for (i = 0; i < row_width; i++, sp++)
2731 if (*sp == trans_values->gray)
2733 *sp = (png_byte)background->gray;
2737 break;
2739 case 16:
2741 #if defined(PNG_READ_GAMMA_SUPPORTED)
2742 if (gamma_16 != NULL)
2744 sp = row;
2745 for (i = 0; i < row_width; i++, sp += 2)
2747 png_uint_16 v;
2749 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2750 if (v == trans_values->gray)
2752 /* background is already in screen gamma */
2753 *sp = (png_byte)((background->gray >> 8) & 0xff);
2754 *(sp + 1) = (png_byte)(background->gray & 0xff);
2756 else
2758 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2759 *sp = (png_byte)((v >> 8) & 0xff);
2760 *(sp + 1) = (png_byte)(v & 0xff);
2764 else
2765 #endif
2767 sp = row;
2768 for (i = 0; i < row_width; i++, sp += 2)
2770 png_uint_16 v;
2772 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2773 if (v == trans_values->gray)
2775 *sp = (png_byte)((background->gray >> 8) & 0xff);
2776 *(sp + 1) = (png_byte)(background->gray & 0xff);
2780 break;
2783 break;
2785 case PNG_COLOR_TYPE_RGB:
2787 if (row_info->bit_depth == 8)
2789 #if defined(PNG_READ_GAMMA_SUPPORTED)
2790 if (gamma_table != NULL)
2792 sp = row;
2793 for (i = 0; i < row_width; i++, sp += 3)
2795 if (*sp == trans_values->red &&
2796 *(sp + 1) == trans_values->green &&
2797 *(sp + 2) == trans_values->blue)
2799 *sp = (png_byte)background->red;
2800 *(sp + 1) = (png_byte)background->green;
2801 *(sp + 2) = (png_byte)background->blue;
2803 else
2805 *sp = gamma_table[*sp];
2806 *(sp + 1) = gamma_table[*(sp + 1)];
2807 *(sp + 2) = gamma_table[*(sp + 2)];
2811 else
2812 #endif
2814 sp = row;
2815 for (i = 0; i < row_width; i++, sp += 3)
2817 if (*sp == trans_values->red &&
2818 *(sp + 1) == trans_values->green &&
2819 *(sp + 2) == trans_values->blue)
2821 *sp = (png_byte)background->red;
2822 *(sp + 1) = (png_byte)background->green;
2823 *(sp + 2) = (png_byte)background->blue;
2828 else /* if (row_info->bit_depth == 16) */
2830 #if defined(PNG_READ_GAMMA_SUPPORTED)
2831 if (gamma_16 != NULL)
2833 sp = row;
2834 for (i = 0; i < row_width; i++, sp += 6)
2836 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2837 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2838 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
2839 if (r == trans_values->red && g == trans_values->green &&
2840 b == trans_values->blue)
2842 /* background is already in screen gamma */
2843 *sp = (png_byte)((background->red >> 8) & 0xff);
2844 *(sp + 1) = (png_byte)(background->red & 0xff);
2845 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2846 *(sp + 3) = (png_byte)(background->green & 0xff);
2847 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2848 *(sp + 5) = (png_byte)(background->blue & 0xff);
2850 else
2852 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2853 *sp = (png_byte)((v >> 8) & 0xff);
2854 *(sp + 1) = (png_byte)(v & 0xff);
2855 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
2856 *(sp + 2) = (png_byte)((v >> 8) & 0xff);
2857 *(sp + 3) = (png_byte)(v & 0xff);
2858 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
2859 *(sp + 4) = (png_byte)((v >> 8) & 0xff);
2860 *(sp + 5) = (png_byte)(v & 0xff);
2864 else
2865 #endif
2867 sp = row;
2868 for (i = 0; i < row_width; i++, sp += 6)
2870 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
2871 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2872 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
2874 if (r == trans_values->red && g == trans_values->green &&
2875 b == trans_values->blue)
2877 *sp = (png_byte)((background->red >> 8) & 0xff);
2878 *(sp + 1) = (png_byte)(background->red & 0xff);
2879 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2880 *(sp + 3) = (png_byte)(background->green & 0xff);
2881 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2882 *(sp + 5) = (png_byte)(background->blue & 0xff);
2887 break;
2889 case PNG_COLOR_TYPE_GRAY_ALPHA:
2891 if (row_info->bit_depth == 8)
2893 #if defined(PNG_READ_GAMMA_SUPPORTED)
2894 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2895 gamma_table != NULL)
2897 sp = row;
2898 dp = row;
2899 for (i = 0; i < row_width; i++, sp += 2, dp++)
2901 png_uint_16 a = *(sp + 1);
2903 if (a == 0xff)
2905 *dp = gamma_table[*sp];
2907 else if (a == 0)
2909 /* background is already in screen gamma */
2910 *dp = (png_byte)background->gray;
2912 else
2914 png_byte v, w;
2916 v = gamma_to_1[*sp];
2917 png_composite(w, v, a, background_1->gray);
2918 *dp = gamma_from_1[w];
2922 else
2923 #endif
2925 sp = row;
2926 dp = row;
2927 for (i = 0; i < row_width; i++, sp += 2, dp++)
2929 png_byte a = *(sp + 1);
2931 if (a == 0xff)
2933 *dp = *sp;
2935 else if (a == 0)
2937 *dp = (png_byte)background->gray;
2939 else
2941 png_composite(*dp, *sp, a, background_1->gray);
2946 else /* if (png_ptr->bit_depth == 16) */
2948 #if defined(PNG_READ_GAMMA_SUPPORTED)
2949 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
2950 gamma_16_to_1 != NULL)
2952 sp = row;
2953 dp = row;
2954 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
2956 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2958 if (a == (png_uint_16)0xffff)
2960 png_uint_16 v;
2962 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2963 *dp = (png_byte)((v >> 8) & 0xff);
2964 *(dp + 1) = (png_byte)(v & 0xff);
2966 else if (a == 0)
2968 /* background is already in screen gamma */
2969 *dp = (png_byte)((background->gray >> 8) & 0xff);
2970 *(dp + 1) = (png_byte)(background->gray & 0xff);
2972 else
2974 png_uint_16 g, v, w;
2976 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
2977 png_composite_16(v, g, a, background_1->gray);
2978 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
2979 *dp = (png_byte)((w >> 8) & 0xff);
2980 *(dp + 1) = (png_byte)(w & 0xff);
2984 else
2985 #endif
2987 sp = row;
2988 dp = row;
2989 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
2991 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2992 if (a == (png_uint_16)0xffff)
2994 png_memcpy(dp, sp, 2);
2996 else if (a == 0)
2998 *dp = (png_byte)((background->gray >> 8) & 0xff);
2999 *(dp + 1) = (png_byte)(background->gray & 0xff);
3001 else
3003 png_uint_16 g, v;
3005 g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3006 png_composite_16(v, g, a, background_1->gray);
3007 *dp = (png_byte)((v >> 8) & 0xff);
3008 *(dp + 1) = (png_byte)(v & 0xff);
3013 break;
3015 case PNG_COLOR_TYPE_RGB_ALPHA:
3017 if (row_info->bit_depth == 8)
3019 #if defined(PNG_READ_GAMMA_SUPPORTED)
3020 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3021 gamma_table != NULL)
3023 sp = row;
3024 dp = row;
3025 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3027 png_byte a = *(sp + 3);
3029 if (a == 0xff)
3031 *dp = gamma_table[*sp];
3032 *(dp + 1) = gamma_table[*(sp + 1)];
3033 *(dp + 2) = gamma_table[*(sp + 2)];
3035 else if (a == 0)
3037 /* background is already in screen gamma */
3038 *dp = (png_byte)background->red;
3039 *(dp + 1) = (png_byte)background->green;
3040 *(dp + 2) = (png_byte)background->blue;
3042 else
3044 png_byte v, w;
3046 v = gamma_to_1[*sp];
3047 png_composite(w, v, a, background_1->red);
3048 *dp = gamma_from_1[w];
3049 v = gamma_to_1[*(sp + 1)];
3050 png_composite(w, v, a, background_1->green);
3051 *(dp + 1) = gamma_from_1[w];
3052 v = gamma_to_1[*(sp + 2)];
3053 png_composite(w, v, a, background_1->blue);
3054 *(dp + 2) = gamma_from_1[w];
3058 else
3059 #endif
3061 sp = row;
3062 dp = row;
3063 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3065 png_byte a = *(sp + 3);
3067 if (a == 0xff)
3069 *dp = *sp;
3070 *(dp + 1) = *(sp + 1);
3071 *(dp + 2) = *(sp + 2);
3073 else if (a == 0)
3075 *dp = (png_byte)background->red;
3076 *(dp + 1) = (png_byte)background->green;
3077 *(dp + 2) = (png_byte)background->blue;
3079 else
3081 png_composite(*dp, *sp, a, background->red);
3082 png_composite(*(dp + 1), *(sp + 1), a,
3083 background->green);
3084 png_composite(*(dp + 2), *(sp + 2), a,
3085 background->blue);
3090 else /* if (row_info->bit_depth == 16) */
3092 #if defined(PNG_READ_GAMMA_SUPPORTED)
3093 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3094 gamma_16_to_1 != NULL)
3096 sp = row;
3097 dp = row;
3098 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3100 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3101 << 8) + (png_uint_16)(*(sp + 7)));
3102 if (a == (png_uint_16)0xffff)
3104 png_uint_16 v;
3106 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3107 *dp = (png_byte)((v >> 8) & 0xff);
3108 *(dp + 1) = (png_byte)(v & 0xff);
3109 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3110 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3111 *(dp + 3) = (png_byte)(v & 0xff);
3112 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3113 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3114 *(dp + 5) = (png_byte)(v & 0xff);
3116 else if (a == 0)
3118 /* background is already in screen gamma */
3119 *dp = (png_byte)((background->red >> 8) & 0xff);
3120 *(dp + 1) = (png_byte)(background->red & 0xff);
3121 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3122 *(dp + 3) = (png_byte)(background->green & 0xff);
3123 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3124 *(dp + 5) = (png_byte)(background->blue & 0xff);
3126 else
3128 png_uint_16 v, w, x;
3130 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3131 png_composite_16(w, v, a, background->red);
3132 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3133 *dp = (png_byte)((x >> 8) & 0xff);
3134 *(dp + 1) = (png_byte)(x & 0xff);
3135 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3136 png_composite_16(w, v, a, background->green);
3137 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3138 *(dp + 2) = (png_byte)((x >> 8) & 0xff);
3139 *(dp + 3) = (png_byte)(x & 0xff);
3140 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3141 png_composite_16(w, v, a, background->blue);
3142 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3143 *(dp + 4) = (png_byte)((x >> 8) & 0xff);
3144 *(dp + 5) = (png_byte)(x & 0xff);
3148 else
3149 #endif
3151 sp = row;
3152 dp = row;
3153 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3155 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3156 << 8) + (png_uint_16)(*(sp + 7)));
3157 if (a == (png_uint_16)0xffff)
3159 png_memcpy(dp, sp, 6);
3161 else if (a == 0)
3163 *dp = (png_byte)((background->red >> 8) & 0xff);
3164 *(dp + 1) = (png_byte)(background->red & 0xff);
3165 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3166 *(dp + 3) = (png_byte)(background->green & 0xff);
3167 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3168 *(dp + 5) = (png_byte)(background->blue & 0xff);
3170 else
3172 png_uint_16 v;
3174 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3175 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3176 + *(sp + 3));
3177 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3178 + *(sp + 5));
3180 png_composite_16(v, r, a, background->red);
3181 *dp = (png_byte)((v >> 8) & 0xff);
3182 *(dp + 1) = (png_byte)(v & 0xff);
3183 png_composite_16(v, g, a, background->green);
3184 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3185 *(dp + 3) = (png_byte)(v & 0xff);
3186 png_composite_16(v, b, a, background->blue);
3187 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3188 *(dp + 5) = (png_byte)(v & 0xff);
3193 break;
3197 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3199 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
3200 row_info->channels--;
3201 row_info->pixel_depth = (png_byte)(row_info->channels *
3202 row_info->bit_depth);
3203 row_info->rowbytes = ((row_width *
3204 row_info->pixel_depth + 7) >> 3);
3208 #endif
3210 #if defined(PNG_READ_GAMMA_SUPPORTED)
3211 /* Gamma correct the image, avoiding the alpha channel. Make sure
3212 * you do this after you deal with the transparency issue on grayscale
3213 * or RGB images. If your bit depth is 8, use gamma_table, if it
3214 * is 16, use gamma_16_table and gamma_shift. Build these with
3215 * build_gamma_table().
3217 void /* PRIVATE */
3218 png_do_gamma(png_row_infop row_info, png_bytep row,
3219 png_bytep gamma_table, png_uint_16pp gamma_16_table,
3220 int gamma_shift)
3222 png_bytep sp;
3223 png_uint_32 i;
3224 png_uint_32 row_width=row_info->width;
3226 png_debug(1, "in png_do_gamma\n");
3227 if (
3228 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3229 row != NULL && row_info != NULL &&
3230 #endif
3231 ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3232 (row_info->bit_depth == 16 && gamma_16_table != NULL)))
3234 switch (row_info->color_type)
3236 case PNG_COLOR_TYPE_RGB:
3238 if (row_info->bit_depth == 8)
3240 sp = row;
3241 for (i = 0; i < row_width; i++)
3243 *sp = gamma_table[*sp];
3244 sp++;
3245 *sp = gamma_table[*sp];
3246 sp++;
3247 *sp = gamma_table[*sp];
3248 sp++;
3251 else /* if (row_info->bit_depth == 16) */
3253 sp = row;
3254 for (i = 0; i < row_width; i++)
3256 png_uint_16 v;
3258 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3259 *sp = (png_byte)((v >> 8) & 0xff);
3260 *(sp + 1) = (png_byte)(v & 0xff);
3261 sp += 2;
3262 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3263 *sp = (png_byte)((v >> 8) & 0xff);
3264 *(sp + 1) = (png_byte)(v & 0xff);
3265 sp += 2;
3266 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3267 *sp = (png_byte)((v >> 8) & 0xff);
3268 *(sp + 1) = (png_byte)(v & 0xff);
3269 sp += 2;
3272 break;
3274 case PNG_COLOR_TYPE_RGB_ALPHA:
3276 if (row_info->bit_depth == 8)
3278 sp = row;
3279 for (i = 0; i < row_width; i++)
3281 *sp = gamma_table[*sp];
3282 sp++;
3283 *sp = gamma_table[*sp];
3284 sp++;
3285 *sp = gamma_table[*sp];
3286 sp++;
3287 sp++;
3290 else /* if (row_info->bit_depth == 16) */
3292 sp = row;
3293 for (i = 0; i < row_width; i++)
3295 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3296 *sp = (png_byte)((v >> 8) & 0xff);
3297 *(sp + 1) = (png_byte)(v & 0xff);
3298 sp += 2;
3299 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3300 *sp = (png_byte)((v >> 8) & 0xff);
3301 *(sp + 1) = (png_byte)(v & 0xff);
3302 sp += 2;
3303 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3304 *sp = (png_byte)((v >> 8) & 0xff);
3305 *(sp + 1) = (png_byte)(v & 0xff);
3306 sp += 4;
3309 break;
3311 case PNG_COLOR_TYPE_GRAY_ALPHA:
3313 if (row_info->bit_depth == 8)
3315 sp = row;
3316 for (i = 0; i < row_width; i++)
3318 *sp = gamma_table[*sp];
3319 sp += 2;
3322 else /* if (row_info->bit_depth == 16) */
3324 sp = row;
3325 for (i = 0; i < row_width; i++)
3327 png_uint_16 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 += 4;
3333 break;
3335 case PNG_COLOR_TYPE_GRAY:
3337 if (row_info->bit_depth == 2)
3339 sp = row;
3340 for (i = 0; i < row_width; i += 4)
3342 int a = *sp & 0xc0;
3343 int b = *sp & 0x30;
3344 int c = *sp & 0x0c;
3345 int d = *sp & 0x03;
3347 *sp = (png_byte)(
3348 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
3349 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3350 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
3351 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
3352 sp++;
3355 if (row_info->bit_depth == 4)
3357 sp = row;
3358 for (i = 0; i < row_width; i += 2)
3360 int msb = *sp & 0xf0;
3361 int lsb = *sp & 0x0f;
3363 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3364 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
3365 sp++;
3368 else if (row_info->bit_depth == 8)
3370 sp = row;
3371 for (i = 0; i < row_width; i++)
3373 *sp = gamma_table[*sp];
3374 sp++;
3377 else if (row_info->bit_depth == 16)
3379 sp = row;
3380 for (i = 0; i < row_width; i++)
3382 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3383 *sp = (png_byte)((v >> 8) & 0xff);
3384 *(sp + 1) = (png_byte)(v & 0xff);
3385 sp += 2;
3388 break;
3393 #endif
3395 #if defined(PNG_READ_EXPAND_SUPPORTED)
3396 /* Expands a palette row to an RGB or RGBA row depending
3397 * upon whether you supply trans and num_trans.
3399 void /* PRIVATE */
3400 png_do_expand_palette(png_row_infop row_info, png_bytep row,
3401 png_colorp palette, png_bytep trans, int num_trans)
3403 int shift, value;
3404 png_bytep sp, dp;
3405 png_uint_32 i;
3406 png_uint_32 row_width=row_info->width;
3408 png_debug(1, "in png_do_expand_palette\n");
3409 if (
3410 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3411 row != NULL && row_info != NULL &&
3412 #endif
3413 row_info->color_type == PNG_COLOR_TYPE_PALETTE)
3415 if (row_info->bit_depth < 8)
3417 switch (row_info->bit_depth)
3419 case 1:
3421 sp = row + (png_size_t)((row_width - 1) >> 3);
3422 dp = row + (png_size_t)row_width - 1;
3423 shift = 7 - (int)((row_width + 7) & 0x07);
3424 for (i = 0; i < row_width; i++)
3426 if ((*sp >> shift) & 0x01)
3427 *dp = 1;
3428 else
3429 *dp = 0;
3430 if (shift == 7)
3432 shift = 0;
3433 sp--;
3435 else
3436 shift++;
3438 dp--;
3440 break;
3442 case 2:
3444 sp = row + (png_size_t)((row_width - 1) >> 2);
3445 dp = row + (png_size_t)row_width - 1;
3446 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3447 for (i = 0; i < row_width; i++)
3449 value = (*sp >> shift) & 0x03;
3450 *dp = (png_byte)value;
3451 if (shift == 6)
3453 shift = 0;
3454 sp--;
3456 else
3457 shift += 2;
3459 dp--;
3461 break;
3463 case 4:
3465 sp = row + (png_size_t)((row_width - 1) >> 1);
3466 dp = row + (png_size_t)row_width - 1;
3467 shift = (int)((row_width & 0x01) << 2);
3468 for (i = 0; i < row_width; i++)
3470 value = (*sp >> shift) & 0x0f;
3471 *dp = (png_byte)value;
3472 if (shift == 4)
3474 shift = 0;
3475 sp--;
3477 else
3478 shift += 4;
3480 dp--;
3482 break;
3485 row_info->bit_depth = 8;
3486 row_info->pixel_depth = 8;
3487 row_info->rowbytes = row_width;
3489 switch (row_info->bit_depth)
3491 case 8:
3493 if (trans != NULL)
3495 sp = row + (png_size_t)row_width - 1;
3496 dp = row + (png_size_t)(row_width << 2) - 1;
3498 for (i = 0; i < row_width; i++)
3500 if ((int)(*sp) >= num_trans)
3501 *dp-- = 0xff;
3502 else
3503 *dp-- = trans[*sp];
3504 *dp-- = palette[*sp].blue;
3505 *dp-- = palette[*sp].green;
3506 *dp-- = palette[*sp].red;
3507 sp--;
3509 row_info->bit_depth = 8;
3510 row_info->pixel_depth = 32;
3511 row_info->rowbytes = row_width * 4;
3512 row_info->color_type = 6;
3513 row_info->channels = 4;
3515 else
3517 sp = row + (png_size_t)row_width - 1;
3518 dp = row + (png_size_t)(row_width * 3) - 1;
3520 for (i = 0; i < row_width; i++)
3522 *dp-- = palette[*sp].blue;
3523 *dp-- = palette[*sp].green;
3524 *dp-- = palette[*sp].red;
3525 sp--;
3527 row_info->bit_depth = 8;
3528 row_info->pixel_depth = 24;
3529 row_info->rowbytes = row_width * 3;
3530 row_info->color_type = 2;
3531 row_info->channels = 3;
3533 break;
3539 /* If the bit depth < 8, it is expanded to 8. Also, if the
3540 * transparency value is supplied, an alpha channel is built.
3542 void /* PRIVATE */
3543 png_do_expand(png_row_infop row_info, png_bytep row,
3544 png_color_16p trans_value)
3546 int shift, value;
3547 png_bytep sp, dp;
3548 png_uint_32 i;
3549 png_uint_32 row_width=row_info->width;
3551 png_debug(1, "in png_do_expand\n");
3552 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3553 if (row != NULL && row_info != NULL)
3554 #endif
3556 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
3558 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
3560 if (row_info->bit_depth < 8)
3562 switch (row_info->bit_depth)
3564 case 1:
3566 gray = (png_uint_16)(gray*0xff);
3567 sp = row + (png_size_t)((row_width - 1) >> 3);
3568 dp = row + (png_size_t)row_width - 1;
3569 shift = 7 - (int)((row_width + 7) & 0x07);
3570 for (i = 0; i < row_width; i++)
3572 if ((*sp >> shift) & 0x01)
3573 *dp = 0xff;
3574 else
3575 *dp = 0;
3576 if (shift == 7)
3578 shift = 0;
3579 sp--;
3581 else
3582 shift++;
3584 dp--;
3586 break;
3588 case 2:
3590 gray = (png_uint_16)(gray*0x55);
3591 sp = row + (png_size_t)((row_width - 1) >> 2);
3592 dp = row + (png_size_t)row_width - 1;
3593 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3594 for (i = 0; i < row_width; i++)
3596 value = (*sp >> shift) & 0x03;
3597 *dp = (png_byte)(value | (value << 2) | (value << 4) |
3598 (value << 6));
3599 if (shift == 6)
3601 shift = 0;
3602 sp--;
3604 else
3605 shift += 2;
3607 dp--;
3609 break;
3611 case 4:
3613 gray = (png_uint_16)(gray*0x11);
3614 sp = row + (png_size_t)((row_width - 1) >> 1);
3615 dp = row + (png_size_t)row_width - 1;
3616 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
3617 for (i = 0; i < row_width; i++)
3619 value = (*sp >> shift) & 0x0f;
3620 *dp = (png_byte)(value | (value << 4));
3621 if (shift == 4)
3623 shift = 0;
3624 sp--;
3626 else
3627 shift = 4;
3629 dp--;
3631 break;
3634 row_info->bit_depth = 8;
3635 row_info->pixel_depth = 8;
3636 row_info->rowbytes = row_width;
3639 if (trans_value != NULL)
3641 if (row_info->bit_depth == 8)
3643 sp = row + (png_size_t)row_width - 1;
3644 dp = row + (png_size_t)(row_width << 1) - 1;
3645 for (i = 0; i < row_width; i++)
3647 if (*sp == gray)
3648 *dp-- = 0;
3649 else
3650 *dp-- = 0xff;
3651 *dp-- = *sp--;
3654 else if (row_info->bit_depth == 16)
3656 sp = row + row_info->rowbytes - 1;
3657 dp = row + (row_info->rowbytes << 1) - 1;
3658 for (i = 0; i < row_width; i++)
3660 if (((png_uint_16)*(sp) |
3661 ((png_uint_16)*(sp - 1) << 8)) == gray)
3663 *dp-- = 0;
3664 *dp-- = 0;
3666 else
3668 *dp-- = 0xff;
3669 *dp-- = 0xff;
3671 *dp-- = *sp--;
3672 *dp-- = *sp--;
3675 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3676 row_info->channels = 2;
3677 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3678 row_info->rowbytes =
3679 ((row_width * row_info->pixel_depth) >> 3);
3682 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3684 if (row_info->bit_depth == 8)
3686 sp = row + (png_size_t)row_info->rowbytes - 1;
3687 dp = row + (png_size_t)(row_width << 2) - 1;
3688 for (i = 0; i < row_width; i++)
3690 if (*(sp - 2) == trans_value->red &&
3691 *(sp - 1) == trans_value->green &&
3692 *(sp - 0) == trans_value->blue)
3693 *dp-- = 0;
3694 else
3695 *dp-- = 0xff;
3696 *dp-- = *sp--;
3697 *dp-- = *sp--;
3698 *dp-- = *sp--;
3701 else if (row_info->bit_depth == 16)
3703 sp = row + row_info->rowbytes - 1;
3704 dp = row + (png_size_t)(row_width << 3) - 1;
3705 for (i = 0; i < row_width; i++)
3707 if ((((png_uint_16)*(sp - 4) |
3708 ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
3709 (((png_uint_16)*(sp - 2) |
3710 ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
3711 (((png_uint_16)*(sp - 0) |
3712 ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
3714 *dp-- = 0;
3715 *dp-- = 0;
3717 else
3719 *dp-- = 0xff;
3720 *dp-- = 0xff;
3722 *dp-- = *sp--;
3723 *dp-- = *sp--;
3724 *dp-- = *sp--;
3725 *dp-- = *sp--;
3726 *dp-- = *sp--;
3727 *dp-- = *sp--;
3730 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3731 row_info->channels = 4;
3732 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
3733 row_info->rowbytes =
3734 ((row_width * row_info->pixel_depth) >> 3);
3738 #endif
3740 #if defined(PNG_READ_DITHER_SUPPORTED)
3741 void /* PRIVATE */
3742 png_do_dither(png_row_infop row_info, png_bytep row,
3743 png_bytep palette_lookup, png_bytep dither_lookup)
3745 png_bytep sp, dp;
3746 png_uint_32 i;
3747 png_uint_32 row_width=row_info->width;
3749 png_debug(1, "in png_do_dither\n");
3750 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3751 if (row != NULL && row_info != NULL)
3752 #endif
3754 if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3755 palette_lookup && row_info->bit_depth == 8)
3757 int r, g, b, p;
3758 sp = row;
3759 dp = row;
3760 for (i = 0; i < row_width; i++)
3762 r = *sp++;
3763 g = *sp++;
3764 b = *sp++;
3766 /* this looks real messy, but the compiler will reduce
3767 it down to a reasonable formula. For example, with
3768 5 bits per color, we get:
3769 p = (((r >> 3) & 0x1f) << 10) |
3770 (((g >> 3) & 0x1f) << 5) |
3771 ((b >> 3) & 0x1f);
3773 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3774 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3775 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3776 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3777 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3778 (PNG_DITHER_BLUE_BITS)) |
3779 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3780 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3782 *dp++ = palette_lookup[p];
3784 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3785 row_info->channels = 1;
3786 row_info->pixel_depth = row_info->bit_depth;
3787 row_info->rowbytes =
3788 ((row_width * row_info->pixel_depth + 7) >> 3);
3790 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
3791 palette_lookup != NULL && row_info->bit_depth == 8)
3793 int r, g, b, p;
3794 sp = row;
3795 dp = row;
3796 for (i = 0; i < row_width; i++)
3798 r = *sp++;
3799 g = *sp++;
3800 b = *sp++;
3801 sp++;
3803 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3804 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3805 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3806 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3807 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3808 (PNG_DITHER_BLUE_BITS)) |
3809 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3810 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3812 *dp++ = palette_lookup[p];
3814 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3815 row_info->channels = 1;
3816 row_info->pixel_depth = row_info->bit_depth;
3817 row_info->rowbytes =
3818 ((row_width * row_info->pixel_depth + 7) >> 3);
3820 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
3821 dither_lookup && row_info->bit_depth == 8)
3823 sp = row;
3824 for (i = 0; i < row_width; i++, sp++)
3826 *sp = dither_lookup[*sp];
3831 #endif
3833 #ifdef PNG_FLOATING_POINT_SUPPORTED
3834 #if defined(PNG_READ_GAMMA_SUPPORTED)
3835 static int png_gamma_shift[] =
3836 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
3838 /* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
3839 * tables, we don't make a full table if we are reducing to 8-bit in
3840 * the future. Note also how the gamma_16 tables are segmented so that
3841 * we don't need to allocate > 64K chunks for a full 16-bit table.
3843 void /* PRIVATE */
3844 png_build_gamma_table(png_structp png_ptr)
3846 png_debug(1, "in png_build_gamma_table\n");
3847 if(png_ptr->gamma != 0.0)
3849 if (png_ptr->bit_depth <= 8)
3851 int i;
3852 double g;
3854 if (png_ptr->screen_gamma > .000001)
3855 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3856 else
3857 g = 1.0;
3859 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
3860 (png_uint_32)256);
3862 for (i = 0; i < 256; i++)
3864 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
3865 g) * 255.0 + .5);
3868 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3869 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
3870 if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
3873 g = 1.0 / (png_ptr->gamma);
3875 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
3876 (png_uint_32)256);
3878 for (i = 0; i < 256; i++)
3880 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
3881 g) * 255.0 + .5);
3885 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
3886 (png_uint_32)256);
3888 if(png_ptr->screen_gamma > 0.000001)
3889 g = 1.0 / png_ptr->screen_gamma;
3890 else
3891 g = png_ptr->gamma; /* probably doing rgb_to_gray */
3893 for (i = 0; i < 256; i++)
3895 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
3896 g) * 255.0 + .5);
3900 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
3902 else
3904 double g;
3905 int i, j, shift, num;
3906 int sig_bit;
3907 png_uint_32 ig;
3909 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
3911 sig_bit = (int)png_ptr->sig_bit.red;
3912 if ((int)png_ptr->sig_bit.green > sig_bit)
3913 sig_bit = png_ptr->sig_bit.green;
3914 if ((int)png_ptr->sig_bit.blue > sig_bit)
3915 sig_bit = png_ptr->sig_bit.blue;
3917 else
3919 sig_bit = (int)png_ptr->sig_bit.gray;
3922 if (sig_bit > 0)
3923 shift = 16 - sig_bit;
3924 else
3925 shift = 0;
3927 if (png_ptr->transformations & PNG_16_TO_8)
3929 if (shift < (16 - PNG_MAX_GAMMA_8))
3930 shift = (16 - PNG_MAX_GAMMA_8);
3933 if (shift > 8)
3934 shift = 8;
3935 if (shift < 0)
3936 shift = 0;
3938 png_ptr->gamma_shift = (png_byte)shift;
3940 num = (1 << (8 - shift));
3942 if (png_ptr->screen_gamma > .000001)
3943 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3944 else
3945 g = 1.0;
3947 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
3948 (png_uint_32)(num * sizeof (png_uint_16p)));
3950 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
3952 double fin, fout;
3953 png_uint_32 last, max;
3955 for (i = 0; i < num; i++)
3957 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
3958 (png_uint_32)(256 * sizeof (png_uint_16)));
3961 g = 1.0 / g;
3962 last = 0;
3963 for (i = 0; i < 256; i++)
3965 fout = ((double)i + 0.5) / 256.0;
3966 fin = pow(fout, g);
3967 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
3968 while (last <= max)
3970 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
3971 [(int)(last >> (8 - shift))] = (png_uint_16)(
3972 (png_uint_16)i | ((png_uint_16)i << 8));
3973 last++;
3976 while (last < ((png_uint_32)num << 8))
3978 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
3979 [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
3980 last++;
3983 else
3985 for (i = 0; i < num; i++)
3987 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
3988 (png_uint_32)(256 * sizeof (png_uint_16)));
3990 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
3991 for (j = 0; j < 256; j++)
3993 png_ptr->gamma_16_table[i][j] =
3994 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
3995 65535.0, g) * 65535.0 + .5);
4000 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4001 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4002 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
4005 g = 1.0 / (png_ptr->gamma);
4007 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
4008 (png_uint_32)(num * sizeof (png_uint_16p )));
4010 for (i = 0; i < num; i++)
4012 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
4013 (png_uint_32)(256 * sizeof (png_uint_16)));
4015 ig = (((png_uint_32)i *
4016 (png_uint_32)png_gamma_shift[shift]) >> 4);
4017 for (j = 0; j < 256; j++)
4019 png_ptr->gamma_16_to_1[i][j] =
4020 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4021 65535.0, g) * 65535.0 + .5);
4025 if(png_ptr->screen_gamma > 0.000001)
4026 g = 1.0 / png_ptr->screen_gamma;
4027 else
4028 g = png_ptr->gamma; /* probably doing rgb_to_gray */
4030 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
4031 (png_uint_32)(num * sizeof (png_uint_16p)));
4033 for (i = 0; i < num; i++)
4035 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
4036 (png_uint_32)(256 * sizeof (png_uint_16)));
4038 ig = (((png_uint_32)i *
4039 (png_uint_32)png_gamma_shift[shift]) >> 4);
4040 for (j = 0; j < 256; j++)
4042 png_ptr->gamma_16_from_1[i][j] =
4043 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4044 65535.0, g) * 65535.0 + .5);
4048 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4052 #endif
4053 /* To do: install integer version of png_build_gamma_table here */
4054 #endif
4056 #if defined(PNG_MNG_FEATURES_SUPPORTED)
4057 /* undoes intrapixel differencing */
4058 void /* PRIVATE */
4059 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4061 png_debug(1, "in png_do_read_intrapixel\n");
4062 if (
4063 #if defined(PNG_USELESS_TESTS_SUPPORTED)
4064 row != NULL && row_info != NULL &&
4065 #endif
4066 (row_info->color_type & PNG_COLOR_MASK_COLOR))
4068 int bytes_per_pixel;
4069 png_uint_32 row_width = row_info->width;
4070 if (row_info->bit_depth == 8)
4072 png_bytep rp;
4073 png_uint_32 i;
4075 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4076 bytes_per_pixel = 3;
4077 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4078 bytes_per_pixel = 4;
4079 else
4080 return;
4082 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4084 *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
4085 *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
4088 else if (row_info->bit_depth == 16)
4090 png_bytep rp;
4091 png_uint_32 i;
4093 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4094 bytes_per_pixel = 6;
4095 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4096 bytes_per_pixel = 8;
4097 else
4098 return;
4100 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4102 png_uint_32 s0=*(rp )<<8 | *(rp+1);
4103 png_uint_32 s1=*(rp+2)<<8 | *(rp+3);
4104 png_uint_32 s2=*(rp+4)<<8 | *(rp+5);
4105 png_uint_32 red=(65536+s0+s1)&0xffff;
4106 png_uint_32 blue=(65536+s2+s1)&0xffff;
4107 *(rp ) = (png_byte)((red>>8)&0xff);
4108 *(rp+1) = (png_byte)(red&0xff);
4109 *(rp+4) = (png_byte)((blue>>8)&0xff);
4110 *(rp+5) = (png_byte)(blue&0xff);
4115 #endif /* PNG_MNG_FEATURES_SUPPORTED */