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