istereo
view libs/libpng/pngrtran.c @ 26:862a3329a8f0
wohooo, added a shitload of code from zlib/libpng/libjpeg. When the good lord was raining shared libraries the iphone held a fucking umbrella...
author | John Tsiombikas <nuclear@mutantstargoat.com> |
---|---|
date | Thu, 08 Sep 2011 06:28:38 +0300 |
parents | |
children |
line source
2 /* pngrtran.c - transforms the data in a row for PNG readers
3 *
4 * Last changed in libpng 1.2.30 [August 15, 2008]
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2008 Glenn Randers-Pehrson
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9 *
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.
14 */
16 #define PNG_INTERNAL
17 #include "png.h"
18 #if defined(PNG_READ_SUPPORTED)
20 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
21 void PNGAPI
22 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
23 {
24 png_debug(1, "in png_set_crc_action\n");
25 /* Tell libpng how we react to CRC errors in critical chunks */
26 if (png_ptr == NULL) return;
27 switch (crit_action)
28 {
29 case PNG_CRC_NO_CHANGE: /* leave setting as is */
30 break;
31 case PNG_CRC_WARN_USE: /* warn/use data */
32 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
33 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
34 break;
35 case PNG_CRC_QUIET_USE: /* quiet/use data */
36 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
37 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
38 PNG_FLAG_CRC_CRITICAL_IGNORE;
39 break;
40 case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */
41 png_warning(png_ptr,
42 "Can't discard critical data on CRC error.");
43 case PNG_CRC_ERROR_QUIT: /* error/quit */
44 case PNG_CRC_DEFAULT:
45 default:
46 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
47 break;
48 }
50 switch (ancil_action)
51 {
52 case PNG_CRC_NO_CHANGE: /* leave setting as is */
53 break;
54 case PNG_CRC_WARN_USE: /* warn/use data */
55 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
56 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
57 break;
58 case PNG_CRC_QUIET_USE: /* quiet/use data */
59 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
60 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
61 PNG_FLAG_CRC_ANCILLARY_NOWARN;
62 break;
63 case PNG_CRC_ERROR_QUIT: /* error/quit */
64 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
65 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
66 break;
67 case PNG_CRC_WARN_DISCARD: /* warn/discard data */
68 case PNG_CRC_DEFAULT:
69 default:
70 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
71 break;
72 }
73 }
75 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
76 defined(PNG_FLOATING_POINT_SUPPORTED)
77 /* handle alpha and tRNS via a background color */
78 void PNGAPI
79 png_set_background(png_structp png_ptr,
80 png_color_16p background_color, int background_gamma_code,
81 int need_expand, double background_gamma)
82 {
83 png_debug(1, "in png_set_background\n");
84 if (png_ptr == NULL) return;
85 if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
86 {
87 png_warning(png_ptr, "Application must supply a known background gamma");
88 return;
89 }
91 png_ptr->transformations |= PNG_BACKGROUND;
92 png_memcpy(&(png_ptr->background), background_color,
93 png_sizeof(png_color_16));
94 png_ptr->background_gamma = (float)background_gamma;
95 png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
96 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
97 }
98 #endif
100 #if defined(PNG_READ_16_TO_8_SUPPORTED)
101 /* strip 16 bit depth files to 8 bit depth */
102 void PNGAPI
103 png_set_strip_16(png_structp png_ptr)
104 {
105 png_debug(1, "in png_set_strip_16\n");
106 if (png_ptr == NULL) return;
107 png_ptr->transformations |= PNG_16_TO_8;
108 }
109 #endif
111 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
112 void PNGAPI
113 png_set_strip_alpha(png_structp png_ptr)
114 {
115 png_debug(1, "in png_set_strip_alpha\n");
116 if (png_ptr == NULL) return;
117 png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
118 }
119 #endif
121 #if defined(PNG_READ_DITHER_SUPPORTED)
122 /* Dither file to 8 bit. Supply a palette, the current number
123 * of elements in the palette, the maximum number of elements
124 * allowed, and a histogram if possible. If the current number
125 * of colors is greater then the maximum number, the palette will be
126 * modified to fit in the maximum number. "full_dither" indicates
127 * whether we need a dithering cube set up for RGB images, or if we
128 * simply are reducing the number of colors in a paletted image.
129 */
131 typedef struct png_dsort_struct
132 {
133 struct png_dsort_struct FAR * next;
134 png_byte left;
135 png_byte right;
136 } png_dsort;
137 typedef png_dsort FAR * png_dsortp;
138 typedef png_dsort FAR * FAR * png_dsortpp;
140 void PNGAPI
141 png_set_dither(png_structp png_ptr, png_colorp palette,
142 int num_palette, int maximum_colors, png_uint_16p histogram,
143 int full_dither)
144 {
145 png_debug(1, "in png_set_dither\n");
146 if (png_ptr == NULL) return;
147 png_ptr->transformations |= PNG_DITHER;
149 if (!full_dither)
150 {
151 int i;
153 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
154 (png_uint_32)(num_palette * png_sizeof(png_byte)));
155 for (i = 0; i < num_palette; i++)
156 png_ptr->dither_index[i] = (png_byte)i;
157 }
159 if (num_palette > maximum_colors)
160 {
161 if (histogram != NULL)
162 {
163 /* This is easy enough, just throw out the least used colors.
164 Perhaps not the best solution, but good enough. */
166 int i;
168 /* initialize an array to sort colors */
169 png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
170 (png_uint_32)(num_palette * png_sizeof(png_byte)));
172 /* initialize the dither_sort array */
173 for (i = 0; i < num_palette; i++)
174 png_ptr->dither_sort[i] = (png_byte)i;
176 /* Find the least used palette entries by starting a
177 bubble sort, and running it until we have sorted
178 out enough colors. Note that we don't care about
179 sorting all the colors, just finding which are
180 least used. */
182 for (i = num_palette - 1; i >= maximum_colors; i--)
183 {
184 int done; /* to stop early if the list is pre-sorted */
185 int j;
187 done = 1;
188 for (j = 0; j < i; j++)
189 {
190 if (histogram[png_ptr->dither_sort[j]]
191 < histogram[png_ptr->dither_sort[j + 1]])
192 {
193 png_byte t;
195 t = png_ptr->dither_sort[j];
196 png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
197 png_ptr->dither_sort[j + 1] = t;
198 done = 0;
199 }
200 }
201 if (done)
202 break;
203 }
205 /* swap the palette around, and set up a table, if necessary */
206 if (full_dither)
207 {
208 int j = num_palette;
210 /* put all the useful colors within the max, but don't
211 move the others */
212 for (i = 0; i < maximum_colors; i++)
213 {
214 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
215 {
216 do
217 j--;
218 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
219 palette[i] = palette[j];
220 }
221 }
222 }
223 else
224 {
225 int j = num_palette;
227 /* move all the used colors inside the max limit, and
228 develop a translation table */
229 for (i = 0; i < maximum_colors; i++)
230 {
231 /* only move the colors we need to */
232 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
233 {
234 png_color tmp_color;
236 do
237 j--;
238 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
240 tmp_color = palette[j];
241 palette[j] = palette[i];
242 palette[i] = tmp_color;
243 /* indicate where the color went */
244 png_ptr->dither_index[j] = (png_byte)i;
245 png_ptr->dither_index[i] = (png_byte)j;
246 }
247 }
249 /* find closest color for those colors we are not using */
250 for (i = 0; i < num_palette; i++)
251 {
252 if ((int)png_ptr->dither_index[i] >= maximum_colors)
253 {
254 int min_d, k, min_k, d_index;
256 /* find the closest color to one we threw out */
257 d_index = png_ptr->dither_index[i];
258 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
259 for (k = 1, min_k = 0; k < maximum_colors; k++)
260 {
261 int d;
263 d = PNG_COLOR_DIST(palette[d_index], palette[k]);
265 if (d < min_d)
266 {
267 min_d = d;
268 min_k = k;
269 }
270 }
271 /* point to closest color */
272 png_ptr->dither_index[i] = (png_byte)min_k;
273 }
274 }
275 }
276 png_free(png_ptr, png_ptr->dither_sort);
277 png_ptr->dither_sort = NULL;
278 }
279 else
280 {
281 /* This is much harder to do simply (and quickly). Perhaps
282 we need to go through a median cut routine, but those
283 don't always behave themselves with only a few colors
284 as input. So we will just find the closest two colors,
285 and throw out one of them (chosen somewhat randomly).
286 [We don't understand this at all, so if someone wants to
287 work on improving it, be our guest - AED, GRP]
288 */
289 int i;
290 int max_d;
291 int num_new_palette;
292 png_dsortp t;
293 png_dsortpp hash;
295 t = NULL;
297 /* initialize palette index arrays */
298 png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
299 (png_uint_32)(num_palette * png_sizeof(png_byte)));
300 png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
301 (png_uint_32)(num_palette * png_sizeof(png_byte)));
303 /* initialize the sort array */
304 for (i = 0; i < num_palette; i++)
305 {
306 png_ptr->index_to_palette[i] = (png_byte)i;
307 png_ptr->palette_to_index[i] = (png_byte)i;
308 }
310 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
311 png_sizeof(png_dsortp)));
312 for (i = 0; i < 769; i++)
313 hash[i] = NULL;
314 /* png_memset(hash, 0, 769 * png_sizeof(png_dsortp)); */
316 num_new_palette = num_palette;
318 /* initial wild guess at how far apart the farthest pixel
319 pair we will be eliminating will be. Larger
320 numbers mean more areas will be allocated, Smaller
321 numbers run the risk of not saving enough data, and
322 having to do this all over again.
324 I have not done extensive checking on this number.
325 */
326 max_d = 96;
328 while (num_new_palette > maximum_colors)
329 {
330 for (i = 0; i < num_new_palette - 1; i++)
331 {
332 int j;
334 for (j = i + 1; j < num_new_palette; j++)
335 {
336 int d;
338 d = PNG_COLOR_DIST(palette[i], palette[j]);
340 if (d <= max_d)
341 {
343 t = (png_dsortp)png_malloc_warn(png_ptr,
344 (png_uint_32)(png_sizeof(png_dsort)));
345 if (t == NULL)
346 break;
347 t->next = hash[d];
348 t->left = (png_byte)i;
349 t->right = (png_byte)j;
350 hash[d] = t;
351 }
352 }
353 if (t == NULL)
354 break;
355 }
357 if (t != NULL)
358 for (i = 0; i <= max_d; i++)
359 {
360 if (hash[i] != NULL)
361 {
362 png_dsortp p;
364 for (p = hash[i]; p; p = p->next)
365 {
366 if ((int)png_ptr->index_to_palette[p->left]
367 < num_new_palette &&
368 (int)png_ptr->index_to_palette[p->right]
369 < num_new_palette)
370 {
371 int j, next_j;
373 if (num_new_palette & 0x01)
374 {
375 j = p->left;
376 next_j = p->right;
377 }
378 else
379 {
380 j = p->right;
381 next_j = p->left;
382 }
384 num_new_palette--;
385 palette[png_ptr->index_to_palette[j]]
386 = palette[num_new_palette];
387 if (!full_dither)
388 {
389 int k;
391 for (k = 0; k < num_palette; k++)
392 {
393 if (png_ptr->dither_index[k] ==
394 png_ptr->index_to_palette[j])
395 png_ptr->dither_index[k] =
396 png_ptr->index_to_palette[next_j];
397 if ((int)png_ptr->dither_index[k] ==
398 num_new_palette)
399 png_ptr->dither_index[k] =
400 png_ptr->index_to_palette[j];
401 }
402 }
404 png_ptr->index_to_palette[png_ptr->palette_to_index
405 [num_new_palette]] = png_ptr->index_to_palette[j];
406 png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
407 = png_ptr->palette_to_index[num_new_palette];
409 png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
410 png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
411 }
412 if (num_new_palette <= maximum_colors)
413 break;
414 }
415 if (num_new_palette <= maximum_colors)
416 break;
417 }
418 }
420 for (i = 0; i < 769; i++)
421 {
422 if (hash[i] != NULL)
423 {
424 png_dsortp p = hash[i];
425 while (p)
426 {
427 t = p->next;
428 png_free(png_ptr, p);
429 p = t;
430 }
431 }
432 hash[i] = 0;
433 }
434 max_d += 96;
435 }
436 png_free(png_ptr, hash);
437 png_free(png_ptr, png_ptr->palette_to_index);
438 png_free(png_ptr, png_ptr->index_to_palette);
439 png_ptr->palette_to_index = NULL;
440 png_ptr->index_to_palette = NULL;
441 }
442 num_palette = maximum_colors;
443 }
444 if (png_ptr->palette == NULL)
445 {
446 png_ptr->palette = palette;
447 }
448 png_ptr->num_palette = (png_uint_16)num_palette;
450 if (full_dither)
451 {
452 int i;
453 png_bytep distance;
454 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
455 PNG_DITHER_BLUE_BITS;
456 int num_red = (1 << PNG_DITHER_RED_BITS);
457 int num_green = (1 << PNG_DITHER_GREEN_BITS);
458 int num_blue = (1 << PNG_DITHER_BLUE_BITS);
459 png_size_t num_entries = ((png_size_t)1 << total_bits);
461 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
462 (png_uint_32)(num_entries * png_sizeof(png_byte)));
464 png_memset(png_ptr->palette_lookup, 0, num_entries *
465 png_sizeof(png_byte));
467 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
468 png_sizeof(png_byte)));
470 png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
472 for (i = 0; i < num_palette; i++)
473 {
474 int ir, ig, ib;
475 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
476 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
477 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
479 for (ir = 0; ir < num_red; ir++)
480 {
481 /* int dr = abs(ir - r); */
482 int dr = ((ir > r) ? ir - r : r - ir);
483 int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
485 for (ig = 0; ig < num_green; ig++)
486 {
487 /* int dg = abs(ig - g); */
488 int dg = ((ig > g) ? ig - g : g - ig);
489 int dt = dr + dg;
490 int dm = ((dr > dg) ? dr : dg);
491 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
493 for (ib = 0; ib < num_blue; ib++)
494 {
495 int d_index = index_g | ib;
496 /* int db = abs(ib - b); */
497 int db = ((ib > b) ? ib - b : b - ib);
498 int dmax = ((dm > db) ? dm : db);
499 int d = dmax + dt + db;
501 if (d < (int)distance[d_index])
502 {
503 distance[d_index] = (png_byte)d;
504 png_ptr->palette_lookup[d_index] = (png_byte)i;
505 }
506 }
507 }
508 }
509 }
511 png_free(png_ptr, distance);
512 }
513 }
514 #endif
516 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
517 /* Transform the image from the file_gamma to the screen_gamma. We
518 * only do transformations on images where the file_gamma and screen_gamma
519 * are not close reciprocals, otherwise it slows things down slightly, and
520 * also needlessly introduces small errors.
521 *
522 * We will turn off gamma transformation later if no semitransparent entries
523 * are present in the tRNS array for palette images. We can't do it here
524 * because we don't necessarily have the tRNS chunk yet.
525 */
526 void PNGAPI
527 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
528 {
529 png_debug(1, "in png_set_gamma\n");
530 if (png_ptr == NULL) return;
531 if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
532 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
533 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
534 png_ptr->transformations |= PNG_GAMMA;
535 png_ptr->gamma = (float)file_gamma;
536 png_ptr->screen_gamma = (float)scrn_gamma;
537 }
538 #endif
540 #if defined(PNG_READ_EXPAND_SUPPORTED)
541 /* Expand paletted images to RGB, expand grayscale images of
542 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
543 * to alpha channels.
544 */
545 void PNGAPI
546 png_set_expand(png_structp png_ptr)
547 {
548 png_debug(1, "in png_set_expand\n");
549 if (png_ptr == NULL) return;
550 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
551 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
552 }
554 /* GRR 19990627: the following three functions currently are identical
555 * to png_set_expand(). However, it is entirely reasonable that someone
556 * might wish to expand an indexed image to RGB but *not* expand a single,
557 * fully transparent palette entry to a full alpha channel--perhaps instead
558 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
559 * the transparent color with a particular RGB value, or drop tRNS entirely.
560 * IOW, a future version of the library may make the transformations flag
561 * a bit more fine-grained, with separate bits for each of these three
562 * functions.
563 *
564 * More to the point, these functions make it obvious what libpng will be
565 * doing, whereas "expand" can (and does) mean any number of things.
566 *
567 * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified
568 * to expand only the sample depth but not to expand the tRNS to alpha.
569 */
571 /* Expand paletted images to RGB. */
572 void PNGAPI
573 png_set_palette_to_rgb(png_structp png_ptr)
574 {
575 png_debug(1, "in png_set_palette_to_rgb\n");
576 if (png_ptr == NULL) return;
577 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
578 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
579 }
581 #if !defined(PNG_1_0_X)
582 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
583 void PNGAPI
584 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
585 {
586 png_debug(1, "in png_set_expand_gray_1_2_4_to_8\n");
587 if (png_ptr == NULL) return;
588 png_ptr->transformations |= PNG_EXPAND;
589 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
590 }
591 #endif
593 #if defined(PNG_1_0_X) || defined(PNG_1_2_X)
594 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
595 /* Deprecated as of libpng-1.2.9 */
596 void PNGAPI
597 png_set_gray_1_2_4_to_8(png_structp png_ptr)
598 {
599 png_debug(1, "in png_set_gray_1_2_4_to_8\n");
600 if (png_ptr == NULL) return;
601 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
602 }
603 #endif
606 /* Expand tRNS chunks to alpha channels. */
607 void PNGAPI
608 png_set_tRNS_to_alpha(png_structp png_ptr)
609 {
610 png_debug(1, "in png_set_tRNS_to_alpha\n");
611 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
612 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
613 }
614 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
616 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
617 void PNGAPI
618 png_set_gray_to_rgb(png_structp png_ptr)
619 {
620 png_debug(1, "in png_set_gray_to_rgb\n");
621 png_ptr->transformations |= PNG_GRAY_TO_RGB;
622 png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
623 }
624 #endif
626 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
627 #if defined(PNG_FLOATING_POINT_SUPPORTED)
628 /* Convert a RGB image to a grayscale of the same width. This allows us,
629 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
630 */
632 void PNGAPI
633 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
634 double green)
635 {
636 int red_fixed = (int)((float)red*100000.0 + 0.5);
637 int green_fixed = (int)((float)green*100000.0 + 0.5);
638 if (png_ptr == NULL) return;
639 png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
640 }
641 #endif
643 void PNGAPI
644 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
645 png_fixed_point red, png_fixed_point green)
646 {
647 png_debug(1, "in png_set_rgb_to_gray\n");
648 if (png_ptr == NULL) return;
649 switch(error_action)
650 {
651 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
652 break;
653 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
654 break;
655 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
656 }
657 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
658 #if defined(PNG_READ_EXPAND_SUPPORTED)
659 png_ptr->transformations |= PNG_EXPAND;
660 #else
661 {
662 png_warning(png_ptr,
663 "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
664 png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
665 }
666 #endif
667 {
668 png_uint_16 red_int, green_int;
669 if (red < 0 || green < 0)
670 {
671 red_int = 6968; /* .212671 * 32768 + .5 */
672 green_int = 23434; /* .715160 * 32768 + .5 */
673 }
674 else if (red + green < 100000L)
675 {
676 red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
677 green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
678 }
679 else
680 {
681 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
682 red_int = 6968;
683 green_int = 23434;
684 }
685 png_ptr->rgb_to_gray_red_coeff = red_int;
686 png_ptr->rgb_to_gray_green_coeff = green_int;
687 png_ptr->rgb_to_gray_blue_coeff =
688 (png_uint_16)(32768 - red_int - green_int);
689 }
690 }
691 #endif
693 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
694 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
695 defined(PNG_LEGACY_SUPPORTED)
696 void PNGAPI
697 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
698 read_user_transform_fn)
699 {
700 png_debug(1, "in png_set_read_user_transform_fn\n");
701 if (png_ptr == NULL) return;
702 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
703 png_ptr->transformations |= PNG_USER_TRANSFORM;
704 png_ptr->read_user_transform_fn = read_user_transform_fn;
705 #endif
706 #ifdef PNG_LEGACY_SUPPORTED
707 if (read_user_transform_fn)
708 png_warning(png_ptr,
709 "This version of libpng does not support user transforms");
710 #endif
711 }
712 #endif
714 /* Initialize everything needed for the read. This includes modifying
715 * the palette.
716 */
717 void /* PRIVATE */
718 png_init_read_transformations(png_structp png_ptr)
719 {
720 png_debug(1, "in png_init_read_transformations\n");
721 #if defined(PNG_USELESS_TESTS_SUPPORTED)
722 if (png_ptr != NULL)
723 #endif
724 {
725 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
726 || defined(PNG_READ_GAMMA_SUPPORTED)
727 int color_type = png_ptr->color_type;
728 #endif
730 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
732 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
733 /* Detect gray background and attempt to enable optimization
734 * for gray --> RGB case */
735 /* Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
736 * RGB_ALPHA (in which case need_expand is superfluous anyway), the
737 * background color might actually be gray yet not be flagged as such.
738 * This is not a problem for the current code, which uses
739 * PNG_BACKGROUND_IS_GRAY only to decide when to do the
740 * png_do_gray_to_rgb() transformation.
741 */
742 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
743 !(color_type & PNG_COLOR_MASK_COLOR))
744 {
745 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
746 } else if ((png_ptr->transformations & PNG_BACKGROUND) &&
747 !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
748 (png_ptr->transformations & PNG_GRAY_TO_RGB) &&
749 png_ptr->background.red == png_ptr->background.green &&
750 png_ptr->background.red == png_ptr->background.blue)
751 {
752 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
753 png_ptr->background.gray = png_ptr->background.red;
754 }
755 #endif
757 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
758 (png_ptr->transformations & PNG_EXPAND))
759 {
760 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
761 {
762 /* expand background and tRNS chunks */
763 switch (png_ptr->bit_depth)
764 {
765 case 1:
766 png_ptr->background.gray *= (png_uint_16)0xff;
767 png_ptr->background.red = png_ptr->background.green
768 = png_ptr->background.blue = png_ptr->background.gray;
769 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
770 {
771 png_ptr->trans_values.gray *= (png_uint_16)0xff;
772 png_ptr->trans_values.red = png_ptr->trans_values.green
773 = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
774 }
775 break;
776 case 2:
777 png_ptr->background.gray *= (png_uint_16)0x55;
778 png_ptr->background.red = png_ptr->background.green
779 = png_ptr->background.blue = png_ptr->background.gray;
780 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
781 {
782 png_ptr->trans_values.gray *= (png_uint_16)0x55;
783 png_ptr->trans_values.red = png_ptr->trans_values.green
784 = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
785 }
786 break;
787 case 4:
788 png_ptr->background.gray *= (png_uint_16)0x11;
789 png_ptr->background.red = png_ptr->background.green
790 = png_ptr->background.blue = png_ptr->background.gray;
791 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
792 {
793 png_ptr->trans_values.gray *= (png_uint_16)0x11;
794 png_ptr->trans_values.red = png_ptr->trans_values.green
795 = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
796 }
797 break;
798 case 8:
799 case 16:
800 png_ptr->background.red = png_ptr->background.green
801 = png_ptr->background.blue = png_ptr->background.gray;
802 break;
803 }
804 }
805 else if (color_type == PNG_COLOR_TYPE_PALETTE)
806 {
807 png_ptr->background.red =
808 png_ptr->palette[png_ptr->background.index].red;
809 png_ptr->background.green =
810 png_ptr->palette[png_ptr->background.index].green;
811 png_ptr->background.blue =
812 png_ptr->palette[png_ptr->background.index].blue;
814 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
815 if (png_ptr->transformations & PNG_INVERT_ALPHA)
816 {
817 #if defined(PNG_READ_EXPAND_SUPPORTED)
818 if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
819 #endif
820 {
821 /* invert the alpha channel (in tRNS) unless the pixels are
822 going to be expanded, in which case leave it for later */
823 int i, istop;
824 istop=(int)png_ptr->num_trans;
825 for (i=0; i<istop; i++)
826 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
827 }
828 }
829 #endif
831 }
832 }
833 #endif
835 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
836 png_ptr->background_1 = png_ptr->background;
837 #endif
838 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
840 if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
841 && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
842 < PNG_GAMMA_THRESHOLD))
843 {
844 int i, k;
845 k=0;
846 for (i=0; i<png_ptr->num_trans; i++)
847 {
848 if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
849 k=1; /* partial transparency is present */
850 }
851 if (k == 0)
852 png_ptr->transformations &= ~PNG_GAMMA;
853 }
855 if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) &&
856 png_ptr->gamma != 0.0)
857 {
858 png_build_gamma_table(png_ptr);
859 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
860 if (png_ptr->transformations & PNG_BACKGROUND)
861 {
862 if (color_type == PNG_COLOR_TYPE_PALETTE)
863 {
864 /* could skip if no transparency and
865 */
866 png_color back, back_1;
867 png_colorp palette = png_ptr->palette;
868 int num_palette = png_ptr->num_palette;
869 int i;
870 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
871 {
872 back.red = png_ptr->gamma_table[png_ptr->background.red];
873 back.green = png_ptr->gamma_table[png_ptr->background.green];
874 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
876 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
877 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
878 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
879 }
880 else
881 {
882 double g, gs;
884 switch (png_ptr->background_gamma_type)
885 {
886 case PNG_BACKGROUND_GAMMA_SCREEN:
887 g = (png_ptr->screen_gamma);
888 gs = 1.0;
889 break;
890 case PNG_BACKGROUND_GAMMA_FILE:
891 g = 1.0 / (png_ptr->gamma);
892 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
893 break;
894 case PNG_BACKGROUND_GAMMA_UNIQUE:
895 g = 1.0 / (png_ptr->background_gamma);
896 gs = 1.0 / (png_ptr->background_gamma *
897 png_ptr->screen_gamma);
898 break;
899 default:
900 g = 1.0; /* back_1 */
901 gs = 1.0; /* back */
902 }
904 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
905 {
906 back.red = (png_byte)png_ptr->background.red;
907 back.green = (png_byte)png_ptr->background.green;
908 back.blue = (png_byte)png_ptr->background.blue;
909 }
910 else
911 {
912 back.red = (png_byte)(pow(
913 (double)png_ptr->background.red/255, gs) * 255.0 + .5);
914 back.green = (png_byte)(pow(
915 (double)png_ptr->background.green/255, gs) * 255.0 + .5);
916 back.blue = (png_byte)(pow(
917 (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
918 }
920 back_1.red = (png_byte)(pow(
921 (double)png_ptr->background.red/255, g) * 255.0 + .5);
922 back_1.green = (png_byte)(pow(
923 (double)png_ptr->background.green/255, g) * 255.0 + .5);
924 back_1.blue = (png_byte)(pow(
925 (double)png_ptr->background.blue/255, g) * 255.0 + .5);
926 }
927 for (i = 0; i < num_palette; i++)
928 {
929 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
930 {
931 if (png_ptr->trans[i] == 0)
932 {
933 palette[i] = back;
934 }
935 else /* if (png_ptr->trans[i] != 0xff) */
936 {
937 png_byte v, w;
939 v = png_ptr->gamma_to_1[palette[i].red];
940 png_composite(w, v, png_ptr->trans[i], back_1.red);
941 palette[i].red = png_ptr->gamma_from_1[w];
943 v = png_ptr->gamma_to_1[palette[i].green];
944 png_composite(w, v, png_ptr->trans[i], back_1.green);
945 palette[i].green = png_ptr->gamma_from_1[w];
947 v = png_ptr->gamma_to_1[palette[i].blue];
948 png_composite(w, v, png_ptr->trans[i], back_1.blue);
949 palette[i].blue = png_ptr->gamma_from_1[w];
950 }
951 }
952 else
953 {
954 palette[i].red = png_ptr->gamma_table[palette[i].red];
955 palette[i].green = png_ptr->gamma_table[palette[i].green];
956 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
957 }
958 }
959 /* Prevent the transformations being done again, and make sure
960 * that the now spurious alpha channel is stripped - the code
961 * has just reduced background composition and gamma correction
962 * to a simple alpha channel strip.
963 */
964 png_ptr->transformations &= ~PNG_BACKGROUND;
965 png_ptr->transformations &= ~PNG_GAMMA;
966 png_ptr->transformations |= PNG_STRIP_ALPHA;
967 }
968 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
969 else
970 /* color_type != PNG_COLOR_TYPE_PALETTE */
971 {
972 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
973 double g = 1.0;
974 double gs = 1.0;
976 switch (png_ptr->background_gamma_type)
977 {
978 case PNG_BACKGROUND_GAMMA_SCREEN:
979 g = (png_ptr->screen_gamma);
980 gs = 1.0;
981 break;
982 case PNG_BACKGROUND_GAMMA_FILE:
983 g = 1.0 / (png_ptr->gamma);
984 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
985 break;
986 case PNG_BACKGROUND_GAMMA_UNIQUE:
987 g = 1.0 / (png_ptr->background_gamma);
988 gs = 1.0 / (png_ptr->background_gamma *
989 png_ptr->screen_gamma);
990 break;
991 }
993 png_ptr->background_1.gray = (png_uint_16)(pow(
994 (double)png_ptr->background.gray / m, g) * m + .5);
995 png_ptr->background.gray = (png_uint_16)(pow(
996 (double)png_ptr->background.gray / m, gs) * m + .5);
998 if ((png_ptr->background.red != png_ptr->background.green) ||
999 (png_ptr->background.red != png_ptr->background.blue) ||
1000 (png_ptr->background.red != png_ptr->background.gray))
1001 {
1002 /* RGB or RGBA with color background */
1003 png_ptr->background_1.red = (png_uint_16)(pow(
1004 (double)png_ptr->background.red / m, g) * m + .5);
1005 png_ptr->background_1.green = (png_uint_16)(pow(
1006 (double)png_ptr->background.green / m, g) * m + .5);
1007 png_ptr->background_1.blue = (png_uint_16)(pow(
1008 (double)png_ptr->background.blue / m, g) * m + .5);
1009 png_ptr->background.red = (png_uint_16)(pow(
1010 (double)png_ptr->background.red / m, gs) * m + .5);
1011 png_ptr->background.green = (png_uint_16)(pow(
1012 (double)png_ptr->background.green / m, gs) * m + .5);
1013 png_ptr->background.blue = (png_uint_16)(pow(
1014 (double)png_ptr->background.blue / m, gs) * m + .5);
1015 }
1016 else
1017 {
1018 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
1019 png_ptr->background_1.red = png_ptr->background_1.green
1020 = png_ptr->background_1.blue = png_ptr->background_1.gray;
1021 png_ptr->background.red = png_ptr->background.green
1022 = png_ptr->background.blue = png_ptr->background.gray;
1023 }
1024 }
1025 }
1026 else
1027 /* transformation does not include PNG_BACKGROUND */
1028 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
1029 if (color_type == PNG_COLOR_TYPE_PALETTE)
1030 {
1031 png_colorp palette = png_ptr->palette;
1032 int num_palette = png_ptr->num_palette;
1033 int i;
1035 for (i = 0; i < num_palette; i++)
1036 {
1037 palette[i].red = png_ptr->gamma_table[palette[i].red];
1038 palette[i].green = png_ptr->gamma_table[palette[i].green];
1039 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1040 }
1042 /* Done the gamma correction. */
1043 png_ptr->transformations &= ~PNG_GAMMA;
1044 }
1045 }
1046 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1047 else
1048 #endif
1049 #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
1050 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1051 /* No GAMMA transformation */
1052 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1053 (color_type == PNG_COLOR_TYPE_PALETTE))
1054 {
1055 int i;
1056 int istop = (int)png_ptr->num_trans;
1057 png_color back;
1058 png_colorp palette = png_ptr->palette;
1060 back.red = (png_byte)png_ptr->background.red;
1061 back.green = (png_byte)png_ptr->background.green;
1062 back.blue = (png_byte)png_ptr->background.blue;
1064 for (i = 0; i < istop; i++)
1065 {
1066 if (png_ptr->trans[i] == 0)
1067 {
1068 palette[i] = back;
1069 }
1070 else if (png_ptr->trans[i] != 0xff)
1071 {
1072 /* The png_composite() macro is defined in png.h */
1073 png_composite(palette[i].red, palette[i].red,
1074 png_ptr->trans[i], back.red);
1075 png_composite(palette[i].green, palette[i].green,
1076 png_ptr->trans[i], back.green);
1077 png_composite(palette[i].blue, palette[i].blue,
1078 png_ptr->trans[i], back.blue);
1079 }
1080 }
1082 /* Handled alpha, still need to strip the channel. */
1083 png_ptr->transformations &= ~PNG_BACKGROUND;
1084 png_ptr->transformations |= PNG_STRIP_ALPHA;
1085 }
1086 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
1088 #if defined(PNG_READ_SHIFT_SUPPORTED)
1089 if ((png_ptr->transformations & PNG_SHIFT) &&
1090 (color_type == PNG_COLOR_TYPE_PALETTE))
1091 {
1092 png_uint_16 i;
1093 png_uint_16 istop = png_ptr->num_palette;
1094 int sr = 8 - png_ptr->sig_bit.red;
1095 int sg = 8 - png_ptr->sig_bit.green;
1096 int sb = 8 - png_ptr->sig_bit.blue;
1098 if (sr < 0 || sr > 8)
1099 sr = 0;
1100 if (sg < 0 || sg > 8)
1101 sg = 0;
1102 if (sb < 0 || sb > 8)
1103 sb = 0;
1104 for (i = 0; i < istop; i++)
1105 {
1106 png_ptr->palette[i].red >>= sr;
1107 png_ptr->palette[i].green >>= sg;
1108 png_ptr->palette[i].blue >>= sb;
1109 }
1110 }
1111 #endif /* PNG_READ_SHIFT_SUPPORTED */
1112 }
1113 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1114 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1115 if (png_ptr)
1116 return;
1117 #endif
1118 }
1120 /* Modify the info structure to reflect the transformations. The
1121 * info should be updated so a PNG file could be written with it,
1122 * assuming the transformations result in valid PNG data.
1123 */
1124 void /* PRIVATE */
1125 png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
1126 {
1127 png_debug(1, "in png_read_transform_info\n");
1128 #if defined(PNG_READ_EXPAND_SUPPORTED)
1129 if (png_ptr->transformations & PNG_EXPAND)
1130 {
1131 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1132 {
1133 if (png_ptr->num_trans &&
1134 (png_ptr->transformations & PNG_EXPAND_tRNS))
1135 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1136 else
1137 info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1138 info_ptr->bit_depth = 8;
1139 info_ptr->num_trans = 0;
1140 }
1141 else
1142 {
1143 if (png_ptr->num_trans)
1144 {
1145 if (png_ptr->transformations & PNG_EXPAND_tRNS)
1146 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1147 #if 0 /* Removed from libpng-1.2.27 */
1148 else
1149 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1150 #endif
1151 }
1152 if (info_ptr->bit_depth < 8)
1153 info_ptr->bit_depth = 8;
1154 info_ptr->num_trans = 0;
1155 }
1156 }
1157 #endif
1159 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1160 if (png_ptr->transformations & PNG_BACKGROUND)
1161 {
1162 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1163 info_ptr->num_trans = 0;
1164 info_ptr->background = png_ptr->background;
1165 }
1166 #endif
1168 #if defined(PNG_READ_GAMMA_SUPPORTED)
1169 if (png_ptr->transformations & PNG_GAMMA)
1170 {
1171 #ifdef PNG_FLOATING_POINT_SUPPORTED
1172 info_ptr->gamma = png_ptr->gamma;
1173 #endif
1174 #ifdef PNG_FIXED_POINT_SUPPORTED
1175 info_ptr->int_gamma = png_ptr->int_gamma;
1176 #endif
1177 }
1178 #endif
1180 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1181 if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
1182 info_ptr->bit_depth = 8;
1183 #endif
1185 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1186 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1187 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1188 #endif
1190 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1191 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1192 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1193 #endif
1195 #if defined(PNG_READ_DITHER_SUPPORTED)
1196 if (png_ptr->transformations & PNG_DITHER)
1197 {
1198 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1199 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1200 png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1201 {
1202 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1203 }
1204 }
1205 #endif
1207 #if defined(PNG_READ_PACK_SUPPORTED)
1208 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
1209 info_ptr->bit_depth = 8;
1210 #endif
1212 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1213 info_ptr->channels = 1;
1214 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1215 info_ptr->channels = 3;
1216 else
1217 info_ptr->channels = 1;
1219 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1220 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1221 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1222 #endif
1224 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1225 info_ptr->channels++;
1227 #if defined(PNG_READ_FILLER_SUPPORTED)
1228 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
1229 if ((png_ptr->transformations & PNG_FILLER) &&
1230 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1231 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1232 {
1233 info_ptr->channels++;
1234 /* if adding a true alpha channel not just filler */
1235 #if !defined(PNG_1_0_X)
1236 if (png_ptr->transformations & PNG_ADD_ALPHA)
1237 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1238 #endif
1239 }
1240 #endif
1242 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1243 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1244 if (png_ptr->transformations & PNG_USER_TRANSFORM)
1245 {
1246 if (info_ptr->bit_depth < png_ptr->user_transform_depth)
1247 info_ptr->bit_depth = png_ptr->user_transform_depth;
1248 if (info_ptr->channels < png_ptr->user_transform_channels)
1249 info_ptr->channels = png_ptr->user_transform_channels;
1250 }
1251 #endif
1253 info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1254 info_ptr->bit_depth);
1256 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
1258 #if !defined(PNG_READ_EXPAND_SUPPORTED)
1259 if (png_ptr)
1260 return;
1261 #endif
1262 }
1264 /* Transform the row. The order of transformations is significant,
1265 * and is very touchy. If you add a transformation, take care to
1266 * decide how it fits in with the other transformations here.
1267 */
1268 void /* PRIVATE */
1269 png_do_read_transformations(png_structp png_ptr)
1270 {
1271 png_debug(1, "in png_do_read_transformations\n");
1272 if (png_ptr->row_buf == NULL)
1273 {
1274 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1275 char msg[50];
1277 png_snprintf2(msg, 50,
1278 "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number,
1279 png_ptr->pass);
1280 png_error(png_ptr, msg);
1281 #else
1282 png_error(png_ptr, "NULL row buffer");
1283 #endif
1284 }
1285 #ifdef PNG_WARN_UNINITIALIZED_ROW
1286 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
1287 /* Application has failed to call either png_read_start_image()
1288 * or png_read_update_info() after setting transforms that expand
1289 * pixels. This check added to libpng-1.2.19 */
1290 #if (PNG_WARN_UNINITIALIZED_ROW==1)
1291 png_error(png_ptr, "Uninitialized row");
1292 #else
1293 png_warning(png_ptr, "Uninitialized row");
1294 #endif
1295 #endif
1297 #if defined(PNG_READ_EXPAND_SUPPORTED)
1298 if (png_ptr->transformations & PNG_EXPAND)
1299 {
1300 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1301 {
1302 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1303 png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1304 }
1305 else
1306 {
1307 if (png_ptr->num_trans &&
1308 (png_ptr->transformations & PNG_EXPAND_tRNS))
1309 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1310 &(png_ptr->trans_values));
1311 else
1312 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1313 NULL);
1314 }
1315 }
1316 #endif
1318 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1319 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1320 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1321 PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
1322 #endif
1324 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1325 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1326 {
1327 int rgb_error =
1328 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1329 if (rgb_error)
1330 {
1331 png_ptr->rgb_to_gray_status=1;
1332 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
1333 PNG_RGB_TO_GRAY_WARN)
1334 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1335 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
1336 PNG_RGB_TO_GRAY_ERR)
1337 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1338 }
1339 }
1340 #endif
1342 /*
1343 From Andreas Dilger e-mail to png-implement, 26 March 1998:
1345 In most cases, the "simple transparency" should be done prior to doing
1346 gray-to-RGB, or you will have to test 3x as many bytes to check if a
1347 pixel is transparent. You would also need to make sure that the
1348 transparency information is upgraded to RGB.
1350 To summarize, the current flow is:
1351 - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1352 with background "in place" if transparent,
1353 convert to RGB if necessary
1354 - Gray + alpha -> composite with gray background and remove alpha bytes,
1355 convert to RGB if necessary
1357 To support RGB backgrounds for gray images we need:
1358 - Gray + simple transparency -> convert to RGB + simple transparency, compare
1359 3 or 6 bytes and composite with background
1360 "in place" if transparent (3x compare/pixel
1361 compared to doing composite with gray bkgrnd)
1362 - Gray + alpha -> convert to RGB + alpha, composite with background and
1363 remove alpha bytes (3x float operations/pixel
1364 compared with composite on gray background)
1366 Greg's change will do this. The reason it wasn't done before is for
1367 performance, as this increases the per-pixel operations. If we would check
1368 in advance if the background was gray or RGB, and position the gray-to-RGB
1369 transform appropriately, then it would save a lot of work/time.
1370 */
1372 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1373 /* if gray -> RGB, do so now only if background is non-gray; else do later
1374 * for performance reasons */
1375 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1376 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1377 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1378 #endif
1380 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1381 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1382 ((png_ptr->num_trans != 0 ) ||
1383 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
1384 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1385 &(png_ptr->trans_values), &(png_ptr->background)
1386 #if defined(PNG_READ_GAMMA_SUPPORTED)
1387 , &(png_ptr->background_1),
1388 png_ptr->gamma_table, png_ptr->gamma_from_1,
1389 png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1390 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1391 png_ptr->gamma_shift
1392 #endif
1393 );
1394 #endif
1396 #if defined(PNG_READ_GAMMA_SUPPORTED)
1397 if ((png_ptr->transformations & PNG_GAMMA) &&
1398 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1399 !((png_ptr->transformations & PNG_BACKGROUND) &&
1400 ((png_ptr->num_trans != 0) ||
1401 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1402 #endif
1403 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
1404 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1405 png_ptr->gamma_table, png_ptr->gamma_16_table,
1406 png_ptr->gamma_shift);
1407 #endif
1409 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1410 if (png_ptr->transformations & PNG_16_TO_8)
1411 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
1412 #endif
1414 #if defined(PNG_READ_DITHER_SUPPORTED)
1415 if (png_ptr->transformations & PNG_DITHER)
1416 {
1417 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1418 png_ptr->palette_lookup, png_ptr->dither_index);
1419 if (png_ptr->row_info.rowbytes == (png_uint_32)0)
1420 png_error(png_ptr, "png_do_dither returned rowbytes=0");
1421 }
1422 #endif
1424 #if defined(PNG_READ_INVERT_SUPPORTED)
1425 if (png_ptr->transformations & PNG_INVERT_MONO)
1426 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
1427 #endif
1429 #if defined(PNG_READ_SHIFT_SUPPORTED)
1430 if (png_ptr->transformations & PNG_SHIFT)
1431 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1432 &(png_ptr->shift));
1433 #endif
1435 #if defined(PNG_READ_PACK_SUPPORTED)
1436 if (png_ptr->transformations & PNG_PACK)
1437 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
1438 #endif
1440 #if defined(PNG_READ_BGR_SUPPORTED)
1441 if (png_ptr->transformations & PNG_BGR)
1442 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
1443 #endif
1445 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
1446 if (png_ptr->transformations & PNG_PACKSWAP)
1447 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1448 #endif
1450 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1451 /* if gray -> RGB, do so now only if we did not do so above */
1452 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1453 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1454 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1455 #endif
1457 #if defined(PNG_READ_FILLER_SUPPORTED)
1458 if (png_ptr->transformations & PNG_FILLER)
1459 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1460 (png_uint_32)png_ptr->filler, png_ptr->flags);
1461 #endif
1463 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1464 if (png_ptr->transformations & PNG_INVERT_ALPHA)
1465 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1466 #endif
1468 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1469 if (png_ptr->transformations & PNG_SWAP_ALPHA)
1470 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1471 #endif
1473 #if defined(PNG_READ_SWAP_SUPPORTED)
1474 if (png_ptr->transformations & PNG_SWAP_BYTES)
1475 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1476 #endif
1478 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1479 if (png_ptr->transformations & PNG_USER_TRANSFORM)
1480 {
1481 if (png_ptr->read_user_transform_fn != NULL)
1482 (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1483 (png_ptr, /* png_ptr */
1484 &(png_ptr->row_info), /* row_info: */
1485 /* png_uint_32 width; width of row */
1486 /* png_uint_32 rowbytes; number of bytes in row */
1487 /* png_byte color_type; color type of pixels */
1488 /* png_byte bit_depth; bit depth of samples */
1489 /* png_byte channels; number of channels (1-4) */
1490 /* png_byte pixel_depth; bits per pixel (depth*channels) */
1491 png_ptr->row_buf + 1); /* start of pixel data for row */
1492 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
1493 if (png_ptr->user_transform_depth)
1494 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1495 if (png_ptr->user_transform_channels)
1496 png_ptr->row_info.channels = png_ptr->user_transform_channels;
1497 #endif
1498 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1499 png_ptr->row_info.channels);
1500 png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
1501 png_ptr->row_info.width);
1502 }
1503 #endif
1505 }
1507 #if defined(PNG_READ_PACK_SUPPORTED)
1508 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1509 * without changing the actual values. Thus, if you had a row with
1510 * a bit depth of 1, you would end up with bytes that only contained
1511 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1512 * png_do_shift() after this.
1513 */
1514 void /* PRIVATE */
1515 png_do_unpack(png_row_infop row_info, png_bytep row)
1516 {
1517 png_debug(1, "in png_do_unpack\n");
1518 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1519 if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1520 #else
1521 if (row_info->bit_depth < 8)
1522 #endif
1523 {
1524 png_uint_32 i;
1525 png_uint_32 row_width=row_info->width;
1527 switch (row_info->bit_depth)
1528 {
1529 case 1:
1530 {
1531 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1532 png_bytep dp = row + (png_size_t)row_width - 1;
1533 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
1534 for (i = 0; i < row_width; i++)
1535 {
1536 *dp = (png_byte)((*sp >> shift) & 0x01);
1537 if (shift == 7)
1538 {
1539 shift = 0;
1540 sp--;
1541 }
1542 else
1543 shift++;
1545 dp--;
1546 }
1547 break;
1548 }
1549 case 2:
1550 {
1552 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1553 png_bytep dp = row + (png_size_t)row_width - 1;
1554 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
1555 for (i = 0; i < row_width; i++)
1556 {
1557 *dp = (png_byte)((*sp >> shift) & 0x03);
1558 if (shift == 6)
1559 {
1560 shift = 0;
1561 sp--;
1562 }
1563 else
1564 shift += 2;
1566 dp--;
1567 }
1568 break;
1569 }
1570 case 4:
1571 {
1572 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1573 png_bytep dp = row + (png_size_t)row_width - 1;
1574 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
1575 for (i = 0; i < row_width; i++)
1576 {
1577 *dp = (png_byte)((*sp >> shift) & 0x0f);
1578 if (shift == 4)
1579 {
1580 shift = 0;
1581 sp--;
1582 }
1583 else
1584 shift = 4;
1586 dp--;
1587 }
1588 break;
1589 }
1590 }
1591 row_info->bit_depth = 8;
1592 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1593 row_info->rowbytes = row_width * row_info->channels;
1594 }
1595 }
1596 #endif
1598 #if defined(PNG_READ_SHIFT_SUPPORTED)
1599 /* Reverse the effects of png_do_shift. This routine merely shifts the
1600 * pixels back to their significant bits values. Thus, if you have
1601 * a row of bit depth 8, but only 5 are significant, this will shift
1602 * the values back to 0 through 31.
1603 */
1604 void /* PRIVATE */
1605 png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
1606 {
1607 png_debug(1, "in png_do_unshift\n");
1608 if (
1609 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1610 row != NULL && row_info != NULL && sig_bits != NULL &&
1611 #endif
1612 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
1613 {
1614 int shift[4];
1615 int channels = 0;
1616 int c;
1617 png_uint_16 value = 0;
1618 png_uint_32 row_width = row_info->width;
1620 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1621 {
1622 shift[channels++] = row_info->bit_depth - sig_bits->red;
1623 shift[channels++] = row_info->bit_depth - sig_bits->green;
1624 shift[channels++] = row_info->bit_depth - sig_bits->blue;
1625 }
1626 else
1627 {
1628 shift[channels++] = row_info->bit_depth - sig_bits->gray;
1629 }
1630 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1631 {
1632 shift[channels++] = row_info->bit_depth - sig_bits->alpha;
1633 }
1635 for (c = 0; c < channels; c++)
1636 {
1637 if (shift[c] <= 0)
1638 shift[c] = 0;
1639 else
1640 value = 1;
1641 }
1643 if (!value)
1644 return;
1646 switch (row_info->bit_depth)
1647 {
1648 case 2:
1649 {
1650 png_bytep bp;
1651 png_uint_32 i;
1652 png_uint_32 istop = row_info->rowbytes;
1654 for (bp = row, i = 0; i < istop; i++)
1655 {
1656 *bp >>= 1;
1657 *bp++ &= 0x55;
1658 }
1659 break;
1660 }
1661 case 4:
1662 {
1663 png_bytep bp = row;
1664 png_uint_32 i;
1665 png_uint_32 istop = row_info->rowbytes;
1666 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1667 (png_byte)((int)0xf >> shift[0]));
1669 for (i = 0; i < istop; i++)
1670 {
1671 *bp >>= shift[0];
1672 *bp++ &= mask;
1673 }
1674 break;
1675 }
1676 case 8:
1677 {
1678 png_bytep bp = row;
1679 png_uint_32 i;
1680 png_uint_32 istop = row_width * channels;
1682 for (i = 0; i < istop; i++)
1683 {
1684 *bp++ >>= shift[i%channels];
1685 }
1686 break;
1687 }
1688 case 16:
1689 {
1690 png_bytep bp = row;
1691 png_uint_32 i;
1692 png_uint_32 istop = channels * row_width;
1694 for (i = 0; i < istop; i++)
1695 {
1696 value = (png_uint_16)((*bp << 8) + *(bp + 1));
1697 value >>= shift[i%channels];
1698 *bp++ = (png_byte)(value >> 8);
1699 *bp++ = (png_byte)(value & 0xff);
1700 }
1701 break;
1702 }
1703 }
1704 }
1705 }
1706 #endif
1708 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1709 /* chop rows of bit depth 16 down to 8 */
1710 void /* PRIVATE */
1711 png_do_chop(png_row_infop row_info, png_bytep row)
1712 {
1713 png_debug(1, "in png_do_chop\n");
1714 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1715 if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1716 #else
1717 if (row_info->bit_depth == 16)
1718 #endif
1719 {
1720 png_bytep sp = row;
1721 png_bytep dp = row;
1722 png_uint_32 i;
1723 png_uint_32 istop = row_info->width * row_info->channels;
1725 for (i = 0; i<istop; i++, sp += 2, dp++)
1726 {
1727 #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
1728 /* This does a more accurate scaling of the 16-bit color
1729 * value, rather than a simple low-byte truncation.
1730 *
1731 * What the ideal calculation should be:
1732 * *dp = (((((png_uint_32)(*sp) << 8) |
1733 * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1734 *
1735 * GRR: no, I think this is what it really should be:
1736 * *dp = (((((png_uint_32)(*sp) << 8) |
1737 * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1738 *
1739 * GRR: here's the exact calculation with shifts:
1740 * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1741 * *dp = (temp - (temp >> 8)) >> 8;
1742 *
1743 * Approximate calculation with shift/add instead of multiply/divide:
1744 * *dp = ((((png_uint_32)(*sp) << 8) |
1745 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1746 *
1747 * What we actually do to avoid extra shifting and conversion:
1748 */
1750 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1751 #else
1752 /* Simply discard the low order byte */
1753 *dp = *sp;
1754 #endif
1755 }
1756 row_info->bit_depth = 8;
1757 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1758 row_info->rowbytes = row_info->width * row_info->channels;
1759 }
1760 }
1761 #endif
1763 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1764 void /* PRIVATE */
1765 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1766 {
1767 png_debug(1, "in png_do_read_swap_alpha\n");
1768 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1769 if (row != NULL && row_info != NULL)
1770 #endif
1771 {
1772 png_uint_32 row_width = row_info->width;
1773 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1774 {
1775 /* This converts from RGBA to ARGB */
1776 if (row_info->bit_depth == 8)
1777 {
1778 png_bytep sp = row + row_info->rowbytes;
1779 png_bytep dp = sp;
1780 png_byte save;
1781 png_uint_32 i;
1783 for (i = 0; i < row_width; i++)
1784 {
1785 save = *(--sp);
1786 *(--dp) = *(--sp);
1787 *(--dp) = *(--sp);
1788 *(--dp) = *(--sp);
1789 *(--dp) = save;
1790 }
1791 }
1792 /* This converts from RRGGBBAA to AARRGGBB */
1793 else
1794 {
1795 png_bytep sp = row + row_info->rowbytes;
1796 png_bytep dp = sp;
1797 png_byte save[2];
1798 png_uint_32 i;
1800 for (i = 0; i < row_width; i++)
1801 {
1802 save[0] = *(--sp);
1803 save[1] = *(--sp);
1804 *(--dp) = *(--sp);
1805 *(--dp) = *(--sp);
1806 *(--dp) = *(--sp);
1807 *(--dp) = *(--sp);
1808 *(--dp) = *(--sp);
1809 *(--dp) = *(--sp);
1810 *(--dp) = save[0];
1811 *(--dp) = save[1];
1812 }
1813 }
1814 }
1815 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1816 {
1817 /* This converts from GA to AG */
1818 if (row_info->bit_depth == 8)
1819 {
1820 png_bytep sp = row + row_info->rowbytes;
1821 png_bytep dp = sp;
1822 png_byte save;
1823 png_uint_32 i;
1825 for (i = 0; i < row_width; i++)
1826 {
1827 save = *(--sp);
1828 *(--dp) = *(--sp);
1829 *(--dp) = save;
1830 }
1831 }
1832 /* This converts from GGAA to AAGG */
1833 else
1834 {
1835 png_bytep sp = row + row_info->rowbytes;
1836 png_bytep dp = sp;
1837 png_byte save[2];
1838 png_uint_32 i;
1840 for (i = 0; i < row_width; i++)
1841 {
1842 save[0] = *(--sp);
1843 save[1] = *(--sp);
1844 *(--dp) = *(--sp);
1845 *(--dp) = *(--sp);
1846 *(--dp) = save[0];
1847 *(--dp) = save[1];
1848 }
1849 }
1850 }
1851 }
1852 }
1853 #endif
1855 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1856 void /* PRIVATE */
1857 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1858 {
1859 png_debug(1, "in png_do_read_invert_alpha\n");
1860 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1861 if (row != NULL && row_info != NULL)
1862 #endif
1863 {
1864 png_uint_32 row_width = row_info->width;
1865 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1866 {
1867 /* This inverts the alpha channel in RGBA */
1868 if (row_info->bit_depth == 8)
1869 {
1870 png_bytep sp = row + row_info->rowbytes;
1871 png_bytep dp = sp;
1872 png_uint_32 i;
1874 for (i = 0; i < row_width; i++)
1875 {
1876 *(--dp) = (png_byte)(255 - *(--sp));
1878 /* This does nothing:
1879 *(--dp) = *(--sp);
1880 *(--dp) = *(--sp);
1881 *(--dp) = *(--sp);
1882 We can replace it with:
1883 */
1884 sp-=3;
1885 dp=sp;
1886 }
1887 }
1888 /* This inverts the alpha channel in RRGGBBAA */
1889 else
1890 {
1891 png_bytep sp = row + row_info->rowbytes;
1892 png_bytep dp = sp;
1893 png_uint_32 i;
1895 for (i = 0; i < row_width; i++)
1896 {
1897 *(--dp) = (png_byte)(255 - *(--sp));
1898 *(--dp) = (png_byte)(255 - *(--sp));
1900 /* This does nothing:
1901 *(--dp) = *(--sp);
1902 *(--dp) = *(--sp);
1903 *(--dp) = *(--sp);
1904 *(--dp) = *(--sp);
1905 *(--dp) = *(--sp);
1906 *(--dp) = *(--sp);
1907 We can replace it with:
1908 */
1909 sp-=6;
1910 dp=sp;
1911 }
1912 }
1913 }
1914 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1915 {
1916 /* This inverts the alpha channel in GA */
1917 if (row_info->bit_depth == 8)
1918 {
1919 png_bytep sp = row + row_info->rowbytes;
1920 png_bytep dp = sp;
1921 png_uint_32 i;
1923 for (i = 0; i < row_width; i++)
1924 {
1925 *(--dp) = (png_byte)(255 - *(--sp));
1926 *(--dp) = *(--sp);
1927 }
1928 }
1929 /* This inverts the alpha channel in GGAA */
1930 else
1931 {
1932 png_bytep sp = row + row_info->rowbytes;
1933 png_bytep dp = sp;
1934 png_uint_32 i;
1936 for (i = 0; i < row_width; i++)
1937 {
1938 *(--dp) = (png_byte)(255 - *(--sp));
1939 *(--dp) = (png_byte)(255 - *(--sp));
1940 /*
1941 *(--dp) = *(--sp);
1942 *(--dp) = *(--sp);
1943 */
1944 sp-=2;
1945 dp=sp;
1946 }
1947 }
1948 }
1949 }
1950 }
1951 #endif
1953 #if defined(PNG_READ_FILLER_SUPPORTED)
1954 /* Add filler channel if we have RGB color */
1955 void /* PRIVATE */
1956 png_do_read_filler(png_row_infop row_info, png_bytep row,
1957 png_uint_32 filler, png_uint_32 flags)
1958 {
1959 png_uint_32 i;
1960 png_uint_32 row_width = row_info->width;
1962 png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
1963 png_byte lo_filler = (png_byte)(filler & 0xff);
1965 png_debug(1, "in png_do_read_filler\n");
1966 if (
1967 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1968 row != NULL && row_info != NULL &&
1969 #endif
1970 row_info->color_type == PNG_COLOR_TYPE_GRAY)
1971 {
1972 if (row_info->bit_depth == 8)
1973 {
1974 /* This changes the data from G to GX */
1975 if (flags & PNG_FLAG_FILLER_AFTER)
1976 {
1977 png_bytep sp = row + (png_size_t)row_width;
1978 png_bytep dp = sp + (png_size_t)row_width;
1979 for (i = 1; i < row_width; i++)
1980 {
1981 *(--dp) = lo_filler;
1982 *(--dp) = *(--sp);
1983 }
1984 *(--dp) = lo_filler;
1985 row_info->channels = 2;
1986 row_info->pixel_depth = 16;
1987 row_info->rowbytes = row_width * 2;
1988 }
1989 /* This changes the data from G to XG */
1990 else
1991 {
1992 png_bytep sp = row + (png_size_t)row_width;
1993 png_bytep dp = sp + (png_size_t)row_width;
1994 for (i = 0; i < row_width; i++)
1995 {
1996 *(--dp) = *(--sp);
1997 *(--dp) = lo_filler;
1998 }
1999 row_info->channels = 2;
2000 row_info->pixel_depth = 16;
2001 row_info->rowbytes = row_width * 2;
2002 }
2003 }
2004 else if (row_info->bit_depth == 16)
2005 {
2006 /* This changes the data from GG to GGXX */
2007 if (flags & PNG_FLAG_FILLER_AFTER)
2008 {
2009 png_bytep sp = row + (png_size_t)row_width * 2;
2010 png_bytep dp = sp + (png_size_t)row_width * 2;
2011 for (i = 1; i < row_width; i++)
2012 {
2013 *(--dp) = hi_filler;
2014 *(--dp) = lo_filler;
2015 *(--dp) = *(--sp);
2016 *(--dp) = *(--sp);
2017 }
2018 *(--dp) = hi_filler;
2019 *(--dp) = lo_filler;
2020 row_info->channels = 2;
2021 row_info->pixel_depth = 32;
2022 row_info->rowbytes = row_width * 4;
2023 }
2024 /* This changes the data from GG to XXGG */
2025 else
2026 {
2027 png_bytep sp = row + (png_size_t)row_width * 2;
2028 png_bytep dp = sp + (png_size_t)row_width * 2;
2029 for (i = 0; i < row_width; i++)
2030 {
2031 *(--dp) = *(--sp);
2032 *(--dp) = *(--sp);
2033 *(--dp) = hi_filler;
2034 *(--dp) = lo_filler;
2035 }
2036 row_info->channels = 2;
2037 row_info->pixel_depth = 32;
2038 row_info->rowbytes = row_width * 4;
2039 }
2040 }
2041 } /* COLOR_TYPE == GRAY */
2042 else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2043 {
2044 if (row_info->bit_depth == 8)
2045 {
2046 /* This changes the data from RGB to RGBX */
2047 if (flags & PNG_FLAG_FILLER_AFTER)
2048 {
2049 png_bytep sp = row + (png_size_t)row_width * 3;
2050 png_bytep dp = sp + (png_size_t)row_width;
2051 for (i = 1; i < row_width; i++)
2052 {
2053 *(--dp) = lo_filler;
2054 *(--dp) = *(--sp);
2055 *(--dp) = *(--sp);
2056 *(--dp) = *(--sp);
2057 }
2058 *(--dp) = lo_filler;
2059 row_info->channels = 4;
2060 row_info->pixel_depth = 32;
2061 row_info->rowbytes = row_width * 4;
2062 }
2063 /* This changes the data from RGB to XRGB */
2064 else
2065 {
2066 png_bytep sp = row + (png_size_t)row_width * 3;
2067 png_bytep dp = sp + (png_size_t)row_width;
2068 for (i = 0; i < row_width; i++)
2069 {
2070 *(--dp) = *(--sp);
2071 *(--dp) = *(--sp);
2072 *(--dp) = *(--sp);
2073 *(--dp) = lo_filler;
2074 }
2075 row_info->channels = 4;
2076 row_info->pixel_depth = 32;
2077 row_info->rowbytes = row_width * 4;
2078 }
2079 }
2080 else if (row_info->bit_depth == 16)
2081 {
2082 /* This changes the data from RRGGBB to RRGGBBXX */
2083 if (flags & PNG_FLAG_FILLER_AFTER)
2084 {
2085 png_bytep sp = row + (png_size_t)row_width * 6;
2086 png_bytep dp = sp + (png_size_t)row_width * 2;
2087 for (i = 1; i < row_width; i++)
2088 {
2089 *(--dp) = hi_filler;
2090 *(--dp) = lo_filler;
2091 *(--dp) = *(--sp);
2092 *(--dp) = *(--sp);
2093 *(--dp) = *(--sp);
2094 *(--dp) = *(--sp);
2095 *(--dp) = *(--sp);
2096 *(--dp) = *(--sp);
2097 }
2098 *(--dp) = hi_filler;
2099 *(--dp) = lo_filler;
2100 row_info->channels = 4;
2101 row_info->pixel_depth = 64;
2102 row_info->rowbytes = row_width * 8;
2103 }
2104 /* This changes the data from RRGGBB to XXRRGGBB */
2105 else
2106 {
2107 png_bytep sp = row + (png_size_t)row_width * 6;
2108 png_bytep dp = sp + (png_size_t)row_width * 2;
2109 for (i = 0; i < row_width; i++)
2110 {
2111 *(--dp) = *(--sp);
2112 *(--dp) = *(--sp);
2113 *(--dp) = *(--sp);
2114 *(--dp) = *(--sp);
2115 *(--dp) = *(--sp);
2116 *(--dp) = *(--sp);
2117 *(--dp) = hi_filler;
2118 *(--dp) = lo_filler;
2119 }
2120 row_info->channels = 4;
2121 row_info->pixel_depth = 64;
2122 row_info->rowbytes = row_width * 8;
2123 }
2124 }
2125 } /* COLOR_TYPE == RGB */
2126 }
2127 #endif
2129 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2130 /* expand grayscale files to RGB, with or without alpha */
2131 void /* PRIVATE */
2132 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
2133 {
2134 png_uint_32 i;
2135 png_uint_32 row_width = row_info->width;
2137 png_debug(1, "in png_do_gray_to_rgb\n");
2138 if (row_info->bit_depth >= 8 &&
2139 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2140 row != NULL && row_info != NULL &&
2141 #endif
2142 !(row_info->color_type & PNG_COLOR_MASK_COLOR))
2143 {
2144 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2145 {
2146 if (row_info->bit_depth == 8)
2147 {
2148 png_bytep sp = row + (png_size_t)row_width - 1;
2149 png_bytep dp = sp + (png_size_t)row_width * 2;
2150 for (i = 0; i < row_width; i++)
2151 {
2152 *(dp--) = *sp;
2153 *(dp--) = *sp;
2154 *(dp--) = *(sp--);
2155 }
2156 }
2157 else
2158 {
2159 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2160 png_bytep dp = sp + (png_size_t)row_width * 4;
2161 for (i = 0; i < row_width; i++)
2162 {
2163 *(dp--) = *sp;
2164 *(dp--) = *(sp - 1);
2165 *(dp--) = *sp;
2166 *(dp--) = *(sp - 1);
2167 *(dp--) = *(sp--);
2168 *(dp--) = *(sp--);
2169 }
2170 }
2171 }
2172 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2173 {
2174 if (row_info->bit_depth == 8)
2175 {
2176 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2177 png_bytep dp = sp + (png_size_t)row_width * 2;
2178 for (i = 0; i < row_width; i++)
2179 {
2180 *(dp--) = *(sp--);
2181 *(dp--) = *sp;
2182 *(dp--) = *sp;
2183 *(dp--) = *(sp--);
2184 }
2185 }
2186 else
2187 {
2188 png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2189 png_bytep dp = sp + (png_size_t)row_width * 4;
2190 for (i = 0; i < row_width; i++)
2191 {
2192 *(dp--) = *(sp--);
2193 *(dp--) = *(sp--);
2194 *(dp--) = *sp;
2195 *(dp--) = *(sp - 1);
2196 *(dp--) = *sp;
2197 *(dp--) = *(sp - 1);
2198 *(dp--) = *(sp--);
2199 *(dp--) = *(sp--);
2200 }
2201 }
2202 }
2203 row_info->channels += (png_byte)2;
2204 row_info->color_type |= PNG_COLOR_MASK_COLOR;
2205 row_info->pixel_depth = (png_byte)(row_info->channels *
2206 row_info->bit_depth);
2207 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2208 }
2209 }
2210 #endif
2212 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
2213 /* reduce RGB files to grayscale, with or without alpha
2214 * using the equation given in Poynton's ColorFAQ at
2215 * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008)
2216 * New link:
2217 * <http://www.poynton.com/notes/colour_and_gamma/>
2218 * Charles Poynton poynton at poynton.com
2219 *
2220 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2221 *
2222 * We approximate this with
2223 *
2224 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
2225 *
2226 * which can be expressed with integers as
2227 *
2228 * Y = (6969 * R + 23434 * G + 2365 * B)/32768
2229 *
2230 * The calculation is to be done in a linear colorspace.
2231 *
2232 * Other integer coefficents can be used via png_set_rgb_to_gray().
2233 */
2234 int /* PRIVATE */
2235 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2237 {
2238 png_uint_32 i;
2240 png_uint_32 row_width = row_info->width;
2241 int rgb_error = 0;
2243 png_debug(1, "in png_do_rgb_to_gray\n");
2244 if (
2245 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2246 row != NULL && row_info != NULL &&
2247 #endif
2248 (row_info->color_type & PNG_COLOR_MASK_COLOR))
2249 {
2250 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2251 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2252 png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
2254 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2255 {
2256 if (row_info->bit_depth == 8)
2257 {
2258 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2259 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2260 {
2261 png_bytep sp = row;
2262 png_bytep dp = row;
2264 for (i = 0; i < row_width; i++)
2265 {
2266 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2267 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2268 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2269 if (red != green || red != blue)
2270 {
2271 rgb_error |= 1;
2272 *(dp++) = png_ptr->gamma_from_1[
2273 (rc*red + gc*green + bc*blue)>>15];
2274 }
2275 else
2276 *(dp++) = *(sp - 1);
2277 }
2278 }
2279 else
2280 #endif
2281 {
2282 png_bytep sp = row;
2283 png_bytep dp = row;
2284 for (i = 0; i < row_width; i++)
2285 {
2286 png_byte red = *(sp++);
2287 png_byte green = *(sp++);
2288 png_byte blue = *(sp++);
2289 if (red != green || red != blue)
2290 {
2291 rgb_error |= 1;
2292 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
2293 }
2294 else
2295 *(dp++) = *(sp - 1);
2296 }
2297 }
2298 }
2300 else /* RGB bit_depth == 16 */
2301 {
2302 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2303 if (png_ptr->gamma_16_to_1 != NULL &&
2304 png_ptr->gamma_16_from_1 != NULL)
2305 {
2306 png_bytep sp = row;
2307 png_bytep dp = row;
2308 for (i = 0; i < row_width; i++)
2309 {
2310 png_uint_16 red, green, blue, w;
2312 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2313 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2314 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2316 if (red == green && red == blue)
2317 w = red;
2318 else
2319 {
2320 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2321 png_ptr->gamma_shift][red>>8];
2322 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2323 png_ptr->gamma_shift][green>>8];
2324 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2325 png_ptr->gamma_shift][blue>>8];
2326 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
2327 + bc*blue_1)>>15);
2328 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2329 png_ptr->gamma_shift][gray16 >> 8];
2330 rgb_error |= 1;
2331 }
2333 *(dp++) = (png_byte)((w>>8) & 0xff);
2334 *(dp++) = (png_byte)(w & 0xff);
2335 }
2336 }
2337 else
2338 #endif
2339 {
2340 png_bytep sp = row;
2341 png_bytep dp = row;
2342 for (i = 0; i < row_width; i++)
2343 {
2344 png_uint_16 red, green, blue, gray16;
2346 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2347 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2348 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2350 if (red != green || red != blue)
2351 rgb_error |= 1;
2352 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2353 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2354 *(dp++) = (png_byte)(gray16 & 0xff);
2355 }
2356 }
2357 }
2358 }
2359 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2360 {
2361 if (row_info->bit_depth == 8)
2362 {
2363 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2364 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2365 {
2366 png_bytep sp = row;
2367 png_bytep dp = row;
2368 for (i = 0; i < row_width; i++)
2369 {
2370 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2371 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2372 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2373 if (red != green || red != blue)
2374 rgb_error |= 1;
2375 *(dp++) = png_ptr->gamma_from_1
2376 [(rc*red + gc*green + bc*blue)>>15];
2377 *(dp++) = *(sp++); /* alpha */
2378 }
2379 }
2380 else
2381 #endif
2382 {
2383 png_bytep sp = row;
2384 png_bytep dp = row;
2385 for (i = 0; i < row_width; i++)
2386 {
2387 png_byte red = *(sp++);
2388 png_byte green = *(sp++);
2389 png_byte blue = *(sp++);
2390 if (red != green || red != blue)
2391 rgb_error |= 1;
2392 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
2393 *(dp++) = *(sp++); /* alpha */
2394 }
2395 }
2396 }
2397 else /* RGBA bit_depth == 16 */
2398 {
2399 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2400 if (png_ptr->gamma_16_to_1 != NULL &&
2401 png_ptr->gamma_16_from_1 != NULL)
2402 {
2403 png_bytep sp = row;
2404 png_bytep dp = row;
2405 for (i = 0; i < row_width; i++)
2406 {
2407 png_uint_16 red, green, blue, w;
2409 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2410 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2411 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2413 if (red == green && red == blue)
2414 w = red;
2415 else
2416 {
2417 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2418 png_ptr->gamma_shift][red>>8];
2419 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2420 png_ptr->gamma_shift][green>>8];
2421 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2422 png_ptr->gamma_shift][blue>>8];
2423 png_uint_16 gray16 = (png_uint_16)((rc * red_1
2424 + gc * green_1 + bc * blue_1)>>15);
2425 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2426 png_ptr->gamma_shift][gray16 >> 8];
2427 rgb_error |= 1;
2428 }
2430 *(dp++) = (png_byte)((w>>8) & 0xff);
2431 *(dp++) = (png_byte)(w & 0xff);
2432 *(dp++) = *(sp++); /* alpha */
2433 *(dp++) = *(sp++);
2434 }
2435 }
2436 else
2437 #endif
2438 {
2439 png_bytep sp = row;
2440 png_bytep dp = row;
2441 for (i = 0; i < row_width; i++)
2442 {
2443 png_uint_16 red, green, blue, gray16;
2444 red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2445 green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2446 blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2447 if (red != green || red != blue)
2448 rgb_error |= 1;
2449 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2450 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2451 *(dp++) = (png_byte)(gray16 & 0xff);
2452 *(dp++) = *(sp++); /* alpha */
2453 *(dp++) = *(sp++);
2454 }
2455 }
2456 }
2457 }
2458 row_info->channels -= (png_byte)2;
2459 row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2460 row_info->pixel_depth = (png_byte)(row_info->channels *
2461 row_info->bit_depth);
2462 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
2463 }
2464 return rgb_error;
2465 }
2466 #endif
2468 /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
2469 * large of png_color. This lets grayscale images be treated as
2470 * paletted. Most useful for gamma correction and simplification
2471 * of code.
2472 */
2473 void PNGAPI
2474 png_build_grayscale_palette(int bit_depth, png_colorp palette)
2475 {
2476 int num_palette;
2477 int color_inc;
2478 int i;
2479 int v;
2481 png_debug(1, "in png_do_build_grayscale_palette\n");
2482 if (palette == NULL)
2483 return;
2485 switch (bit_depth)
2486 {
2487 case 1:
2488 num_palette = 2;
2489 color_inc = 0xff;
2490 break;
2491 case 2:
2492 num_palette = 4;
2493 color_inc = 0x55;
2494 break;
2495 case 4:
2496 num_palette = 16;
2497 color_inc = 0x11;
2498 break;
2499 case 8:
2500 num_palette = 256;
2501 color_inc = 1;
2502 break;
2503 default:
2504 num_palette = 0;
2505 color_inc = 0;
2506 break;
2507 }
2509 for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2510 {
2511 palette[i].red = (png_byte)v;
2512 palette[i].green = (png_byte)v;
2513 palette[i].blue = (png_byte)v;
2514 }
2515 }
2517 /* This function is currently unused. Do we really need it? */
2518 #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
2519 void /* PRIVATE */
2520 png_correct_palette(png_structp png_ptr, png_colorp palette,
2521 int num_palette)
2522 {
2523 png_debug(1, "in png_correct_palette\n");
2524 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2525 defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
2526 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
2527 {
2528 png_color back, back_1;
2530 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
2531 {
2532 back.red = png_ptr->gamma_table[png_ptr->background.red];
2533 back.green = png_ptr->gamma_table[png_ptr->background.green];
2534 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
2536 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
2537 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
2538 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
2539 }
2540 else
2541 {
2542 double g;
2544 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
2546 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2547 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
2548 {
2549 back.red = png_ptr->background.red;
2550 back.green = png_ptr->background.green;
2551 back.blue = png_ptr->background.blue;
2552 }
2553 else
2554 {
2555 back.red =
2556 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2557 255.0 + 0.5);
2558 back.green =
2559 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2560 255.0 + 0.5);
2561 back.blue =
2562 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2563 255.0 + 0.5);
2564 }
2566 g = 1.0 / png_ptr->background_gamma;
2568 back_1.red =
2569 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2570 255.0 + 0.5);
2571 back_1.green =
2572 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2573 255.0 + 0.5);
2574 back_1.blue =
2575 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2576 255.0 + 0.5);
2577 }
2579 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2580 {
2581 png_uint_32 i;
2583 for (i = 0; i < (png_uint_32)num_palette; i++)
2584 {
2585 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
2586 {
2587 palette[i] = back;
2588 }
2589 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
2590 {
2591 png_byte v, w;
2593 v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
2594 png_composite(w, v, png_ptr->trans[i], back_1.red);
2595 palette[i].red = png_ptr->gamma_from_1[w];
2597 v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
2598 png_composite(w, v, png_ptr->trans[i], back_1.green);
2599 palette[i].green = png_ptr->gamma_from_1[w];
2601 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
2602 png_composite(w, v, png_ptr->trans[i], back_1.blue);
2603 palette[i].blue = png_ptr->gamma_from_1[w];
2604 }
2605 else
2606 {
2607 palette[i].red = png_ptr->gamma_table[palette[i].red];
2608 palette[i].green = png_ptr->gamma_table[palette[i].green];
2609 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2610 }
2611 }
2612 }
2613 else
2614 {
2615 int i;
2617 for (i = 0; i < num_palette; i++)
2618 {
2619 if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
2620 {
2621 palette[i] = back;
2622 }
2623 else
2624 {
2625 palette[i].red = png_ptr->gamma_table[palette[i].red];
2626 palette[i].green = png_ptr->gamma_table[palette[i].green];
2627 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2628 }
2629 }
2630 }
2631 }
2632 else
2633 #endif
2634 #if defined(PNG_READ_GAMMA_SUPPORTED)
2635 if (png_ptr->transformations & PNG_GAMMA)
2636 {
2637 int i;
2639 for (i = 0; i < num_palette; i++)
2640 {
2641 palette[i].red = png_ptr->gamma_table[palette[i].red];
2642 palette[i].green = png_ptr->gamma_table[palette[i].green];
2643 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2644 }
2645 }
2646 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2647 else
2648 #endif
2649 #endif
2650 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2651 if (png_ptr->transformations & PNG_BACKGROUND)
2652 {
2653 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2654 {
2655 png_color back;
2657 back.red = (png_byte)png_ptr->background.red;
2658 back.green = (png_byte)png_ptr->background.green;
2659 back.blue = (png_byte)png_ptr->background.blue;
2661 for (i = 0; i < (int)png_ptr->num_trans; i++)
2662 {
2663 if (png_ptr->trans[i] == 0)
2664 {
2665 palette[i].red = back.red;
2666 palette[i].green = back.green;
2667 palette[i].blue = back.blue;
2668 }
2669 else if (png_ptr->trans[i] != 0xff)
2670 {
2671 png_composite(palette[i].red, png_ptr->palette[i].red,
2672 png_ptr->trans[i], back.red);
2673 png_composite(palette[i].green, png_ptr->palette[i].green,
2674 png_ptr->trans[i], back.green);
2675 png_composite(palette[i].blue, png_ptr->palette[i].blue,
2676 png_ptr->trans[i], back.blue);
2677 }
2678 }
2679 }
2680 else /* assume grayscale palette (what else could it be?) */
2681 {
2682 int i;
2684 for (i = 0; i < num_palette; i++)
2685 {
2686 if (i == (png_byte)png_ptr->trans_values.gray)
2687 {
2688 palette[i].red = (png_byte)png_ptr->background.red;
2689 palette[i].green = (png_byte)png_ptr->background.green;
2690 palette[i].blue = (png_byte)png_ptr->background.blue;
2691 }
2692 }
2693 }
2694 }
2695 #endif
2696 }
2697 #endif
2699 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2700 /* Replace any alpha or transparency with the supplied background color.
2701 * "background" is already in the screen gamma, while "background_1" is
2702 * at a gamma of 1.0. Paletted files have already been taken care of.
2703 */
2704 void /* PRIVATE */
2705 png_do_background(png_row_infop row_info, png_bytep row,
2706 png_color_16p trans_values, png_color_16p background
2707 #if defined(PNG_READ_GAMMA_SUPPORTED)
2708 , png_color_16p background_1,
2709 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
2710 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2711 png_uint_16pp gamma_16_to_1, int gamma_shift
2712 #endif
2713 )
2714 {
2715 png_bytep sp, dp;
2716 png_uint_32 i;
2717 png_uint_32 row_width=row_info->width;
2718 int shift;
2720 png_debug(1, "in png_do_background\n");
2721 if (background != NULL &&
2722 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2723 row != NULL && row_info != NULL &&
2724 #endif
2725 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
2726 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
2727 {
2728 switch (row_info->color_type)
2729 {
2730 case PNG_COLOR_TYPE_GRAY:
2731 {
2732 switch (row_info->bit_depth)
2733 {
2734 case 1:
2735 {
2736 sp = row;
2737 shift = 7;
2738 for (i = 0; i < row_width; i++)
2739 {
2740 if ((png_uint_16)((*sp >> shift) & 0x01)
2741 == trans_values->gray)
2742 {
2743 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2744 *sp |= (png_byte)(background->gray << shift);
2745 }
2746 if (!shift)
2747 {
2748 shift = 7;
2749 sp++;
2750 }
2751 else
2752 shift--;
2753 }
2754 break;
2755 }
2756 case 2:
2757 {
2758 #if defined(PNG_READ_GAMMA_SUPPORTED)
2759 if (gamma_table != NULL)
2760 {
2761 sp = row;
2762 shift = 6;
2763 for (i = 0; i < row_width; i++)
2764 {
2765 if ((png_uint_16)((*sp >> shift) & 0x03)
2766 == trans_values->gray)
2767 {
2768 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2769 *sp |= (png_byte)(background->gray << shift);
2770 }
2771 else
2772 {
2773 png_byte p = (png_byte)((*sp >> shift) & 0x03);
2774 png_byte g = (png_byte)((gamma_table [p | (p << 2) |
2775 (p << 4) | (p << 6)] >> 6) & 0x03);
2776 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2777 *sp |= (png_byte)(g << shift);
2778 }
2779 if (!shift)
2780 {
2781 shift = 6;
2782 sp++;
2783 }
2784 else
2785 shift -= 2;
2786 }
2787 }
2788 else
2789 #endif
2790 {
2791 sp = row;
2792 shift = 6;
2793 for (i = 0; i < row_width; i++)
2794 {
2795 if ((png_uint_16)((*sp >> shift) & 0x03)
2796 == trans_values->gray)
2797 {
2798 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2799 *sp |= (png_byte)(background->gray << shift);
2800 }
2801 if (!shift)
2802 {
2803 shift = 6;
2804 sp++;
2805 }
2806 else
2807 shift -= 2;
2808 }
2809 }
2810 break;
2811 }
2812 case 4:
2813 {
2814 #if defined(PNG_READ_GAMMA_SUPPORTED)
2815 if (gamma_table != NULL)
2816 {
2817 sp = row;
2818 shift = 4;
2819 for (i = 0; i < row_width; i++)
2820 {
2821 if ((png_uint_16)((*sp >> shift) & 0x0f)
2822 == trans_values->gray)
2823 {
2824 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2825 *sp |= (png_byte)(background->gray << shift);
2826 }
2827 else
2828 {
2829 png_byte p = (png_byte)((*sp >> shift) & 0x0f);
2830 png_byte g = (png_byte)((gamma_table[p |
2831 (p << 4)] >> 4) & 0x0f);
2832 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2833 *sp |= (png_byte)(g << shift);
2834 }
2835 if (!shift)
2836 {
2837 shift = 4;
2838 sp++;
2839 }
2840 else
2841 shift -= 4;
2842 }
2843 }
2844 else
2845 #endif
2846 {
2847 sp = row;
2848 shift = 4;
2849 for (i = 0; i < row_width; i++)
2850 {
2851 if ((png_uint_16)((*sp >> shift) & 0x0f)
2852 == trans_values->gray)
2853 {
2854 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2855 *sp |= (png_byte)(background->gray << shift);
2856 }
2857 if (!shift)
2858 {
2859 shift = 4;
2860 sp++;
2861 }
2862 else
2863 shift -= 4;
2864 }
2865 }
2866 break;
2867 }
2868 case 8:
2869 {
2870 #if defined(PNG_READ_GAMMA_SUPPORTED)
2871 if (gamma_table != NULL)
2872 {
2873 sp = row;
2874 for (i = 0; i < row_width; i++, sp++)
2875 {
2876 if (*sp == trans_values->gray)
2877 {
2878 *sp = (png_byte)background->gray;
2879 }
2880 else
2881 {
2882 *sp = gamma_table[*sp];
2883 }
2884 }
2885 }
2886 else
2887 #endif
2888 {
2889 sp = row;
2890 for (i = 0; i < row_width; i++, sp++)
2891 {
2892 if (*sp == trans_values->gray)
2893 {
2894 *sp = (png_byte)background->gray;
2895 }
2896 }
2897 }
2898 break;
2899 }
2900 case 16:
2901 {
2902 #if defined(PNG_READ_GAMMA_SUPPORTED)
2903 if (gamma_16 != NULL)
2904 {
2905 sp = row;
2906 for (i = 0; i < row_width; i++, sp += 2)
2907 {
2908 png_uint_16 v;
2910 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2911 if (v == trans_values->gray)
2912 {
2913 /* background is already in screen gamma */
2914 *sp = (png_byte)((background->gray >> 8) & 0xff);
2915 *(sp + 1) = (png_byte)(background->gray & 0xff);
2916 }
2917 else
2918 {
2919 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2920 *sp = (png_byte)((v >> 8) & 0xff);
2921 *(sp + 1) = (png_byte)(v & 0xff);
2922 }
2923 }
2924 }
2925 else
2926 #endif
2927 {
2928 sp = row;
2929 for (i = 0; i < row_width; i++, sp += 2)
2930 {
2931 png_uint_16 v;
2933 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2934 if (v == trans_values->gray)
2935 {
2936 *sp = (png_byte)((background->gray >> 8) & 0xff);
2937 *(sp + 1) = (png_byte)(background->gray & 0xff);
2938 }
2939 }
2940 }
2941 break;
2942 }
2943 }
2944 break;
2945 }
2946 case PNG_COLOR_TYPE_RGB:
2947 {
2948 if (row_info->bit_depth == 8)
2949 {
2950 #if defined(PNG_READ_GAMMA_SUPPORTED)
2951 if (gamma_table != NULL)
2952 {
2953 sp = row;
2954 for (i = 0; i < row_width; i++, sp += 3)
2955 {
2956 if (*sp == trans_values->red &&
2957 *(sp + 1) == trans_values->green &&
2958 *(sp + 2) == trans_values->blue)
2959 {
2960 *sp = (png_byte)background->red;
2961 *(sp + 1) = (png_byte)background->green;
2962 *(sp + 2) = (png_byte)background->blue;
2963 }
2964 else
2965 {
2966 *sp = gamma_table[*sp];
2967 *(sp + 1) = gamma_table[*(sp + 1)];
2968 *(sp + 2) = gamma_table[*(sp + 2)];
2969 }
2970 }
2971 }
2972 else
2973 #endif
2974 {
2975 sp = row;
2976 for (i = 0; i < row_width; i++, sp += 3)
2977 {
2978 if (*sp == trans_values->red &&
2979 *(sp + 1) == trans_values->green &&
2980 *(sp + 2) == trans_values->blue)
2981 {
2982 *sp = (png_byte)background->red;
2983 *(sp + 1) = (png_byte)background->green;
2984 *(sp + 2) = (png_byte)background->blue;
2985 }
2986 }
2987 }
2988 }
2989 else /* if (row_info->bit_depth == 16) */
2990 {
2991 #if defined(PNG_READ_GAMMA_SUPPORTED)
2992 if (gamma_16 != NULL)
2993 {
2994 sp = row;
2995 for (i = 0; i < row_width; i++, sp += 6)
2996 {
2997 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2998 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2999 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
3000 if (r == trans_values->red && g == trans_values->green &&
3001 b == trans_values->blue)
3002 {
3003 /* background is already in screen gamma */
3004 *sp = (png_byte)((background->red >> 8) & 0xff);
3005 *(sp + 1) = (png_byte)(background->red & 0xff);
3006 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
3007 *(sp + 3) = (png_byte)(background->green & 0xff);
3008 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3009 *(sp + 5) = (png_byte)(background->blue & 0xff);
3010 }
3011 else
3012 {
3013 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3014 *sp = (png_byte)((v >> 8) & 0xff);
3015 *(sp + 1) = (png_byte)(v & 0xff);
3016 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3017 *(sp + 2) = (png_byte)((v >> 8) & 0xff);
3018 *(sp + 3) = (png_byte)(v & 0xff);
3019 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3020 *(sp + 4) = (png_byte)((v >> 8) & 0xff);
3021 *(sp + 5) = (png_byte)(v & 0xff);
3022 }
3023 }
3024 }
3025 else
3026 #endif
3027 {
3028 sp = row;
3029 for (i = 0; i < row_width; i++, sp += 6)
3030 {
3031 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
3032 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3033 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
3035 if (r == trans_values->red && g == trans_values->green &&
3036 b == trans_values->blue)
3037 {
3038 *sp = (png_byte)((background->red >> 8) & 0xff);
3039 *(sp + 1) = (png_byte)(background->red & 0xff);
3040 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
3041 *(sp + 3) = (png_byte)(background->green & 0xff);
3042 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3043 *(sp + 5) = (png_byte)(background->blue & 0xff);
3044 }
3045 }
3046 }
3047 }
3048 break;
3049 }
3050 case PNG_COLOR_TYPE_GRAY_ALPHA:
3051 {
3052 if (row_info->bit_depth == 8)
3053 {
3054 #if defined(PNG_READ_GAMMA_SUPPORTED)
3055 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3056 gamma_table != NULL)
3057 {
3058 sp = row;
3059 dp = row;
3060 for (i = 0; i < row_width; i++, sp += 2, dp++)
3061 {
3062 png_uint_16 a = *(sp + 1);
3064 if (a == 0xff)
3065 {
3066 *dp = gamma_table[*sp];
3067 }
3068 else if (a == 0)
3069 {
3070 /* background is already in screen gamma */
3071 *dp = (png_byte)background->gray;
3072 }
3073 else
3074 {
3075 png_byte v, w;
3077 v = gamma_to_1[*sp];
3078 png_composite(w, v, a, background_1->gray);
3079 *dp = gamma_from_1[w];
3080 }
3081 }
3082 }
3083 else
3084 #endif
3085 {
3086 sp = row;
3087 dp = row;
3088 for (i = 0; i < row_width; i++, sp += 2, dp++)
3089 {
3090 png_byte a = *(sp + 1);
3092 if (a == 0xff)
3093 {
3094 *dp = *sp;
3095 }
3096 #if defined(PNG_READ_GAMMA_SUPPORTED)
3097 else if (a == 0)
3098 {
3099 *dp = (png_byte)background->gray;
3100 }
3101 else
3102 {
3103 png_composite(*dp, *sp, a, background_1->gray);
3104 }
3105 #else
3106 *dp = (png_byte)background->gray;
3107 #endif
3108 }
3109 }
3110 }
3111 else /* if (png_ptr->bit_depth == 16) */
3112 {
3113 #if defined(PNG_READ_GAMMA_SUPPORTED)
3114 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3115 gamma_16_to_1 != NULL)
3116 {
3117 sp = row;
3118 dp = row;
3119 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3120 {
3121 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3123 if (a == (png_uint_16)0xffff)
3124 {
3125 png_uint_16 v;
3127 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3128 *dp = (png_byte)((v >> 8) & 0xff);
3129 *(dp + 1) = (png_byte)(v & 0xff);
3130 }
3131 #if defined(PNG_READ_GAMMA_SUPPORTED)
3132 else if (a == 0)
3133 #else
3134 else
3135 #endif
3136 {
3137 /* background is already in screen gamma */
3138 *dp = (png_byte)((background->gray >> 8) & 0xff);
3139 *(dp + 1) = (png_byte)(background->gray & 0xff);
3140 }
3141 #if defined(PNG_READ_GAMMA_SUPPORTED)
3142 else
3143 {
3144 png_uint_16 g, v, w;
3146 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3147 png_composite_16(v, g, a, background_1->gray);
3148 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3149 *dp = (png_byte)((w >> 8) & 0xff);
3150 *(dp + 1) = (png_byte)(w & 0xff);
3151 }
3152 #endif
3153 }
3154 }
3155 else
3156 #endif
3157 {
3158 sp = row;
3159 dp = row;
3160 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3161 {
3162 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3163 if (a == (png_uint_16)0xffff)
3164 {
3165 png_memcpy(dp, sp, 2);
3166 }
3167 #if defined(PNG_READ_GAMMA_SUPPORTED)
3168 else if (a == 0)
3169 #else
3170 else
3171 #endif
3172 {
3173 *dp = (png_byte)((background->gray >> 8) & 0xff);
3174 *(dp + 1) = (png_byte)(background->gray & 0xff);
3175 }
3176 #if defined(PNG_READ_GAMMA_SUPPORTED)
3177 else
3178 {
3179 png_uint_16 g, v;
3181 g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3182 png_composite_16(v, g, a, background_1->gray);
3183 *dp = (png_byte)((v >> 8) & 0xff);
3184 *(dp + 1) = (png_byte)(v & 0xff);
3185 }
3186 #endif
3187 }
3188 }
3189 }
3190 break;
3191 }
3192 case PNG_COLOR_TYPE_RGB_ALPHA:
3193 {
3194 if (row_info->bit_depth == 8)
3195 {
3196 #if defined(PNG_READ_GAMMA_SUPPORTED)
3197 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3198 gamma_table != NULL)
3199 {
3200 sp = row;
3201 dp = row;
3202 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3203 {
3204 png_byte a = *(sp + 3);
3206 if (a == 0xff)
3207 {
3208 *dp = gamma_table[*sp];
3209 *(dp + 1) = gamma_table[*(sp + 1)];
3210 *(dp + 2) = gamma_table[*(sp + 2)];
3211 }
3212 else if (a == 0)
3213 {
3214 /* background is already in screen gamma */
3215 *dp = (png_byte)background->red;
3216 *(dp + 1) = (png_byte)background->green;
3217 *(dp + 2) = (png_byte)background->blue;
3218 }
3219 else
3220 {
3221 png_byte v, w;
3223 v = gamma_to_1[*sp];
3224 png_composite(w, v, a, background_1->red);
3225 *dp = gamma_from_1[w];
3226 v = gamma_to_1[*(sp + 1)];
3227 png_composite(w, v, a, background_1->green);
3228 *(dp + 1) = gamma_from_1[w];
3229 v = gamma_to_1[*(sp + 2)];
3230 png_composite(w, v, a, background_1->blue);
3231 *(dp + 2) = gamma_from_1[w];
3232 }
3233 }
3234 }
3235 else
3236 #endif
3237 {
3238 sp = row;
3239 dp = row;
3240 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3241 {
3242 png_byte a = *(sp + 3);
3244 if (a == 0xff)
3245 {
3246 *dp = *sp;
3247 *(dp + 1) = *(sp + 1);
3248 *(dp + 2) = *(sp + 2);
3249 }
3250 else if (a == 0)
3251 {
3252 *dp = (png_byte)background->red;
3253 *(dp + 1) = (png_byte)background->green;
3254 *(dp + 2) = (png_byte)background->blue;
3255 }
3256 else
3257 {
3258 png_composite(*dp, *sp, a, background->red);
3259 png_composite(*(dp + 1), *(sp + 1), a,
3260 background->green);
3261 png_composite(*(dp + 2), *(sp + 2), a,
3262 background->blue);
3263 }
3264 }
3265 }
3266 }
3267 else /* if (row_info->bit_depth == 16) */
3268 {
3269 #if defined(PNG_READ_GAMMA_SUPPORTED)
3270 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3271 gamma_16_to_1 != NULL)
3272 {
3273 sp = row;
3274 dp = row;
3275 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3276 {
3277 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3278 << 8) + (png_uint_16)(*(sp + 7)));
3279 if (a == (png_uint_16)0xffff)
3280 {
3281 png_uint_16 v;
3283 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3284 *dp = (png_byte)((v >> 8) & 0xff);
3285 *(dp + 1) = (png_byte)(v & 0xff);
3286 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3287 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3288 *(dp + 3) = (png_byte)(v & 0xff);
3289 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3290 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3291 *(dp + 5) = (png_byte)(v & 0xff);
3292 }
3293 else if (a == 0)
3294 {
3295 /* background is already in screen gamma */
3296 *dp = (png_byte)((background->red >> 8) & 0xff);
3297 *(dp + 1) = (png_byte)(background->red & 0xff);
3298 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3299 *(dp + 3) = (png_byte)(background->green & 0xff);
3300 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3301 *(dp + 5) = (png_byte)(background->blue & 0xff);
3302 }
3303 else
3304 {
3305 png_uint_16 v, w, x;
3307 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3308 png_composite_16(w, v, a, background_1->red);
3309 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3310 *dp = (png_byte)((x >> 8) & 0xff);
3311 *(dp + 1) = (png_byte)(x & 0xff);
3312 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3313 png_composite_16(w, v, a, background_1->green);
3314 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3315 *(dp + 2) = (png_byte)((x >> 8) & 0xff);
3316 *(dp + 3) = (png_byte)(x & 0xff);
3317 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3318 png_composite_16(w, v, a, background_1->blue);
3319 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3320 *(dp + 4) = (png_byte)((x >> 8) & 0xff);
3321 *(dp + 5) = (png_byte)(x & 0xff);
3322 }
3323 }
3324 }
3325 else
3326 #endif
3327 {
3328 sp = row;
3329 dp = row;
3330 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3331 {
3332 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3333 << 8) + (png_uint_16)(*(sp + 7)));
3334 if (a == (png_uint_16)0xffff)
3335 {
3336 png_memcpy(dp, sp, 6);
3337 }
3338 else if (a == 0)
3339 {
3340 *dp = (png_byte)((background->red >> 8) & 0xff);
3341 *(dp + 1) = (png_byte)(background->red & 0xff);
3342 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3343 *(dp + 3) = (png_byte)(background->green & 0xff);
3344 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3345 *(dp + 5) = (png_byte)(background->blue & 0xff);
3346 }
3347 else
3348 {
3349 png_uint_16 v;
3351 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3352 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3353 + *(sp + 3));
3354 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3355 + *(sp + 5));
3357 png_composite_16(v, r, a, background->red);
3358 *dp = (png_byte)((v >> 8) & 0xff);
3359 *(dp + 1) = (png_byte)(v & 0xff);
3360 png_composite_16(v, g, a, background->green);
3361 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3362 *(dp + 3) = (png_byte)(v & 0xff);
3363 png_composite_16(v, b, a, background->blue);
3364 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3365 *(dp + 5) = (png_byte)(v & 0xff);
3366 }
3367 }
3368 }
3369 }
3370 break;
3371 }
3372 }
3374 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3375 {
3376 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
3377 row_info->channels--;
3378 row_info->pixel_depth = (png_byte)(row_info->channels *
3379 row_info->bit_depth);
3380 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3381 }
3382 }
3383 }
3384 #endif
3386 #if defined(PNG_READ_GAMMA_SUPPORTED)
3387 /* Gamma correct the image, avoiding the alpha channel. Make sure
3388 * you do this after you deal with the transparency issue on grayscale
3389 * or RGB images. If your bit depth is 8, use gamma_table, if it
3390 * is 16, use gamma_16_table and gamma_shift. Build these with
3391 * build_gamma_table().
3392 */
3393 void /* PRIVATE */
3394 png_do_gamma(png_row_infop row_info, png_bytep row,
3395 png_bytep gamma_table, png_uint_16pp gamma_16_table,
3396 int gamma_shift)
3397 {
3398 png_bytep sp;
3399 png_uint_32 i;
3400 png_uint_32 row_width=row_info->width;
3402 png_debug(1, "in png_do_gamma\n");
3403 if (
3404 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3405 row != NULL && row_info != NULL &&
3406 #endif
3407 ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3408 (row_info->bit_depth == 16 && gamma_16_table != NULL)))
3409 {
3410 switch (row_info->color_type)
3411 {
3412 case PNG_COLOR_TYPE_RGB:
3413 {
3414 if (row_info->bit_depth == 8)
3415 {
3416 sp = row;
3417 for (i = 0; i < row_width; i++)
3418 {
3419 *sp = gamma_table[*sp];
3420 sp++;
3421 *sp = gamma_table[*sp];
3422 sp++;
3423 *sp = gamma_table[*sp];
3424 sp++;
3425 }
3426 }
3427 else /* if (row_info->bit_depth == 16) */
3428 {
3429 sp = row;
3430 for (i = 0; i < row_width; i++)
3431 {
3432 png_uint_16 v;
3434 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3435 *sp = (png_byte)((v >> 8) & 0xff);
3436 *(sp + 1) = (png_byte)(v & 0xff);
3437 sp += 2;
3438 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3439 *sp = (png_byte)((v >> 8) & 0xff);
3440 *(sp + 1) = (png_byte)(v & 0xff);
3441 sp += 2;
3442 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3443 *sp = (png_byte)((v >> 8) & 0xff);
3444 *(sp + 1) = (png_byte)(v & 0xff);
3445 sp += 2;
3446 }
3447 }
3448 break;
3449 }
3450 case PNG_COLOR_TYPE_RGB_ALPHA:
3451 {
3452 if (row_info->bit_depth == 8)
3453 {
3454 sp = row;
3455 for (i = 0; i < row_width; i++)
3456 {
3457 *sp = gamma_table[*sp];
3458 sp++;
3459 *sp = gamma_table[*sp];
3460 sp++;
3461 *sp = gamma_table[*sp];
3462 sp++;
3463 sp++;
3464 }
3465 }
3466 else /* if (row_info->bit_depth == 16) */
3467 {
3468 sp = row;
3469 for (i = 0; i < row_width; i++)
3470 {
3471 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3472 *sp = (png_byte)((v >> 8) & 0xff);
3473 *(sp + 1) = (png_byte)(v & 0xff);
3474 sp += 2;
3475 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3476 *sp = (png_byte)((v >> 8) & 0xff);
3477 *(sp + 1) = (png_byte)(v & 0xff);
3478 sp += 2;
3479 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3480 *sp = (png_byte)((v >> 8) & 0xff);
3481 *(sp + 1) = (png_byte)(v & 0xff);
3482 sp += 4;
3483 }
3484 }
3485 break;
3486 }
3487 case PNG_COLOR_TYPE_GRAY_ALPHA:
3488 {
3489 if (row_info->bit_depth == 8)
3490 {
3491 sp = row;
3492 for (i = 0; i < row_width; i++)
3493 {
3494 *sp = gamma_table[*sp];
3495 sp += 2;
3496 }
3497 }
3498 else /* if (row_info->bit_depth == 16) */
3499 {
3500 sp = row;
3501 for (i = 0; i < row_width; i++)
3502 {
3503 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3504 *sp = (png_byte)((v >> 8) & 0xff);
3505 *(sp + 1) = (png_byte)(v & 0xff);
3506 sp += 4;
3507 }
3508 }
3509 break;
3510 }
3511 case PNG_COLOR_TYPE_GRAY:
3512 {
3513 if (row_info->bit_depth == 2)
3514 {
3515 sp = row;
3516 for (i = 0; i < row_width; i += 4)
3517 {
3518 int a = *sp & 0xc0;
3519 int b = *sp & 0x30;
3520 int c = *sp & 0x0c;
3521 int d = *sp & 0x03;
3523 *sp = (png_byte)(
3524 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
3525 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3526 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
3527 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
3528 sp++;
3529 }
3530 }
3531 if (row_info->bit_depth == 4)
3532 {
3533 sp = row;
3534 for (i = 0; i < row_width; i += 2)
3535 {
3536 int msb = *sp & 0xf0;
3537 int lsb = *sp & 0x0f;
3539 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3540 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
3541 sp++;
3542 }
3543 }
3544 else if (row_info->bit_depth == 8)
3545 {
3546 sp = row;
3547 for (i = 0; i < row_width; i++)
3548 {
3549 *sp = gamma_table[*sp];
3550 sp++;
3551 }
3552 }
3553 else if (row_info->bit_depth == 16)
3554 {
3555 sp = row;
3556 for (i = 0; i < row_width; i++)
3557 {
3558 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3559 *sp = (png_byte)((v >> 8) & 0xff);
3560 *(sp + 1) = (png_byte)(v & 0xff);
3561 sp += 2;
3562 }
3563 }
3564 break;
3565 }
3566 }
3567 }
3568 }
3569 #endif
3571 #if defined(PNG_READ_EXPAND_SUPPORTED)
3572 /* Expands a palette row to an RGB or RGBA row depending
3573 * upon whether you supply trans and num_trans.
3574 */
3575 void /* PRIVATE */
3576 png_do_expand_palette(png_row_infop row_info, png_bytep row,
3577 png_colorp palette, png_bytep trans, int num_trans)
3578 {
3579 int shift, value;
3580 png_bytep sp, dp;
3581 png_uint_32 i;
3582 png_uint_32 row_width=row_info->width;
3584 png_debug(1, "in png_do_expand_palette\n");
3585 if (
3586 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3587 row != NULL && row_info != NULL &&
3588 #endif
3589 row_info->color_type == PNG_COLOR_TYPE_PALETTE)
3590 {
3591 if (row_info->bit_depth < 8)
3592 {
3593 switch (row_info->bit_depth)
3594 {
3595 case 1:
3596 {
3597 sp = row + (png_size_t)((row_width - 1) >> 3);
3598 dp = row + (png_size_t)row_width - 1;
3599 shift = 7 - (int)((row_width + 7) & 0x07);
3600 for (i = 0; i < row_width; i++)
3601 {
3602 if ((*sp >> shift) & 0x01)
3603 *dp = 1;
3604 else
3605 *dp = 0;
3606 if (shift == 7)
3607 {
3608 shift = 0;
3609 sp--;
3610 }
3611 else
3612 shift++;
3614 dp--;
3615 }
3616 break;
3617 }
3618 case 2:
3619 {
3620 sp = row + (png_size_t)((row_width - 1) >> 2);
3621 dp = row + (png_size_t)row_width - 1;
3622 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3623 for (i = 0; i < row_width; i++)
3624 {
3625 value = (*sp >> shift) & 0x03;
3626 *dp = (png_byte)value;
3627 if (shift == 6)
3628 {
3629 shift = 0;
3630 sp--;
3631 }
3632 else
3633 shift += 2;
3635 dp--;
3636 }
3637 break;
3638 }
3639 case 4:
3640 {
3641 sp = row + (png_size_t)((row_width - 1) >> 1);
3642 dp = row + (png_size_t)row_width - 1;
3643 shift = (int)((row_width & 0x01) << 2);
3644 for (i = 0; i < row_width; i++)
3645 {
3646 value = (*sp >> shift) & 0x0f;
3647 *dp = (png_byte)value;
3648 if (shift == 4)
3649 {
3650 shift = 0;
3651 sp--;
3652 }
3653 else
3654 shift += 4;
3656 dp--;
3657 }
3658 break;
3659 }
3660 }
3661 row_info->bit_depth = 8;
3662 row_info->pixel_depth = 8;
3663 row_info->rowbytes = row_width;
3664 }
3665 switch (row_info->bit_depth)
3666 {
3667 case 8:
3668 {
3669 if (trans != NULL)
3670 {
3671 sp = row + (png_size_t)row_width - 1;
3672 dp = row + (png_size_t)(row_width << 2) - 1;
3674 for (i = 0; i < row_width; i++)
3675 {
3676 if ((int)(*sp) >= num_trans)
3677 *dp-- = 0xff;
3678 else
3679 *dp-- = trans[*sp];
3680 *dp-- = palette[*sp].blue;
3681 *dp-- = palette[*sp].green;
3682 *dp-- = palette[*sp].red;
3683 sp--;
3684 }
3685 row_info->bit_depth = 8;
3686 row_info->pixel_depth = 32;
3687 row_info->rowbytes = row_width * 4;
3688 row_info->color_type = 6;
3689 row_info->channels = 4;
3690 }
3691 else
3692 {
3693 sp = row + (png_size_t)row_width - 1;
3694 dp = row + (png_size_t)(row_width * 3) - 1;
3696 for (i = 0; i < row_width; i++)
3697 {
3698 *dp-- = palette[*sp].blue;
3699 *dp-- = palette[*sp].green;
3700 *dp-- = palette[*sp].red;
3701 sp--;
3702 }
3703 row_info->bit_depth = 8;
3704 row_info->pixel_depth = 24;
3705 row_info->rowbytes = row_width * 3;
3706 row_info->color_type = 2;
3707 row_info->channels = 3;
3708 }
3709 break;
3710 }
3711 }
3712 }
3713 }
3715 /* If the bit depth < 8, it is expanded to 8. Also, if the already
3716 * expanded transparency value is supplied, an alpha channel is built.
3717 */
3718 void /* PRIVATE */
3719 png_do_expand(png_row_infop row_info, png_bytep row,
3720 png_color_16p trans_value)
3721 {
3722 int shift, value;
3723 png_bytep sp, dp;
3724 png_uint_32 i;
3725 png_uint_32 row_width=row_info->width;
3727 png_debug(1, "in png_do_expand\n");
3728 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3729 if (row != NULL && row_info != NULL)
3730 #endif
3731 {
3732 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
3733 {
3734 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
3736 if (row_info->bit_depth < 8)
3737 {
3738 switch (row_info->bit_depth)
3739 {
3740 case 1:
3741 {
3742 gray = (png_uint_16)((gray&0x01)*0xff);
3743 sp = row + (png_size_t)((row_width - 1) >> 3);
3744 dp = row + (png_size_t)row_width - 1;
3745 shift = 7 - (int)((row_width + 7) & 0x07);
3746 for (i = 0; i < row_width; i++)
3747 {
3748 if ((*sp >> shift) & 0x01)
3749 *dp = 0xff;
3750 else
3751 *dp = 0;
3752 if (shift == 7)
3753 {
3754 shift = 0;
3755 sp--;
3756 }
3757 else
3758 shift++;
3760 dp--;
3761 }
3762 break;
3763 }
3764 case 2:
3765 {
3766 gray = (png_uint_16)((gray&0x03)*0x55);
3767 sp = row + (png_size_t)((row_width - 1) >> 2);
3768 dp = row + (png_size_t)row_width - 1;
3769 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3770 for (i = 0; i < row_width; i++)
3771 {
3772 value = (*sp >> shift) & 0x03;
3773 *dp = (png_byte)(value | (value << 2) | (value << 4) |
3774 (value << 6));
3775 if (shift == 6)
3776 {
3777 shift = 0;
3778 sp--;
3779 }
3780 else
3781 shift += 2;
3783 dp--;
3784 }
3785 break;
3786 }
3787 case 4:
3788 {
3789 gray = (png_uint_16)((gray&0x0f)*0x11);
3790 sp = row + (png_size_t)((row_width - 1) >> 1);
3791 dp = row + (png_size_t)row_width - 1;
3792 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
3793 for (i = 0; i < row_width; i++)
3794 {
3795 value = (*sp >> shift) & 0x0f;
3796 *dp = (png_byte)(value | (value << 4));
3797 if (shift == 4)
3798 {
3799 shift = 0;
3800 sp--;
3801 }
3802 else
3803 shift = 4;
3805 dp--;
3806 }
3807 break;
3808 }
3809 }
3810 row_info->bit_depth = 8;
3811 row_info->pixel_depth = 8;
3812 row_info->rowbytes = row_width;
3813 }
3815 if (trans_value != NULL)
3816 {
3817 if (row_info->bit_depth == 8)
3818 {
3819 gray = gray & 0xff;
3820 sp = row + (png_size_t)row_width - 1;
3821 dp = row + (png_size_t)(row_width << 1) - 1;
3822 for (i = 0; i < row_width; i++)
3823 {
3824 if (*sp == gray)
3825 *dp-- = 0;
3826 else
3827 *dp-- = 0xff;
3828 *dp-- = *sp--;
3829 }
3830 }
3831 else if (row_info->bit_depth == 16)
3832 {
3833 png_byte gray_high = (gray >> 8) & 0xff;
3834 png_byte gray_low = gray & 0xff;
3835 sp = row + row_info->rowbytes - 1;
3836 dp = row + (row_info->rowbytes << 1) - 1;
3837 for (i = 0; i < row_width; i++)
3838 {
3839 if (*(sp - 1) == gray_high && *(sp) == gray_low)
3840 {
3841 *dp-- = 0;
3842 *dp-- = 0;
3843 }
3844 else
3845 {
3846 *dp-- = 0xff;
3847 *dp-- = 0xff;
3848 }
3849 *dp-- = *sp--;
3850 *dp-- = *sp--;
3851 }
3852 }
3853 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3854 row_info->channels = 2;
3855 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3856 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
3857 row_width);
3858 }
3859 }
3860 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3861 {
3862 if (row_info->bit_depth == 8)
3863 {
3864 png_byte red = trans_value->red & 0xff;
3865 png_byte green = trans_value->green & 0xff;
3866 png_byte blue = trans_value->blue & 0xff;
3867 sp = row + (png_size_t)row_info->rowbytes - 1;
3868 dp = row + (png_size_t)(row_width << 2) - 1;
3869 for (i = 0; i < row_width; i++)
3870 {
3871 if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
3872 *dp-- = 0;
3873 else
3874 *dp-- = 0xff;
3875 *dp-- = *sp--;
3876 *dp-- = *sp--;
3877 *dp-- = *sp--;
3878 }
3879 }
3880 else if (row_info->bit_depth == 16)
3881 {
3882 png_byte red_high = (trans_value->red >> 8) & 0xff;
3883 png_byte green_high = (trans_value->green >> 8) & 0xff;
3884 png_byte blue_high = (trans_value->blue >> 8) & 0xff;
3885 png_byte red_low = trans_value->red & 0xff;
3886 png_byte green_low = trans_value->green & 0xff;
3887 png_byte blue_low = trans_value->blue & 0xff;
3888 sp = row + row_info->rowbytes - 1;
3889 dp = row + (png_size_t)(row_width << 3) - 1;
3890 for (i = 0; i < row_width; i++)
3891 {
3892 if (*(sp - 5) == red_high &&
3893 *(sp - 4) == red_low &&
3894 *(sp - 3) == green_high &&
3895 *(sp - 2) == green_low &&
3896 *(sp - 1) == blue_high &&
3897 *(sp ) == blue_low)
3898 {
3899 *dp-- = 0;
3900 *dp-- = 0;
3901 }
3902 else
3903 {
3904 *dp-- = 0xff;
3905 *dp-- = 0xff;
3906 }
3907 *dp-- = *sp--;
3908 *dp-- = *sp--;
3909 *dp-- = *sp--;
3910 *dp-- = *sp--;
3911 *dp-- = *sp--;
3912 *dp-- = *sp--;
3913 }
3914 }
3915 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3916 row_info->channels = 4;
3917 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
3918 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3919 }
3920 }
3921 }
3922 #endif
3924 #if defined(PNG_READ_DITHER_SUPPORTED)
3925 void /* PRIVATE */
3926 png_do_dither(png_row_infop row_info, png_bytep row,
3927 png_bytep palette_lookup, png_bytep dither_lookup)
3928 {
3929 png_bytep sp, dp;
3930 png_uint_32 i;
3931 png_uint_32 row_width=row_info->width;
3933 png_debug(1, "in png_do_dither\n");
3934 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3935 if (row != NULL && row_info != NULL)
3936 #endif
3937 {
3938 if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3939 palette_lookup && row_info->bit_depth == 8)
3940 {
3941 int r, g, b, p;
3942 sp = row;
3943 dp = row;
3944 for (i = 0; i < row_width; i++)
3945 {
3946 r = *sp++;
3947 g = *sp++;
3948 b = *sp++;
3950 /* this looks real messy, but the compiler will reduce
3951 it down to a reasonable formula. For example, with
3952 5 bits per color, we get:
3953 p = (((r >> 3) & 0x1f) << 10) |
3954 (((g >> 3) & 0x1f) << 5) |
3955 ((b >> 3) & 0x1f);
3956 */
3957 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3958 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3959 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3960 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3961 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3962 (PNG_DITHER_BLUE_BITS)) |
3963 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3964 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3966 *dp++ = palette_lookup[p];
3967 }
3968 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3969 row_info->channels = 1;
3970 row_info->pixel_depth = row_info->bit_depth;
3971 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
3972 }
3973 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
3974 palette_lookup != NULL && row_info->bit_depth == 8)
3975 {
3976 int r, g, b, p;
3977 sp = row;
3978 dp = row;
3979 for (i = 0; i < row_width; i++)
3980 {
3981 r = *sp++;
3982 g = *sp++;
3983 b = *sp++;
3984 sp++;
3986 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3987 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3988 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3989 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3990 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3991 (PNG_DITHER_BLUE_BITS)) |
3992 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3993 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3995 *dp++ = palette_lookup[p];
3996 }
3997 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3998 row_info->channels = 1;
3999 row_info->pixel_depth = row_info->bit_depth;
4000 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
4001 }
4002 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
4003 dither_lookup && row_info->bit_depth == 8)
4004 {
4005 sp = row;
4006 for (i = 0; i < row_width; i++, sp++)
4007 {
4008 *sp = dither_lookup[*sp];
4009 }
4010 }
4011 }
4012 }
4013 #endif
4015 #ifdef PNG_FLOATING_POINT_SUPPORTED
4016 #if defined(PNG_READ_GAMMA_SUPPORTED)
4017 static PNG_CONST int png_gamma_shift[] =
4018 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
4020 /* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
4021 * tables, we don't make a full table if we are reducing to 8-bit in
4022 * the future. Note also how the gamma_16 tables are segmented so that
4023 * we don't need to allocate > 64K chunks for a full 16-bit table.
4024 */
4025 void /* PRIVATE */
4026 png_build_gamma_table(png_structp png_ptr)
4027 {
4028 png_debug(1, "in png_build_gamma_table\n");
4030 if (png_ptr->bit_depth <= 8)
4031 {
4032 int i;
4033 double g;
4035 if (png_ptr->screen_gamma > .000001)
4036 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4037 else
4038 g = 1.0;
4040 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
4041 (png_uint_32)256);
4043 for (i = 0; i < 256; i++)
4044 {
4045 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
4046 g) * 255.0 + .5);
4047 }
4049 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4050 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4051 if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
4052 {
4054 g = 1.0 / (png_ptr->gamma);
4056 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
4057 (png_uint_32)256);
4059 for (i = 0; i < 256; i++)
4060 {
4061 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
4062 g) * 255.0 + .5);
4063 }
4066 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
4067 (png_uint_32)256);
4069 if (png_ptr->screen_gamma > 0.000001)
4070 g = 1.0 / png_ptr->screen_gamma;
4071 else
4072 g = png_ptr->gamma; /* probably doing rgb_to_gray */
4074 for (i = 0; i < 256; i++)
4075 {
4076 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
4077 g) * 255.0 + .5);
4079 }
4080 }
4081 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4082 }
4083 else
4084 {
4085 double g;
4086 int i, j, shift, num;
4087 int sig_bit;
4088 png_uint_32 ig;
4090 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
4091 {
4092 sig_bit = (int)png_ptr->sig_bit.red;
4093 if ((int)png_ptr->sig_bit.green > sig_bit)
4094 sig_bit = png_ptr->sig_bit.green;
4095 if ((int)png_ptr->sig_bit.blue > sig_bit)
4096 sig_bit = png_ptr->sig_bit.blue;
4097 }
4098 else
4099 {
4100 sig_bit = (int)png_ptr->sig_bit.gray;
4101 }
4103 if (sig_bit > 0)
4104 shift = 16 - sig_bit;
4105 else
4106 shift = 0;
4108 if (png_ptr->transformations & PNG_16_TO_8)
4109 {
4110 if (shift < (16 - PNG_MAX_GAMMA_8))
4111 shift = (16 - PNG_MAX_GAMMA_8);
4112 }
4114 if (shift > 8)
4115 shift = 8;
4116 if (shift < 0)
4117 shift = 0;
4119 png_ptr->gamma_shift = (png_byte)shift;
4121 num = (1 << (8 - shift));
4123 if (png_ptr->screen_gamma > .000001)
4124 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4125 else
4126 g = 1.0;
4128 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
4129 (png_uint_32)(num * png_sizeof(png_uint_16p)));
4131 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
4132 {
4133 double fin, fout;
4134 png_uint_32 last, max;
4136 for (i = 0; i < num; i++)
4137 {
4138 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4139 (png_uint_32)(256 * png_sizeof(png_uint_16)));
4140 }
4142 g = 1.0 / g;
4143 last = 0;
4144 for (i = 0; i < 256; i++)
4145 {
4146 fout = ((double)i + 0.5) / 256.0;
4147 fin = pow(fout, g);
4148 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
4149 while (last <= max)
4150 {
4151 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4152 [(int)(last >> (8 - shift))] = (png_uint_16)(
4153 (png_uint_16)i | ((png_uint_16)i << 8));
4154 last++;
4155 }
4156 }
4157 while (last < ((png_uint_32)num << 8))
4158 {
4159 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4160 [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
4161 last++;
4162 }
4163 }
4164 else
4165 {
4166 for (i = 0; i < num; i++)
4167 {
4168 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4169 (png_uint_32)(256 * png_sizeof(png_uint_16)));
4171 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
4172 for (j = 0; j < 256; j++)
4173 {
4174 png_ptr->gamma_16_table[i][j] =
4175 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4176 65535.0, g) * 65535.0 + .5);
4177 }
4178 }
4179 }
4181 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4182 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4183 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
4184 {
4186 g = 1.0 / (png_ptr->gamma);
4188 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
4189 (png_uint_32)(num * png_sizeof(png_uint_16p )));
4191 for (i = 0; i < num; i++)
4192 {
4193 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
4194 (png_uint_32)(256 * png_sizeof(png_uint_16)));
4196 ig = (((png_uint_32)i *
4197 (png_uint_32)png_gamma_shift[shift]) >> 4);
4198 for (j = 0; j < 256; j++)
4199 {
4200 png_ptr->gamma_16_to_1[i][j] =
4201 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4202 65535.0, g) * 65535.0 + .5);
4203 }
4204 }
4206 if (png_ptr->screen_gamma > 0.000001)
4207 g = 1.0 / png_ptr->screen_gamma;
4208 else
4209 g = png_ptr->gamma; /* probably doing rgb_to_gray */
4211 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
4212 (png_uint_32)(num * png_sizeof(png_uint_16p)));
4214 for (i = 0; i < num; i++)
4215 {
4216 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
4217 (png_uint_32)(256 * png_sizeof(png_uint_16)));
4219 ig = (((png_uint_32)i *
4220 (png_uint_32)png_gamma_shift[shift]) >> 4);
4221 for (j = 0; j < 256; j++)
4222 {
4223 png_ptr->gamma_16_from_1[i][j] =
4224 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4225 65535.0, g) * 65535.0 + .5);
4226 }
4227 }
4228 }
4229 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4230 }
4231 }
4232 #endif
4233 /* To do: install integer version of png_build_gamma_table here */
4234 #endif
4236 #if defined(PNG_MNG_FEATURES_SUPPORTED)
4237 /* undoes intrapixel differencing */
4238 void /* PRIVATE */
4239 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4240 {
4241 png_debug(1, "in png_do_read_intrapixel\n");
4242 if (
4243 #if defined(PNG_USELESS_TESTS_SUPPORTED)
4244 row != NULL && row_info != NULL &&
4245 #endif
4246 (row_info->color_type & PNG_COLOR_MASK_COLOR))
4247 {
4248 int bytes_per_pixel;
4249 png_uint_32 row_width = row_info->width;
4250 if (row_info->bit_depth == 8)
4251 {
4252 png_bytep rp;
4253 png_uint_32 i;
4255 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4256 bytes_per_pixel = 3;
4257 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4258 bytes_per_pixel = 4;
4259 else
4260 return;
4262 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4263 {
4264 *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
4265 *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
4266 }
4267 }
4268 else if (row_info->bit_depth == 16)
4269 {
4270 png_bytep rp;
4271 png_uint_32 i;
4273 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4274 bytes_per_pixel = 6;
4275 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4276 bytes_per_pixel = 8;
4277 else
4278 return;
4280 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4281 {
4282 png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
4283 png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
4284 png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
4285 png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL);
4286 png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL);
4287 *(rp ) = (png_byte)((red >> 8) & 0xff);
4288 *(rp+1) = (png_byte)(red & 0xff);
4289 *(rp+4) = (png_byte)((blue >> 8) & 0xff);
4290 *(rp+5) = (png_byte)(blue & 0xff);
4291 }
4292 }
4293 }
4294 }
4295 #endif /* PNG_MNG_FEATURES_SUPPORTED */
4296 #endif /* PNG_READ_SUPPORTED */