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