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