[DDK]: Merge 46183 from header-branch.
[reactos.git] / rosapps / lib / libpng / pngrtran.c
1
2 /* pngrtran.c - transforms the data in a row for PNG readers
3 *
4 * Last changed in libpng 1.2.22 [October 13, 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. */
22 void PNGAPI
23 png_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 */
78 void PNGAPI
79 png_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 */
102 void PNGAPI
103 png_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)
112 void PNGAPI
113 png_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
131 typedef struct png_dsort_struct
132 {
133 struct png_dsort_struct FAR * next;
134 png_byte left;
135 png_byte right;
136 } png_dsort;
137 typedef png_dsort FAR * png_dsortp;
138 typedef png_dsort FAR * FAR * png_dsortpp;
139
140 void PNGAPI
141 png_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 */
526 void PNGAPI
527 png_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 */
545 void PNGAPI
546 png_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. */
574 void PNGAPI
575 png_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. */
587 void PNGAPI
588 png_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 */
602 void PNGAPI
603 png_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. */
613 void PNGAPI
614 png_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)
625 void PNGAPI
626 png_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
642 void PNGAPI
643 png_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
653 void PNGAPI
654 png_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)
704 void PNGAPI
705 png_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 */
725 void /* PRIVATE */
726 png_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 */
1117 void /* PRIVATE */
1118 png_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) && \
1233 defined(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 */
1258 void /* PRIVATE */
1259 png_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 /*
1333 From 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 */
1504 void /* PRIVATE */
1505 png_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 */
1594 void /* PRIVATE */
1595 png_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 */
1700 void /* PRIVATE */
1701 png_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)
1754 void /* PRIVATE */
1755 png_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)
1846 void /* PRIVATE */
1847 png_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 */
1945 void /* PRIVATE */
1946 png_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 */
2121 void /* PRIVATE */
2122 png_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 */
2222 int /* PRIVATE */
2223 png_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 */
2461 void PNGAPI
2462 png_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)
2507 void /* PRIVATE */
2508 png_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 */
2692 void /* PRIVATE */
2693 png_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