blob: 693befcd5f542dabcc36962e7aa00003b6a41e2c [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-Pehrson6d8f3b01999-10-23 08:39:18 -05004 * libpng 1.0.5a - October 23, 1999
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-Pehrsonc9442291999-01-06 21:50:16 -06008 * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06009 *
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -060010 * This file contains functions optionally called by an application
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060011 * 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).
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600287 [We don't understand this at all, so if someone wants to
288 work on improving it, be our guest - AED, GRP]
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-Pehrson5c6aeb21998-12-29 11:47:59 -0600312 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600313 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)
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -0500525/* Expand paletted images to RGB, expand grayscale images of
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -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}
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500535
536/* GRR 19990627: the following three functions currently are identical
537 * to png_set_expand(). However, it is entirely reasonable that someone
538 * might wish to expand an indexed image to RGB but *not* expand a single,
539 * fully transparent palette entry to a full alpha channel--perhaps instead
540 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
541 * the transparent color with a particular RGB value, or drop tRNS entirely.
542 * IOW, a future version of the library may make the transformations flag
543 * a bit more fine-grained, with separate bits for each of these three
544 * functions.
545 *
546 * More to the point, these functions make it obvious what libpng will be
547 * doing, whereas "expand" can (and does) mean any number of things.
548 */
549
550/* Expand paletted images to RGB. */
551void
552png_set_palette_to_rgb(png_structp png_ptr)
553{
554 png_debug(1, "in png_set_expand\n");
555 png_ptr->transformations |= PNG_EXPAND;
556}
557
558/* Expand grayscale images of less than 8-bit depth to 8 bits. */
559void
560png_set_gray_1_2_4_to_8(png_structp png_ptr)
561{
562 png_debug(1, "in png_set_expand\n");
563 png_ptr->transformations |= PNG_EXPAND;
564}
565
566/* Expand tRNS chunks to alpha channels. */
567void
568png_set_tRNS_to_alpha(png_structp png_ptr)
569{
570 png_debug(1, "in png_set_expand\n");
571 png_ptr->transformations |= PNG_EXPAND;
572}
573#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
Guy Schalnat0d580581995-07-20 02:43:20 -0500574
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500575#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500576void
Guy Schalnat6d764711995-12-19 03:22:19 -0600577png_set_gray_to_rgb(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500578{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500579 png_debug(1, "in png_set_gray_to_rgb\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500580 png_ptr->transformations |= PNG_GRAY_TO_RGB;
581}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500582#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500583
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600584#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600585/* Convert a RGB image to a grayscale of the same width. This allows us,
586 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600587 */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600588void
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500589png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
590 double green)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600591{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500592 png_debug(1, "in png_set_rgb_to_gray\n");
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600593 switch(error_action)
594 {
595 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
596 break;
597 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
598 break;
599 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
600 }
601 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
602#if defined(PNG_READ_EXPAND_SUPPORTED)
603 png_ptr->transformations |= PNG_EXPAND;
604#else
605 {
606 png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
607 png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
608 }
609#endif
610 {
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500611 png_byte red_byte = (png_byte)((float)red*255.0 + 0.5);
612 png_byte green_byte = (png_byte)((float)green*255.0 + 0.5);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600613 if(red < 0.0 || green < 0.0)
614 {
615 red_byte = 54;
616 green_byte = 183;
617 }
618 else if(red_byte + green_byte > 255)
619 {
620 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
621 red_byte = 54;
622 green_byte = 183;
623 }
624 png_ptr->rgb_to_gray_red_coeff = red_byte;
625 png_ptr->rgb_to_gray_green_coeff = green_byte;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -0500626 png_ptr->rgb_to_gray_blue_coeff = (png_byte)(255-red_byte-green_byte);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600627 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600628}
629#endif
630
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600631#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
632void
633png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
634 read_user_transform_fn)
635{
636 png_debug(1, "in png_set_read_user_transform_fn\n");
637 png_ptr->transformations |= PNG_USER_TRANSFORM;
638 png_ptr->read_user_transform_fn = read_user_transform_fn;
639}
640#endif
641
Andreas Dilger47a0c421997-05-16 02:46:07 -0500642/* Initialize everything needed for the read. This includes modifying
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600643 * the palette.
644 */
Guy Schalnat0d580581995-07-20 02:43:20 -0500645void
Guy Schalnat6d764711995-12-19 03:22:19 -0600646png_init_read_transformations(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500647{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500648 png_debug(1, "in png_init_read_transformations\n");
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500649#if defined(PNG_USELESS_TESTS_SUPPORTED)
650 if(png_ptr != NULL)
651#endif
652 {
653#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
654 || defined(PNG_READ_GAMMA_SUPPORTED)
655 int color_type = png_ptr->color_type;
656#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500657
Guy Schalnate5a37791996-06-05 15:50:50 -0500658#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
659 if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -0500660 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500661 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
Guy Schalnat0d580581995-07-20 02:43:20 -0500662 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500663 /* expand background chunk. */
Guy Schalnat0d580581995-07-20 02:43:20 -0500664 switch (png_ptr->bit_depth)
665 {
666 case 1:
Guy Schalnate5a37791996-06-05 15:50:50 -0500667 png_ptr->background.gray *= (png_uint_16)0xff;
668 png_ptr->background.red = png_ptr->background.green =
669 png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500670 break;
671 case 2:
Guy Schalnate5a37791996-06-05 15:50:50 -0500672 png_ptr->background.gray *= (png_uint_16)0x55;
673 png_ptr->background.red = png_ptr->background.green =
674 png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500675 break;
676 case 4:
Guy Schalnate5a37791996-06-05 15:50:50 -0500677 png_ptr->background.gray *= (png_uint_16)0x11;
678 png_ptr->background.red = png_ptr->background.green =
679 png_ptr->background.blue = png_ptr->background.gray;
680 break;
681 case 8:
682 case 16:
683 png_ptr->background.red = png_ptr->background.green =
684 png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500685 break;
686 }
687 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500688 else if (color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -0500689 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500690 png_ptr->background.red =
Guy Schalnat0d580581995-07-20 02:43:20 -0500691 png_ptr->palette[png_ptr->background.index].red;
692 png_ptr->background.green =
693 png_ptr->palette[png_ptr->background.index].green;
Guy Schalnate5a37791996-06-05 15:50:50 -0500694 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -0500695 png_ptr->palette[png_ptr->background.index].blue;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600696
697#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
698 if (png_ptr->transformations & PNG_INVERT_ALPHA)
699 {
700#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600701 if (!(png_ptr->transformations & PNG_EXPAND))
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600702#endif
703 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600704 /* invert the alpha channel (in tRNS) unless the pixels are
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600705 going to be expanded, in which case leave it for later */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500706 int i,istop;
707 istop=(int)png_ptr->num_trans;
708 for (i=0; i<istop; i++)
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -0500709 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600710 }
711 }
712#endif
713
Guy Schalnat0d580581995-07-20 02:43:20 -0500714 }
715 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500716#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500717
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500718#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500719 png_ptr->background_1 = png_ptr->background;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500720#endif
721#if defined(PNG_READ_GAMMA_SUPPORTED)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600722 if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -0500723 {
724 png_build_gamma_table(png_ptr);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500725#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnate5a37791996-06-05 15:50:50 -0500726 if (png_ptr->transformations & PNG_BACKGROUND)
Guy Schalnat0d580581995-07-20 02:43:20 -0500727 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500728 if (color_type == PNG_COLOR_TYPE_PALETTE)
729 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500730 png_color back, back_1;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500731 png_colorp palette = png_ptr->palette;
732 int num_palette = png_ptr->num_palette;
733 int i;
Guy Schalnate5a37791996-06-05 15:50:50 -0500734
Andreas Dilger47a0c421997-05-16 02:46:07 -0500735 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
736 {
737 back.red = png_ptr->gamma_table[png_ptr->background.red];
738 back.green = png_ptr->gamma_table[png_ptr->background.green];
739 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
Guy Schalnate5a37791996-06-05 15:50:50 -0500740
Andreas Dilger47a0c421997-05-16 02:46:07 -0500741 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
742 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
743 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
744 }
745 else
746 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600747 double g, gs;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500748
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600749 switch (png_ptr->background_gamma_type)
Glenn Randers-Pehrson4922b1b1998-03-08 22:55:17 -0600750 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600751 case PNG_BACKGROUND_GAMMA_SCREEN:
752 g = (png_ptr->screen_gamma);
753 gs = 1.0;
754 break;
755 case PNG_BACKGROUND_GAMMA_FILE:
756 g = 1.0 / (png_ptr->gamma);
757 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
758 break;
759 case PNG_BACKGROUND_GAMMA_UNIQUE:
760 g = 1.0 / (png_ptr->background_gamma);
761 gs = 1.0 / (png_ptr->background_gamma *
762 png_ptr->screen_gamma);
763 break;
764 default:
765 g = 1.0; /* back_1 */
766 gs = 1.0; /* back */
767 }
768
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -0600769 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600770 {
771 back.red = (png_byte)png_ptr->background.red;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500772 back.green = (png_byte)png_ptr->background.green;
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600773 back.blue = (png_byte)png_ptr->background.blue;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500774 }
775 else
776 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600777 back.red = (png_byte)(pow(
778 (double)png_ptr->background.red/255, gs) * 255.0 + .5);
779 back.green = (png_byte)(pow(
780 (double)png_ptr->background.green/255, gs) * 255.0 + .5);
781 back.blue = (png_byte)(pow(
782 (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500783 }
784
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600785 back_1.red = (png_byte)(pow(
786 (double)png_ptr->background.red/255, g) * 255.0 + .5);
787 back_1.green = (png_byte)(pow(
788 (double)png_ptr->background.green/255, g) * 255.0 + .5);
789 back_1.blue = (png_byte)(pow(
790 (double)png_ptr->background.blue/255, g) * 255.0 + .5);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500791 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500792
793 for (i = 0; i < num_palette; i++)
794 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500795 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
Guy Schalnate5a37791996-06-05 15:50:50 -0500796 {
797 if (png_ptr->trans[i] == 0)
798 {
799 palette[i] = back;
800 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500801 else /* if (png_ptr->trans[i] != 0xff) */
Guy Schalnate5a37791996-06-05 15:50:50 -0500802 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500803 png_byte v, w;
Guy Schalnate5a37791996-06-05 15:50:50 -0500804
805 v = png_ptr->gamma_to_1[palette[i].red];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500806 png_composite(w, v, png_ptr->trans[i], back_1.red);
Guy Schalnate5a37791996-06-05 15:50:50 -0500807 palette[i].red = png_ptr->gamma_from_1[w];
808
809 v = png_ptr->gamma_to_1[palette[i].green];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500810 png_composite(w, v, png_ptr->trans[i], back_1.green);
Guy Schalnate5a37791996-06-05 15:50:50 -0500811 palette[i].green = png_ptr->gamma_from_1[w];
812
813 v = png_ptr->gamma_to_1[palette[i].blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500814 png_composite(w, v, png_ptr->trans[i], back_1.blue);
Guy Schalnate5a37791996-06-05 15:50:50 -0500815 palette[i].blue = png_ptr->gamma_from_1[w];
816 }
817 }
818 else
819 {
820 palette[i].red = png_ptr->gamma_table[palette[i].red];
821 palette[i].green = png_ptr->gamma_table[palette[i].green];
822 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
823 }
824 }
825 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500826 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN)*/
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600827 else
828 /* color_type != PNG_COLOR_TYPE_PALETTE */
Guy Schalnat0d580581995-07-20 02:43:20 -0500829 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500830 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
831 double g = 1.0;
832 double gs = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500833
834 switch (png_ptr->background_gamma_type)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600835 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500836 case PNG_BACKGROUND_GAMMA_SCREEN:
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600837 g = (png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500838 gs = 1.0;
839 break;
840 case PNG_BACKGROUND_GAMMA_FILE:
841 g = 1.0 / (png_ptr->gamma);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600842 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500843 break;
844 case PNG_BACKGROUND_GAMMA_UNIQUE:
845 g = 1.0 / (png_ptr->background_gamma);
846 gs = 1.0 / (png_ptr->background_gamma *
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600847 png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500848 break;
849 }
850
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600851 if (color_type & PNG_COLOR_MASK_COLOR)
Guy Schalnat0d580581995-07-20 02:43:20 -0500852 {
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600853 /* RGB or RGBA */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600854 png_ptr->background_1.red = (png_uint_16)(pow(
Guy Schalnat0d580581995-07-20 02:43:20 -0500855 (double)png_ptr->background.red / m, g) * m + .5);
856 png_ptr->background_1.green = (png_uint_16)(pow(
857 (double)png_ptr->background.green / m, g) * m + .5);
858 png_ptr->background_1.blue = (png_uint_16)(pow(
859 (double)png_ptr->background.blue / m, g) * m + .5);
860 png_ptr->background.red = (png_uint_16)(pow(
861 (double)png_ptr->background.red / m, gs) * m + .5);
862 png_ptr->background.green = (png_uint_16)(pow(
863 (double)png_ptr->background.green / m, gs) * m + .5);
864 png_ptr->background.blue = (png_uint_16)(pow(
865 (double)png_ptr->background.blue / m, gs) * m + .5);
866 }
867 else
868 {
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600869 /* GRAY or GRAY ALPHA */
Guy Schalnat0d580581995-07-20 02:43:20 -0500870 png_ptr->background_1.gray = (png_uint_16)(pow(
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600871 (double)png_ptr->background.gray / m, g) * m + .5);
Guy Schalnat0d580581995-07-20 02:43:20 -0500872 png_ptr->background.gray = (png_uint_16)(pow(
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600873 (double)png_ptr->background.gray / m, gs) * m + .5);
Guy Schalnat0d580581995-07-20 02:43:20 -0500874 }
875 }
876 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500877 else
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600878 /* transformation does not include PNG_BACKGROUND */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500879#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500880 if (color_type == PNG_COLOR_TYPE_PALETTE)
881 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500882 png_colorp palette = png_ptr->palette;
883 int num_palette = png_ptr->num_palette;
884 int i;
Guy Schalnate5a37791996-06-05 15:50:50 -0500885
886 for (i = 0; i < num_palette; i++)
887 {
888 palette[i].red = png_ptr->gamma_table[palette[i].red];
889 palette[i].green = png_ptr->gamma_table[palette[i].green];
890 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
891 }
892 }
893 }
894#if defined(PNG_READ_BACKGROUND_SUPPORTED)
895 else
896#endif
897#endif
898#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600899 /* No GAMMA transformation */
Guy Schalnate5a37791996-06-05 15:50:50 -0500900 if (png_ptr->transformations & PNG_BACKGROUND &&
901 color_type == PNG_COLOR_TYPE_PALETTE)
902 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500903 int i;
904 int istop = (int)png_ptr->num_trans;
Guy Schalnate5a37791996-06-05 15:50:50 -0500905 png_color back;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500906 png_colorp palette = png_ptr->palette;
Guy Schalnate5a37791996-06-05 15:50:50 -0500907
Guy Schalnate5a37791996-06-05 15:50:50 -0500908 back.red = (png_byte)png_ptr->background.red;
909 back.green = (png_byte)png_ptr->background.green;
910 back.blue = (png_byte)png_ptr->background.blue;
911
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500912 for (i = 0; i < istop; i++)
Guy Schalnate5a37791996-06-05 15:50:50 -0500913 {
914 if (png_ptr->trans[i] == 0)
915 {
916 palette[i] = back;
917 }
918 else if (png_ptr->trans[i] != 0xff)
919 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500920 /* The png_composite() macro is defined in png.h */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500921 png_composite(palette[i].red, palette[i].red,
922 png_ptr->trans[i], back.red);
923 png_composite(palette[i].green, palette[i].green,
924 png_ptr->trans[i], back.green);
925 png_composite(palette[i].blue, palette[i].blue,
926 png_ptr->trans[i], back.blue);
Guy Schalnate5a37791996-06-05 15:50:50 -0500927 }
928 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500929 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500930#endif
931
Guy Schalnat6d764711995-12-19 03:22:19 -0600932#if defined(PNG_READ_SHIFT_SUPPORTED)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500933 if ((png_ptr->transformations & PNG_SHIFT) &&
Guy Schalnat6d764711995-12-19 03:22:19 -0600934 color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500935 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500936 png_uint_16 i;
937 png_uint_16 istop = png_ptr->num_palette;
938 int sr = 8 - png_ptr->sig_bit.red;
939 int sg = 8 - png_ptr->sig_bit.green;
940 int sb = 8 - png_ptr->sig_bit.blue;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500941
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500942 if (sr < 0 || sr > 8)
943 sr = 0;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500944 if (sg < 0 || sg > 8)
945 sg = 0;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500946 if (sb < 0 || sb > 8)
947 sb = 0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500948 for (i = 0; i < istop; i++)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500949 {
950 png_ptr->palette[i].red >>= sr;
951 png_ptr->palette[i].green >>= sg;
952 png_ptr->palette[i].blue >>= sb;
953 }
954 }
955#endif
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500956 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500957}
958
Andreas Dilger47a0c421997-05-16 02:46:07 -0500959/* Modify the info structure to reflect the transformations. The
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600960 * info should be updated so a PNG file could be written with it,
961 * assuming the transformations result in valid PNG data.
962 */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500963void
Guy Schalnat6d764711995-12-19 03:22:19 -0600964png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500965{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500966 png_debug(1, "in png_read_transform_info\n");
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500967#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500968 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500969 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500970 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
971 {
972 if (png_ptr->num_trans)
973 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
974 else
975 info_ptr->color_type = PNG_COLOR_TYPE_RGB;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500976 info_ptr->bit_depth = 8;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500977 info_ptr->num_trans = 0;
978 }
979 else
980 {
981 if (png_ptr->num_trans)
982 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
983 if (info_ptr->bit_depth < 8)
984 info_ptr->bit_depth = 8;
985 info_ptr->num_trans = 0;
986 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500987 }
988#endif
989
990#if defined(PNG_READ_BACKGROUND_SUPPORTED)
991 if (png_ptr->transformations & PNG_BACKGROUND)
992 {
993 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
994 info_ptr->num_trans = 0;
995 info_ptr->background = png_ptr->background;
996 }
997#endif
998
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500999#if defined(PNG_READ_GAMMA_SUPPORTED)
1000 if (png_ptr->transformations & PNG_GAMMA)
1001 info_ptr->gamma = png_ptr->gamma;
1002#endif
1003
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001004#if defined(PNG_READ_16_TO_8_SUPPORTED)
1005 if ((png_ptr->transformations & PNG_16_TO_8) && info_ptr->bit_depth == 16)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001006 info_ptr->bit_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001007#endif
1008
1009#if defined(PNG_READ_DITHER_SUPPORTED)
1010 if (png_ptr->transformations & PNG_DITHER)
1011 {
1012 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1013 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1014 png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1015 {
1016 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1017 }
1018 }
1019#endif
1020
1021#if defined(PNG_READ_PACK_SUPPORTED)
1022 if ((png_ptr->transformations & PNG_PACK) && info_ptr->bit_depth < 8)
1023 info_ptr->bit_depth = 8;
1024#endif
1025
1026#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001027 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001028 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1029#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001030
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001031#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1032 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1033 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1034#endif
1035
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001036 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001037 info_ptr->channels = 1;
1038 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1039 info_ptr->channels = 3;
1040 else
1041 info_ptr->channels = 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001042
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001043#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001044 if (png_ptr->transformations & PNG_STRIP_ALPHA)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001045 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001046#endif
1047
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001048 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1049 info_ptr->channels++;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001050
1051#if defined(PNG_READ_FILLER_SUPPORTED)
1052 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
1053 if (png_ptr->transformations & PNG_FILLER &&
1054 (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
1055 info_ptr->color_type == PNG_COLOR_TYPE_GRAY))
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001056 info_ptr->channels++;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001057#endif
1058
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001059#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1060 if(png_ptr->transformations & PNG_USER_TRANSFORM)
1061 {
1062 if(info_ptr->bit_depth < png_ptr->user_transform_depth)
1063 info_ptr->bit_depth = png_ptr->user_transform_depth;
1064 if(info_ptr->channels < png_ptr->user_transform_channels)
1065 info_ptr->channels = png_ptr->user_transform_channels;
1066 }
1067#endif
1068
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001069 info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1070 info_ptr->bit_depth);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001071 info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3);
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05001072
Guy Schalnat0d580581995-07-20 02:43:20 -05001073}
1074
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001075/* Transform the row. The order of transformations is significant,
1076 * and is very touchy. If you add a transformation, take care to
1077 * decide how it fits in with the other transformations here.
1078 */
Guy Schalnat0d580581995-07-20 02:43:20 -05001079void
Guy Schalnat6d764711995-12-19 03:22:19 -06001080png_do_read_transformations(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05001081{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001082 png_debug(1, "in png_do_read_transformations\n");
1083#if !defined(PNG_USELESS_TESTS_SUPPORTED)
1084 if (png_ptr->row_buf == NULL)
1085 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001086#if !defined(PNG_NO_STDIO)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001087 char msg[50];
1088
1089 sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
1090 png_ptr->pass);
1091 png_error(png_ptr, msg);
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001092#else
1093 png_error(png_ptr, "NULL row buffer");
1094#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001095 }
1096#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001097
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001098#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001099 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05001100 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001101 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1102 {
1103 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1104 png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1105 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001106 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001107 {
1108 if (png_ptr->num_trans)
1109 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1110 &(png_ptr->trans_values));
1111 else
1112 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1113 NULL);
1114 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001115 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001116#endif
1117
1118#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1119 if (png_ptr->transformations & PNG_STRIP_ALPHA)
1120 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1121 PNG_FLAG_FILLER_AFTER);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001122#endif
1123
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001124#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1125 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1126 {
1127 int rgb_error =
1128 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1129 if(rgb_error)
1130 {
1131 png_ptr->rgb_to_gray_status=1;
1132 if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
1133 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1134 if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
1135 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1136 }
1137 }
1138#endif
1139
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001140/*
1141From Andreas Dilger e-mail to png-implement, 26 March 1998:
1142
1143 In most cases, the "simple transparency" should be done prior to doing
1144 gray-to-RGB, or you will have to test 3x as many bytes to check if a
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001145 pixel is transparent. You would also need to make sure that the
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001146 transparency information is upgraded to RGB.
1147
1148 To summarize, the current flow is:
1149 - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1150 with background "in place" if transparent,
1151 convert to RGB if necessary
1152 - Gray + alpha -> composite with gray background and remove alpha bytes,
1153 convert to RGB if necessary
1154
1155 To support RGB backgrounds for gray images we need:
1156 - Gray + simple transparency -> convert to RGB + simple transparency, compare
1157 3 or 6 bytes and composite with background
1158 "in place" if transparent (3x compare/pixel
1159 compared to doing composite with gray bkgrnd)
1160 - Gray + alpha -> convert to RGB + alpha, composite with background and
1161 remove alpha bytes (3x float operations/pixel
1162 compared with composite on gray background)
1163
1164 Greg's change will do this. The reason it wasn't done before is for
1165 performance, as this increases the per-pixel operations. If we would check
1166 in advance if the background was gray or RGB, and position the gray-to-RGB
1167 transform appropriately, then it would save a lot of work/time.
1168 */
1169
1170#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1171 /* if gray -> RGB, do so now only if background is non-gray; else do later
1172 * for performance reasons */
1173 if (png_ptr->transformations & PNG_GRAY_TO_RGB &&
1174 !(png_ptr->flags & PNG_FLAG_BACKGROUND_IS_GRAY))
1175 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1176#endif
1177
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001178#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001179 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1180 ((png_ptr->num_trans != 0 ) ||
1181 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
Guy Schalnat0d580581995-07-20 02:43:20 -05001182 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1183 &(png_ptr->trans_values), &(png_ptr->background),
1184 &(png_ptr->background_1),
1185 png_ptr->gamma_table, png_ptr->gamma_from_1,
1186 png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1187 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1188 png_ptr->gamma_shift);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001189#endif
1190
1191#if defined(PNG_READ_GAMMA_SUPPORTED)
1192 if ((png_ptr->transformations & PNG_GAMMA) &&
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001193#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1194 !((png_ptr->transformations & PNG_BACKGROUND) &&
1195 ((png_ptr->num_trans != 0) ||
1196 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1197#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001198 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
Guy Schalnat0d580581995-07-20 02:43:20 -05001199 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1200 png_ptr->gamma_table, png_ptr->gamma_16_table,
1201 png_ptr->gamma_shift);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001202#endif
1203
1204#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001205 if (png_ptr->transformations & PNG_16_TO_8)
1206 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001207#endif
1208
1209#if defined(PNG_READ_DITHER_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001210 if (png_ptr->transformations & PNG_DITHER)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001211 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001212 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1213 png_ptr->palette_lookup, png_ptr->dither_index);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001214 if(png_ptr->row_info.rowbytes == (png_uint_32)0)
1215 png_error(png_ptr, "png_do_dither returned rowbytes=0");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001216 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001217#endif
1218
1219#if defined(PNG_READ_INVERT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001220 if (png_ptr->transformations & PNG_INVERT_MONO)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001221 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001222#endif
1223
1224#if defined(PNG_READ_SHIFT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001225 if (png_ptr->transformations & PNG_SHIFT)
1226 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1227 &(png_ptr->shift));
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001228#endif
1229
1230#if defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001231 if (png_ptr->transformations & PNG_PACK)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001232 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001233#endif
1234
1235#if defined(PNG_READ_BGR_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001236 if (png_ptr->transformations & PNG_BGR)
1237 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001238#endif
1239
Andreas Dilger47a0c421997-05-16 02:46:07 -05001240#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1241 if (png_ptr->transformations & PNG_PACKSWAP)
1242 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1243#endif
1244
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001245#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001246 /* if gray -> RGB, do so now only if we did not do so above */
1247 if (png_ptr->transformations & PNG_GRAY_TO_RGB &&
1248 png_ptr->flags & PNG_FLAG_BACKGROUND_IS_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05001249 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001250#endif
1251
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001252#if defined(PNG_READ_FILLER_SUPPORTED)
1253 if (png_ptr->transformations & PNG_FILLER)
1254 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001255 (png_uint_32)png_ptr->filler, png_ptr->flags);
1256#endif
1257
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001258#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1259 if (png_ptr->transformations & PNG_INVERT_ALPHA)
1260 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1261#endif
1262
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001263#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1264 if (png_ptr->transformations & PNG_SWAP_ALPHA)
1265 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1266#endif
1267
Andreas Dilger47a0c421997-05-16 02:46:07 -05001268#if defined(PNG_READ_SWAP_SUPPORTED)
1269 if (png_ptr->transformations & PNG_SWAP_BYTES)
1270 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001271#endif
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001272
1273#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1274 if (png_ptr->transformations & PNG_USER_TRANSFORM)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001275 {
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001276 if(png_ptr->read_user_transform_fn != NULL)
1277 (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1278 (png_ptr, /* png_ptr */
1279 &(png_ptr->row_info), /* row_info: */
1280 /* png_uint_32 width; width of row */
1281 /* png_uint_32 rowbytes; number of bytes in row */
1282 /* png_byte color_type; color type of pixels */
1283 /* png_byte bit_depth; bit depth of samples */
1284 /* png_byte channels; number of channels (1-4) */
1285 /* png_byte pixel_depth; bits per pixel (depth*channels) */
1286 png_ptr->row_buf + 1); /* start of pixel data for row */
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001287 if(png_ptr->user_transform_depth)
1288 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1289 if(png_ptr->user_transform_channels)
1290 png_ptr->row_info.channels = png_ptr->user_transform_channels;
1291 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1292 png_ptr->row_info.channels);
1293 png_ptr->row_info.rowbytes = (png_ptr->row_info.width *
1294 png_ptr->row_info.pixel_depth+7)>>3;
1295 }
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001296#endif
1297
Guy Schalnat0d580581995-07-20 02:43:20 -05001298}
1299
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001300#if defined(PNG_READ_PACK_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001301/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1302 * without changing the actual values. Thus, if you had a row with
1303 * a bit depth of 1, you would end up with bytes that only contained
1304 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1305 * png_do_shift() after this.
1306 */
Guy Schalnat0d580581995-07-20 02:43:20 -05001307void
Guy Schalnat6d764711995-12-19 03:22:19 -06001308png_do_unpack(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001309{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001310 png_debug(1, "in png_do_unpack\n");
1311#if defined(PNG_USELESS_TESTS_SUPPORTED)
1312 if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1313#else
1314 if (row_info->bit_depth < 8)
1315#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001316 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001317 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001318 png_uint_32 row_width=row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001319
Guy Schalnat0d580581995-07-20 02:43:20 -05001320 switch (row_info->bit_depth)
1321 {
1322 case 1:
1323 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001324 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1325 png_bytep dp = row + (png_size_t)row_width - 1;
1326 png_uint_32 shift = 7 - (int)((row_width + 7) & 7);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001327 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001328 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001329 *dp = (png_byte)((*sp >> shift) & 0x1);
Guy Schalnat0d580581995-07-20 02:43:20 -05001330 if (shift == 7)
1331 {
1332 shift = 0;
1333 sp--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001334 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001335 else
1336 shift++;
1337
1338 dp--;
1339 }
1340 break;
1341 }
1342 case 2:
1343 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001344
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001345 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1346 png_bytep dp = row + (png_size_t)row_width - 1;
1347 png_uint_32 shift = (int)((3 - ((row_width + 3) & 3)) << 1);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001348 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001349 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001350 *dp = (png_byte)((*sp >> shift) & 0x3);
Guy Schalnat0d580581995-07-20 02:43:20 -05001351 if (shift == 6)
1352 {
1353 shift = 0;
1354 sp--;
1355 }
1356 else
1357 shift += 2;
1358
1359 dp--;
1360 }
1361 break;
1362 }
1363 case 4:
1364 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001365 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1366 png_bytep dp = row + (png_size_t)row_width - 1;
1367 png_uint_32 shift = (int)((1 - ((row_width + 1) & 1)) << 2);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001368 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001369 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001370 *dp = (png_byte)((*sp >> shift) & 0xf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001371 if (shift == 4)
1372 {
1373 shift = 0;
1374 sp--;
1375 }
1376 else
1377 shift = 4;
1378
1379 dp--;
1380 }
1381 break;
1382 }
1383 }
1384 row_info->bit_depth = 8;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001385 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001386 row_info->rowbytes = row_width * row_info->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -05001387 }
1388}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001389#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001390
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001391#if defined(PNG_READ_SHIFT_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001392/* Reverse the effects of png_do_shift. This routine merely shifts the
1393 * pixels back to their significant bits values. Thus, if you have
1394 * a row of bit depth 8, but only 5 are significant, this will shift
1395 * the values back to 0 through 31.
1396 */
Guy Schalnat0d580581995-07-20 02:43:20 -05001397void
Andreas Dilger47a0c421997-05-16 02:46:07 -05001398png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
Guy Schalnat0d580581995-07-20 02:43:20 -05001399{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001400 png_debug(1, "in png_do_unshift\n");
1401 if (
1402#if defined(PNG_USELESS_TESTS_SUPPORTED)
1403 row != NULL && row_info != NULL && sig_bits != NULL &&
1404#endif
1405 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05001406 {
1407 int shift[4];
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001408 int channels = 0;
1409 int c;
1410 png_uint_16 value = 0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001411 png_uint_32 row_width = row_info->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001412
Guy Schalnat0d580581995-07-20 02:43:20 -05001413 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1414 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001415 shift[channels++] = row_info->bit_depth - sig_bits->red;
1416 shift[channels++] = row_info->bit_depth - sig_bits->green;
1417 shift[channels++] = row_info->bit_depth - sig_bits->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05001418 }
1419 else
1420 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001421 shift[channels++] = row_info->bit_depth - sig_bits->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05001422 }
1423 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1424 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001425 shift[channels++] = row_info->bit_depth - sig_bits->alpha;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001426 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001427
Andreas Dilger47a0c421997-05-16 02:46:07 -05001428 for (c = 0; c < channels; c++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001429 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001430 if (shift[c] <= 0)
1431 shift[c] = 0;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001432 else
1433 value = 1;
1434 }
Guy Schalnat0f716451995-11-28 11:22:13 -06001435
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001436 if (!value)
1437 return;
Guy Schalnat0f716451995-11-28 11:22:13 -06001438
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001439 switch (row_info->bit_depth)
Guy Schalnat0d580581995-07-20 02:43:20 -05001440 {
1441 case 2:
1442 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001443 png_bytep bp;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001444 png_uint_32 i;
1445 png_uint_32 istop = row_info->rowbytes;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001446
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001447 for (bp = row, i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001448 {
1449 *bp >>= 1;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001450 *bp++ &= 0x55;
Guy Schalnat0d580581995-07-20 02:43:20 -05001451 }
1452 break;
1453 }
1454 case 4:
1455 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001456 png_bytep bp = row;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001457 png_uint_32 i;
1458 png_uint_32 istop = row_info->rowbytes;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001459 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1460 (png_byte)((int)0xf >> shift[0]));
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001461
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001462 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001463 {
1464 *bp >>= shift[0];
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001465 *bp++ &= mask;
Guy Schalnat0d580581995-07-20 02:43:20 -05001466 }
1467 break;
1468 }
1469 case 8:
1470 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001471 png_bytep bp = row;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001472 png_uint_32 i;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001473 png_uint_32 istop = row_width * channels;
Guy Schalnat0d580581995-07-20 02:43:20 -05001474
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001475 for (i = 0; i < istop; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001476 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001477 *bp++ >>= shift[i%channels];
Guy Schalnat0d580581995-07-20 02:43:20 -05001478 }
1479 break;
1480 }
1481 case 16:
1482 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001483 png_bytep bp = row;
1484 png_uint_32 i;
1485 png_uint_32 istop = channels * row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001486
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001487 for (i = 0; i < istop; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001488 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001489 value = (png_uint_16)((*bp << 8) + *(bp + 1));
1490 value >>= shift[i%channels];
1491 *bp++ = (png_byte)(value >> 8);
1492 *bp++ = (png_byte)(value & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05001493 }
1494 break;
1495 }
1496 }
1497 }
1498}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001499#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001500
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001501#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001502/* chop rows of bit depth 16 down to 8 */
1503void
Guy Schalnat6d764711995-12-19 03:22:19 -06001504png_do_chop(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001505{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001506 png_debug(1, "in png_do_chop\n");
1507#if defined(PNG_USELESS_TESTS_SUPPORTED)
1508 if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1509#else
1510 if (row_info->bit_depth == 16)
1511#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001512 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001513 png_bytep sp = row;
1514 png_bytep dp = row;
1515 png_uint_32 i;
1516 png_uint_32 istop = row_info->width * row_info->channels;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001517
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001518 for (i = 0; i<istop; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001519 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001520#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001521 /* This does a more accurate scaling of the 16-bit color
1522 * value, rather than a simple low-byte truncation.
1523 *
1524 * What the ideal calculation should be:
1525 * *dp = (((((png_uint_32)(*sp) << 8) |
1526 * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1527 *
1528 * GRR: no, I think this is what it really should be:
1529 * *dp = (((((png_uint_32)(*sp) << 8) |
1530 * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1531 *
1532 * GRR: here's the exact calculation with shifts:
1533 * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1534 * *dp = (temp - (temp >> 8)) >> 8;
1535 *
1536 * Approximate calculation with shift/add instead of multiply/divide:
1537 * *dp = ((((png_uint_32)(*sp) << 8) |
1538 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1539 *
1540 * What we actually do to avoid extra shifting and conversion:
1541 */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001542
Andreas Dilger47a0c421997-05-16 02:46:07 -05001543 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1544#else
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001545 /* Simply discard the low order byte */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001546 *dp = *sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001547#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001548 }
1549 row_info->bit_depth = 8;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001550 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001551 row_info->rowbytes = row_info->width * row_info->channels;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001552 }
1553}
1554#endif
1555
1556#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1557void
1558png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1559{
1560 png_debug(1, "in png_do_read_swap_alpha\n");
1561#if defined(PNG_USELESS_TESTS_SUPPORTED)
1562 if (row != NULL && row_info != NULL)
1563#endif
1564 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001565 png_uint_32 row_width = row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001566 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1567 {
1568 /* This converts from RGBA to ARGB */
1569 if (row_info->bit_depth == 8)
1570 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001571 png_bytep sp = row + row_info->rowbytes;
1572 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001573 png_byte save;
1574 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001575
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001576 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001577 {
1578 save = *(--sp);
1579 *(--dp) = *(--sp);
1580 *(--dp) = *(--sp);
1581 *(--dp) = *(--sp);
1582 *(--dp) = save;
1583 }
1584 }
1585 /* This converts from RRGGBBAA to AARRGGBB */
1586 else
1587 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001588 png_bytep sp = row + row_info->rowbytes;
1589 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001590 png_byte save[2];
1591 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001592
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001593 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001594 {
1595 save[0] = *(--sp);
1596 save[1] = *(--sp);
1597 *(--dp) = *(--sp);
1598 *(--dp) = *(--sp);
1599 *(--dp) = *(--sp);
1600 *(--dp) = *(--sp);
1601 *(--dp) = *(--sp);
1602 *(--dp) = *(--sp);
1603 *(--dp) = save[0];
1604 *(--dp) = save[1];
1605 }
1606 }
1607 }
1608 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1609 {
1610 /* This converts from GA to AG */
1611 if (row_info->bit_depth == 8)
1612 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001613 png_bytep sp = row + row_info->rowbytes;
1614 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001615 png_byte save;
1616 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001617
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001618 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001619 {
1620 save = *(--sp);
1621 *(--dp) = *(--sp);
1622 *(--dp) = save;
1623 }
1624 }
1625 /* This converts from GGAA to AAGG */
1626 else
1627 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001628 png_bytep sp = row + row_info->rowbytes;
1629 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001630 png_byte save[2];
1631 png_uint_32 i;
1632
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001633 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001634 {
1635 save[0] = *(--sp);
1636 save[1] = *(--sp);
1637 *(--dp) = *(--sp);
1638 *(--dp) = *(--sp);
1639 *(--dp) = save[0];
1640 *(--dp) = save[1];
1641 }
1642 }
1643 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001644 }
1645}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001646#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001647
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001648#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1649void
1650png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1651{
1652 png_debug(1, "in png_do_read_invert_alpha\n");
1653#if defined(PNG_USELESS_TESTS_SUPPORTED)
1654 if (row != NULL && row_info != NULL)
1655#endif
1656 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001657 png_uint_32 row_width = row_info->width;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001658 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1659 {
1660 /* This inverts the alpha channel in RGBA */
1661 if (row_info->bit_depth == 8)
1662 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001663 png_bytep sp = row + row_info->rowbytes;
1664 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001665 png_uint_32 i;
1666
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001667 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001668 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001669 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001670 *(--dp) = *(--sp);
1671 *(--dp) = *(--sp);
1672 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001673 }
1674 }
1675 /* This inverts the alpha channel in RRGGBBAA */
1676 else
1677 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001678 png_bytep sp = row + row_info->rowbytes;
1679 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001680 png_uint_32 i;
1681
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001682 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001683 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001684 *(--dp) = (png_byte)(255 - *(--sp));
1685 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001686 *(--dp) = *(--sp);
1687 *(--dp) = *(--sp);
1688 *(--dp) = *(--sp);
1689 *(--dp) = *(--sp);
1690 *(--dp) = *(--sp);
1691 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001692 }
1693 }
1694 }
1695 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1696 {
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001697 /* This inverts the alpha channel in GA */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001698 if (row_info->bit_depth == 8)
1699 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001700 png_bytep sp = row + row_info->rowbytes;
1701 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001702 png_uint_32 i;
1703
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001704 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001705 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001706 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001707 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001708 }
1709 }
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001710 /* This inverts the alpha channel in GGAA */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001711 else
1712 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001713 png_bytep sp = row + row_info->rowbytes;
1714 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001715 png_uint_32 i;
1716
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001717 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001718 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001719 *(--dp) = (png_byte)(255 - *(--sp));
1720 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001721 *(--dp) = *(--sp);
1722 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001723 }
1724 }
1725 }
1726 }
1727}
1728#endif
1729
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001730#if defined(PNG_READ_FILLER_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001731/* Add filler channel if we have RGB color */
Guy Schalnat0d580581995-07-20 02:43:20 -05001732void
Guy Schalnat6d764711995-12-19 03:22:19 -06001733png_do_read_filler(png_row_infop row_info, png_bytep row,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001734 png_uint_32 filler, png_uint_32 flags)
Guy Schalnat0d580581995-07-20 02:43:20 -05001735{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001736 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001737 png_uint_32 row_width = row_info->width;
1738
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001739 png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001740 png_byte lo_filler = (png_byte)(filler & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001741
1742 png_debug(1, "in png_do_read_filler\n");
1743 if (
1744#if defined(PNG_USELESS_TESTS_SUPPORTED)
1745 row != NULL && row_info != NULL &&
1746#endif
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001747 row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05001748 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001749 if(row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05001750 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001751 /* This changes the data from G to GX */
1752 if (flags & PNG_FLAG_FILLER_AFTER)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001753 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001754 png_bytep sp = row + (png_size_t)row_width;
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 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001758 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001759 *(--dp) = *(--sp);
1760 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001761 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001762 row_info->channels = 2;
1763 row_info->pixel_depth = 16;
1764 row_info->rowbytes = row_width * 2;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001765 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001766 /* This changes the data from G to XG */
1767 else
1768 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001769 png_bytep sp = row + (png_size_t)row_width;
1770 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001771 for (i = 0; i < row_width; i++)
1772 {
1773 *(--dp) = *(--sp);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001774 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001775 }
1776 row_info->channels = 2;
1777 row_info->pixel_depth = 16;
1778 row_info->rowbytes = row_width * 2;
1779 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001780 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001781 else if(row_info->bit_depth == 16)
1782 {
1783 /* This changes the data from GG to GGXX */
1784 if (flags & PNG_FLAG_FILLER_AFTER)
1785 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001786 png_bytep sp = row + (png_size_t)row_width;
1787 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001788 for (i = 1; i < row_width; i++)
1789 {
1790 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001791 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001792 *(--dp) = *(--sp);
1793 *(--dp) = *(--sp);
1794 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001795 *(--dp) = hi_filler;
1796 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001797 row_info->channels = 2;
1798 row_info->pixel_depth = 32;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001799 row_info->rowbytes = row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001800 }
1801 /* This changes the data from GG to XXGG */
1802 else
1803 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001804 png_bytep sp = row + (png_size_t)row_width;
1805 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001806 for (i = 0; i < row_width; i++)
1807 {
1808 *(--dp) = *(--sp);
1809 *(--dp) = *(--sp);
1810 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001811 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001812 }
1813 row_info->channels = 2;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001814 row_info->pixel_depth = 32;
1815 row_info->rowbytes = row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001816 }
1817 }
1818 } /* COLOR_TYPE == GRAY */
1819 else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
1820 {
1821 if(row_info->bit_depth == 8)
1822 {
1823 /* This changes the data from RGB to RGBX */
1824 if (flags & PNG_FLAG_FILLER_AFTER)
1825 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001826 png_bytep sp = row + (png_size_t)row_width * 3;
1827 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001828 for (i = 1; i < row_width; i++)
1829 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001830 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001831 *(--dp) = *(--sp);
1832 *(--dp) = *(--sp);
1833 *(--dp) = *(--sp);
1834 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001835 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001836 row_info->channels = 4;
1837 row_info->pixel_depth = 32;
1838 row_info->rowbytes = row_width * 4;
1839 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001840 /* This changes the data from RGB to XRGB */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001841 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001842 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001843 png_bytep sp = row + (png_size_t)row_width * 3;
1844 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001845 for (i = 0; i < row_width; i++)
1846 {
1847 *(--dp) = *(--sp);
1848 *(--dp) = *(--sp);
1849 *(--dp) = *(--sp);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001850 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001851 }
1852 row_info->channels = 4;
1853 row_info->pixel_depth = 32;
1854 row_info->rowbytes = row_width * 4;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001855 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001856 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001857 else if(row_info->bit_depth == 16)
1858 {
1859 /* This changes the data from RRGGBB to RRGGBBXX */
1860 if (flags & PNG_FLAG_FILLER_AFTER)
1861 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001862 png_bytep sp = row + (png_size_t)row_width * 3;
1863 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001864 for (i = 1; i < row_width; i++)
1865 {
1866 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001867 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001868 *(--dp) = *(--sp);
1869 *(--dp) = *(--sp);
1870 *(--dp) = *(--sp);
1871 *(--dp) = *(--sp);
1872 *(--dp) = *(--sp);
1873 *(--dp) = *(--sp);
1874 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001875 *(--dp) = hi_filler;
1876 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001877 row_info->channels = 4;
1878 row_info->pixel_depth = 64;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001879 row_info->rowbytes = row_width * 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001880 }
1881 /* This changes the data from RRGGBB to XXRRGGBB */
1882 else
1883 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001884 png_bytep sp = row + (png_size_t)row_width * 3;
1885 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001886 for (i = 0; i < row_width; i++)
1887 {
1888 *(--dp) = *(--sp);
1889 *(--dp) = *(--sp);
1890 *(--dp) = *(--sp);
1891 *(--dp) = *(--sp);
1892 *(--dp) = *(--sp);
1893 *(--dp) = *(--sp);
1894 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001895 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001896 }
1897 row_info->channels = 4;
1898 row_info->pixel_depth = 64;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001899 row_info->rowbytes = row_width * 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001900 }
1901 }
1902 } /* COLOR_TYPE == RGB */
Guy Schalnat0d580581995-07-20 02:43:20 -05001903}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001904#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001905
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001906#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001907/* expand grayscale files to RGB, with or without alpha */
Guy Schalnat0d580581995-07-20 02:43:20 -05001908void
Guy Schalnat6d764711995-12-19 03:22:19 -06001909png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001910{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001911 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001912 png_uint_32 row_width = row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06001913
Andreas Dilger47a0c421997-05-16 02:46:07 -05001914 png_debug(1, "in png_do_gray_to_rgb\n");
1915 if (row_info->bit_depth >= 8 &&
1916#if defined(PNG_USELESS_TESTS_SUPPORTED)
1917 row != NULL && row_info != NULL &&
1918#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001919 !(row_info->color_type & PNG_COLOR_MASK_COLOR))
1920 {
1921 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
1922 {
1923 if (row_info->bit_depth == 8)
1924 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001925 png_bytep sp = row + (png_size_t)row_width - 1;
1926 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001927 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001928 {
1929 *(dp--) = *sp;
1930 *(dp--) = *sp;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001931 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05001932 }
1933 }
1934 else
1935 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001936 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
1937 png_bytep dp = sp + (png_size_t)row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001938 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001939 {
1940 *(dp--) = *sp;
1941 *(dp--) = *(sp - 1);
1942 *(dp--) = *sp;
1943 *(dp--) = *(sp - 1);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001944 *(dp--) = *(sp--);
1945 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05001946 }
1947 }
1948 }
1949 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1950 {
1951 if (row_info->bit_depth == 8)
1952 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001953 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
1954 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001955 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001956 {
1957 *(dp--) = *(sp--);
1958 *(dp--) = *sp;
1959 *(dp--) = *sp;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001960 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05001961 }
1962 }
1963 else
1964 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001965 png_bytep sp = row + (png_size_t)row_width * 4 - 1;
1966 png_bytep dp = sp + (png_size_t)row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001967 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001968 {
1969 *(dp--) = *(sp--);
1970 *(dp--) = *(sp--);
1971 *(dp--) = *sp;
1972 *(dp--) = *(sp - 1);
1973 *(dp--) = *sp;
1974 *(dp--) = *(sp - 1);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001975 *(dp--) = *(sp--);
1976 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05001977 }
1978 }
1979 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001980 row_info->channels += (png_byte)2;
Guy Schalnat0d580581995-07-20 02:43:20 -05001981 row_info->color_type |= PNG_COLOR_MASK_COLOR;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001982 row_info->pixel_depth = (png_byte)(row_info->channels *
1983 row_info->bit_depth);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001984 row_info->rowbytes = ((row_width *
Guy Schalnat0d580581995-07-20 02:43:20 -05001985 row_info->pixel_depth + 7) >> 3);
1986 }
1987}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001988#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001989
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001990#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1991/* reduce RGB files to grayscale, with or without alpha
1992 * using the equation given in Poynton's ColorFAQ at
1993 * <http://www.inforamp.net/~poynton/>
1994 * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
1995 *
1996 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
1997 *
1998 * We approximate this with
1999 *
2000 * Y = 0.211 * R + 0.715 * G + 0.074 * B
2001 *
2002 * which can be expressed with integers as
2003 *
2004 * Y = (54 * R + 183 * G + 19 * B)/256
2005 *
2006 * The calculation is to be done in a linear colorspace.
2007 *
2008 * Other integer coefficents can be used via png_set_rgb_to_gray().
2009 */
2010int
2011png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2012
2013{
2014 png_uint_32 i;
2015
2016 png_uint_32 row_width = row_info->width;
2017 int rgb_error = 0;
2018
2019 png_debug(1, "in png_do_rgb_to_gray\n");
2020 if (
2021#if defined(PNG_USELESS_TESTS_SUPPORTED)
2022 row != NULL && row_info != NULL &&
2023#endif
2024 (row_info->color_type & PNG_COLOR_MASK_COLOR))
2025 {
2026 png_byte rc = png_ptr->rgb_to_gray_red_coeff;
2027 png_byte gc = png_ptr->rgb_to_gray_green_coeff;
2028 png_byte bc = png_ptr->rgb_to_gray_blue_coeff;
2029
2030 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2031 {
2032 if (row_info->bit_depth == 8)
2033 {
2034#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2035 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2036 {
2037 png_bytep sp = row;
2038 png_bytep dp = row;
2039
2040 for (i = 0; i < row_width; i++)
2041 {
2042 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2043 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2044 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2045 if(red != green || red != blue)
2046 {
2047 rgb_error |= 1;
2048 *(dp++) = png_ptr->gamma_from_1[
2049 (rc*red+gc*green+bc*blue)>>8];
2050 }
2051 else
2052 *(dp++) = *(sp-1);
2053 }
2054 }
2055 else
2056#endif
2057 {
2058 png_bytep sp = row;
2059 png_bytep dp = row;
2060 for (i = 0; i < row_width; i++)
2061 {
2062 png_byte red = *(sp++);
2063 png_byte green = *(sp++);
2064 png_byte blue = *(sp++);
2065 if(red != green || red != blue)
2066 {
2067 rgb_error |= 1;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002068 *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>8);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002069 }
2070 else
2071 *(dp++) = *(sp-1);
2072 }
2073 }
2074 }
2075
2076 else /* RGB bit_depth == 16 */
2077 {
2078#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2079 if (png_ptr->gamma_16_to_1 != NULL &&
2080 png_ptr->gamma_16_from_1 != NULL)
2081 {
2082 png_bytep sp = row;
2083 png_bytep dp = row;
2084 for (i = 0; i < row_width; i++)
2085 {
2086 png_uint_16 red, green, blue, w;
2087
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002088 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2089 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2090 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002091
2092 if(red == green && red == blue)
2093 w = red;
2094 else
2095 {
2096 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2097 png_ptr->gamma_shift][red>>8];
2098 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2099 png_ptr->gamma_shift][green>>8];
2100 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2101 png_ptr->gamma_shift][blue>>8];
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002102 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
2103 + bc*blue_1)>>8);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002104 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2105 png_ptr->gamma_shift][gray16 >> 8];
2106 rgb_error |= 1;
2107 }
2108
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002109 *(dp++) = (png_byte)((w>>8) & 0xff);
2110 *(dp++) = (png_byte)(w & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002111 }
2112 }
2113 else
2114#endif
2115 {
2116 png_bytep sp = row;
2117 png_bytep dp = row;
2118 for (i = 0; i < row_width; i++)
2119 {
2120 png_uint_16 red, green, blue, gray16;
2121
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002122 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2123 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2124 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002125
2126 if(red != green || red != blue)
2127 rgb_error |= 1;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002128 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>8);
2129 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2130 *(dp++) = (png_byte)(gray16 & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002131 }
2132 }
2133 }
2134 }
2135 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2136 {
2137 if (row_info->bit_depth == 8)
2138 {
2139#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2140 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2141 {
2142 png_bytep sp = row;
2143 png_bytep dp = row;
2144 for (i = 0; i < row_width; i++)
2145 {
2146 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2147 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2148 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2149 if(red != green || red != blue)
2150 rgb_error |= 1;
2151 *(dp++) = png_ptr->gamma_from_1
2152 [(rc*red + gc*green + bc*blue)>>8];
2153 *(dp++) = *(sp++); /* alpha */
2154 }
2155 }
2156 else
2157#endif
2158 {
2159 png_bytep sp = row;
2160 png_bytep dp = row;
2161 for (i = 0; i < row_width; i++)
2162 {
2163 png_byte red = *(sp++);
2164 png_byte green = *(sp++);
2165 png_byte blue = *(sp++);
2166 if(red != green || red != blue)
2167 rgb_error |= 1;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002168 *(dp++) = (png_byte)((gc*red + gc*green + bc*blue)>>8);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002169 *(dp++) = *(sp++); /* alpha */
2170 }
2171 }
2172 }
2173 else /* RGBA bit_depth == 16 */
2174 {
2175#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2176 if (png_ptr->gamma_16_to_1 != NULL &&
2177 png_ptr->gamma_16_from_1 != NULL)
2178 {
2179 png_bytep sp = row;
2180 png_bytep dp = row;
2181 for (i = 0; i < row_width; i++)
2182 {
2183 png_uint_16 red, green, blue, w;
2184
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002185 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2186 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2187 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002188
2189 if(red == green && red == blue)
2190 w = red;
2191 else
2192 {
2193 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2194 png_ptr->gamma_shift][red>>8];
2195 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2196 png_ptr->gamma_shift][green>>8];
2197 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
2198 png_ptr->gamma_shift][blue>>8];
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002199 png_uint_16 gray16 = (png_uint_16)((rc * red_1
2200 + gc * green_1 + bc * blue_1)>>8);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002201 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2202 png_ptr->gamma_shift][gray16 >> 8];
2203 rgb_error |= 1;
2204 }
2205
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002206 *(dp++) = (png_byte)((w>>8) & 0xff);
2207 *(dp++) = (png_byte)(w & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002208 *(dp++) = *(sp++); /* alpha */
2209 *(dp++) = *(sp++);
2210 }
2211 }
2212 else
2213#endif
2214 {
2215 png_bytep sp = row;
2216 png_bytep dp = row;
2217 for (i = 0; i < row_width; i++)
2218 {
2219 png_uint_16 red, green, blue, gray16;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002220 red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2221 green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2222 blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002223 if(red != green || red != blue)
2224 rgb_error |= 1;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002225 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>8);
2226 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2227 *(dp++) = (png_byte)(gray16 & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002228 *(dp++) = *(sp++); /* alpha */
2229 *(dp++) = *(sp++);
2230 }
2231 }
2232 }
2233 }
2234 row_info->channels -= (png_byte)2;
2235 row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2236 row_info->pixel_depth = (png_byte)(row_info->channels *
2237 row_info->bit_depth);
2238 row_info->rowbytes = ((row_width *
2239 row_info->pixel_depth + 7) >> 3);
2240 }
2241 return rgb_error;
2242}
2243#endif
2244
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002245/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
2246 * large of png_color. This lets grayscale images be treated as
2247 * paletted. Most useful for gamma correction and simplification
2248 * of code.
2249 */
Guy Schalnat0d580581995-07-20 02:43:20 -05002250void
Guy Schalnat6d764711995-12-19 03:22:19 -06002251png_build_grayscale_palette(int bit_depth, png_colorp palette)
Guy Schalnat0d580581995-07-20 02:43:20 -05002252{
2253 int num_palette;
2254 int color_inc;
2255 int i;
2256 int v;
2257
Andreas Dilger47a0c421997-05-16 02:46:07 -05002258 png_debug(1, "in png_do_build_grayscale_palette\n");
2259 if (palette == NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002260 return;
2261
2262 switch (bit_depth)
2263 {
2264 case 1:
2265 num_palette = 2;
2266 color_inc = 0xff;
2267 break;
2268 case 2:
2269 num_palette = 4;
2270 color_inc = 0x55;
2271 break;
2272 case 4:
2273 num_palette = 16;
2274 color_inc = 0x11;
2275 break;
2276 case 8:
2277 num_palette = 256;
2278 color_inc = 1;
2279 break;
2280 default:
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002281 num_palette = 0;
Guy Schalnat69b14481996-01-10 02:56:49 -06002282 color_inc = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05002283 break;
2284 }
2285
2286 for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2287 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002288 palette[i].red = (png_byte)v;
2289 palette[i].green = (png_byte)v;
2290 palette[i].blue = (png_byte)v;
Guy Schalnat0d580581995-07-20 02:43:20 -05002291 }
2292}
2293
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002294/* This function is currently unused. Do we really need it? */
2295#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05002296void
Guy Schalnat6d764711995-12-19 03:22:19 -06002297png_correct_palette(png_structp png_ptr, png_colorp palette,
Guy Schalnat0d580581995-07-20 02:43:20 -05002298 int num_palette)
2299{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002300 png_debug(1, "in png_correct_palette\n");
Guy Schalnate5a37791996-06-05 15:50:50 -05002301#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002302 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
Guy Schalnat0d580581995-07-20 02:43:20 -05002303 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002304 png_color back, back_1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002305
Andreas Dilger47a0c421997-05-16 02:46:07 -05002306 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
2307 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002308 back.red = png_ptr->gamma_table[png_ptr->background.red];
2309 back.green = png_ptr->gamma_table[png_ptr->background.green];
2310 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
Guy Schalnat0d580581995-07-20 02:43:20 -05002311
Guy Schalnate5a37791996-06-05 15:50:50 -05002312 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
2313 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
2314 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002315 }
2316 else
2317 {
2318 double g;
Guy Schalnat0d580581995-07-20 02:43:20 -05002319
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06002320 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002321
2322 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2323 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
Guy Schalnat0d580581995-07-20 02:43:20 -05002324 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002325 back.red = png_ptr->background.red;
2326 back.green = png_ptr->background.green;
2327 back.blue = png_ptr->background.blue;
2328 }
2329 else
2330 {
2331 back.red =
2332 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2333 255.0 + 0.5);
2334 back.green =
2335 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2336 255.0 + 0.5);
2337 back.blue =
2338 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2339 255.0 + 0.5);
2340 }
2341
2342 g = 1.0 / png_ptr->background_gamma;
2343
2344 back_1.red =
2345 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2346 255.0 + 0.5);
2347 back_1.green =
2348 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2349 255.0 + 0.5);
2350 back_1.blue =
2351 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2352 255.0 + 0.5);
2353 }
2354
2355 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2356 {
2357 png_uint_32 i;
2358
2359 for (i = 0; i < (png_uint_32)num_palette; i++)
2360 {
2361 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -05002362 {
2363 palette[i] = back;
2364 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002365 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002366 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002367 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002368
2369 v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002370 png_composite(w, v, png_ptr->trans[i], back_1.red);
2371 palette[i].red = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002372
2373 v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002374 png_composite(w, v, png_ptr->trans[i], back_1.green);
2375 palette[i].green = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002376
2377 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002378 png_composite(w, v, png_ptr->trans[i], back_1.blue);
2379 palette[i].blue = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002380 }
2381 else
2382 {
2383 palette[i].red = png_ptr->gamma_table[palette[i].red];
2384 palette[i].green = png_ptr->gamma_table[palette[i].green];
2385 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2386 }
2387 }
2388 }
2389 else
2390 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002391 int i;
Guy Schalnat0d580581995-07-20 02:43:20 -05002392
2393 for (i = 0; i < num_palette; i++)
2394 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002395 if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002396 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002397 palette[i] = back;
Guy Schalnat0d580581995-07-20 02:43:20 -05002398 }
2399 else
2400 {
2401 palette[i].red = png_ptr->gamma_table[palette[i].red];
2402 palette[i].green = png_ptr->gamma_table[palette[i].green];
2403 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2404 }
2405 }
2406 }
2407 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002408 else
2409#endif
2410#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002411 if (png_ptr->transformations & PNG_GAMMA)
Guy Schalnat0d580581995-07-20 02:43:20 -05002412 {
2413 int i;
2414
2415 for (i = 0; i < num_palette; i++)
2416 {
2417 palette[i].red = png_ptr->gamma_table[palette[i].red];
2418 palette[i].green = png_ptr->gamma_table[palette[i].green];
2419 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2420 }
2421 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002422#if defined(PNG_READ_BACKGROUND_SUPPORTED)
2423 else
2424#endif
2425#endif
2426#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002427 if (png_ptr->transformations & PNG_BACKGROUND)
Guy Schalnat0d580581995-07-20 02:43:20 -05002428 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002429 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05002430 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002431 png_color back;
Guy Schalnat0d580581995-07-20 02:43:20 -05002432
Guy Schalnate5a37791996-06-05 15:50:50 -05002433 back.red = (png_byte)png_ptr->background.red;
2434 back.green = (png_byte)png_ptr->background.green;
2435 back.blue = (png_byte)png_ptr->background.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002436
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06002437 for (i = 0; i < (int)png_ptr->num_trans; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002438 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002439 if (png_ptr->trans[i] == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -05002440 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002441 palette[i].red = back.red;
2442 palette[i].green = back.green;
2443 palette[i].blue = back.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002444 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002445 else if (png_ptr->trans[i] != 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002446 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002447 png_composite(palette[i].red, png_ptr->palette[i].red,
2448 png_ptr->trans[i], back.red);
2449 png_composite(palette[i].green, png_ptr->palette[i].green,
2450 png_ptr->trans[i], back.green);
2451 png_composite(palette[i].blue, png_ptr->palette[i].blue,
2452 png_ptr->trans[i], back.blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05002453 }
2454 }
2455 }
2456 else /* assume grayscale palette (what else could it be?) */
2457 {
2458 int i;
2459
2460 for (i = 0; i < num_palette; i++)
2461 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002462 if (i == (png_byte)png_ptr->trans_values.gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002463 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002464 palette[i].red = (png_byte)png_ptr->background.red;
2465 palette[i].green = (png_byte)png_ptr->background.green;
2466 palette[i].blue = (png_byte)png_ptr->background.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002467 }
2468 }
2469 }
2470 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002471#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002472}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002473#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002474
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002475#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002476/* Replace any alpha or transparency with the supplied background color.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002477 * "background" is already in the screen gamma, while "background_1" is
2478 * at a gamma of 1.0. Paletted files have already been taken care of.
2479 */
Guy Schalnat0d580581995-07-20 02:43:20 -05002480void
Guy Schalnat6d764711995-12-19 03:22:19 -06002481png_do_background(png_row_infop row_info, png_bytep row,
2482 png_color_16p trans_values, png_color_16p background,
2483 png_color_16p background_1,
2484 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002485 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2486 png_uint_16pp gamma_16_to_1, int gamma_shift)
Guy Schalnat0d580581995-07-20 02:43:20 -05002487{
Guy Schalnat6d764711995-12-19 03:22:19 -06002488 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002489 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002490 png_uint_32 row_width=row_info->width;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002491 int shift;
Guy Schalnate5a37791996-06-05 15:50:50 -05002492
Andreas Dilger47a0c421997-05-16 02:46:07 -05002493 png_debug(1, "in png_do_background\n");
2494 if (background != NULL &&
2495#if defined(PNG_USELESS_TESTS_SUPPORTED)
2496 row != NULL && row_info != NULL &&
2497#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002498 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
Andreas Dilger47a0c421997-05-16 02:46:07 -05002499 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
Guy Schalnat0d580581995-07-20 02:43:20 -05002500 {
2501 switch (row_info->color_type)
2502 {
2503 case PNG_COLOR_TYPE_GRAY:
2504 {
2505 switch (row_info->bit_depth)
2506 {
2507 case 1:
2508 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002509 sp = row;
2510 shift = 7;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002511 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002512 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002513 if ((png_uint_16)((*sp >> shift) & 0x1)
2514 == trans_values->gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002515 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002516 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2517 *sp |= (png_byte)(background->gray << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05002518 }
2519 if (!shift)
2520 {
2521 shift = 7;
2522 sp++;
2523 }
2524 else
2525 shift--;
2526 }
2527 break;
2528 }
2529 case 2:
2530 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002531#if defined(PNG_READ_GAMMA_SUPPORTED)
2532 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002533 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002534 sp = row;
2535 shift = 6;
2536 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002537 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002538 if ((png_uint_16)((*sp >> shift) & 0x3)
2539 == trans_values->gray)
2540 {
2541 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2542 *sp |= (png_byte)(background->gray << shift);
2543 }
2544 else
2545 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002546 png_byte p = (png_byte)((*sp >> shift) & 0x3);
2547 png_byte g = (png_byte)((gamma_table [p | (p << 2) |
2548 (p << 4) | (p << 6)] >> 6) & 0x3);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002549 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2550 *sp |= (png_byte)(g << shift);
2551 }
2552 if (!shift)
2553 {
2554 shift = 6;
2555 sp++;
2556 }
2557 else
2558 shift -= 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002559 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002560 }
2561 else
2562#endif
2563 {
2564 sp = row;
2565 shift = 6;
2566 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002567 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002568 if ((png_uint_16)((*sp >> shift) & 0x3)
2569 == trans_values->gray)
2570 {
2571 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2572 *sp |= (png_byte)(background->gray << shift);
2573 }
2574 if (!shift)
2575 {
2576 shift = 6;
2577 sp++;
2578 }
2579 else
2580 shift -= 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002581 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002582 }
2583 break;
2584 }
2585 case 4:
2586 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002587#if defined(PNG_READ_GAMMA_SUPPORTED)
2588 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002589 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002590 sp = row;
2591 shift = 4;
2592 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002593 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002594 if ((png_uint_16)((*sp >> shift) & 0xf)
2595 == trans_values->gray)
2596 {
2597 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2598 *sp |= (png_byte)(background->gray << shift);
2599 }
2600 else
2601 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002602 png_byte p = (png_byte)((*sp >> shift) & 0xf);
2603 png_byte g = (png_byte)((gamma_table[p |
2604 (p << 4)] >> 4) & 0xf);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002605 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2606 *sp |= (png_byte)(g << shift);
2607 }
2608 if (!shift)
2609 {
2610 shift = 4;
2611 sp++;
2612 }
2613 else
2614 shift -= 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05002615 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002616 }
2617 else
2618#endif
2619 {
2620 sp = row;
2621 shift = 4;
2622 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002623 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002624 if ((png_uint_16)((*sp >> shift) & 0xf)
2625 == trans_values->gray)
2626 {
2627 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2628 *sp |= (png_byte)(background->gray << shift);
2629 }
2630 if (!shift)
2631 {
2632 shift = 4;
2633 sp++;
2634 }
2635 else
2636 shift -= 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05002637 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002638 }
2639 break;
2640 }
2641 case 8:
2642 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002643#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002644 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002645 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002646 sp = row;
2647 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002648 {
2649 if (*sp == trans_values->gray)
2650 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002651 *sp = (png_byte)background->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05002652 }
2653 else
2654 {
2655 *sp = gamma_table[*sp];
2656 }
2657 }
2658 }
2659 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002660#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002661 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002662 sp = row;
2663 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002664 {
2665 if (*sp == trans_values->gray)
2666 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002667 *sp = (png_byte)background->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05002668 }
2669 }
2670 }
2671 break;
2672 }
2673 case 16:
2674 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002675#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002676 if (gamma_16 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002677 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002678 sp = row;
2679 for (i = 0; i < row_width; i++, sp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002680 {
2681 png_uint_16 v;
2682
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002683 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05002684 if (v == trans_values->gray)
2685 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002686 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002687 *sp = (png_byte)((background->gray >> 8) & 0xff);
2688 *(sp + 1) = (png_byte)(background->gray & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002689 }
2690 else
2691 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002692 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002693 *sp = (png_byte)((v >> 8) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002694 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002695 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002696 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002697 }
2698 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002699#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002700 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002701 sp = row;
2702 for (i = 0; i < row_width; i++, sp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002703 {
2704 png_uint_16 v;
2705
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002706 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05002707 if (v == trans_values->gray)
2708 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002709 *sp = (png_byte)((background->gray >> 8) & 0xff);
2710 *(sp + 1) = (png_byte)(background->gray & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002711 }
2712 }
2713 }
2714 break;
2715 }
2716 }
2717 break;
2718 }
2719 case PNG_COLOR_TYPE_RGB:
2720 {
2721 if (row_info->bit_depth == 8)
2722 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002723#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002724 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002725 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002726 sp = row;
2727 for (i = 0; i < row_width; i++, sp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002728 {
2729 if (*sp == trans_values->red &&
2730 *(sp + 1) == trans_values->green &&
2731 *(sp + 2) == trans_values->blue)
2732 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002733 *sp = (png_byte)background->red;
2734 *(sp + 1) = (png_byte)background->green;
2735 *(sp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002736 }
2737 else
2738 {
2739 *sp = gamma_table[*sp];
2740 *(sp + 1) = gamma_table[*(sp + 1)];
2741 *(sp + 2) = gamma_table[*(sp + 2)];
2742 }
2743 }
2744 }
2745 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002746#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002747 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002748 sp = row;
2749 for (i = 0; i < row_width; i++, sp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002750 {
2751 if (*sp == trans_values->red &&
2752 *(sp + 1) == trans_values->green &&
2753 *(sp + 2) == trans_values->blue)
2754 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002755 *sp = (png_byte)background->red;
2756 *(sp + 1) = (png_byte)background->green;
2757 *(sp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002758 }
2759 }
2760 }
2761 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002762 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002763 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002764#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002765 if (gamma_16 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002766 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002767 sp = row;
2768 for (i = 0; i < row_width; i++, sp += 6)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002769 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002770 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2771 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2772 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
Andreas Dilger47a0c421997-05-16 02:46:07 -05002773 if (r == trans_values->red && g == trans_values->green &&
Guy Schalnat0d580581995-07-20 02:43:20 -05002774 b == trans_values->blue)
2775 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002776 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002777 *sp = (png_byte)((background->red >> 8) & 0xff);
2778 *(sp + 1) = (png_byte)(background->red & 0xff);
2779 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2780 *(sp + 3) = (png_byte)(background->green & 0xff);
2781 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2782 *(sp + 5) = (png_byte)(background->blue & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002783 }
2784 else
2785 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002786 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002787 *sp = (png_byte)((v >> 8) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002788 *(sp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002789 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002790 *(sp + 2) = (png_byte)((v >> 8) & 0xff);
2791 *(sp + 3) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002792 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002793 *(sp + 4) = (png_byte)((v >> 8) & 0xff);
2794 *(sp + 5) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002795 }
2796 }
2797 }
2798 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002799#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002800 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002801 sp = row;
2802 for (i = 0; i < row_width; i++, sp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05002803 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002804 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
2805 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2806 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
Guy Schalnat0d580581995-07-20 02:43:20 -05002807
Andreas Dilger47a0c421997-05-16 02:46:07 -05002808 if (r == trans_values->red && g == trans_values->green &&
Guy Schalnat0d580581995-07-20 02:43:20 -05002809 b == trans_values->blue)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002810 {
2811 *sp = (png_byte)((background->red >> 8) & 0xff);
2812 *(sp + 1) = (png_byte)(background->red & 0xff);
2813 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2814 *(sp + 3) = (png_byte)(background->green & 0xff);
2815 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2816 *(sp + 5) = (png_byte)(background->blue & 0xff);
2817 }
2818 }
2819 }
2820 }
2821 break;
2822 }
2823 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -05002824 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002825 if (row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05002826 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002827#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002828 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2829 gamma_table != NULL)
2830 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002831 sp = row;
2832 dp = row;
2833 for (i = 0; i < row_width; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002834 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002835 png_uint_16 a = *(sp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002836
Andreas Dilger47a0c421997-05-16 02:46:07 -05002837 if (a == 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002838 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002839 *dp = gamma_table[*sp];
2840 }
2841 else if (a == 0)
2842 {
2843 /* background is already in screen gamma */
2844 *dp = (png_byte)background->gray;
2845 }
2846 else
2847 {
2848 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002849
Andreas Dilger47a0c421997-05-16 02:46:07 -05002850 v = gamma_to_1[*sp];
2851 png_composite(w, v, a, background_1->gray);
2852 *dp = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002853 }
2854 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002855 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002856 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002857#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05002858 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002859 sp = row;
2860 dp = row;
2861 for (i = 0; i < row_width; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002862 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002863 png_byte a = *(sp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002864
Andreas Dilger47a0c421997-05-16 02:46:07 -05002865 if (a == 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002866 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002867 *dp = *sp;
2868 }
2869 else if (a == 0)
2870 {
2871 *dp = (png_byte)background->gray;
2872 }
2873 else
2874 {
2875 png_composite(*dp, *sp, a, background_1->gray);
Guy Schalnat0d580581995-07-20 02:43:20 -05002876 }
2877 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002878 }
2879 }
2880 else /* if (png_ptr->bit_depth == 16) */
2881 {
2882#if defined(PNG_READ_GAMMA_SUPPORTED)
2883 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
2884 gamma_16_to_1 != NULL)
2885 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002886 sp = row;
2887 dp = row;
2888 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002889 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002890 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
Andreas Dilger47a0c421997-05-16 02:46:07 -05002891
Andreas Dilger47a0c421997-05-16 02:46:07 -05002892 if (a == (png_uint_16)0xffff)
2893 {
2894 png_uint_16 v;
2895
2896 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2897 *dp = (png_byte)((v >> 8) & 0xff);
2898 *(dp + 1) = (png_byte)(v & 0xff);
2899 }
2900 else if (a == 0)
2901 {
2902 /* background is already in screen gamma */
2903 *dp = (png_byte)((background->gray >> 8) & 0xff);
2904 *(dp + 1) = (png_byte)(background->gray & 0xff);
2905 }
2906 else
2907 {
2908 png_uint_16 g, v, w;
2909
2910 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
2911 png_composite_16(v, g, a, background_1->gray);
2912 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
2913 *dp = (png_byte)((w >> 8) & 0xff);
2914 *(dp + 1) = (png_byte)(w & 0xff);
2915 }
2916 }
2917 }
2918 else
2919#endif
2920 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002921 sp = row;
2922 dp = row;
2923 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002924 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002925 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
Andreas Dilger47a0c421997-05-16 02:46:07 -05002926 if (a == (png_uint_16)0xffff)
2927 {
2928 png_memcpy(dp, sp, 2);
2929 }
2930 else if (a == 0)
2931 {
2932 *dp = (png_byte)((background->gray >> 8) & 0xff);
2933 *(dp + 1) = (png_byte)(background->gray & 0xff);
2934 }
2935 else
2936 {
2937 png_uint_16 g, v;
2938
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002939 g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
Andreas Dilger47a0c421997-05-16 02:46:07 -05002940 png_composite_16(v, g, a, background_1->gray);
2941 *dp = (png_byte)((v >> 8) & 0xff);
2942 *(dp + 1) = (png_byte)(v & 0xff);
2943 }
2944 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002945 }
2946 }
2947 break;
2948 }
2949 case PNG_COLOR_TYPE_RGB_ALPHA:
2950 {
2951 if (row_info->bit_depth == 8)
2952 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002953#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002954 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2955 gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002956 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002957 sp = row;
2958 dp = row;
2959 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002960 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002961 png_byte a = *(sp + 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05002962
Guy Schalnat0d580581995-07-20 02:43:20 -05002963 if (a == 0xff)
2964 {
2965 *dp = gamma_table[*sp];
2966 *(dp + 1) = gamma_table[*(sp + 1)];
2967 *(dp + 2) = gamma_table[*(sp + 2)];
2968 }
2969 else if (a == 0)
2970 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002971 /* background is already in screen gamma */
2972 *dp = (png_byte)background->red;
2973 *(dp + 1) = (png_byte)background->green;
2974 *(dp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002975 }
2976 else
2977 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002978 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002979
2980 v = gamma_to_1[*sp];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002981 png_composite(w, v, a, background_1->red);
2982 *dp = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002983 v = gamma_to_1[*(sp + 1)];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002984 png_composite(w, v, a, background_1->green);
2985 *(dp + 1) = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002986 v = gamma_to_1[*(sp + 2)];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002987 png_composite(w, v, a, background_1->blue);
2988 *(dp + 2) = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002989 }
2990 }
2991 }
2992 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002993#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002994 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002995 sp = row;
2996 dp = row;
2997 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002998 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002999 png_byte a = *(sp + 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003000
Guy Schalnat0d580581995-07-20 02:43:20 -05003001 if (a == 0xff)
3002 {
3003 *dp = *sp;
3004 *(dp + 1) = *(sp + 1);
3005 *(dp + 2) = *(sp + 2);
3006 }
3007 else if (a == 0)
3008 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003009 *dp = (png_byte)background->red;
3010 *(dp + 1) = (png_byte)background->green;
3011 *(dp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003012 }
3013 else
3014 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003015 png_composite(*dp, *sp, a, background->red);
3016 png_composite(*(dp + 1), *(sp + 1), a,
3017 background->green);
3018 png_composite(*(dp + 2), *(sp + 2), a,
3019 background->blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05003020 }
3021 }
3022 }
3023 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003024 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003025 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003026#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003027 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3028 gamma_16_to_1 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05003029 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003030 sp = row;
3031 dp = row;
3032 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05003033 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003034 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3035 << 8) + (png_uint_16)(*(sp + 7)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003036 if (a == (png_uint_16)0xffff)
3037 {
3038 png_uint_16 v;
3039
Andreas Dilger47a0c421997-05-16 02:46:07 -05003040 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003041 *dp = (png_byte)((v >> 8) & 0xff);
3042 *(dp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003043 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003044 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3045 *(dp + 3) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003046 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003047 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3048 *(dp + 5) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003049 }
3050 else if (a == 0)
3051 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003052 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003053 *dp = (png_byte)((background->red >> 8) & 0xff);
3054 *(dp + 1) = (png_byte)(background->red & 0xff);
3055 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3056 *(dp + 3) = (png_byte)(background->green & 0xff);
3057 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3058 *(dp + 5) = (png_byte)(background->blue & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003059 }
3060 else
3061 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003062 png_uint_16 v, w, x;
Guy Schalnat0d580581995-07-20 02:43:20 -05003063
Andreas Dilger47a0c421997-05-16 02:46:07 -05003064 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3065 png_composite_16(w, v, a, background->red);
3066 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3067 *dp = (png_byte)((x >> 8) & 0xff);
3068 *(dp + 1) = (png_byte)(x & 0xff);
3069 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3070 png_composite_16(w, v, a, background->green);
3071 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3072 *(dp + 2) = (png_byte)((x >> 8) & 0xff);
3073 *(dp + 3) = (png_byte)(x & 0xff);
3074 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3075 png_composite_16(w, v, a, background->blue);
3076 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3077 *(dp + 4) = (png_byte)((x >> 8) & 0xff);
3078 *(dp + 5) = (png_byte)(x & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003079 }
3080 }
3081 }
3082 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003083#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003084 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003085 sp = row;
3086 dp = row;
3087 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05003088 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003089 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3090 << 8) + (png_uint_16)(*(sp + 7)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003091 if (a == (png_uint_16)0xffff)
3092 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003093 png_memcpy(dp, sp, 6);
Guy Schalnat0d580581995-07-20 02:43:20 -05003094 }
3095 else if (a == 0)
3096 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003097 *dp = (png_byte)((background->red >> 8) & 0xff);
3098 *(dp + 1) = (png_byte)(background->red & 0xff);
3099 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3100 *(dp + 3) = (png_byte)(background->green & 0xff);
3101 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3102 *(dp + 5) = (png_byte)(background->blue & 0xff);
3103 }
3104 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003105 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003106 png_uint_16 v;
Guy Schalnat0d580581995-07-20 02:43:20 -05003107
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003108 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3109 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3110 + *(sp + 3));
3111 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3112 + *(sp + 5));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003113
3114 png_composite_16(v, r, a, background->red);
Guy Schalnat0d580581995-07-20 02:43:20 -05003115 *dp = (png_byte)((v >> 8) & 0xff);
3116 *(dp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003117 png_composite_16(v, g, a, background->green);
Guy Schalnat0d580581995-07-20 02:43:20 -05003118 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3119 *(dp + 3) = (png_byte)(v & 0xff);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003120 png_composite_16(v, b, a, background->blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05003121 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3122 *(dp + 5) = (png_byte)(v & 0xff);
3123 }
3124 }
3125 }
3126 }
3127 break;
3128 }
3129 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003130
Guy Schalnat0d580581995-07-20 02:43:20 -05003131 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3132 {
3133 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
Guy Schalnate5a37791996-06-05 15:50:50 -05003134 row_info->channels--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003135 row_info->pixel_depth = (png_byte)(row_info->channels *
3136 row_info->bit_depth);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003137 row_info->rowbytes = ((row_width *
Guy Schalnat0d580581995-07-20 02:43:20 -05003138 row_info->pixel_depth + 7) >> 3);
3139 }
3140 }
3141}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003142#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003143
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003144#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003145/* Gamma correct the image, avoiding the alpha channel. Make sure
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05003146 * you do this after you deal with the transparency issue on grayscale
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -05003147 * or RGB images. If your bit depth is 8, use gamma_table, if it
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003148 * is 16, use gamma_16_table and gamma_shift. Build these with
3149 * build_gamma_table().
3150 */
Guy Schalnat0d580581995-07-20 02:43:20 -05003151void
Guy Schalnat6d764711995-12-19 03:22:19 -06003152png_do_gamma(png_row_infop row_info, png_bytep row,
3153 png_bytep gamma_table, png_uint_16pp gamma_16_table,
Guy Schalnat0d580581995-07-20 02:43:20 -05003154 int gamma_shift)
3155{
Guy Schalnat6d764711995-12-19 03:22:19 -06003156 png_bytep sp;
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_gamma\n");
3161 if (
3162#if defined(PNG_USELESS_TESTS_SUPPORTED)
3163 row != NULL && row_info != NULL &&
3164#endif
3165 ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3166 (row_info->bit_depth == 16 && gamma_16_table != NULL)))
Guy Schalnat0d580581995-07-20 02:43:20 -05003167 {
3168 switch (row_info->color_type)
3169 {
3170 case PNG_COLOR_TYPE_RGB:
3171 {
3172 if (row_info->bit_depth == 8)
3173 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003174 sp = row;
3175 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003176 {
3177 *sp = gamma_table[*sp];
3178 sp++;
3179 *sp = gamma_table[*sp];
3180 sp++;
3181 *sp = gamma_table[*sp];
3182 sp++;
3183 }
3184 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003185 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003186 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003187 sp = row;
3188 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003189 {
3190 png_uint_16 v;
3191
Andreas Dilger47a0c421997-05-16 02:46:07 -05003192 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003193 *sp = (png_byte)((v >> 8) & 0xff);
3194 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003195 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003196 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003197 *sp = (png_byte)((v >> 8) & 0xff);
3198 *(sp + 1) = (png_byte)(v & 0xff);
3199 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003200 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003201 *sp = (png_byte)((v >> 8) & 0xff);
3202 *(sp + 1) = (png_byte)(v & 0xff);
3203 sp += 2;
3204 }
3205 }
3206 break;
3207 }
3208 case PNG_COLOR_TYPE_RGB_ALPHA:
3209 {
3210 if (row_info->bit_depth == 8)
3211 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003212 sp = row;
3213 for (i = 0; i < row_width; i++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003214 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003215 *sp = gamma_table[*sp];
3216 sp++;
3217 *sp = gamma_table[*sp];
3218 sp++;
3219 *sp = gamma_table[*sp];
3220 sp++;
3221 sp++;
3222 }
3223 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003224 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003225 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003226 sp = row;
3227 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003228 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003229 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003230 *sp = (png_byte)((v >> 8) & 0xff);
3231 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003232 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003233 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003234 *sp = (png_byte)((v >> 8) & 0xff);
3235 *(sp + 1) = (png_byte)(v & 0xff);
3236 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003237 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003238 *sp = (png_byte)((v >> 8) & 0xff);
3239 *(sp + 1) = (png_byte)(v & 0xff);
3240 sp += 4;
3241 }
3242 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003243 break;
3244 }
3245 case PNG_COLOR_TYPE_GRAY_ALPHA:
3246 {
3247 if (row_info->bit_depth == 8)
3248 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003249 sp = row;
3250 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003251 {
3252 *sp = gamma_table[*sp];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003253 sp += 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05003254 }
3255 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003256 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003257 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003258 sp = row;
3259 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003260 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003261 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003262 *sp = (png_byte)((v >> 8) & 0xff);
3263 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003264 sp += 4;
3265 }
3266 }
3267 break;
3268 }
3269 case PNG_COLOR_TYPE_GRAY:
3270 {
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003271 if (row_info->bit_depth == 2)
3272 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003273 sp = row;
3274 for (i = 0; i < row_width; i += 4)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003275 {
3276 int a = *sp & 0xc0;
3277 int b = *sp & 0x30;
3278 int c = *sp & 0x0c;
3279 int d = *sp & 0x03;
3280
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003281 *sp = (png_byte)(
3282 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003283 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3284 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003285 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003286 sp++;
3287 }
3288 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003289 if (row_info->bit_depth == 4)
Guy Schalnat0d580581995-07-20 02:43:20 -05003290 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003291 sp = row;
3292 for (i = 0; i < row_width; i += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003293 {
3294 int msb = *sp & 0xf0;
3295 int lsb = *sp & 0x0f;
3296
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003297 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3298 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003299 sp++;
3300 }
3301 }
3302 else if (row_info->bit_depth == 8)
3303 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003304 sp = row;
3305 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003306 {
3307 *sp = gamma_table[*sp];
3308 sp++;
3309 }
3310 }
3311 else if (row_info->bit_depth == 16)
3312 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003313 sp = row;
3314 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003315 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003316 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003317 *sp = (png_byte)((v >> 8) & 0xff);
3318 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003319 sp += 2;
3320 }
3321 }
3322 break;
3323 }
3324 }
3325 }
3326}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003327#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003328
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003329#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -05003330/* Expands a palette row to an RGB or RGBA row depending
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003331 * upon whether you supply trans and num_trans.
3332 */
Guy Schalnat0d580581995-07-20 02:43:20 -05003333void
Guy Schalnat6d764711995-12-19 03:22:19 -06003334png_do_expand_palette(png_row_infop row_info, png_bytep row,
Andreas Dilger47a0c421997-05-16 02:46:07 -05003335 png_colorp palette, png_bytep trans, int num_trans)
Guy Schalnat0d580581995-07-20 02:43:20 -05003336{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003337 int shift, value;
Guy Schalnat6d764711995-12-19 03:22:19 -06003338 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003339 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003340 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003341
Andreas Dilger47a0c421997-05-16 02:46:07 -05003342 png_debug(1, "in png_do_expand_palette\n");
3343 if (
3344#if defined(PNG_USELESS_TESTS_SUPPORTED)
3345 row != NULL && row_info != NULL &&
3346#endif
3347 row_info->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05003348 {
3349 if (row_info->bit_depth < 8)
3350 {
3351 switch (row_info->bit_depth)
3352 {
3353 case 1:
3354 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003355 sp = row + (png_size_t)((row_width - 1) >> 3);
3356 dp = row + (png_size_t)row_width - 1;
3357 shift = 7 - (int)((row_width + 7) & 7);
3358 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003359 {
3360 if ((*sp >> shift) & 0x1)
3361 *dp = 1;
3362 else
3363 *dp = 0;
3364 if (shift == 7)
3365 {
3366 shift = 0;
3367 sp--;
3368 }
3369 else
3370 shift++;
3371
3372 dp--;
3373 }
3374 break;
3375 }
3376 case 2:
3377 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003378 sp = row + (png_size_t)((row_width - 1) >> 2);
3379 dp = row + (png_size_t)row_width - 1;
3380 shift = (int)((3 - ((row_width + 3) & 3)) << 1);
3381 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003382 {
3383 value = (*sp >> shift) & 0x3;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003384 *dp = (png_byte)value;
Guy Schalnat0d580581995-07-20 02:43:20 -05003385 if (shift == 6)
3386 {
3387 shift = 0;
3388 sp--;
3389 }
3390 else
3391 shift += 2;
3392
3393 dp--;
3394 }
3395 break;
3396 }
3397 case 4:
3398 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003399 sp = row + (png_size_t)((row_width - 1) >> 1);
3400 dp = row + (png_size_t)row_width - 1;
3401 shift = (int)((row_width & 1) << 2);
3402 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003403 {
3404 value = (*sp >> shift) & 0xf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003405 *dp = (png_byte)value;
Guy Schalnat0d580581995-07-20 02:43:20 -05003406 if (shift == 4)
3407 {
3408 shift = 0;
3409 sp--;
3410 }
3411 else
3412 shift += 4;
3413
3414 dp--;
3415 }
3416 break;
3417 }
3418 }
3419 row_info->bit_depth = 8;
3420 row_info->pixel_depth = 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003421 row_info->rowbytes = row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -05003422 }
3423 switch (row_info->bit_depth)
3424 {
3425 case 8:
3426 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003427 if (trans != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05003428 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003429 sp = row + (png_size_t)row_width - 1;
3430 dp = row + (png_size_t)(row_width << 2) - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003431
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003432 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003433 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003434 if ((int)(*sp) >= num_trans)
Guy Schalnat0d580581995-07-20 02:43:20 -05003435 *dp-- = 0xff;
3436 else
3437 *dp-- = trans[*sp];
3438 *dp-- = palette[*sp].blue;
3439 *dp-- = palette[*sp].green;
3440 *dp-- = palette[*sp].red;
3441 sp--;
3442 }
3443 row_info->bit_depth = 8;
3444 row_info->pixel_depth = 32;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003445 row_info->rowbytes = row_width * 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05003446 row_info->color_type = 6;
3447 row_info->channels = 4;
3448 }
3449 else
3450 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003451 sp = row + (png_size_t)row_width - 1;
3452 dp = row + (png_size_t)(row_width * 3) - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003453
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003454 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003455 {
3456 *dp-- = palette[*sp].blue;
3457 *dp-- = palette[*sp].green;
3458 *dp-- = palette[*sp].red;
3459 sp--;
3460 }
3461 row_info->bit_depth = 8;
3462 row_info->pixel_depth = 24;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003463 row_info->rowbytes = row_width * 3;
Guy Schalnat0d580581995-07-20 02:43:20 -05003464 row_info->color_type = 2;
3465 row_info->channels = 3;
3466 }
3467 break;
3468 }
3469 }
3470 }
3471}
3472
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003473/* If the bit depth < 8, it is expanded to 8. Also, if the
3474 * transparency value is supplied, an alpha channel is built.
3475 */
Guy Schalnat0d580581995-07-20 02:43:20 -05003476void
Guy Schalnat6d764711995-12-19 03:22:19 -06003477png_do_expand(png_row_infop row_info, png_bytep row,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003478 png_color_16p trans_value)
Guy Schalnat0d580581995-07-20 02:43:20 -05003479{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003480 int shift, value;
Guy Schalnat6d764711995-12-19 03:22:19 -06003481 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003482 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003483 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003484
Andreas Dilger47a0c421997-05-16 02:46:07 -05003485 png_debug(1, "in png_do_expand\n");
3486#if defined(PNG_USELESS_TESTS_SUPPORTED)
3487 if (row != NULL && row_info != NULL)
3488#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003489 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003490 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05003491 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003492 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003493
3494 if (row_info->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003495 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003496 switch (row_info->bit_depth)
Guy Schalnat0d580581995-07-20 02:43:20 -05003497 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003498 case 1:
3499 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003500 gray = (png_uint_16)(gray*0xff);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003501 sp = row + (png_size_t)((row_width - 1) >> 3);
3502 dp = row + (png_size_t)row_width - 1;
3503 shift = 7 - (int)((row_width + 7) & 7);
3504 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003505 {
3506 if ((*sp >> shift) & 0x1)
3507 *dp = 0xff;
3508 else
3509 *dp = 0;
3510 if (shift == 7)
3511 {
3512 shift = 0;
3513 sp--;
3514 }
3515 else
3516 shift++;
3517
3518 dp--;
3519 }
3520 break;
3521 }
3522 case 2:
3523 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003524 gray = (png_uint_16)(gray*0x55);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003525 sp = row + (png_size_t)((row_width - 1) >> 2);
3526 dp = row + (png_size_t)row_width - 1;
3527 shift = (int)((3 - ((row_width + 3) & 3)) << 1);
3528 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003529 {
3530 value = (*sp >> shift) & 0x3;
3531 *dp = (png_byte)(value | (value << 2) | (value << 4) |
3532 (value << 6));
3533 if (shift == 6)
3534 {
3535 shift = 0;
3536 sp--;
3537 }
3538 else
3539 shift += 2;
3540
3541 dp--;
3542 }
3543 break;
3544 }
3545 case 4:
3546 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003547 gray = (png_uint_16)(gray*0x11);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003548 sp = row + (png_size_t)((row_width - 1) >> 1);
3549 dp = row + (png_size_t)row_width - 1;
3550 shift = (int)((1 - ((row_width + 1) & 1)) << 2);
3551 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003552 {
3553 value = (*sp >> shift) & 0xf;
3554 *dp = (png_byte)(value | (value << 4));
3555 if (shift == 4)
3556 {
3557 shift = 0;
3558 sp--;
3559 }
3560 else
3561 shift = 4;
3562
3563 dp--;
3564 }
3565 break;
3566 }
3567 }
3568 row_info->bit_depth = 8;
3569 row_info->pixel_depth = 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003570 row_info->rowbytes = row_width;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003571 }
3572
Andreas Dilger47a0c421997-05-16 02:46:07 -05003573 if (trans_value != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003574 {
3575 if (row_info->bit_depth == 8)
3576 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003577 sp = row + (png_size_t)row_width - 1;
3578 dp = row + (png_size_t)(row_width << 1) - 1;
3579 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003580 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003581 if (*sp == gray)
3582 *dp-- = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003583 else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003584 *dp-- = 0xff;
3585 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003586 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003587 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003588 else if (row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -05003589 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003590 sp = row + row_info->rowbytes - 1;
3591 dp = row + (row_info->rowbytes << 1) - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003592 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003593 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003594 if (((png_uint_16)*(sp) |
3595 ((png_uint_16)*(sp - 1) << 8)) == gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05003596 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003597 *dp-- = 0;
3598 *dp-- = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003599 }
3600 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003601 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003602 *dp-- = 0xff;
3603 *dp-- = 0xff;
Guy Schalnat0d580581995-07-20 02:43:20 -05003604 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003605 *dp-- = *sp--;
3606 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003607 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003608 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003609 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3610 row_info->channels = 2;
3611 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3612 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003613 ((row_width * row_info->pixel_depth) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003614 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003615 }
3616 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3617 {
3618 if (row_info->bit_depth == 8)
3619 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003620 sp = row + (png_size_t)row_info->rowbytes - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003621 dp = row + (png_size_t)(row_width << 2) - 1;
3622 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003623 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003624 if (*(sp - 2) == trans_value->red &&
Guy Schalnat0d580581995-07-20 02:43:20 -05003625 *(sp - 1) == trans_value->green &&
3626 *(sp - 0) == trans_value->blue)
3627 *dp-- = 0;
3628 else
3629 *dp-- = 0xff;
3630 *dp-- = *sp--;
3631 *dp-- = *sp--;
3632 *dp-- = *sp--;
3633 }
3634 }
3635 else if (row_info->bit_depth == 16)
3636 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003637 sp = row + row_info->rowbytes - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003638 dp = row + (png_size_t)(row_width << 3) - 1;
3639 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003640 {
3641 if ((((png_uint_16)*(sp - 4) |
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003642 ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
Guy Schalnat0d580581995-07-20 02:43:20 -05003643 (((png_uint_16)*(sp - 2) |
3644 ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
3645 (((png_uint_16)*(sp - 0) |
3646 ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
3647 {
3648 *dp-- = 0;
3649 *dp-- = 0;
3650 }
3651 else
3652 {
3653 *dp-- = 0xff;
3654 *dp-- = 0xff;
3655 }
3656 *dp-- = *sp--;
3657 *dp-- = *sp--;
3658 *dp-- = *sp--;
3659 *dp-- = *sp--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003660 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003661 *dp-- = *sp--;
3662 }
3663 }
3664 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3665 row_info->channels = 4;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003666 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
Guy Schalnat0d580581995-07-20 02:43:20 -05003667 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003668 ((row_width * row_info->pixel_depth) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003669 }
3670 }
3671}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003672#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003673
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003674#if defined(PNG_READ_DITHER_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003675void
Guy Schalnat6d764711995-12-19 03:22:19 -06003676png_do_dither(png_row_infop row_info, png_bytep row,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003677 png_bytep palette_lookup, png_bytep dither_lookup)
Guy Schalnat0d580581995-07-20 02:43:20 -05003678{
Guy Schalnat6d764711995-12-19 03:22:19 -06003679 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003680 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003681 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003682
Andreas Dilger47a0c421997-05-16 02:46:07 -05003683 png_debug(1, "in png_do_dither\n");
3684#if defined(PNG_USELESS_TESTS_SUPPORTED)
3685 if (row != NULL && row_info != NULL)
3686#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003687 {
3688 if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3689 palette_lookup && row_info->bit_depth == 8)
3690 {
3691 int r, g, b, p;
Guy Schalnat0d580581995-07-20 02:43:20 -05003692 sp = row;
3693 dp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003694 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003695 {
3696 r = *sp++;
3697 g = *sp++;
3698 b = *sp++;
3699
3700 /* this looks real messy, but the compiler will reduce
3701 it down to a reasonable formula. For example, with
3702 5 bits per color, we get:
3703 p = (((r >> 3) & 0x1f) << 10) |
3704 (((g >> 3) & 0x1f) << 5) |
3705 ((b >> 3) & 0x1f);
3706 */
3707 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3708 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3709 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3710 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003711 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
Guy Schalnat0d580581995-07-20 02:43:20 -05003712 (PNG_DITHER_BLUE_BITS)) |
3713 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3714 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3715
3716 *dp++ = palette_lookup[p];
3717 }
3718 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3719 row_info->channels = 1;
3720 row_info->pixel_depth = row_info->bit_depth;
3721 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003722 ((row_width * row_info->pixel_depth + 7) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003723 }
3724 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
Andreas Dilger47a0c421997-05-16 02:46:07 -05003725 palette_lookup != NULL && row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003726 {
3727 int r, g, b, p;
Guy Schalnat0d580581995-07-20 02:43:20 -05003728 sp = row;
3729 dp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003730 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003731 {
3732 r = *sp++;
3733 g = *sp++;
3734 b = *sp++;
3735 sp++;
3736
3737 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003738 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
Guy Schalnat0d580581995-07-20 02:43:20 -05003739 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3740 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3741 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3742 (PNG_DITHER_BLUE_BITS)) |
3743 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3744 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3745
3746 *dp++ = palette_lookup[p];
3747 }
3748 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3749 row_info->channels = 1;
3750 row_info->pixel_depth = row_info->bit_depth;
3751 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003752 ((row_width * row_info->pixel_depth + 7) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003753 }
3754 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
3755 dither_lookup && row_info->bit_depth == 8)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003756 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003757 sp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003758 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003759 {
3760 *sp = dither_lookup[*sp];
3761 }
3762 }
3763 }
3764}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003765#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003766
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003767#if defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003768static int png_gamma_shift[] =
3769 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
3770
Andreas Dilger47a0c421997-05-16 02:46:07 -05003771/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003772 * tables, we don't make a full table if we are reducing to 8-bit in
3773 * the future. Note also how the gamma_16 tables are segmented so that
3774 * we don't need to allocate > 64K chunks for a full 16-bit table.
3775 */
Guy Schalnat0d580581995-07-20 02:43:20 -05003776void
Guy Schalnat6d764711995-12-19 03:22:19 -06003777png_build_gamma_table(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05003778{
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003779 png_debug(1, "in png_build_gamma_table\n");
3780 if(png_ptr->gamma != 0.0)
3781 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003782 if (png_ptr->bit_depth <= 8)
3783 {
3784 int i;
3785 double g;
3786
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003787 if (png_ptr->screen_gamma > .000001)
3788 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3789 else
3790 g = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003791
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003792 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003793 (png_uint_32)256);
3794
3795 for (i = 0; i < 256; i++)
3796 {
3797 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
3798 g) * 255.0 + .5);
3799 }
3800
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003801#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3802 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
3803 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -05003804 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003805
Guy Schalnat0d580581995-07-20 02:43:20 -05003806 g = 1.0 / (png_ptr->gamma);
3807
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003808 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003809 (png_uint_32)256);
3810
3811 for (i = 0; i < 256; i++)
3812 {
3813 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
3814 g) * 255.0 + .5);
3815 }
3816
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003817
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003818 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003819 (png_uint_32)256);
3820
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003821 if(png_ptr->screen_gamma > 0.000001)
3822 g = 1.0 / png_ptr->screen_gamma;
3823 else
3824 g = png_ptr->gamma; /* probably doing rgb_to_gray */
3825
Guy Schalnat0d580581995-07-20 02:43:20 -05003826 for (i = 0; i < 256; i++)
3827 {
3828 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
3829 g) * 255.0 + .5);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003830
Guy Schalnat0d580581995-07-20 02:43:20 -05003831 }
3832 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003833#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003834 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003835 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003836 {
3837 double g;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003838 int i, j, shift, num;
3839 int sig_bit;
3840 png_uint_32 ig;
Guy Schalnat0d580581995-07-20 02:43:20 -05003841
3842 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003843 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003844 sig_bit = (int)png_ptr->sig_bit.red;
3845 if ((int)png_ptr->sig_bit.green > sig_bit)
3846 sig_bit = png_ptr->sig_bit.green;
3847 if ((int)png_ptr->sig_bit.blue > sig_bit)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003848 sig_bit = png_ptr->sig_bit.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003849 }
3850 else
3851 {
3852 sig_bit = (int)png_ptr->sig_bit.gray;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003853 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003854
3855 if (sig_bit > 0)
3856 shift = 16 - sig_bit;
3857 else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003858 shift = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003859
3860 if (png_ptr->transformations & PNG_16_TO_8)
3861 {
3862 if (shift < (16 - PNG_MAX_GAMMA_8))
3863 shift = (16 - PNG_MAX_GAMMA_8);
3864 }
3865
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003866 if (shift > 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003867 shift = 8;
3868 if (shift < 0)
3869 shift = 0;
3870
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003871 png_ptr->gamma_shift = (png_byte)shift;
Guy Schalnat0d580581995-07-20 02:43:20 -05003872
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003873 num = (1 << (8 - shift));
Guy Schalnat0d580581995-07-20 02:43:20 -05003874
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003875 if (png_ptr->screen_gamma > .000001)
3876 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3877 else
3878 g = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003879
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003880 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003881 (png_uint_32)(num * sizeof (png_uint_16p)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003882
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003883 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003884 {
3885 double fin, fout;
3886 png_uint_32 last, max;
Guy Schalnat0d580581995-07-20 02:43:20 -05003887
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003888 for (i = 0; i < num; i++)
3889 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003890 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003891 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003892 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003893
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003894 g = 1.0 / g;
3895 last = 0;
3896 for (i = 0; i < 256; i++)
3897 {
3898 fout = ((double)i + 0.5) / 256.0;
3899 fin = pow(fout, g);
3900 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
3901 while (last <= max)
3902 {
3903 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
3904 [(int)(last >> (8 - shift))] = (png_uint_16)(
3905 (png_uint_16)i | ((png_uint_16)i << 8));
3906 last++;
3907 }
3908 }
3909 while (last < ((png_uint_32)num << 8))
3910 {
3911 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
Andreas Dilger47a0c421997-05-16 02:46:07 -05003912 [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003913 last++;
Guy Schalnat6d764711995-12-19 03:22:19 -06003914 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003915 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003916 else
3917 {
3918 for (i = 0; i < num; i++)
3919 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003920 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003921 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003922
Andreas Dilger47a0c421997-05-16 02:46:07 -05003923 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003924 for (j = 0; j < 256; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003925 {
3926 png_ptr->gamma_16_table[i][j] =
3927 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
3928 65535.0, g) * 65535.0 + .5);
3929 }
3930 }
3931 }
3932
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003933#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3934 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
3935 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -05003936 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003937
Guy Schalnat0d580581995-07-20 02:43:20 -05003938 g = 1.0 / (png_ptr->gamma);
3939
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003940 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003941 (png_uint_32)(num * sizeof (png_uint_16p )));
Guy Schalnat0d580581995-07-20 02:43:20 -05003942
3943 for (i = 0; i < num; i++)
3944 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003945 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003946 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003947
3948 ig = (((png_uint_32)i *
3949 (png_uint_32)png_gamma_shift[shift]) >> 4);
3950 for (j = 0; j < 256; j++)
3951 {
3952 png_ptr->gamma_16_to_1[i][j] =
3953 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
3954 65535.0, g) * 65535.0 + .5);
3955 }
3956 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003957
3958 if(png_ptr->screen_gamma > 0.000001)
3959 g = 1.0 / png_ptr->screen_gamma;
3960 else
3961 g = png_ptr->gamma; /* probably doing rgb_to_gray */
Guy Schalnat0d580581995-07-20 02:43:20 -05003962
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003963 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003964 (png_uint_32)(num * sizeof (png_uint_16p)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003965
3966 for (i = 0; i < num; i++)
3967 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003968 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003969 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003970
3971 ig = (((png_uint_32)i *
3972 (png_uint_32)png_gamma_shift[shift]) >> 4);
3973 for (j = 0; j < 256; j++)
3974 {
3975 png_ptr->gamma_16_from_1[i][j] =
3976 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
3977 65535.0, g) * 65535.0 + .5);
3978 }
3979 }
3980 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003981#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003982 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003983 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003984}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003985#endif
3986