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