blob: f426c92639cf353a96bb3e469f50bc40a2dd6d4c [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-Pehrson345bc271998-06-14 14:43:31 -05004 * libpng 1.0.2 - June 14, 1998
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-Pehrsonb6ce43d1998-01-01 07:13:13 -06009 *
10 * This file contains functions optionally called by an application
11 * in order to tell libpng how to handle data when reading a PNG.
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050012 * Transformations that are used in both reading and writing are
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060013 * in pngtrans.c.
14 */
Guy Schalnat0d580581995-07-20 02:43:20 -050015
16#define PNG_INTERNAL
17#include "png.h"
18
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060019/* Set the action on getting a CRC error for an ancillary or critical chunk. */
20void
21png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
22{
23 png_debug(1, "in png_set_crc_action\n");
24 /* Tell libpng how we react to CRC errors in critical chunks */
25 switch (crit_action)
26 {
27 case PNG_CRC_NO_CHANGE: /* leave setting as is */
28 break;
29 case PNG_CRC_WARN_USE: /* warn/use data */
30 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
31 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
32 break;
33 case PNG_CRC_QUIET_USE: /* quiet/use data */
34 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
35 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
36 PNG_FLAG_CRC_CRITICAL_IGNORE;
37 break;
38 case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */
39 png_warning(png_ptr, "Can't discard critical data on CRC error.");
40 case PNG_CRC_ERROR_QUIT: /* error/quit */
41 case PNG_CRC_DEFAULT:
42 default:
43 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
44 break;
45 }
46
47 switch (ancil_action)
48 {
49 case PNG_CRC_NO_CHANGE: /* leave setting as is */
50 break;
51 case PNG_CRC_WARN_USE: /* warn/use data */
52 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
53 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
54 break;
55 case PNG_CRC_QUIET_USE: /* quiet/use data */
56 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
57 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
58 PNG_FLAG_CRC_ANCILLARY_NOWARN;
59 break;
60 case PNG_CRC_ERROR_QUIT: /* error/quit */
61 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
62 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
63 break;
64 case PNG_CRC_WARN_DISCARD: /* warn/discard data */
65 case PNG_CRC_DEFAULT:
66 default:
67 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
68 break;
69 }
70}
71
Guy Schalnat51f0eb41995-09-26 05:22:39 -050072#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050073/* handle alpha and tRNS via a background color */
74void
Guy Schalnat6d764711995-12-19 03:22:19 -060075png_set_background(png_structp png_ptr,
76 png_color_16p background_color, int background_gamma_code,
Guy Schalnat51f0eb41995-09-26 05:22:39 -050077 int need_expand, double background_gamma)
Guy Schalnat0d580581995-07-20 02:43:20 -050078{
Andreas Dilger47a0c421997-05-16 02:46:07 -050079 png_debug(1, "in png_set_background\n");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060080 if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
81 {
82 png_warning(png_ptr, "Application must supply a known background gamma");
83 return;
84 }
85
Guy Schalnat0d580581995-07-20 02:43:20 -050086 png_ptr->transformations |= PNG_BACKGROUND;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050087 png_memcpy(&(png_ptr->background), background_color, sizeof(png_color_16));
Guy Schalnat51f0eb41995-09-26 05:22:39 -050088 png_ptr->background_gamma = (float)background_gamma;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060089 png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
Guy Schalnate5a37791996-06-05 15:50:50 -050090 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050091
92 /* Note: if need_expand is set and color_type is either RGB or RGB_ALPHA
93 * (in which case need_expand is superfluous anyway), the background color
94 * might actually be gray yet not be flagged as such. This is not a problem
95 * for the current code, which uses PNG_FLAG_BACKGROUND_IS_GRAY only to
96 * decide when to do the png_do_gray_to_rgb() transformation.
97 */
98 if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
99 (!need_expand && background_color->red == background_color->green &&
100 background_color->red == background_color->blue))
101 png_ptr->flags |= PNG_FLAG_BACKGROUND_IS_GRAY;
Guy Schalnat0d580581995-07-20 02:43:20 -0500102}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500103#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500104
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500105#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500106/* strip 16 bit depth files to 8 bit depth */
107void
Guy Schalnat6d764711995-12-19 03:22:19 -0600108png_set_strip_16(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500109{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500110 png_debug(1, "in png_set_strip_16\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500111 png_ptr->transformations |= PNG_16_TO_8;
112}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500113#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500114
Andreas Dilger47a0c421997-05-16 02:46:07 -0500115#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
116void
117png_set_strip_alpha(png_structp png_ptr)
118{
119 png_debug(1, "in png_set_strip_alpha\n");
120 png_ptr->transformations |= PNG_STRIP_ALPHA;
121}
122#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500123
Andreas Dilger47a0c421997-05-16 02:46:07 -0500124#if defined(PNG_READ_DITHER_SUPPORTED)
125/* Dither file to 8 bit. Supply a palette, the current number
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600126 * of elements in the palette, the maximum number of elements
127 * allowed, and a histogram if possible. If the current number
128 * of colors is greater then the maximum number, the palette will be
129 * modified to fit in the maximum number. "full_dither" indicates
130 * whether we need a dithering cube set up for RGB images, or if we
131 * simply are reducing the number of colors in a paletted image.
132 */
Guy Schalnat6d764711995-12-19 03:22:19 -0600133
134typedef struct png_dsort_struct
Guy Schalnat0d580581995-07-20 02:43:20 -0500135{
Guy Schalnat6d764711995-12-19 03:22:19 -0600136 struct png_dsort_struct FAR * next;
Guy Schalnat0d580581995-07-20 02:43:20 -0500137 png_byte left;
138 png_byte right;
Guy Schalnat6d764711995-12-19 03:22:19 -0600139} png_dsort;
140typedef png_dsort FAR * png_dsortp;
141typedef png_dsort FAR * FAR * png_dsortpp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500142
143void
Guy Schalnat6d764711995-12-19 03:22:19 -0600144png_set_dither(png_structp png_ptr, png_colorp palette,
145 int num_palette, int maximum_colors, png_uint_16p histogram,
Guy Schalnat0d580581995-07-20 02:43:20 -0500146 int full_dither)
147{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500148 png_debug(1, "in png_set_dither\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500149 png_ptr->transformations |= PNG_DITHER;
150
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600151 if (!full_dither)
Guy Schalnat0d580581995-07-20 02:43:20 -0500152 {
153 int i;
154
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600155 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600156 (png_uint_32)(num_palette * sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500157 for (i = 0; i < num_palette; i++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600158 png_ptr->dither_index[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500159 }
160
161 if (num_palette > maximum_colors)
162 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500163 if (histogram != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500164 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500165 /* This is easy enough, just throw out the least used colors.
166 Perhaps not the best solution, but good enough. */
Guy Schalnat0d580581995-07-20 02:43:20 -0500167
168 int i;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600169 png_bytep sort;
Guy Schalnat0d580581995-07-20 02:43:20 -0500170
171 /* initialize an array to sort colors */
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600172 sort = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_palette
173 * sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500174
175 /* initialize the sort array */
176 for (i = 0; i < num_palette; i++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600177 sort[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500178
Andreas Dilger47a0c421997-05-16 02:46:07 -0500179 /* Find the least used palette entries by starting a
Guy Schalnat0d580581995-07-20 02:43:20 -0500180 bubble sort, and running it until we have sorted
181 out enough colors. Note that we don't care about
182 sorting all the colors, just finding which are
183 least used. */
184
185 for (i = num_palette - 1; i >= maximum_colors; i--)
186 {
187 int done; /* to stop early if the list is pre-sorted */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600188 int j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500189
190 done = 1;
191 for (j = 0; j < i; j++)
192 {
193 if (histogram[sort[j]] < histogram[sort[j + 1]])
194 {
195 png_byte t;
196
197 t = sort[j];
198 sort[j] = sort[j + 1];
199 sort[j + 1] = t;
200 done = 0;
201 }
202 }
203 if (done)
204 break;
205 }
206
207 /* swap the palette around, and set up a table, if necessary */
208 if (full_dither)
209 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500210 int j = num_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500211
212 /* put all the useful colors within the max, but don't
213 move the others */
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500214 for (i = 0; i < maximum_colors; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500215 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600216 if ((int)sort[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500217 {
218 do
219 j--;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600220 while ((int)sort[j] >= maximum_colors);
Guy Schalnat0d580581995-07-20 02:43:20 -0500221 palette[i] = palette[j];
222 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600223 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500224 }
225 else
226 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500227 int j = num_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500228
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600229 /* move all the used colors inside the max limit, and
Guy Schalnat0d580581995-07-20 02:43:20 -0500230 develop a translation table */
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500231 for (i = 0; i < maximum_colors; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500232 {
233 /* only move the colors we need to */
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600234 if ((int)sort[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500235 {
236 png_color tmp_color;
237
238 do
239 j--;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600240 while ((int)sort[j] >= maximum_colors);
Guy Schalnat0d580581995-07-20 02:43:20 -0500241
242 tmp_color = palette[j];
243 palette[j] = palette[i];
244 palette[i] = tmp_color;
245 /* indicate where the color went */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600246 png_ptr->dither_index[j] = (png_byte)i;
247 png_ptr->dither_index[i] = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500248 }
249 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500250
251 /* find closest color for those colors we are not using */
Guy Schalnat0d580581995-07-20 02:43:20 -0500252 for (i = 0; i < num_palette; i++)
253 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600254 if ((int)png_ptr->dither_index[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500255 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500256 int min_d, k, min_k, d_index;
Guy Schalnat0d580581995-07-20 02:43:20 -0500257
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600258 /* find the closest color to one we threw out */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500259 d_index = png_ptr->dither_index[i];
260 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
261 for (k = 1, min_k = 0; k < maximum_colors; k++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500262 {
263 int d;
264
Andreas Dilger47a0c421997-05-16 02:46:07 -0500265 d = PNG_COLOR_DIST(palette[d_index], palette[k]);
Guy Schalnat0d580581995-07-20 02:43:20 -0500266
267 if (d < min_d)
268 {
269 min_d = d;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500270 min_k = k;
Guy Schalnat0d580581995-07-20 02:43:20 -0500271 }
272 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600273 /* point to closest color */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500274 png_ptr->dither_index[i] = (png_byte)min_k;
Guy Schalnat0d580581995-07-20 02:43:20 -0500275 }
276 }
277 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600278 png_free(png_ptr, sort);
Guy Schalnat0d580581995-07-20 02:43:20 -0500279 }
280 else
281 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500282 /* This is much harder to do simply (and quickly). Perhaps
Guy Schalnat0d580581995-07-20 02:43:20 -0500283 we need to go through a median cut routine, but those
284 don't always behave themselves with only a few colors
285 as input. So we will just find the closest two colors,
286 and throw out one of them (chosen somewhat randomly).
Andreas Dilger47a0c421997-05-16 02:46:07 -0500287 [I don't understand this at all, so if someone wants to
288 work on improving it, be my guest - AED]
Guy Schalnat0d580581995-07-20 02:43:20 -0500289 */
290 int i;
291 int max_d;
292 int num_new_palette;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600293 png_dsortpp hash;
294 png_bytep index_to_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500295 /* where the original index currently is in the palette */
Guy Schalnat6d764711995-12-19 03:22:19 -0600296 png_bytep palette_to_index;
Guy Schalnat0d580581995-07-20 02:43:20 -0500297 /* which original index points to this palette color */
298
299 /* initialize palette index arrays */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600300 index_to_palette = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600301 (png_uint_32)(num_palette * sizeof (png_byte)));
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600302 palette_to_index = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600303 (png_uint_32)(num_palette * sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500304
305 /* initialize the sort array */
306 for (i = 0; i < num_palette; i++)
307 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600308 index_to_palette[i] = (png_byte)i;
309 palette_to_index[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500310 }
311
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600312 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
313 sizeof (png_dsortp)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500314 for (i = 0; i < 769; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500315 hash[i] = NULL;
Guy Schalnat6d764711995-12-19 03:22:19 -0600316/* png_memset(hash, 0, 769 * sizeof (png_dsortp)); */
Guy Schalnat0d580581995-07-20 02:43:20 -0500317
318 num_new_palette = num_palette;
319
320 /* initial wild guess at how far apart the farthest pixel
321 pair we will be eliminating will be. Larger
322 numbers mean more areas will be allocated, Smaller
323 numbers run the risk of not saving enough data, and
324 having to do this all over again.
325
326 I have not done extensive checking on this number.
327 */
328 max_d = 96;
329
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600330 while (num_new_palette > maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500331 {
332 for (i = 0; i < num_new_palette - 1; i++)
333 {
334 int j;
335
336 for (j = i + 1; j < num_new_palette; j++)
337 {
338 int d;
339
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600340 d = PNG_COLOR_DIST(palette[i], palette[j]);
Guy Schalnat0d580581995-07-20 02:43:20 -0500341
342 if (d <= max_d)
343 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600344 png_dsortp t;
Guy Schalnat0d580581995-07-20 02:43:20 -0500345
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600346 t = (png_dsortp)png_malloc(png_ptr, (png_uint_32)(sizeof
347 (png_dsort)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500348 t->next = hash[d];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600349 t->left = (png_byte)i;
350 t->right = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500351 hash[d] = t;
352 }
353 }
354 }
355
356 for (i = 0; i <= max_d; i++)
357 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500358 if (hash[i] != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500359 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600360 png_dsortp p;
Guy Schalnat0d580581995-07-20 02:43:20 -0500361
362 for (p = hash[i]; p; p = p->next)
363 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600364 if ((int)index_to_palette[p->left] < num_new_palette &&
365 (int)index_to_palette[p->right] < num_new_palette)
Guy Schalnat0d580581995-07-20 02:43:20 -0500366 {
367 int j, next_j;
368
369 if (num_new_palette & 1)
370 {
371 j = p->left;
372 next_j = p->right;
373 }
374 else
375 {
376 j = p->right;
377 next_j = p->left;
378 }
379
380 num_new_palette--;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500381 palette[index_to_palette[j]] = palette[num_new_palette];
Guy Schalnat0d580581995-07-20 02:43:20 -0500382 if (!full_dither)
383 {
384 int k;
385
386 for (k = 0; k < num_palette; k++)
387 {
388 if (png_ptr->dither_index[k] ==
389 index_to_palette[j])
390 png_ptr->dither_index[k] =
391 index_to_palette[next_j];
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600392 if ((int)png_ptr->dither_index[k] ==
Guy Schalnat0d580581995-07-20 02:43:20 -0500393 num_new_palette)
394 png_ptr->dither_index[k] =
395 index_to_palette[j];
396 }
397 }
398
399 index_to_palette[palette_to_index[num_new_palette]] =
400 index_to_palette[j];
401 palette_to_index[index_to_palette[j]] =
402 palette_to_index[num_new_palette];
403
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600404 index_to_palette[j] = (png_byte)num_new_palette;
405 palette_to_index[num_new_palette] = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500406 }
407 if (num_new_palette <= maximum_colors)
408 break;
409 }
410 if (num_new_palette <= maximum_colors)
411 break;
412 }
413 }
414
415 for (i = 0; i < 769; i++)
416 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500417 if (hash[i] != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500418 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500419 png_dsortp p = hash[i];
Guy Schalnat0d580581995-07-20 02:43:20 -0500420 while (p)
421 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600422 png_dsortp t;
Guy Schalnat0d580581995-07-20 02:43:20 -0500423
424 t = p->next;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600425 png_free(png_ptr, p);
Guy Schalnat0d580581995-07-20 02:43:20 -0500426 p = t;
427 }
428 }
429 hash[i] = 0;
430 }
431 max_d += 96;
432 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600433 png_free(png_ptr, hash);
434 png_free(png_ptr, palette_to_index);
435 png_free(png_ptr, index_to_palette);
Guy Schalnat0d580581995-07-20 02:43:20 -0500436 }
437 num_palette = maximum_colors;
438 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500439 if (png_ptr->palette == NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600440 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500441 png_ptr->palette = palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500442 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600443 png_ptr->num_palette = (png_uint_16)num_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500444
445 if (full_dither)
446 {
447 int i;
Guy Schalnat6d764711995-12-19 03:22:19 -0600448 png_bytep distance;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500449 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600450 PNG_DITHER_BLUE_BITS;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500451 int num_red = (1 << PNG_DITHER_RED_BITS);
452 int num_green = (1 << PNG_DITHER_GREEN_BITS);
453 int num_blue = (1 << PNG_DITHER_BLUE_BITS);
454 png_size_t num_entries = ((png_size_t)1 << total_bits);
Guy Schalnat0d580581995-07-20 02:43:20 -0500455
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600456 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600457 (png_uint_32)(num_entries * sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500458
Andreas Dilger47a0c421997-05-16 02:46:07 -0500459 png_memset(png_ptr->palette_lookup, 0, num_entries * sizeof (png_byte));
Guy Schalnat0d580581995-07-20 02:43:20 -0500460
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600461 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
462 sizeof(png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500463
Andreas Dilger47a0c421997-05-16 02:46:07 -0500464 png_memset(distance, 0xff, num_entries * sizeof(png_byte));
Guy Schalnat0d580581995-07-20 02:43:20 -0500465
466 for (i = 0; i < num_palette; i++)
467 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500468 int ir, ig, ib;
469 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
470 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
471 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
Guy Schalnat0d580581995-07-20 02:43:20 -0500472
473 for (ir = 0; ir < num_red; ir++)
474 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500475 int dr = abs(ir - r);
476 int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
Guy Schalnat0d580581995-07-20 02:43:20 -0500477
Guy Schalnat0d580581995-07-20 02:43:20 -0500478 for (ig = 0; ig < num_green; ig++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600479 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500480 int dg = abs(ig - g);
481 int dt = dr + dg;
482 int dm = ((dr > dg) ? dr : dg);
483 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
Guy Schalnat0d580581995-07-20 02:43:20 -0500484
Guy Schalnat0d580581995-07-20 02:43:20 -0500485 for (ib = 0; ib < num_blue; ib++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600486 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500487 int d_index = index_g | ib;
488 int db = abs(ib - b);
489 int dmax = ((dm > db) ? dm : db);
490 int d = dmax + dt + db;
Guy Schalnat0d580581995-07-20 02:43:20 -0500491
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600492 if (d < (int)distance[d_index])
Guy Schalnat0d580581995-07-20 02:43:20 -0500493 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500494 distance[d_index] = (png_byte)d;
495 png_ptr->palette_lookup[d_index] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500496 }
497 }
498 }
499 }
500 }
501
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600502 png_free(png_ptr, distance);
Guy Schalnat0d580581995-07-20 02:43:20 -0500503 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500504}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500505#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500506
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500507#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600508/* Transform the image from the file_gamma to the screen_gamma. We
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600509 * only do transformations on images where the file_gamma and screen_gamma
510 * are not close reciprocals, otherwise it slows things down slightly, and
511 * also needlessly introduces small errors.
512 */
Guy Schalnat0d580581995-07-20 02:43:20 -0500513void
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600514png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
Guy Schalnat0d580581995-07-20 02:43:20 -0500515{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500516 png_debug(1, "in png_set_gamma\n");
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600517 if (fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600518 png_ptr->transformations |= PNG_GAMMA;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500519 png_ptr->gamma = (float)file_gamma;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600520 png_ptr->screen_gamma = (float)scrn_gamma;
Guy Schalnat0d580581995-07-20 02:43:20 -0500521}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500522#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500523
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500524#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600525/* Expand paletted images to rgb, expand grayscale images of
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500526 * less than 8 bit depth to 8 bit depth, and expand tRNS chunks
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600527 * to alpha channels.
528 */
Guy Schalnat0d580581995-07-20 02:43:20 -0500529void
Guy Schalnat6d764711995-12-19 03:22:19 -0600530png_set_expand(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500531{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500532 png_debug(1, "in png_set_expand\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500533 png_ptr->transformations |= PNG_EXPAND;
534}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500535#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500536
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500537#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500538void
Guy Schalnat6d764711995-12-19 03:22:19 -0600539png_set_gray_to_rgb(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500540{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500541 png_debug(1, "in png_set_gray_to_rgb\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500542 png_ptr->transformations |= PNG_GRAY_TO_RGB;
543}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500544#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500545
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600546#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
547/* Convert a RGB image to a grayscale of the given width. This would
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600548 * allow us, for example, to convert a 24 bpp RGB image into an 8 or
549 * 16 bpp grayscale image. (Not yet implemented.)
550 */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600551void
552png_set_rgb_to_gray(png_structp png_ptr, int gray_bits)
553{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500554 png_debug(1, "in png_set_rgb_to_gray\n");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600555 png_ptr->transformations |= PNG_RGB_TO_GRAY;
556 /* Need to do something with gray_bits here. */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600557 png_warning(png_ptr, "RGB to GRAY transformation is not yet implemented.");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600558}
559#endif
560
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600561#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
562void
563png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
564 read_user_transform_fn)
565{
566 png_debug(1, "in png_set_read_user_transform_fn\n");
567 png_ptr->transformations |= PNG_USER_TRANSFORM;
568 png_ptr->read_user_transform_fn = read_user_transform_fn;
569}
570#endif
571
Andreas Dilger47a0c421997-05-16 02:46:07 -0500572/* Initialize everything needed for the read. This includes modifying
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600573 * the palette.
574 */
Guy Schalnat0d580581995-07-20 02:43:20 -0500575void
Guy Schalnat6d764711995-12-19 03:22:19 -0600576png_init_read_transformations(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500577{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500578 png_debug(1, "in png_init_read_transformations\n");
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500579#if defined(PNG_USELESS_TESTS_SUPPORTED)
580 if(png_ptr != NULL)
581#endif
582 {
583#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
584 || defined(PNG_READ_GAMMA_SUPPORTED)
585 int color_type = png_ptr->color_type;
586#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500587
Guy Schalnate5a37791996-06-05 15:50:50 -0500588#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
589 if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -0500590 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500591 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
Guy Schalnat0d580581995-07-20 02:43:20 -0500592 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500593 /* expand background chunk. */
Guy Schalnat0d580581995-07-20 02:43:20 -0500594 switch (png_ptr->bit_depth)
595 {
596 case 1:
Guy Schalnate5a37791996-06-05 15:50:50 -0500597 png_ptr->background.gray *= (png_uint_16)0xff;
598 png_ptr->background.red = png_ptr->background.green =
599 png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500600 break;
601 case 2:
Guy Schalnate5a37791996-06-05 15:50:50 -0500602 png_ptr->background.gray *= (png_uint_16)0x55;
603 png_ptr->background.red = png_ptr->background.green =
604 png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500605 break;
606 case 4:
Guy Schalnate5a37791996-06-05 15:50:50 -0500607 png_ptr->background.gray *= (png_uint_16)0x11;
608 png_ptr->background.red = png_ptr->background.green =
609 png_ptr->background.blue = png_ptr->background.gray;
610 break;
611 case 8:
612 case 16:
613 png_ptr->background.red = png_ptr->background.green =
614 png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500615 break;
616 }
617 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500618 else if (color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -0500619 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500620 png_ptr->background.red =
Guy Schalnat0d580581995-07-20 02:43:20 -0500621 png_ptr->palette[png_ptr->background.index].red;
622 png_ptr->background.green =
623 png_ptr->palette[png_ptr->background.index].green;
Guy Schalnate5a37791996-06-05 15:50:50 -0500624 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -0500625 png_ptr->palette[png_ptr->background.index].blue;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600626
627#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
628 if (png_ptr->transformations & PNG_INVERT_ALPHA)
629 {
630#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600631 if (!(png_ptr->transformations & PNG_EXPAND))
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600632#endif
633 {
634 /* invert the alpha channel (in tRNS) unless the pixels are
635 going to be expanded, in which case leave it for later */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500636 int i,istop;
637 istop=(int)png_ptr->num_trans;
638 for (i=0; i<istop; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600639 png_ptr->trans[i] = 255 - png_ptr->trans[i];
640 }
641 }
642#endif
643
Guy Schalnat0d580581995-07-20 02:43:20 -0500644 }
645 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500646#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500647
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500648#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500649 png_ptr->background_1 = png_ptr->background;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500650#endif
651#if defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500652 if (png_ptr->transformations & PNG_GAMMA)
653 {
654 png_build_gamma_table(png_ptr);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500655#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnate5a37791996-06-05 15:50:50 -0500656 if (png_ptr->transformations & PNG_BACKGROUND)
Guy Schalnat0d580581995-07-20 02:43:20 -0500657 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500658 if (color_type == PNG_COLOR_TYPE_PALETTE)
659 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500660 png_color back, back_1;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500661 png_colorp palette = png_ptr->palette;
662 int num_palette = png_ptr->num_palette;
663 int i;
Guy Schalnate5a37791996-06-05 15:50:50 -0500664
Andreas Dilger47a0c421997-05-16 02:46:07 -0500665 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
666 {
667 back.red = png_ptr->gamma_table[png_ptr->background.red];
668 back.green = png_ptr->gamma_table[png_ptr->background.green];
669 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
Guy Schalnate5a37791996-06-05 15:50:50 -0500670
Andreas Dilger47a0c421997-05-16 02:46:07 -0500671 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
672 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
673 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
674 }
675 else
676 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600677 double g, gs;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500678
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600679 switch (png_ptr->background_gamma_type)
Glenn Randers-Pehrson4922b1b1998-03-08 22:55:17 -0600680 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600681 case PNG_BACKGROUND_GAMMA_SCREEN:
682 g = (png_ptr->screen_gamma);
683 gs = 1.0;
684 break;
685 case PNG_BACKGROUND_GAMMA_FILE:
686 g = 1.0 / (png_ptr->gamma);
687 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
688 break;
689 case PNG_BACKGROUND_GAMMA_UNIQUE:
690 g = 1.0 / (png_ptr->background_gamma);
691 gs = 1.0 / (png_ptr->background_gamma *
692 png_ptr->screen_gamma);
693 break;
694 default:
695 g = 1.0; /* back_1 */
696 gs = 1.0; /* back */
697 }
698
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -0600699 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600700 {
701 back.red = (png_byte)png_ptr->background.red;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500702 back.green = (png_byte)png_ptr->background.green;
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600703 back.blue = (png_byte)png_ptr->background.blue;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500704 }
705 else
706 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600707 back.red = (png_byte)(pow(
708 (double)png_ptr->background.red/255, gs) * 255.0 + .5);
709 back.green = (png_byte)(pow(
710 (double)png_ptr->background.green/255, gs) * 255.0 + .5);
711 back.blue = (png_byte)(pow(
712 (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500713 }
714
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600715 back_1.red = (png_byte)(pow(
716 (double)png_ptr->background.red/255, g) * 255.0 + .5);
717 back_1.green = (png_byte)(pow(
718 (double)png_ptr->background.green/255, g) * 255.0 + .5);
719 back_1.blue = (png_byte)(pow(
720 (double)png_ptr->background.blue/255, g) * 255.0 + .5);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500721 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500722
723 for (i = 0; i < num_palette; i++)
724 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500725 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
Guy Schalnate5a37791996-06-05 15:50:50 -0500726 {
727 if (png_ptr->trans[i] == 0)
728 {
729 palette[i] = back;
730 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500731 else /* if (png_ptr->trans[i] != 0xff) */
Guy Schalnate5a37791996-06-05 15:50:50 -0500732 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500733 png_byte v, w;
Guy Schalnate5a37791996-06-05 15:50:50 -0500734
735 v = png_ptr->gamma_to_1[palette[i].red];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500736 png_composite(w, v, png_ptr->trans[i], back_1.red);
Guy Schalnate5a37791996-06-05 15:50:50 -0500737 palette[i].red = png_ptr->gamma_from_1[w];
738
739 v = png_ptr->gamma_to_1[palette[i].green];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500740 png_composite(w, v, png_ptr->trans[i], back_1.green);
Guy Schalnate5a37791996-06-05 15:50:50 -0500741 palette[i].green = png_ptr->gamma_from_1[w];
742
743 v = png_ptr->gamma_to_1[palette[i].blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500744 png_composite(w, v, png_ptr->trans[i], back_1.blue);
Guy Schalnate5a37791996-06-05 15:50:50 -0500745 palette[i].blue = png_ptr->gamma_from_1[w];
746 }
747 }
748 else
749 {
750 palette[i].red = png_ptr->gamma_table[palette[i].red];
751 palette[i].green = png_ptr->gamma_table[palette[i].green];
752 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
753 }
754 }
755 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500756 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN)*/
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600757 else
758 /* color_type != PNG_COLOR_TYPE_PALETTE */
Guy Schalnat0d580581995-07-20 02:43:20 -0500759 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500760 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
761 double g = 1.0;
762 double gs = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500763
764 switch (png_ptr->background_gamma_type)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600765 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500766 case PNG_BACKGROUND_GAMMA_SCREEN:
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600767 g = (png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500768 gs = 1.0;
769 break;
770 case PNG_BACKGROUND_GAMMA_FILE:
771 g = 1.0 / (png_ptr->gamma);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600772 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500773 break;
774 case PNG_BACKGROUND_GAMMA_UNIQUE:
775 g = 1.0 / (png_ptr->background_gamma);
776 gs = 1.0 / (png_ptr->background_gamma *
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600777 png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500778 break;
779 }
780
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600781 if (color_type & PNG_COLOR_MASK_COLOR)
Guy Schalnat0d580581995-07-20 02:43:20 -0500782 {
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600783 /* RGB or RGBA */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600784 png_ptr->background_1.red = (png_uint_16)(pow(
Guy Schalnat0d580581995-07-20 02:43:20 -0500785 (double)png_ptr->background.red / m, g) * m + .5);
786 png_ptr->background_1.green = (png_uint_16)(pow(
787 (double)png_ptr->background.green / m, g) * m + .5);
788 png_ptr->background_1.blue = (png_uint_16)(pow(
789 (double)png_ptr->background.blue / m, g) * m + .5);
790 png_ptr->background.red = (png_uint_16)(pow(
791 (double)png_ptr->background.red / m, gs) * m + .5);
792 png_ptr->background.green = (png_uint_16)(pow(
793 (double)png_ptr->background.green / m, gs) * m + .5);
794 png_ptr->background.blue = (png_uint_16)(pow(
795 (double)png_ptr->background.blue / m, gs) * m + .5);
796 }
797 else
798 {
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600799 /* GRAY or GRAY ALPHA */
Guy Schalnat0d580581995-07-20 02:43:20 -0500800 png_ptr->background_1.gray = (png_uint_16)(pow(
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600801 (double)png_ptr->background.gray / m, g) * m + .5);
Guy Schalnat0d580581995-07-20 02:43:20 -0500802 png_ptr->background.gray = (png_uint_16)(pow(
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600803 (double)png_ptr->background.gray / m, gs) * m + .5);
Guy Schalnat0d580581995-07-20 02:43:20 -0500804 }
805 }
806 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500807 else
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600808 /* transformation does not include PNG_BACKGROUND */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500809#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500810 if (color_type == PNG_COLOR_TYPE_PALETTE)
811 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500812 png_colorp palette = png_ptr->palette;
813 int num_palette = png_ptr->num_palette;
814 int i;
Guy Schalnate5a37791996-06-05 15:50:50 -0500815
816 for (i = 0; i < num_palette; i++)
817 {
818 palette[i].red = png_ptr->gamma_table[palette[i].red];
819 palette[i].green = png_ptr->gamma_table[palette[i].green];
820 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
821 }
822 }
823 }
824#if defined(PNG_READ_BACKGROUND_SUPPORTED)
825 else
826#endif
827#endif
828#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600829 /* No GAMMA transformation */
Guy Schalnate5a37791996-06-05 15:50:50 -0500830 if (png_ptr->transformations & PNG_BACKGROUND &&
831 color_type == PNG_COLOR_TYPE_PALETTE)
832 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500833 int i;
834 int istop = (int)png_ptr->num_trans;
Guy Schalnate5a37791996-06-05 15:50:50 -0500835 png_color back;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500836 png_colorp palette = png_ptr->palette;
Guy Schalnate5a37791996-06-05 15:50:50 -0500837
Guy Schalnate5a37791996-06-05 15:50:50 -0500838 back.red = (png_byte)png_ptr->background.red;
839 back.green = (png_byte)png_ptr->background.green;
840 back.blue = (png_byte)png_ptr->background.blue;
841
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500842 for (i = 0; i < istop; i++)
Guy Schalnate5a37791996-06-05 15:50:50 -0500843 {
844 if (png_ptr->trans[i] == 0)
845 {
846 palette[i] = back;
847 }
848 else if (png_ptr->trans[i] != 0xff)
849 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500850 /* The png_composite() macro is defined in png.h */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500851 png_composite(palette[i].red, palette[i].red,
852 png_ptr->trans[i], back.red);
853 png_composite(palette[i].green, palette[i].green,
854 png_ptr->trans[i], back.green);
855 png_composite(palette[i].blue, palette[i].blue,
856 png_ptr->trans[i], back.blue);
Guy Schalnate5a37791996-06-05 15:50:50 -0500857 }
858 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500859 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500860#endif
861
Guy Schalnat6d764711995-12-19 03:22:19 -0600862#if defined(PNG_READ_SHIFT_SUPPORTED)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500863 if ((png_ptr->transformations & PNG_SHIFT) &&
Guy Schalnat6d764711995-12-19 03:22:19 -0600864 color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500865 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500866 png_uint_16 i;
867 png_uint_16 istop = png_ptr->num_palette;
868 int sr = 8 - png_ptr->sig_bit.red;
869 int sg = 8 - png_ptr->sig_bit.green;
870 int sb = 8 - png_ptr->sig_bit.blue;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500871
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500872 if (sr < 0 || sr > 8)
873 sr = 0;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500874 if (sg < 0 || sg > 8)
875 sg = 0;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500876 if (sb < 0 || sb > 8)
877 sb = 0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500878 for (i = 0; i < istop; i++)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500879 {
880 png_ptr->palette[i].red >>= sr;
881 png_ptr->palette[i].green >>= sg;
882 png_ptr->palette[i].blue >>= sb;
883 }
884 }
885#endif
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500886 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500887}
888
Andreas Dilger47a0c421997-05-16 02:46:07 -0500889/* Modify the info structure to reflect the transformations. The
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600890 * info should be updated so a PNG file could be written with it,
891 * assuming the transformations result in valid PNG data.
892 */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500893void
Guy Schalnat6d764711995-12-19 03:22:19 -0600894png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500895{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500896 png_debug(1, "in png_read_transform_info\n");
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500897#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500898 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500899 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500900 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
901 {
902 if (png_ptr->num_trans)
903 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
904 else
905 info_ptr->color_type = PNG_COLOR_TYPE_RGB;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500906 info_ptr->bit_depth = 8;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500907 info_ptr->num_trans = 0;
908 }
909 else
910 {
911 if (png_ptr->num_trans)
912 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
913 if (info_ptr->bit_depth < 8)
914 info_ptr->bit_depth = 8;
915 info_ptr->num_trans = 0;
916 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500917 }
918#endif
919
920#if defined(PNG_READ_BACKGROUND_SUPPORTED)
921 if (png_ptr->transformations & PNG_BACKGROUND)
922 {
923 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
924 info_ptr->num_trans = 0;
925 info_ptr->background = png_ptr->background;
926 }
927#endif
928
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500929#if defined(PNG_READ_GAMMA_SUPPORTED)
930 if (png_ptr->transformations & PNG_GAMMA)
931 info_ptr->gamma = png_ptr->gamma;
932#endif
933
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500934#if defined(PNG_READ_16_TO_8_SUPPORTED)
935 if ((png_ptr->transformations & PNG_16_TO_8) && info_ptr->bit_depth == 16)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600936 info_ptr->bit_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500937#endif
938
939#if defined(PNG_READ_DITHER_SUPPORTED)
940 if (png_ptr->transformations & PNG_DITHER)
941 {
942 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
943 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
944 png_ptr->palette_lookup && info_ptr->bit_depth == 8)
945 {
946 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
947 }
948 }
949#endif
950
951#if defined(PNG_READ_PACK_SUPPORTED)
952 if ((png_ptr->transformations & PNG_PACK) && info_ptr->bit_depth < 8)
953 info_ptr->bit_depth = 8;
954#endif
955
956#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -0600957 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500958 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
959#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500960
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600961 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500962 info_ptr->channels = 1;
963 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
964 info_ptr->channels = 3;
965 else
966 info_ptr->channels = 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500967
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600968#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -0600969 if (png_ptr->transformations & PNG_STRIP_ALPHA)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500970 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500971#endif
972
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500973 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
974 info_ptr->channels++;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500975
976#if defined(PNG_READ_FILLER_SUPPORTED)
977 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
978 if (png_ptr->transformations & PNG_FILLER &&
979 (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
980 info_ptr->color_type == PNG_COLOR_TYPE_GRAY))
981 ++info_ptr->channels;
982#endif
983
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600984 info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
985 info_ptr->bit_depth);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600986 info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -0500987}
988
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600989/* Transform the row. The order of transformations is significant,
990 * and is very touchy. If you add a transformation, take care to
991 * decide how it fits in with the other transformations here.
992 */
Guy Schalnat0d580581995-07-20 02:43:20 -0500993void
Guy Schalnat6d764711995-12-19 03:22:19 -0600994png_do_read_transformations(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500995{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500996 png_debug(1, "in png_do_read_transformations\n");
997#if !defined(PNG_USELESS_TESTS_SUPPORTED)
998 if (png_ptr->row_buf == NULL)
999 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001000#if !defined(PNG_NO_STDIO)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001001 char msg[50];
1002
1003 sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
1004 png_ptr->pass);
1005 png_error(png_ptr, msg);
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001006#else
1007 png_error(png_ptr, "NULL row buffer");
1008#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001009 }
1010#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001011
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001012#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001013 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05001014 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001015 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1016 {
1017 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1018 png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1019 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001020 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001021 {
1022 if (png_ptr->num_trans)
1023 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1024 &(png_ptr->trans_values));
1025 else
1026 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1027 NULL);
1028 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001029 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001030#endif
1031
1032#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1033 if (png_ptr->transformations & PNG_STRIP_ALPHA)
1034 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1035 PNG_FLAG_FILLER_AFTER);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001036#endif
1037
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001038/*
1039From Andreas Dilger e-mail to png-implement, 26 March 1998:
1040
1041 In most cases, the "simple transparency" should be done prior to doing
1042 gray-to-RGB, or you will have to test 3x as many bytes to check if a
1043 pixel is transparent. You would also need to make sure that the
1044 transparency information is upgraded to RGB.
1045
1046 To summarize, the current flow is:
1047 - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1048 with background "in place" if transparent,
1049 convert to RGB if necessary
1050 - Gray + alpha -> composite with gray background and remove alpha bytes,
1051 convert to RGB if necessary
1052
1053 To support RGB backgrounds for gray images we need:
1054 - Gray + simple transparency -> convert to RGB + simple transparency, compare
1055 3 or 6 bytes and composite with background
1056 "in place" if transparent (3x compare/pixel
1057 compared to doing composite with gray bkgrnd)
1058 - Gray + alpha -> convert to RGB + alpha, composite with background and
1059 remove alpha bytes (3x float operations/pixel
1060 compared with composite on gray background)
1061
1062 Greg's change will do this. The reason it wasn't done before is for
1063 performance, as this increases the per-pixel operations. If we would check
1064 in advance if the background was gray or RGB, and position the gray-to-RGB
1065 transform appropriately, then it would save a lot of work/time.
1066 */
1067
1068#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1069 /* if gray -> RGB, do so now only if background is non-gray; else do later
1070 * for performance reasons */
1071 if (png_ptr->transformations & PNG_GRAY_TO_RGB &&
1072 !(png_ptr->flags & PNG_FLAG_BACKGROUND_IS_GRAY))
1073 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1074#endif
1075
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001076#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001077 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1078 ((png_ptr->num_trans != 0 ) ||
1079 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
Guy Schalnat0d580581995-07-20 02:43:20 -05001080 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1081 &(png_ptr->trans_values), &(png_ptr->background),
1082 &(png_ptr->background_1),
1083 png_ptr->gamma_table, png_ptr->gamma_from_1,
1084 png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1085 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1086 png_ptr->gamma_shift);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001087#endif
1088
1089#if defined(PNG_READ_GAMMA_SUPPORTED)
1090 if ((png_ptr->transformations & PNG_GAMMA) &&
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001091#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1092 !((png_ptr->transformations & PNG_BACKGROUND) &&
1093 ((png_ptr->num_trans != 0) ||
1094 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1095#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001096 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
Guy Schalnat0d580581995-07-20 02:43:20 -05001097 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1098 png_ptr->gamma_table, png_ptr->gamma_16_table,
1099 png_ptr->gamma_shift);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001100#endif
1101
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001102#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001103 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1104 png_do_rgb_to_gray(&(png_ptr->row_info), png_ptr->row_buf + 1);
1105#endif
1106
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001107#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001108 if (png_ptr->transformations & PNG_16_TO_8)
1109 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001110#endif
1111
1112#if defined(PNG_READ_DITHER_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001113 if (png_ptr->transformations & PNG_DITHER)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001114 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001115 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1116 png_ptr->palette_lookup, png_ptr->dither_index);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001117 if(png_ptr->row_info.rowbytes == (png_uint_32)0)
1118 png_error(png_ptr, "png_do_dither returned rowbytes=0");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001119 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001120#endif
1121
1122#if defined(PNG_READ_INVERT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001123 if (png_ptr->transformations & PNG_INVERT_MONO)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001124 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001125#endif
1126
1127#if defined(PNG_READ_SHIFT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001128 if (png_ptr->transformations & PNG_SHIFT)
1129 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1130 &(png_ptr->shift));
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001131#endif
1132
1133#if defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001134 if (png_ptr->transformations & PNG_PACK)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001135 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001136#endif
1137
1138#if defined(PNG_READ_BGR_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001139 if (png_ptr->transformations & PNG_BGR)
1140 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001141#endif
1142
Andreas Dilger47a0c421997-05-16 02:46:07 -05001143#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1144 if (png_ptr->transformations & PNG_PACKSWAP)
1145 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1146#endif
1147
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001148#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001149 /* if gray -> RGB, do so now only if we did not do so above */
1150 if (png_ptr->transformations & PNG_GRAY_TO_RGB &&
1151 png_ptr->flags & PNG_FLAG_BACKGROUND_IS_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05001152 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001153#endif
1154
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001155#if defined(PNG_READ_FILLER_SUPPORTED)
1156 if (png_ptr->transformations & PNG_FILLER)
1157 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001158 (png_uint_32)png_ptr->filler, png_ptr->flags);
1159#endif
1160
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001161#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1162 if (png_ptr->transformations & PNG_INVERT_ALPHA)
1163 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1164#endif
1165
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001166#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1167 if (png_ptr->transformations & PNG_SWAP_ALPHA)
1168 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1169#endif
1170
Andreas Dilger47a0c421997-05-16 02:46:07 -05001171#if defined(PNG_READ_SWAP_SUPPORTED)
1172 if (png_ptr->transformations & PNG_SWAP_BYTES)
1173 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001174#endif
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001175
1176#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1177 if (png_ptr->transformations & PNG_USER_TRANSFORM)
1178 if(png_ptr->read_user_transform_fn != NULL)
1179 (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1180 (png_ptr, /* png_ptr */
1181 &(png_ptr->row_info), /* row_info: */
1182 /* png_uint_32 width; width of row */
1183 /* png_uint_32 rowbytes; number of bytes in row */
1184 /* png_byte color_type; color type of pixels */
1185 /* png_byte bit_depth; bit depth of samples */
1186 /* png_byte channels; number of channels (1-4) */
1187 /* png_byte pixel_depth; bits per pixel (depth*channels) */
1188 png_ptr->row_buf + 1); /* start of pixel data for row */
1189#endif
1190
Guy Schalnat0d580581995-07-20 02:43:20 -05001191}
1192
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001193#if defined(PNG_READ_PACK_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001194/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1195 * without changing the actual values. Thus, if you had a row with
1196 * a bit depth of 1, you would end up with bytes that only contained
1197 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1198 * png_do_shift() after this.
1199 */
Guy Schalnat0d580581995-07-20 02:43:20 -05001200void
Guy Schalnat6d764711995-12-19 03:22:19 -06001201png_do_unpack(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001202{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001203 png_debug(1, "in png_do_unpack\n");
1204#if defined(PNG_USELESS_TESTS_SUPPORTED)
1205 if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1206#else
1207 if (row_info->bit_depth < 8)
1208#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001209 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001210 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001211 png_uint_32 row_width=row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001212
Guy Schalnat0d580581995-07-20 02:43:20 -05001213 switch (row_info->bit_depth)
1214 {
1215 case 1:
1216 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001217 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1218 png_bytep dp = row + (png_size_t)row_width - 1;
1219 png_uint_32 shift = 7 - (int)((row_width + 7) & 7);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001220 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001221 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001222 *dp = (png_byte)((*sp >> shift) & 0x1);
Guy Schalnat0d580581995-07-20 02:43:20 -05001223 if (shift == 7)
1224 {
1225 shift = 0;
1226 sp--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001227 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001228 else
1229 shift++;
1230
1231 dp--;
1232 }
1233 break;
1234 }
1235 case 2:
1236 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001237
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001238 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1239 png_bytep dp = row + (png_size_t)row_width - 1;
1240 png_uint_32 shift = (int)((3 - ((row_width + 3) & 3)) << 1);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001241 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001242 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001243 *dp = (png_byte)((*sp >> shift) & 0x3);
Guy Schalnat0d580581995-07-20 02:43:20 -05001244 if (shift == 6)
1245 {
1246 shift = 0;
1247 sp--;
1248 }
1249 else
1250 shift += 2;
1251
1252 dp--;
1253 }
1254 break;
1255 }
1256 case 4:
1257 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001258 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1259 png_bytep dp = row + (png_size_t)row_width - 1;
1260 png_uint_32 shift = (int)((1 - ((row_width + 1) & 1)) << 2);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001261 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001262 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001263 *dp = (png_byte)((*sp >> shift) & 0xf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001264 if (shift == 4)
1265 {
1266 shift = 0;
1267 sp--;
1268 }
1269 else
1270 shift = 4;
1271
1272 dp--;
1273 }
1274 break;
1275 }
1276 }
1277 row_info->bit_depth = 8;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001278 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001279 row_info->rowbytes = row_width * row_info->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -05001280 }
1281}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001282#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001283
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001284#if defined(PNG_READ_SHIFT_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001285/* Reverse the effects of png_do_shift. This routine merely shifts the
1286 * pixels back to their significant bits values. Thus, if you have
1287 * a row of bit depth 8, but only 5 are significant, this will shift
1288 * the values back to 0 through 31.
1289 */
Guy Schalnat0d580581995-07-20 02:43:20 -05001290void
Andreas Dilger47a0c421997-05-16 02:46:07 -05001291png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
Guy Schalnat0d580581995-07-20 02:43:20 -05001292{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001293 png_debug(1, "in png_do_unshift\n");
1294 if (
1295#if defined(PNG_USELESS_TESTS_SUPPORTED)
1296 row != NULL && row_info != NULL && sig_bits != NULL &&
1297#endif
1298 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05001299 {
1300 int shift[4];
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001301 int channels = 0;
1302 int c;
1303 png_uint_16 value = 0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001304 png_uint_32 row_width = row_info->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001305
Guy Schalnat0d580581995-07-20 02:43:20 -05001306 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1307 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001308 shift[channels++] = row_info->bit_depth - sig_bits->red;
1309 shift[channels++] = row_info->bit_depth - sig_bits->green;
1310 shift[channels++] = row_info->bit_depth - sig_bits->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05001311 }
1312 else
1313 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001314 shift[channels++] = row_info->bit_depth - sig_bits->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05001315 }
1316 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1317 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001318 shift[channels++] = row_info->bit_depth - sig_bits->alpha;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001319 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001320
Andreas Dilger47a0c421997-05-16 02:46:07 -05001321 for (c = 0; c < channels; c++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001322 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001323 if (shift[c] <= 0)
1324 shift[c] = 0;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001325 else
1326 value = 1;
1327 }
Guy Schalnat0f716451995-11-28 11:22:13 -06001328
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001329 if (!value)
1330 return;
Guy Schalnat0f716451995-11-28 11:22:13 -06001331
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001332 switch (row_info->bit_depth)
Guy Schalnat0d580581995-07-20 02:43:20 -05001333 {
1334 case 2:
1335 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001336 png_bytep bp;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001337 png_uint_32 i;
1338 png_uint_32 istop = row_info->rowbytes;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001339
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001340 for (bp = row, i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001341 {
1342 *bp >>= 1;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001343 *bp++ &= 0x55;
Guy Schalnat0d580581995-07-20 02:43:20 -05001344 }
1345 break;
1346 }
1347 case 4:
1348 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001349 png_bytep bp = row;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001350 png_uint_32 i;
1351 png_uint_32 istop = row_info->rowbytes;
1352 png_byte mask = (png_byte)(((int)0xf0 >> shift[0]) & (int)0xf0) |
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001353 (png_byte)((int)0xf >> shift[0]);
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001354
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001355 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001356 {
1357 *bp >>= shift[0];
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001358 *bp++ &= mask;
Guy Schalnat0d580581995-07-20 02:43:20 -05001359 }
1360 break;
1361 }
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001362#ifndef PNG_SLOW_SHIFT
Guy Schalnat0d580581995-07-20 02:43:20 -05001363 case 8:
1364 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001365 png_bytep bp = row;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001366 png_uint_32 i;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001367 png_uint_32 istop = row_width * channels;
Guy Schalnat0d580581995-07-20 02:43:20 -05001368
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001369 for (i = 0; i < istop; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001370 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001371 *bp++ >>= shift[i%channels];
Guy Schalnat0d580581995-07-20 02:43:20 -05001372 }
1373 break;
1374 }
1375 case 16:
1376 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001377 png_bytep bp = row;
1378 png_uint_32 i;
1379 png_uint_32 istop = channels * row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001380
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001381 for (i = 0; i < istop; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001382 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001383 value = (png_uint_16)((*bp << 8) + *(bp + 1));
1384 value >>= shift[i%channels];
1385 *bp++ = (png_byte)(value >> 8);
1386 *bp++ = (png_byte)(value & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05001387 }
1388 break;
1389 }
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001390#else
1391 case 8:
1392 {
1393 png_bytep bp;
1394 png_uint_32 i;
1395 int cstop;
1396
1397 cstop=(int)row_info->channels;
1398 for (bp = row, i = 0; i < row_width; i++)
1399 {
1400 for (c = 0; c < cstop; c++, bp++)
1401 {
1402 *bp >>= shift[c];
1403 }
1404 }
1405 break;
1406 }
1407 case 16:
1408 {
1409 png_bytep bp;
1410 png_size_t i;
1411 int cstop;
1412
1413 cstop=(int)row_info->channels;
1414 for (bp = row, i = 0; i < row_width; i++)
1415 {
1416 for (c = 0; c < cstop; c++, bp += 2)
1417 {
1418 value = (png_uint_16)((*bp << 8) + *(bp + 1));
1419 value >>= shift[c];
1420 *bp = (png_byte)(value >> 8);
1421 *(bp + 1) = (png_byte)(value & 0xff);
1422 }
1423 }
1424 break;
1425 }
1426#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001427 }
1428 }
1429}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001430#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001431
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001432#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001433/* chop rows of bit depth 16 down to 8 */
1434void
Guy Schalnat6d764711995-12-19 03:22:19 -06001435png_do_chop(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001436{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001437 png_debug(1, "in png_do_chop\n");
1438#if defined(PNG_USELESS_TESTS_SUPPORTED)
1439 if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1440#else
1441 if (row_info->bit_depth == 16)
1442#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001443 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001444 png_bytep sp = row;
1445 png_bytep dp = row;
1446 png_uint_32 i;
1447 png_uint_32 istop = row_info->width * row_info->channels;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001448
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001449 for (i = 0; i<istop; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001450 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001451#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001452 /* This does a more accurate scaling of the 16-bit color
1453 * value, rather than a simple low-byte truncation.
1454 *
1455 * What the ideal calculation should be:
1456 * *dp = (((((png_uint_32)(*sp) << 8) |
1457 * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1458 *
1459 * GRR: no, I think this is what it really should be:
1460 * *dp = (((((png_uint_32)(*sp) << 8) |
1461 * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1462 *
1463 * GRR: here's the exact calculation with shifts:
1464 * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1465 * *dp = (temp - (temp >> 8)) >> 8;
1466 *
1467 * Approximate calculation with shift/add instead of multiply/divide:
1468 * *dp = ((((png_uint_32)(*sp) << 8) |
1469 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1470 *
1471 * What we actually do to avoid extra shifting and conversion:
1472 */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001473
Andreas Dilger47a0c421997-05-16 02:46:07 -05001474 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1475#else
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001476 /* Simply discard the low order byte */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001477 *dp = *sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001478#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001479 }
1480 row_info->bit_depth = 8;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001481 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001482 row_info->rowbytes = row_info->width * row_info->channels;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001483 }
1484}
1485#endif
1486
1487#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1488void
1489png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1490{
1491 png_debug(1, "in png_do_read_swap_alpha\n");
1492#if defined(PNG_USELESS_TESTS_SUPPORTED)
1493 if (row != NULL && row_info != NULL)
1494#endif
1495 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001496 png_uint_32 row_width = row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001497 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1498 {
1499 /* This converts from RGBA to ARGB */
1500 if (row_info->bit_depth == 8)
1501 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001502 png_bytep sp = row + row_info->rowbytes;
1503 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001504 png_byte save;
1505 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001506
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001507 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001508 {
1509 save = *(--sp);
1510 *(--dp) = *(--sp);
1511 *(--dp) = *(--sp);
1512 *(--dp) = *(--sp);
1513 *(--dp) = save;
1514 }
1515 }
1516 /* This converts from RRGGBBAA to AARRGGBB */
1517 else
1518 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001519 png_bytep sp = row + row_info->rowbytes;
1520 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001521 png_byte save[2];
1522 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001523
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001524 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001525 {
1526 save[0] = *(--sp);
1527 save[1] = *(--sp);
1528 *(--dp) = *(--sp);
1529 *(--dp) = *(--sp);
1530 *(--dp) = *(--sp);
1531 *(--dp) = *(--sp);
1532 *(--dp) = *(--sp);
1533 *(--dp) = *(--sp);
1534 *(--dp) = save[0];
1535 *(--dp) = save[1];
1536 }
1537 }
1538 }
1539 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1540 {
1541 /* This converts from GA to AG */
1542 if (row_info->bit_depth == 8)
1543 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001544 png_bytep sp = row + row_info->rowbytes;
1545 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001546 png_byte save;
1547 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001548
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001549 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001550 {
1551 save = *(--sp);
1552 *(--dp) = *(--sp);
1553 *(--dp) = save;
1554 }
1555 }
1556 /* This converts from GGAA to AAGG */
1557 else
1558 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001559 png_bytep sp = row + row_info->rowbytes;
1560 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001561 png_byte save[2];
1562 png_uint_32 i;
1563
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001564 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001565 {
1566 save[0] = *(--sp);
1567 save[1] = *(--sp);
1568 *(--dp) = *(--sp);
1569 *(--dp) = *(--sp);
1570 *(--dp) = save[0];
1571 *(--dp) = save[1];
1572 }
1573 }
1574 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001575 }
1576}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001577#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001578
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001579#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1580void
1581png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1582{
1583 png_debug(1, "in png_do_read_invert_alpha\n");
1584#if defined(PNG_USELESS_TESTS_SUPPORTED)
1585 if (row != NULL && row_info != NULL)
1586#endif
1587 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001588 png_uint_32 row_width = row_info->width;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001589 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1590 {
1591 /* This inverts the alpha channel in RGBA */
1592 if (row_info->bit_depth == 8)
1593 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001594 png_bytep sp = row + row_info->rowbytes;
1595 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001596 png_uint_32 i;
1597
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001598 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001599 {
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001600 *(--dp) = 255 - *(--sp);
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001601 *(--dp) = *(--sp);
1602 *(--dp) = *(--sp);
1603 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001604 }
1605 }
1606 /* This inverts the alpha channel in RRGGBBAA */
1607 else
1608 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001609 png_bytep sp = row + row_info->rowbytes;
1610 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001611 png_uint_32 i;
1612
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001613 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001614 {
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001615 *(--dp) = 255 - *(--sp);
1616 *(--dp) = 255 - *(--sp);
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001617 *(--dp) = *(--sp);
1618 *(--dp) = *(--sp);
1619 *(--dp) = *(--sp);
1620 *(--dp) = *(--sp);
1621 *(--dp) = *(--sp);
1622 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001623 }
1624 }
1625 }
1626 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1627 {
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001628 /* This inverts the alpha channel in GA */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001629 if (row_info->bit_depth == 8)
1630 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001631 png_bytep sp = row + row_info->rowbytes;
1632 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001633 png_uint_32 i;
1634
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001635 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001636 {
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001637 *(--dp) = 255 - *(--sp);
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001638 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001639 }
1640 }
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001641 /* This inverts the alpha channel in GGAA */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001642 else
1643 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001644 png_bytep sp = row + row_info->rowbytes;
1645 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001646 png_uint_32 i;
1647
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001648 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001649 {
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001650 *(--dp) = 255 - *(--sp);
1651 *(--dp) = 255 - *(--sp);
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001652 *(--dp) = *(--sp);
1653 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001654 }
1655 }
1656 }
1657 }
1658}
1659#endif
1660
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001661#if defined(PNG_READ_FILLER_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001662/* Add filler channel if we have RGB color */
Guy Schalnat0d580581995-07-20 02:43:20 -05001663void
Guy Schalnat6d764711995-12-19 03:22:19 -06001664png_do_read_filler(png_row_infop row_info, png_bytep row,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001665 png_uint_32 filler, png_uint_32 flags)
Guy Schalnat0d580581995-07-20 02:43:20 -05001666{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001667 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001668 png_uint_32 row_width = row_info->width;
1669
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001670 png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
1671 png_byte low_filler = (png_byte)(filler & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001672
1673 png_debug(1, "in png_do_read_filler\n");
1674 if (
1675#if defined(PNG_USELESS_TESTS_SUPPORTED)
1676 row != NULL && row_info != NULL &&
1677#endif
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001678 row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05001679 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001680 if(row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05001681 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001682 /* This changes the data from G to GX */
1683 if (flags & PNG_FLAG_FILLER_AFTER)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001684 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001685 png_bytep sp = row + (png_size_t)row_width;
1686 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001687 for (i = 1; i < row_width; i++)
1688 {
1689 *(--dp) = low_filler;
1690 *(--dp) = *(--sp);
1691 }
1692 row_info->channels = 2;
1693 row_info->pixel_depth = 16;
1694 row_info->rowbytes = row_width * 2;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001695 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001696 /* This changes the data from G to XG */
1697 else
1698 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001699 png_bytep sp = row + (png_size_t)row_width;
1700 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001701 for (i = 0; i < row_width; i++)
1702 {
1703 *(--dp) = *(--sp);
1704 *(--dp) = low_filler;
1705 }
1706 row_info->channels = 2;
1707 row_info->pixel_depth = 16;
1708 row_info->rowbytes = row_width * 2;
1709 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001710 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001711 else if(row_info->bit_depth == 16)
1712 {
1713 /* This changes the data from GG to GGXX */
1714 if (flags & PNG_FLAG_FILLER_AFTER)
1715 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001716 png_bytep sp = row + (png_size_t)row_width;
1717 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001718 for (i = 1; i < row_width; i++)
1719 {
1720 *(--dp) = hi_filler;
1721 *(--dp) = low_filler;
1722 *(--dp) = *(--sp);
1723 *(--dp) = *(--sp);
1724 }
1725 row_info->channels = 2;
1726 row_info->pixel_depth = 32;
1727 row_info->rowbytes = row_width * 2;
1728 }
1729 /* This changes the data from GG to XXGG */
1730 else
1731 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001732 png_bytep sp = row + (png_size_t)row_width;
1733 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001734 for (i = 0; i < row_width; i++)
1735 {
1736 *(--dp) = *(--sp);
1737 *(--dp) = *(--sp);
1738 *(--dp) = hi_filler;
1739 *(--dp) = low_filler;
1740 }
1741 row_info->channels = 2;
1742 row_info->pixel_depth = 16;
1743 row_info->rowbytes = row_width * 2;
1744 }
1745 }
1746 } /* COLOR_TYPE == GRAY */
1747 else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
1748 {
1749 if(row_info->bit_depth == 8)
1750 {
1751 /* This changes the data from RGB to RGBX */
1752 if (flags & PNG_FLAG_FILLER_AFTER)
1753 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001754 png_bytep sp = row + (png_size_t)row_width * 3;
1755 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001756 for (i = 1; i < row_width; i++)
1757 {
1758 *(--dp) = low_filler;
1759 *(--dp) = *(--sp);
1760 *(--dp) = *(--sp);
1761 *(--dp) = *(--sp);
1762 }
1763 row_info->channels = 4;
1764 row_info->pixel_depth = 32;
1765 row_info->rowbytes = row_width * 4;
1766 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001767 /* This changes the data from RGB to XRGB */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001768 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001769 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001770 png_bytep sp = row + (png_size_t)row_width * 3;
1771 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001772 for (i = 0; i < row_width; i++)
1773 {
1774 *(--dp) = *(--sp);
1775 *(--dp) = *(--sp);
1776 *(--dp) = *(--sp);
1777 *(--dp) = low_filler;
1778 }
1779 row_info->channels = 4;
1780 row_info->pixel_depth = 32;
1781 row_info->rowbytes = row_width * 4;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001782 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001783 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001784 else if(row_info->bit_depth == 16)
1785 {
1786 /* This changes the data from RRGGBB to RRGGBBXX */
1787 if (flags & PNG_FLAG_FILLER_AFTER)
1788 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001789 png_bytep sp = row + (png_size_t)row_width * 3;
1790 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001791 for (i = 1; i < row_width; i++)
1792 {
1793 *(--dp) = hi_filler;
1794 *(--dp) = low_filler;
1795 *(--dp) = *(--sp);
1796 *(--dp) = *(--sp);
1797 *(--dp) = *(--sp);
1798 *(--dp) = *(--sp);
1799 *(--dp) = *(--sp);
1800 *(--dp) = *(--sp);
1801 }
1802 row_info->channels = 4;
1803 row_info->pixel_depth = 64;
1804 row_info->rowbytes = row_width * 4;
1805 }
1806 /* This changes the data from RRGGBB to XXRRGGBB */
1807 else
1808 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001809 png_bytep sp = row + (png_size_t)row_width * 3;
1810 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001811 for (i = 0; i < row_width; i++)
1812 {
1813 *(--dp) = *(--sp);
1814 *(--dp) = *(--sp);
1815 *(--dp) = *(--sp);
1816 *(--dp) = *(--sp);
1817 *(--dp) = *(--sp);
1818 *(--dp) = *(--sp);
1819 *(--dp) = hi_filler;
1820 *(--dp) = low_filler;
1821 }
1822 row_info->channels = 4;
1823 row_info->pixel_depth = 64;
1824 row_info->rowbytes = row_width * 4;
1825 }
1826 }
1827 } /* COLOR_TYPE == RGB */
Guy Schalnat0d580581995-07-20 02:43:20 -05001828}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001829#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001830
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001831#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001832/* expand grayscale files to RGB, with or without alpha */
Guy Schalnat0d580581995-07-20 02:43:20 -05001833void
Guy Schalnat6d764711995-12-19 03:22:19 -06001834png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001835{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001836 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001837 png_uint_32 row_width = row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06001838
Andreas Dilger47a0c421997-05-16 02:46:07 -05001839 png_debug(1, "in png_do_gray_to_rgb\n");
1840 if (row_info->bit_depth >= 8 &&
1841#if defined(PNG_USELESS_TESTS_SUPPORTED)
1842 row != NULL && row_info != NULL &&
1843#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001844 !(row_info->color_type & PNG_COLOR_MASK_COLOR))
1845 {
1846 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
1847 {
1848 if (row_info->bit_depth == 8)
1849 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001850 png_bytep sp = row + (png_size_t)row_width - 1;
1851 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001852 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001853 {
1854 *(dp--) = *sp;
1855 *(dp--) = *sp;
1856 *(dp--) = *sp;
1857 sp--;
1858 }
1859 }
1860 else
1861 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001862 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
1863 png_bytep dp = sp + (png_size_t)row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001864 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001865 {
1866 *(dp--) = *sp;
1867 *(dp--) = *(sp - 1);
1868 *(dp--) = *sp;
1869 *(dp--) = *(sp - 1);
1870 *(dp--) = *sp;
1871 *(dp--) = *(sp - 1);
1872 sp--;
1873 sp--;
1874 }
1875 }
1876 }
1877 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1878 {
1879 if (row_info->bit_depth == 8)
1880 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001881 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
1882 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001883 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001884 {
1885 *(dp--) = *(sp--);
1886 *(dp--) = *sp;
1887 *(dp--) = *sp;
1888 *(dp--) = *sp;
1889 sp--;
1890 }
1891 }
1892 else
1893 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001894 png_bytep sp = row + (png_size_t)row_width * 4 - 1;
1895 png_bytep dp = sp + (png_size_t)row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001896 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001897 {
1898 *(dp--) = *(sp--);
1899 *(dp--) = *(sp--);
1900 *(dp--) = *sp;
1901 *(dp--) = *(sp - 1);
1902 *(dp--) = *sp;
1903 *(dp--) = *(sp - 1);
1904 *(dp--) = *sp;
1905 *(dp--) = *(sp - 1);
1906 sp--;
1907 sp--;
1908 }
1909 }
1910 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001911 row_info->channels += (png_byte)2;
Guy Schalnat0d580581995-07-20 02:43:20 -05001912 row_info->color_type |= PNG_COLOR_MASK_COLOR;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001913 row_info->pixel_depth = (png_byte)(row_info->channels *
1914 row_info->bit_depth);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001915 row_info->rowbytes = ((row_width *
Guy Schalnat0d580581995-07-20 02:43:20 -05001916 row_info->pixel_depth + 7) >> 3);
1917 }
1918}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001919#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001920
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001921/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
1922 * large of png_color. This lets grayscale images be treated as
1923 * paletted. Most useful for gamma correction and simplification
1924 * of code.
1925 */
Guy Schalnat0d580581995-07-20 02:43:20 -05001926void
Guy Schalnat6d764711995-12-19 03:22:19 -06001927png_build_grayscale_palette(int bit_depth, png_colorp palette)
Guy Schalnat0d580581995-07-20 02:43:20 -05001928{
1929 int num_palette;
1930 int color_inc;
1931 int i;
1932 int v;
1933
Andreas Dilger47a0c421997-05-16 02:46:07 -05001934 png_debug(1, "in png_do_build_grayscale_palette\n");
1935 if (palette == NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05001936 return;
1937
1938 switch (bit_depth)
1939 {
1940 case 1:
1941 num_palette = 2;
1942 color_inc = 0xff;
1943 break;
1944 case 2:
1945 num_palette = 4;
1946 color_inc = 0x55;
1947 break;
1948 case 4:
1949 num_palette = 16;
1950 color_inc = 0x11;
1951 break;
1952 case 8:
1953 num_palette = 256;
1954 color_inc = 1;
1955 break;
1956 default:
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001957 num_palette = 0;
Guy Schalnat69b14481996-01-10 02:56:49 -06001958 color_inc = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05001959 break;
1960 }
1961
1962 for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
1963 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001964 palette[i].red = (png_byte)v;
1965 palette[i].green = (png_byte)v;
1966 palette[i].blue = (png_byte)v;
Guy Schalnat0d580581995-07-20 02:43:20 -05001967 }
1968}
1969
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001970/* This function is currently unused. Do we really need it? */
1971#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001972void
Guy Schalnat6d764711995-12-19 03:22:19 -06001973png_correct_palette(png_structp png_ptr, png_colorp palette,
Guy Schalnat0d580581995-07-20 02:43:20 -05001974 int num_palette)
1975{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001976 png_debug(1, "in png_correct_palette\n");
Guy Schalnate5a37791996-06-05 15:50:50 -05001977#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001978 if ((png_ptr->transformations & (PNG_GAMMA)) &&
1979 (png_ptr->transformations & (PNG_BACKGROUND)))
1980 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001981 png_color back, back_1;
Guy Schalnat0d580581995-07-20 02:43:20 -05001982
Andreas Dilger47a0c421997-05-16 02:46:07 -05001983 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
1984 {
Guy Schalnate5a37791996-06-05 15:50:50 -05001985 back.red = png_ptr->gamma_table[png_ptr->background.red];
1986 back.green = png_ptr->gamma_table[png_ptr->background.green];
1987 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
Guy Schalnat0d580581995-07-20 02:43:20 -05001988
Guy Schalnate5a37791996-06-05 15:50:50 -05001989 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
1990 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
1991 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001992 }
1993 else
1994 {
1995 double g;
Guy Schalnat0d580581995-07-20 02:43:20 -05001996
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001997 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001998
1999 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2000 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
Guy Schalnat0d580581995-07-20 02:43:20 -05002001 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002002 back.red = png_ptr->background.red;
2003 back.green = png_ptr->background.green;
2004 back.blue = png_ptr->background.blue;
2005 }
2006 else
2007 {
2008 back.red =
2009 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2010 255.0 + 0.5);
2011 back.green =
2012 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2013 255.0 + 0.5);
2014 back.blue =
2015 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2016 255.0 + 0.5);
2017 }
2018
2019 g = 1.0 / png_ptr->background_gamma;
2020
2021 back_1.red =
2022 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2023 255.0 + 0.5);
2024 back_1.green =
2025 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2026 255.0 + 0.5);
2027 back_1.blue =
2028 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2029 255.0 + 0.5);
2030 }
2031
2032 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2033 {
2034 png_uint_32 i;
2035
2036 for (i = 0; i < (png_uint_32)num_palette; i++)
2037 {
2038 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -05002039 {
2040 palette[i] = back;
2041 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002042 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002043 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002044 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002045
2046 v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002047 png_composite(w, v, png_ptr->trans[i], back_1.red);
2048 palette[i].red = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002049
2050 v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002051 png_composite(w, v, png_ptr->trans[i], back_1.green);
2052 palette[i].green = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002053
2054 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002055 png_composite(w, v, png_ptr->trans[i], back_1.blue);
2056 palette[i].blue = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002057 }
2058 else
2059 {
2060 palette[i].red = png_ptr->gamma_table[palette[i].red];
2061 palette[i].green = png_ptr->gamma_table[palette[i].green];
2062 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2063 }
2064 }
2065 }
2066 else
2067 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002068 int i;
Guy Schalnat0d580581995-07-20 02:43:20 -05002069
2070 for (i = 0; i < num_palette; i++)
2071 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002072 if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002073 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002074 palette[i] = back;
Guy Schalnat0d580581995-07-20 02:43:20 -05002075 }
2076 else
2077 {
2078 palette[i].red = png_ptr->gamma_table[palette[i].red];
2079 palette[i].green = png_ptr->gamma_table[palette[i].green];
2080 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2081 }
2082 }
2083 }
2084 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002085 else
2086#endif
2087#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002088 if (png_ptr->transformations & PNG_GAMMA)
Guy Schalnat0d580581995-07-20 02:43:20 -05002089 {
2090 int i;
2091
2092 for (i = 0; i < num_palette; i++)
2093 {
2094 palette[i].red = png_ptr->gamma_table[palette[i].red];
2095 palette[i].green = png_ptr->gamma_table[palette[i].green];
2096 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2097 }
2098 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002099#if defined(PNG_READ_BACKGROUND_SUPPORTED)
2100 else
2101#endif
2102#endif
2103#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002104 if (png_ptr->transformations & PNG_BACKGROUND)
Guy Schalnat0d580581995-07-20 02:43:20 -05002105 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002106 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05002107 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002108 png_color back;
Guy Schalnat0d580581995-07-20 02:43:20 -05002109
Guy Schalnate5a37791996-06-05 15:50:50 -05002110 back.red = (png_byte)png_ptr->background.red;
2111 back.green = (png_byte)png_ptr->background.green;
2112 back.blue = (png_byte)png_ptr->background.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002113
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06002114 for (i = 0; i < (int)png_ptr->num_trans; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002115 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002116 if (png_ptr->trans[i] == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -05002117 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002118 palette[i].red = back.red;
2119 palette[i].green = back.green;
2120 palette[i].blue = back.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002121 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002122 else if (png_ptr->trans[i] != 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002123 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002124 png_composite(palette[i].red, png_ptr->palette[i].red,
2125 png_ptr->trans[i], back.red);
2126 png_composite(palette[i].green, png_ptr->palette[i].green,
2127 png_ptr->trans[i], back.green);
2128 png_composite(palette[i].blue, png_ptr->palette[i].blue,
2129 png_ptr->trans[i], back.blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05002130 }
2131 }
2132 }
2133 else /* assume grayscale palette (what else could it be?) */
2134 {
2135 int i;
2136
2137 for (i = 0; i < num_palette; i++)
2138 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002139 if (i == (png_byte)png_ptr->trans_values.gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002140 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002141 palette[i].red = (png_byte)png_ptr->background.red;
2142 palette[i].green = (png_byte)png_ptr->background.green;
2143 palette[i].blue = (png_byte)png_ptr->background.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002144 }
2145 }
2146 }
2147 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002148#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002149}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002150#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002151
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002152#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002153/* Replace any alpha or transparency with the supplied background color.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002154 * "background" is already in the screen gamma, while "background_1" is
2155 * at a gamma of 1.0. Paletted files have already been taken care of.
2156 */
Guy Schalnat0d580581995-07-20 02:43:20 -05002157void
Guy Schalnat6d764711995-12-19 03:22:19 -06002158png_do_background(png_row_infop row_info, png_bytep row,
2159 png_color_16p trans_values, png_color_16p background,
2160 png_color_16p background_1,
2161 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002162 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2163 png_uint_16pp gamma_16_to_1, int gamma_shift)
Guy Schalnat0d580581995-07-20 02:43:20 -05002164{
Guy Schalnat6d764711995-12-19 03:22:19 -06002165 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002166 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002167 png_uint_32 row_width=row_info->width;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002168 int shift;
Guy Schalnate5a37791996-06-05 15:50:50 -05002169
Andreas Dilger47a0c421997-05-16 02:46:07 -05002170 png_debug(1, "in png_do_background\n");
2171 if (background != NULL &&
2172#if defined(PNG_USELESS_TESTS_SUPPORTED)
2173 row != NULL && row_info != NULL &&
2174#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002175 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
Andreas Dilger47a0c421997-05-16 02:46:07 -05002176 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
Guy Schalnat0d580581995-07-20 02:43:20 -05002177 {
2178 switch (row_info->color_type)
2179 {
2180 case PNG_COLOR_TYPE_GRAY:
2181 {
2182 switch (row_info->bit_depth)
2183 {
2184 case 1:
2185 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002186 sp = row;
2187 shift = 7;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002188 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002189 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002190 if ((png_uint_16)((*sp >> shift) & 0x1)
2191 == trans_values->gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002192 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002193 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2194 *sp |= (png_byte)(background->gray << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05002195 }
2196 if (!shift)
2197 {
2198 shift = 7;
2199 sp++;
2200 }
2201 else
2202 shift--;
2203 }
2204 break;
2205 }
2206 case 2:
2207 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002208#if defined(PNG_READ_GAMMA_SUPPORTED)
2209 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002210 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002211 sp = row;
2212 shift = 6;
2213 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002214 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002215 if ((png_uint_16)((*sp >> shift) & 0x3)
2216 == trans_values->gray)
2217 {
2218 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2219 *sp |= (png_byte)(background->gray << shift);
2220 }
2221 else
2222 {
2223 png_byte p = (*sp >> shift) & 0x3;
2224 png_byte g = (gamma_table [p | (p << 2) | (p << 4) |
2225 (p << 6)] >> 6) & 0x3;
2226 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2227 *sp |= (png_byte)(g << shift);
2228 }
2229 if (!shift)
2230 {
2231 shift = 6;
2232 sp++;
2233 }
2234 else
2235 shift -= 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002236 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002237 }
2238 else
2239#endif
2240 {
2241 sp = row;
2242 shift = 6;
2243 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002244 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002245 if ((png_uint_16)((*sp >> shift) & 0x3)
2246 == trans_values->gray)
2247 {
2248 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2249 *sp |= (png_byte)(background->gray << shift);
2250 }
2251 if (!shift)
2252 {
2253 shift = 6;
2254 sp++;
2255 }
2256 else
2257 shift -= 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002258 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002259 }
2260 break;
2261 }
2262 case 4:
2263 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002264#if defined(PNG_READ_GAMMA_SUPPORTED)
2265 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002266 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002267 sp = row;
2268 shift = 4;
2269 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002270 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002271 if ((png_uint_16)((*sp >> shift) & 0xf)
2272 == trans_values->gray)
2273 {
2274 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2275 *sp |= (png_byte)(background->gray << shift);
2276 }
2277 else
2278 {
2279 png_byte p = (*sp >> shift) & 0xf;
2280 png_byte g = (gamma_table[p | (p << 4)] >> 4) & 0xf;
2281 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2282 *sp |= (png_byte)(g << shift);
2283 }
2284 if (!shift)
2285 {
2286 shift = 4;
2287 sp++;
2288 }
2289 else
2290 shift -= 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05002291 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002292 }
2293 else
2294#endif
2295 {
2296 sp = row;
2297 shift = 4;
2298 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002299 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002300 if ((png_uint_16)((*sp >> shift) & 0xf)
2301 == trans_values->gray)
2302 {
2303 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2304 *sp |= (png_byte)(background->gray << shift);
2305 }
2306 if (!shift)
2307 {
2308 shift = 4;
2309 sp++;
2310 }
2311 else
2312 shift -= 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05002313 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002314 }
2315 break;
2316 }
2317 case 8:
2318 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002319#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002320 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002321 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002322 sp = row;
2323 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002324 {
2325 if (*sp == trans_values->gray)
2326 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002327 *sp = (png_byte)background->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05002328 }
2329 else
2330 {
2331 *sp = gamma_table[*sp];
2332 }
2333 }
2334 }
2335 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002336#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002337 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002338 sp = row;
2339 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002340 {
2341 if (*sp == trans_values->gray)
2342 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002343 *sp = (png_byte)background->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05002344 }
2345 }
2346 }
2347 break;
2348 }
2349 case 16:
2350 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002351#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002352 if (gamma_16 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002353 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002354 sp = row;
2355 for (i = 0; i < row_width; i++, sp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002356 {
2357 png_uint_16 v;
2358
Andreas Dilger47a0c421997-05-16 02:46:07 -05002359 v = ((png_uint_16)(*sp) << 8) + *(sp + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05002360 if (v == trans_values->gray)
2361 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002362 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002363 *sp = (png_byte)((background->gray >> 8) & 0xff);
2364 *(sp + 1) = (png_byte)(background->gray & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002365 }
2366 else
2367 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002368 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002369 *sp = (png_byte)((v >> 8) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002370 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002371 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002372 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002373 }
2374 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002375#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002376 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002377 sp = row;
2378 for (i = 0; i < row_width; i++, sp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002379 {
2380 png_uint_16 v;
2381
Andreas Dilger47a0c421997-05-16 02:46:07 -05002382 v = ((png_uint_16)(*sp) << 8) + *(sp + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05002383 if (v == trans_values->gray)
2384 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002385 *sp = (png_byte)((background->gray >> 8) & 0xff);
2386 *(sp + 1) = (png_byte)(background->gray & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002387 }
2388 }
2389 }
2390 break;
2391 }
2392 }
2393 break;
2394 }
2395 case PNG_COLOR_TYPE_RGB:
2396 {
2397 if (row_info->bit_depth == 8)
2398 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002399#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002400 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002401 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002402 sp = row;
2403 for (i = 0; i < row_width; i++, sp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002404 {
2405 if (*sp == trans_values->red &&
2406 *(sp + 1) == trans_values->green &&
2407 *(sp + 2) == trans_values->blue)
2408 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002409 *sp = (png_byte)background->red;
2410 *(sp + 1) = (png_byte)background->green;
2411 *(sp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002412 }
2413 else
2414 {
2415 *sp = gamma_table[*sp];
2416 *(sp + 1) = gamma_table[*(sp + 1)];
2417 *(sp + 2) = gamma_table[*(sp + 2)];
2418 }
2419 }
2420 }
2421 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002422#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002423 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002424 sp = row;
2425 for (i = 0; i < row_width; i++, sp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002426 {
2427 if (*sp == trans_values->red &&
2428 *(sp + 1) == trans_values->green &&
2429 *(sp + 2) == trans_values->blue)
2430 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002431 *sp = (png_byte)background->red;
2432 *(sp + 1) = (png_byte)background->green;
2433 *(sp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002434 }
2435 }
2436 }
2437 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002438 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002439 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002440#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002441 if (gamma_16 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002442 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002443 sp = row;
2444 for (i = 0; i < row_width; i++, sp += 6)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002445 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002446 png_uint_16 r = ((png_uint_16)(*sp) << 8) + *(sp + 1);
2447 png_uint_16 g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
2448 png_uint_16 b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002449 if (r == trans_values->red && g == trans_values->green &&
Guy Schalnat0d580581995-07-20 02:43:20 -05002450 b == trans_values->blue)
2451 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002452 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002453 *sp = (png_byte)((background->red >> 8) & 0xff);
2454 *(sp + 1) = (png_byte)(background->red & 0xff);
2455 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2456 *(sp + 3) = (png_byte)(background->green & 0xff);
2457 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2458 *(sp + 5) = (png_byte)(background->blue & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002459 }
2460 else
2461 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002462 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002463 *sp = (png_byte)((v >> 8) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002464 *(sp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002465 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002466 *(sp + 2) = (png_byte)((v >> 8) & 0xff);
2467 *(sp + 3) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002468 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002469 *(sp + 4) = (png_byte)((v >> 8) & 0xff);
2470 *(sp + 5) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002471 }
2472 }
2473 }
2474 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002475#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002476 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002477 sp = row;
2478 for (i = 0; i < row_width; i++, sp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05002479 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002480 png_uint_16 r = ((png_uint_16)(*sp) << 8) + *(sp + 1);
2481 png_uint_16 g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
2482 png_uint_16 b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5);
Guy Schalnat0d580581995-07-20 02:43:20 -05002483
Andreas Dilger47a0c421997-05-16 02:46:07 -05002484 if (r == trans_values->red && g == trans_values->green &&
Guy Schalnat0d580581995-07-20 02:43:20 -05002485 b == trans_values->blue)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002486 {
2487 *sp = (png_byte)((background->red >> 8) & 0xff);
2488 *(sp + 1) = (png_byte)(background->red & 0xff);
2489 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2490 *(sp + 3) = (png_byte)(background->green & 0xff);
2491 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2492 *(sp + 5) = (png_byte)(background->blue & 0xff);
2493 }
2494 }
2495 }
2496 }
2497 break;
2498 }
2499 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -05002500 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002501 if (row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05002502 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002503#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002504 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2505 gamma_table != NULL)
2506 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002507 sp = row;
2508 dp = row;
2509 for (i = 0; i < row_width; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002510 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002511 png_uint_16 a = *(sp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002512
Andreas Dilger47a0c421997-05-16 02:46:07 -05002513 if (a == 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002514 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002515 *dp = gamma_table[*sp];
2516 }
2517 else if (a == 0)
2518 {
2519 /* background is already in screen gamma */
2520 *dp = (png_byte)background->gray;
2521 }
2522 else
2523 {
2524 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002525
Andreas Dilger47a0c421997-05-16 02:46:07 -05002526 v = gamma_to_1[*sp];
2527 png_composite(w, v, a, background_1->gray);
2528 *dp = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002529 }
2530 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002531 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002532 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002533#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05002534 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002535 sp = row;
2536 dp = row;
2537 for (i = 0; i < row_width; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002538 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002539 png_byte a = *(sp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002540
Andreas Dilger47a0c421997-05-16 02:46:07 -05002541 if (a == 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002542 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002543 *dp = *sp;
2544 }
2545 else if (a == 0)
2546 {
2547 *dp = (png_byte)background->gray;
2548 }
2549 else
2550 {
2551 png_composite(*dp, *sp, a, background_1->gray);
Guy Schalnat0d580581995-07-20 02:43:20 -05002552 }
2553 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002554 }
2555 }
2556 else /* if (png_ptr->bit_depth == 16) */
2557 {
2558#if defined(PNG_READ_GAMMA_SUPPORTED)
2559 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
2560 gamma_16_to_1 != NULL)
2561 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002562 sp = row;
2563 dp = row;
2564 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002565 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002566 png_uint_16 a = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002567
Andreas Dilger47a0c421997-05-16 02:46:07 -05002568 if (a == (png_uint_16)0xffff)
2569 {
2570 png_uint_16 v;
2571
2572 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2573 *dp = (png_byte)((v >> 8) & 0xff);
2574 *(dp + 1) = (png_byte)(v & 0xff);
2575 }
2576 else if (a == 0)
2577 {
2578 /* background is already in screen gamma */
2579 *dp = (png_byte)((background->gray >> 8) & 0xff);
2580 *(dp + 1) = (png_byte)(background->gray & 0xff);
2581 }
2582 else
2583 {
2584 png_uint_16 g, v, w;
2585
2586 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
2587 png_composite_16(v, g, a, background_1->gray);
2588 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
2589 *dp = (png_byte)((w >> 8) & 0xff);
2590 *(dp + 1) = (png_byte)(w & 0xff);
2591 }
2592 }
2593 }
2594 else
2595#endif
2596 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002597 sp = row;
2598 dp = row;
2599 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002600 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002601 png_uint_16 a = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002602 if (a == (png_uint_16)0xffff)
2603 {
2604 png_memcpy(dp, sp, 2);
2605 }
2606 else if (a == 0)
2607 {
2608 *dp = (png_byte)((background->gray >> 8) & 0xff);
2609 *(dp + 1) = (png_byte)(background->gray & 0xff);
2610 }
2611 else
2612 {
2613 png_uint_16 g, v;
2614
2615 g = ((png_uint_16)(*sp) << 8) + *(sp + 1);
2616 png_composite_16(v, g, a, background_1->gray);
2617 *dp = (png_byte)((v >> 8) & 0xff);
2618 *(dp + 1) = (png_byte)(v & 0xff);
2619 }
2620 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002621 }
2622 }
2623 break;
2624 }
2625 case PNG_COLOR_TYPE_RGB_ALPHA:
2626 {
2627 if (row_info->bit_depth == 8)
2628 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002629#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002630 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2631 gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002632 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002633 sp = row;
2634 dp = row;
2635 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002636 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002637 png_byte a = *(sp + 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05002638
Guy Schalnat0d580581995-07-20 02:43:20 -05002639 if (a == 0xff)
2640 {
2641 *dp = gamma_table[*sp];
2642 *(dp + 1) = gamma_table[*(sp + 1)];
2643 *(dp + 2) = gamma_table[*(sp + 2)];
2644 }
2645 else if (a == 0)
2646 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002647 /* background is already in screen gamma */
2648 *dp = (png_byte)background->red;
2649 *(dp + 1) = (png_byte)background->green;
2650 *(dp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002651 }
2652 else
2653 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002654 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002655
2656 v = gamma_to_1[*sp];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002657 png_composite(w, v, a, background_1->red);
2658 *dp = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002659 v = gamma_to_1[*(sp + 1)];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002660 png_composite(w, v, a, background_1->green);
2661 *(dp + 1) = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002662 v = gamma_to_1[*(sp + 2)];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002663 png_composite(w, v, a, background_1->blue);
2664 *(dp + 2) = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002665 }
2666 }
2667 }
2668 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002669#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002670 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002671 sp = row;
2672 dp = row;
2673 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002674 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002675 png_byte a = *(sp + 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05002676
Guy Schalnat0d580581995-07-20 02:43:20 -05002677 if (a == 0xff)
2678 {
2679 *dp = *sp;
2680 *(dp + 1) = *(sp + 1);
2681 *(dp + 2) = *(sp + 2);
2682 }
2683 else if (a == 0)
2684 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002685 *dp = (png_byte)background->red;
2686 *(dp + 1) = (png_byte)background->green;
2687 *(dp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002688 }
2689 else
2690 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002691 png_composite(*dp, *sp, a, background->red);
2692 png_composite(*(dp + 1), *(sp + 1), a,
2693 background->green);
2694 png_composite(*(dp + 2), *(sp + 2), a,
2695 background->blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05002696 }
2697 }
2698 }
2699 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002700 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002701 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002702#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002703 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
2704 gamma_16_to_1 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002705 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002706 sp = row;
2707 dp = row;
2708 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05002709 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002710 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
2711 << 8) + (png_uint_16)(*(sp + 7)));
Guy Schalnat0d580581995-07-20 02:43:20 -05002712 if (a == (png_uint_16)0xffff)
2713 {
2714 png_uint_16 v;
2715
Andreas Dilger47a0c421997-05-16 02:46:07 -05002716 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002717 *dp = (png_byte)((v >> 8) & 0xff);
2718 *(dp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002719 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002720 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
2721 *(dp + 3) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002722 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002723 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
2724 *(dp + 5) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002725 }
2726 else if (a == 0)
2727 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002728 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002729 *dp = (png_byte)((background->red >> 8) & 0xff);
2730 *(dp + 1) = (png_byte)(background->red & 0xff);
2731 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
2732 *(dp + 3) = (png_byte)(background->green & 0xff);
2733 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2734 *(dp + 5) = (png_byte)(background->blue & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002735 }
2736 else
2737 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002738 png_uint_16 v, w, x;
Guy Schalnat0d580581995-07-20 02:43:20 -05002739
Andreas Dilger47a0c421997-05-16 02:46:07 -05002740 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
2741 png_composite_16(w, v, a, background->red);
2742 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
2743 *dp = (png_byte)((x >> 8) & 0xff);
2744 *(dp + 1) = (png_byte)(x & 0xff);
2745 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
2746 png_composite_16(w, v, a, background->green);
2747 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
2748 *(dp + 2) = (png_byte)((x >> 8) & 0xff);
2749 *(dp + 3) = (png_byte)(x & 0xff);
2750 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
2751 png_composite_16(w, v, a, background->blue);
2752 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
2753 *(dp + 4) = (png_byte)((x >> 8) & 0xff);
2754 *(dp + 5) = (png_byte)(x & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002755 }
2756 }
2757 }
2758 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002759#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002760 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002761 sp = row;
2762 dp = row;
2763 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05002764 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002765 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
2766 << 8) + (png_uint_16)(*(sp + 7)));
Guy Schalnat0d580581995-07-20 02:43:20 -05002767 if (a == (png_uint_16)0xffff)
2768 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002769 png_memcpy(dp, sp, 6);
Guy Schalnat0d580581995-07-20 02:43:20 -05002770 }
2771 else if (a == 0)
2772 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002773 *dp = (png_byte)((background->red >> 8) & 0xff);
2774 *(dp + 1) = (png_byte)(background->red & 0xff);
2775 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
2776 *(dp + 3) = (png_byte)(background->green & 0xff);
2777 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2778 *(dp + 5) = (png_byte)(background->blue & 0xff);
2779 }
2780 else
Guy Schalnat0d580581995-07-20 02:43:20 -05002781 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002782 png_uint_16 v;
Guy Schalnat0d580581995-07-20 02:43:20 -05002783
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002784 png_uint_16 r = ((png_uint_16)(*sp) << 8) + *(sp + 1);
2785 png_uint_16 g = ((png_uint_16)(*(sp + 2)) << 8)
2786 + *(sp + 3);
2787 png_uint_16 b = ((png_uint_16)(*(sp + 4)) << 8)
2788 + *(sp + 5);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002789
2790 png_composite_16(v, r, a, background->red);
Guy Schalnat0d580581995-07-20 02:43:20 -05002791 *dp = (png_byte)((v >> 8) & 0xff);
2792 *(dp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002793 png_composite_16(v, g, a, background->green);
Guy Schalnat0d580581995-07-20 02:43:20 -05002794 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
2795 *(dp + 3) = (png_byte)(v & 0xff);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002796 png_composite_16(v, b, a, background->blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05002797 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
2798 *(dp + 5) = (png_byte)(v & 0xff);
2799 }
2800 }
2801 }
2802 }
2803 break;
2804 }
2805 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002806
Guy Schalnat0d580581995-07-20 02:43:20 -05002807 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
2808 {
2809 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
Guy Schalnate5a37791996-06-05 15:50:50 -05002810 row_info->channels--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002811 row_info->pixel_depth = (png_byte)(row_info->channels *
2812 row_info->bit_depth);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002813 row_info->rowbytes = ((row_width *
Guy Schalnat0d580581995-07-20 02:43:20 -05002814 row_info->pixel_depth + 7) >> 3);
2815 }
2816 }
2817}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002818#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002819
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002820#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002821/* Gamma correct the image, avoiding the alpha channel. Make sure
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002822 * you do this after you deal with the transparency issue on grayscale
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002823 * or rgb images. If your bit depth is 8, use gamma_table, if it
2824 * is 16, use gamma_16_table and gamma_shift. Build these with
2825 * build_gamma_table().
2826 */
Guy Schalnat0d580581995-07-20 02:43:20 -05002827void
Guy Schalnat6d764711995-12-19 03:22:19 -06002828png_do_gamma(png_row_infop row_info, png_bytep row,
2829 png_bytep gamma_table, png_uint_16pp gamma_16_table,
Guy Schalnat0d580581995-07-20 02:43:20 -05002830 int gamma_shift)
2831{
Guy Schalnat6d764711995-12-19 03:22:19 -06002832 png_bytep sp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002833 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002834 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06002835
Andreas Dilger47a0c421997-05-16 02:46:07 -05002836 png_debug(1, "in png_do_gamma\n");
2837 if (
2838#if defined(PNG_USELESS_TESTS_SUPPORTED)
2839 row != NULL && row_info != NULL &&
2840#endif
2841 ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
2842 (row_info->bit_depth == 16 && gamma_16_table != NULL)))
Guy Schalnat0d580581995-07-20 02:43:20 -05002843 {
2844 switch (row_info->color_type)
2845 {
2846 case PNG_COLOR_TYPE_RGB:
2847 {
2848 if (row_info->bit_depth == 8)
2849 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002850 sp = row;
2851 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002852 {
2853 *sp = gamma_table[*sp];
2854 sp++;
2855 *sp = gamma_table[*sp];
2856 sp++;
2857 *sp = gamma_table[*sp];
2858 sp++;
2859 }
2860 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002861 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002862 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002863 sp = row;
2864 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002865 {
2866 png_uint_16 v;
2867
Andreas Dilger47a0c421997-05-16 02:46:07 -05002868 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002869 *sp = (png_byte)((v >> 8) & 0xff);
2870 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002871 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002872 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002873 *sp = (png_byte)((v >> 8) & 0xff);
2874 *(sp + 1) = (png_byte)(v & 0xff);
2875 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002876 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002877 *sp = (png_byte)((v >> 8) & 0xff);
2878 *(sp + 1) = (png_byte)(v & 0xff);
2879 sp += 2;
2880 }
2881 }
2882 break;
2883 }
2884 case PNG_COLOR_TYPE_RGB_ALPHA:
2885 {
2886 if (row_info->bit_depth == 8)
2887 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002888 sp = row;
2889 for (i = 0; i < row_width; i++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002890 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002891 *sp = gamma_table[*sp];
2892 sp++;
2893 *sp = gamma_table[*sp];
2894 sp++;
2895 *sp = gamma_table[*sp];
2896 sp++;
2897 sp++;
2898 }
2899 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002900 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002901 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002902 sp = row;
2903 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002904 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002905 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002906 *sp = (png_byte)((v >> 8) & 0xff);
2907 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002908 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002909 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002910 *sp = (png_byte)((v >> 8) & 0xff);
2911 *(sp + 1) = (png_byte)(v & 0xff);
2912 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002913 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002914 *sp = (png_byte)((v >> 8) & 0xff);
2915 *(sp + 1) = (png_byte)(v & 0xff);
2916 sp += 4;
2917 }
2918 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002919 break;
2920 }
2921 case PNG_COLOR_TYPE_GRAY_ALPHA:
2922 {
2923 if (row_info->bit_depth == 8)
2924 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002925 sp = row;
2926 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002927 {
2928 *sp = gamma_table[*sp];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002929 sp += 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002930 }
2931 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002932 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002933 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002934 sp = row;
2935 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002936 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002937 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002938 *sp = (png_byte)((v >> 8) & 0xff);
2939 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002940 sp += 4;
2941 }
2942 }
2943 break;
2944 }
2945 case PNG_COLOR_TYPE_GRAY:
2946 {
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06002947 if (row_info->bit_depth == 2)
2948 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002949 sp = row;
2950 for (i = 0; i < row_width; i += 4)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06002951 {
2952 int a = *sp & 0xc0;
2953 int b = *sp & 0x30;
2954 int c = *sp & 0x0c;
2955 int d = *sp & 0x03;
2956
2957 *sp = ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
2958 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
2959 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
2960 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) );
2961 sp++;
2962 }
2963 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002964 if (row_info->bit_depth == 4)
Guy Schalnat0d580581995-07-20 02:43:20 -05002965 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002966 sp = row;
2967 for (i = 0; i < row_width; i += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002968 {
2969 int msb = *sp & 0xf0;
2970 int lsb = *sp & 0x0f;
2971
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002972 *sp = (((int)gamma_table[msb | (msb >> 4)]) & 0xf0) |
2973 (((int)gamma_table[(lsb << 4) | lsb]) >> 4);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002974 sp++;
2975 }
2976 }
2977 else if (row_info->bit_depth == 8)
2978 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002979 sp = row;
2980 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002981 {
2982 *sp = gamma_table[*sp];
2983 sp++;
2984 }
2985 }
2986 else if (row_info->bit_depth == 16)
2987 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002988 sp = row;
2989 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002990 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002991 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002992 *sp = (png_byte)((v >> 8) & 0xff);
2993 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002994 sp += 2;
2995 }
2996 }
2997 break;
2998 }
2999 }
3000 }
3001}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003002#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003003
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003004#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003005/* Expands a palette row to an rgb or rgba row depending
3006 * upon whether you supply trans and num_trans.
3007 */
Guy Schalnat0d580581995-07-20 02:43:20 -05003008void
Guy Schalnat6d764711995-12-19 03:22:19 -06003009png_do_expand_palette(png_row_infop row_info, png_bytep row,
Andreas Dilger47a0c421997-05-16 02:46:07 -05003010 png_colorp palette, png_bytep trans, int num_trans)
Guy Schalnat0d580581995-07-20 02:43:20 -05003011{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003012 int shift, value;
Guy Schalnat6d764711995-12-19 03:22:19 -06003013 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003014 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003015 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003016
Andreas Dilger47a0c421997-05-16 02:46:07 -05003017 png_debug(1, "in png_do_expand_palette\n");
3018 if (
3019#if defined(PNG_USELESS_TESTS_SUPPORTED)
3020 row != NULL && row_info != NULL &&
3021#endif
3022 row_info->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05003023 {
3024 if (row_info->bit_depth < 8)
3025 {
3026 switch (row_info->bit_depth)
3027 {
3028 case 1:
3029 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003030 sp = row + (png_size_t)((row_width - 1) >> 3);
3031 dp = row + (png_size_t)row_width - 1;
3032 shift = 7 - (int)((row_width + 7) & 7);
3033 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003034 {
3035 if ((*sp >> shift) & 0x1)
3036 *dp = 1;
3037 else
3038 *dp = 0;
3039 if (shift == 7)
3040 {
3041 shift = 0;
3042 sp--;
3043 }
3044 else
3045 shift++;
3046
3047 dp--;
3048 }
3049 break;
3050 }
3051 case 2:
3052 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003053 sp = row + (png_size_t)((row_width - 1) >> 2);
3054 dp = row + (png_size_t)row_width - 1;
3055 shift = (int)((3 - ((row_width + 3) & 3)) << 1);
3056 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003057 {
3058 value = (*sp >> shift) & 0x3;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003059 *dp = (png_byte)value;
Guy Schalnat0d580581995-07-20 02:43:20 -05003060 if (shift == 6)
3061 {
3062 shift = 0;
3063 sp--;
3064 }
3065 else
3066 shift += 2;
3067
3068 dp--;
3069 }
3070 break;
3071 }
3072 case 4:
3073 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003074 sp = row + (png_size_t)((row_width - 1) >> 1);
3075 dp = row + (png_size_t)row_width - 1;
3076 shift = (int)((row_width & 1) << 2);
3077 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003078 {
3079 value = (*sp >> shift) & 0xf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003080 *dp = (png_byte)value;
Guy Schalnat0d580581995-07-20 02:43:20 -05003081 if (shift == 4)
3082 {
3083 shift = 0;
3084 sp--;
3085 }
3086 else
3087 shift += 4;
3088
3089 dp--;
3090 }
3091 break;
3092 }
3093 }
3094 row_info->bit_depth = 8;
3095 row_info->pixel_depth = 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003096 row_info->rowbytes = row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -05003097 }
3098 switch (row_info->bit_depth)
3099 {
3100 case 8:
3101 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003102 if (trans != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05003103 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003104 sp = row + (png_size_t)row_width - 1;
3105 dp = row + (png_size_t)(row_width << 2) - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003106
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003107 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003108 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003109 if ((int)(*sp) >= num_trans)
Guy Schalnat0d580581995-07-20 02:43:20 -05003110 *dp-- = 0xff;
3111 else
3112 *dp-- = trans[*sp];
3113 *dp-- = palette[*sp].blue;
3114 *dp-- = palette[*sp].green;
3115 *dp-- = palette[*sp].red;
3116 sp--;
3117 }
3118 row_info->bit_depth = 8;
3119 row_info->pixel_depth = 32;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003120 row_info->rowbytes = row_width * 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05003121 row_info->color_type = 6;
3122 row_info->channels = 4;
3123 }
3124 else
3125 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003126 sp = row + (png_size_t)row_width - 1;
3127 dp = row + (png_size_t)(row_width * 3) - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003128
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003129 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003130 {
3131 *dp-- = palette[*sp].blue;
3132 *dp-- = palette[*sp].green;
3133 *dp-- = palette[*sp].red;
3134 sp--;
3135 }
3136 row_info->bit_depth = 8;
3137 row_info->pixel_depth = 24;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003138 row_info->rowbytes = row_width * 3;
Guy Schalnat0d580581995-07-20 02:43:20 -05003139 row_info->color_type = 2;
3140 row_info->channels = 3;
3141 }
3142 break;
3143 }
3144 }
3145 }
3146}
3147
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003148/* If the bit depth < 8, it is expanded to 8. Also, if the
3149 * transparency value is supplied, an alpha channel is built.
3150 */
Guy Schalnat0d580581995-07-20 02:43:20 -05003151void
Guy Schalnat6d764711995-12-19 03:22:19 -06003152png_do_expand(png_row_infop row_info, png_bytep row,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003153 png_color_16p trans_value)
Guy Schalnat0d580581995-07-20 02:43:20 -05003154{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003155 int shift, value;
Guy Schalnat6d764711995-12-19 03:22:19 -06003156 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003157 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003158 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003159
Andreas Dilger47a0c421997-05-16 02:46:07 -05003160 png_debug(1, "in png_do_expand\n");
3161#if defined(PNG_USELESS_TESTS_SUPPORTED)
3162 if (row != NULL && row_info != NULL)
3163#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003164 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003165 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05003166 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003167 png_uint_16 gray = trans_value ? trans_value->gray : 0;
3168
3169 if (row_info->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003170 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003171 switch (row_info->bit_depth)
Guy Schalnat0d580581995-07-20 02:43:20 -05003172 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003173 case 1:
3174 {
3175 gray *= 0xff;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003176 sp = row + (png_size_t)((row_width - 1) >> 3);
3177 dp = row + (png_size_t)row_width - 1;
3178 shift = 7 - (int)((row_width + 7) & 7);
3179 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003180 {
3181 if ((*sp >> shift) & 0x1)
3182 *dp = 0xff;
3183 else
3184 *dp = 0;
3185 if (shift == 7)
3186 {
3187 shift = 0;
3188 sp--;
3189 }
3190 else
3191 shift++;
3192
3193 dp--;
3194 }
3195 break;
3196 }
3197 case 2:
3198 {
3199 gray *= 0x55;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003200 sp = row + (png_size_t)((row_width - 1) >> 2);
3201 dp = row + (png_size_t)row_width - 1;
3202 shift = (int)((3 - ((row_width + 3) & 3)) << 1);
3203 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003204 {
3205 value = (*sp >> shift) & 0x3;
3206 *dp = (png_byte)(value | (value << 2) | (value << 4) |
3207 (value << 6));
3208 if (shift == 6)
3209 {
3210 shift = 0;
3211 sp--;
3212 }
3213 else
3214 shift += 2;
3215
3216 dp--;
3217 }
3218 break;
3219 }
3220 case 4:
3221 {
3222 gray *= 0x11;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003223 sp = row + (png_size_t)((row_width - 1) >> 1);
3224 dp = row + (png_size_t)row_width - 1;
3225 shift = (int)((1 - ((row_width + 1) & 1)) << 2);
3226 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003227 {
3228 value = (*sp >> shift) & 0xf;
3229 *dp = (png_byte)(value | (value << 4));
3230 if (shift == 4)
3231 {
3232 shift = 0;
3233 sp--;
3234 }
3235 else
3236 shift = 4;
3237
3238 dp--;
3239 }
3240 break;
3241 }
3242 }
3243 row_info->bit_depth = 8;
3244 row_info->pixel_depth = 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003245 row_info->rowbytes = row_width;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003246 }
3247
Andreas Dilger47a0c421997-05-16 02:46:07 -05003248 if (trans_value != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003249 {
3250 if (row_info->bit_depth == 8)
3251 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003252 sp = row + (png_size_t)row_width - 1;
3253 dp = row + (png_size_t)(row_width << 1) - 1;
3254 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003255 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003256 if (*sp == gray)
3257 *dp-- = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003258 else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003259 *dp-- = 0xff;
3260 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003261 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003262 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003263 else if (row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -05003264 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003265 sp = row + row_info->rowbytes - 1;
3266 dp = row + (row_info->rowbytes << 1) - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003267 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003268 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003269 if (((png_uint_16)*(sp) |
3270 ((png_uint_16)*(sp - 1) << 8)) == gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05003271 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003272 *dp-- = 0;
3273 *dp-- = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003274 }
3275 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003276 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003277 *dp-- = 0xff;
3278 *dp-- = 0xff;
Guy Schalnat0d580581995-07-20 02:43:20 -05003279 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003280 *dp-- = *sp--;
3281 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003282 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003283 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003284 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3285 row_info->channels = 2;
3286 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3287 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003288 ((row_width * row_info->pixel_depth) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003289 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003290 }
3291 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3292 {
3293 if (row_info->bit_depth == 8)
3294 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003295 sp = row + (png_size_t)row_info->rowbytes - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003296 dp = row + (png_size_t)(row_width << 2) - 1;
3297 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003298 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003299 if (*(sp - 2) == trans_value->red &&
Guy Schalnat0d580581995-07-20 02:43:20 -05003300 *(sp - 1) == trans_value->green &&
3301 *(sp - 0) == trans_value->blue)
3302 *dp-- = 0;
3303 else
3304 *dp-- = 0xff;
3305 *dp-- = *sp--;
3306 *dp-- = *sp--;
3307 *dp-- = *sp--;
3308 }
3309 }
3310 else if (row_info->bit_depth == 16)
3311 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003312 sp = row + row_info->rowbytes - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003313 dp = row + (png_size_t)(row_width << 3) - 1;
3314 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003315 {
3316 if ((((png_uint_16)*(sp - 4) |
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003317 ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
Guy Schalnat0d580581995-07-20 02:43:20 -05003318 (((png_uint_16)*(sp - 2) |
3319 ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
3320 (((png_uint_16)*(sp - 0) |
3321 ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
3322 {
3323 *dp-- = 0;
3324 *dp-- = 0;
3325 }
3326 else
3327 {
3328 *dp-- = 0xff;
3329 *dp-- = 0xff;
3330 }
3331 *dp-- = *sp--;
3332 *dp-- = *sp--;
3333 *dp-- = *sp--;
3334 *dp-- = *sp--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003335 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003336 *dp-- = *sp--;
3337 }
3338 }
3339 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3340 row_info->channels = 4;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003341 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
Guy Schalnat0d580581995-07-20 02:43:20 -05003342 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003343 ((row_width * row_info->pixel_depth) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003344 }
3345 }
3346}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003347#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003348
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003349#if defined(PNG_READ_DITHER_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003350void
Guy Schalnat6d764711995-12-19 03:22:19 -06003351png_do_dither(png_row_infop row_info, png_bytep row,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003352 png_bytep palette_lookup, png_bytep dither_lookup)
Guy Schalnat0d580581995-07-20 02:43:20 -05003353{
Guy Schalnat6d764711995-12-19 03:22:19 -06003354 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003355 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003356 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003357
Andreas Dilger47a0c421997-05-16 02:46:07 -05003358 png_debug(1, "in png_do_dither\n");
3359#if defined(PNG_USELESS_TESTS_SUPPORTED)
3360 if (row != NULL && row_info != NULL)
3361#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003362 {
3363 if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3364 palette_lookup && row_info->bit_depth == 8)
3365 {
3366 int r, g, b, p;
Guy Schalnat0d580581995-07-20 02:43:20 -05003367 sp = row;
3368 dp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003369 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003370 {
3371 r = *sp++;
3372 g = *sp++;
3373 b = *sp++;
3374
3375 /* this looks real messy, but the compiler will reduce
3376 it down to a reasonable formula. For example, with
3377 5 bits per color, we get:
3378 p = (((r >> 3) & 0x1f) << 10) |
3379 (((g >> 3) & 0x1f) << 5) |
3380 ((b >> 3) & 0x1f);
3381 */
3382 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3383 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3384 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3385 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003386 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
Guy Schalnat0d580581995-07-20 02:43:20 -05003387 (PNG_DITHER_BLUE_BITS)) |
3388 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3389 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3390
3391 *dp++ = palette_lookup[p];
3392 }
3393 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3394 row_info->channels = 1;
3395 row_info->pixel_depth = row_info->bit_depth;
3396 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003397 ((row_width * row_info->pixel_depth + 7) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003398 }
3399 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
Andreas Dilger47a0c421997-05-16 02:46:07 -05003400 palette_lookup != NULL && row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003401 {
3402 int r, g, b, p;
Guy Schalnat0d580581995-07-20 02:43:20 -05003403 sp = row;
3404 dp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003405 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003406 {
3407 r = *sp++;
3408 g = *sp++;
3409 b = *sp++;
3410 sp++;
3411
3412 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003413 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
Guy Schalnat0d580581995-07-20 02:43:20 -05003414 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3415 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3416 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3417 (PNG_DITHER_BLUE_BITS)) |
3418 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3419 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3420
3421 *dp++ = palette_lookup[p];
3422 }
3423 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3424 row_info->channels = 1;
3425 row_info->pixel_depth = row_info->bit_depth;
3426 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003427 ((row_width * row_info->pixel_depth + 7) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003428 }
3429 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
3430 dither_lookup && row_info->bit_depth == 8)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003431 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003432 sp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003433 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003434 {
3435 *sp = dither_lookup[*sp];
3436 }
3437 }
3438 }
3439}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003440#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003441
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003442#if defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003443static int png_gamma_shift[] =
3444 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
3445
Andreas Dilger47a0c421997-05-16 02:46:07 -05003446/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003447 * tables, we don't make a full table if we are reducing to 8-bit in
3448 * the future. Note also how the gamma_16 tables are segmented so that
3449 * we don't need to allocate > 64K chunks for a full 16-bit table.
3450 */
Guy Schalnat0d580581995-07-20 02:43:20 -05003451void
Guy Schalnat6d764711995-12-19 03:22:19 -06003452png_build_gamma_table(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05003453{
Andreas Dilger47a0c421997-05-16 02:46:07 -05003454 png_debug(1, "in png_build_gamma_table\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05003455 if (png_ptr->bit_depth <= 8)
3456 {
3457 int i;
3458 double g;
3459
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06003460 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -05003461
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003462 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003463 (png_uint_32)256);
3464
3465 for (i = 0; i < 256; i++)
3466 {
3467 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
3468 g) * 255.0 + .5);
3469 }
3470
Andreas Dilger47a0c421997-05-16 02:46:07 -05003471#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003472 if (png_ptr->transformations & PNG_BACKGROUND)
3473 {
3474 g = 1.0 / (png_ptr->gamma);
3475
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003476 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003477 (png_uint_32)256);
3478
3479 for (i = 0; i < 256; i++)
3480 {
3481 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
3482 g) * 255.0 + .5);
3483 }
3484
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06003485 g = 1.0 / (png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -05003486
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003487 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003488 (png_uint_32)256);
3489
3490 for (i = 0; i < 256; i++)
3491 {
3492 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
3493 g) * 255.0 + .5);
3494 }
3495 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003496#endif /* PNG_BACKGROUND_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003497 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003498 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003499 {
3500 double g;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003501 int i, j, shift, num;
3502 int sig_bit;
3503 png_uint_32 ig;
Guy Schalnat0d580581995-07-20 02:43:20 -05003504
3505 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003506 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003507 sig_bit = (int)png_ptr->sig_bit.red;
3508 if ((int)png_ptr->sig_bit.green > sig_bit)
3509 sig_bit = png_ptr->sig_bit.green;
3510 if ((int)png_ptr->sig_bit.blue > sig_bit)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003511 sig_bit = png_ptr->sig_bit.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003512 }
3513 else
3514 {
3515 sig_bit = (int)png_ptr->sig_bit.gray;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003516 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003517
3518 if (sig_bit > 0)
3519 shift = 16 - sig_bit;
3520 else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003521 shift = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003522
3523 if (png_ptr->transformations & PNG_16_TO_8)
3524 {
3525 if (shift < (16 - PNG_MAX_GAMMA_8))
3526 shift = (16 - PNG_MAX_GAMMA_8);
3527 }
3528
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003529 if (shift > 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003530 shift = 8;
3531 if (shift < 0)
3532 shift = 0;
3533
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003534 png_ptr->gamma_shift = (png_byte)shift;
Guy Schalnat0d580581995-07-20 02:43:20 -05003535
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003536 num = (1 << (8 - shift));
Guy Schalnat0d580581995-07-20 02:43:20 -05003537
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06003538 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -05003539
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003540 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003541 (png_uint_32)(num * sizeof (png_uint_16p)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003542
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003543 if ((png_ptr->transformations & PNG_16_TO_8) &&
3544 !(png_ptr->transformations & PNG_BACKGROUND))
3545 {
3546 double fin, fout;
3547 png_uint_32 last, max;
Guy Schalnat0d580581995-07-20 02:43:20 -05003548
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003549 for (i = 0; i < num; i++)
3550 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003551 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003552 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003553 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003554
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003555 g = 1.0 / g;
3556 last = 0;
3557 for (i = 0; i < 256; i++)
3558 {
3559 fout = ((double)i + 0.5) / 256.0;
3560 fin = pow(fout, g);
3561 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
3562 while (last <= max)
3563 {
3564 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
3565 [(int)(last >> (8 - shift))] = (png_uint_16)(
3566 (png_uint_16)i | ((png_uint_16)i << 8));
3567 last++;
3568 }
3569 }
3570 while (last < ((png_uint_32)num << 8))
3571 {
3572 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
Andreas Dilger47a0c421997-05-16 02:46:07 -05003573 [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003574 last++;
Guy Schalnat6d764711995-12-19 03:22:19 -06003575 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003576 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003577 else
3578 {
3579 for (i = 0; i < num; i++)
3580 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003581 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003582 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003583
Andreas Dilger47a0c421997-05-16 02:46:07 -05003584 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003585 for (j = 0; j < 256; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003586 {
3587 png_ptr->gamma_16_table[i][j] =
3588 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
3589 65535.0, g) * 65535.0 + .5);
3590 }
3591 }
3592 }
3593
Andreas Dilger47a0c421997-05-16 02:46:07 -05003594#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003595 if (png_ptr->transformations & PNG_BACKGROUND)
3596 {
3597 g = 1.0 / (png_ptr->gamma);
3598
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003599 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003600 (png_uint_32)(num * sizeof (png_uint_16p )));
Guy Schalnat0d580581995-07-20 02:43:20 -05003601
3602 for (i = 0; i < num; i++)
3603 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003604 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003605 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003606
3607 ig = (((png_uint_32)i *
3608 (png_uint_32)png_gamma_shift[shift]) >> 4);
3609 for (j = 0; j < 256; j++)
3610 {
3611 png_ptr->gamma_16_to_1[i][j] =
3612 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
3613 65535.0, g) * 65535.0 + .5);
3614 }
3615 }
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06003616 g = 1.0 / (png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -05003617
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003618 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003619 (png_uint_32)(num * sizeof (png_uint_16p)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003620
3621 for (i = 0; i < num; i++)
3622 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003623 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003624 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003625
3626 ig = (((png_uint_32)i *
3627 (png_uint_32)png_gamma_shift[shift]) >> 4);
3628 for (j = 0; j < 256; j++)
3629 {
3630 png_ptr->gamma_16_from_1[i][j] =
3631 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
3632 65535.0, g) * 65535.0 + .5);
3633 }
3634 }
3635 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003636#endif /* PNG_BACKGROUND_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003637 }
3638}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003639#endif
3640