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