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