/[zanavi_public1]/navit/navit/support/libpng/pngrtran.c
ZANavi

Contents of /navit/navit/support/libpng/pngrtran.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki