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