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