blob: f4dea7ae4f4aa6e6ecd2e008c8c36cd60a359a04 [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-Pehrsondff799e2004-08-07 21:42:49 -05004 * libpng version 1.2.6rc2 - August 8, 2004
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * For conditions of distribution and use, see copyright notice in png.h
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05006 * Copyright (c) 1998-2004 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05007 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
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. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050020void PNGAPI
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060021png_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
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060072#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
73 defined(PNG_FLOATING_POINT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050074/* handle alpha and tRNS via a background color */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050075void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060076png_set_background(png_structp png_ptr,
77 png_color_16p background_color, int background_gamma_code,
Guy Schalnat51f0eb41995-09-26 05:22:39 -050078 int need_expand, double background_gamma)
Guy Schalnat0d580581995-07-20 02:43:20 -050079{
Andreas Dilger47a0c421997-05-16 02:46:07 -050080 png_debug(1, "in png_set_background\n");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060081 if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
82 {
83 png_warning(png_ptr, "Application must supply a known background gamma");
84 return;
85 }
86
Guy Schalnat0d580581995-07-20 02:43:20 -050087 png_ptr->transformations |= PNG_BACKGROUND;
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050088 png_memcpy(&(png_ptr->background), background_color,
89 png_sizeof(png_color_16));
Guy Schalnat51f0eb41995-09-26 05:22:39 -050090 png_ptr->background_gamma = (float)background_gamma;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060091 png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
Guy Schalnate5a37791996-06-05 15:50:50 -050092 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050093
94 /* Note: if need_expand is set and color_type is either RGB or RGB_ALPHA
95 * (in which case need_expand is superfluous anyway), the background color
96 * might actually be gray yet not be flagged as such. This is not a problem
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -060097 * for the current code, which uses PNG_BACKGROUND_IS_GRAY only to
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050098 * decide when to do the png_do_gray_to_rgb() transformation.
99 */
100 if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
101 (!need_expand && background_color->red == background_color->green &&
102 background_color->red == background_color->blue))
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600103 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
Guy Schalnat0d580581995-07-20 02:43:20 -0500104}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500105#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500106
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500107#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500108/* strip 16 bit depth files to 8 bit depth */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500109void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600110png_set_strip_16(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500111{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500112 png_debug(1, "in png_set_strip_16\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500113 png_ptr->transformations |= PNG_16_TO_8;
114}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500115#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500116
Andreas Dilger47a0c421997-05-16 02:46:07 -0500117#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500118void PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -0500119png_set_strip_alpha(png_structp png_ptr)
120{
121 png_debug(1, "in png_set_strip_alpha\n");
122 png_ptr->transformations |= PNG_STRIP_ALPHA;
123}
124#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500125
Andreas Dilger47a0c421997-05-16 02:46:07 -0500126#if defined(PNG_READ_DITHER_SUPPORTED)
127/* Dither file to 8 bit. Supply a palette, the current number
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600128 * of elements in the palette, the maximum number of elements
129 * allowed, and a histogram if possible. If the current number
130 * of colors is greater then the maximum number, the palette will be
131 * modified to fit in the maximum number. "full_dither" indicates
132 * whether we need a dithering cube set up for RGB images, or if we
133 * simply are reducing the number of colors in a paletted image.
134 */
Guy Schalnat6d764711995-12-19 03:22:19 -0600135
136typedef struct png_dsort_struct
Guy Schalnat0d580581995-07-20 02:43:20 -0500137{
Guy Schalnat6d764711995-12-19 03:22:19 -0600138 struct png_dsort_struct FAR * next;
Guy Schalnat0d580581995-07-20 02:43:20 -0500139 png_byte left;
140 png_byte right;
Guy Schalnat6d764711995-12-19 03:22:19 -0600141} png_dsort;
142typedef png_dsort FAR * png_dsortp;
143typedef png_dsort FAR * FAR * png_dsortpp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500144
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500145void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600146png_set_dither(png_structp png_ptr, png_colorp palette,
147 int num_palette, int maximum_colors, png_uint_16p histogram,
Guy Schalnat0d580581995-07-20 02:43:20 -0500148 int full_dither)
149{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500150 png_debug(1, "in png_set_dither\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500151 png_ptr->transformations |= PNG_DITHER;
152
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600153 if (!full_dither)
Guy Schalnat0d580581995-07-20 02:43:20 -0500154 {
155 int i;
156
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600157 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500158 (png_uint_32)(num_palette * png_sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500159 for (i = 0; i < num_palette; i++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600160 png_ptr->dither_index[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500161 }
162
163 if (num_palette > maximum_colors)
164 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500165 if (histogram != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500166 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500167 /* This is easy enough, just throw out the least used colors.
168 Perhaps not the best solution, but good enough. */
Guy Schalnat0d580581995-07-20 02:43:20 -0500169
170 int i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500171
172 /* initialize an array to sort colors */
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500173 png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500174 (png_uint_32)(num_palette * png_sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500175
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500176 /* initialize the dither_sort array */
Guy Schalnat0d580581995-07-20 02:43:20 -0500177 for (i = 0; i < num_palette; i++)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500178 png_ptr->dither_sort[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500179
Andreas Dilger47a0c421997-05-16 02:46:07 -0500180 /* Find the least used palette entries by starting a
Guy Schalnat0d580581995-07-20 02:43:20 -0500181 bubble sort, and running it until we have sorted
182 out enough colors. Note that we don't care about
183 sorting all the colors, just finding which are
184 least used. */
185
186 for (i = num_palette - 1; i >= maximum_colors; i--)
187 {
188 int done; /* to stop early if the list is pre-sorted */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600189 int j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500190
191 done = 1;
192 for (j = 0; j < i; j++)
193 {
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500194 if (histogram[png_ptr->dither_sort[j]]
195 < histogram[png_ptr->dither_sort[j + 1]])
Guy Schalnat0d580581995-07-20 02:43:20 -0500196 {
197 png_byte t;
198
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500199 t = png_ptr->dither_sort[j];
200 png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
201 png_ptr->dither_sort[j + 1] = t;
Guy Schalnat0d580581995-07-20 02:43:20 -0500202 done = 0;
203 }
204 }
205 if (done)
206 break;
207 }
208
209 /* swap the palette around, and set up a table, if necessary */
210 if (full_dither)
211 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500212 int j = num_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500213
214 /* put all the useful colors within the max, but don't
215 move the others */
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500216 for (i = 0; i < maximum_colors; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500217 {
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500218 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500219 {
220 do
221 j--;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500222 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
Guy Schalnat0d580581995-07-20 02:43:20 -0500223 palette[i] = palette[j];
224 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600225 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500226 }
227 else
228 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500229 int j = num_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500230
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600231 /* move all the used colors inside the max limit, and
Guy Schalnat0d580581995-07-20 02:43:20 -0500232 develop a translation table */
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500233 for (i = 0; i < maximum_colors; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500234 {
235 /* only move the colors we need to */
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500236 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500237 {
238 png_color tmp_color;
239
240 do
241 j--;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500242 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
Guy Schalnat0d580581995-07-20 02:43:20 -0500243
244 tmp_color = palette[j];
245 palette[j] = palette[i];
246 palette[i] = tmp_color;
247 /* indicate where the color went */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600248 png_ptr->dither_index[j] = (png_byte)i;
249 png_ptr->dither_index[i] = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500250 }
251 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500252
253 /* find closest color for those colors we are not using */
Guy Schalnat0d580581995-07-20 02:43:20 -0500254 for (i = 0; i < num_palette; i++)
255 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600256 if ((int)png_ptr->dither_index[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500257 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500258 int min_d, k, min_k, d_index;
Guy Schalnat0d580581995-07-20 02:43:20 -0500259
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600260 /* find the closest color to one we threw out */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500261 d_index = png_ptr->dither_index[i];
262 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
263 for (k = 1, min_k = 0; k < maximum_colors; k++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500264 {
265 int d;
266
Andreas Dilger47a0c421997-05-16 02:46:07 -0500267 d = PNG_COLOR_DIST(palette[d_index], palette[k]);
Guy Schalnat0d580581995-07-20 02:43:20 -0500268
269 if (d < min_d)
270 {
271 min_d = d;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500272 min_k = k;
Guy Schalnat0d580581995-07-20 02:43:20 -0500273 }
274 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600275 /* point to closest color */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500276 png_ptr->dither_index[i] = (png_byte)min_k;
Guy Schalnat0d580581995-07-20 02:43:20 -0500277 }
278 }
279 }
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500280 png_free(png_ptr, png_ptr->dither_sort);
281 png_ptr->dither_sort=NULL;
Guy Schalnat0d580581995-07-20 02:43:20 -0500282 }
283 else
284 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500285 /* This is much harder to do simply (and quickly). Perhaps
Guy Schalnat0d580581995-07-20 02:43:20 -0500286 we need to go through a median cut routine, but those
287 don't always behave themselves with only a few colors
288 as input. So we will just find the closest two colors,
289 and throw out one of them (chosen somewhat randomly).
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600290 [We don't understand this at all, so if someone wants to
291 work on improving it, be our guest - AED, GRP]
Guy Schalnat0d580581995-07-20 02:43:20 -0500292 */
293 int i;
294 int max_d;
295 int num_new_palette;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500296 png_dsortp t;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600297 png_dsortpp hash;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500298
299 t=NULL;
Guy Schalnat0d580581995-07-20 02:43:20 -0500300
301 /* initialize palette index arrays */
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500302 png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500303 (png_uint_32)(num_palette * png_sizeof (png_byte)));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500304 png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500305 (png_uint_32)(num_palette * png_sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500306
307 /* initialize the sort array */
308 for (i = 0; i < num_palette; i++)
309 {
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500310 png_ptr->index_to_palette[i] = (png_byte)i;
311 png_ptr->palette_to_index[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500312 }
313
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600314 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500315 png_sizeof (png_dsortp)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500316 for (i = 0; i < 769; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500317 hash[i] = NULL;
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500318/* png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */
Guy Schalnat0d580581995-07-20 02:43:20 -0500319
320 num_new_palette = num_palette;
321
322 /* initial wild guess at how far apart the farthest pixel
323 pair we will be eliminating will be. Larger
324 numbers mean more areas will be allocated, Smaller
325 numbers run the risk of not saving enough data, and
326 having to do this all over again.
327
328 I have not done extensive checking on this number.
329 */
330 max_d = 96;
331
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600332 while (num_new_palette > maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500333 {
334 for (i = 0; i < num_new_palette - 1; i++)
335 {
336 int j;
337
338 for (j = i + 1; j < num_new_palette; j++)
339 {
340 int d;
341
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600342 d = PNG_COLOR_DIST(palette[i], palette[j]);
Guy Schalnat0d580581995-07-20 02:43:20 -0500343
344 if (d <= max_d)
345 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500346
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500347 t = (png_dsortp)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500348 (png_uint_32)(png_sizeof(png_dsort)));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500349 if (t == NULL)
350 break;
Guy Schalnat0d580581995-07-20 02:43:20 -0500351 t->next = hash[d];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600352 t->left = (png_byte)i;
353 t->right = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500354 hash[d] = t;
355 }
356 }
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500357 if (t == NULL)
358 break;
Guy Schalnat0d580581995-07-20 02:43:20 -0500359 }
360
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500361 if (t != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500362 for (i = 0; i <= max_d; i++)
363 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500364 if (hash[i] != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500365 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600366 png_dsortp p;
Guy Schalnat0d580581995-07-20 02:43:20 -0500367
368 for (p = hash[i]; p; p = p->next)
369 {
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500370 if ((int)png_ptr->index_to_palette[p->left]
371 < num_new_palette &&
372 (int)png_ptr->index_to_palette[p->right]
373 < num_new_palette)
Guy Schalnat0d580581995-07-20 02:43:20 -0500374 {
375 int j, next_j;
376
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600377 if (num_new_palette & 0x01)
Guy Schalnat0d580581995-07-20 02:43:20 -0500378 {
379 j = p->left;
380 next_j = p->right;
381 }
382 else
383 {
384 j = p->right;
385 next_j = p->left;
386 }
387
388 num_new_palette--;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500389 palette[png_ptr->index_to_palette[j]]
390 = palette[num_new_palette];
Guy Schalnat0d580581995-07-20 02:43:20 -0500391 if (!full_dither)
392 {
393 int k;
394
395 for (k = 0; k < num_palette; k++)
396 {
397 if (png_ptr->dither_index[k] ==
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500398 png_ptr->index_to_palette[j])
Guy Schalnat0d580581995-07-20 02:43:20 -0500399 png_ptr->dither_index[k] =
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500400 png_ptr->index_to_palette[next_j];
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600401 if ((int)png_ptr->dither_index[k] ==
Guy Schalnat0d580581995-07-20 02:43:20 -0500402 num_new_palette)
403 png_ptr->dither_index[k] =
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500404 png_ptr->index_to_palette[j];
Guy Schalnat0d580581995-07-20 02:43:20 -0500405 }
406 }
407
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500408 png_ptr->index_to_palette[png_ptr->palette_to_index
409 [num_new_palette]] = png_ptr->index_to_palette[j];
410 png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
411 = png_ptr->palette_to_index[num_new_palette];
Guy Schalnat0d580581995-07-20 02:43:20 -0500412
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500413 png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
414 png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500415 }
416 if (num_new_palette <= maximum_colors)
417 break;
418 }
419 if (num_new_palette <= maximum_colors)
420 break;
421 }
422 }
423
424 for (i = 0; i < 769; i++)
425 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500426 if (hash[i] != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500427 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500428 png_dsortp p = hash[i];
Guy Schalnat0d580581995-07-20 02:43:20 -0500429 while (p)
430 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500431 t = p->next;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600432 png_free(png_ptr, p);
Guy Schalnat0d580581995-07-20 02:43:20 -0500433 p = t;
434 }
435 }
436 hash[i] = 0;
437 }
438 max_d += 96;
439 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600440 png_free(png_ptr, hash);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500441 png_free(png_ptr, png_ptr->palette_to_index);
442 png_free(png_ptr, png_ptr->index_to_palette);
443 png_ptr->palette_to_index=NULL;
444 png_ptr->index_to_palette=NULL;
Guy Schalnat0d580581995-07-20 02:43:20 -0500445 }
446 num_palette = maximum_colors;
447 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500448 if (png_ptr->palette == NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600449 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500450 png_ptr->palette = palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500451 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600452 png_ptr->num_palette = (png_uint_16)num_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500453
454 if (full_dither)
455 {
456 int i;
Guy Schalnat6d764711995-12-19 03:22:19 -0600457 png_bytep distance;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500458 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600459 PNG_DITHER_BLUE_BITS;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500460 int num_red = (1 << PNG_DITHER_RED_BITS);
461 int num_green = (1 << PNG_DITHER_GREEN_BITS);
462 int num_blue = (1 << PNG_DITHER_BLUE_BITS);
463 png_size_t num_entries = ((png_size_t)1 << total_bits);
Guy Schalnat0d580581995-07-20 02:43:20 -0500464
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600465 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500466 (png_uint_32)(num_entries * png_sizeof (png_byte)));
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500467
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500468 png_memset(png_ptr->palette_lookup, 0, num_entries *
469 png_sizeof (png_byte));
Guy Schalnat0d580581995-07-20 02:43:20 -0500470
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600471 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500472 png_sizeof(png_byte)));
Glenn Randers-Pehrsone1eff582001-04-14 20:15:41 -0500473
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500474 png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500475
476 for (i = 0; i < num_palette; i++)
477 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500478 int ir, ig, ib;
479 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
480 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
481 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
Guy Schalnat0d580581995-07-20 02:43:20 -0500482
483 for (ir = 0; ir < num_red; ir++)
484 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500485 int dr = abs(ir - r);
486 int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
Guy Schalnat0d580581995-07-20 02:43:20 -0500487
Guy Schalnat0d580581995-07-20 02:43:20 -0500488 for (ig = 0; ig < num_green; ig++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600489 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500490 int dg = abs(ig - g);
491 int dt = dr + dg;
492 int dm = ((dr > dg) ? dr : dg);
493 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
Guy Schalnat0d580581995-07-20 02:43:20 -0500494
Guy Schalnat0d580581995-07-20 02:43:20 -0500495 for (ib = 0; ib < num_blue; ib++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600496 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500497 int d_index = index_g | ib;
498 int db = abs(ib - b);
499 int dmax = ((dm > db) ? dm : db);
500 int d = dmax + dt + db;
Guy Schalnat0d580581995-07-20 02:43:20 -0500501
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600502 if (d < (int)distance[d_index])
Guy Schalnat0d580581995-07-20 02:43:20 -0500503 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500504 distance[d_index] = (png_byte)d;
505 png_ptr->palette_lookup[d_index] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500506 }
507 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500508 }
509 }
510 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500511
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600512 png_free(png_ptr, distance);
Guy Schalnat0d580581995-07-20 02:43:20 -0500513 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500514}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500515#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500516
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600517#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600518/* Transform the image from the file_gamma to the screen_gamma. We
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600519 * only do transformations on images where the file_gamma and screen_gamma
520 * are not close reciprocals, otherwise it slows things down slightly, and
521 * also needlessly introduces small errors.
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -0600522 *
523 * We will turn off gamma transformation later if no semitransparent entries
524 * are present in the tRNS array for palette images. We can't do it here
525 * because we don't necessarily have the tRNS chunk yet.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600526 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500527void PNGAPI
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600528png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
Guy Schalnat0d580581995-07-20 02:43:20 -0500529{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500530 png_debug(1, "in png_set_gamma\n");
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -0600531 if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
532 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
533 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
534 png_ptr->transformations |= PNG_GAMMA;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500535 png_ptr->gamma = (float)file_gamma;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600536 png_ptr->screen_gamma = (float)scrn_gamma;
Guy Schalnat0d580581995-07-20 02:43:20 -0500537}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500538#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500539
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500540#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -0500541/* Expand paletted images to RGB, expand grayscale images of
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500542 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600543 * to alpha channels.
544 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500545void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600546png_set_expand(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500547{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500548 png_debug(1, "in png_set_expand\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500549 png_ptr->transformations |= PNG_EXPAND;
550}
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500551
552/* GRR 19990627: the following three functions currently are identical
553 * to png_set_expand(). However, it is entirely reasonable that someone
554 * might wish to expand an indexed image to RGB but *not* expand a single,
555 * fully transparent palette entry to a full alpha channel--perhaps instead
556 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
557 * the transparent color with a particular RGB value, or drop tRNS entirely.
558 * IOW, a future version of the library may make the transformations flag
559 * a bit more fine-grained, with separate bits for each of these three
560 * functions.
561 *
562 * More to the point, these functions make it obvious what libpng will be
563 * doing, whereas "expand" can (and does) mean any number of things.
564 */
565
566/* Expand paletted images to RGB. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500567void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500568png_set_palette_to_rgb(png_structp png_ptr)
569{
570 png_debug(1, "in png_set_expand\n");
571 png_ptr->transformations |= PNG_EXPAND;
572}
573
574/* Expand grayscale images of less than 8-bit depth to 8 bits. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500575void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500576png_set_gray_1_2_4_to_8(png_structp png_ptr)
577{
578 png_debug(1, "in png_set_expand\n");
579 png_ptr->transformations |= PNG_EXPAND;
580}
581
582/* Expand tRNS chunks to alpha channels. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500583void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500584png_set_tRNS_to_alpha(png_structp png_ptr)
585{
586 png_debug(1, "in png_set_expand\n");
587 png_ptr->transformations |= PNG_EXPAND;
588}
589#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
Guy Schalnat0d580581995-07-20 02:43:20 -0500590
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500591#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500592void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600593png_set_gray_to_rgb(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500594{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500595 png_debug(1, "in png_set_gray_to_rgb\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500596 png_ptr->transformations |= PNG_GRAY_TO_RGB;
597}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500598#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500599
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600600#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
601#if defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600602/* Convert a RGB image to a grayscale of the same width. This allows us,
603 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600604 */
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600605
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500606void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500607png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600608 double green)
609{
610 int red_fixed = (int)((float)red*100000.0 + 0.5);
611 int green_fixed = (int)((float)green*100000.0 + 0.5);
612 png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
613}
614#endif
615
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500616void PNGAPI
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600617png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
618 png_fixed_point red, png_fixed_point green)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600619{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500620 png_debug(1, "in png_set_rgb_to_gray\n");
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600621 switch(error_action)
622 {
623 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
624 break;
625 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
626 break;
627 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
628 }
629 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
630#if defined(PNG_READ_EXPAND_SUPPORTED)
631 png_ptr->transformations |= PNG_EXPAND;
632#else
633 {
634 png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
635 png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
636 }
637#endif
638 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600639 png_uint_16 red_int, green_int;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600640 if(red < 0 || green < 0)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600641 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600642 red_int = 6968; /* .212671 * 32768 + .5 */
643 green_int = 23434; /* .715160 * 32768 + .5 */
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600644 }
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600645 else if(red + green < 100000L)
646 {
647 red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
648 green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
649 }
650 else
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600651 {
652 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600653 red_int = 6968;
654 green_int = 23434;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600655 }
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600656 png_ptr->rgb_to_gray_red_coeff = red_int;
657 png_ptr->rgb_to_gray_green_coeff = green_int;
658 png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600659 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600660}
661#endif
662
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500663#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
664 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
665 defined(PNG_LEGACY_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500666void PNGAPI
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600667png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
668 read_user_transform_fn)
669{
670 png_debug(1, "in png_set_read_user_transform_fn\n");
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500671#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600672 png_ptr->transformations |= PNG_USER_TRANSFORM;
673 png_ptr->read_user_transform_fn = read_user_transform_fn;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500674#endif
675#ifdef PNG_LEGACY_SUPPORTED
676 if(read_user_transform_fn)
677 png_warning(png_ptr,
678 "This version of libpng does not support user transforms");
679#endif
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600680}
681#endif
682
Andreas Dilger47a0c421997-05-16 02:46:07 -0500683/* Initialize everything needed for the read. This includes modifying
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600684 * the palette.
685 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500686void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600687png_init_read_transformations(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500688{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500689 png_debug(1, "in png_init_read_transformations\n");
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500690#if defined(PNG_USELESS_TESTS_SUPPORTED)
691 if(png_ptr != NULL)
692#endif
693 {
694#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
695 || defined(PNG_READ_GAMMA_SUPPORTED)
696 int color_type = png_ptr->color_type;
697#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500698
Guy Schalnate5a37791996-06-05 15:50:50 -0500699#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600700 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
701 (png_ptr->transformations & PNG_EXPAND))
Guy Schalnat0d580581995-07-20 02:43:20 -0500702 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500703 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
Guy Schalnat0d580581995-07-20 02:43:20 -0500704 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500705 /* expand background chunk. */
Guy Schalnat0d580581995-07-20 02:43:20 -0500706 switch (png_ptr->bit_depth)
707 {
708 case 1:
Guy Schalnate5a37791996-06-05 15:50:50 -0500709 png_ptr->background.gray *= (png_uint_16)0xff;
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600710 png_ptr->background.red = png_ptr->background.green
711 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500712 break;
713 case 2:
Guy Schalnate5a37791996-06-05 15:50:50 -0500714 png_ptr->background.gray *= (png_uint_16)0x55;
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600715 png_ptr->background.red = png_ptr->background.green
716 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500717 break;
718 case 4:
Guy Schalnate5a37791996-06-05 15:50:50 -0500719 png_ptr->background.gray *= (png_uint_16)0x11;
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600720 png_ptr->background.red = png_ptr->background.green
721 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnate5a37791996-06-05 15:50:50 -0500722 break;
723 case 8:
724 case 16:
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600725 png_ptr->background.red = png_ptr->background.green
726 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500727 break;
728 }
729 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500730 else if (color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -0500731 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500732 png_ptr->background.red =
Guy Schalnat0d580581995-07-20 02:43:20 -0500733 png_ptr->palette[png_ptr->background.index].red;
734 png_ptr->background.green =
735 png_ptr->palette[png_ptr->background.index].green;
Guy Schalnate5a37791996-06-05 15:50:50 -0500736 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -0500737 png_ptr->palette[png_ptr->background.index].blue;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600738
739#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
740 if (png_ptr->transformations & PNG_INVERT_ALPHA)
741 {
742#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600743 if (!(png_ptr->transformations & PNG_EXPAND))
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600744#endif
745 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600746 /* invert the alpha channel (in tRNS) unless the pixels are
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600747 going to be expanded, in which case leave it for later */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500748 int i,istop;
749 istop=(int)png_ptr->num_trans;
750 for (i=0; i<istop; i++)
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -0500751 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600752 }
753 }
754#endif
755
Guy Schalnat0d580581995-07-20 02:43:20 -0500756 }
757 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500758#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500759
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -0500760#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500761 png_ptr->background_1 = png_ptr->background;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500762#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600763#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -0600764
765 if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
766 && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
767 < PNG_GAMMA_THRESHOLD))
768 {
769 int i,k;
770 k=0;
771 for (i=0; i<png_ptr->num_trans; i++)
772 {
773 if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
774 k=1; /* partial transparency is present */
775 }
776 if (k == 0)
777 png_ptr->transformations &= (~PNG_GAMMA);
778 }
779
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600780 if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -0500781 {
782 png_build_gamma_table(png_ptr);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500783#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnate5a37791996-06-05 15:50:50 -0500784 if (png_ptr->transformations & PNG_BACKGROUND)
Guy Schalnat0d580581995-07-20 02:43:20 -0500785 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500786 if (color_type == PNG_COLOR_TYPE_PALETTE)
787 {
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -0600788 /* could skip if no transparency and
789 */
Guy Schalnate5a37791996-06-05 15:50:50 -0500790 png_color back, back_1;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500791 png_colorp palette = png_ptr->palette;
792 int num_palette = png_ptr->num_palette;
793 int i;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500794 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
795 {
796 back.red = png_ptr->gamma_table[png_ptr->background.red];
797 back.green = png_ptr->gamma_table[png_ptr->background.green];
798 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
Guy Schalnate5a37791996-06-05 15:50:50 -0500799
Andreas Dilger47a0c421997-05-16 02:46:07 -0500800 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
801 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
802 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
803 }
804 else
805 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600806 double g, gs;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500807
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600808 switch (png_ptr->background_gamma_type)
Glenn Randers-Pehrson4922b1b1998-03-08 22:55:17 -0600809 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600810 case PNG_BACKGROUND_GAMMA_SCREEN:
811 g = (png_ptr->screen_gamma);
812 gs = 1.0;
813 break;
814 case PNG_BACKGROUND_GAMMA_FILE:
815 g = 1.0 / (png_ptr->gamma);
816 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
817 break;
818 case PNG_BACKGROUND_GAMMA_UNIQUE:
819 g = 1.0 / (png_ptr->background_gamma);
820 gs = 1.0 / (png_ptr->background_gamma *
821 png_ptr->screen_gamma);
822 break;
823 default:
824 g = 1.0; /* back_1 */
825 gs = 1.0; /* back */
826 }
827
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -0600828 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600829 {
830 back.red = (png_byte)png_ptr->background.red;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500831 back.green = (png_byte)png_ptr->background.green;
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600832 back.blue = (png_byte)png_ptr->background.blue;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500833 }
834 else
835 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600836 back.red = (png_byte)(pow(
837 (double)png_ptr->background.red/255, gs) * 255.0 + .5);
838 back.green = (png_byte)(pow(
839 (double)png_ptr->background.green/255, gs) * 255.0 + .5);
840 back.blue = (png_byte)(pow(
841 (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500842 }
843
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600844 back_1.red = (png_byte)(pow(
845 (double)png_ptr->background.red/255, g) * 255.0 + .5);
846 back_1.green = (png_byte)(pow(
847 (double)png_ptr->background.green/255, g) * 255.0 + .5);
848 back_1.blue = (png_byte)(pow(
849 (double)png_ptr->background.blue/255, g) * 255.0 + .5);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500850 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500851 for (i = 0; i < num_palette; i++)
852 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500853 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
Guy Schalnate5a37791996-06-05 15:50:50 -0500854 {
855 if (png_ptr->trans[i] == 0)
856 {
857 palette[i] = back;
858 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500859 else /* if (png_ptr->trans[i] != 0xff) */
Guy Schalnate5a37791996-06-05 15:50:50 -0500860 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500861 png_byte v, w;
Guy Schalnate5a37791996-06-05 15:50:50 -0500862
863 v = png_ptr->gamma_to_1[palette[i].red];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500864 png_composite(w, v, png_ptr->trans[i], back_1.red);
Guy Schalnate5a37791996-06-05 15:50:50 -0500865 palette[i].red = png_ptr->gamma_from_1[w];
866
867 v = png_ptr->gamma_to_1[palette[i].green];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500868 png_composite(w, v, png_ptr->trans[i], back_1.green);
Guy Schalnate5a37791996-06-05 15:50:50 -0500869 palette[i].green = png_ptr->gamma_from_1[w];
870
871 v = png_ptr->gamma_to_1[palette[i].blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500872 png_composite(w, v, png_ptr->trans[i], back_1.blue);
Guy Schalnate5a37791996-06-05 15:50:50 -0500873 palette[i].blue = png_ptr->gamma_from_1[w];
874 }
875 }
876 else
877 {
878 palette[i].red = png_ptr->gamma_table[palette[i].red];
879 palette[i].green = png_ptr->gamma_table[palette[i].green];
880 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
881 }
882 }
883 }
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500884 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600885 else
886 /* color_type != PNG_COLOR_TYPE_PALETTE */
Guy Schalnat0d580581995-07-20 02:43:20 -0500887 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500888 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
889 double g = 1.0;
890 double gs = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500891
892 switch (png_ptr->background_gamma_type)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600893 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500894 case PNG_BACKGROUND_GAMMA_SCREEN:
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600895 g = (png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500896 gs = 1.0;
897 break;
898 case PNG_BACKGROUND_GAMMA_FILE:
899 g = 1.0 / (png_ptr->gamma);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600900 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500901 break;
902 case PNG_BACKGROUND_GAMMA_UNIQUE:
903 g = 1.0 / (png_ptr->background_gamma);
904 gs = 1.0 / (png_ptr->background_gamma *
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600905 png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500906 break;
907 }
908
Glenn Randers-Pehrson377657d2002-03-08 01:31:27 -0600909 png_ptr->background_1.gray = (png_uint_16)(pow(
910 (double)png_ptr->background.gray / m, g) * m + .5);
911 png_ptr->background.gray = (png_uint_16)(pow(
912 (double)png_ptr->background.gray / m, gs) * m + .5);
913
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600914 if ((png_ptr->background.red != png_ptr->background.green) ||
915 (png_ptr->background.red != png_ptr->background.blue) ||
916 (png_ptr->background.red != png_ptr->background.gray))
Guy Schalnat0d580581995-07-20 02:43:20 -0500917 {
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600918 /* RGB or RGBA with color background */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600919 png_ptr->background_1.red = (png_uint_16)(pow(
Guy Schalnat0d580581995-07-20 02:43:20 -0500920 (double)png_ptr->background.red / m, g) * m + .5);
921 png_ptr->background_1.green = (png_uint_16)(pow(
922 (double)png_ptr->background.green / m, g) * m + .5);
923 png_ptr->background_1.blue = (png_uint_16)(pow(
924 (double)png_ptr->background.blue / m, g) * m + .5);
925 png_ptr->background.red = (png_uint_16)(pow(
926 (double)png_ptr->background.red / m, gs) * m + .5);
927 png_ptr->background.green = (png_uint_16)(pow(
928 (double)png_ptr->background.green / m, gs) * m + .5);
929 png_ptr->background.blue = (png_uint_16)(pow(
930 (double)png_ptr->background.blue / m, gs) * m + .5);
931 }
932 else
933 {
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600934 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
935 png_ptr->background_1.red = png_ptr->background_1.green
936 = png_ptr->background_1.blue = png_ptr->background_1.gray;
937 png_ptr->background.red = png_ptr->background.green
938 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500939 }
940 }
941 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500942 else
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600943 /* transformation does not include PNG_BACKGROUND */
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -0500944#endif /* PNG_READ_BACKGROUND_SUPPORTED */
Guy Schalnate5a37791996-06-05 15:50:50 -0500945 if (color_type == PNG_COLOR_TYPE_PALETTE)
946 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500947 png_colorp palette = png_ptr->palette;
948 int num_palette = png_ptr->num_palette;
949 int i;
Guy Schalnate5a37791996-06-05 15:50:50 -0500950
951 for (i = 0; i < num_palette; i++)
952 {
953 palette[i].red = png_ptr->gamma_table[palette[i].red];
954 palette[i].green = png_ptr->gamma_table[palette[i].green];
955 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
956 }
957 }
958 }
959#if defined(PNG_READ_BACKGROUND_SUPPORTED)
960 else
961#endif
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -0500962#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
Guy Schalnate5a37791996-06-05 15:50:50 -0500963#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600964 /* No GAMMA transformation */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600965 if ((png_ptr->transformations & PNG_BACKGROUND) &&
966 (color_type == PNG_COLOR_TYPE_PALETTE))
Guy Schalnate5a37791996-06-05 15:50:50 -0500967 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500968 int i;
969 int istop = (int)png_ptr->num_trans;
Guy Schalnate5a37791996-06-05 15:50:50 -0500970 png_color back;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500971 png_colorp palette = png_ptr->palette;
Guy Schalnate5a37791996-06-05 15:50:50 -0500972
Guy Schalnate5a37791996-06-05 15:50:50 -0500973 back.red = (png_byte)png_ptr->background.red;
974 back.green = (png_byte)png_ptr->background.green;
975 back.blue = (png_byte)png_ptr->background.blue;
976
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500977 for (i = 0; i < istop; i++)
Guy Schalnate5a37791996-06-05 15:50:50 -0500978 {
979 if (png_ptr->trans[i] == 0)
980 {
981 palette[i] = back;
982 }
983 else if (png_ptr->trans[i] != 0xff)
984 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500985 /* The png_composite() macro is defined in png.h */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500986 png_composite(palette[i].red, palette[i].red,
987 png_ptr->trans[i], back.red);
988 png_composite(palette[i].green, palette[i].green,
989 png_ptr->trans[i], back.green);
990 png_composite(palette[i].blue, palette[i].blue,
991 png_ptr->trans[i], back.blue);
Guy Schalnate5a37791996-06-05 15:50:50 -0500992 }
993 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500994 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -0500995#endif /* PNG_READ_BACKGROUND_SUPPORTED */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500996
Guy Schalnat6d764711995-12-19 03:22:19 -0600997#if defined(PNG_READ_SHIFT_SUPPORTED)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500998 if ((png_ptr->transformations & PNG_SHIFT) &&
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600999 (color_type == PNG_COLOR_TYPE_PALETTE))
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001000 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001001 png_uint_16 i;
1002 png_uint_16 istop = png_ptr->num_palette;
1003 int sr = 8 - png_ptr->sig_bit.red;
1004 int sg = 8 - png_ptr->sig_bit.green;
1005 int sb = 8 - png_ptr->sig_bit.blue;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001006
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001007 if (sr < 0 || sr > 8)
1008 sr = 0;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001009 if (sg < 0 || sg > 8)
1010 sg = 0;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001011 if (sb < 0 || sb > 8)
1012 sb = 0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001013 for (i = 0; i < istop; i++)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001014 {
1015 png_ptr->palette[i].red >>= sr;
1016 png_ptr->palette[i].green >>= sg;
1017 png_ptr->palette[i].blue >>= sb;
1018 }
1019 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05001020#endif /* PNG_READ_SHIFT_SUPPORTED */
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001021 }
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001022#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1023 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1024 if(png_ptr)
1025 return;
1026#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001027}
1028
Andreas Dilger47a0c421997-05-16 02:46:07 -05001029/* Modify the info structure to reflect the transformations. The
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001030 * info should be updated so a PNG file could be written with it,
1031 * assuming the transformations result in valid PNG data.
1032 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001033void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001034png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001035{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001036 png_debug(1, "in png_read_transform_info\n");
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001037#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001038 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001039 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001040 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1041 {
1042 if (png_ptr->num_trans)
1043 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1044 else
1045 info_ptr->color_type = PNG_COLOR_TYPE_RGB;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001046 info_ptr->bit_depth = 8;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001047 info_ptr->num_trans = 0;
1048 }
1049 else
1050 {
1051 if (png_ptr->num_trans)
1052 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1053 if (info_ptr->bit_depth < 8)
1054 info_ptr->bit_depth = 8;
1055 info_ptr->num_trans = 0;
1056 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001057 }
1058#endif
1059
1060#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1061 if (png_ptr->transformations & PNG_BACKGROUND)
1062 {
1063 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1064 info_ptr->num_trans = 0;
1065 info_ptr->background = png_ptr->background;
1066 }
1067#endif
1068
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001069#if defined(PNG_READ_GAMMA_SUPPORTED)
1070 if (png_ptr->transformations & PNG_GAMMA)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001071 {
1072#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001073 info_ptr->gamma = png_ptr->gamma;
1074#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001075#ifdef PNG_FIXED_POINT_SUPPORTED
1076 info_ptr->int_gamma = png_ptr->int_gamma;
1077#endif
1078 }
1079#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001080
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001081#if defined(PNG_READ_16_TO_8_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001082 if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001083 info_ptr->bit_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001084#endif
1085
1086#if defined(PNG_READ_DITHER_SUPPORTED)
1087 if (png_ptr->transformations & PNG_DITHER)
1088 {
1089 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1090 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1091 png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1092 {
1093 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1094 }
1095 }
1096#endif
1097
1098#if defined(PNG_READ_PACK_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001099 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001100 info_ptr->bit_depth = 8;
1101#endif
1102
1103#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001104 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001105 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1106#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001107
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001108#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1109 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1110 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1111#endif
1112
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001113 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001114 info_ptr->channels = 1;
1115 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1116 info_ptr->channels = 3;
1117 else
1118 info_ptr->channels = 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001119
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001120#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001121 if (png_ptr->transformations & PNG_STRIP_ALPHA)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001122 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001123#endif
1124
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001125 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1126 info_ptr->channels++;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001127
1128#if defined(PNG_READ_FILLER_SUPPORTED)
1129 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001130 if ((png_ptr->transformations & PNG_FILLER) &&
1131 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1132 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001133 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001134 info_ptr->channels++;
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001135#if 0 /* if adding a true alpha channel not just filler */
1136 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1137#endif
1138 }
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001139#endif
1140
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001141#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1142defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001143 if(png_ptr->transformations & PNG_USER_TRANSFORM)
1144 {
1145 if(info_ptr->bit_depth < png_ptr->user_transform_depth)
1146 info_ptr->bit_depth = png_ptr->user_transform_depth;
1147 if(info_ptr->channels < png_ptr->user_transform_channels)
1148 info_ptr->channels = png_ptr->user_transform_channels;
1149 }
1150#endif
1151
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001152 info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1153 info_ptr->bit_depth);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001154
1155 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width);
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05001156
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001157#if !defined(PNG_READ_EXPAND_SUPPORTED)
1158 if(png_ptr)
1159 return;
1160#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001161}
1162
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001163/* Transform the row. The order of transformations is significant,
1164 * and is very touchy. If you add a transformation, take care to
1165 * decide how it fits in with the other transformations here.
1166 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001167void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001168png_do_read_transformations(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05001169{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001170 png_debug(1, "in png_do_read_transformations\n");
1171#if !defined(PNG_USELESS_TESTS_SUPPORTED)
1172 if (png_ptr->row_buf == NULL)
1173 {
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -05001174#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001175 char msg[50];
1176
1177 sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
1178 png_ptr->pass);
1179 png_error(png_ptr, msg);
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001180#else
1181 png_error(png_ptr, "NULL row buffer");
1182#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001183 }
1184#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001185
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001186#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001187 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05001188 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001189 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1190 {
1191 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1192 png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1193 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001194 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001195 {
1196 if (png_ptr->num_trans)
1197 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1198 &(png_ptr->trans_values));
1199 else
1200 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1201 NULL);
1202 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001203 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001204#endif
1205
1206#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1207 if (png_ptr->transformations & PNG_STRIP_ALPHA)
1208 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1209 PNG_FLAG_FILLER_AFTER);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001210#endif
1211
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001212#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1213 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1214 {
1215 int rgb_error =
1216 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1217 if(rgb_error)
1218 {
1219 png_ptr->rgb_to_gray_status=1;
1220 if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
1221 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1222 if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
1223 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1224 }
1225 }
1226#endif
1227
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001228/*
1229From Andreas Dilger e-mail to png-implement, 26 March 1998:
1230
1231 In most cases, the "simple transparency" should be done prior to doing
1232 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 -06001233 pixel is transparent. You would also need to make sure that the
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001234 transparency information is upgraded to RGB.
1235
1236 To summarize, the current flow is:
1237 - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1238 with background "in place" if transparent,
1239 convert to RGB if necessary
1240 - Gray + alpha -> composite with gray background and remove alpha bytes,
1241 convert to RGB if necessary
1242
1243 To support RGB backgrounds for gray images we need:
1244 - Gray + simple transparency -> convert to RGB + simple transparency, compare
1245 3 or 6 bytes and composite with background
1246 "in place" if transparent (3x compare/pixel
1247 compared to doing composite with gray bkgrnd)
1248 - Gray + alpha -> convert to RGB + alpha, composite with background and
1249 remove alpha bytes (3x float operations/pixel
1250 compared with composite on gray background)
1251
1252 Greg's change will do this. The reason it wasn't done before is for
1253 performance, as this increases the per-pixel operations. If we would check
1254 in advance if the background was gray or RGB, and position the gray-to-RGB
1255 transform appropriately, then it would save a lot of work/time.
1256 */
1257
1258#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1259 /* if gray -> RGB, do so now only if background is non-gray; else do later
1260 * for performance reasons */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001261 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06001262 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001263 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1264#endif
1265
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001266#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001267 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1268 ((png_ptr->num_trans != 0 ) ||
1269 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
Guy Schalnat0d580581995-07-20 02:43:20 -05001270 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05001271 &(png_ptr->trans_values), &(png_ptr->background)
1272#if defined(PNG_READ_GAMMA_SUPPORTED)
1273 , &(png_ptr->background_1),
Guy Schalnat0d580581995-07-20 02:43:20 -05001274 png_ptr->gamma_table, png_ptr->gamma_from_1,
1275 png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1276 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05001277 png_ptr->gamma_shift
1278#endif
1279);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001280#endif
1281
1282#if defined(PNG_READ_GAMMA_SUPPORTED)
1283 if ((png_ptr->transformations & PNG_GAMMA) &&
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001284#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1285 !((png_ptr->transformations & PNG_BACKGROUND) &&
1286 ((png_ptr->num_trans != 0) ||
1287 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1288#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001289 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
Guy Schalnat0d580581995-07-20 02:43:20 -05001290 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1291 png_ptr->gamma_table, png_ptr->gamma_16_table,
1292 png_ptr->gamma_shift);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001293#endif
1294
1295#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001296 if (png_ptr->transformations & PNG_16_TO_8)
1297 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001298#endif
1299
1300#if defined(PNG_READ_DITHER_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001301 if (png_ptr->transformations & PNG_DITHER)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001302 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001303 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1304 png_ptr->palette_lookup, png_ptr->dither_index);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001305 if(png_ptr->row_info.rowbytes == (png_uint_32)0)
1306 png_error(png_ptr, "png_do_dither returned rowbytes=0");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001307 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001308#endif
1309
1310#if defined(PNG_READ_INVERT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001311 if (png_ptr->transformations & PNG_INVERT_MONO)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001312 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001313#endif
1314
1315#if defined(PNG_READ_SHIFT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001316 if (png_ptr->transformations & PNG_SHIFT)
1317 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1318 &(png_ptr->shift));
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001319#endif
1320
1321#if defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001322 if (png_ptr->transformations & PNG_PACK)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001323 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001324#endif
1325
1326#if defined(PNG_READ_BGR_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001327 if (png_ptr->transformations & PNG_BGR)
1328 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001329#endif
1330
Andreas Dilger47a0c421997-05-16 02:46:07 -05001331#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1332 if (png_ptr->transformations & PNG_PACKSWAP)
1333 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1334#endif
1335
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001336#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001337 /* if gray -> RGB, do so now only if we did not do so above */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001338 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1339 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -05001340 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001341#endif
1342
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001343#if defined(PNG_READ_FILLER_SUPPORTED)
1344 if (png_ptr->transformations & PNG_FILLER)
1345 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001346 (png_uint_32)png_ptr->filler, png_ptr->flags);
1347#endif
1348
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001349#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1350 if (png_ptr->transformations & PNG_INVERT_ALPHA)
1351 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1352#endif
1353
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001354#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1355 if (png_ptr->transformations & PNG_SWAP_ALPHA)
1356 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1357#endif
1358
Andreas Dilger47a0c421997-05-16 02:46:07 -05001359#if defined(PNG_READ_SWAP_SUPPORTED)
1360 if (png_ptr->transformations & PNG_SWAP_BYTES)
1361 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001362#endif
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001363
1364#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1365 if (png_ptr->transformations & PNG_USER_TRANSFORM)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001366 {
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001367 if(png_ptr->read_user_transform_fn != NULL)
1368 (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1369 (png_ptr, /* png_ptr */
1370 &(png_ptr->row_info), /* row_info: */
1371 /* png_uint_32 width; width of row */
1372 /* png_uint_32 rowbytes; number of bytes in row */
1373 /* png_byte color_type; color type of pixels */
1374 /* png_byte bit_depth; bit depth of samples */
1375 /* png_byte channels; number of channels (1-4) */
1376 /* png_byte pixel_depth; bits per pixel (depth*channels) */
1377 png_ptr->row_buf + 1); /* start of pixel data for row */
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001378#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001379 if(png_ptr->user_transform_depth)
1380 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1381 if(png_ptr->user_transform_channels)
1382 png_ptr->row_info.channels = png_ptr->user_transform_channels;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001383#endif
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001384 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1385 png_ptr->row_info.channels);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001386 png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
1387 png_ptr->row_info.width);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001388 }
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001389#endif
1390
Guy Schalnat0d580581995-07-20 02:43:20 -05001391}
1392
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001393#if defined(PNG_READ_PACK_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001394/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1395 * without changing the actual values. Thus, if you had a row with
1396 * a bit depth of 1, you would end up with bytes that only contained
1397 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1398 * png_do_shift() after this.
1399 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001400void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001401png_do_unpack(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001402{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001403 png_debug(1, "in png_do_unpack\n");
1404#if defined(PNG_USELESS_TESTS_SUPPORTED)
1405 if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1406#else
1407 if (row_info->bit_depth < 8)
1408#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001409 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001410 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001411 png_uint_32 row_width=row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001412
Guy Schalnat0d580581995-07-20 02:43:20 -05001413 switch (row_info->bit_depth)
1414 {
1415 case 1:
1416 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001417 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1418 png_bytep dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001419 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001420 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001421 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001422 *dp = (png_byte)((*sp >> shift) & 0x01);
Guy Schalnat0d580581995-07-20 02:43:20 -05001423 if (shift == 7)
1424 {
1425 shift = 0;
1426 sp--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001427 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001428 else
1429 shift++;
1430
1431 dp--;
1432 }
1433 break;
1434 }
1435 case 2:
1436 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001437
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001438 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1439 png_bytep dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001440 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001441 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001442 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001443 *dp = (png_byte)((*sp >> shift) & 0x03);
Guy Schalnat0d580581995-07-20 02:43:20 -05001444 if (shift == 6)
1445 {
1446 shift = 0;
1447 sp--;
1448 }
1449 else
1450 shift += 2;
1451
1452 dp--;
1453 }
1454 break;
1455 }
1456 case 4:
1457 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001458 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1459 png_bytep dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001460 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001461 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001462 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001463 *dp = (png_byte)((*sp >> shift) & 0x0f);
Guy Schalnat0d580581995-07-20 02:43:20 -05001464 if (shift == 4)
1465 {
1466 shift = 0;
1467 sp--;
1468 }
1469 else
1470 shift = 4;
1471
1472 dp--;
1473 }
1474 break;
1475 }
1476 }
1477 row_info->bit_depth = 8;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001478 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001479 row_info->rowbytes = row_width * row_info->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -05001480 }
1481}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001482#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001483
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001484#if defined(PNG_READ_SHIFT_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001485/* Reverse the effects of png_do_shift. This routine merely shifts the
1486 * pixels back to their significant bits values. Thus, if you have
1487 * a row of bit depth 8, but only 5 are significant, this will shift
1488 * the values back to 0 through 31.
1489 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001490void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001491png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
Guy Schalnat0d580581995-07-20 02:43:20 -05001492{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001493 png_debug(1, "in png_do_unshift\n");
1494 if (
1495#if defined(PNG_USELESS_TESTS_SUPPORTED)
1496 row != NULL && row_info != NULL && sig_bits != NULL &&
1497#endif
1498 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05001499 {
1500 int shift[4];
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001501 int channels = 0;
1502 int c;
1503 png_uint_16 value = 0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001504 png_uint_32 row_width = row_info->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001505
Guy Schalnat0d580581995-07-20 02:43:20 -05001506 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1507 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001508 shift[channels++] = row_info->bit_depth - sig_bits->red;
1509 shift[channels++] = row_info->bit_depth - sig_bits->green;
1510 shift[channels++] = row_info->bit_depth - sig_bits->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05001511 }
1512 else
1513 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001514 shift[channels++] = row_info->bit_depth - sig_bits->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05001515 }
1516 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1517 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001518 shift[channels++] = row_info->bit_depth - sig_bits->alpha;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001519 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001520
Andreas Dilger47a0c421997-05-16 02:46:07 -05001521 for (c = 0; c < channels; c++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001522 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001523 if (shift[c] <= 0)
1524 shift[c] = 0;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001525 else
1526 value = 1;
1527 }
Guy Schalnat0f716451995-11-28 11:22:13 -06001528
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001529 if (!value)
1530 return;
Guy Schalnat0f716451995-11-28 11:22:13 -06001531
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001532 switch (row_info->bit_depth)
Guy Schalnat0d580581995-07-20 02:43:20 -05001533 {
1534 case 2:
1535 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001536 png_bytep bp;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001537 png_uint_32 i;
1538 png_uint_32 istop = row_info->rowbytes;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001539
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001540 for (bp = row, i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001541 {
1542 *bp >>= 1;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001543 *bp++ &= 0x55;
Guy Schalnat0d580581995-07-20 02:43:20 -05001544 }
1545 break;
1546 }
1547 case 4:
1548 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001549 png_bytep bp = row;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001550 png_uint_32 i;
1551 png_uint_32 istop = row_info->rowbytes;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001552 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1553 (png_byte)((int)0xf >> shift[0]));
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001554
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001555 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001556 {
1557 *bp >>= shift[0];
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001558 *bp++ &= mask;
Guy Schalnat0d580581995-07-20 02:43:20 -05001559 }
1560 break;
1561 }
1562 case 8:
1563 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001564 png_bytep bp = row;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001565 png_uint_32 i;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001566 png_uint_32 istop = row_width * channels;
Guy Schalnat0d580581995-07-20 02:43:20 -05001567
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001568 for (i = 0; i < istop; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001569 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001570 *bp++ >>= shift[i%channels];
Guy Schalnat0d580581995-07-20 02:43:20 -05001571 }
1572 break;
1573 }
1574 case 16:
1575 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001576 png_bytep bp = row;
1577 png_uint_32 i;
1578 png_uint_32 istop = channels * row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001579
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001580 for (i = 0; i < istop; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001581 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001582 value = (png_uint_16)((*bp << 8) + *(bp + 1));
1583 value >>= shift[i%channels];
1584 *bp++ = (png_byte)(value >> 8);
1585 *bp++ = (png_byte)(value & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05001586 }
1587 break;
1588 }
1589 }
1590 }
1591}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001592#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001593
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001594#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001595/* chop rows of bit depth 16 down to 8 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001596void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001597png_do_chop(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001598{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001599 png_debug(1, "in png_do_chop\n");
1600#if defined(PNG_USELESS_TESTS_SUPPORTED)
1601 if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1602#else
1603 if (row_info->bit_depth == 16)
1604#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001605 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001606 png_bytep sp = row;
1607 png_bytep dp = row;
1608 png_uint_32 i;
1609 png_uint_32 istop = row_info->width * row_info->channels;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001610
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001611 for (i = 0; i<istop; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001612 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001613#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001614 /* This does a more accurate scaling of the 16-bit color
1615 * value, rather than a simple low-byte truncation.
1616 *
1617 * What the ideal calculation should be:
1618 * *dp = (((((png_uint_32)(*sp) << 8) |
1619 * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1620 *
1621 * GRR: no, I think this is what it really should be:
1622 * *dp = (((((png_uint_32)(*sp) << 8) |
1623 * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1624 *
1625 * GRR: here's the exact calculation with shifts:
1626 * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1627 * *dp = (temp - (temp >> 8)) >> 8;
1628 *
1629 * Approximate calculation with shift/add instead of multiply/divide:
1630 * *dp = ((((png_uint_32)(*sp) << 8) |
1631 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1632 *
1633 * What we actually do to avoid extra shifting and conversion:
1634 */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001635
Andreas Dilger47a0c421997-05-16 02:46:07 -05001636 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1637#else
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001638 /* Simply discard the low order byte */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001639 *dp = *sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001640#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001641 }
1642 row_info->bit_depth = 8;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001643 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001644 row_info->rowbytes = row_info->width * row_info->channels;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001645 }
1646}
1647#endif
1648
1649#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001650void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001651png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1652{
1653 png_debug(1, "in png_do_read_swap_alpha\n");
1654#if defined(PNG_USELESS_TESTS_SUPPORTED)
1655 if (row != NULL && row_info != NULL)
1656#endif
1657 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001658 png_uint_32 row_width = row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001659 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1660 {
1661 /* This converts from RGBA to ARGB */
1662 if (row_info->bit_depth == 8)
1663 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001664 png_bytep sp = row + row_info->rowbytes;
1665 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001666 png_byte save;
1667 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001668
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001669 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001670 {
1671 save = *(--sp);
1672 *(--dp) = *(--sp);
1673 *(--dp) = *(--sp);
1674 *(--dp) = *(--sp);
1675 *(--dp) = save;
1676 }
1677 }
1678 /* This converts from RRGGBBAA to AARRGGBB */
1679 else
1680 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001681 png_bytep sp = row + row_info->rowbytes;
1682 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001683 png_byte save[2];
1684 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001685
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001686 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001687 {
1688 save[0] = *(--sp);
1689 save[1] = *(--sp);
1690 *(--dp) = *(--sp);
1691 *(--dp) = *(--sp);
1692 *(--dp) = *(--sp);
1693 *(--dp) = *(--sp);
1694 *(--dp) = *(--sp);
1695 *(--dp) = *(--sp);
1696 *(--dp) = save[0];
1697 *(--dp) = save[1];
1698 }
1699 }
1700 }
1701 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1702 {
1703 /* This converts from GA to AG */
1704 if (row_info->bit_depth == 8)
1705 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001706 png_bytep sp = row + row_info->rowbytes;
1707 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001708 png_byte save;
1709 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001710
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001711 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001712 {
1713 save = *(--sp);
1714 *(--dp) = *(--sp);
1715 *(--dp) = save;
1716 }
1717 }
1718 /* This converts from GGAA to AAGG */
1719 else
1720 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001721 png_bytep sp = row + row_info->rowbytes;
1722 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001723 png_byte save[2];
1724 png_uint_32 i;
1725
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001726 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001727 {
1728 save[0] = *(--sp);
1729 save[1] = *(--sp);
1730 *(--dp) = *(--sp);
1731 *(--dp) = *(--sp);
1732 *(--dp) = save[0];
1733 *(--dp) = save[1];
1734 }
1735 }
1736 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001737 }
1738}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001739#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001740
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001741#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001742void /* PRIVATE */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001743png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1744{
1745 png_debug(1, "in png_do_read_invert_alpha\n");
1746#if defined(PNG_USELESS_TESTS_SUPPORTED)
1747 if (row != NULL && row_info != NULL)
1748#endif
1749 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001750 png_uint_32 row_width = row_info->width;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001751 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1752 {
1753 /* This inverts the alpha channel in RGBA */
1754 if (row_info->bit_depth == 8)
1755 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001756 png_bytep sp = row + row_info->rowbytes;
1757 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001758 png_uint_32 i;
1759
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001760 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001761 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001762 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001763
1764/* This does nothing:
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001765 *(--dp) = *(--sp);
1766 *(--dp) = *(--sp);
1767 *(--dp) = *(--sp);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001768 We can replace it with:
1769*/
1770 sp-=3;
1771 dp=sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001772 }
1773 }
1774 /* This inverts the alpha channel in RRGGBBAA */
1775 else
1776 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001777 png_bytep sp = row + row_info->rowbytes;
1778 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001779 png_uint_32 i;
1780
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001781 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001782 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001783 *(--dp) = (png_byte)(255 - *(--sp));
1784 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001785
1786/* This does nothing:
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001787 *(--dp) = *(--sp);
1788 *(--dp) = *(--sp);
1789 *(--dp) = *(--sp);
1790 *(--dp) = *(--sp);
1791 *(--dp) = *(--sp);
1792 *(--dp) = *(--sp);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001793 We can replace it with:
1794*/
1795 sp-=6;
1796 dp=sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001797 }
1798 }
1799 }
1800 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1801 {
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001802 /* This inverts the alpha channel in GA */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001803 if (row_info->bit_depth == 8)
1804 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001805 png_bytep sp = row + row_info->rowbytes;
1806 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001807 png_uint_32 i;
1808
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001809 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001810 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001811 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001812 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001813 }
1814 }
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001815 /* This inverts the alpha channel in GGAA */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001816 else
1817 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001818 png_bytep sp = row + row_info->rowbytes;
1819 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001820 png_uint_32 i;
1821
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001822 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001823 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001824 *(--dp) = (png_byte)(255 - *(--sp));
1825 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001826/*
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001827 *(--dp) = *(--sp);
1828 *(--dp) = *(--sp);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001829*/
1830 sp-=2;
1831 dp=sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001832 }
1833 }
1834 }
1835 }
1836}
1837#endif
1838
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001839#if defined(PNG_READ_FILLER_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001840/* Add filler channel if we have RGB color */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001841void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001842png_do_read_filler(png_row_infop row_info, png_bytep row,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001843 png_uint_32 filler, png_uint_32 flags)
Guy Schalnat0d580581995-07-20 02:43:20 -05001844{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001845 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001846 png_uint_32 row_width = row_info->width;
1847
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001848 png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001849 png_byte lo_filler = (png_byte)(filler & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001850
1851 png_debug(1, "in png_do_read_filler\n");
1852 if (
1853#if defined(PNG_USELESS_TESTS_SUPPORTED)
1854 row != NULL && row_info != NULL &&
1855#endif
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001856 row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05001857 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001858 if(row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05001859 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001860 /* This changes the data from G to GX */
1861 if (flags & PNG_FLAG_FILLER_AFTER)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001862 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001863 png_bytep sp = row + (png_size_t)row_width;
1864 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001865 for (i = 1; i < row_width; i++)
1866 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001867 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001868 *(--dp) = *(--sp);
1869 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001870 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001871 row_info->channels = 2;
1872 row_info->pixel_depth = 16;
1873 row_info->rowbytes = row_width * 2;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001874 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001875 /* This changes the data from G to XG */
1876 else
1877 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001878 png_bytep sp = row + (png_size_t)row_width;
1879 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001880 for (i = 0; i < row_width; i++)
1881 {
1882 *(--dp) = *(--sp);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001883 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001884 }
1885 row_info->channels = 2;
1886 row_info->pixel_depth = 16;
1887 row_info->rowbytes = row_width * 2;
1888 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001889 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001890 else if(row_info->bit_depth == 16)
1891 {
1892 /* This changes the data from GG to GGXX */
1893 if (flags & PNG_FLAG_FILLER_AFTER)
1894 {
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05001895 png_bytep sp = row + (png_size_t)row_width * 2;
1896 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001897 for (i = 1; i < row_width; i++)
1898 {
1899 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001900 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001901 *(--dp) = *(--sp);
1902 *(--dp) = *(--sp);
1903 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001904 *(--dp) = hi_filler;
1905 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001906 row_info->channels = 2;
1907 row_info->pixel_depth = 32;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001908 row_info->rowbytes = row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001909 }
1910 /* This changes the data from GG to XXGG */
1911 else
1912 {
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05001913 png_bytep sp = row + (png_size_t)row_width * 2;
1914 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001915 for (i = 0; i < row_width; i++)
1916 {
1917 *(--dp) = *(--sp);
1918 *(--dp) = *(--sp);
1919 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001920 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001921 }
1922 row_info->channels = 2;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001923 row_info->pixel_depth = 32;
1924 row_info->rowbytes = row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001925 }
1926 }
Glenn Randers-Pehrsondff799e2004-08-07 21:42:49 -05001927 row_info->color_type |= PNG_COLOR_MASK_ALPHA;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001928 } /* COLOR_TYPE == GRAY */
1929 else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
1930 {
1931 if(row_info->bit_depth == 8)
1932 {
1933 /* This changes the data from RGB to RGBX */
1934 if (flags & PNG_FLAG_FILLER_AFTER)
1935 {
Glenn Randers-Pehrsondff799e2004-08-07 21:42:49 -05001936 png_bytep sp = row + (png_size_t)row_width * 3;
1937 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001938 for (i = 1; i < row_width; i++)
1939 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001940 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001941 *(--dp) = *(--sp);
1942 *(--dp) = *(--sp);
1943 *(--dp) = *(--sp);
1944 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001945 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001946 row_info->channels = 4;
1947 row_info->pixel_depth = 32;
1948 row_info->rowbytes = row_width * 4;
1949 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001950 /* This changes the data from RGB to XRGB */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001951 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001952 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001953 png_bytep sp = row + (png_size_t)row_width * 3;
1954 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001955 for (i = 0; i < row_width; i++)
1956 {
1957 *(--dp) = *(--sp);
1958 *(--dp) = *(--sp);
1959 *(--dp) = *(--sp);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001960 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001961 }
1962 row_info->channels = 4;
1963 row_info->pixel_depth = 32;
1964 row_info->rowbytes = row_width * 4;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001965 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001966 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001967 else if(row_info->bit_depth == 16)
1968 {
1969 /* This changes the data from RRGGBB to RRGGBBXX */
1970 if (flags & PNG_FLAG_FILLER_AFTER)
1971 {
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05001972 png_bytep sp = row + (png_size_t)row_width * 6;
1973 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001974 for (i = 1; i < row_width; i++)
1975 {
1976 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001977 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001978 *(--dp) = *(--sp);
1979 *(--dp) = *(--sp);
1980 *(--dp) = *(--sp);
1981 *(--dp) = *(--sp);
1982 *(--dp) = *(--sp);
1983 *(--dp) = *(--sp);
1984 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001985 *(--dp) = hi_filler;
1986 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001987 row_info->channels = 4;
1988 row_info->pixel_depth = 64;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001989 row_info->rowbytes = row_width * 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001990 }
1991 /* This changes the data from RRGGBB to XXRRGGBB */
1992 else
1993 {
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05001994 png_bytep sp = row + (png_size_t)row_width * 6;
1995 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001996 for (i = 0; i < row_width; i++)
1997 {
1998 *(--dp) = *(--sp);
1999 *(--dp) = *(--sp);
2000 *(--dp) = *(--sp);
2001 *(--dp) = *(--sp);
2002 *(--dp) = *(--sp);
2003 *(--dp) = *(--sp);
2004 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002005 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002006 }
2007 row_info->channels = 4;
2008 row_info->pixel_depth = 64;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002009 row_info->rowbytes = row_width * 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002010 }
2011 }
Glenn Randers-Pehrsondff799e2004-08-07 21:42:49 -05002012 row_info->color_type |= PNG_COLOR_MASK_ALPHA;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002013 } /* COLOR_TYPE == RGB */
Guy Schalnat0d580581995-07-20 02:43:20 -05002014}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002015#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002016
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002017#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002018/* expand grayscale files to RGB, with or without alpha */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002019void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002020png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05002021{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002022 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002023 png_uint_32 row_width = row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06002024
Andreas Dilger47a0c421997-05-16 02:46:07 -05002025 png_debug(1, "in png_do_gray_to_rgb\n");
2026 if (row_info->bit_depth >= 8 &&
2027#if defined(PNG_USELESS_TESTS_SUPPORTED)
2028 row != NULL && row_info != NULL &&
2029#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002030 !(row_info->color_type & PNG_COLOR_MASK_COLOR))
2031 {
2032 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2033 {
2034 if (row_info->bit_depth == 8)
2035 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002036 png_bytep sp = row + (png_size_t)row_width - 1;
2037 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002038 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002039 {
2040 *(dp--) = *sp;
2041 *(dp--) = *sp;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002042 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05002043 }
2044 }
2045 else
2046 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002047 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2048 png_bytep dp = sp + (png_size_t)row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002049 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002050 {
2051 *(dp--) = *sp;
2052 *(dp--) = *(sp - 1);
2053 *(dp--) = *sp;
2054 *(dp--) = *(sp - 1);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002055 *(dp--) = *(sp--);
2056 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05002057 }
2058 }
2059 }
2060 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2061 {
2062 if (row_info->bit_depth == 8)
2063 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002064 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2065 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002066 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002067 {
2068 *(dp--) = *(sp--);
2069 *(dp--) = *sp;
2070 *(dp--) = *sp;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002071 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05002072 }
2073 }
2074 else
2075 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002076 png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2077 png_bytep dp = sp + (png_size_t)row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002078 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002079 {
2080 *(dp--) = *(sp--);
2081 *(dp--) = *(sp--);
2082 *(dp--) = *sp;
2083 *(dp--) = *(sp - 1);
2084 *(dp--) = *sp;
2085 *(dp--) = *(sp - 1);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002086 *(dp--) = *(sp--);
2087 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05002088 }
2089 }
2090 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002091 row_info->channels += (png_byte)2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002092 row_info->color_type |= PNG_COLOR_MASK_COLOR;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002093 row_info->pixel_depth = (png_byte)(row_info->channels *
2094 row_info->bit_depth);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002095 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
Guy Schalnat0d580581995-07-20 02:43:20 -05002096 }
2097}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002098#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002099
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002100#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002101/* reduce RGB files to grayscale, with or without alpha
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002102 * using the equation given in Poynton's ColorFAQ at
2103 * <http://www.inforamp.net/~poynton/>
2104 * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
2105 *
2106 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2107 *
2108 * We approximate this with
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002109 *
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002110 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002111 *
2112 * which can be expressed with integers as
2113 *
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002114 * Y = (6969 * R + 23434 * G + 2365 * B)/32768
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002115 *
2116 * The calculation is to be done in a linear colorspace.
2117 *
2118 * Other integer coefficents can be used via png_set_rgb_to_gray().
2119 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002120int /* PRIVATE */
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002121png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2122
2123{
2124 png_uint_32 i;
2125
2126 png_uint_32 row_width = row_info->width;
2127 int rgb_error = 0;
2128
2129 png_debug(1, "in png_do_rgb_to_gray\n");
2130 if (
2131#if defined(PNG_USELESS_TESTS_SUPPORTED)
2132 row != NULL && row_info != NULL &&
2133#endif
2134 (row_info->color_type & PNG_COLOR_MASK_COLOR))
2135 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002136 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2137 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2138 png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002139
2140 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2141 {
2142 if (row_info->bit_depth == 8)
2143 {
2144#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2145 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2146 {
2147 png_bytep sp = row;
2148 png_bytep dp = row;
2149
2150 for (i = 0; i < row_width; i++)
2151 {
2152 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2153 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2154 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2155 if(red != green || red != blue)
2156 {
2157 rgb_error |= 1;
2158 *(dp++) = png_ptr->gamma_from_1[
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002159 (rc*red+gc*green+bc*blue)>>15];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002160 }
2161 else
2162 *(dp++) = *(sp-1);
2163 }
2164 }
2165 else
2166#endif
2167 {
2168 png_bytep sp = row;
2169 png_bytep dp = row;
2170 for (i = 0; i < row_width; i++)
2171 {
2172 png_byte red = *(sp++);
2173 png_byte green = *(sp++);
2174 png_byte blue = *(sp++);
2175 if(red != green || red != blue)
2176 {
2177 rgb_error |= 1;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002178 *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002179 }
2180 else
2181 *(dp++) = *(sp-1);
2182 }
2183 }
2184 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002185
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002186 else /* RGB bit_depth == 16 */
2187 {
2188#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2189 if (png_ptr->gamma_16_to_1 != NULL &&
2190 png_ptr->gamma_16_from_1 != NULL)
2191 {
2192 png_bytep sp = row;
2193 png_bytep dp = row;
2194 for (i = 0; i < row_width; i++)
2195 {
2196 png_uint_16 red, green, blue, w;
2197
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002198 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2199 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2200 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002201
2202 if(red == green && red == blue)
2203 w = red;
2204 else
2205 {
2206 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2207 png_ptr->gamma_shift][red>>8];
2208 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2209 png_ptr->gamma_shift][green>>8];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002210 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002211 png_ptr->gamma_shift][blue>>8];
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002212 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002213 + bc*blue_1)>>15);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002214 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2215 png_ptr->gamma_shift][gray16 >> 8];
2216 rgb_error |= 1;
2217 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002218
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002219 *(dp++) = (png_byte)((w>>8) & 0xff);
2220 *(dp++) = (png_byte)(w & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002221 }
2222 }
2223 else
2224#endif
2225 {
2226 png_bytep sp = row;
2227 png_bytep dp = row;
2228 for (i = 0; i < row_width; i++)
2229 {
2230 png_uint_16 red, green, blue, gray16;
2231
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002232 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2233 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2234 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002235
2236 if(red != green || red != blue)
2237 rgb_error |= 1;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002238 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002239 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2240 *(dp++) = (png_byte)(gray16 & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002241 }
2242 }
2243 }
2244 }
2245 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2246 {
2247 if (row_info->bit_depth == 8)
2248 {
2249#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2250 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2251 {
2252 png_bytep sp = row;
2253 png_bytep dp = row;
2254 for (i = 0; i < row_width; i++)
2255 {
2256 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2257 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2258 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2259 if(red != green || red != blue)
2260 rgb_error |= 1;
2261 *(dp++) = png_ptr->gamma_from_1
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002262 [(rc*red + gc*green + bc*blue)>>15];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002263 *(dp++) = *(sp++); /* alpha */
2264 }
2265 }
2266 else
2267#endif
2268 {
2269 png_bytep sp = row;
2270 png_bytep dp = row;
2271 for (i = 0; i < row_width; i++)
2272 {
2273 png_byte red = *(sp++);
2274 png_byte green = *(sp++);
2275 png_byte blue = *(sp++);
2276 if(red != green || red != blue)
2277 rgb_error |= 1;
Glenn Randers-Pehrsondff799e2004-08-07 21:42:49 -05002278 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002279 *(dp++) = *(sp++); /* alpha */
2280 }
2281 }
2282 }
2283 else /* RGBA bit_depth == 16 */
2284 {
2285#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2286 if (png_ptr->gamma_16_to_1 != NULL &&
2287 png_ptr->gamma_16_from_1 != NULL)
2288 {
2289 png_bytep sp = row;
2290 png_bytep dp = row;
2291 for (i = 0; i < row_width; i++)
2292 {
2293 png_uint_16 red, green, blue, w;
2294
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002295 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2296 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2297 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002298
2299 if(red == green && red == blue)
2300 w = red;
2301 else
2302 {
2303 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2304 png_ptr->gamma_shift][red>>8];
2305 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2306 png_ptr->gamma_shift][green>>8];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002307 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002308 png_ptr->gamma_shift][blue>>8];
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002309 png_uint_16 gray16 = (png_uint_16)((rc * red_1
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002310 + gc * green_1 + bc * blue_1)>>15);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002311 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2312 png_ptr->gamma_shift][gray16 >> 8];
2313 rgb_error |= 1;
2314 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002315
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002316 *(dp++) = (png_byte)((w>>8) & 0xff);
2317 *(dp++) = (png_byte)(w & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002318 *(dp++) = *(sp++); /* alpha */
2319 *(dp++) = *(sp++);
2320 }
2321 }
2322 else
2323#endif
2324 {
2325 png_bytep sp = row;
2326 png_bytep dp = row;
2327 for (i = 0; i < row_width; i++)
2328 {
2329 png_uint_16 red, green, blue, gray16;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002330 red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2331 green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2332 blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002333 if(red != green || red != blue)
2334 rgb_error |= 1;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002335 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002336 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2337 *(dp++) = (png_byte)(gray16 & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002338 *(dp++) = *(sp++); /* alpha */
2339 *(dp++) = *(sp++);
2340 }
2341 }
2342 }
2343 }
2344 row_info->channels -= (png_byte)2;
2345 row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2346 row_info->pixel_depth = (png_byte)(row_info->channels *
2347 row_info->bit_depth);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002348 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002349 }
2350 return rgb_error;
2351}
2352#endif
2353
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002354/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
2355 * large of png_color. This lets grayscale images be treated as
2356 * paletted. Most useful for gamma correction and simplification
2357 * of code.
2358 */
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -06002359void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -06002360png_build_grayscale_palette(int bit_depth, png_colorp palette)
Guy Schalnat0d580581995-07-20 02:43:20 -05002361{
2362 int num_palette;
2363 int color_inc;
2364 int i;
2365 int v;
2366
Andreas Dilger47a0c421997-05-16 02:46:07 -05002367 png_debug(1, "in png_do_build_grayscale_palette\n");
2368 if (palette == NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002369 return;
2370
2371 switch (bit_depth)
2372 {
2373 case 1:
2374 num_palette = 2;
2375 color_inc = 0xff;
2376 break;
2377 case 2:
2378 num_palette = 4;
2379 color_inc = 0x55;
2380 break;
2381 case 4:
2382 num_palette = 16;
2383 color_inc = 0x11;
2384 break;
2385 case 8:
2386 num_palette = 256;
2387 color_inc = 1;
2388 break;
2389 default:
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002390 num_palette = 0;
Guy Schalnat69b14481996-01-10 02:56:49 -06002391 color_inc = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05002392 break;
2393 }
2394
2395 for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2396 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002397 palette[i].red = (png_byte)v;
2398 palette[i].green = (png_byte)v;
2399 palette[i].blue = (png_byte)v;
Guy Schalnat0d580581995-07-20 02:43:20 -05002400 }
2401}
2402
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002403/* This function is currently unused. Do we really need it? */
2404#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002405void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002406png_correct_palette(png_structp png_ptr, png_colorp palette,
Guy Schalnat0d580581995-07-20 02:43:20 -05002407 int num_palette)
2408{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002409 png_debug(1, "in png_correct_palette\n");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002410#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2411 defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002412 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
Guy Schalnat0d580581995-07-20 02:43:20 -05002413 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002414 png_color back, back_1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002415
Andreas Dilger47a0c421997-05-16 02:46:07 -05002416 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
2417 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002418 back.red = png_ptr->gamma_table[png_ptr->background.red];
2419 back.green = png_ptr->gamma_table[png_ptr->background.green];
2420 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
Guy Schalnat0d580581995-07-20 02:43:20 -05002421
Guy Schalnate5a37791996-06-05 15:50:50 -05002422 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
2423 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
2424 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002425 }
2426 else
2427 {
2428 double g;
Guy Schalnat0d580581995-07-20 02:43:20 -05002429
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06002430 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002431
2432 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2433 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
Guy Schalnat0d580581995-07-20 02:43:20 -05002434 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002435 back.red = png_ptr->background.red;
2436 back.green = png_ptr->background.green;
2437 back.blue = png_ptr->background.blue;
2438 }
2439 else
2440 {
2441 back.red =
2442 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2443 255.0 + 0.5);
2444 back.green =
2445 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2446 255.0 + 0.5);
2447 back.blue =
2448 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2449 255.0 + 0.5);
2450 }
2451
2452 g = 1.0 / png_ptr->background_gamma;
2453
2454 back_1.red =
2455 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2456 255.0 + 0.5);
2457 back_1.green =
2458 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2459 255.0 + 0.5);
2460 back_1.blue =
2461 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2462 255.0 + 0.5);
2463 }
2464
2465 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2466 {
2467 png_uint_32 i;
2468
2469 for (i = 0; i < (png_uint_32)num_palette; i++)
2470 {
2471 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -05002472 {
2473 palette[i] = back;
2474 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002475 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002476 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002477 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002478
2479 v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002480 png_composite(w, v, png_ptr->trans[i], back_1.red);
2481 palette[i].red = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002482
2483 v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002484 png_composite(w, v, png_ptr->trans[i], back_1.green);
2485 palette[i].green = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002486
2487 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002488 png_composite(w, v, png_ptr->trans[i], back_1.blue);
2489 palette[i].blue = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002490 }
2491 else
2492 {
2493 palette[i].red = png_ptr->gamma_table[palette[i].red];
2494 palette[i].green = png_ptr->gamma_table[palette[i].green];
2495 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2496 }
2497 }
2498 }
2499 else
2500 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002501 int i;
Guy Schalnat0d580581995-07-20 02:43:20 -05002502
2503 for (i = 0; i < num_palette; i++)
2504 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002505 if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002506 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002507 palette[i] = back;
Guy Schalnat0d580581995-07-20 02:43:20 -05002508 }
2509 else
2510 {
2511 palette[i].red = png_ptr->gamma_table[palette[i].red];
2512 palette[i].green = png_ptr->gamma_table[palette[i].green];
2513 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2514 }
2515 }
2516 }
2517 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002518 else
2519#endif
2520#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002521 if (png_ptr->transformations & PNG_GAMMA)
Guy Schalnat0d580581995-07-20 02:43:20 -05002522 {
2523 int i;
2524
2525 for (i = 0; i < num_palette; i++)
2526 {
2527 palette[i].red = png_ptr->gamma_table[palette[i].red];
2528 palette[i].green = png_ptr->gamma_table[palette[i].green];
2529 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2530 }
2531 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002532#if defined(PNG_READ_BACKGROUND_SUPPORTED)
2533 else
2534#endif
2535#endif
2536#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002537 if (png_ptr->transformations & PNG_BACKGROUND)
Guy Schalnat0d580581995-07-20 02:43:20 -05002538 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002539 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05002540 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002541 png_color back;
Guy Schalnat0d580581995-07-20 02:43:20 -05002542
Guy Schalnate5a37791996-06-05 15:50:50 -05002543 back.red = (png_byte)png_ptr->background.red;
2544 back.green = (png_byte)png_ptr->background.green;
2545 back.blue = (png_byte)png_ptr->background.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002546
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06002547 for (i = 0; i < (int)png_ptr->num_trans; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002548 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002549 if (png_ptr->trans[i] == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -05002550 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002551 palette[i].red = back.red;
2552 palette[i].green = back.green;
2553 palette[i].blue = back.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002554 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002555 else if (png_ptr->trans[i] != 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002556 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002557 png_composite(palette[i].red, png_ptr->palette[i].red,
2558 png_ptr->trans[i], back.red);
2559 png_composite(palette[i].green, png_ptr->palette[i].green,
2560 png_ptr->trans[i], back.green);
2561 png_composite(palette[i].blue, png_ptr->palette[i].blue,
2562 png_ptr->trans[i], back.blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05002563 }
2564 }
2565 }
2566 else /* assume grayscale palette (what else could it be?) */
2567 {
2568 int i;
2569
2570 for (i = 0; i < num_palette; i++)
2571 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002572 if (i == (png_byte)png_ptr->trans_values.gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002573 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002574 palette[i].red = (png_byte)png_ptr->background.red;
2575 palette[i].green = (png_byte)png_ptr->background.green;
2576 palette[i].blue = (png_byte)png_ptr->background.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002577 }
2578 }
2579 }
2580 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002581#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002582}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002583#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002584
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002585#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002586/* Replace any alpha or transparency with the supplied background color.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002587 * "background" is already in the screen gamma, while "background_1" is
2588 * at a gamma of 1.0. Paletted files have already been taken care of.
2589 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002590void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002591png_do_background(png_row_infop row_info, png_bytep row,
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05002592 png_color_16p trans_values, png_color_16p background
2593#if defined(PNG_READ_GAMMA_SUPPORTED)
2594 , png_color_16p background_1,
Guy Schalnat6d764711995-12-19 03:22:19 -06002595 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002596 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05002597 png_uint_16pp gamma_16_to_1, int gamma_shift
2598#endif
2599 )
Guy Schalnat0d580581995-07-20 02:43:20 -05002600{
Guy Schalnat6d764711995-12-19 03:22:19 -06002601 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002602 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002603 png_uint_32 row_width=row_info->width;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002604 int shift;
Guy Schalnate5a37791996-06-05 15:50:50 -05002605
Andreas Dilger47a0c421997-05-16 02:46:07 -05002606 png_debug(1, "in png_do_background\n");
2607 if (background != NULL &&
2608#if defined(PNG_USELESS_TESTS_SUPPORTED)
2609 row != NULL && row_info != NULL &&
2610#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002611 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
Andreas Dilger47a0c421997-05-16 02:46:07 -05002612 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
Guy Schalnat0d580581995-07-20 02:43:20 -05002613 {
2614 switch (row_info->color_type)
2615 {
2616 case PNG_COLOR_TYPE_GRAY:
2617 {
2618 switch (row_info->bit_depth)
2619 {
2620 case 1:
2621 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002622 sp = row;
2623 shift = 7;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002624 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002625 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002626 if ((png_uint_16)((*sp >> shift) & 0x01)
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002627 == trans_values->gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002628 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002629 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2630 *sp |= (png_byte)(background->gray << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05002631 }
2632 if (!shift)
2633 {
2634 shift = 7;
2635 sp++;
2636 }
2637 else
2638 shift--;
2639 }
2640 break;
2641 }
2642 case 2:
2643 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002644#if defined(PNG_READ_GAMMA_SUPPORTED)
2645 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002646 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002647 sp = row;
2648 shift = 6;
2649 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002650 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002651 if ((png_uint_16)((*sp >> shift) & 0x03)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002652 == trans_values->gray)
2653 {
2654 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2655 *sp |= (png_byte)(background->gray << shift);
2656 }
2657 else
2658 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002659 png_byte p = (png_byte)((*sp >> shift) & 0x03);
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002660 png_byte g = (png_byte)((gamma_table [p | (p << 2) |
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002661 (p << 4) | (p << 6)] >> 6) & 0x03);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002662 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2663 *sp |= (png_byte)(g << shift);
2664 }
2665 if (!shift)
2666 {
2667 shift = 6;
2668 sp++;
2669 }
2670 else
2671 shift -= 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002672 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002673 }
2674 else
2675#endif
2676 {
2677 sp = row;
2678 shift = 6;
2679 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002680 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002681 if ((png_uint_16)((*sp >> shift) & 0x03)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002682 == trans_values->gray)
2683 {
2684 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2685 *sp |= (png_byte)(background->gray << shift);
2686 }
2687 if (!shift)
2688 {
2689 shift = 6;
2690 sp++;
2691 }
2692 else
2693 shift -= 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002694 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002695 }
2696 break;
2697 }
2698 case 4:
2699 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002700#if defined(PNG_READ_GAMMA_SUPPORTED)
2701 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002702 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002703 sp = row;
2704 shift = 4;
2705 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002706 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002707 if ((png_uint_16)((*sp >> shift) & 0x0f)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002708 == trans_values->gray)
2709 {
2710 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2711 *sp |= (png_byte)(background->gray << shift);
2712 }
2713 else
2714 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002715 png_byte p = (png_byte)((*sp >> shift) & 0x0f);
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002716 png_byte g = (png_byte)((gamma_table[p |
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002717 (p << 4)] >> 4) & 0x0f);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002718 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2719 *sp |= (png_byte)(g << shift);
2720 }
2721 if (!shift)
2722 {
2723 shift = 4;
2724 sp++;
2725 }
2726 else
2727 shift -= 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05002728 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002729 }
2730 else
2731#endif
2732 {
2733 sp = row;
2734 shift = 4;
2735 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002736 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002737 if ((png_uint_16)((*sp >> shift) & 0x0f)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002738 == trans_values->gray)
2739 {
2740 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2741 *sp |= (png_byte)(background->gray << shift);
2742 }
2743 if (!shift)
2744 {
2745 shift = 4;
2746 sp++;
2747 }
2748 else
2749 shift -= 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05002750 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002751 }
2752 break;
2753 }
2754 case 8:
2755 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002756#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002757 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002758 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002759 sp = row;
2760 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002761 {
2762 if (*sp == trans_values->gray)
2763 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002764 *sp = (png_byte)background->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05002765 }
2766 else
2767 {
2768 *sp = gamma_table[*sp];
2769 }
2770 }
2771 }
2772 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002773#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002774 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002775 sp = row;
2776 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002777 {
2778 if (*sp == trans_values->gray)
2779 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002780 *sp = (png_byte)background->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05002781 }
2782 }
2783 }
2784 break;
2785 }
2786 case 16:
2787 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002788#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002789 if (gamma_16 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002790 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002791 sp = row;
2792 for (i = 0; i < row_width; i++, sp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002793 {
2794 png_uint_16 v;
2795
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002796 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05002797 if (v == trans_values->gray)
2798 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002799 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002800 *sp = (png_byte)((background->gray >> 8) & 0xff);
2801 *(sp + 1) = (png_byte)(background->gray & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002802 }
2803 else
2804 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002805 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002806 *sp = (png_byte)((v >> 8) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002807 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002808 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002809 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002810 }
2811 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002812#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002813 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002814 sp = row;
2815 for (i = 0; i < row_width; i++, sp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002816 {
2817 png_uint_16 v;
2818
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002819 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05002820 if (v == trans_values->gray)
2821 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002822 *sp = (png_byte)((background->gray >> 8) & 0xff);
2823 *(sp + 1) = (png_byte)(background->gray & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002824 }
2825 }
2826 }
2827 break;
2828 }
2829 }
2830 break;
2831 }
2832 case PNG_COLOR_TYPE_RGB:
2833 {
2834 if (row_info->bit_depth == 8)
2835 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002836#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002837 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002838 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002839 sp = row;
2840 for (i = 0; i < row_width; i++, sp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002841 {
2842 if (*sp == trans_values->red &&
2843 *(sp + 1) == trans_values->green &&
2844 *(sp + 2) == trans_values->blue)
2845 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002846 *sp = (png_byte)background->red;
2847 *(sp + 1) = (png_byte)background->green;
2848 *(sp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002849 }
2850 else
2851 {
2852 *sp = gamma_table[*sp];
2853 *(sp + 1) = gamma_table[*(sp + 1)];
2854 *(sp + 2) = gamma_table[*(sp + 2)];
2855 }
2856 }
2857 }
2858 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002859#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002860 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002861 sp = row;
2862 for (i = 0; i < row_width; i++, sp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002863 {
2864 if (*sp == trans_values->red &&
2865 *(sp + 1) == trans_values->green &&
2866 *(sp + 2) == trans_values->blue)
2867 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002868 *sp = (png_byte)background->red;
2869 *(sp + 1) = (png_byte)background->green;
2870 *(sp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002871 }
2872 }
2873 }
2874 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002875 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002876 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002877#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002878 if (gamma_16 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002879 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002880 sp = row;
2881 for (i = 0; i < row_width; i++, sp += 6)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002882 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002883 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2884 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2885 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
Andreas Dilger47a0c421997-05-16 02:46:07 -05002886 if (r == trans_values->red && g == trans_values->green &&
Guy Schalnat0d580581995-07-20 02:43:20 -05002887 b == trans_values->blue)
2888 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002889 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002890 *sp = (png_byte)((background->red >> 8) & 0xff);
2891 *(sp + 1) = (png_byte)(background->red & 0xff);
2892 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2893 *(sp + 3) = (png_byte)(background->green & 0xff);
2894 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2895 *(sp + 5) = (png_byte)(background->blue & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002896 }
2897 else
2898 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002899 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002900 *sp = (png_byte)((v >> 8) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002901 *(sp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002902 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002903 *(sp + 2) = (png_byte)((v >> 8) & 0xff);
2904 *(sp + 3) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002905 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002906 *(sp + 4) = (png_byte)((v >> 8) & 0xff);
2907 *(sp + 5) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002908 }
2909 }
2910 }
2911 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002912#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002913 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002914 sp = row;
2915 for (i = 0; i < row_width; i++, sp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05002916 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002917 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
2918 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2919 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
Guy Schalnat0d580581995-07-20 02:43:20 -05002920
Andreas Dilger47a0c421997-05-16 02:46:07 -05002921 if (r == trans_values->red && g == trans_values->green &&
Guy Schalnat0d580581995-07-20 02:43:20 -05002922 b == trans_values->blue)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002923 {
2924 *sp = (png_byte)((background->red >> 8) & 0xff);
2925 *(sp + 1) = (png_byte)(background->red & 0xff);
2926 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2927 *(sp + 3) = (png_byte)(background->green & 0xff);
2928 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2929 *(sp + 5) = (png_byte)(background->blue & 0xff);
2930 }
2931 }
2932 }
2933 }
2934 break;
2935 }
2936 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -05002937 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002938 if (row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05002939 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002940#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002941 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2942 gamma_table != NULL)
2943 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002944 sp = row;
2945 dp = row;
2946 for (i = 0; i < row_width; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002947 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002948 png_uint_16 a = *(sp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002949
Andreas Dilger47a0c421997-05-16 02:46:07 -05002950 if (a == 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002951 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002952 *dp = gamma_table[*sp];
2953 }
2954 else if (a == 0)
2955 {
2956 /* background is already in screen gamma */
2957 *dp = (png_byte)background->gray;
2958 }
2959 else
2960 {
2961 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002962
Andreas Dilger47a0c421997-05-16 02:46:07 -05002963 v = gamma_to_1[*sp];
2964 png_composite(w, v, a, background_1->gray);
2965 *dp = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002966 }
2967 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002968 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002969 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002970#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05002971 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002972 sp = row;
2973 dp = row;
2974 for (i = 0; i < row_width; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002975 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002976 png_byte a = *(sp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002977
Andreas Dilger47a0c421997-05-16 02:46:07 -05002978 if (a == 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002979 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002980 *dp = *sp;
2981 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05002982#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002983 else if (a == 0)
2984 {
2985 *dp = (png_byte)background->gray;
2986 }
2987 else
2988 {
2989 png_composite(*dp, *sp, a, background_1->gray);
Guy Schalnat0d580581995-07-20 02:43:20 -05002990 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05002991#else
2992 *dp = (png_byte)background->gray;
2993#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002994 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002995 }
2996 }
2997 else /* if (png_ptr->bit_depth == 16) */
2998 {
2999#if defined(PNG_READ_GAMMA_SUPPORTED)
3000 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3001 gamma_16_to_1 != NULL)
3002 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003003 sp = row;
3004 dp = row;
3005 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003006 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003007 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003008
Andreas Dilger47a0c421997-05-16 02:46:07 -05003009 if (a == (png_uint_16)0xffff)
3010 {
3011 png_uint_16 v;
3012
3013 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3014 *dp = (png_byte)((v >> 8) & 0xff);
3015 *(dp + 1) = (png_byte)(v & 0xff);
3016 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003017#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003018 else if (a == 0)
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003019#else
3020 else
3021#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05003022 {
3023 /* background is already in screen gamma */
3024 *dp = (png_byte)((background->gray >> 8) & 0xff);
3025 *(dp + 1) = (png_byte)(background->gray & 0xff);
3026 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003027#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003028 else
3029 {
3030 png_uint_16 g, v, w;
3031
3032 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3033 png_composite_16(v, g, a, background_1->gray);
3034 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3035 *dp = (png_byte)((w >> 8) & 0xff);
3036 *(dp + 1) = (png_byte)(w & 0xff);
3037 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003038#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05003039 }
3040 }
3041 else
3042#endif
3043 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003044 sp = row;
3045 dp = row;
3046 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003047 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003048 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003049 if (a == (png_uint_16)0xffff)
3050 {
3051 png_memcpy(dp, sp, 2);
3052 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003053#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003054 else if (a == 0)
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003055#else
3056 else
3057#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05003058 {
3059 *dp = (png_byte)((background->gray >> 8) & 0xff);
3060 *(dp + 1) = (png_byte)(background->gray & 0xff);
3061 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003062#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003063 else
3064 {
3065 png_uint_16 g, v;
3066
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003067 g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003068 png_composite_16(v, g, a, background_1->gray);
3069 *dp = (png_byte)((v >> 8) & 0xff);
3070 *(dp + 1) = (png_byte)(v & 0xff);
3071 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003072#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05003073 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003074 }
3075 }
3076 break;
3077 }
3078 case PNG_COLOR_TYPE_RGB_ALPHA:
3079 {
3080 if (row_info->bit_depth == 8)
3081 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003082#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003083 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3084 gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05003085 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003086 sp = row;
3087 dp = row;
3088 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05003089 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003090 png_byte a = *(sp + 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003091
Guy Schalnat0d580581995-07-20 02:43:20 -05003092 if (a == 0xff)
3093 {
3094 *dp = gamma_table[*sp];
3095 *(dp + 1) = gamma_table[*(sp + 1)];
3096 *(dp + 2) = gamma_table[*(sp + 2)];
3097 }
3098 else if (a == 0)
3099 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003100 /* background is already in screen gamma */
3101 *dp = (png_byte)background->red;
3102 *(dp + 1) = (png_byte)background->green;
3103 *(dp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003104 }
3105 else
3106 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003107 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05003108
3109 v = gamma_to_1[*sp];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003110 png_composite(w, v, a, background_1->red);
3111 *dp = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05003112 v = gamma_to_1[*(sp + 1)];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003113 png_composite(w, v, a, background_1->green);
3114 *(dp + 1) = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05003115 v = gamma_to_1[*(sp + 2)];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003116 png_composite(w, v, a, background_1->blue);
3117 *(dp + 2) = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05003118 }
3119 }
3120 }
3121 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003122#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003123 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003124 sp = row;
3125 dp = row;
3126 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05003127 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003128 png_byte a = *(sp + 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003129
Guy Schalnat0d580581995-07-20 02:43:20 -05003130 if (a == 0xff)
3131 {
3132 *dp = *sp;
3133 *(dp + 1) = *(sp + 1);
3134 *(dp + 2) = *(sp + 2);
3135 }
3136 else if (a == 0)
3137 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003138 *dp = (png_byte)background->red;
3139 *(dp + 1) = (png_byte)background->green;
3140 *(dp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003141 }
3142 else
3143 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003144 png_composite(*dp, *sp, a, background->red);
3145 png_composite(*(dp + 1), *(sp + 1), a,
3146 background->green);
3147 png_composite(*(dp + 2), *(sp + 2), a,
3148 background->blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05003149 }
3150 }
3151 }
3152 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003153 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003154 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003155#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003156 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3157 gamma_16_to_1 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05003158 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003159 sp = row;
3160 dp = row;
3161 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05003162 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003163 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3164 << 8) + (png_uint_16)(*(sp + 7)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003165 if (a == (png_uint_16)0xffff)
3166 {
3167 png_uint_16 v;
3168
Andreas Dilger47a0c421997-05-16 02:46:07 -05003169 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003170 *dp = (png_byte)((v >> 8) & 0xff);
3171 *(dp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003172 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003173 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3174 *(dp + 3) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003175 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003176 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3177 *(dp + 5) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003178 }
3179 else if (a == 0)
3180 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003181 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003182 *dp = (png_byte)((background->red >> 8) & 0xff);
3183 *(dp + 1) = (png_byte)(background->red & 0xff);
3184 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3185 *(dp + 3) = (png_byte)(background->green & 0xff);
3186 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3187 *(dp + 5) = (png_byte)(background->blue & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003188 }
3189 else
3190 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003191 png_uint_16 v, w, x;
Guy Schalnat0d580581995-07-20 02:43:20 -05003192
Andreas Dilger47a0c421997-05-16 02:46:07 -05003193 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -06003194 png_composite_16(w, v, a, background_1->red);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003195 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3196 *dp = (png_byte)((x >> 8) & 0xff);
3197 *(dp + 1) = (png_byte)(x & 0xff);
3198 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -06003199 png_composite_16(w, v, a, background_1->green);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003200 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3201 *(dp + 2) = (png_byte)((x >> 8) & 0xff);
3202 *(dp + 3) = (png_byte)(x & 0xff);
3203 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -06003204 png_composite_16(w, v, a, background_1->blue);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003205 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3206 *(dp + 4) = (png_byte)((x >> 8) & 0xff);
3207 *(dp + 5) = (png_byte)(x & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003208 }
3209 }
3210 }
3211 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003212#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003213 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003214 sp = row;
3215 dp = row;
3216 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05003217 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003218 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3219 << 8) + (png_uint_16)(*(sp + 7)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003220 if (a == (png_uint_16)0xffff)
3221 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003222 png_memcpy(dp, sp, 6);
Guy Schalnat0d580581995-07-20 02:43:20 -05003223 }
3224 else if (a == 0)
3225 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003226 *dp = (png_byte)((background->red >> 8) & 0xff);
3227 *(dp + 1) = (png_byte)(background->red & 0xff);
3228 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3229 *(dp + 3) = (png_byte)(background->green & 0xff);
3230 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3231 *(dp + 5) = (png_byte)(background->blue & 0xff);
3232 }
3233 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003234 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003235 png_uint_16 v;
Guy Schalnat0d580581995-07-20 02:43:20 -05003236
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003237 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3238 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3239 + *(sp + 3));
3240 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3241 + *(sp + 5));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003242
3243 png_composite_16(v, r, a, background->red);
Guy Schalnat0d580581995-07-20 02:43:20 -05003244 *dp = (png_byte)((v >> 8) & 0xff);
3245 *(dp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003246 png_composite_16(v, g, a, background->green);
Guy Schalnat0d580581995-07-20 02:43:20 -05003247 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3248 *(dp + 3) = (png_byte)(v & 0xff);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003249 png_composite_16(v, b, a, background->blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05003250 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3251 *(dp + 5) = (png_byte)(v & 0xff);
3252 }
3253 }
3254 }
3255 }
3256 break;
3257 }
3258 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003259
Guy Schalnat0d580581995-07-20 02:43:20 -05003260 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3261 {
3262 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
Guy Schalnate5a37791996-06-05 15:50:50 -05003263 row_info->channels--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003264 row_info->pixel_depth = (png_byte)(row_info->channels *
3265 row_info->bit_depth);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05003266 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
Guy Schalnat0d580581995-07-20 02:43:20 -05003267 }
3268 }
3269}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003270#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003271
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003272#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003273/* Gamma correct the image, avoiding the alpha channel. Make sure
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05003274 * you do this after you deal with the transparency issue on grayscale
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -05003275 * or RGB images. If your bit depth is 8, use gamma_table, if it
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003276 * is 16, use gamma_16_table and gamma_shift. Build these with
3277 * build_gamma_table().
3278 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003279void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003280png_do_gamma(png_row_infop row_info, png_bytep row,
3281 png_bytep gamma_table, png_uint_16pp gamma_16_table,
Guy Schalnat0d580581995-07-20 02:43:20 -05003282 int gamma_shift)
3283{
Guy Schalnat6d764711995-12-19 03:22:19 -06003284 png_bytep sp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003285 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003286 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003287
Andreas Dilger47a0c421997-05-16 02:46:07 -05003288 png_debug(1, "in png_do_gamma\n");
3289 if (
3290#if defined(PNG_USELESS_TESTS_SUPPORTED)
3291 row != NULL && row_info != NULL &&
3292#endif
3293 ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3294 (row_info->bit_depth == 16 && gamma_16_table != NULL)))
Guy Schalnat0d580581995-07-20 02:43:20 -05003295 {
3296 switch (row_info->color_type)
3297 {
3298 case PNG_COLOR_TYPE_RGB:
3299 {
3300 if (row_info->bit_depth == 8)
3301 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003302 sp = row;
3303 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003304 {
3305 *sp = gamma_table[*sp];
3306 sp++;
3307 *sp = gamma_table[*sp];
3308 sp++;
3309 *sp = gamma_table[*sp];
3310 sp++;
3311 }
3312 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003313 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003314 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003315 sp = row;
3316 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003317 {
3318 png_uint_16 v;
3319
Andreas Dilger47a0c421997-05-16 02:46:07 -05003320 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003321 *sp = (png_byte)((v >> 8) & 0xff);
3322 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003323 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003324 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003325 *sp = (png_byte)((v >> 8) & 0xff);
3326 *(sp + 1) = (png_byte)(v & 0xff);
3327 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003328 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003329 *sp = (png_byte)((v >> 8) & 0xff);
3330 *(sp + 1) = (png_byte)(v & 0xff);
3331 sp += 2;
3332 }
3333 }
3334 break;
3335 }
3336 case PNG_COLOR_TYPE_RGB_ALPHA:
3337 {
3338 if (row_info->bit_depth == 8)
3339 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003340 sp = row;
3341 for (i = 0; i < row_width; i++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003342 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003343 *sp = gamma_table[*sp];
3344 sp++;
3345 *sp = gamma_table[*sp];
3346 sp++;
3347 *sp = gamma_table[*sp];
3348 sp++;
3349 sp++;
3350 }
3351 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003352 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003353 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003354 sp = row;
3355 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003356 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003357 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003358 *sp = (png_byte)((v >> 8) & 0xff);
3359 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003360 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003361 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003362 *sp = (png_byte)((v >> 8) & 0xff);
3363 *(sp + 1) = (png_byte)(v & 0xff);
3364 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003365 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003366 *sp = (png_byte)((v >> 8) & 0xff);
3367 *(sp + 1) = (png_byte)(v & 0xff);
3368 sp += 4;
3369 }
3370 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003371 break;
3372 }
3373 case PNG_COLOR_TYPE_GRAY_ALPHA:
3374 {
3375 if (row_info->bit_depth == 8)
3376 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003377 sp = row;
3378 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003379 {
3380 *sp = gamma_table[*sp];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003381 sp += 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05003382 }
3383 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003384 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003385 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003386 sp = row;
3387 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003388 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003389 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003390 *sp = (png_byte)((v >> 8) & 0xff);
3391 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003392 sp += 4;
3393 }
3394 }
3395 break;
3396 }
3397 case PNG_COLOR_TYPE_GRAY:
3398 {
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003399 if (row_info->bit_depth == 2)
3400 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003401 sp = row;
3402 for (i = 0; i < row_width; i += 4)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003403 {
3404 int a = *sp & 0xc0;
3405 int b = *sp & 0x30;
3406 int c = *sp & 0x0c;
3407 int d = *sp & 0x03;
3408
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003409 *sp = (png_byte)(
3410 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003411 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3412 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003413 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003414 sp++;
3415 }
3416 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003417 if (row_info->bit_depth == 4)
Guy Schalnat0d580581995-07-20 02:43:20 -05003418 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003419 sp = row;
3420 for (i = 0; i < row_width; i += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003421 {
3422 int msb = *sp & 0xf0;
3423 int lsb = *sp & 0x0f;
3424
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003425 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3426 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003427 sp++;
3428 }
3429 }
3430 else if (row_info->bit_depth == 8)
3431 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003432 sp = row;
3433 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003434 {
3435 *sp = gamma_table[*sp];
3436 sp++;
3437 }
3438 }
3439 else if (row_info->bit_depth == 16)
3440 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003441 sp = row;
3442 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003443 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003444 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003445 *sp = (png_byte)((v >> 8) & 0xff);
3446 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003447 sp += 2;
3448 }
3449 }
3450 break;
3451 }
3452 }
3453 }
3454}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003455#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003456
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003457#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -05003458/* Expands a palette row to an RGB or RGBA row depending
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003459 * upon whether you supply trans and num_trans.
3460 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003461void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003462png_do_expand_palette(png_row_infop row_info, png_bytep row,
Andreas Dilger47a0c421997-05-16 02:46:07 -05003463 png_colorp palette, png_bytep trans, int num_trans)
Guy Schalnat0d580581995-07-20 02:43:20 -05003464{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003465 int shift, value;
Guy Schalnat6d764711995-12-19 03:22:19 -06003466 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003467 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003468 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003469
Andreas Dilger47a0c421997-05-16 02:46:07 -05003470 png_debug(1, "in png_do_expand_palette\n");
3471 if (
3472#if defined(PNG_USELESS_TESTS_SUPPORTED)
3473 row != NULL && row_info != NULL &&
3474#endif
3475 row_info->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05003476 {
3477 if (row_info->bit_depth < 8)
3478 {
3479 switch (row_info->bit_depth)
3480 {
3481 case 1:
3482 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003483 sp = row + (png_size_t)((row_width - 1) >> 3);
3484 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003485 shift = 7 - (int)((row_width + 7) & 0x07);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003486 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003487 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003488 if ((*sp >> shift) & 0x01)
Guy Schalnat0d580581995-07-20 02:43:20 -05003489 *dp = 1;
3490 else
3491 *dp = 0;
3492 if (shift == 7)
3493 {
3494 shift = 0;
3495 sp--;
3496 }
3497 else
3498 shift++;
3499
3500 dp--;
3501 }
3502 break;
3503 }
3504 case 2:
3505 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003506 sp = row + (png_size_t)((row_width - 1) >> 2);
3507 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003508 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003509 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003510 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003511 value = (*sp >> shift) & 0x03;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003512 *dp = (png_byte)value;
Guy Schalnat0d580581995-07-20 02:43:20 -05003513 if (shift == 6)
3514 {
3515 shift = 0;
3516 sp--;
3517 }
3518 else
3519 shift += 2;
3520
3521 dp--;
3522 }
3523 break;
3524 }
3525 case 4:
3526 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003527 sp = row + (png_size_t)((row_width - 1) >> 1);
3528 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003529 shift = (int)((row_width & 0x01) << 2);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003530 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003531 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003532 value = (*sp >> shift) & 0x0f;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003533 *dp = (png_byte)value;
Guy Schalnat0d580581995-07-20 02:43:20 -05003534 if (shift == 4)
3535 {
3536 shift = 0;
3537 sp--;
3538 }
3539 else
3540 shift += 4;
3541
3542 dp--;
3543 }
3544 break;
3545 }
3546 }
3547 row_info->bit_depth = 8;
3548 row_info->pixel_depth = 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003549 row_info->rowbytes = row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -05003550 }
3551 switch (row_info->bit_depth)
3552 {
3553 case 8:
3554 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003555 if (trans != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05003556 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003557 sp = row + (png_size_t)row_width - 1;
3558 dp = row + (png_size_t)(row_width << 2) - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003559
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003560 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003561 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003562 if ((int)(*sp) >= num_trans)
Guy Schalnat0d580581995-07-20 02:43:20 -05003563 *dp-- = 0xff;
3564 else
3565 *dp-- = trans[*sp];
3566 *dp-- = palette[*sp].blue;
3567 *dp-- = palette[*sp].green;
3568 *dp-- = palette[*sp].red;
3569 sp--;
3570 }
3571 row_info->bit_depth = 8;
3572 row_info->pixel_depth = 32;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003573 row_info->rowbytes = row_width * 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05003574 row_info->color_type = 6;
3575 row_info->channels = 4;
3576 }
3577 else
3578 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003579 sp = row + (png_size_t)row_width - 1;
3580 dp = row + (png_size_t)(row_width * 3) - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003581
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003582 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003583 {
3584 *dp-- = palette[*sp].blue;
3585 *dp-- = palette[*sp].green;
3586 *dp-- = palette[*sp].red;
3587 sp--;
3588 }
3589 row_info->bit_depth = 8;
3590 row_info->pixel_depth = 24;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003591 row_info->rowbytes = row_width * 3;
Guy Schalnat0d580581995-07-20 02:43:20 -05003592 row_info->color_type = 2;
3593 row_info->channels = 3;
3594 }
3595 break;
3596 }
3597 }
3598 }
3599}
3600
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003601/* If the bit depth < 8, it is expanded to 8. Also, if the
3602 * transparency value is supplied, an alpha channel is built.
3603 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003604void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003605png_do_expand(png_row_infop row_info, png_bytep row,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003606 png_color_16p trans_value)
Guy Schalnat0d580581995-07-20 02:43:20 -05003607{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003608 int shift, value;
Guy Schalnat6d764711995-12-19 03:22:19 -06003609 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003610 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003611 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003612
Andreas Dilger47a0c421997-05-16 02:46:07 -05003613 png_debug(1, "in png_do_expand\n");
3614#if defined(PNG_USELESS_TESTS_SUPPORTED)
3615 if (row != NULL && row_info != NULL)
3616#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003617 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003618 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05003619 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003620 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003621
3622 if (row_info->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003623 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003624 switch (row_info->bit_depth)
Guy Schalnat0d580581995-07-20 02:43:20 -05003625 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003626 case 1:
3627 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003628 gray = (png_uint_16)(gray*0xff);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003629 sp = row + (png_size_t)((row_width - 1) >> 3);
3630 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003631 shift = 7 - (int)((row_width + 7) & 0x07);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003632 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003633 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003634 if ((*sp >> shift) & 0x01)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003635 *dp = 0xff;
3636 else
3637 *dp = 0;
3638 if (shift == 7)
3639 {
3640 shift = 0;
3641 sp--;
3642 }
3643 else
3644 shift++;
3645
3646 dp--;
3647 }
3648 break;
3649 }
3650 case 2:
3651 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003652 gray = (png_uint_16)(gray*0x55);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003653 sp = row + (png_size_t)((row_width - 1) >> 2);
3654 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003655 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003656 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003657 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003658 value = (*sp >> shift) & 0x03;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003659 *dp = (png_byte)(value | (value << 2) | (value << 4) |
3660 (value << 6));
3661 if (shift == 6)
3662 {
3663 shift = 0;
3664 sp--;
3665 }
3666 else
3667 shift += 2;
3668
3669 dp--;
3670 }
3671 break;
3672 }
3673 case 4:
3674 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003675 gray = (png_uint_16)(gray*0x11);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003676 sp = row + (png_size_t)((row_width - 1) >> 1);
3677 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003678 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003679 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003680 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003681 value = (*sp >> shift) & 0x0f;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003682 *dp = (png_byte)(value | (value << 4));
3683 if (shift == 4)
3684 {
3685 shift = 0;
3686 sp--;
3687 }
3688 else
3689 shift = 4;
3690
3691 dp--;
3692 }
3693 break;
3694 }
3695 }
3696 row_info->bit_depth = 8;
3697 row_info->pixel_depth = 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003698 row_info->rowbytes = row_width;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003699 }
3700
Andreas Dilger47a0c421997-05-16 02:46:07 -05003701 if (trans_value != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003702 {
3703 if (row_info->bit_depth == 8)
3704 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003705 sp = row + (png_size_t)row_width - 1;
3706 dp = row + (png_size_t)(row_width << 1) - 1;
3707 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003708 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003709 if (*sp == gray)
3710 *dp-- = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003711 else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003712 *dp-- = 0xff;
3713 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003714 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003715 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003716 else if (row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -05003717 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003718 sp = row + row_info->rowbytes - 1;
3719 dp = row + (row_info->rowbytes << 1) - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003720 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003721 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003722 if (((png_uint_16)*(sp) |
3723 ((png_uint_16)*(sp - 1) << 8)) == gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05003724 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003725 *dp-- = 0;
3726 *dp-- = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003727 }
3728 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003729 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003730 *dp-- = 0xff;
3731 *dp-- = 0xff;
Guy Schalnat0d580581995-07-20 02:43:20 -05003732 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003733 *dp-- = *sp--;
3734 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003735 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003736 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003737 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3738 row_info->channels = 2;
3739 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05003740 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
3741 row_width);
Guy Schalnat0d580581995-07-20 02:43:20 -05003742 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003743 }
3744 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3745 {
3746 if (row_info->bit_depth == 8)
3747 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003748 sp = row + (png_size_t)row_info->rowbytes - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003749 dp = row + (png_size_t)(row_width << 2) - 1;
3750 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003751 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003752 if (*(sp - 2) == trans_value->red &&
Guy Schalnat0d580581995-07-20 02:43:20 -05003753 *(sp - 1) == trans_value->green &&
3754 *(sp - 0) == trans_value->blue)
3755 *dp-- = 0;
3756 else
3757 *dp-- = 0xff;
3758 *dp-- = *sp--;
3759 *dp-- = *sp--;
3760 *dp-- = *sp--;
3761 }
3762 }
3763 else if (row_info->bit_depth == 16)
3764 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003765 sp = row + row_info->rowbytes - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003766 dp = row + (png_size_t)(row_width << 3) - 1;
3767 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003768 {
3769 if ((((png_uint_16)*(sp - 4) |
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003770 ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
Guy Schalnat0d580581995-07-20 02:43:20 -05003771 (((png_uint_16)*(sp - 2) |
3772 ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
3773 (((png_uint_16)*(sp - 0) |
3774 ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
3775 {
3776 *dp-- = 0;
3777 *dp-- = 0;
3778 }
3779 else
3780 {
3781 *dp-- = 0xff;
3782 *dp-- = 0xff;
3783 }
3784 *dp-- = *sp--;
3785 *dp-- = *sp--;
3786 *dp-- = *sp--;
3787 *dp-- = *sp--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003788 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003789 *dp-- = *sp--;
3790 }
3791 }
3792 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3793 row_info->channels = 4;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003794 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05003795 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
Guy Schalnat0d580581995-07-20 02:43:20 -05003796 }
3797 }
3798}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003799#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003800
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003801#if defined(PNG_READ_DITHER_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003802void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003803png_do_dither(png_row_infop row_info, png_bytep row,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003804 png_bytep palette_lookup, png_bytep dither_lookup)
Guy Schalnat0d580581995-07-20 02:43:20 -05003805{
Guy Schalnat6d764711995-12-19 03:22:19 -06003806 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003807 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003808 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003809
Andreas Dilger47a0c421997-05-16 02:46:07 -05003810 png_debug(1, "in png_do_dither\n");
3811#if defined(PNG_USELESS_TESTS_SUPPORTED)
3812 if (row != NULL && row_info != NULL)
3813#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003814 {
3815 if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3816 palette_lookup && row_info->bit_depth == 8)
3817 {
3818 int r, g, b, p;
Guy Schalnat0d580581995-07-20 02:43:20 -05003819 sp = row;
3820 dp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003821 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003822 {
3823 r = *sp++;
3824 g = *sp++;
3825 b = *sp++;
3826
3827 /* this looks real messy, but the compiler will reduce
3828 it down to a reasonable formula. For example, with
3829 5 bits per color, we get:
3830 p = (((r >> 3) & 0x1f) << 10) |
3831 (((g >> 3) & 0x1f) << 5) |
3832 ((b >> 3) & 0x1f);
3833 */
3834 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3835 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3836 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3837 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003838 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
Guy Schalnat0d580581995-07-20 02:43:20 -05003839 (PNG_DITHER_BLUE_BITS)) |
3840 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3841 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3842
3843 *dp++ = palette_lookup[p];
3844 }
3845 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3846 row_info->channels = 1;
3847 row_info->pixel_depth = row_info->bit_depth;
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05003848 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
Guy Schalnat0d580581995-07-20 02:43:20 -05003849 }
3850 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
Andreas Dilger47a0c421997-05-16 02:46:07 -05003851 palette_lookup != NULL && row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003852 {
3853 int r, g, b, p;
Guy Schalnat0d580581995-07-20 02:43:20 -05003854 sp = row;
3855 dp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003856 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003857 {
3858 r = *sp++;
3859 g = *sp++;
3860 b = *sp++;
3861 sp++;
3862
3863 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003864 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
Guy Schalnat0d580581995-07-20 02:43:20 -05003865 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3866 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3867 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3868 (PNG_DITHER_BLUE_BITS)) |
3869 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3870 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3871
3872 *dp++ = palette_lookup[p];
3873 }
3874 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3875 row_info->channels = 1;
3876 row_info->pixel_depth = row_info->bit_depth;
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05003877 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
Guy Schalnat0d580581995-07-20 02:43:20 -05003878 }
3879 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
3880 dither_lookup && row_info->bit_depth == 8)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003881 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003882 sp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003883 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003884 {
3885 *sp = dither_lookup[*sp];
3886 }
3887 }
3888 }
3889}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003890#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003891
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003892#ifdef PNG_FLOATING_POINT_SUPPORTED
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003893#if defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003894static int png_gamma_shift[] =
3895 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
3896
Andreas Dilger47a0c421997-05-16 02:46:07 -05003897/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003898 * tables, we don't make a full table if we are reducing to 8-bit in
3899 * the future. Note also how the gamma_16 tables are segmented so that
3900 * we don't need to allocate > 64K chunks for a full 16-bit table.
3901 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003902void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003903png_build_gamma_table(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05003904{
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003905 png_debug(1, "in png_build_gamma_table\n");
3906 if(png_ptr->gamma != 0.0)
3907 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003908 if (png_ptr->bit_depth <= 8)
3909 {
3910 int i;
3911 double g;
3912
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003913 if (png_ptr->screen_gamma > .000001)
3914 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3915 else
3916 g = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003917
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003918 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003919 (png_uint_32)256);
3920
3921 for (i = 0; i < 256; i++)
3922 {
3923 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
3924 g) * 255.0 + .5);
3925 }
3926
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003927#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3928 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003929 if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -05003930 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003931
Guy Schalnat0d580581995-07-20 02:43:20 -05003932 g = 1.0 / (png_ptr->gamma);
3933
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003934 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003935 (png_uint_32)256);
3936
3937 for (i = 0; i < 256; i++)
3938 {
3939 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
3940 g) * 255.0 + .5);
3941 }
3942
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003943
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003944 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003945 (png_uint_32)256);
3946
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003947 if(png_ptr->screen_gamma > 0.000001)
3948 g = 1.0 / png_ptr->screen_gamma;
3949 else
3950 g = png_ptr->gamma; /* probably doing rgb_to_gray */
3951
Guy Schalnat0d580581995-07-20 02:43:20 -05003952 for (i = 0; i < 256; i++)
3953 {
3954 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
3955 g) * 255.0 + .5);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003956
Guy Schalnat0d580581995-07-20 02:43:20 -05003957 }
3958 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003959#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003960 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003961 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003962 {
3963 double g;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003964 int i, j, shift, num;
3965 int sig_bit;
3966 png_uint_32 ig;
Guy Schalnat0d580581995-07-20 02:43:20 -05003967
3968 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003969 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003970 sig_bit = (int)png_ptr->sig_bit.red;
3971 if ((int)png_ptr->sig_bit.green > sig_bit)
3972 sig_bit = png_ptr->sig_bit.green;
3973 if ((int)png_ptr->sig_bit.blue > sig_bit)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003974 sig_bit = png_ptr->sig_bit.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003975 }
3976 else
3977 {
3978 sig_bit = (int)png_ptr->sig_bit.gray;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003979 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003980
3981 if (sig_bit > 0)
3982 shift = 16 - sig_bit;
3983 else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003984 shift = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003985
3986 if (png_ptr->transformations & PNG_16_TO_8)
3987 {
3988 if (shift < (16 - PNG_MAX_GAMMA_8))
3989 shift = (16 - PNG_MAX_GAMMA_8);
3990 }
3991
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003992 if (shift > 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003993 shift = 8;
3994 if (shift < 0)
3995 shift = 0;
3996
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003997 png_ptr->gamma_shift = (png_byte)shift;
Guy Schalnat0d580581995-07-20 02:43:20 -05003998
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003999 num = (1 << (8 - shift));
Guy Schalnat0d580581995-07-20 02:43:20 -05004000
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004001 if (png_ptr->screen_gamma > .000001)
4002 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4003 else
4004 g = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -05004005
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004006 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05004007 (png_uint_32)(num * png_sizeof (png_uint_16p)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004008
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004009 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004010 {
4011 double fin, fout;
4012 png_uint_32 last, max;
Guy Schalnat0d580581995-07-20 02:43:20 -05004013
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004014 for (i = 0; i < num; i++)
4015 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004016 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05004017 (png_uint_32)(256 * png_sizeof (png_uint_16)));
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004018 }
Guy Schalnat0d580581995-07-20 02:43:20 -05004019
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004020 g = 1.0 / g;
4021 last = 0;
4022 for (i = 0; i < 256; i++)
4023 {
4024 fout = ((double)i + 0.5) / 256.0;
4025 fin = pow(fout, g);
4026 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
4027 while (last <= max)
4028 {
4029 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4030 [(int)(last >> (8 - shift))] = (png_uint_16)(
4031 (png_uint_16)i | ((png_uint_16)i << 8));
4032 last++;
4033 }
4034 }
4035 while (last < ((png_uint_32)num << 8))
4036 {
4037 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
Andreas Dilger47a0c421997-05-16 02:46:07 -05004038 [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004039 last++;
Guy Schalnat6d764711995-12-19 03:22:19 -06004040 }
Guy Schalnat0d580581995-07-20 02:43:20 -05004041 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004042 else
4043 {
4044 for (i = 0; i < num; i++)
4045 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004046 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05004047 (png_uint_32)(256 * png_sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004048
Andreas Dilger47a0c421997-05-16 02:46:07 -05004049 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004050 for (j = 0; j < 256; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05004051 {
4052 png_ptr->gamma_16_table[i][j] =
4053 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4054 65535.0, g) * 65535.0 + .5);
4055 }
4056 }
4057 }
4058
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004059#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4060 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4061 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -05004062 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004063
Guy Schalnat0d580581995-07-20 02:43:20 -05004064 g = 1.0 / (png_ptr->gamma);
4065
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004066 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05004067 (png_uint_32)(num * png_sizeof (png_uint_16p )));
Guy Schalnat0d580581995-07-20 02:43:20 -05004068
4069 for (i = 0; i < num; i++)
4070 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004071 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05004072 (png_uint_32)(256 * png_sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004073
4074 ig = (((png_uint_32)i *
4075 (png_uint_32)png_gamma_shift[shift]) >> 4);
4076 for (j = 0; j < 256; j++)
4077 {
4078 png_ptr->gamma_16_to_1[i][j] =
4079 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4080 65535.0, g) * 65535.0 + .5);
4081 }
4082 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004083
4084 if(png_ptr->screen_gamma > 0.000001)
4085 g = 1.0 / png_ptr->screen_gamma;
4086 else
4087 g = png_ptr->gamma; /* probably doing rgb_to_gray */
Guy Schalnat0d580581995-07-20 02:43:20 -05004088
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004089 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05004090 (png_uint_32)(num * png_sizeof (png_uint_16p)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004091
4092 for (i = 0; i < num; i++)
4093 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004094 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05004095 (png_uint_32)(256 * png_sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004096
4097 ig = (((png_uint_32)i *
4098 (png_uint_32)png_gamma_shift[shift]) >> 4);
4099 for (j = 0; j < 256; j++)
4100 {
4101 png_ptr->gamma_16_from_1[i][j] =
4102 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4103 65535.0, g) * 65535.0 + .5);
4104 }
4105 }
4106 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004107#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05004108 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004109 }
Guy Schalnat0d580581995-07-20 02:43:20 -05004110}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05004111#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06004112/* To do: install integer version of png_build_gamma_table here */
4113#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -05004114
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -06004115#if defined(PNG_MNG_FEATURES_SUPPORTED)
4116/* undoes intrapixel differencing */
4117void /* PRIVATE */
4118png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4119{
4120 png_debug(1, "in png_do_read_intrapixel\n");
4121 if (
4122#if defined(PNG_USELESS_TESTS_SUPPORTED)
4123 row != NULL && row_info != NULL &&
4124#endif
4125 (row_info->color_type & PNG_COLOR_MASK_COLOR))
4126 {
4127 int bytes_per_pixel;
4128 png_uint_32 row_width = row_info->width;
4129 if (row_info->bit_depth == 8)
4130 {
4131 png_bytep rp;
4132 png_uint_32 i;
4133
4134 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4135 bytes_per_pixel = 3;
4136 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4137 bytes_per_pixel = 4;
4138 else
4139 return;
4140
4141 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4142 {
4143 *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
4144 *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
4145 }
4146 }
4147 else if (row_info->bit_depth == 16)
4148 {
4149 png_bytep rp;
4150 png_uint_32 i;
4151
4152 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4153 bytes_per_pixel = 6;
4154 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4155 bytes_per_pixel = 8;
4156 else
4157 return;
4158
4159 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4160 {
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05004161 png_uint_32 s0 = (*(rp ) << 8) | *(rp+1);
4162 png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3);
4163 png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5);
4164 png_uint_32 red = (png_uint_32)((s0+s1+65536L) & 0xffffL);
4165 png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL);
4166 *(rp ) = (png_byte)((red >> 8) & 0xff);
4167 *(rp+1) = (png_byte)(red & 0xff);
4168 *(rp+4) = (png_byte)((blue >> 8) & 0xff);
4169 *(rp+5) = (png_byte)(blue & 0xff);
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -06004170 }
4171 }
4172 }
4173}
4174#endif /* PNG_MNG_FEATURES_SUPPORTED */