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