blob: 9f02191cd6e0002c9dc526bdce73f935b9d41890 [file] [log] [blame]
Guy Schalnat0d580581995-07-20 02:43:20 -05001
Andreas Dilger47a0c421997-05-16 02:46:07 -05002/* pngrtran.c - transforms the data in a row for PNG readers
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003 *
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -06004 * libpng 1.0.0a
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
7 * Copyright (c) 1996, 1997 Andreas Dilger
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06008 * Copyright (c) 1998, Glenn Randers-Pehrson
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -06009 * March 9, 1998
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060010 *
11 * This file contains functions optionally called by an application
12 * in order to tell libpng how to handle data when reading a PNG.
13 * Transformations which are used in both reading and writing are
14 * in pngtrans.c.
15 */
Guy Schalnat0d580581995-07-20 02:43:20 -050016
17#define PNG_INTERNAL
18#include "png.h"
19
Andreas Dilger47a0c421997-05-16 02:46:07 -050020#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED
21/* With these routines, we avoid an integer divide, which will be slower on
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060022 * many machines. However, it does take more operations than the corresponding
23 * divide method, so it may be slower on some RISC systems. There are two
24 * shifts (by 8 or 16 bits) and an addition, versus a single integer divide.
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -060025 *
26 * Note that the rounding factors are NOT supposed to be the same! 128 and
27 * 32768 are correct for the NODIV code; 127 and 32767 are correct for the
28 * standard method.
29 *
30 * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ]
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060031 */
Andreas Dilger47a0c421997-05-16 02:46:07 -050032
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -060033 /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */
34# define png_composite(composite, fg, alpha, bg) \
35 { png_uint_16 temp = ((png_uint_16)(fg) * (png_uint_16)(alpha) + \
36 (png_uint_16)(bg)*(png_uint_16)(255 - \
37 (png_uint_16)(alpha)) + (png_uint_16)128); \
38 (composite) = (png_byte)((temp + (temp >> 8)) >> 8); }
39# define png_composite_16(composite, fg, alpha, bg) \
40 { png_uint_32 temp = ((png_uint_32)(fg) * (png_uint_32)(alpha) + \
41 (png_uint_32)(bg)*(png_uint_32)(65535L - \
42 (png_uint_32)(alpha)) + (png_uint_32)32768L); \
43 (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); }
Andreas Dilger47a0c421997-05-16 02:46:07 -050044
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -060045#else /* standard method using integer division */
46
47 /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */
48# define png_composite(composite, fg, alpha, bg) \
49 (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \
50 (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \
51 (png_uint_16)127) / 255)
52# define png_composite_16(composite, fg, alpha, bg) \
53 (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \
54 (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \
55 (png_uint_32)32767) / (png_uint_32)65535L)
56
57#endif /* ?PNG_READ_COMPOSITE_NODIV_SUPPORTED */
58
Andreas Dilger47a0c421997-05-16 02:46:07 -050059
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060060/* Set the action on getting a CRC error for an ancillary or critical chunk. */
61void
62png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
63{
64 png_debug(1, "in png_set_crc_action\n");
65 /* Tell libpng how we react to CRC errors in critical chunks */
66 switch (crit_action)
67 {
68 case PNG_CRC_NO_CHANGE: /* leave setting as is */
69 break;
70 case PNG_CRC_WARN_USE: /* warn/use data */
71 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
72 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
73 break;
74 case PNG_CRC_QUIET_USE: /* quiet/use data */
75 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
76 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
77 PNG_FLAG_CRC_CRITICAL_IGNORE;
78 break;
79 case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */
80 png_warning(png_ptr, "Can't discard critical data on CRC error.");
81 case PNG_CRC_ERROR_QUIT: /* error/quit */
82 case PNG_CRC_DEFAULT:
83 default:
84 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
85 break;
86 }
87
88 switch (ancil_action)
89 {
90 case PNG_CRC_NO_CHANGE: /* leave setting as is */
91 break;
92 case PNG_CRC_WARN_USE: /* warn/use data */
93 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
94 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
95 break;
96 case PNG_CRC_QUIET_USE: /* quiet/use data */
97 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
98 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
99 PNG_FLAG_CRC_ANCILLARY_NOWARN;
100 break;
101 case PNG_CRC_ERROR_QUIT: /* error/quit */
102 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
103 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
104 break;
105 case PNG_CRC_WARN_DISCARD: /* warn/discard data */
106 case PNG_CRC_DEFAULT:
107 default:
108 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
109 break;
110 }
111}
112
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500113#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500114/* handle alpha and tRNS via a background color */
115void
Guy Schalnat6d764711995-12-19 03:22:19 -0600116png_set_background(png_structp png_ptr,
117 png_color_16p background_color, int background_gamma_code,
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500118 int need_expand, double background_gamma)
Guy Schalnat0d580581995-07-20 02:43:20 -0500119{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500120 png_debug(1, "in png_set_background\n");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600121 if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
122 {
123 png_warning(png_ptr, "Application must supply a known background gamma");
124 return;
125 }
126
Guy Schalnat0d580581995-07-20 02:43:20 -0500127 png_ptr->transformations |= PNG_BACKGROUND;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500128 png_memcpy(&(png_ptr->background), background_color,
Guy Schalnat0d580581995-07-20 02:43:20 -0500129 sizeof(png_color_16));
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500130 png_ptr->background_gamma = (float)background_gamma;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600131 png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
Guy Schalnate5a37791996-06-05 15:50:50 -0500132 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500133}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500134#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500135
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500136#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500137/* strip 16 bit depth files to 8 bit depth */
138void
Guy Schalnat6d764711995-12-19 03:22:19 -0600139png_set_strip_16(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500140{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500141 png_debug(1, "in png_set_strip_16\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500142 png_ptr->transformations |= PNG_16_TO_8;
143}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500144#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500145
Andreas Dilger47a0c421997-05-16 02:46:07 -0500146#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
147void
148png_set_strip_alpha(png_structp png_ptr)
149{
150 png_debug(1, "in png_set_strip_alpha\n");
151 png_ptr->transformations |= PNG_STRIP_ALPHA;
152}
153#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500154
Andreas Dilger47a0c421997-05-16 02:46:07 -0500155#if defined(PNG_READ_DITHER_SUPPORTED)
156/* Dither file to 8 bit. Supply a palette, the current number
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600157 * of elements in the palette, the maximum number of elements
158 * allowed, and a histogram if possible. If the current number
159 * of colors is greater then the maximum number, the palette will be
160 * modified to fit in the maximum number. "full_dither" indicates
161 * whether we need a dithering cube set up for RGB images, or if we
162 * simply are reducing the number of colors in a paletted image.
163 */
Guy Schalnat6d764711995-12-19 03:22:19 -0600164
165typedef struct png_dsort_struct
Guy Schalnat0d580581995-07-20 02:43:20 -0500166{
Guy Schalnat6d764711995-12-19 03:22:19 -0600167 struct png_dsort_struct FAR * next;
Guy Schalnat0d580581995-07-20 02:43:20 -0500168 png_byte left;
169 png_byte right;
Guy Schalnat6d764711995-12-19 03:22:19 -0600170} png_dsort;
171typedef png_dsort FAR * png_dsortp;
172typedef png_dsort FAR * FAR * png_dsortpp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500173
174void
Guy Schalnat6d764711995-12-19 03:22:19 -0600175png_set_dither(png_structp png_ptr, png_colorp palette,
176 int num_palette, int maximum_colors, png_uint_16p histogram,
Guy Schalnat0d580581995-07-20 02:43:20 -0500177 int full_dither)
178{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500179 png_debug(1, "in png_set_dither\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500180 png_ptr->transformations |= PNG_DITHER;
181
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600182 if (!full_dither)
Guy Schalnat0d580581995-07-20 02:43:20 -0500183 {
184 int i;
185
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600186 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600187 (png_uint_32)(num_palette * sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500188 for (i = 0; i < num_palette; i++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600189 png_ptr->dither_index[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500190 }
191
192 if (num_palette > maximum_colors)
193 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500194 if (histogram != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500195 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500196 /* This is easy enough, just throw out the least used colors.
197 Perhaps not the best solution, but good enough. */
Guy Schalnat0d580581995-07-20 02:43:20 -0500198
199 int i;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600200 png_bytep sort;
Guy Schalnat0d580581995-07-20 02:43:20 -0500201
202 /* initialize an array to sort colors */
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600203 sort = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_palette
204 * sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500205
206 /* initialize the sort array */
207 for (i = 0; i < num_palette; i++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600208 sort[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500209
Andreas Dilger47a0c421997-05-16 02:46:07 -0500210 /* Find the least used palette entries by starting a
Guy Schalnat0d580581995-07-20 02:43:20 -0500211 bubble sort, and running it until we have sorted
212 out enough colors. Note that we don't care about
213 sorting all the colors, just finding which are
214 least used. */
215
216 for (i = num_palette - 1; i >= maximum_colors; i--)
217 {
218 int done; /* to stop early if the list is pre-sorted */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600219 int j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500220
221 done = 1;
222 for (j = 0; j < i; j++)
223 {
224 if (histogram[sort[j]] < histogram[sort[j + 1]])
225 {
226 png_byte t;
227
228 t = sort[j];
229 sort[j] = sort[j + 1];
230 sort[j + 1] = t;
231 done = 0;
232 }
233 }
234 if (done)
235 break;
236 }
237
238 /* swap the palette around, and set up a table, if necessary */
239 if (full_dither)
240 {
241 int j;
242
243 /* put all the useful colors within the max, but don't
244 move the others */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500245 for (i = 0, j = num_palette; i < maximum_colors; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500246 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600247 if ((int)sort[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500248 {
249 do
250 j--;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600251 while ((int)sort[j] >= maximum_colors);
Guy Schalnat0d580581995-07-20 02:43:20 -0500252 palette[i] = palette[j];
253 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600254 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500255 }
256 else
257 {
258 int j;
259
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600260 /* move all the used colors inside the max limit, and
Guy Schalnat0d580581995-07-20 02:43:20 -0500261 develop a translation table */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500262 for (i = 0, j = num_palette; i < maximum_colors; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500263 {
264 /* only move the colors we need to */
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600265 if ((int)sort[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500266 {
267 png_color tmp_color;
268
269 do
270 j--;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600271 while ((int)sort[j] >= maximum_colors);
Guy Schalnat0d580581995-07-20 02:43:20 -0500272
273 tmp_color = palette[j];
274 palette[j] = palette[i];
275 palette[i] = tmp_color;
276 /* indicate where the color went */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600277 png_ptr->dither_index[j] = (png_byte)i;
278 png_ptr->dither_index[i] = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500279 }
280 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500281
282 /* find closest color for those colors we are not using */
Guy Schalnat0d580581995-07-20 02:43:20 -0500283 for (i = 0; i < num_palette; i++)
284 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600285 if ((int)png_ptr->dither_index[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500286 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500287 int min_d, k, min_k, d_index;
Guy Schalnat0d580581995-07-20 02:43:20 -0500288
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600289 /* find the closest color to one we threw out */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500290 d_index = png_ptr->dither_index[i];
291 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
292 for (k = 1, min_k = 0; k < maximum_colors; k++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500293 {
294 int d;
295
Andreas Dilger47a0c421997-05-16 02:46:07 -0500296 d = PNG_COLOR_DIST(palette[d_index], palette[k]);
Guy Schalnat0d580581995-07-20 02:43:20 -0500297
298 if (d < min_d)
299 {
300 min_d = d;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500301 min_k = k;
Guy Schalnat0d580581995-07-20 02:43:20 -0500302 }
303 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600304 /* point to closest color */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500305 png_ptr->dither_index[i] = (png_byte)min_k;
Guy Schalnat0d580581995-07-20 02:43:20 -0500306 }
307 }
308 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600309 png_free(png_ptr, sort);
Guy Schalnat0d580581995-07-20 02:43:20 -0500310 }
311 else
312 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500313 /* This is much harder to do simply (and quickly). Perhaps
Guy Schalnat0d580581995-07-20 02:43:20 -0500314 we need to go through a median cut routine, but those
315 don't always behave themselves with only a few colors
316 as input. So we will just find the closest two colors,
317 and throw out one of them (chosen somewhat randomly).
Andreas Dilger47a0c421997-05-16 02:46:07 -0500318 [I don't understand this at all, so if someone wants to
319 work on improving it, be my guest - AED]
Guy Schalnat0d580581995-07-20 02:43:20 -0500320 */
321 int i;
322 int max_d;
323 int num_new_palette;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600324 png_dsortpp hash;
325 png_bytep index_to_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500326 /* where the original index currently is in the palette */
Guy Schalnat6d764711995-12-19 03:22:19 -0600327 png_bytep palette_to_index;
Guy Schalnat0d580581995-07-20 02:43:20 -0500328 /* which original index points to this palette color */
329
330 /* initialize palette index arrays */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600331 index_to_palette = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600332 (png_uint_32)(num_palette * sizeof (png_byte)));
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600333 palette_to_index = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600334 (png_uint_32)(num_palette * sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500335
336 /* initialize the sort array */
337 for (i = 0; i < num_palette; i++)
338 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600339 index_to_palette[i] = (png_byte)i;
340 palette_to_index[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500341 }
342
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600343 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
344 sizeof (png_dsortp)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500345 for (i = 0; i < 769; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500346 hash[i] = NULL;
Guy Schalnat6d764711995-12-19 03:22:19 -0600347/* png_memset(hash, 0, 769 * sizeof (png_dsortp)); */
Guy Schalnat0d580581995-07-20 02:43:20 -0500348
349 num_new_palette = num_palette;
350
351 /* initial wild guess at how far apart the farthest pixel
352 pair we will be eliminating will be. Larger
353 numbers mean more areas will be allocated, Smaller
354 numbers run the risk of not saving enough data, and
355 having to do this all over again.
356
357 I have not done extensive checking on this number.
358 */
359 max_d = 96;
360
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600361 while (num_new_palette > maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500362 {
363 for (i = 0; i < num_new_palette - 1; i++)
364 {
365 int j;
366
367 for (j = i + 1; j < num_new_palette; j++)
368 {
369 int d;
370
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600371 d = PNG_COLOR_DIST(palette[i], palette[j]);
Guy Schalnat0d580581995-07-20 02:43:20 -0500372
373 if (d <= max_d)
374 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600375 png_dsortp t;
Guy Schalnat0d580581995-07-20 02:43:20 -0500376
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600377 t = (png_dsortp)png_malloc(png_ptr, (png_uint_32)(sizeof
378 (png_dsort)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500379 t->next = hash[d];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600380 t->left = (png_byte)i;
381 t->right = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500382 hash[d] = t;
383 }
384 }
385 }
386
387 for (i = 0; i <= max_d; i++)
388 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500389 if (hash[i] != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500390 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600391 png_dsortp p;
Guy Schalnat0d580581995-07-20 02:43:20 -0500392
393 for (p = hash[i]; p; p = p->next)
394 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600395 if ((int)index_to_palette[p->left] < num_new_palette &&
396 (int)index_to_palette[p->right] < num_new_palette)
Guy Schalnat0d580581995-07-20 02:43:20 -0500397 {
398 int j, next_j;
399
400 if (num_new_palette & 1)
401 {
402 j = p->left;
403 next_j = p->right;
404 }
405 else
406 {
407 j = p->right;
408 next_j = p->left;
409 }
410
411 num_new_palette--;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500412 palette[index_to_palette[j]] = palette[num_new_palette];
Guy Schalnat0d580581995-07-20 02:43:20 -0500413 if (!full_dither)
414 {
415 int k;
416
417 for (k = 0; k < num_palette; k++)
418 {
419 if (png_ptr->dither_index[k] ==
420 index_to_palette[j])
421 png_ptr->dither_index[k] =
422 index_to_palette[next_j];
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600423 if ((int)png_ptr->dither_index[k] ==
Guy Schalnat0d580581995-07-20 02:43:20 -0500424 num_new_palette)
425 png_ptr->dither_index[k] =
426 index_to_palette[j];
427 }
428 }
429
430 index_to_palette[palette_to_index[num_new_palette]] =
431 index_to_palette[j];
432 palette_to_index[index_to_palette[j]] =
433 palette_to_index[num_new_palette];
434
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600435 index_to_palette[j] = (png_byte)num_new_palette;
436 palette_to_index[num_new_palette] = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500437 }
438 if (num_new_palette <= maximum_colors)
439 break;
440 }
441 if (num_new_palette <= maximum_colors)
442 break;
443 }
444 }
445
446 for (i = 0; i < 769; i++)
447 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500448 if (hash[i] != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500449 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600450 png_dsortp p;
Guy Schalnat0d580581995-07-20 02:43:20 -0500451
452 p = hash[i];
453 while (p)
454 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600455 png_dsortp t;
Guy Schalnat0d580581995-07-20 02:43:20 -0500456
457 t = p->next;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600458 png_free(png_ptr, p);
Guy Schalnat0d580581995-07-20 02:43:20 -0500459 p = t;
460 }
461 }
462 hash[i] = 0;
463 }
464 max_d += 96;
465 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600466 png_free(png_ptr, hash);
467 png_free(png_ptr, palette_to_index);
468 png_free(png_ptr, index_to_palette);
Guy Schalnat0d580581995-07-20 02:43:20 -0500469 }
470 num_palette = maximum_colors;
471 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500472 if (png_ptr->palette == NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600473 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500474 png_ptr->palette = palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500475 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600476 png_ptr->num_palette = (png_uint_16)num_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500477
478 if (full_dither)
479 {
480 int i;
481 int total_bits, num_red, num_green, num_blue;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500482 png_size_t num_entries;
Guy Schalnat6d764711995-12-19 03:22:19 -0600483 png_bytep distance;
Guy Schalnat0d580581995-07-20 02:43:20 -0500484
485 total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600486 PNG_DITHER_BLUE_BITS;
Guy Schalnat0d580581995-07-20 02:43:20 -0500487
488 num_red = (1 << PNG_DITHER_RED_BITS);
489 num_green = (1 << PNG_DITHER_GREEN_BITS);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600490 num_blue = (1 << PNG_DITHER_BLUE_BITS);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500491 num_entries = ((png_size_t)1 << total_bits);
Guy Schalnat0d580581995-07-20 02:43:20 -0500492
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600493 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600494 (png_uint_32)(num_entries * sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500495
Andreas Dilger47a0c421997-05-16 02:46:07 -0500496 png_memset(png_ptr->palette_lookup, 0, num_entries * sizeof (png_byte));
Guy Schalnat0d580581995-07-20 02:43:20 -0500497
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600498 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
499 sizeof(png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500500
Andreas Dilger47a0c421997-05-16 02:46:07 -0500501 png_memset(distance, 0xff, num_entries * sizeof(png_byte));
Guy Schalnat0d580581995-07-20 02:43:20 -0500502
503 for (i = 0; i < num_palette; i++)
504 {
505 int r, g, b, ir, ig, ib;
506
507 r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600508 g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
Guy Schalnat0d580581995-07-20 02:43:20 -0500509 b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
510
511 for (ir = 0; ir < num_red; ir++)
512 {
513 int dr, index_r;
514
515 dr = abs(ir - r);
516 index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
517 for (ig = 0; ig < num_green; ig++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600518 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500519 int dg, dt, dm, index_g;
520
521 dg = abs(ig - g);
522 dt = dr + dg;
523 dm = ((dr > dg) ? dr : dg);
524 index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
525 for (ib = 0; ib < num_blue; ib++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600526 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500527 int d_index, db, dmax, d;
Guy Schalnat0d580581995-07-20 02:43:20 -0500528
Andreas Dilger47a0c421997-05-16 02:46:07 -0500529 d_index = index_g | ib;
Guy Schalnat0d580581995-07-20 02:43:20 -0500530 db = abs(ib - b);
531 dmax = ((dm > db) ? dm : db);
532 d = dmax + dt + db;
533
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600534 if (d < (int)distance[d_index])
Guy Schalnat0d580581995-07-20 02:43:20 -0500535 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500536 distance[d_index] = (png_byte)d;
537 png_ptr->palette_lookup[d_index] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500538 }
539 }
540 }
541 }
542 }
543
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600544 png_free(png_ptr, distance);
Guy Schalnat0d580581995-07-20 02:43:20 -0500545 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500546}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500547#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500548
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500549#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600550/* Transform the image from the file_gamma to the screen_gamma. We
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600551 * only do transformations on images where the file_gamma and screen_gamma
552 * are not close reciprocals, otherwise it slows things down slightly, and
553 * also needlessly introduces small errors.
554 */
Guy Schalnat0d580581995-07-20 02:43:20 -0500555void
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600556png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
Guy Schalnat0d580581995-07-20 02:43:20 -0500557{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500558 png_debug(1, "in png_set_gamma\n");
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600559 if (fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600560 png_ptr->transformations |= PNG_GAMMA;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500561 png_ptr->gamma = (float)file_gamma;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600562 png_ptr->screen_gamma = (float)scrn_gamma;
Guy Schalnat0d580581995-07-20 02:43:20 -0500563}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500564#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500565
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500566#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600567/* Expand paletted images to rgb, expand grayscale images of
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600568 * less then 8 bit depth to 8 bit depth, and expand tRNS chunks
569 * to alpha channels.
570 */
Guy Schalnat0d580581995-07-20 02:43:20 -0500571void
Guy Schalnat6d764711995-12-19 03:22:19 -0600572png_set_expand(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500573{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500574 png_debug(1, "in png_set_expand\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500575 png_ptr->transformations |= PNG_EXPAND;
576}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500577#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500578
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500579#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500580void
Guy Schalnat6d764711995-12-19 03:22:19 -0600581png_set_gray_to_rgb(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500582{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500583 png_debug(1, "in png_set_gray_to_rgb\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500584 png_ptr->transformations |= PNG_GRAY_TO_RGB;
585}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500586#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500587
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600588#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
589/* Convert a RGB image to a grayscale of the given width. This would
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600590 * allow us, for example, to convert a 24 bpp RGB image into an 8 or
591 * 16 bpp grayscale image. (Not yet implemented.)
592 */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600593void
594png_set_rgb_to_gray(png_structp png_ptr, int gray_bits)
595{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500596 png_debug(1, "in png_set_rgb_to_gray\n");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600597 png_ptr->transformations |= PNG_RGB_TO_GRAY;
598 /* Need to do something with gray_bits here. */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600599 png_warning(png_ptr, "RGB to GRAY transformation is not yet implemented.");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600600}
601#endif
602
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600603#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
604void
605png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
606 read_user_transform_fn)
607{
608 png_debug(1, "in png_set_read_user_transform_fn\n");
609 png_ptr->transformations |= PNG_USER_TRANSFORM;
610 png_ptr->read_user_transform_fn = read_user_transform_fn;
611}
612#endif
613
Andreas Dilger47a0c421997-05-16 02:46:07 -0500614/* Initialize everything needed for the read. This includes modifying
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600615 * the palette.
616 */
Guy Schalnat0d580581995-07-20 02:43:20 -0500617void
Guy Schalnat6d764711995-12-19 03:22:19 -0600618png_init_read_transformations(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500619{
620 int color_type;
621
Andreas Dilger47a0c421997-05-16 02:46:07 -0500622 png_debug(1, "in png_init_read_transformations\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500623 color_type = png_ptr->color_type;
624
Guy Schalnate5a37791996-06-05 15:50:50 -0500625#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
626 if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -0500627 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500628 if (color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -0500629 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500630 /* expand background chunk. */
Guy Schalnat0d580581995-07-20 02:43:20 -0500631 switch (png_ptr->bit_depth)
632 {
633 case 1:
Guy Schalnate5a37791996-06-05 15:50:50 -0500634 png_ptr->background.gray *= (png_uint_16)0xff;
635 png_ptr->background.red = png_ptr->background.green =
636 png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500637 break;
638 case 2:
Guy Schalnate5a37791996-06-05 15:50:50 -0500639 png_ptr->background.gray *= (png_uint_16)0x55;
640 png_ptr->background.red = png_ptr->background.green =
641 png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500642 break;
643 case 4:
Guy Schalnate5a37791996-06-05 15:50:50 -0500644 png_ptr->background.gray *= (png_uint_16)0x11;
645 png_ptr->background.red = png_ptr->background.green =
646 png_ptr->background.blue = png_ptr->background.gray;
647 break;
648 case 8:
649 case 16:
650 png_ptr->background.red = png_ptr->background.green =
651 png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500652 break;
653 }
654 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500655 else if (color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -0500656 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500657 png_ptr->background.red =
Guy Schalnat0d580581995-07-20 02:43:20 -0500658 png_ptr->palette[png_ptr->background.index].red;
659 png_ptr->background.green =
660 png_ptr->palette[png_ptr->background.index].green;
Guy Schalnate5a37791996-06-05 15:50:50 -0500661 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -0500662 png_ptr->palette[png_ptr->background.index].blue;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600663
664#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
665 if (png_ptr->transformations & PNG_INVERT_ALPHA)
666 {
667#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600668 /* GRR BUG #1: was (png_ptr->transformations & !PNG_EXPAND) */
669 if (!(png_ptr->transformations & PNG_EXPAND))
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600670#endif
671 {
672 /* invert the alpha channel (in tRNS) unless the pixels are
673 going to be expanded, in which case leave it for later */
674 int i;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600675 for (i=0; i<(int)png_ptr->num_trans; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600676 png_ptr->trans[i] = 255 - png_ptr->trans[i];
677 }
678 }
679#endif
680
Guy Schalnat0d580581995-07-20 02:43:20 -0500681 }
682 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500683#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500684
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500685#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500686 png_ptr->background_1 = png_ptr->background;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500687#endif
688#if defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500689 if (png_ptr->transformations & PNG_GAMMA)
690 {
691 png_build_gamma_table(png_ptr);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500692#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnate5a37791996-06-05 15:50:50 -0500693 if (png_ptr->transformations & PNG_BACKGROUND)
Guy Schalnat0d580581995-07-20 02:43:20 -0500694 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500695 if (color_type == PNG_COLOR_TYPE_PALETTE)
696 {
697 int num_palette, i;
698 png_color back, back_1;
699 png_colorp palette;
700
701 palette = png_ptr->palette;
702 num_palette = png_ptr->num_palette;
703
Andreas Dilger47a0c421997-05-16 02:46:07 -0500704 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
705 {
706 back.red = png_ptr->gamma_table[png_ptr->background.red];
707 back.green = png_ptr->gamma_table[png_ptr->background.green];
708 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
Guy Schalnate5a37791996-06-05 15:50:50 -0500709
Andreas Dilger47a0c421997-05-16 02:46:07 -0500710 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
711 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
712 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
713 }
714 else
715 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600716 double g, gs;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500717
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600718/*
719 GRR BUG #3: inconsistent with handling of full RGBA below
720 g = 1.0 / png_ptr->background_gamma;
721 gs = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
722 */
723 switch (png_ptr->background_gamma_type)
Glenn Randers-Pehrson4922b1b1998-03-08 22:55:17 -0600724 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600725 case PNG_BACKGROUND_GAMMA_SCREEN:
726 g = (png_ptr->screen_gamma);
727 gs = 1.0;
728 break;
729 case PNG_BACKGROUND_GAMMA_FILE:
730 g = 1.0 / (png_ptr->gamma);
731 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
732 break;
733 case PNG_BACKGROUND_GAMMA_UNIQUE:
734 g = 1.0 / (png_ptr->background_gamma);
735 gs = 1.0 / (png_ptr->background_gamma *
736 png_ptr->screen_gamma);
737 break;
738 default:
739 g = 1.0; /* back_1 */
740 gs = 1.0; /* back */
741 }
742
743 if (
744/*
745 GRR BUG #2: This creates self-inconsistent images--fully
746 transparent and fully opaque look fine, but translucent
747 pixels are wrong (too bright if XV's code can be trusted).
748 Commenting it out makes an internally self-consistent
749 image, but still not consistent with RGBA version of same
750 thing (again, too bright in XV).
751 png_ptr->background_gamma_type==PNG_BACKGROUND_GAMMA_SCREEN||
752 */
753 fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
754 {
755 back.red = (png_byte)png_ptr->background.red;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500756 back.green = (png_byte)png_ptr->background.green;
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600757 back.blue = (png_byte)png_ptr->background.blue;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500758 }
759 else
760 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600761 back.red = (png_byte)(pow(
762 (double)png_ptr->background.red/255, gs) * 255.0 + .5);
763 back.green = (png_byte)(pow(
764 (double)png_ptr->background.green/255, gs) * 255.0 + .5);
765 back.blue = (png_byte)(pow(
766 (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500767 }
768
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600769 back_1.red = (png_byte)(pow(
770 (double)png_ptr->background.red/255, g) * 255.0 + .5);
771 back_1.green = (png_byte)(pow(
772 (double)png_ptr->background.green/255, g) * 255.0 + .5);
773 back_1.blue = (png_byte)(pow(
774 (double)png_ptr->background.blue/255, g) * 255.0 + .5);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500775 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500776
777 for (i = 0; i < num_palette; i++)
778 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500779 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
Guy Schalnate5a37791996-06-05 15:50:50 -0500780 {
781 if (png_ptr->trans[i] == 0)
782 {
783 palette[i] = back;
784 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500785 else /* if (png_ptr->trans[i] != 0xff) */
Guy Schalnate5a37791996-06-05 15:50:50 -0500786 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500787 png_byte v, w;
Guy Schalnate5a37791996-06-05 15:50:50 -0500788
789 v = png_ptr->gamma_to_1[palette[i].red];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500790 png_composite(w, v, png_ptr->trans[i], back_1.red);
Guy Schalnate5a37791996-06-05 15:50:50 -0500791 palette[i].red = png_ptr->gamma_from_1[w];
792
793 v = png_ptr->gamma_to_1[palette[i].green];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500794 png_composite(w, v, png_ptr->trans[i], back_1.green);
Guy Schalnate5a37791996-06-05 15:50:50 -0500795 palette[i].green = png_ptr->gamma_from_1[w];
796
797 v = png_ptr->gamma_to_1[palette[i].blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500798 png_composite(w, v, png_ptr->trans[i], back_1.blue);
Guy Schalnate5a37791996-06-05 15:50:50 -0500799 palette[i].blue = png_ptr->gamma_from_1[w];
800 }
801 }
802 else
803 {
804 palette[i].red = png_ptr->gamma_table[palette[i].red];
805 palette[i].green = png_ptr->gamma_table[palette[i].green];
806 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
807 }
808 }
809 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500810 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN)*/
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600811 else
812 /* color_type != PNG_COLOR_TYPE_PALETTE */
Guy Schalnat0d580581995-07-20 02:43:20 -0500813 {
814 double g, gs, m;
815
Guy Schalnat6d764711995-12-19 03:22:19 -0600816 m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
Guy Schalnat0d580581995-07-20 02:43:20 -0500817 g = 1.0;
818 gs = 1.0;
819
820 switch (png_ptr->background_gamma_type)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600821 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500822 case PNG_BACKGROUND_GAMMA_SCREEN:
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600823 g = (png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500824 gs = 1.0;
825 break;
826 case PNG_BACKGROUND_GAMMA_FILE:
827 g = 1.0 / (png_ptr->gamma);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600828 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500829 break;
830 case PNG_BACKGROUND_GAMMA_UNIQUE:
831 g = 1.0 / (png_ptr->background_gamma);
832 gs = 1.0 / (png_ptr->background_gamma *
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600833 png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500834 break;
835 }
836
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600837 if (color_type & PNG_COLOR_MASK_COLOR)
Guy Schalnat0d580581995-07-20 02:43:20 -0500838 {
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600839 /* RGB or RGBA */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600840 png_ptr->background_1.red = (png_uint_16)(pow(
Guy Schalnat0d580581995-07-20 02:43:20 -0500841 (double)png_ptr->background.red / m, g) * m + .5);
842 png_ptr->background_1.green = (png_uint_16)(pow(
843 (double)png_ptr->background.green / m, g) * m + .5);
844 png_ptr->background_1.blue = (png_uint_16)(pow(
845 (double)png_ptr->background.blue / m, g) * m + .5);
846 png_ptr->background.red = (png_uint_16)(pow(
847 (double)png_ptr->background.red / m, gs) * m + .5);
848 png_ptr->background.green = (png_uint_16)(pow(
849 (double)png_ptr->background.green / m, gs) * m + .5);
850 png_ptr->background.blue = (png_uint_16)(pow(
851 (double)png_ptr->background.blue / m, gs) * m + .5);
852 }
853 else
854 {
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600855 /* GRAY or GRAY ALPHA */
Guy Schalnat0d580581995-07-20 02:43:20 -0500856 png_ptr->background_1.gray = (png_uint_16)(pow(
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600857 (double)png_ptr->background.gray / m, g) * m + .5);
Guy Schalnat0d580581995-07-20 02:43:20 -0500858 png_ptr->background.gray = (png_uint_16)(pow(
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600859 (double)png_ptr->background.gray / m, gs) * m + .5);
Guy Schalnat0d580581995-07-20 02:43:20 -0500860 }
861 }
862 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500863 else
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600864 /* transformation does not include PNG_BACKGROUND */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500865#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500866 if (color_type == PNG_COLOR_TYPE_PALETTE)
867 {
868 int num_palette, i;
869 png_colorp palette;
870
871 palette = png_ptr->palette;
872 num_palette = png_ptr->num_palette;
873
874 for (i = 0; i < num_palette; i++)
875 {
876 palette[i].red = png_ptr->gamma_table[palette[i].red];
877 palette[i].green = png_ptr->gamma_table[palette[i].green];
878 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
879 }
880 }
881 }
882#if defined(PNG_READ_BACKGROUND_SUPPORTED)
883 else
884#endif
885#endif
886#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600887 /* No GAMMA transformation */
Guy Schalnate5a37791996-06-05 15:50:50 -0500888 if (png_ptr->transformations & PNG_BACKGROUND &&
889 color_type == PNG_COLOR_TYPE_PALETTE)
890 {
891 int i;
892 png_color back;
893 png_colorp palette;
894
895 palette = png_ptr->palette;
896 back.red = (png_byte)png_ptr->background.red;
897 back.green = (png_byte)png_ptr->background.green;
898 back.blue = (png_byte)png_ptr->background.blue;
899
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600900 for (i = 0; i < (int)png_ptr->num_trans; i++)
Guy Schalnate5a37791996-06-05 15:50:50 -0500901 {
902 if (png_ptr->trans[i] == 0)
903 {
904 palette[i] = back;
905 }
906 else if (png_ptr->trans[i] != 0xff)
907 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500908 png_composite(palette[i].red, palette[i].red,
909 png_ptr->trans[i], back.red);
910 png_composite(palette[i].green, palette[i].green,
911 png_ptr->trans[i], back.green);
912 png_composite(palette[i].blue, palette[i].blue,
913 png_ptr->trans[i], back.blue);
Guy Schalnate5a37791996-06-05 15:50:50 -0500914 }
915 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500916 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500917#endif
918
Guy Schalnat6d764711995-12-19 03:22:19 -0600919#if defined(PNG_READ_SHIFT_SUPPORTED)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500920 if ((png_ptr->transformations & PNG_SHIFT) &&
Guy Schalnat6d764711995-12-19 03:22:19 -0600921 color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500922 {
923 png_uint_16 i;
924 int sr, sg, sb;
925
926 sr = 8 - png_ptr->sig_bit.red;
927 if (sr < 0 || sr > 8)
928 sr = 0;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600929 sg = 8 - png_ptr->sig_bit.green;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500930 if (sg < 0 || sg > 8)
931 sg = 0;
932 sb = 8 - png_ptr->sig_bit.blue;
933 if (sb < 0 || sb > 8)
934 sb = 0;
935 for (i = 0; i < png_ptr->num_palette; i++)
936 {
937 png_ptr->palette[i].red >>= sr;
938 png_ptr->palette[i].green >>= sg;
939 png_ptr->palette[i].blue >>= sb;
940 }
941 }
942#endif
943}
944
Andreas Dilger47a0c421997-05-16 02:46:07 -0500945/* Modify the info structure to reflect the transformations. The
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600946 * info should be updated so a PNG file could be written with it,
947 * assuming the transformations result in valid PNG data.
948 */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500949void
Guy Schalnat6d764711995-12-19 03:22:19 -0600950png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500951{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500952 png_debug(1, "in png_read_transform_info\n");
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500953#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500954 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500955 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500956 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
957 {
958 if (png_ptr->num_trans)
959 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
960 else
961 info_ptr->color_type = PNG_COLOR_TYPE_RGB;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500962 info_ptr->bit_depth = 8;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500963 info_ptr->num_trans = 0;
964 }
965 else
966 {
967 if (png_ptr->num_trans)
968 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
969 if (info_ptr->bit_depth < 8)
970 info_ptr->bit_depth = 8;
971 info_ptr->num_trans = 0;
972 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500973 }
974#endif
975
976#if defined(PNG_READ_BACKGROUND_SUPPORTED)
977 if (png_ptr->transformations & PNG_BACKGROUND)
978 {
979 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
980 info_ptr->num_trans = 0;
981 info_ptr->background = png_ptr->background;
982 }
983#endif
984
985#if defined(PNG_READ_16_TO_8_SUPPORTED)
986 if ((png_ptr->transformations & PNG_16_TO_8) && info_ptr->bit_depth == 16)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600987 info_ptr->bit_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500988#endif
989
990#if defined(PNG_READ_DITHER_SUPPORTED)
991 if (png_ptr->transformations & PNG_DITHER)
992 {
993 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
994 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
995 png_ptr->palette_lookup && info_ptr->bit_depth == 8)
996 {
997 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
998 }
999 }
1000#endif
1001
1002#if defined(PNG_READ_PACK_SUPPORTED)
1003 if ((png_ptr->transformations & PNG_PACK) && info_ptr->bit_depth < 8)
1004 info_ptr->bit_depth = 8;
1005#endif
1006
1007#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1008 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1009 !(info_ptr->color_type & PNG_COLOR_MASK_COLOR))
1010 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1011#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001012
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001013 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001014 info_ptr->channels = 1;
1015 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1016 info_ptr->channels = 3;
1017 else
1018 info_ptr->channels = 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001019
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001020#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001021 if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
1022 info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1023 {
1024 info_ptr->channels--;
1025 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1026 }
1027#endif
1028
1029#if defined(PNG_READ_FILLER_SUPPORTED)
1030 if ((png_ptr->transformations & PNG_FILLER) &&
1031 info_ptr->color_type & PNG_COLOR_TYPE_RGB &&
1032 info_ptr->channels == 3)
1033 {
1034 info_ptr->channels = 4;
1035 }
1036#endif
1037
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001038 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1039 info_ptr->channels++;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001040 info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1041 info_ptr->bit_depth);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001042
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001043 info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05001044}
1045
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001046/* Transform the row. The order of transformations is significant,
1047 * and is very touchy. If you add a transformation, take care to
1048 * decide how it fits in with the other transformations here.
1049 */
Guy Schalnat0d580581995-07-20 02:43:20 -05001050void
Guy Schalnat6d764711995-12-19 03:22:19 -06001051png_do_read_transformations(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05001052{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001053 png_debug(1, "in png_do_read_transformations\n");
1054#if !defined(PNG_USELESS_TESTS_SUPPORTED)
1055 if (png_ptr->row_buf == NULL)
1056 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001057#if !defined(PNG_NO_STDIO)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001058 char msg[50];
1059
1060 sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
1061 png_ptr->pass);
1062 png_error(png_ptr, msg);
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001063#else
1064 png_error(png_ptr, "NULL row buffer");
1065#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001066 }
1067#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001068
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001069#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001070 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05001071 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001072 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1073 {
1074 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1075 png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1076 }
1077 else if (png_ptr->transformations & PNG_EXPAND)
1078 {
1079 if (png_ptr->num_trans)
1080 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1081 &(png_ptr->trans_values));
1082 else
1083 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1084 NULL);
1085 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001086 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001087#endif
1088
1089#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1090 if (png_ptr->transformations & PNG_STRIP_ALPHA)
1091 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1092 PNG_FLAG_FILLER_AFTER);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001093#endif
1094
1095#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001096 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1097 ((png_ptr->num_trans != 0 ) ||
1098 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
Guy Schalnat0d580581995-07-20 02:43:20 -05001099 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1100 &(png_ptr->trans_values), &(png_ptr->background),
1101 &(png_ptr->background_1),
1102 png_ptr->gamma_table, png_ptr->gamma_from_1,
1103 png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1104 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1105 png_ptr->gamma_shift);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001106#endif
1107
1108#if defined(PNG_READ_GAMMA_SUPPORTED)
1109 if ((png_ptr->transformations & PNG_GAMMA) &&
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001110 !(png_ptr->transformations & PNG_BACKGROUND) &&
1111 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
Guy Schalnat0d580581995-07-20 02:43:20 -05001112 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1113 png_ptr->gamma_table, png_ptr->gamma_16_table,
1114 png_ptr->gamma_shift);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001115#endif
1116
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001117#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001118 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1119 png_do_rgb_to_gray(&(png_ptr->row_info), png_ptr->row_buf + 1);
1120#endif
1121
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001122#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001123 if (png_ptr->transformations & PNG_16_TO_8)
1124 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001125#endif
1126
1127#if defined(PNG_READ_DITHER_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001128 if (png_ptr->transformations & PNG_DITHER)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001129 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001130 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1131 png_ptr->palette_lookup, png_ptr->dither_index);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001132 if(png_ptr->row_info.rowbytes == (png_uint_32)0)
1133 png_error(png_ptr, "png_do_dither returned rowbytes=0");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001134 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001135#endif
1136
1137#if defined(PNG_READ_INVERT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001138 if (png_ptr->transformations & PNG_INVERT_MONO)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001139 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001140#endif
1141
1142#if defined(PNG_READ_SHIFT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001143 if (png_ptr->transformations & PNG_SHIFT)
1144 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1145 &(png_ptr->shift));
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001146#endif
1147
1148#if defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001149 if (png_ptr->transformations & PNG_PACK)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001150 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001151#endif
1152
1153#if defined(PNG_READ_BGR_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001154 if (png_ptr->transformations & PNG_BGR)
1155 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001156#endif
1157
Andreas Dilger47a0c421997-05-16 02:46:07 -05001158#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1159 if (png_ptr->transformations & PNG_PACKSWAP)
1160 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1161#endif
1162
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001163#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001164 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1165 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001166#endif
1167
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001168#if defined(PNG_READ_FILLER_SUPPORTED)
1169 if (png_ptr->transformations & PNG_FILLER)
1170 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001171 (png_uint_32)png_ptr->filler, png_ptr->flags);
1172#endif
1173
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001174#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1175 if (png_ptr->transformations & PNG_INVERT_ALPHA)
1176 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1177#endif
1178
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001179#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1180 if (png_ptr->transformations & PNG_SWAP_ALPHA)
1181 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1182#endif
1183
Andreas Dilger47a0c421997-05-16 02:46:07 -05001184#if defined(PNG_READ_SWAP_SUPPORTED)
1185 if (png_ptr->transformations & PNG_SWAP_BYTES)
1186 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001187#endif
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001188
1189#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1190 if (png_ptr->transformations & PNG_USER_TRANSFORM)
1191 if(png_ptr->read_user_transform_fn != NULL)
1192 (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1193 (png_ptr, /* png_ptr */
1194 &(png_ptr->row_info), /* row_info: */
1195 /* png_uint_32 width; width of row */
1196 /* png_uint_32 rowbytes; number of bytes in row */
1197 /* png_byte color_type; color type of pixels */
1198 /* png_byte bit_depth; bit depth of samples */
1199 /* png_byte channels; number of channels (1-4) */
1200 /* png_byte pixel_depth; bits per pixel (depth*channels) */
1201 png_ptr->row_buf + 1); /* start of pixel data for row */
1202#endif
1203
Guy Schalnat0d580581995-07-20 02:43:20 -05001204}
1205
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001206#if defined(PNG_READ_PACK_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001207/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1208 * without changing the actual values. Thus, if you had a row with
1209 * a bit depth of 1, you would end up with bytes that only contained
1210 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1211 * png_do_shift() after this.
1212 */
Guy Schalnat0d580581995-07-20 02:43:20 -05001213void
Guy Schalnat6d764711995-12-19 03:22:19 -06001214png_do_unpack(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001215{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001216 png_debug(1, "in png_do_unpack\n");
1217#if defined(PNG_USELESS_TESTS_SUPPORTED)
1218 if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1219#else
1220 if (row_info->bit_depth < 8)
1221#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001222 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001223 png_uint_32 shift, i;
1224 png_bytep sp, dp;
1225
Guy Schalnat0d580581995-07-20 02:43:20 -05001226 switch (row_info->bit_depth)
1227 {
1228 case 1:
1229 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001230 sp = row + (png_size_t)((row_info->width - 1) >> 3);
1231 dp = row + (png_size_t)row_info->width - 1;
1232 shift = 7 - (int)((row_info->width + 7) & 7);
1233 for (i = 0; i < row_info->width; i++)
1234 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001235 *dp = (png_byte)((*sp >> shift) & 0x1);
Guy Schalnat0d580581995-07-20 02:43:20 -05001236 if (shift == 7)
1237 {
1238 shift = 0;
1239 sp--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001240 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001241 else
1242 shift++;
1243
1244 dp--;
1245 }
1246 break;
1247 }
1248 case 2:
1249 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001250
1251 sp = row + (png_size_t)((row_info->width - 1) >> 2);
1252 dp = row + (png_size_t)row_info->width - 1;
1253 shift = (int)((3 - ((row_info->width + 3) & 3)) << 1);
1254 for (i = 0; i < row_info->width; i++)
1255 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001256 *dp = (png_byte)((*sp >> shift) & 0x3);
Guy Schalnat0d580581995-07-20 02:43:20 -05001257 if (shift == 6)
1258 {
1259 shift = 0;
1260 sp--;
1261 }
1262 else
1263 shift += 2;
1264
1265 dp--;
1266 }
1267 break;
1268 }
1269 case 4:
1270 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001271 sp = row + (png_size_t)((row_info->width - 1) >> 1);
1272 dp = row + (png_size_t)row_info->width - 1;
Guy Schalnat6d764711995-12-19 03:22:19 -06001273 shift = (int)((1 - ((row_info->width + 1) & 1)) << 2);
Guy Schalnat0d580581995-07-20 02:43:20 -05001274 for (i = 0; i < row_info->width; i++)
1275 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001276 *dp = (png_byte)((*sp >> shift) & 0xf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001277 if (shift == 4)
1278 {
1279 shift = 0;
1280 sp--;
1281 }
1282 else
1283 shift = 4;
1284
1285 dp--;
1286 }
1287 break;
1288 }
1289 }
1290 row_info->bit_depth = 8;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001291 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001292 row_info->rowbytes = row_info->width * row_info->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -05001293 }
1294}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001295#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001296
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001297#if defined(PNG_READ_SHIFT_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001298/* Reverse the effects of png_do_shift. This routine merely shifts the
1299 * pixels back to their significant bits values. Thus, if you have
1300 * a row of bit depth 8, but only 5 are significant, this will shift
1301 * the values back to 0 through 31.
1302 */
Guy Schalnat0d580581995-07-20 02:43:20 -05001303void
Andreas Dilger47a0c421997-05-16 02:46:07 -05001304png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
Guy Schalnat0d580581995-07-20 02:43:20 -05001305{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001306 png_debug(1, "in png_do_unshift\n");
1307 if (
1308#if defined(PNG_USELESS_TESTS_SUPPORTED)
1309 row != NULL && row_info != NULL && sig_bits != NULL &&
1310#endif
1311 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05001312 {
1313 int shift[4];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001314 int channels, c;
1315 png_uint_16 value;
Guy Schalnat0d580581995-07-20 02:43:20 -05001316
1317 channels = 0;
1318 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1319 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001320 shift[channels++] = row_info->bit_depth - sig_bits->red;
1321 shift[channels++] = row_info->bit_depth - sig_bits->green;
1322 shift[channels++] = row_info->bit_depth - sig_bits->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05001323 }
1324 else
1325 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001326 shift[channels++] = row_info->bit_depth - sig_bits->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05001327 }
1328 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1329 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001330 shift[channels++] = row_info->bit_depth - sig_bits->alpha;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001331 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001332
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001333 value = 0;
Guy Schalnat0f716451995-11-28 11:22:13 -06001334
Andreas Dilger47a0c421997-05-16 02:46:07 -05001335 for (c = 0; c < channels; c++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001336 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001337 if (shift[c] <= 0)
1338 shift[c] = 0;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001339 else
1340 value = 1;
1341 }
Guy Schalnat0f716451995-11-28 11:22:13 -06001342
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001343 if (!value)
1344 return;
Guy Schalnat0f716451995-11-28 11:22:13 -06001345
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001346 switch (row_info->bit_depth)
Guy Schalnat0d580581995-07-20 02:43:20 -05001347 {
1348 case 2:
1349 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001350 png_bytep bp;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001351 png_uint_32 i;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001352
1353 for (bp = row, i = 0; i < row_info->rowbytes; i++, bp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001354 {
1355 *bp >>= 1;
1356 *bp &= 0x55;
1357 }
1358 break;
1359 }
1360 case 4:
1361 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001362 png_bytep bp;
1363 png_byte mask;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001364 png_uint_32 i;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001365
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001366 mask = (png_byte)(((int)0xf0 >> shift[0]) & (int)0xf0) |
1367 (png_byte)((int)0xf >> shift[0]);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001368 for (bp = row, i = 0; i < row_info->rowbytes; i++, bp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001369 {
1370 *bp >>= shift[0];
1371 *bp &= mask;
1372 }
1373 break;
1374 }
1375 case 8:
1376 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001377 png_bytep bp;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001378 png_uint_32 i;
Guy Schalnat0d580581995-07-20 02:43:20 -05001379
Andreas Dilger47a0c421997-05-16 02:46:07 -05001380 for (bp = row, i = 0; i < row_info->width; i++)
1381 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001382 for (c = 0; c < (int)row_info->channels; c++, bp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001383 {
1384 *bp >>= shift[c];
1385 }
1386 }
1387 break;
1388 }
1389 case 16:
1390 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001391 png_bytep bp;
1392 png_size_t i;
Guy Schalnat0d580581995-07-20 02:43:20 -05001393
Andreas Dilger47a0c421997-05-16 02:46:07 -05001394 for (bp = row, i = 0; i < row_info->width; i++)
1395 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001396 for (c = 0; c < (int)row_info->channels; c++, bp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05001397 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001398 value = (png_uint_16)((*bp << 8) + *(bp + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05001399 value >>= shift[c];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001400 *bp = (png_byte)(value >> 8);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001401 *(bp + 1) = (png_byte)(value & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05001402 }
1403 }
1404 break;
1405 }
1406 }
1407 }
1408}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001409#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001410
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001411#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001412/* chop rows of bit depth 16 down to 8 */
1413void
Guy Schalnat6d764711995-12-19 03:22:19 -06001414png_do_chop(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001415{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001416 png_debug(1, "in png_do_chop\n");
1417#if defined(PNG_USELESS_TESTS_SUPPORTED)
1418 if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1419#else
1420 if (row_info->bit_depth == 16)
1421#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001422 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001423 png_bytep sp, dp;
1424 png_uint_32 i;
1425
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001426 sp = row;
1427 dp = row;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001428 for (i = 0; i < row_info->width * row_info->channels; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001429 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001430#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
1431 /* This does a more accurate scaling of the 16-bit color
1432 * value, rather than a simple low-byte truncation.
1433 *
1434 * What the ideal calculation should be:
1435 *dp = (((((png_uint_32)(*sp) << 8) |
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001436 (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001437
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06001438
1439 * GRR: no, I think this is what it really should be:
1440 *dp = (((((png_uint_32)(*sp) << 8) |
1441 (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1442
1443 * GRR: here's the exact calculation with shifts:
1444 temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1445 *dp = (temp - (temp >> 8)) >> 8;
1446
1447
Andreas Dilger47a0c421997-05-16 02:46:07 -05001448 * Approximate calculation with shift/add instead of multiply/divide:
1449 *dp = ((((png_uint_32)(*sp) << 8) |
1450 (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1451
1452 * What we actually do to avoid extra shifting and conversion: */
1453 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1454#else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001455 *dp = *sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001456#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001457 }
1458 row_info->bit_depth = 8;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001459 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001460 row_info->rowbytes = row_info->width * row_info->channels;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001461 }
1462}
1463#endif
1464
1465#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1466void
1467png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1468{
1469 png_debug(1, "in png_do_read_swap_alpha\n");
1470#if defined(PNG_USELESS_TESTS_SUPPORTED)
1471 if (row != NULL && row_info != NULL)
1472#endif
1473 {
1474 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1475 {
1476 /* This converts from RGBA to ARGB */
1477 if (row_info->bit_depth == 8)
1478 {
1479 png_bytep sp, dp;
1480 png_byte save;
1481 png_uint_32 i;
1482
1483 for (i = 0, sp = dp = row + row_info->rowbytes;
1484 i < row_info->width; i++)
1485 {
1486 save = *(--sp);
1487 *(--dp) = *(--sp);
1488 *(--dp) = *(--sp);
1489 *(--dp) = *(--sp);
1490 *(--dp) = save;
1491 }
1492 }
1493 /* This converts from RRGGBBAA to AARRGGBB */
1494 else
1495 {
1496 png_bytep sp, dp;
1497 png_byte save[2];
1498 png_uint_32 i;
1499
1500 for (i = 0, sp = dp = row + row_info->rowbytes;
1501 i < row_info->width; i++)
1502 {
1503 save[0] = *(--sp);
1504 save[1] = *(--sp);
1505 *(--dp) = *(--sp);
1506 *(--dp) = *(--sp);
1507 *(--dp) = *(--sp);
1508 *(--dp) = *(--sp);
1509 *(--dp) = *(--sp);
1510 *(--dp) = *(--sp);
1511 *(--dp) = save[0];
1512 *(--dp) = save[1];
1513 }
1514 }
1515 }
1516 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1517 {
1518 /* This converts from GA to AG */
1519 if (row_info->bit_depth == 8)
1520 {
1521 png_bytep sp, dp;
1522 png_byte save;
1523 png_uint_32 i;
1524
1525 for (i = 0, sp = dp = row + row_info->rowbytes;
1526 i < row_info->width; i++)
1527 {
1528 save = *(--sp);
1529 *(--dp) = *(--sp);
1530 *(--dp) = save;
1531 }
1532 }
1533 /* This converts from GGAA to AAGG */
1534 else
1535 {
1536 png_bytep sp, dp;
1537 png_byte save[2];
1538 png_uint_32 i;
1539
1540 for (i = 0, sp = dp = row + row_info->rowbytes;
1541 i < row_info->width; i++)
1542 {
1543 save[0] = *(--sp);
1544 save[1] = *(--sp);
1545 *(--dp) = *(--sp);
1546 *(--dp) = *(--sp);
1547 *(--dp) = save[0];
1548 *(--dp) = save[1];
1549 }
1550 }
1551 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001552 }
1553}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001554#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001555
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001556#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1557void
1558png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1559{
1560 png_debug(1, "in png_do_read_invert_alpha\n");
1561#if defined(PNG_USELESS_TESTS_SUPPORTED)
1562 if (row != NULL && row_info != NULL)
1563#endif
1564 {
1565 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1566 {
1567 /* This inverts the alpha channel in RGBA */
1568 if (row_info->bit_depth == 8)
1569 {
1570 png_bytep sp, dp;
1571 png_uint_32 i;
1572
1573 for (i = 0, sp = dp = row + row_info->rowbytes;
1574 i < row_info->width; i++)
1575 {
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001576 *(--dp) = 255 - *(--sp);
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001577 *(--dp) = *(--sp);
1578 *(--dp) = *(--sp);
1579 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001580 }
1581 }
1582 /* This inverts the alpha channel in RRGGBBAA */
1583 else
1584 {
1585 png_bytep sp, dp;
1586 png_uint_32 i;
1587
1588 for (i = 0, sp = dp = row + row_info->rowbytes;
1589 i < row_info->width; i++)
1590 {
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001591 *(--dp) = 255 - *(--sp);
1592 *(--dp) = 255 - *(--sp);
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001593 *(--dp) = *(--sp);
1594 *(--dp) = *(--sp);
1595 *(--dp) = *(--sp);
1596 *(--dp) = *(--sp);
1597 *(--dp) = *(--sp);
1598 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001599 }
1600 }
1601 }
1602 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1603 {
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001604 /* This inverts the alpha channel in GA */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001605 if (row_info->bit_depth == 8)
1606 {
1607 png_bytep sp, dp;
1608 png_uint_32 i;
1609
1610 for (i = 0, sp = dp = row + row_info->rowbytes;
1611 i < row_info->width; i++)
1612 {
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001613 *(--dp) = 255 - *(--sp);
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001614 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001615 }
1616 }
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001617 /* This inverts the alpha channel in GGAA */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001618 else
1619 {
1620 png_bytep sp, dp;
1621 png_uint_32 i;
1622
1623 for (i = 0, sp = dp = row + row_info->rowbytes;
1624 i < row_info->width; i++)
1625 {
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001626 *(--dp) = 255 - *(--sp);
1627 *(--dp) = 255 - *(--sp);
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001628 *(--dp) = *(--sp);
1629 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001630 }
1631 }
1632 }
1633 }
1634}
1635#endif
1636
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001637#if defined(PNG_READ_FILLER_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001638/* Add filler channel if we have RGB color */
Guy Schalnat0d580581995-07-20 02:43:20 -05001639void
Guy Schalnat6d764711995-12-19 03:22:19 -06001640png_do_read_filler(png_row_infop row_info, png_bytep row,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001641 png_uint_32 filler, png_uint_32 flags)
Guy Schalnat0d580581995-07-20 02:43:20 -05001642{
Guy Schalnat6d764711995-12-19 03:22:19 -06001643 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001644 png_uint_32 i;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001645
1646 png_debug(1, "in png_do_read_filler\n");
1647 if (
1648#if defined(PNG_USELESS_TESTS_SUPPORTED)
1649 row != NULL && row_info != NULL &&
1650#endif
1651 row_info->color_type == PNG_COLOR_TYPE_RGB && row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05001652 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001653 /* This changes the data from RGB to RGBX */
Guy Schalnate5a37791996-06-05 15:50:50 -05001654 if (flags & PNG_FLAG_FILLER_AFTER)
Guy Schalnat0d580581995-07-20 02:43:20 -05001655 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001656 for (i = 1, sp = row + (png_size_t)row_info->width * 3,
1657 dp = row + (png_size_t)row_info->width * 4;
1658 i < row_info->width;
1659 i++)
1660 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001661 *(--dp) = (png_byte)filler;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001662 *(--dp) = *(--sp);
1663 *(--dp) = *(--sp);
1664 *(--dp) = *(--sp);
1665 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001666 *(--dp) = (png_byte)filler;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001667 row_info->channels = 4;
1668 row_info->pixel_depth = 32;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001669 row_info->rowbytes = row_info->width * 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05001670 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001671 /* This changes the data from RGB to XRGB */
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001672 else
1673 {
1674 for (i = 0, sp = row + (png_size_t)row_info->width * 3,
1675 dp = row + (png_size_t)row_info->width * 4;
1676 i < row_info->width;
1677 i++)
1678 {
1679 *(--dp) = *(--sp);
1680 *(--dp) = *(--sp);
1681 *(--dp) = *(--sp);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001682 *(--dp) = (png_byte)filler;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001683 }
1684 row_info->channels = 4;
1685 row_info->pixel_depth = 32;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001686 row_info->rowbytes = row_info->width * 4;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001687 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001688 }
1689}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001690#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001691
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001692#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001693/* expand grayscale files to RGB, with or without alpha */
Guy Schalnat0d580581995-07-20 02:43:20 -05001694void
Guy Schalnat6d764711995-12-19 03:22:19 -06001695png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001696{
Guy Schalnat6d764711995-12-19 03:22:19 -06001697 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001698 png_uint_32 i;
Guy Schalnat6d764711995-12-19 03:22:19 -06001699
Andreas Dilger47a0c421997-05-16 02:46:07 -05001700 png_debug(1, "in png_do_gray_to_rgb\n");
1701 if (row_info->bit_depth >= 8 &&
1702#if defined(PNG_USELESS_TESTS_SUPPORTED)
1703 row != NULL && row_info != NULL &&
1704#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001705 !(row_info->color_type & PNG_COLOR_MASK_COLOR))
1706 {
1707 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
1708 {
1709 if (row_info->bit_depth == 8)
1710 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001711 for (i = 0, sp = row + (png_size_t)row_info->width - 1,
1712 dp = row + (png_size_t)row_info->width * 3 - 1;
1713 i < row_info->width;
1714 i++)
1715 {
1716 *(dp--) = *sp;
1717 *(dp--) = *sp;
1718 *(dp--) = *sp;
1719 sp--;
1720 }
1721 }
1722 else
1723 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001724 for (i = 0, sp = row + (png_size_t)row_info->width * 2 - 1,
1725 dp = row + (png_size_t)row_info->width * 6 - 1;
1726 i < row_info->width;
1727 i++)
1728 {
1729 *(dp--) = *sp;
1730 *(dp--) = *(sp - 1);
1731 *(dp--) = *sp;
1732 *(dp--) = *(sp - 1);
1733 *(dp--) = *sp;
1734 *(dp--) = *(sp - 1);
1735 sp--;
1736 sp--;
1737 }
1738 }
1739 }
1740 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1741 {
1742 if (row_info->bit_depth == 8)
1743 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001744 for (i = 0, sp = row + (png_size_t)row_info->width * 2 - 1,
1745 dp = row + (png_size_t)row_info->width * 4 - 1;
1746 i < row_info->width;
1747 i++)
1748 {
1749 *(dp--) = *(sp--);
1750 *(dp--) = *sp;
1751 *(dp--) = *sp;
1752 *(dp--) = *sp;
1753 sp--;
1754 }
1755 }
1756 else
1757 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001758 for (i = 0, sp = row + (png_size_t)row_info->width * 4 - 1,
1759 dp = row + (png_size_t)row_info->width * 8 - 1;
1760 i < row_info->width;
1761 i++)
1762 {
1763 *(dp--) = *(sp--);
1764 *(dp--) = *(sp--);
1765 *(dp--) = *sp;
1766 *(dp--) = *(sp - 1);
1767 *(dp--) = *sp;
1768 *(dp--) = *(sp - 1);
1769 *(dp--) = *sp;
1770 *(dp--) = *(sp - 1);
1771 sp--;
1772 sp--;
1773 }
1774 }
1775 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001776 row_info->channels += (png_byte)2;
Guy Schalnat0d580581995-07-20 02:43:20 -05001777 row_info->color_type |= PNG_COLOR_MASK_COLOR;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001778 row_info->pixel_depth = (png_byte)(row_info->channels *
1779 row_info->bit_depth);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001780 row_info->rowbytes = ((row_info->width *
Guy Schalnat0d580581995-07-20 02:43:20 -05001781 row_info->pixel_depth + 7) >> 3);
1782 }
1783}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001784#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001785
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001786/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
1787 * large of png_color. This lets grayscale images be treated as
1788 * paletted. Most useful for gamma correction and simplification
1789 * of code.
1790 */
Guy Schalnat0d580581995-07-20 02:43:20 -05001791void
Guy Schalnat6d764711995-12-19 03:22:19 -06001792png_build_grayscale_palette(int bit_depth, png_colorp palette)
Guy Schalnat0d580581995-07-20 02:43:20 -05001793{
1794 int num_palette;
1795 int color_inc;
1796 int i;
1797 int v;
1798
Andreas Dilger47a0c421997-05-16 02:46:07 -05001799 png_debug(1, "in png_do_build_grayscale_palette\n");
1800 if (palette == NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05001801 return;
1802
1803 switch (bit_depth)
1804 {
1805 case 1:
1806 num_palette = 2;
1807 color_inc = 0xff;
1808 break;
1809 case 2:
1810 num_palette = 4;
1811 color_inc = 0x55;
1812 break;
1813 case 4:
1814 num_palette = 16;
1815 color_inc = 0x11;
1816 break;
1817 case 8:
1818 num_palette = 256;
1819 color_inc = 1;
1820 break;
1821 default:
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001822 num_palette = 0;
Guy Schalnat69b14481996-01-10 02:56:49 -06001823 color_inc = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05001824 break;
1825 }
1826
1827 for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
1828 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001829 palette[i].red = (png_byte)v;
1830 palette[i].green = (png_byte)v;
1831 palette[i].blue = (png_byte)v;
Guy Schalnat0d580581995-07-20 02:43:20 -05001832 }
1833}
1834
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001835/* This function is currently unused. Do we really need it? */
1836#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001837void
Guy Schalnat6d764711995-12-19 03:22:19 -06001838png_correct_palette(png_structp png_ptr, png_colorp palette,
Guy Schalnat0d580581995-07-20 02:43:20 -05001839 int num_palette)
1840{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001841 png_debug(1, "in png_correct_palette\n");
Guy Schalnate5a37791996-06-05 15:50:50 -05001842#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001843 if ((png_ptr->transformations & (PNG_GAMMA)) &&
1844 (png_ptr->transformations & (PNG_BACKGROUND)))
1845 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001846 png_color back, back_1;
Guy Schalnat0d580581995-07-20 02:43:20 -05001847
Andreas Dilger47a0c421997-05-16 02:46:07 -05001848 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
1849 {
Guy Schalnate5a37791996-06-05 15:50:50 -05001850 back.red = png_ptr->gamma_table[png_ptr->background.red];
1851 back.green = png_ptr->gamma_table[png_ptr->background.green];
1852 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
Guy Schalnat0d580581995-07-20 02:43:20 -05001853
Guy Schalnate5a37791996-06-05 15:50:50 -05001854 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
1855 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
1856 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001857 }
1858 else
1859 {
1860 double g;
Guy Schalnat0d580581995-07-20 02:43:20 -05001861
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001862 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001863
1864 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
1865 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
Guy Schalnat0d580581995-07-20 02:43:20 -05001866 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001867 back.red = png_ptr->background.red;
1868 back.green = png_ptr->background.green;
1869 back.blue = png_ptr->background.blue;
1870 }
1871 else
1872 {
1873 back.red =
1874 (png_byte)(pow((double)png_ptr->background.red/255, g) *
1875 255.0 + 0.5);
1876 back.green =
1877 (png_byte)(pow((double)png_ptr->background.green/255, g) *
1878 255.0 + 0.5);
1879 back.blue =
1880 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
1881 255.0 + 0.5);
1882 }
1883
1884 g = 1.0 / png_ptr->background_gamma;
1885
1886 back_1.red =
1887 (png_byte)(pow((double)png_ptr->background.red/255, g) *
1888 255.0 + 0.5);
1889 back_1.green =
1890 (png_byte)(pow((double)png_ptr->background.green/255, g) *
1891 255.0 + 0.5);
1892 back_1.blue =
1893 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
1894 255.0 + 0.5);
1895 }
1896
1897 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1898 {
1899 png_uint_32 i;
1900
1901 for (i = 0; i < (png_uint_32)num_palette; i++)
1902 {
1903 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -05001904 {
1905 palette[i] = back;
1906 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001907 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05001908 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001909 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05001910
1911 v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001912 png_composite(w, v, png_ptr->trans[i], back_1.red);
1913 palette[i].red = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05001914
1915 v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001916 png_composite(w, v, png_ptr->trans[i], back_1.green);
1917 palette[i].green = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05001918
1919 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001920 png_composite(w, v, png_ptr->trans[i], back_1.blue);
1921 palette[i].blue = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05001922 }
1923 else
1924 {
1925 palette[i].red = png_ptr->gamma_table[palette[i].red];
1926 palette[i].green = png_ptr->gamma_table[palette[i].green];
1927 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1928 }
1929 }
1930 }
1931 else
1932 {
Guy Schalnate5a37791996-06-05 15:50:50 -05001933 int i;
Guy Schalnat0d580581995-07-20 02:43:20 -05001934
1935 for (i = 0; i < num_palette; i++)
1936 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001937 if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05001938 {
Guy Schalnate5a37791996-06-05 15:50:50 -05001939 palette[i] = back;
Guy Schalnat0d580581995-07-20 02:43:20 -05001940 }
1941 else
1942 {
1943 palette[i].red = png_ptr->gamma_table[palette[i].red];
1944 palette[i].green = png_ptr->gamma_table[palette[i].green];
1945 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1946 }
1947 }
1948 }
1949 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001950 else
1951#endif
1952#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001953 if (png_ptr->transformations & PNG_GAMMA)
Guy Schalnat0d580581995-07-20 02:43:20 -05001954 {
1955 int i;
1956
1957 for (i = 0; i < num_palette; i++)
1958 {
1959 palette[i].red = png_ptr->gamma_table[palette[i].red];
1960 palette[i].green = png_ptr->gamma_table[palette[i].green];
1961 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
1962 }
1963 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001964#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1965 else
1966#endif
1967#endif
1968#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001969 if (png_ptr->transformations & PNG_BACKGROUND)
Guy Schalnat0d580581995-07-20 02:43:20 -05001970 {
Guy Schalnate5a37791996-06-05 15:50:50 -05001971 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05001972 {
Guy Schalnate5a37791996-06-05 15:50:50 -05001973 png_color back;
Guy Schalnat0d580581995-07-20 02:43:20 -05001974
Guy Schalnate5a37791996-06-05 15:50:50 -05001975 back.red = (png_byte)png_ptr->background.red;
1976 back.green = (png_byte)png_ptr->background.green;
1977 back.blue = (png_byte)png_ptr->background.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05001978
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001979 for (i = 0; i < (int)png_ptr->num_trans; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001980 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001981 if (png_ptr->trans[i] == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -05001982 {
Guy Schalnate5a37791996-06-05 15:50:50 -05001983 palette[i].red = back.red;
1984 palette[i].green = back.green;
1985 palette[i].blue = back.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05001986 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001987 else if (png_ptr->trans[i] != 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05001988 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001989 png_composite(palette[i].red, png_ptr->palette[i].red,
1990 png_ptr->trans[i], back.red);
1991 png_composite(palette[i].green, png_ptr->palette[i].green,
1992 png_ptr->trans[i], back.green);
1993 png_composite(palette[i].blue, png_ptr->palette[i].blue,
1994 png_ptr->trans[i], back.blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05001995 }
1996 }
1997 }
1998 else /* assume grayscale palette (what else could it be?) */
1999 {
2000 int i;
2001
2002 for (i = 0; i < num_palette; i++)
2003 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002004 if (i == (png_byte)png_ptr->trans_values.gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002005 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002006 palette[i].red = (png_byte)png_ptr->background.red;
2007 palette[i].green = (png_byte)png_ptr->background.green;
2008 palette[i].blue = (png_byte)png_ptr->background.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002009 }
2010 }
2011 }
2012 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002013#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002014}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002015#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002016
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002017#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002018/* Replace any alpha or transparency with the supplied background color.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002019 * "background" is already in the screen gamma, while "background_1" is
2020 * at a gamma of 1.0. Paletted files have already been taken care of.
2021 */
Guy Schalnat0d580581995-07-20 02:43:20 -05002022void
Guy Schalnat6d764711995-12-19 03:22:19 -06002023png_do_background(png_row_infop row_info, png_bytep row,
2024 png_color_16p trans_values, png_color_16p background,
2025 png_color_16p background_1,
2026 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002027 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2028 png_uint_16pp gamma_16_to_1, int gamma_shift)
Guy Schalnat0d580581995-07-20 02:43:20 -05002029{
Guy Schalnat6d764711995-12-19 03:22:19 -06002030 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002031 png_uint_32 i;
2032 int shift;
Guy Schalnate5a37791996-06-05 15:50:50 -05002033
Andreas Dilger47a0c421997-05-16 02:46:07 -05002034 png_debug(1, "in png_do_background\n");
2035 if (background != NULL &&
2036#if defined(PNG_USELESS_TESTS_SUPPORTED)
2037 row != NULL && row_info != NULL &&
2038#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002039 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
Andreas Dilger47a0c421997-05-16 02:46:07 -05002040 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
Guy Schalnat0d580581995-07-20 02:43:20 -05002041 {
2042 switch (row_info->color_type)
2043 {
2044 case PNG_COLOR_TYPE_GRAY:
2045 {
2046 switch (row_info->bit_depth)
2047 {
2048 case 1:
2049 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002050 sp = row;
2051 shift = 7;
2052 for (i = 0; i < row_info->width; i++)
2053 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002054 if ((png_uint_16)((*sp >> shift) & 0x1)
2055 == trans_values->gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002056 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002057 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2058 *sp |= (png_byte)(background->gray << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05002059 }
2060 if (!shift)
2061 {
2062 shift = 7;
2063 sp++;
2064 }
2065 else
2066 shift--;
2067 }
2068 break;
2069 }
2070 case 2:
2071 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002072 sp = row;
2073 shift = 6;
2074 for (i = 0; i < row_info->width; i++)
2075 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002076 if ((png_uint_16)((*sp >> shift) & 0x3)
2077 == trans_values->gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002078 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002079 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2080 *sp |= (png_byte)(background->gray << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05002081 }
2082 if (!shift)
2083 {
2084 shift = 6;
2085 sp++;
2086 }
2087 else
2088 shift -= 2;
2089 }
2090 break;
2091 }
2092 case 4:
2093 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002094 sp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -05002095 shift = 4;
2096 for (i = 0; i < row_info->width; i++)
2097 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002098 if ((png_uint_16)((*sp >> shift) & 0xf)
2099 == trans_values->gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002100 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002101 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2102 *sp |= (png_byte)(background->gray << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05002103 }
2104 if (!shift)
2105 {
2106 shift = 4;
2107 sp++;
2108 }
2109 else
2110 shift -= 4;
2111 }
2112 break;
2113 }
2114 case 8:
2115 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002116#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002117 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002118 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002119 for (i = 0, sp = row; i < row_info->width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002120 {
2121 if (*sp == trans_values->gray)
2122 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002123 *sp = (png_byte)background->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05002124 }
2125 else
2126 {
2127 *sp = gamma_table[*sp];
2128 }
2129 }
2130 }
2131 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002132#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002133 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002134 for (i = 0, sp = row; i < row_info->width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002135 {
2136 if (*sp == trans_values->gray)
2137 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002138 *sp = (png_byte)background->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05002139 }
2140 }
2141 }
2142 break;
2143 }
2144 case 16:
2145 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002146#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002147 if (gamma_16 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002148 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002149 for (i = 0, sp = row; i < row_info->width; i++, sp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002150 {
2151 png_uint_16 v;
2152
Andreas Dilger47a0c421997-05-16 02:46:07 -05002153 v = ((png_uint_16)(*sp) << 8) + *(sp + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05002154 if (v == trans_values->gray)
2155 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002156 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002157 *sp = (png_byte)((background->gray >> 8) & 0xff);
2158 *(sp + 1) = (png_byte)(background->gray & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002159 }
2160 else
2161 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002162 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002163 *sp = (png_byte)((v >> 8) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002164 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002165 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002166 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002167 }
2168 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002169#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002170 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002171 for (i = 0, sp = row; i < row_info->width; i++, sp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002172 {
2173 png_uint_16 v;
2174
Andreas Dilger47a0c421997-05-16 02:46:07 -05002175 v = ((png_uint_16)(*sp) << 8) + *(sp + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05002176 if (v == trans_values->gray)
2177 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002178 *sp = (png_byte)((background->gray >> 8) & 0xff);
2179 *(sp + 1) = (png_byte)(background->gray & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002180 }
2181 }
2182 }
2183 break;
2184 }
2185 }
2186 break;
2187 }
2188 case PNG_COLOR_TYPE_RGB:
2189 {
2190 if (row_info->bit_depth == 8)
2191 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002192#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002193 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002194 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002195 for (i = 0, sp = row; i < row_info->width; i++, sp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002196 {
2197 if (*sp == trans_values->red &&
2198 *(sp + 1) == trans_values->green &&
2199 *(sp + 2) == trans_values->blue)
2200 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002201 *sp = (png_byte)background->red;
2202 *(sp + 1) = (png_byte)background->green;
2203 *(sp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002204 }
2205 else
2206 {
2207 *sp = gamma_table[*sp];
2208 *(sp + 1) = gamma_table[*(sp + 1)];
2209 *(sp + 2) = gamma_table[*(sp + 2)];
2210 }
2211 }
2212 }
2213 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002214#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002215 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002216 for (i = 0, sp = row; i < row_info->width; i++, sp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002217 {
2218 if (*sp == trans_values->red &&
2219 *(sp + 1) == trans_values->green &&
2220 *(sp + 2) == trans_values->blue)
2221 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002222 *sp = (png_byte)background->red;
2223 *(sp + 1) = (png_byte)background->green;
2224 *(sp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002225 }
2226 }
2227 }
2228 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002229 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002230 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002231#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002232 if (gamma_16 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002233 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002234 for (i = 0, sp = row; i < row_info->width; i++, sp += 6)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002235 {
2236 png_uint_16 r, g, b;
Guy Schalnat0d580581995-07-20 02:43:20 -05002237
Andreas Dilger47a0c421997-05-16 02:46:07 -05002238 r = ((png_uint_16)(*sp) << 8) + *(sp + 1);
2239 g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
2240 b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5);
2241 if (r == trans_values->red && g == trans_values->green &&
Guy Schalnat0d580581995-07-20 02:43:20 -05002242 b == trans_values->blue)
2243 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002244 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002245 *sp = (png_byte)((background->red >> 8) & 0xff);
2246 *(sp + 1) = (png_byte)(background->red & 0xff);
2247 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2248 *(sp + 3) = (png_byte)(background->green & 0xff);
2249 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2250 *(sp + 5) = (png_byte)(background->blue & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002251 }
2252 else
2253 {
2254 png_uint_16 v;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002255 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002256 *sp = (png_byte)((v >> 8) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002257 *(sp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002258 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002259 *(sp + 2) = (png_byte)((v >> 8) & 0xff);
2260 *(sp + 3) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002261 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002262 *(sp + 4) = (png_byte)((v >> 8) & 0xff);
2263 *(sp + 5) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002264 }
2265 }
2266 }
2267 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002268#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002269 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002270 for (i = 0, sp = row; i < row_info->width; i++, sp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05002271 {
2272 png_uint_16 r, g, b;
2273
Andreas Dilger47a0c421997-05-16 02:46:07 -05002274 r = ((png_uint_16)(*sp) << 8) + *(sp + 1);
2275 g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
2276 b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5);
2277 if (r == trans_values->red && g == trans_values->green &&
Guy Schalnat0d580581995-07-20 02:43:20 -05002278 b == trans_values->blue)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002279 {
2280 *sp = (png_byte)((background->red >> 8) & 0xff);
2281 *(sp + 1) = (png_byte)(background->red & 0xff);
2282 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2283 *(sp + 3) = (png_byte)(background->green & 0xff);
2284 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2285 *(sp + 5) = (png_byte)(background->blue & 0xff);
2286 }
2287 }
2288 }
2289 }
2290 break;
2291 }
2292 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -05002293 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002294 if (row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05002295 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002296#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002297 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2298 gamma_table != NULL)
2299 {
2300 for (i = 0, sp = row, dp = row;
2301 i < row_info->width; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002302 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002303 png_uint_16 a;
2304
2305 a = *(sp + 1);
2306 if (a == 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002307 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002308 *dp = gamma_table[*sp];
2309 }
2310 else if (a == 0)
2311 {
2312 /* background is already in screen gamma */
2313 *dp = (png_byte)background->gray;
2314 }
2315 else
2316 {
2317 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002318
Andreas Dilger47a0c421997-05-16 02:46:07 -05002319 v = gamma_to_1[*sp];
2320 png_composite(w, v, a, background_1->gray);
2321 *dp = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002322 }
2323 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002324 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002325 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002326#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05002327 {
2328 for (i = 0, sp = row, dp = row;
2329 i < row_info->width; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002330 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002331 png_byte a;
2332
2333 a = *(sp + 1);
2334 if (a == 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002335 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002336 *dp = *sp;
2337 }
2338 else if (a == 0)
2339 {
2340 *dp = (png_byte)background->gray;
2341 }
2342 else
2343 {
2344 png_composite(*dp, *sp, a, background_1->gray);
Guy Schalnat0d580581995-07-20 02:43:20 -05002345 }
2346 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002347 }
2348 }
2349 else /* if (png_ptr->bit_depth == 16) */
2350 {
2351#if defined(PNG_READ_GAMMA_SUPPORTED)
2352 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
2353 gamma_16_to_1 != NULL)
2354 {
2355 for (i = 0, sp = row, dp = row;
2356 i < row_info->width; i++, sp += 4, dp += 2)
2357 {
2358 png_uint_16 a;
2359
2360 a = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
2361 if (a == (png_uint_16)0xffff)
2362 {
2363 png_uint_16 v;
2364
2365 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2366 *dp = (png_byte)((v >> 8) & 0xff);
2367 *(dp + 1) = (png_byte)(v & 0xff);
2368 }
2369 else if (a == 0)
2370 {
2371 /* background is already in screen gamma */
2372 *dp = (png_byte)((background->gray >> 8) & 0xff);
2373 *(dp + 1) = (png_byte)(background->gray & 0xff);
2374 }
2375 else
2376 {
2377 png_uint_16 g, v, w;
2378
2379 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
2380 png_composite_16(v, g, a, background_1->gray);
2381 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
2382 *dp = (png_byte)((w >> 8) & 0xff);
2383 *(dp + 1) = (png_byte)(w & 0xff);
2384 }
2385 }
2386 }
2387 else
2388#endif
2389 {
2390 for (i = 0, sp = row, dp = row;
2391 i < row_info->width; i++, sp += 4, dp += 2)
2392 {
2393 png_uint_16 a;
2394
2395 a = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
2396 if (a == (png_uint_16)0xffff)
2397 {
2398 png_memcpy(dp, sp, 2);
2399 }
2400 else if (a == 0)
2401 {
2402 *dp = (png_byte)((background->gray >> 8) & 0xff);
2403 *(dp + 1) = (png_byte)(background->gray & 0xff);
2404 }
2405 else
2406 {
2407 png_uint_16 g, v;
2408
2409 g = ((png_uint_16)(*sp) << 8) + *(sp + 1);
2410 png_composite_16(v, g, a, background_1->gray);
2411 *dp = (png_byte)((v >> 8) & 0xff);
2412 *(dp + 1) = (png_byte)(v & 0xff);
2413 }
2414 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002415 }
2416 }
2417 break;
2418 }
2419 case PNG_COLOR_TYPE_RGB_ALPHA:
2420 {
2421 if (row_info->bit_depth == 8)
2422 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002423#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002424 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2425 gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002426 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002427 for (i = 0, sp = row, dp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -05002428 i < row_info->width; i++, sp += 4, dp += 3)
2429 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002430 png_byte a;
Guy Schalnat0d580581995-07-20 02:43:20 -05002431
2432 a = *(sp + 3);
2433 if (a == 0xff)
2434 {
2435 *dp = gamma_table[*sp];
2436 *(dp + 1) = gamma_table[*(sp + 1)];
2437 *(dp + 2) = gamma_table[*(sp + 2)];
2438 }
2439 else if (a == 0)
2440 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002441 /* background is already in screen gamma */
2442 *dp = (png_byte)background->red;
2443 *(dp + 1) = (png_byte)background->green;
2444 *(dp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002445 }
2446 else
2447 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002448 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002449
2450 v = gamma_to_1[*sp];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002451 png_composite(w, v, a, background_1->red);
2452 *dp = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002453 v = gamma_to_1[*(sp + 1)];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002454 png_composite(w, v, a, background_1->green);
2455 *(dp + 1) = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002456 v = gamma_to_1[*(sp + 2)];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002457 png_composite(w, v, a, background_1->blue);
2458 *(dp + 2) = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002459 }
2460 }
2461 }
2462 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002463#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002464 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002465 for (i = 0, sp = row, dp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -05002466 i < row_info->width; i++, sp += 4, dp += 3)
2467 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002468 png_byte a;
Guy Schalnat0d580581995-07-20 02:43:20 -05002469
2470 a = *(sp + 3);
2471 if (a == 0xff)
2472 {
2473 *dp = *sp;
2474 *(dp + 1) = *(sp + 1);
2475 *(dp + 2) = *(sp + 2);
2476 }
2477 else if (a == 0)
2478 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002479 *dp = (png_byte)background->red;
2480 *(dp + 1) = (png_byte)background->green;
2481 *(dp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002482 }
2483 else
2484 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002485 png_composite(*dp, *sp, a, background->red);
2486 png_composite(*(dp + 1), *(sp + 1), a,
2487 background->green);
2488 png_composite(*(dp + 2), *(sp + 2), a,
2489 background->blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05002490 }
2491 }
2492 }
2493 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002494 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002495 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002496#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002497 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
2498 gamma_16_to_1 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002499 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002500 for (i = 0, sp = row, dp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -05002501 i < row_info->width; i++, sp += 8, dp += 6)
2502 {
2503 png_uint_16 a;
2504
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002505 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) << 8) +
Andreas Dilger47a0c421997-05-16 02:46:07 -05002506 (png_uint_16)(*(sp + 7)));
Guy Schalnat0d580581995-07-20 02:43:20 -05002507 if (a == (png_uint_16)0xffff)
2508 {
2509 png_uint_16 v;
2510
Andreas Dilger47a0c421997-05-16 02:46:07 -05002511 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002512 *dp = (png_byte)((v >> 8) & 0xff);
2513 *(dp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002514 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002515 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
2516 *(dp + 3) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002517 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002518 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
2519 *(dp + 5) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002520 }
2521 else if (a == 0)
2522 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002523 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002524 *dp = (png_byte)((background->red >> 8) & 0xff);
2525 *(dp + 1) = (png_byte)(background->red & 0xff);
2526 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
2527 *(dp + 3) = (png_byte)(background->green & 0xff);
2528 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2529 *(dp + 5) = (png_byte)(background->blue & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002530 }
2531 else
2532 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002533 png_uint_16 v, w, x;
Guy Schalnat0d580581995-07-20 02:43:20 -05002534
Andreas Dilger47a0c421997-05-16 02:46:07 -05002535 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
2536 png_composite_16(w, v, a, background->red);
2537 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
2538 *dp = (png_byte)((x >> 8) & 0xff);
2539 *(dp + 1) = (png_byte)(x & 0xff);
2540 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
2541 png_composite_16(w, v, a, background->green);
2542 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
2543 *(dp + 2) = (png_byte)((x >> 8) & 0xff);
2544 *(dp + 3) = (png_byte)(x & 0xff);
2545 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
2546 png_composite_16(w, v, a, background->blue);
2547 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
2548 *(dp + 4) = (png_byte)((x >> 8) & 0xff);
2549 *(dp + 5) = (png_byte)(x & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002550 }
2551 }
2552 }
2553 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002554#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002555 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002556 for (i = 0, sp = row, dp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -05002557 i < row_info->width; i++, sp += 8, dp += 6)
2558 {
2559 png_uint_16 a;
2560
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002561 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) << 8) +
2562 (png_uint_16)(*(sp + 7)));
Guy Schalnat0d580581995-07-20 02:43:20 -05002563 if (a == (png_uint_16)0xffff)
2564 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002565 png_memcpy(dp, sp, 6);
Guy Schalnat0d580581995-07-20 02:43:20 -05002566 }
2567 else if (a == 0)
2568 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002569 *dp = (png_byte)((background->red >> 8) & 0xff);
2570 *(dp + 1) = (png_byte)(background->red & 0xff);
2571 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
2572 *(dp + 3) = (png_byte)(background->green & 0xff);
2573 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2574 *(dp + 5) = (png_byte)(background->blue & 0xff);
2575 }
2576 else
Guy Schalnat0d580581995-07-20 02:43:20 -05002577 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002578 png_uint_16 r, g, b, v;
Guy Schalnat0d580581995-07-20 02:43:20 -05002579
Andreas Dilger47a0c421997-05-16 02:46:07 -05002580 r = ((png_uint_16)(*sp) << 8) + *(sp + 1);
2581 g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
2582 b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5);
2583
2584 png_composite_16(v, r, a, background->red);
Guy Schalnat0d580581995-07-20 02:43:20 -05002585 *dp = (png_byte)((v >> 8) & 0xff);
2586 *(dp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002587 png_composite_16(v, g, a, background->green);
Guy Schalnat0d580581995-07-20 02:43:20 -05002588 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
2589 *(dp + 3) = (png_byte)(v & 0xff);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002590 png_composite_16(v, b, a, background->blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05002591 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
2592 *(dp + 5) = (png_byte)(v & 0xff);
2593 }
2594 }
2595 }
2596 }
2597 break;
2598 }
2599 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002600
Guy Schalnat0d580581995-07-20 02:43:20 -05002601 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
2602 {
2603 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
Guy Schalnate5a37791996-06-05 15:50:50 -05002604 row_info->channels--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002605 row_info->pixel_depth = (png_byte)(row_info->channels *
2606 row_info->bit_depth);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002607 row_info->rowbytes = ((row_info->width *
Guy Schalnat0d580581995-07-20 02:43:20 -05002608 row_info->pixel_depth + 7) >> 3);
2609 }
2610 }
2611}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002612#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002613
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002614#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002615/* Gamma correct the image, avoiding the alpha channel. Make sure
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002616 * you do this after you deal with the trasparency issue on grayscale
2617 * or rgb images. If your bit depth is 8, use gamma_table, if it
2618 * is 16, use gamma_16_table and gamma_shift. Build these with
2619 * build_gamma_table().
2620 */
Guy Schalnat0d580581995-07-20 02:43:20 -05002621void
Guy Schalnat6d764711995-12-19 03:22:19 -06002622png_do_gamma(png_row_infop row_info, png_bytep row,
2623 png_bytep gamma_table, png_uint_16pp gamma_16_table,
Guy Schalnat0d580581995-07-20 02:43:20 -05002624 int gamma_shift)
2625{
Guy Schalnat6d764711995-12-19 03:22:19 -06002626 png_bytep sp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002627 png_uint_32 i;
Guy Schalnat6d764711995-12-19 03:22:19 -06002628
Andreas Dilger47a0c421997-05-16 02:46:07 -05002629 png_debug(1, "in png_do_gamma\n");
2630 if (
2631#if defined(PNG_USELESS_TESTS_SUPPORTED)
2632 row != NULL && row_info != NULL &&
2633#endif
2634 ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
2635 (row_info->bit_depth == 16 && gamma_16_table != NULL)))
Guy Schalnat0d580581995-07-20 02:43:20 -05002636 {
2637 switch (row_info->color_type)
2638 {
2639 case PNG_COLOR_TYPE_RGB:
2640 {
2641 if (row_info->bit_depth == 8)
2642 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002643 for (i = 0, sp = row; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002644 {
2645 *sp = gamma_table[*sp];
2646 sp++;
2647 *sp = gamma_table[*sp];
2648 sp++;
2649 *sp = gamma_table[*sp];
2650 sp++;
2651 }
2652 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002653 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002654 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002655 for (i = 0, sp = row; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002656 {
2657 png_uint_16 v;
2658
Andreas Dilger47a0c421997-05-16 02:46:07 -05002659 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002660 *sp = (png_byte)((v >> 8) & 0xff);
2661 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002662 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002663 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002664 *sp = (png_byte)((v >> 8) & 0xff);
2665 *(sp + 1) = (png_byte)(v & 0xff);
2666 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002667 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002668 *sp = (png_byte)((v >> 8) & 0xff);
2669 *(sp + 1) = (png_byte)(v & 0xff);
2670 sp += 2;
2671 }
2672 }
2673 break;
2674 }
2675 case PNG_COLOR_TYPE_RGB_ALPHA:
2676 {
2677 if (row_info->bit_depth == 8)
2678 {
2679 for (i = 0, sp = row;
2680 i < row_info->width; i++)
2681 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002682 *sp = gamma_table[*sp];
2683 sp++;
2684 *sp = gamma_table[*sp];
2685 sp++;
2686 *sp = gamma_table[*sp];
2687 sp++;
2688 sp++;
2689 }
2690 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002691 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002692 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002693 for (i = 0, sp = row;
2694 i < row_info->width; i++)
2695 {
2696 png_uint_16 v;
2697
Andreas Dilger47a0c421997-05-16 02:46:07 -05002698 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002699 *sp = (png_byte)((v >> 8) & 0xff);
2700 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002701 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002702 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002703 *sp = (png_byte)((v >> 8) & 0xff);
2704 *(sp + 1) = (png_byte)(v & 0xff);
2705 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002706 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002707 *sp = (png_byte)((v >> 8) & 0xff);
2708 *(sp + 1) = (png_byte)(v & 0xff);
2709 sp += 4;
2710 }
2711 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002712 break;
2713 }
2714 case PNG_COLOR_TYPE_GRAY_ALPHA:
2715 {
2716 if (row_info->bit_depth == 8)
2717 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002718 for (i = 0, sp = row;
2719 i < row_info->width; i++)
2720 {
2721 *sp = gamma_table[*sp];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002722 sp += 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002723 }
2724 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002725 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002726 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002727 for (i = 0, sp = row;
2728 i < row_info->width; i++)
2729 {
2730 png_uint_16 v;
2731
Andreas Dilger47a0c421997-05-16 02:46:07 -05002732 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002733 *sp = (png_byte)((v >> 8) & 0xff);
2734 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002735 sp += 4;
2736 }
2737 }
2738 break;
2739 }
2740 case PNG_COLOR_TYPE_GRAY:
2741 {
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06002742 if (row_info->bit_depth == 2)
2743 {
2744 for (i = 0, sp = row; i < row_info->width; i += 4)
2745 {
2746 int a = *sp & 0xc0;
2747 int b = *sp & 0x30;
2748 int c = *sp & 0x0c;
2749 int d = *sp & 0x03;
2750
2751 *sp = ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
2752 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
2753 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
2754 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) );
2755 sp++;
2756 }
2757 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002758 if (row_info->bit_depth == 4)
Guy Schalnat0d580581995-07-20 02:43:20 -05002759 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002760 for (i = 0, sp = row; i < row_info->width; i += 2)
2761 {
2762 int msb = *sp & 0xf0;
2763 int lsb = *sp & 0x0f;
2764
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002765 *sp = (((int)gamma_table[msb | (msb >> 4)]) & 0xf0) |
2766 (((int)gamma_table[(lsb << 4) | lsb]) >> 4);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002767 sp++;
2768 }
2769 }
2770 else if (row_info->bit_depth == 8)
2771 {
2772 for (i = 0, sp = row; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002773 {
2774 *sp = gamma_table[*sp];
2775 sp++;
2776 }
2777 }
2778 else if (row_info->bit_depth == 16)
2779 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002780 for (i = 0, sp = row; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002781 {
2782 png_uint_16 v;
2783
Andreas Dilger47a0c421997-05-16 02:46:07 -05002784 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002785 *sp = (png_byte)((v >> 8) & 0xff);
2786 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002787 sp += 2;
2788 }
2789 }
2790 break;
2791 }
2792 }
2793 }
2794}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002795#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002796
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002797#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002798/* Expands a palette row to an rgb or rgba row depending
2799 * upon whether you supply trans and num_trans.
2800 */
Guy Schalnat0d580581995-07-20 02:43:20 -05002801void
Guy Schalnat6d764711995-12-19 03:22:19 -06002802png_do_expand_palette(png_row_infop row_info, png_bytep row,
Andreas Dilger47a0c421997-05-16 02:46:07 -05002803 png_colorp palette, png_bytep trans, int num_trans)
Guy Schalnat0d580581995-07-20 02:43:20 -05002804{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002805 int shift, value;
Guy Schalnat6d764711995-12-19 03:22:19 -06002806 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002807 png_uint_32 i;
Guy Schalnat6d764711995-12-19 03:22:19 -06002808
Andreas Dilger47a0c421997-05-16 02:46:07 -05002809 png_debug(1, "in png_do_expand_palette\n");
2810 if (
2811#if defined(PNG_USELESS_TESTS_SUPPORTED)
2812 row != NULL && row_info != NULL &&
2813#endif
2814 row_info->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05002815 {
2816 if (row_info->bit_depth < 8)
2817 {
2818 switch (row_info->bit_depth)
2819 {
2820 case 1:
2821 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002822 sp = row + (png_size_t)((row_info->width - 1) >> 3);
2823 dp = row + (png_size_t)row_info->width - 1;
2824 shift = 7 - (int)((row_info->width + 7) & 7);
2825 for (i = 0; i < row_info->width; i++)
2826 {
2827 if ((*sp >> shift) & 0x1)
2828 *dp = 1;
2829 else
2830 *dp = 0;
2831 if (shift == 7)
2832 {
2833 shift = 0;
2834 sp--;
2835 }
2836 else
2837 shift++;
2838
2839 dp--;
2840 }
2841 break;
2842 }
2843 case 2:
2844 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002845 sp = row + (png_size_t)((row_info->width - 1) >> 2);
2846 dp = row + (png_size_t)row_info->width - 1;
2847 shift = (int)((3 - ((row_info->width + 3) & 3)) << 1);
2848 for (i = 0; i < row_info->width; i++)
2849 {
2850 value = (*sp >> shift) & 0x3;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002851 *dp = (png_byte)value;
Guy Schalnat0d580581995-07-20 02:43:20 -05002852 if (shift == 6)
2853 {
2854 shift = 0;
2855 sp--;
2856 }
2857 else
2858 shift += 2;
2859
2860 dp--;
2861 }
2862 break;
2863 }
2864 case 4:
2865 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002866 sp = row + (png_size_t)((row_info->width - 1) >> 1);
2867 dp = row + (png_size_t)row_info->width - 1;
2868 shift = (int)((row_info->width & 1) << 2);
2869 for (i = 0; i < row_info->width; i++)
2870 {
2871 value = (*sp >> shift) & 0xf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002872 *dp = (png_byte)value;
Guy Schalnat0d580581995-07-20 02:43:20 -05002873 if (shift == 4)
2874 {
2875 shift = 0;
2876 sp--;
2877 }
2878 else
2879 shift += 4;
2880
2881 dp--;
2882 }
2883 break;
2884 }
2885 }
2886 row_info->bit_depth = 8;
2887 row_info->pixel_depth = 8;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002888 row_info->rowbytes = row_info->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05002889 }
2890 switch (row_info->bit_depth)
2891 {
2892 case 8:
2893 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002894 if (trans != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002895 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002896 sp = row + (png_size_t)row_info->width - 1;
2897 dp = row + (png_size_t)(row_info->width << 2) - 1;
2898
2899 for (i = 0; i < row_info->width; i++)
2900 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002901 if ((int)(*sp) >= num_trans)
Guy Schalnat0d580581995-07-20 02:43:20 -05002902 *dp-- = 0xff;
2903 else
2904 *dp-- = trans[*sp];
2905 *dp-- = palette[*sp].blue;
2906 *dp-- = palette[*sp].green;
2907 *dp-- = palette[*sp].red;
2908 sp--;
2909 }
2910 row_info->bit_depth = 8;
2911 row_info->pixel_depth = 32;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002912 row_info->rowbytes = row_info->width * 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05002913 row_info->color_type = 6;
2914 row_info->channels = 4;
2915 }
2916 else
2917 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002918 sp = row + (png_size_t)row_info->width - 1;
2919 dp = row + (png_size_t)(row_info->width * 3) - 1;
2920
2921 for (i = 0; i < row_info->width; i++)
2922 {
2923 *dp-- = palette[*sp].blue;
2924 *dp-- = palette[*sp].green;
2925 *dp-- = palette[*sp].red;
2926 sp--;
2927 }
2928 row_info->bit_depth = 8;
2929 row_info->pixel_depth = 24;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002930 row_info->rowbytes = row_info->width * 3;
Guy Schalnat0d580581995-07-20 02:43:20 -05002931 row_info->color_type = 2;
2932 row_info->channels = 3;
2933 }
2934 break;
2935 }
2936 }
2937 }
2938}
2939
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002940/* If the bit depth < 8, it is expanded to 8. Also, if the
2941 * transparency value is supplied, an alpha channel is built.
2942 */
Guy Schalnat0d580581995-07-20 02:43:20 -05002943void
Guy Schalnat6d764711995-12-19 03:22:19 -06002944png_do_expand(png_row_infop row_info, png_bytep row,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002945 png_color_16p trans_value)
Guy Schalnat0d580581995-07-20 02:43:20 -05002946{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002947 int shift, value;
Guy Schalnat6d764711995-12-19 03:22:19 -06002948 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002949 png_uint_32 i;
Guy Schalnat6d764711995-12-19 03:22:19 -06002950
Andreas Dilger47a0c421997-05-16 02:46:07 -05002951 png_debug(1, "in png_do_expand\n");
2952#if defined(PNG_USELESS_TESTS_SUPPORTED)
2953 if (row != NULL && row_info != NULL)
2954#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002955 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002956 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05002957 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002958 png_uint_16 gray = trans_value ? trans_value->gray : 0;
2959
2960 if (row_info->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05002961 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002962 switch (row_info->bit_depth)
Guy Schalnat0d580581995-07-20 02:43:20 -05002963 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002964 case 1:
2965 {
2966 gray *= 0xff;
2967 sp = row + (png_size_t)((row_info->width - 1) >> 3);
2968 dp = row + (png_size_t)row_info->width - 1;
2969 shift = 7 - (int)((row_info->width + 7) & 7);
2970 for (i = 0; i < row_info->width; i++)
2971 {
2972 if ((*sp >> shift) & 0x1)
2973 *dp = 0xff;
2974 else
2975 *dp = 0;
2976 if (shift == 7)
2977 {
2978 shift = 0;
2979 sp--;
2980 }
2981 else
2982 shift++;
2983
2984 dp--;
2985 }
2986 break;
2987 }
2988 case 2:
2989 {
2990 gray *= 0x55;
2991 sp = row + (png_size_t)((row_info->width - 1) >> 2);
2992 dp = row + (png_size_t)row_info->width - 1;
2993 shift = (int)((3 - ((row_info->width + 3) & 3)) << 1);
2994 for (i = 0; i < row_info->width; i++)
2995 {
2996 value = (*sp >> shift) & 0x3;
2997 *dp = (png_byte)(value | (value << 2) | (value << 4) |
2998 (value << 6));
2999 if (shift == 6)
3000 {
3001 shift = 0;
3002 sp--;
3003 }
3004 else
3005 shift += 2;
3006
3007 dp--;
3008 }
3009 break;
3010 }
3011 case 4:
3012 {
3013 gray *= 0x11;
3014 sp = row + (png_size_t)((row_info->width - 1) >> 1);
3015 dp = row + (png_size_t)row_info->width - 1;
3016 shift = (int)((1 - ((row_info->width + 1) & 1)) << 2);
3017 for (i = 0; i < row_info->width; i++)
3018 {
3019 value = (*sp >> shift) & 0xf;
3020 *dp = (png_byte)(value | (value << 4));
3021 if (shift == 4)
3022 {
3023 shift = 0;
3024 sp--;
3025 }
3026 else
3027 shift = 4;
3028
3029 dp--;
3030 }
3031 break;
3032 }
3033 }
3034 row_info->bit_depth = 8;
3035 row_info->pixel_depth = 8;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003036 row_info->rowbytes = row_info->width;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003037 }
3038
Andreas Dilger47a0c421997-05-16 02:46:07 -05003039 if (trans_value != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003040 {
3041 if (row_info->bit_depth == 8)
3042 {
3043 sp = row + (png_size_t)row_info->width - 1;
3044 dp = row + (png_size_t)(row_info->width << 1) - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003045 for (i = 0; i < row_info->width; i++)
3046 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003047 if (*sp == gray)
3048 *dp-- = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003049 else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003050 *dp-- = 0xff;
3051 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003052 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003053 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003054 else if (row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -05003055 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003056 sp = row + row_info->rowbytes - 1;
3057 dp = row + (row_info->rowbytes << 1) - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003058 for (i = 0; i < row_info->width; i++)
3059 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003060 if (((png_uint_16)*(sp) |
3061 ((png_uint_16)*(sp - 1) << 8)) == gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05003062 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003063 *dp-- = 0;
3064 *dp-- = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003065 }
3066 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003067 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003068 *dp-- = 0xff;
3069 *dp-- = 0xff;
Guy Schalnat0d580581995-07-20 02:43:20 -05003070 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003071 *dp-- = *sp--;
3072 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003073 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003074 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003075 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3076 row_info->channels = 2;
3077 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3078 row_info->rowbytes =
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003079 ((row_info->width * row_info->pixel_depth) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003080 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003081 }
3082 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3083 {
3084 if (row_info->bit_depth == 8)
3085 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003086 sp = row + (png_size_t)row_info->rowbytes - 1;
3087 dp = row + (png_size_t)(row_info->width << 2) - 1;
3088 for (i = 0; i < row_info->width; i++)
3089 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003090 if (*(sp - 2) == trans_value->red &&
Guy Schalnat0d580581995-07-20 02:43:20 -05003091 *(sp - 1) == trans_value->green &&
3092 *(sp - 0) == trans_value->blue)
3093 *dp-- = 0;
3094 else
3095 *dp-- = 0xff;
3096 *dp-- = *sp--;
3097 *dp-- = *sp--;
3098 *dp-- = *sp--;
3099 }
3100 }
3101 else if (row_info->bit_depth == 16)
3102 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003103 sp = row + row_info->rowbytes - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003104 dp = row + (png_size_t)(row_info->width << 3) - 1;
3105 for (i = 0; i < row_info->width; i++)
3106 {
3107 if ((((png_uint_16)*(sp - 4) |
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003108 ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
Guy Schalnat0d580581995-07-20 02:43:20 -05003109 (((png_uint_16)*(sp - 2) |
3110 ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
3111 (((png_uint_16)*(sp - 0) |
3112 ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
3113 {
3114 *dp-- = 0;
3115 *dp-- = 0;
3116 }
3117 else
3118 {
3119 *dp-- = 0xff;
3120 *dp-- = 0xff;
3121 }
3122 *dp-- = *sp--;
3123 *dp-- = *sp--;
3124 *dp-- = *sp--;
3125 *dp-- = *sp--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003126 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003127 *dp-- = *sp--;
3128 }
3129 }
3130 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3131 row_info->channels = 4;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003132 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
Guy Schalnat0d580581995-07-20 02:43:20 -05003133 row_info->rowbytes =
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003134 ((row_info->width * row_info->pixel_depth) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003135 }
3136 }
3137}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003138#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003139
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003140#if defined(PNG_READ_DITHER_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003141void
Guy Schalnat6d764711995-12-19 03:22:19 -06003142png_do_dither(png_row_infop row_info, png_bytep row,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003143 png_bytep palette_lookup, png_bytep dither_lookup)
Guy Schalnat0d580581995-07-20 02:43:20 -05003144{
Guy Schalnat6d764711995-12-19 03:22:19 -06003145 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003146 png_uint_32 i;
Guy Schalnat6d764711995-12-19 03:22:19 -06003147
Andreas Dilger47a0c421997-05-16 02:46:07 -05003148 png_debug(1, "in png_do_dither\n");
3149#if defined(PNG_USELESS_TESTS_SUPPORTED)
3150 if (row != NULL && row_info != NULL)
3151#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003152 {
3153 if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3154 palette_lookup && row_info->bit_depth == 8)
3155 {
3156 int r, g, b, p;
Guy Schalnat0d580581995-07-20 02:43:20 -05003157 sp = row;
3158 dp = row;
3159 for (i = 0; i < row_info->width; i++)
3160 {
3161 r = *sp++;
3162 g = *sp++;
3163 b = *sp++;
3164
3165 /* this looks real messy, but the compiler will reduce
3166 it down to a reasonable formula. For example, with
3167 5 bits per color, we get:
3168 p = (((r >> 3) & 0x1f) << 10) |
3169 (((g >> 3) & 0x1f) << 5) |
3170 ((b >> 3) & 0x1f);
3171 */
3172 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3173 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3174 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3175 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003176 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
Guy Schalnat0d580581995-07-20 02:43:20 -05003177 (PNG_DITHER_BLUE_BITS)) |
3178 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3179 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3180
3181 *dp++ = palette_lookup[p];
3182 }
3183 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3184 row_info->channels = 1;
3185 row_info->pixel_depth = row_info->bit_depth;
3186 row_info->rowbytes =
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003187 ((row_info->width * row_info->pixel_depth + 7) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003188 }
3189 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
Andreas Dilger47a0c421997-05-16 02:46:07 -05003190 palette_lookup != NULL && row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003191 {
3192 int r, g, b, p;
Guy Schalnat0d580581995-07-20 02:43:20 -05003193 sp = row;
3194 dp = row;
3195 for (i = 0; i < row_info->width; i++)
3196 {
3197 r = *sp++;
3198 g = *sp++;
3199 b = *sp++;
3200 sp++;
3201
3202 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003203 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
Guy Schalnat0d580581995-07-20 02:43:20 -05003204 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3205 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3206 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3207 (PNG_DITHER_BLUE_BITS)) |
3208 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3209 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3210
3211 *dp++ = palette_lookup[p];
3212 }
3213 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3214 row_info->channels = 1;
3215 row_info->pixel_depth = row_info->bit_depth;
3216 row_info->rowbytes =
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003217 ((row_info->width * row_info->pixel_depth + 7) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003218 }
3219 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
3220 dither_lookup && row_info->bit_depth == 8)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003221 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003222 sp = row;
3223 for (i = 0; i < row_info->width; i++, sp++)
3224 {
3225 *sp = dither_lookup[*sp];
3226 }
3227 }
3228 }
3229}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003230#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003231
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003232#if defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003233static int png_gamma_shift[] =
3234 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
3235
Andreas Dilger47a0c421997-05-16 02:46:07 -05003236/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003237 * tables, we don't make a full table if we are reducing to 8-bit in
3238 * the future. Note also how the gamma_16 tables are segmented so that
3239 * we don't need to allocate > 64K chunks for a full 16-bit table.
3240 */
Guy Schalnat0d580581995-07-20 02:43:20 -05003241void
Guy Schalnat6d764711995-12-19 03:22:19 -06003242png_build_gamma_table(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05003243{
Andreas Dilger47a0c421997-05-16 02:46:07 -05003244 png_debug(1, "in png_build_gamma_table\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05003245 if (png_ptr->bit_depth <= 8)
3246 {
3247 int i;
3248 double g;
3249
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06003250 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -05003251
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003252 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003253 (png_uint_32)256);
3254
3255 for (i = 0; i < 256; i++)
3256 {
3257 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
3258 g) * 255.0 + .5);
3259 }
3260
Andreas Dilger47a0c421997-05-16 02:46:07 -05003261#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003262 if (png_ptr->transformations & PNG_BACKGROUND)
3263 {
3264 g = 1.0 / (png_ptr->gamma);
3265
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003266 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003267 (png_uint_32)256);
3268
3269 for (i = 0; i < 256; i++)
3270 {
3271 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
3272 g) * 255.0 + .5);
3273 }
3274
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06003275 g = 1.0 / (png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -05003276
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003277 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003278 (png_uint_32)256);
3279
3280 for (i = 0; i < 256; i++)
3281 {
3282 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
3283 g) * 255.0 + .5);
3284 }
3285 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003286#endif /* PNG_BACKGROUND_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003287 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003288 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003289 {
3290 double g;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003291 int i, j, shift, num;
3292 int sig_bit;
3293 png_uint_32 ig;
Guy Schalnat0d580581995-07-20 02:43:20 -05003294
3295 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003296 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003297 sig_bit = (int)png_ptr->sig_bit.red;
3298 if ((int)png_ptr->sig_bit.green > sig_bit)
3299 sig_bit = png_ptr->sig_bit.green;
3300 if ((int)png_ptr->sig_bit.blue > sig_bit)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003301 sig_bit = png_ptr->sig_bit.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003302 }
3303 else
3304 {
3305 sig_bit = (int)png_ptr->sig_bit.gray;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003306 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003307
3308 if (sig_bit > 0)
3309 shift = 16 - sig_bit;
3310 else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003311 shift = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003312
3313 if (png_ptr->transformations & PNG_16_TO_8)
3314 {
3315 if (shift < (16 - PNG_MAX_GAMMA_8))
3316 shift = (16 - PNG_MAX_GAMMA_8);
3317 }
3318
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003319 if (shift > 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003320 shift = 8;
3321 if (shift < 0)
3322 shift = 0;
3323
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003324 png_ptr->gamma_shift = (png_byte)shift;
Guy Schalnat0d580581995-07-20 02:43:20 -05003325
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003326 num = (1 << (8 - shift));
Guy Schalnat0d580581995-07-20 02:43:20 -05003327
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06003328 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -05003329
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003330 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003331 (png_uint_32)(num * sizeof (png_uint_16p)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003332
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003333 if ((png_ptr->transformations & PNG_16_TO_8) &&
3334 !(png_ptr->transformations & PNG_BACKGROUND))
3335 {
3336 double fin, fout;
3337 png_uint_32 last, max;
Guy Schalnat0d580581995-07-20 02:43:20 -05003338
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003339 for (i = 0; i < num; i++)
3340 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003341 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003342 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003343 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003344
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003345 g = 1.0 / g;
3346 last = 0;
3347 for (i = 0; i < 256; i++)
3348 {
3349 fout = ((double)i + 0.5) / 256.0;
3350 fin = pow(fout, g);
3351 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
3352 while (last <= max)
3353 {
3354 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
3355 [(int)(last >> (8 - shift))] = (png_uint_16)(
3356 (png_uint_16)i | ((png_uint_16)i << 8));
3357 last++;
3358 }
3359 }
3360 while (last < ((png_uint_32)num << 8))
3361 {
3362 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
Andreas Dilger47a0c421997-05-16 02:46:07 -05003363 [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003364 last++;
Guy Schalnat6d764711995-12-19 03:22:19 -06003365 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003366 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003367 else
3368 {
3369 for (i = 0; i < num; i++)
3370 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003371 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003372 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003373
Andreas Dilger47a0c421997-05-16 02:46:07 -05003374 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003375 for (j = 0; j < 256; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003376 {
3377 png_ptr->gamma_16_table[i][j] =
3378 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
3379 65535.0, g) * 65535.0 + .5);
3380 }
3381 }
3382 }
3383
Andreas Dilger47a0c421997-05-16 02:46:07 -05003384#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003385 if (png_ptr->transformations & PNG_BACKGROUND)
3386 {
3387 g = 1.0 / (png_ptr->gamma);
3388
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003389 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003390 (png_uint_32)(num * sizeof (png_uint_16p )));
Guy Schalnat0d580581995-07-20 02:43:20 -05003391
3392 for (i = 0; i < num; i++)
3393 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003394 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003395 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003396
3397 ig = (((png_uint_32)i *
3398 (png_uint_32)png_gamma_shift[shift]) >> 4);
3399 for (j = 0; j < 256; j++)
3400 {
3401 png_ptr->gamma_16_to_1[i][j] =
3402 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
3403 65535.0, g) * 65535.0 + .5);
3404 }
3405 }
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06003406 g = 1.0 / (png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -05003407
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003408 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003409 (png_uint_32)(num * sizeof (png_uint_16p)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003410
3411 for (i = 0; i < num; i++)
3412 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003413 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003414 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003415
3416 ig = (((png_uint_32)i *
3417 (png_uint_32)png_gamma_shift[shift]) >> 4);
3418 for (j = 0; j < 256; j++)
3419 {
3420 png_ptr->gamma_16_from_1[i][j] =
3421 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
3422 65535.0, g) * 65535.0 + .5);
3423 }
3424 }
3425 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003426#endif /* PNG_BACKGROUND_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003427 }
3428}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003429#endif
3430