source: liacs/MIR2010/SourceCode/cximage/png/pngrtran.c@ 111

Last change on this file since 111 was 95, checked in by Rick van der Zwet, 15 years ago

Bad boy, improper move of directory

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