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