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