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