blob: f0cc8bde981108d3e8c66f6de7fa35b27e88a39e [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-Pehrsond1e8c862002-06-20 06:54:34 -05004 * libpng 1.2.4beta2 - June 20, 2002
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * For conditions of distribution and use, see copyright notice in png.h
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -06006 * Copyright (c) 1998-2002 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-Pehrson1d963611998-05-02 12:52:25 -050088 png_memcpy(&(png_ptr->background), background_color, sizeof(png_color_16));
Guy Schalnat51f0eb41995-09-26 05:22:39 -050089 png_ptr->background_gamma = (float)background_gamma;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060090 png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
Guy Schalnate5a37791996-06-05 15:50:50 -050091 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050092
93 /* Note: if need_expand is set and color_type is either RGB or RGB_ALPHA
94 * (in which case need_expand is superfluous anyway), the background color
95 * might actually be gray yet not be flagged as such. This is not a problem
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -060096 * for the current code, which uses PNG_BACKGROUND_IS_GRAY only to
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050097 * decide when to do the png_do_gray_to_rgb() transformation.
98 */
99 if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
100 (!need_expand && background_color->red == background_color->green &&
101 background_color->red == background_color->blue))
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600102 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
Guy Schalnat0d580581995-07-20 02:43:20 -0500103}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500104#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500105
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500106#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500107/* strip 16 bit depth files to 8 bit depth */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500108void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600109png_set_strip_16(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500110{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500111 png_debug(1, "in png_set_strip_16\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500112 png_ptr->transformations |= PNG_16_TO_8;
113}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500114#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500115
Andreas Dilger47a0c421997-05-16 02:46:07 -0500116#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500117void PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -0500118png_set_strip_alpha(png_structp png_ptr)
119{
120 png_debug(1, "in png_set_strip_alpha\n");
121 png_ptr->transformations |= PNG_STRIP_ALPHA;
122}
123#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500124
Andreas Dilger47a0c421997-05-16 02:46:07 -0500125#if defined(PNG_READ_DITHER_SUPPORTED)
126/* Dither file to 8 bit. Supply a palette, the current number
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600127 * of elements in the palette, the maximum number of elements
128 * allowed, and a histogram if possible. If the current number
129 * of colors is greater then the maximum number, the palette will be
130 * modified to fit in the maximum number. "full_dither" indicates
131 * whether we need a dithering cube set up for RGB images, or if we
132 * simply are reducing the number of colors in a paletted image.
133 */
Guy Schalnat6d764711995-12-19 03:22:19 -0600134
135typedef struct png_dsort_struct
Guy Schalnat0d580581995-07-20 02:43:20 -0500136{
Guy Schalnat6d764711995-12-19 03:22:19 -0600137 struct png_dsort_struct FAR * next;
Guy Schalnat0d580581995-07-20 02:43:20 -0500138 png_byte left;
139 png_byte right;
Guy Schalnat6d764711995-12-19 03:22:19 -0600140} png_dsort;
141typedef png_dsort FAR * png_dsortp;
142typedef png_dsort FAR * FAR * png_dsortpp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500143
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500144void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600145png_set_dither(png_structp png_ptr, png_colorp palette,
146 int num_palette, int maximum_colors, png_uint_16p histogram,
Guy Schalnat0d580581995-07-20 02:43:20 -0500147 int full_dither)
148{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500149 png_debug(1, "in png_set_dither\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500150 png_ptr->transformations |= PNG_DITHER;
151
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600152 if (!full_dither)
Guy Schalnat0d580581995-07-20 02:43:20 -0500153 {
154 int i;
155
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600156 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600157 (png_uint_32)(num_palette * sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500158 for (i = 0; i < num_palette; i++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600159 png_ptr->dither_index[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500160 }
161
162 if (num_palette > maximum_colors)
163 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500164 if (histogram != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500165 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500166 /* This is easy enough, just throw out the least used colors.
167 Perhaps not the best solution, but good enough. */
Guy Schalnat0d580581995-07-20 02:43:20 -0500168
169 int i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500170
171 /* initialize an array to sort colors */
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500172 png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
173 (png_uint_32)(num_palette * sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500174
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500175 /* initialize the dither_sort array */
Guy Schalnat0d580581995-07-20 02:43:20 -0500176 for (i = 0; i < num_palette; i++)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500177 png_ptr->dither_sort[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500178
Andreas Dilger47a0c421997-05-16 02:46:07 -0500179 /* Find the least used palette entries by starting a
Guy Schalnat0d580581995-07-20 02:43:20 -0500180 bubble sort, and running it until we have sorted
181 out enough colors. Note that we don't care about
182 sorting all the colors, just finding which are
183 least used. */
184
185 for (i = num_palette - 1; i >= maximum_colors; i--)
186 {
187 int done; /* to stop early if the list is pre-sorted */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600188 int j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500189
190 done = 1;
191 for (j = 0; j < i; j++)
192 {
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500193 if (histogram[png_ptr->dither_sort[j]]
194 < histogram[png_ptr->dither_sort[j + 1]])
Guy Schalnat0d580581995-07-20 02:43:20 -0500195 {
196 png_byte t;
197
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500198 t = png_ptr->dither_sort[j];
199 png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
200 png_ptr->dither_sort[j + 1] = t;
Guy Schalnat0d580581995-07-20 02:43:20 -0500201 done = 0;
202 }
203 }
204 if (done)
205 break;
206 }
207
208 /* swap the palette around, and set up a table, if necessary */
209 if (full_dither)
210 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500211 int j = num_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500212
213 /* put all the useful colors within the max, but don't
214 move the others */
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500215 for (i = 0; i < maximum_colors; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500216 {
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500217 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500218 {
219 do
220 j--;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500221 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
Guy Schalnat0d580581995-07-20 02:43:20 -0500222 palette[i] = palette[j];
223 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600224 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500225 }
226 else
227 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500228 int j = num_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500229
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600230 /* move all the used colors inside the max limit, and
Guy Schalnat0d580581995-07-20 02:43:20 -0500231 develop a translation table */
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500232 for (i = 0; i < maximum_colors; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500233 {
234 /* only move the colors we need to */
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500235 if ((int)png_ptr->dither_sort[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500236 {
237 png_color tmp_color;
238
239 do
240 j--;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500241 while ((int)png_ptr->dither_sort[j] >= maximum_colors);
Guy Schalnat0d580581995-07-20 02:43:20 -0500242
243 tmp_color = palette[j];
244 palette[j] = palette[i];
245 palette[i] = tmp_color;
246 /* indicate where the color went */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600247 png_ptr->dither_index[j] = (png_byte)i;
248 png_ptr->dither_index[i] = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500249 }
250 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500251
252 /* find closest color for those colors we are not using */
Guy Schalnat0d580581995-07-20 02:43:20 -0500253 for (i = 0; i < num_palette; i++)
254 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600255 if ((int)png_ptr->dither_index[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500256 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500257 int min_d, k, min_k, d_index;
Guy Schalnat0d580581995-07-20 02:43:20 -0500258
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600259 /* find the closest color to one we threw out */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500260 d_index = png_ptr->dither_index[i];
261 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
262 for (k = 1, min_k = 0; k < maximum_colors; k++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500263 {
264 int d;
265
Andreas Dilger47a0c421997-05-16 02:46:07 -0500266 d = PNG_COLOR_DIST(palette[d_index], palette[k]);
Guy Schalnat0d580581995-07-20 02:43:20 -0500267
268 if (d < min_d)
269 {
270 min_d = d;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500271 min_k = k;
Guy Schalnat0d580581995-07-20 02:43:20 -0500272 }
273 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600274 /* point to closest color */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500275 png_ptr->dither_index[i] = (png_byte)min_k;
Guy Schalnat0d580581995-07-20 02:43:20 -0500276 }
277 }
278 }
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500279 png_free(png_ptr, png_ptr->dither_sort);
280 png_ptr->dither_sort=NULL;
Guy Schalnat0d580581995-07-20 02:43:20 -0500281 }
282 else
283 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500284 /* This is much harder to do simply (and quickly). Perhaps
Guy Schalnat0d580581995-07-20 02:43:20 -0500285 we need to go through a median cut routine, but those
286 don't always behave themselves with only a few colors
287 as input. So we will just find the closest two colors,
288 and throw out one of them (chosen somewhat randomly).
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600289 [We don't understand this at all, so if someone wants to
290 work on improving it, be our guest - AED, GRP]
Guy Schalnat0d580581995-07-20 02:43:20 -0500291 */
292 int i;
293 int max_d;
294 int num_new_palette;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500295 png_dsortp t;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600296 png_dsortpp hash;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500297
298 t=NULL;
Guy Schalnat0d580581995-07-20 02:43:20 -0500299
300 /* initialize palette index arrays */
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500301 png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600302 (png_uint_32)(num_palette * sizeof (png_byte)));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500303 png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600304 (png_uint_32)(num_palette * sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500305
306 /* initialize the sort array */
307 for (i = 0; i < num_palette; i++)
308 {
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500309 png_ptr->index_to_palette[i] = (png_byte)i;
310 png_ptr->palette_to_index[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500311 }
312
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600313 hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600314 sizeof (png_dsortp)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500315 for (i = 0; i < 769; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500316 hash[i] = NULL;
Guy Schalnat6d764711995-12-19 03:22:19 -0600317/* png_memset(hash, 0, 769 * sizeof (png_dsortp)); */
Guy Schalnat0d580581995-07-20 02:43:20 -0500318
319 num_new_palette = num_palette;
320
321 /* initial wild guess at how far apart the farthest pixel
322 pair we will be eliminating will be. Larger
323 numbers mean more areas will be allocated, Smaller
324 numbers run the risk of not saving enough data, and
325 having to do this all over again.
326
327 I have not done extensive checking on this number.
328 */
329 max_d = 96;
330
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600331 while (num_new_palette > maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500332 {
333 for (i = 0; i < num_new_palette - 1; i++)
334 {
335 int j;
336
337 for (j = i + 1; j < num_new_palette; j++)
338 {
339 int d;
340
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600341 d = PNG_COLOR_DIST(palette[i], palette[j]);
Guy Schalnat0d580581995-07-20 02:43:20 -0500342
343 if (d <= max_d)
344 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500345
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500346 t = (png_dsortp)png_malloc_warn(png_ptr,
347 (png_uint_32)(sizeof(png_dsort)));
348 if (t == NULL)
349 break;
Guy Schalnat0d580581995-07-20 02:43:20 -0500350 t->next = hash[d];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600351 t->left = (png_byte)i;
352 t->right = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500353 hash[d] = t;
354 }
355 }
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500356 if (t == NULL)
357 break;
Guy Schalnat0d580581995-07-20 02:43:20 -0500358 }
359
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500360 if (t != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500361 for (i = 0; i <= max_d; i++)
362 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500363 if (hash[i] != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500364 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600365 png_dsortp p;
Guy Schalnat0d580581995-07-20 02:43:20 -0500366
367 for (p = hash[i]; p; p = p->next)
368 {
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500369 if ((int)png_ptr->index_to_palette[p->left]
370 < num_new_palette &&
371 (int)png_ptr->index_to_palette[p->right]
372 < num_new_palette)
Guy Schalnat0d580581995-07-20 02:43:20 -0500373 {
374 int j, next_j;
375
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600376 if (num_new_palette & 0x01)
Guy Schalnat0d580581995-07-20 02:43:20 -0500377 {
378 j = p->left;
379 next_j = p->right;
380 }
381 else
382 {
383 j = p->right;
384 next_j = p->left;
385 }
386
387 num_new_palette--;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500388 palette[png_ptr->index_to_palette[j]]
389 = palette[num_new_palette];
Guy Schalnat0d580581995-07-20 02:43:20 -0500390 if (!full_dither)
391 {
392 int k;
393
394 for (k = 0; k < num_palette; k++)
395 {
396 if (png_ptr->dither_index[k] ==
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500397 png_ptr->index_to_palette[j])
Guy Schalnat0d580581995-07-20 02:43:20 -0500398 png_ptr->dither_index[k] =
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500399 png_ptr->index_to_palette[next_j];
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600400 if ((int)png_ptr->dither_index[k] ==
Guy Schalnat0d580581995-07-20 02:43:20 -0500401 num_new_palette)
402 png_ptr->dither_index[k] =
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500403 png_ptr->index_to_palette[j];
Guy Schalnat0d580581995-07-20 02:43:20 -0500404 }
405 }
406
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500407 png_ptr->index_to_palette[png_ptr->palette_to_index
408 [num_new_palette]] = png_ptr->index_to_palette[j];
409 png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
410 = png_ptr->palette_to_index[num_new_palette];
Guy Schalnat0d580581995-07-20 02:43:20 -0500411
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500412 png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
413 png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500414 }
415 if (num_new_palette <= maximum_colors)
416 break;
417 }
418 if (num_new_palette <= maximum_colors)
419 break;
420 }
421 }
422
423 for (i = 0; i < 769; i++)
424 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500425 if (hash[i] != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500426 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500427 png_dsortp p = hash[i];
Guy Schalnat0d580581995-07-20 02:43:20 -0500428 while (p)
429 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500430 t = p->next;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600431 png_free(png_ptr, p);
Guy Schalnat0d580581995-07-20 02:43:20 -0500432 p = t;
433 }
434 }
435 hash[i] = 0;
436 }
437 max_d += 96;
438 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600439 png_free(png_ptr, hash);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500440 png_free(png_ptr, png_ptr->palette_to_index);
441 png_free(png_ptr, png_ptr->index_to_palette);
442 png_ptr->palette_to_index=NULL;
443 png_ptr->index_to_palette=NULL;
Guy Schalnat0d580581995-07-20 02:43:20 -0500444 }
445 num_palette = maximum_colors;
446 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500447 if (png_ptr->palette == NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600448 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500449 png_ptr->palette = palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500450 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600451 png_ptr->num_palette = (png_uint_16)num_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500452
453 if (full_dither)
454 {
455 int i;
Guy Schalnat6d764711995-12-19 03:22:19 -0600456 png_bytep distance;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500457 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600458 PNG_DITHER_BLUE_BITS;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500459 int num_red = (1 << PNG_DITHER_RED_BITS);
460 int num_green = (1 << PNG_DITHER_GREEN_BITS);
461 int num_blue = (1 << PNG_DITHER_BLUE_BITS);
462 png_size_t num_entries = ((png_size_t)1 << total_bits);
Guy Schalnat0d580581995-07-20 02:43:20 -0500463
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600464 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600465 (png_uint_32)(num_entries * sizeof (png_byte)));
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500466
467 png_memset(png_ptr->palette_lookup, 0, num_entries * sizeof (png_byte));
Guy Schalnat0d580581995-07-20 02:43:20 -0500468
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600469 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
470 sizeof(png_byte)));
Glenn Randers-Pehrsone1eff582001-04-14 20:15:41 -0500471
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500472 png_memset(distance, 0xff, num_entries * sizeof(png_byte));
473
474 for (i = 0; i < num_palette; i++)
475 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500476 int ir, ig, ib;
477 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
478 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
479 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
Guy Schalnat0d580581995-07-20 02:43:20 -0500480
481 for (ir = 0; ir < num_red; ir++)
482 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500483 int dr = abs(ir - r);
484 int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
Guy Schalnat0d580581995-07-20 02:43:20 -0500485
Guy Schalnat0d580581995-07-20 02:43:20 -0500486 for (ig = 0; ig < num_green; ig++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600487 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500488 int dg = abs(ig - g);
489 int dt = dr + dg;
490 int dm = ((dr > dg) ? dr : dg);
491 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
Guy Schalnat0d580581995-07-20 02:43:20 -0500492
Guy Schalnat0d580581995-07-20 02:43:20 -0500493 for (ib = 0; ib < num_blue; ib++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600494 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500495 int d_index = index_g | ib;
496 int db = abs(ib - b);
497 int dmax = ((dm > db) ? dm : db);
498 int d = dmax + dt + db;
Guy Schalnat0d580581995-07-20 02:43:20 -0500499
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600500 if (d < (int)distance[d_index])
Guy Schalnat0d580581995-07-20 02:43:20 -0500501 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500502 distance[d_index] = (png_byte)d;
503 png_ptr->palette_lookup[d_index] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500504 }
505 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500506 }
507 }
508 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500509
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600510 png_free(png_ptr, distance);
Guy Schalnat0d580581995-07-20 02:43:20 -0500511 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500512}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500513#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500514
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600515#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600516/* Transform the image from the file_gamma to the screen_gamma. We
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600517 * only do transformations on images where the file_gamma and screen_gamma
518 * are not close reciprocals, otherwise it slows things down slightly, and
519 * also needlessly introduces small errors.
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -0600520 *
521 * We will turn off gamma transformation later if no semitransparent entries
522 * are present in the tRNS array for palette images. We can't do it here
523 * because we don't necessarily have the tRNS chunk yet.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600524 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500525void PNGAPI
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600526png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
Guy Schalnat0d580581995-07-20 02:43:20 -0500527{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500528 png_debug(1, "in png_set_gamma\n");
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -0600529 if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
530 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
531 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
532 png_ptr->transformations |= PNG_GAMMA;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500533 png_ptr->gamma = (float)file_gamma;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600534 png_ptr->screen_gamma = (float)scrn_gamma;
Guy Schalnat0d580581995-07-20 02:43:20 -0500535}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500536#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500537
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500538#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -0500539/* Expand paletted images to RGB, expand grayscale images of
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500540 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600541 * to alpha channels.
542 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500543void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600544png_set_expand(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500545{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500546 png_debug(1, "in png_set_expand\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500547 png_ptr->transformations |= PNG_EXPAND;
548}
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500549
550/* GRR 19990627: the following three functions currently are identical
551 * to png_set_expand(). However, it is entirely reasonable that someone
552 * might wish to expand an indexed image to RGB but *not* expand a single,
553 * fully transparent palette entry to a full alpha channel--perhaps instead
554 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
555 * the transparent color with a particular RGB value, or drop tRNS entirely.
556 * IOW, a future version of the library may make the transformations flag
557 * a bit more fine-grained, with separate bits for each of these three
558 * functions.
559 *
560 * More to the point, these functions make it obvious what libpng will be
561 * doing, whereas "expand" can (and does) mean any number of things.
562 */
563
564/* Expand paletted images to RGB. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500565void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500566png_set_palette_to_rgb(png_structp png_ptr)
567{
568 png_debug(1, "in png_set_expand\n");
569 png_ptr->transformations |= PNG_EXPAND;
570}
571
572/* Expand grayscale images of less than 8-bit depth to 8 bits. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500573void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500574png_set_gray_1_2_4_to_8(png_structp png_ptr)
575{
576 png_debug(1, "in png_set_expand\n");
577 png_ptr->transformations |= PNG_EXPAND;
578}
579
580/* Expand tRNS chunks to alpha channels. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500581void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500582png_set_tRNS_to_alpha(png_structp png_ptr)
583{
584 png_debug(1, "in png_set_expand\n");
585 png_ptr->transformations |= PNG_EXPAND;
586}
587#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
Guy Schalnat0d580581995-07-20 02:43:20 -0500588
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500589#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500590void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600591png_set_gray_to_rgb(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500592{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500593 png_debug(1, "in png_set_gray_to_rgb\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500594 png_ptr->transformations |= PNG_GRAY_TO_RGB;
595}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500596#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500597
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600598#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
599#if defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600600/* Convert a RGB image to a grayscale of the same width. This allows us,
601 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600602 */
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600603
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500604void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500605png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600606 double green)
607{
608 int red_fixed = (int)((float)red*100000.0 + 0.5);
609 int green_fixed = (int)((float)green*100000.0 + 0.5);
610 png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
611}
612#endif
613
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500614void PNGAPI
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600615png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
616 png_fixed_point red, png_fixed_point green)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600617{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500618 png_debug(1, "in png_set_rgb_to_gray\n");
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600619 switch(error_action)
620 {
621 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
622 break;
623 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
624 break;
625 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
626 }
627 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
628#if defined(PNG_READ_EXPAND_SUPPORTED)
629 png_ptr->transformations |= PNG_EXPAND;
630#else
631 {
632 png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
633 png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
634 }
635#endif
636 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600637 png_uint_16 red_int, green_int;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600638 if(red < 0 || green < 0)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600639 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600640 red_int = 6968; /* .212671 * 32768 + .5 */
641 green_int = 23434; /* .715160 * 32768 + .5 */
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600642 }
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600643 else if(red + green < 100000L)
644 {
645 red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
646 green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
647 }
648 else
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600649 {
650 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600651 red_int = 6968;
652 green_int = 23434;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600653 }
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600654 png_ptr->rgb_to_gray_red_coeff = red_int;
655 png_ptr->rgb_to_gray_green_coeff = green_int;
656 png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600657 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600658}
659#endif
660
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500661#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
662 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
663 defined(PNG_LEGACY_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500664void PNGAPI
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600665png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
666 read_user_transform_fn)
667{
668 png_debug(1, "in png_set_read_user_transform_fn\n");
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500669#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600670 png_ptr->transformations |= PNG_USER_TRANSFORM;
671 png_ptr->read_user_transform_fn = read_user_transform_fn;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500672#endif
673#ifdef PNG_LEGACY_SUPPORTED
674 if(read_user_transform_fn)
675 png_warning(png_ptr,
676 "This version of libpng does not support user transforms");
677#endif
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600678}
679#endif
680
Andreas Dilger47a0c421997-05-16 02:46:07 -0500681/* Initialize everything needed for the read. This includes modifying
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600682 * the palette.
683 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500684void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600685png_init_read_transformations(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500686{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500687 png_debug(1, "in png_init_read_transformations\n");
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500688#if defined(PNG_USELESS_TESTS_SUPPORTED)
689 if(png_ptr != NULL)
690#endif
691 {
692#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
693 || defined(PNG_READ_GAMMA_SUPPORTED)
694 int color_type = png_ptr->color_type;
695#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500696
Guy Schalnate5a37791996-06-05 15:50:50 -0500697#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600698 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
699 (png_ptr->transformations & PNG_EXPAND))
Guy Schalnat0d580581995-07-20 02:43:20 -0500700 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500701 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
Guy Schalnat0d580581995-07-20 02:43:20 -0500702 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500703 /* expand background chunk. */
Guy Schalnat0d580581995-07-20 02:43:20 -0500704 switch (png_ptr->bit_depth)
705 {
706 case 1:
Guy Schalnate5a37791996-06-05 15:50:50 -0500707 png_ptr->background.gray *= (png_uint_16)0xff;
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600708 png_ptr->background.red = png_ptr->background.green
709 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500710 break;
711 case 2:
Guy Schalnate5a37791996-06-05 15:50:50 -0500712 png_ptr->background.gray *= (png_uint_16)0x55;
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600713 png_ptr->background.red = png_ptr->background.green
714 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500715 break;
716 case 4:
Guy Schalnate5a37791996-06-05 15:50:50 -0500717 png_ptr->background.gray *= (png_uint_16)0x11;
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600718 png_ptr->background.red = png_ptr->background.green
719 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnate5a37791996-06-05 15:50:50 -0500720 break;
721 case 8:
722 case 16:
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600723 png_ptr->background.red = png_ptr->background.green
724 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500725 break;
726 }
727 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500728 else if (color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -0500729 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500730 png_ptr->background.red =
Guy Schalnat0d580581995-07-20 02:43:20 -0500731 png_ptr->palette[png_ptr->background.index].red;
732 png_ptr->background.green =
733 png_ptr->palette[png_ptr->background.index].green;
Guy Schalnate5a37791996-06-05 15:50:50 -0500734 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -0500735 png_ptr->palette[png_ptr->background.index].blue;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600736
737#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
738 if (png_ptr->transformations & PNG_INVERT_ALPHA)
739 {
740#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600741 if (!(png_ptr->transformations & PNG_EXPAND))
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600742#endif
743 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600744 /* invert the alpha channel (in tRNS) unless the pixels are
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600745 going to be expanded, in which case leave it for later */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500746 int i,istop;
747 istop=(int)png_ptr->num_trans;
748 for (i=0; i<istop; i++)
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -0500749 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600750 }
751 }
752#endif
753
Guy Schalnat0d580581995-07-20 02:43:20 -0500754 }
755 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500756#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500757
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -0500758#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500759 png_ptr->background_1 = png_ptr->background;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500760#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600761#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -0600762
763 if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
764 && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
765 < PNG_GAMMA_THRESHOLD))
766 {
767 int i,k;
768 k=0;
769 for (i=0; i<png_ptr->num_trans; i++)
770 {
771 if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
772 k=1; /* partial transparency is present */
773 }
774 if (k == 0)
775 png_ptr->transformations &= (~PNG_GAMMA);
776 }
777
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600778 if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -0500779 {
780 png_build_gamma_table(png_ptr);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500781#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnate5a37791996-06-05 15:50:50 -0500782 if (png_ptr->transformations & PNG_BACKGROUND)
Guy Schalnat0d580581995-07-20 02:43:20 -0500783 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500784 if (color_type == PNG_COLOR_TYPE_PALETTE)
785 {
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -0600786 /* could skip if no transparency and
787 */
Guy Schalnate5a37791996-06-05 15:50:50 -0500788 png_color back, back_1;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500789 png_colorp palette = png_ptr->palette;
790 int num_palette = png_ptr->num_palette;
791 int i;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500792 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
793 {
794 back.red = png_ptr->gamma_table[png_ptr->background.red];
795 back.green = png_ptr->gamma_table[png_ptr->background.green];
796 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
Guy Schalnate5a37791996-06-05 15:50:50 -0500797
Andreas Dilger47a0c421997-05-16 02:46:07 -0500798 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
799 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
800 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
801 }
802 else
803 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600804 double g, gs;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500805
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600806 switch (png_ptr->background_gamma_type)
Glenn Randers-Pehrson4922b1b1998-03-08 22:55:17 -0600807 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600808 case PNG_BACKGROUND_GAMMA_SCREEN:
809 g = (png_ptr->screen_gamma);
810 gs = 1.0;
811 break;
812 case PNG_BACKGROUND_GAMMA_FILE:
813 g = 1.0 / (png_ptr->gamma);
814 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
815 break;
816 case PNG_BACKGROUND_GAMMA_UNIQUE:
817 g = 1.0 / (png_ptr->background_gamma);
818 gs = 1.0 / (png_ptr->background_gamma *
819 png_ptr->screen_gamma);
820 break;
821 default:
822 g = 1.0; /* back_1 */
823 gs = 1.0; /* back */
824 }
825
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -0600826 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600827 {
828 back.red = (png_byte)png_ptr->background.red;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500829 back.green = (png_byte)png_ptr->background.green;
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600830 back.blue = (png_byte)png_ptr->background.blue;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500831 }
832 else
833 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600834 back.red = (png_byte)(pow(
835 (double)png_ptr->background.red/255, gs) * 255.0 + .5);
836 back.green = (png_byte)(pow(
837 (double)png_ptr->background.green/255, gs) * 255.0 + .5);
838 back.blue = (png_byte)(pow(
839 (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500840 }
841
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600842 back_1.red = (png_byte)(pow(
843 (double)png_ptr->background.red/255, g) * 255.0 + .5);
844 back_1.green = (png_byte)(pow(
845 (double)png_ptr->background.green/255, g) * 255.0 + .5);
846 back_1.blue = (png_byte)(pow(
847 (double)png_ptr->background.blue/255, g) * 255.0 + .5);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500848 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500849 for (i = 0; i < num_palette; i++)
850 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500851 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
Guy Schalnate5a37791996-06-05 15:50:50 -0500852 {
853 if (png_ptr->trans[i] == 0)
854 {
855 palette[i] = back;
856 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500857 else /* if (png_ptr->trans[i] != 0xff) */
Guy Schalnate5a37791996-06-05 15:50:50 -0500858 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500859 png_byte v, w;
Guy Schalnate5a37791996-06-05 15:50:50 -0500860
861 v = png_ptr->gamma_to_1[palette[i].red];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500862 png_composite(w, v, png_ptr->trans[i], back_1.red);
Guy Schalnate5a37791996-06-05 15:50:50 -0500863 palette[i].red = png_ptr->gamma_from_1[w];
864
865 v = png_ptr->gamma_to_1[palette[i].green];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500866 png_composite(w, v, png_ptr->trans[i], back_1.green);
Guy Schalnate5a37791996-06-05 15:50:50 -0500867 palette[i].green = png_ptr->gamma_from_1[w];
868
869 v = png_ptr->gamma_to_1[palette[i].blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500870 png_composite(w, v, png_ptr->trans[i], back_1.blue);
Guy Schalnate5a37791996-06-05 15:50:50 -0500871 palette[i].blue = png_ptr->gamma_from_1[w];
872 }
873 }
874 else
875 {
876 palette[i].red = png_ptr->gamma_table[palette[i].red];
877 palette[i].green = png_ptr->gamma_table[palette[i].green];
878 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
879 }
880 }
881 }
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500882 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600883 else
884 /* color_type != PNG_COLOR_TYPE_PALETTE */
Guy Schalnat0d580581995-07-20 02:43:20 -0500885 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500886 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
887 double g = 1.0;
888 double gs = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500889
890 switch (png_ptr->background_gamma_type)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600891 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500892 case PNG_BACKGROUND_GAMMA_SCREEN:
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600893 g = (png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500894 gs = 1.0;
895 break;
896 case PNG_BACKGROUND_GAMMA_FILE:
897 g = 1.0 / (png_ptr->gamma);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600898 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500899 break;
900 case PNG_BACKGROUND_GAMMA_UNIQUE:
901 g = 1.0 / (png_ptr->background_gamma);
902 gs = 1.0 / (png_ptr->background_gamma *
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600903 png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500904 break;
905 }
906
Glenn Randers-Pehrson377657d2002-03-08 01:31:27 -0600907 png_ptr->background_1.gray = (png_uint_16)(pow(
908 (double)png_ptr->background.gray / m, g) * m + .5);
909 png_ptr->background.gray = (png_uint_16)(pow(
910 (double)png_ptr->background.gray / m, gs) * m + .5);
911
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600912 if ((png_ptr->background.red != png_ptr->background.green) ||
913 (png_ptr->background.red != png_ptr->background.blue) ||
914 (png_ptr->background.red != png_ptr->background.gray))
Guy Schalnat0d580581995-07-20 02:43:20 -0500915 {
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600916 /* RGB or RGBA with color background */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600917 png_ptr->background_1.red = (png_uint_16)(pow(
Guy Schalnat0d580581995-07-20 02:43:20 -0500918 (double)png_ptr->background.red / m, g) * m + .5);
919 png_ptr->background_1.green = (png_uint_16)(pow(
920 (double)png_ptr->background.green / m, g) * m + .5);
921 png_ptr->background_1.blue = (png_uint_16)(pow(
922 (double)png_ptr->background.blue / m, g) * m + .5);
923 png_ptr->background.red = (png_uint_16)(pow(
924 (double)png_ptr->background.red / m, gs) * m + .5);
925 png_ptr->background.green = (png_uint_16)(pow(
926 (double)png_ptr->background.green / m, gs) * m + .5);
927 png_ptr->background.blue = (png_uint_16)(pow(
928 (double)png_ptr->background.blue / m, gs) * m + .5);
929 }
930 else
931 {
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600932 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
933 png_ptr->background_1.red = png_ptr->background_1.green
934 = png_ptr->background_1.blue = png_ptr->background_1.gray;
935 png_ptr->background.red = png_ptr->background.green
936 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500937 }
938 }
939 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500940 else
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600941 /* transformation does not include PNG_BACKGROUND */
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -0500942#endif /* PNG_READ_BACKGROUND_SUPPORTED */
Guy Schalnate5a37791996-06-05 15:50:50 -0500943 if (color_type == PNG_COLOR_TYPE_PALETTE)
944 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500945 png_colorp palette = png_ptr->palette;
946 int num_palette = png_ptr->num_palette;
947 int i;
Guy Schalnate5a37791996-06-05 15:50:50 -0500948
949 for (i = 0; i < num_palette; i++)
950 {
951 palette[i].red = png_ptr->gamma_table[palette[i].red];
952 palette[i].green = png_ptr->gamma_table[palette[i].green];
953 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
954 }
955 }
956 }
957#if defined(PNG_READ_BACKGROUND_SUPPORTED)
958 else
959#endif
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -0500960#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
Guy Schalnate5a37791996-06-05 15:50:50 -0500961#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600962 /* No GAMMA transformation */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600963 if ((png_ptr->transformations & PNG_BACKGROUND) &&
964 (color_type == PNG_COLOR_TYPE_PALETTE))
Guy Schalnate5a37791996-06-05 15:50:50 -0500965 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500966 int i;
967 int istop = (int)png_ptr->num_trans;
Guy Schalnate5a37791996-06-05 15:50:50 -0500968 png_color back;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500969 png_colorp palette = png_ptr->palette;
Guy Schalnate5a37791996-06-05 15:50:50 -0500970
Guy Schalnate5a37791996-06-05 15:50:50 -0500971 back.red = (png_byte)png_ptr->background.red;
972 back.green = (png_byte)png_ptr->background.green;
973 back.blue = (png_byte)png_ptr->background.blue;
974
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500975 for (i = 0; i < istop; i++)
Guy Schalnate5a37791996-06-05 15:50:50 -0500976 {
977 if (png_ptr->trans[i] == 0)
978 {
979 palette[i] = back;
980 }
981 else if (png_ptr->trans[i] != 0xff)
982 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500983 /* The png_composite() macro is defined in png.h */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500984 png_composite(palette[i].red, palette[i].red,
985 png_ptr->trans[i], back.red);
986 png_composite(palette[i].green, palette[i].green,
987 png_ptr->trans[i], back.green);
988 png_composite(palette[i].blue, palette[i].blue,
989 png_ptr->trans[i], back.blue);
Guy Schalnate5a37791996-06-05 15:50:50 -0500990 }
991 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500992 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -0500993#endif /* PNG_READ_BACKGROUND_SUPPORTED */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500994
Guy Schalnat6d764711995-12-19 03:22:19 -0600995#if defined(PNG_READ_SHIFT_SUPPORTED)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500996 if ((png_ptr->transformations & PNG_SHIFT) &&
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600997 (color_type == PNG_COLOR_TYPE_PALETTE))
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500998 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500999 png_uint_16 i;
1000 png_uint_16 istop = png_ptr->num_palette;
1001 int sr = 8 - png_ptr->sig_bit.red;
1002 int sg = 8 - png_ptr->sig_bit.green;
1003 int sb = 8 - png_ptr->sig_bit.blue;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001004
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001005 if (sr < 0 || sr > 8)
1006 sr = 0;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001007 if (sg < 0 || sg > 8)
1008 sg = 0;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001009 if (sb < 0 || sb > 8)
1010 sb = 0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001011 for (i = 0; i < istop; i++)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001012 {
1013 png_ptr->palette[i].red >>= sr;
1014 png_ptr->palette[i].green >>= sg;
1015 png_ptr->palette[i].blue >>= sb;
1016 }
1017 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05001018#endif /* PNG_READ_SHIFT_SUPPORTED */
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001019 }
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001020#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1021 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1022 if(png_ptr)
1023 return;
1024#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001025}
1026
Andreas Dilger47a0c421997-05-16 02:46:07 -05001027/* Modify the info structure to reflect the transformations. The
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001028 * info should be updated so a PNG file could be written with it,
1029 * assuming the transformations result in valid PNG data.
1030 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001031void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001032png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001033{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001034 png_debug(1, "in png_read_transform_info\n");
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001035#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001036 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001037 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001038 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1039 {
1040 if (png_ptr->num_trans)
1041 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1042 else
1043 info_ptr->color_type = PNG_COLOR_TYPE_RGB;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001044 info_ptr->bit_depth = 8;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001045 info_ptr->num_trans = 0;
1046 }
1047 else
1048 {
1049 if (png_ptr->num_trans)
1050 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1051 if (info_ptr->bit_depth < 8)
1052 info_ptr->bit_depth = 8;
1053 info_ptr->num_trans = 0;
1054 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001055 }
1056#endif
1057
1058#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1059 if (png_ptr->transformations & PNG_BACKGROUND)
1060 {
1061 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1062 info_ptr->num_trans = 0;
1063 info_ptr->background = png_ptr->background;
1064 }
1065#endif
1066
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001067#if defined(PNG_READ_GAMMA_SUPPORTED)
1068 if (png_ptr->transformations & PNG_GAMMA)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001069 {
1070#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001071 info_ptr->gamma = png_ptr->gamma;
1072#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001073#ifdef PNG_FIXED_POINT_SUPPORTED
1074 info_ptr->int_gamma = png_ptr->int_gamma;
1075#endif
1076 }
1077#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001078
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001079#if defined(PNG_READ_16_TO_8_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001080 if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001081 info_ptr->bit_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001082#endif
1083
1084#if defined(PNG_READ_DITHER_SUPPORTED)
1085 if (png_ptr->transformations & PNG_DITHER)
1086 {
1087 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1088 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1089 png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1090 {
1091 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1092 }
1093 }
1094#endif
1095
1096#if defined(PNG_READ_PACK_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001097 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001098 info_ptr->bit_depth = 8;
1099#endif
1100
1101#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001102 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001103 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1104#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001105
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001106#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1107 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1108 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1109#endif
1110
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001111 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001112 info_ptr->channels = 1;
1113 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1114 info_ptr->channels = 3;
1115 else
1116 info_ptr->channels = 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001117
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001118#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001119 if (png_ptr->transformations & PNG_STRIP_ALPHA)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001120 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001121#endif
1122
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001123 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1124 info_ptr->channels++;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001125
1126#if defined(PNG_READ_FILLER_SUPPORTED)
1127 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001128 if ((png_ptr->transformations & PNG_FILLER) &&
1129 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1130 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001131 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001132 info_ptr->channels++;
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001133#if 0 /* if adding a true alpha channel not just filler */
1134 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1135#endif
1136 }
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001137#endif
1138
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001139#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1140defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001141 if(png_ptr->transformations & PNG_USER_TRANSFORM)
1142 {
1143 if(info_ptr->bit_depth < png_ptr->user_transform_depth)
1144 info_ptr->bit_depth = png_ptr->user_transform_depth;
1145 if(info_ptr->channels < png_ptr->user_transform_channels)
1146 info_ptr->channels = png_ptr->user_transform_channels;
1147 }
1148#endif
1149
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001150 info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1151 info_ptr->bit_depth);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001152 info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3);
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05001153
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001154#if !defined(PNG_READ_EXPAND_SUPPORTED)
1155 if(png_ptr)
1156 return;
1157#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001158}
1159
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001160/* Transform the row. The order of transformations is significant,
1161 * and is very touchy. If you add a transformation, take care to
1162 * decide how it fits in with the other transformations here.
1163 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001164void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001165png_do_read_transformations(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05001166{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001167 png_debug(1, "in png_do_read_transformations\n");
1168#if !defined(PNG_USELESS_TESTS_SUPPORTED)
1169 if (png_ptr->row_buf == NULL)
1170 {
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -05001171#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001172 char msg[50];
1173
1174 sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
1175 png_ptr->pass);
1176 png_error(png_ptr, msg);
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001177#else
1178 png_error(png_ptr, "NULL row buffer");
1179#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001180 }
1181#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001182
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001183#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001184 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05001185 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001186 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1187 {
1188 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1189 png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1190 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001191 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001192 {
1193 if (png_ptr->num_trans)
1194 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1195 &(png_ptr->trans_values));
1196 else
1197 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1198 NULL);
1199 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001200 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001201#endif
1202
1203#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1204 if (png_ptr->transformations & PNG_STRIP_ALPHA)
1205 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1206 PNG_FLAG_FILLER_AFTER);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001207#endif
1208
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001209#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1210 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1211 {
1212 int rgb_error =
1213 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1214 if(rgb_error)
1215 {
1216 png_ptr->rgb_to_gray_status=1;
1217 if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
1218 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1219 if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
1220 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1221 }
1222 }
1223#endif
1224
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001225/*
1226From Andreas Dilger e-mail to png-implement, 26 March 1998:
1227
1228 In most cases, the "simple transparency" should be done prior to doing
1229 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 -06001230 pixel is transparent. You would also need to make sure that the
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001231 transparency information is upgraded to RGB.
1232
1233 To summarize, the current flow is:
1234 - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1235 with background "in place" if transparent,
1236 convert to RGB if necessary
1237 - Gray + alpha -> composite with gray background and remove alpha bytes,
1238 convert to RGB if necessary
1239
1240 To support RGB backgrounds for gray images we need:
1241 - Gray + simple transparency -> convert to RGB + simple transparency, compare
1242 3 or 6 bytes and composite with background
1243 "in place" if transparent (3x compare/pixel
1244 compared to doing composite with gray bkgrnd)
1245 - Gray + alpha -> convert to RGB + alpha, composite with background and
1246 remove alpha bytes (3x float operations/pixel
1247 compared with composite on gray background)
1248
1249 Greg's change will do this. The reason it wasn't done before is for
1250 performance, as this increases the per-pixel operations. If we would check
1251 in advance if the background was gray or RGB, and position the gray-to-RGB
1252 transform appropriately, then it would save a lot of work/time.
1253 */
1254
1255#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1256 /* if gray -> RGB, do so now only if background is non-gray; else do later
1257 * for performance reasons */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001258 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06001259 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001260 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1261#endif
1262
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001263#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001264 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1265 ((png_ptr->num_trans != 0 ) ||
1266 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
Guy Schalnat0d580581995-07-20 02:43:20 -05001267 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05001268 &(png_ptr->trans_values), &(png_ptr->background)
1269#if defined(PNG_READ_GAMMA_SUPPORTED)
1270 , &(png_ptr->background_1),
Guy Schalnat0d580581995-07-20 02:43:20 -05001271 png_ptr->gamma_table, png_ptr->gamma_from_1,
1272 png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1273 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05001274 png_ptr->gamma_shift
1275#endif
1276);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001277#endif
1278
1279#if defined(PNG_READ_GAMMA_SUPPORTED)
1280 if ((png_ptr->transformations & PNG_GAMMA) &&
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001281#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1282 !((png_ptr->transformations & PNG_BACKGROUND) &&
1283 ((png_ptr->num_trans != 0) ||
1284 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1285#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001286 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
Guy Schalnat0d580581995-07-20 02:43:20 -05001287 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1288 png_ptr->gamma_table, png_ptr->gamma_16_table,
1289 png_ptr->gamma_shift);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001290#endif
1291
1292#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001293 if (png_ptr->transformations & PNG_16_TO_8)
1294 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001295#endif
1296
1297#if defined(PNG_READ_DITHER_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001298 if (png_ptr->transformations & PNG_DITHER)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001299 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001300 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1301 png_ptr->palette_lookup, png_ptr->dither_index);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001302 if(png_ptr->row_info.rowbytes == (png_uint_32)0)
1303 png_error(png_ptr, "png_do_dither returned rowbytes=0");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001304 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001305#endif
1306
1307#if defined(PNG_READ_INVERT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001308 if (png_ptr->transformations & PNG_INVERT_MONO)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001309 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001310#endif
1311
1312#if defined(PNG_READ_SHIFT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001313 if (png_ptr->transformations & PNG_SHIFT)
1314 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1315 &(png_ptr->shift));
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001316#endif
1317
1318#if defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001319 if (png_ptr->transformations & PNG_PACK)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001320 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001321#endif
1322
1323#if defined(PNG_READ_BGR_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001324 if (png_ptr->transformations & PNG_BGR)
1325 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001326#endif
1327
Andreas Dilger47a0c421997-05-16 02:46:07 -05001328#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1329 if (png_ptr->transformations & PNG_PACKSWAP)
1330 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1331#endif
1332
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001333#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001334 /* if gray -> RGB, do so now only if we did not do so above */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001335 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1336 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -05001337 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001338#endif
1339
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001340#if defined(PNG_READ_FILLER_SUPPORTED)
1341 if (png_ptr->transformations & PNG_FILLER)
1342 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001343 (png_uint_32)png_ptr->filler, png_ptr->flags);
1344#endif
1345
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001346#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1347 if (png_ptr->transformations & PNG_INVERT_ALPHA)
1348 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1349#endif
1350
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001351#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1352 if (png_ptr->transformations & PNG_SWAP_ALPHA)
1353 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1354#endif
1355
Andreas Dilger47a0c421997-05-16 02:46:07 -05001356#if defined(PNG_READ_SWAP_SUPPORTED)
1357 if (png_ptr->transformations & PNG_SWAP_BYTES)
1358 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001359#endif
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001360
1361#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1362 if (png_ptr->transformations & PNG_USER_TRANSFORM)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001363 {
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001364 if(png_ptr->read_user_transform_fn != NULL)
1365 (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1366 (png_ptr, /* png_ptr */
1367 &(png_ptr->row_info), /* row_info: */
1368 /* png_uint_32 width; width of row */
1369 /* png_uint_32 rowbytes; number of bytes in row */
1370 /* png_byte color_type; color type of pixels */
1371 /* png_byte bit_depth; bit depth of samples */
1372 /* png_byte channels; number of channels (1-4) */
1373 /* png_byte pixel_depth; bits per pixel (depth*channels) */
1374 png_ptr->row_buf + 1); /* start of pixel data for row */
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001375#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001376 if(png_ptr->user_transform_depth)
1377 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1378 if(png_ptr->user_transform_channels)
1379 png_ptr->row_info.channels = png_ptr->user_transform_channels;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001380#endif
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001381 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1382 png_ptr->row_info.channels);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001383 png_ptr->row_info.rowbytes = (png_ptr->row_info.width *
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001384 png_ptr->row_info.pixel_depth+7)>>3;
1385 }
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001386#endif
1387
Guy Schalnat0d580581995-07-20 02:43:20 -05001388}
1389
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001390#if defined(PNG_READ_PACK_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001391/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1392 * without changing the actual values. Thus, if you had a row with
1393 * a bit depth of 1, you would end up with bytes that only contained
1394 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1395 * png_do_shift() after this.
1396 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001397void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001398png_do_unpack(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001399{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001400 png_debug(1, "in png_do_unpack\n");
1401#if defined(PNG_USELESS_TESTS_SUPPORTED)
1402 if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1403#else
1404 if (row_info->bit_depth < 8)
1405#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001406 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001407 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001408 png_uint_32 row_width=row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001409
Guy Schalnat0d580581995-07-20 02:43:20 -05001410 switch (row_info->bit_depth)
1411 {
1412 case 1:
1413 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001414 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1415 png_bytep dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001416 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001417 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001418 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001419 *dp = (png_byte)((*sp >> shift) & 0x01);
Guy Schalnat0d580581995-07-20 02:43:20 -05001420 if (shift == 7)
1421 {
1422 shift = 0;
1423 sp--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001424 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001425 else
1426 shift++;
1427
1428 dp--;
1429 }
1430 break;
1431 }
1432 case 2:
1433 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001434
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001435 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1436 png_bytep dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001437 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001438 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001439 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001440 *dp = (png_byte)((*sp >> shift) & 0x03);
Guy Schalnat0d580581995-07-20 02:43:20 -05001441 if (shift == 6)
1442 {
1443 shift = 0;
1444 sp--;
1445 }
1446 else
1447 shift += 2;
1448
1449 dp--;
1450 }
1451 break;
1452 }
1453 case 4:
1454 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001455 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1456 png_bytep dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001457 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001458 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001459 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001460 *dp = (png_byte)((*sp >> shift) & 0x0f);
Guy Schalnat0d580581995-07-20 02:43:20 -05001461 if (shift == 4)
1462 {
1463 shift = 0;
1464 sp--;
1465 }
1466 else
1467 shift = 4;
1468
1469 dp--;
1470 }
1471 break;
1472 }
1473 }
1474 row_info->bit_depth = 8;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001475 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001476 row_info->rowbytes = row_width * row_info->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -05001477 }
1478}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001479#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001480
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001481#if defined(PNG_READ_SHIFT_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001482/* Reverse the effects of png_do_shift. This routine merely shifts the
1483 * pixels back to their significant bits values. Thus, if you have
1484 * a row of bit depth 8, but only 5 are significant, this will shift
1485 * the values back to 0 through 31.
1486 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001487void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001488png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
Guy Schalnat0d580581995-07-20 02:43:20 -05001489{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001490 png_debug(1, "in png_do_unshift\n");
1491 if (
1492#if defined(PNG_USELESS_TESTS_SUPPORTED)
1493 row != NULL && row_info != NULL && sig_bits != NULL &&
1494#endif
1495 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05001496 {
1497 int shift[4];
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001498 int channels = 0;
1499 int c;
1500 png_uint_16 value = 0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001501 png_uint_32 row_width = row_info->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001502
Guy Schalnat0d580581995-07-20 02:43:20 -05001503 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1504 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001505 shift[channels++] = row_info->bit_depth - sig_bits->red;
1506 shift[channels++] = row_info->bit_depth - sig_bits->green;
1507 shift[channels++] = row_info->bit_depth - sig_bits->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05001508 }
1509 else
1510 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001511 shift[channels++] = row_info->bit_depth - sig_bits->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05001512 }
1513 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1514 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001515 shift[channels++] = row_info->bit_depth - sig_bits->alpha;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001516 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001517
Andreas Dilger47a0c421997-05-16 02:46:07 -05001518 for (c = 0; c < channels; c++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001519 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001520 if (shift[c] <= 0)
1521 shift[c] = 0;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001522 else
1523 value = 1;
1524 }
Guy Schalnat0f716451995-11-28 11:22:13 -06001525
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001526 if (!value)
1527 return;
Guy Schalnat0f716451995-11-28 11:22:13 -06001528
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001529 switch (row_info->bit_depth)
Guy Schalnat0d580581995-07-20 02:43:20 -05001530 {
1531 case 2:
1532 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001533 png_bytep bp;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001534 png_uint_32 i;
1535 png_uint_32 istop = row_info->rowbytes;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001536
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001537 for (bp = row, i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001538 {
1539 *bp >>= 1;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001540 *bp++ &= 0x55;
Guy Schalnat0d580581995-07-20 02:43:20 -05001541 }
1542 break;
1543 }
1544 case 4:
1545 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001546 png_bytep bp = row;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001547 png_uint_32 i;
1548 png_uint_32 istop = row_info->rowbytes;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001549 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1550 (png_byte)((int)0xf >> shift[0]));
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001551
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001552 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001553 {
1554 *bp >>= shift[0];
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001555 *bp++ &= mask;
Guy Schalnat0d580581995-07-20 02:43:20 -05001556 }
1557 break;
1558 }
1559 case 8:
1560 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001561 png_bytep bp = row;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001562 png_uint_32 i;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001563 png_uint_32 istop = row_width * channels;
Guy Schalnat0d580581995-07-20 02:43:20 -05001564
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001565 for (i = 0; i < istop; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001566 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001567 *bp++ >>= shift[i%channels];
Guy Schalnat0d580581995-07-20 02:43:20 -05001568 }
1569 break;
1570 }
1571 case 16:
1572 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001573 png_bytep bp = row;
1574 png_uint_32 i;
1575 png_uint_32 istop = channels * row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001576
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001577 for (i = 0; i < istop; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001578 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001579 value = (png_uint_16)((*bp << 8) + *(bp + 1));
1580 value >>= shift[i%channels];
1581 *bp++ = (png_byte)(value >> 8);
1582 *bp++ = (png_byte)(value & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05001583 }
1584 break;
1585 }
1586 }
1587 }
1588}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001589#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001590
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001591#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001592/* chop rows of bit depth 16 down to 8 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001593void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001594png_do_chop(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001595{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001596 png_debug(1, "in png_do_chop\n");
1597#if defined(PNG_USELESS_TESTS_SUPPORTED)
1598 if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1599#else
1600 if (row_info->bit_depth == 16)
1601#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001602 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001603 png_bytep sp = row;
1604 png_bytep dp = row;
1605 png_uint_32 i;
1606 png_uint_32 istop = row_info->width * row_info->channels;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001607
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001608 for (i = 0; i<istop; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001609 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001610#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001611 /* This does a more accurate scaling of the 16-bit color
1612 * value, rather than a simple low-byte truncation.
1613 *
1614 * What the ideal calculation should be:
1615 * *dp = (((((png_uint_32)(*sp) << 8) |
1616 * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1617 *
1618 * GRR: no, I think this is what it really should be:
1619 * *dp = (((((png_uint_32)(*sp) << 8) |
1620 * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1621 *
1622 * GRR: here's the exact calculation with shifts:
1623 * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1624 * *dp = (temp - (temp >> 8)) >> 8;
1625 *
1626 * Approximate calculation with shift/add instead of multiply/divide:
1627 * *dp = ((((png_uint_32)(*sp) << 8) |
1628 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1629 *
1630 * What we actually do to avoid extra shifting and conversion:
1631 */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001632
Andreas Dilger47a0c421997-05-16 02:46:07 -05001633 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1634#else
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001635 /* Simply discard the low order byte */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001636 *dp = *sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001637#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001638 }
1639 row_info->bit_depth = 8;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001640 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001641 row_info->rowbytes = row_info->width * row_info->channels;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001642 }
1643}
1644#endif
1645
1646#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001647void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001648png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1649{
1650 png_debug(1, "in png_do_read_swap_alpha\n");
1651#if defined(PNG_USELESS_TESTS_SUPPORTED)
1652 if (row != NULL && row_info != NULL)
1653#endif
1654 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001655 png_uint_32 row_width = row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001656 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1657 {
1658 /* This converts from RGBA to ARGB */
1659 if (row_info->bit_depth == 8)
1660 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001661 png_bytep sp = row + row_info->rowbytes;
1662 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001663 png_byte save;
1664 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001665
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001666 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001667 {
1668 save = *(--sp);
1669 *(--dp) = *(--sp);
1670 *(--dp) = *(--sp);
1671 *(--dp) = *(--sp);
1672 *(--dp) = save;
1673 }
1674 }
1675 /* This converts from RRGGBBAA to AARRGGBB */
1676 else
1677 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001678 png_bytep sp = row + row_info->rowbytes;
1679 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001680 png_byte save[2];
1681 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001682
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001683 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001684 {
1685 save[0] = *(--sp);
1686 save[1] = *(--sp);
1687 *(--dp) = *(--sp);
1688 *(--dp) = *(--sp);
1689 *(--dp) = *(--sp);
1690 *(--dp) = *(--sp);
1691 *(--dp) = *(--sp);
1692 *(--dp) = *(--sp);
1693 *(--dp) = save[0];
1694 *(--dp) = save[1];
1695 }
1696 }
1697 }
1698 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1699 {
1700 /* This converts from GA to AG */
1701 if (row_info->bit_depth == 8)
1702 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001703 png_bytep sp = row + row_info->rowbytes;
1704 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001705 png_byte save;
1706 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001707
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001708 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001709 {
1710 save = *(--sp);
1711 *(--dp) = *(--sp);
1712 *(--dp) = save;
1713 }
1714 }
1715 /* This converts from GGAA to AAGG */
1716 else
1717 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001718 png_bytep sp = row + row_info->rowbytes;
1719 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001720 png_byte save[2];
1721 png_uint_32 i;
1722
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001723 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001724 {
1725 save[0] = *(--sp);
1726 save[1] = *(--sp);
1727 *(--dp) = *(--sp);
1728 *(--dp) = *(--sp);
1729 *(--dp) = save[0];
1730 *(--dp) = save[1];
1731 }
1732 }
1733 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001734 }
1735}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001736#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001737
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001738#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001739void /* PRIVATE */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001740png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1741{
1742 png_debug(1, "in png_do_read_invert_alpha\n");
1743#if defined(PNG_USELESS_TESTS_SUPPORTED)
1744 if (row != NULL && row_info != NULL)
1745#endif
1746 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001747 png_uint_32 row_width = row_info->width;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001748 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1749 {
1750 /* This inverts the alpha channel in RGBA */
1751 if (row_info->bit_depth == 8)
1752 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001753 png_bytep sp = row + row_info->rowbytes;
1754 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001755 png_uint_32 i;
1756
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001757 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001758 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001759 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001760
1761/* This does nothing:
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001762 *(--dp) = *(--sp);
1763 *(--dp) = *(--sp);
1764 *(--dp) = *(--sp);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001765 We can replace it with:
1766*/
1767 sp-=3;
1768 dp=sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001769 }
1770 }
1771 /* This inverts the alpha channel in RRGGBBAA */
1772 else
1773 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001774 png_bytep sp = row + row_info->rowbytes;
1775 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001776 png_uint_32 i;
1777
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001778 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001779 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001780 *(--dp) = (png_byte)(255 - *(--sp));
1781 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001782
1783/* This does nothing:
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001784 *(--dp) = *(--sp);
1785 *(--dp) = *(--sp);
1786 *(--dp) = *(--sp);
1787 *(--dp) = *(--sp);
1788 *(--dp) = *(--sp);
1789 *(--dp) = *(--sp);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001790 We can replace it with:
1791*/
1792 sp-=6;
1793 dp=sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001794 }
1795 }
1796 }
1797 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1798 {
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001799 /* This inverts the alpha channel in GA */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001800 if (row_info->bit_depth == 8)
1801 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001802 png_bytep sp = row + row_info->rowbytes;
1803 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001804 png_uint_32 i;
1805
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001806 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001807 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001808 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001809 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001810 }
1811 }
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001812 /* This inverts the alpha channel in GGAA */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001813 else
1814 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001815 png_bytep sp = row + row_info->rowbytes;
1816 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001817 png_uint_32 i;
1818
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001819 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001820 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001821 *(--dp) = (png_byte)(255 - *(--sp));
1822 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001823/*
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001824 *(--dp) = *(--sp);
1825 *(--dp) = *(--sp);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001826*/
1827 sp-=2;
1828 dp=sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001829 }
1830 }
1831 }
1832 }
1833}
1834#endif
1835
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001836#if defined(PNG_READ_FILLER_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001837/* Add filler channel if we have RGB color */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001838void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001839png_do_read_filler(png_row_infop row_info, png_bytep row,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001840 png_uint_32 filler, png_uint_32 flags)
Guy Schalnat0d580581995-07-20 02:43:20 -05001841{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001842 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001843 png_uint_32 row_width = row_info->width;
1844
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001845 png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001846 png_byte lo_filler = (png_byte)(filler & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001847
1848 png_debug(1, "in png_do_read_filler\n");
1849 if (
1850#if defined(PNG_USELESS_TESTS_SUPPORTED)
1851 row != NULL && row_info != NULL &&
1852#endif
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001853 row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05001854 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001855 if(row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05001856 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001857 /* This changes the data from G to GX */
1858 if (flags & PNG_FLAG_FILLER_AFTER)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001859 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001860 png_bytep sp = row + (png_size_t)row_width;
1861 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001862 for (i = 1; i < row_width; i++)
1863 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001864 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001865 *(--dp) = *(--sp);
1866 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001867 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001868 row_info->channels = 2;
1869 row_info->pixel_depth = 16;
1870 row_info->rowbytes = row_width * 2;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001871 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001872 /* This changes the data from G to XG */
1873 else
1874 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001875 png_bytep sp = row + (png_size_t)row_width;
1876 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001877 for (i = 0; i < row_width; i++)
1878 {
1879 *(--dp) = *(--sp);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001880 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001881 }
1882 row_info->channels = 2;
1883 row_info->pixel_depth = 16;
1884 row_info->rowbytes = row_width * 2;
1885 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001886 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001887 else if(row_info->bit_depth == 16)
1888 {
1889 /* This changes the data from GG to GGXX */
1890 if (flags & PNG_FLAG_FILLER_AFTER)
1891 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001892 png_bytep sp = row + (png_size_t)row_width;
1893 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001894 for (i = 1; i < row_width; i++)
1895 {
1896 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001897 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001898 *(--dp) = *(--sp);
1899 *(--dp) = *(--sp);
1900 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001901 *(--dp) = hi_filler;
1902 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001903 row_info->channels = 2;
1904 row_info->pixel_depth = 32;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001905 row_info->rowbytes = row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001906 }
1907 /* This changes the data from GG to XXGG */
1908 else
1909 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001910 png_bytep sp = row + (png_size_t)row_width;
1911 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001912 for (i = 0; i < row_width; i++)
1913 {
1914 *(--dp) = *(--sp);
1915 *(--dp) = *(--sp);
1916 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001917 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001918 }
1919 row_info->channels = 2;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001920 row_info->pixel_depth = 32;
1921 row_info->rowbytes = row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001922 }
1923 }
1924 } /* COLOR_TYPE == GRAY */
1925 else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
1926 {
1927 if(row_info->bit_depth == 8)
1928 {
1929 /* This changes the data from RGB to RGBX */
1930 if (flags & PNG_FLAG_FILLER_AFTER)
1931 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001932 png_bytep sp = row + (png_size_t)row_width * 3;
1933 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001934 for (i = 1; i < row_width; i++)
1935 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001936 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001937 *(--dp) = *(--sp);
1938 *(--dp) = *(--sp);
1939 *(--dp) = *(--sp);
1940 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001941 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001942 row_info->channels = 4;
1943 row_info->pixel_depth = 32;
1944 row_info->rowbytes = row_width * 4;
1945 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001946 /* This changes the data from RGB to XRGB */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001947 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001948 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001949 png_bytep sp = row + (png_size_t)row_width * 3;
1950 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001951 for (i = 0; i < row_width; i++)
1952 {
1953 *(--dp) = *(--sp);
1954 *(--dp) = *(--sp);
1955 *(--dp) = *(--sp);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001956 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001957 }
1958 row_info->channels = 4;
1959 row_info->pixel_depth = 32;
1960 row_info->rowbytes = row_width * 4;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001961 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001962 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001963 else if(row_info->bit_depth == 16)
1964 {
1965 /* This changes the data from RRGGBB to RRGGBBXX */
1966 if (flags & PNG_FLAG_FILLER_AFTER)
1967 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001968 png_bytep sp = row + (png_size_t)row_width * 3;
1969 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001970 for (i = 1; i < row_width; i++)
1971 {
1972 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001973 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001974 *(--dp) = *(--sp);
1975 *(--dp) = *(--sp);
1976 *(--dp) = *(--sp);
1977 *(--dp) = *(--sp);
1978 *(--dp) = *(--sp);
1979 *(--dp) = *(--sp);
1980 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001981 *(--dp) = hi_filler;
1982 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001983 row_info->channels = 4;
1984 row_info->pixel_depth = 64;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001985 row_info->rowbytes = row_width * 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001986 }
1987 /* This changes the data from RRGGBB to XXRRGGBB */
1988 else
1989 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001990 png_bytep sp = row + (png_size_t)row_width * 3;
1991 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001992 for (i = 0; i < row_width; i++)
1993 {
1994 *(--dp) = *(--sp);
1995 *(--dp) = *(--sp);
1996 *(--dp) = *(--sp);
1997 *(--dp) = *(--sp);
1998 *(--dp) = *(--sp);
1999 *(--dp) = *(--sp);
2000 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002001 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002002 }
2003 row_info->channels = 4;
2004 row_info->pixel_depth = 64;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002005 row_info->rowbytes = row_width * 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002006 }
2007 }
2008 } /* COLOR_TYPE == RGB */
Guy Schalnat0d580581995-07-20 02:43:20 -05002009}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002010#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002011
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002012#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002013/* expand grayscale files to RGB, with or without alpha */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002014void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002015png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05002016{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002017 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002018 png_uint_32 row_width = row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06002019
Andreas Dilger47a0c421997-05-16 02:46:07 -05002020 png_debug(1, "in png_do_gray_to_rgb\n");
2021 if (row_info->bit_depth >= 8 &&
2022#if defined(PNG_USELESS_TESTS_SUPPORTED)
2023 row != NULL && row_info != NULL &&
2024#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002025 !(row_info->color_type & PNG_COLOR_MASK_COLOR))
2026 {
2027 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2028 {
2029 if (row_info->bit_depth == 8)
2030 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002031 png_bytep sp = row + (png_size_t)row_width - 1;
2032 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002033 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002034 {
2035 *(dp--) = *sp;
2036 *(dp--) = *sp;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002037 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05002038 }
2039 }
2040 else
2041 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002042 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2043 png_bytep dp = sp + (png_size_t)row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002044 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002045 {
2046 *(dp--) = *sp;
2047 *(dp--) = *(sp - 1);
2048 *(dp--) = *sp;
2049 *(dp--) = *(sp - 1);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002050 *(dp--) = *(sp--);
2051 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05002052 }
2053 }
2054 }
2055 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2056 {
2057 if (row_info->bit_depth == 8)
2058 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002059 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2060 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002061 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002062 {
2063 *(dp--) = *(sp--);
2064 *(dp--) = *sp;
2065 *(dp--) = *sp;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002066 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05002067 }
2068 }
2069 else
2070 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002071 png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2072 png_bytep dp = sp + (png_size_t)row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002073 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002074 {
2075 *(dp--) = *(sp--);
2076 *(dp--) = *(sp--);
2077 *(dp--) = *sp;
2078 *(dp--) = *(sp - 1);
2079 *(dp--) = *sp;
2080 *(dp--) = *(sp - 1);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002081 *(dp--) = *(sp--);
2082 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05002083 }
2084 }
2085 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002086 row_info->channels += (png_byte)2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002087 row_info->color_type |= PNG_COLOR_MASK_COLOR;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002088 row_info->pixel_depth = (png_byte)(row_info->channels *
2089 row_info->bit_depth);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002090 row_info->rowbytes = ((row_width *
Guy Schalnat0d580581995-07-20 02:43:20 -05002091 row_info->pixel_depth + 7) >> 3);
2092 }
2093}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002094#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002095
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002096#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002097/* reduce RGB files to grayscale, with or without alpha
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002098 * using the equation given in Poynton's ColorFAQ at
2099 * <http://www.inforamp.net/~poynton/>
2100 * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
2101 *
2102 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2103 *
2104 * We approximate this with
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002105 *
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002106 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002107 *
2108 * which can be expressed with integers as
2109 *
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002110 * Y = (6969 * R + 23434 * G + 2365 * B)/32768
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002111 *
2112 * The calculation is to be done in a linear colorspace.
2113 *
2114 * Other integer coefficents can be used via png_set_rgb_to_gray().
2115 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002116int /* PRIVATE */
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002117png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2118
2119{
2120 png_uint_32 i;
2121
2122 png_uint_32 row_width = row_info->width;
2123 int rgb_error = 0;
2124
2125 png_debug(1, "in png_do_rgb_to_gray\n");
2126 if (
2127#if defined(PNG_USELESS_TESTS_SUPPORTED)
2128 row != NULL && row_info != NULL &&
2129#endif
2130 (row_info->color_type & PNG_COLOR_MASK_COLOR))
2131 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002132 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2133 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2134 png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002135
2136 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2137 {
2138 if (row_info->bit_depth == 8)
2139 {
2140#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2141 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2142 {
2143 png_bytep sp = row;
2144 png_bytep dp = row;
2145
2146 for (i = 0; i < row_width; i++)
2147 {
2148 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2149 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2150 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2151 if(red != green || red != blue)
2152 {
2153 rgb_error |= 1;
2154 *(dp++) = png_ptr->gamma_from_1[
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002155 (rc*red+gc*green+bc*blue)>>15];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002156 }
2157 else
2158 *(dp++) = *(sp-1);
2159 }
2160 }
2161 else
2162#endif
2163 {
2164 png_bytep sp = row;
2165 png_bytep dp = row;
2166 for (i = 0; i < row_width; i++)
2167 {
2168 png_byte red = *(sp++);
2169 png_byte green = *(sp++);
2170 png_byte blue = *(sp++);
2171 if(red != green || red != blue)
2172 {
2173 rgb_error |= 1;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002174 *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002175 }
2176 else
2177 *(dp++) = *(sp-1);
2178 }
2179 }
2180 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002181
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002182 else /* RGB bit_depth == 16 */
2183 {
2184#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2185 if (png_ptr->gamma_16_to_1 != NULL &&
2186 png_ptr->gamma_16_from_1 != NULL)
2187 {
2188 png_bytep sp = row;
2189 png_bytep dp = row;
2190 for (i = 0; i < row_width; i++)
2191 {
2192 png_uint_16 red, green, blue, w;
2193
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002194 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2195 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2196 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002197
2198 if(red == green && red == blue)
2199 w = red;
2200 else
2201 {
2202 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2203 png_ptr->gamma_shift][red>>8];
2204 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2205 png_ptr->gamma_shift][green>>8];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002206 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002207 png_ptr->gamma_shift][blue>>8];
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002208 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002209 + bc*blue_1)>>15);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002210 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2211 png_ptr->gamma_shift][gray16 >> 8];
2212 rgb_error |= 1;
2213 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002214
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002215 *(dp++) = (png_byte)((w>>8) & 0xff);
2216 *(dp++) = (png_byte)(w & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002217 }
2218 }
2219 else
2220#endif
2221 {
2222 png_bytep sp = row;
2223 png_bytep dp = row;
2224 for (i = 0; i < row_width; i++)
2225 {
2226 png_uint_16 red, green, blue, gray16;
2227
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002228 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2229 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2230 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002231
2232 if(red != green || red != blue)
2233 rgb_error |= 1;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002234 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002235 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2236 *(dp++) = (png_byte)(gray16 & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002237 }
2238 }
2239 }
2240 }
2241 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2242 {
2243 if (row_info->bit_depth == 8)
2244 {
2245#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2246 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2247 {
2248 png_bytep sp = row;
2249 png_bytep dp = row;
2250 for (i = 0; i < row_width; i++)
2251 {
2252 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2253 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2254 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2255 if(red != green || red != blue)
2256 rgb_error |= 1;
2257 *(dp++) = png_ptr->gamma_from_1
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002258 [(rc*red + gc*green + bc*blue)>>15];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002259 *(dp++) = *(sp++); /* alpha */
2260 }
2261 }
2262 else
2263#endif
2264 {
2265 png_bytep sp = row;
2266 png_bytep dp = row;
2267 for (i = 0; i < row_width; i++)
2268 {
2269 png_byte red = *(sp++);
2270 png_byte green = *(sp++);
2271 png_byte blue = *(sp++);
2272 if(red != green || red != blue)
2273 rgb_error |= 1;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002274 *(dp++) = (png_byte)((gc*red + gc*green + bc*blue)>>8);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002275 *(dp++) = *(sp++); /* alpha */
2276 }
2277 }
2278 }
2279 else /* RGBA bit_depth == 16 */
2280 {
2281#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2282 if (png_ptr->gamma_16_to_1 != NULL &&
2283 png_ptr->gamma_16_from_1 != NULL)
2284 {
2285 png_bytep sp = row;
2286 png_bytep dp = row;
2287 for (i = 0; i < row_width; i++)
2288 {
2289 png_uint_16 red, green, blue, w;
2290
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002291 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2292 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2293 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002294
2295 if(red == green && red == blue)
2296 w = red;
2297 else
2298 {
2299 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2300 png_ptr->gamma_shift][red>>8];
2301 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2302 png_ptr->gamma_shift][green>>8];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002303 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002304 png_ptr->gamma_shift][blue>>8];
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002305 png_uint_16 gray16 = (png_uint_16)((rc * red_1
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002306 + gc * green_1 + bc * blue_1)>>15);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002307 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2308 png_ptr->gamma_shift][gray16 >> 8];
2309 rgb_error |= 1;
2310 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002311
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002312 *(dp++) = (png_byte)((w>>8) & 0xff);
2313 *(dp++) = (png_byte)(w & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002314 *(dp++) = *(sp++); /* alpha */
2315 *(dp++) = *(sp++);
2316 }
2317 }
2318 else
2319#endif
2320 {
2321 png_bytep sp = row;
2322 png_bytep dp = row;
2323 for (i = 0; i < row_width; i++)
2324 {
2325 png_uint_16 red, green, blue, gray16;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002326 red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2327 green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2328 blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002329 if(red != green || red != blue)
2330 rgb_error |= 1;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002331 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002332 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2333 *(dp++) = (png_byte)(gray16 & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002334 *(dp++) = *(sp++); /* alpha */
2335 *(dp++) = *(sp++);
2336 }
2337 }
2338 }
2339 }
2340 row_info->channels -= (png_byte)2;
2341 row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2342 row_info->pixel_depth = (png_byte)(row_info->channels *
2343 row_info->bit_depth);
2344 row_info->rowbytes = ((row_width *
2345 row_info->pixel_depth + 7) >> 3);
2346 }
2347 return rgb_error;
2348}
2349#endif
2350
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002351/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
2352 * large of png_color. This lets grayscale images be treated as
2353 * paletted. Most useful for gamma correction and simplification
2354 * of code.
2355 */
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -06002356void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -06002357png_build_grayscale_palette(int bit_depth, png_colorp palette)
Guy Schalnat0d580581995-07-20 02:43:20 -05002358{
2359 int num_palette;
2360 int color_inc;
2361 int i;
2362 int v;
2363
Andreas Dilger47a0c421997-05-16 02:46:07 -05002364 png_debug(1, "in png_do_build_grayscale_palette\n");
2365 if (palette == NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002366 return;
2367
2368 switch (bit_depth)
2369 {
2370 case 1:
2371 num_palette = 2;
2372 color_inc = 0xff;
2373 break;
2374 case 2:
2375 num_palette = 4;
2376 color_inc = 0x55;
2377 break;
2378 case 4:
2379 num_palette = 16;
2380 color_inc = 0x11;
2381 break;
2382 case 8:
2383 num_palette = 256;
2384 color_inc = 1;
2385 break;
2386 default:
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002387 num_palette = 0;
Guy Schalnat69b14481996-01-10 02:56:49 -06002388 color_inc = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05002389 break;
2390 }
2391
2392 for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2393 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002394 palette[i].red = (png_byte)v;
2395 palette[i].green = (png_byte)v;
2396 palette[i].blue = (png_byte)v;
Guy Schalnat0d580581995-07-20 02:43:20 -05002397 }
2398}
2399
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002400/* This function is currently unused. Do we really need it? */
2401#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002402void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002403png_correct_palette(png_structp png_ptr, png_colorp palette,
Guy Schalnat0d580581995-07-20 02:43:20 -05002404 int num_palette)
2405{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002406 png_debug(1, "in png_correct_palette\n");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002407#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2408 defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002409 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
Guy Schalnat0d580581995-07-20 02:43:20 -05002410 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002411 png_color back, back_1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002412
Andreas Dilger47a0c421997-05-16 02:46:07 -05002413 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
2414 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002415 back.red = png_ptr->gamma_table[png_ptr->background.red];
2416 back.green = png_ptr->gamma_table[png_ptr->background.green];
2417 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
Guy Schalnat0d580581995-07-20 02:43:20 -05002418
Guy Schalnate5a37791996-06-05 15:50:50 -05002419 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
2420 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
2421 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002422 }
2423 else
2424 {
2425 double g;
Guy Schalnat0d580581995-07-20 02:43:20 -05002426
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06002427 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002428
2429 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2430 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
Guy Schalnat0d580581995-07-20 02:43:20 -05002431 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002432 back.red = png_ptr->background.red;
2433 back.green = png_ptr->background.green;
2434 back.blue = png_ptr->background.blue;
2435 }
2436 else
2437 {
2438 back.red =
2439 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2440 255.0 + 0.5);
2441 back.green =
2442 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2443 255.0 + 0.5);
2444 back.blue =
2445 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2446 255.0 + 0.5);
2447 }
2448
2449 g = 1.0 / png_ptr->background_gamma;
2450
2451 back_1.red =
2452 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2453 255.0 + 0.5);
2454 back_1.green =
2455 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2456 255.0 + 0.5);
2457 back_1.blue =
2458 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2459 255.0 + 0.5);
2460 }
2461
2462 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2463 {
2464 png_uint_32 i;
2465
2466 for (i = 0; i < (png_uint_32)num_palette; i++)
2467 {
2468 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -05002469 {
2470 palette[i] = back;
2471 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002472 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002473 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002474 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002475
2476 v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002477 png_composite(w, v, png_ptr->trans[i], back_1.red);
2478 palette[i].red = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002479
2480 v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002481 png_composite(w, v, png_ptr->trans[i], back_1.green);
2482 palette[i].green = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002483
2484 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002485 png_composite(w, v, png_ptr->trans[i], back_1.blue);
2486 palette[i].blue = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002487 }
2488 else
2489 {
2490 palette[i].red = png_ptr->gamma_table[palette[i].red];
2491 palette[i].green = png_ptr->gamma_table[palette[i].green];
2492 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2493 }
2494 }
2495 }
2496 else
2497 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002498 int i;
Guy Schalnat0d580581995-07-20 02:43:20 -05002499
2500 for (i = 0; i < num_palette; i++)
2501 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002502 if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002503 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002504 palette[i] = back;
Guy Schalnat0d580581995-07-20 02:43:20 -05002505 }
2506 else
2507 {
2508 palette[i].red = png_ptr->gamma_table[palette[i].red];
2509 palette[i].green = png_ptr->gamma_table[palette[i].green];
2510 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2511 }
2512 }
2513 }
2514 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002515 else
2516#endif
2517#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002518 if (png_ptr->transformations & PNG_GAMMA)
Guy Schalnat0d580581995-07-20 02:43:20 -05002519 {
2520 int i;
2521
2522 for (i = 0; i < num_palette; i++)
2523 {
2524 palette[i].red = png_ptr->gamma_table[palette[i].red];
2525 palette[i].green = png_ptr->gamma_table[palette[i].green];
2526 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2527 }
2528 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002529#if defined(PNG_READ_BACKGROUND_SUPPORTED)
2530 else
2531#endif
2532#endif
2533#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002534 if (png_ptr->transformations & PNG_BACKGROUND)
Guy Schalnat0d580581995-07-20 02:43:20 -05002535 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002536 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05002537 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002538 png_color back;
Guy Schalnat0d580581995-07-20 02:43:20 -05002539
Guy Schalnate5a37791996-06-05 15:50:50 -05002540 back.red = (png_byte)png_ptr->background.red;
2541 back.green = (png_byte)png_ptr->background.green;
2542 back.blue = (png_byte)png_ptr->background.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002543
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06002544 for (i = 0; i < (int)png_ptr->num_trans; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002545 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002546 if (png_ptr->trans[i] == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -05002547 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002548 palette[i].red = back.red;
2549 palette[i].green = back.green;
2550 palette[i].blue = back.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002551 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002552 else if (png_ptr->trans[i] != 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002553 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002554 png_composite(palette[i].red, png_ptr->palette[i].red,
2555 png_ptr->trans[i], back.red);
2556 png_composite(palette[i].green, png_ptr->palette[i].green,
2557 png_ptr->trans[i], back.green);
2558 png_composite(palette[i].blue, png_ptr->palette[i].blue,
2559 png_ptr->trans[i], back.blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05002560 }
2561 }
2562 }
2563 else /* assume grayscale palette (what else could it be?) */
2564 {
2565 int i;
2566
2567 for (i = 0; i < num_palette; i++)
2568 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002569 if (i == (png_byte)png_ptr->trans_values.gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002570 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002571 palette[i].red = (png_byte)png_ptr->background.red;
2572 palette[i].green = (png_byte)png_ptr->background.green;
2573 palette[i].blue = (png_byte)png_ptr->background.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002574 }
2575 }
2576 }
2577 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002578#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002579}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002580#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002581
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002582#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002583/* Replace any alpha or transparency with the supplied background color.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002584 * "background" is already in the screen gamma, while "background_1" is
2585 * at a gamma of 1.0. Paletted files have already been taken care of.
2586 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002587void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002588png_do_background(png_row_infop row_info, png_bytep row,
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05002589 png_color_16p trans_values, png_color_16p background
2590#if defined(PNG_READ_GAMMA_SUPPORTED)
2591 , png_color_16p background_1,
Guy Schalnat6d764711995-12-19 03:22:19 -06002592 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002593 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05002594 png_uint_16pp gamma_16_to_1, int gamma_shift
2595#endif
2596 )
Guy Schalnat0d580581995-07-20 02:43:20 -05002597{
Guy Schalnat6d764711995-12-19 03:22:19 -06002598 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002599 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002600 png_uint_32 row_width=row_info->width;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002601 int shift;
Guy Schalnate5a37791996-06-05 15:50:50 -05002602
Andreas Dilger47a0c421997-05-16 02:46:07 -05002603 png_debug(1, "in png_do_background\n");
2604 if (background != NULL &&
2605#if defined(PNG_USELESS_TESTS_SUPPORTED)
2606 row != NULL && row_info != NULL &&
2607#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002608 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
Andreas Dilger47a0c421997-05-16 02:46:07 -05002609 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
Guy Schalnat0d580581995-07-20 02:43:20 -05002610 {
2611 switch (row_info->color_type)
2612 {
2613 case PNG_COLOR_TYPE_GRAY:
2614 {
2615 switch (row_info->bit_depth)
2616 {
2617 case 1:
2618 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002619 sp = row;
2620 shift = 7;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002621 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002622 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002623 if ((png_uint_16)((*sp >> shift) & 0x01)
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002624 == trans_values->gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002625 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002626 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2627 *sp |= (png_byte)(background->gray << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05002628 }
2629 if (!shift)
2630 {
2631 shift = 7;
2632 sp++;
2633 }
2634 else
2635 shift--;
2636 }
2637 break;
2638 }
2639 case 2:
2640 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002641#if defined(PNG_READ_GAMMA_SUPPORTED)
2642 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002643 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002644 sp = row;
2645 shift = 6;
2646 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002647 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002648 if ((png_uint_16)((*sp >> shift) & 0x03)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002649 == trans_values->gray)
2650 {
2651 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2652 *sp |= (png_byte)(background->gray << shift);
2653 }
2654 else
2655 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002656 png_byte p = (png_byte)((*sp >> shift) & 0x03);
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002657 png_byte g = (png_byte)((gamma_table [p | (p << 2) |
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002658 (p << 4) | (p << 6)] >> 6) & 0x03);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002659 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2660 *sp |= (png_byte)(g << shift);
2661 }
2662 if (!shift)
2663 {
2664 shift = 6;
2665 sp++;
2666 }
2667 else
2668 shift -= 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002669 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002670 }
2671 else
2672#endif
2673 {
2674 sp = row;
2675 shift = 6;
2676 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002677 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002678 if ((png_uint_16)((*sp >> shift) & 0x03)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002679 == trans_values->gray)
2680 {
2681 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2682 *sp |= (png_byte)(background->gray << shift);
2683 }
2684 if (!shift)
2685 {
2686 shift = 6;
2687 sp++;
2688 }
2689 else
2690 shift -= 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002691 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002692 }
2693 break;
2694 }
2695 case 4:
2696 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002697#if defined(PNG_READ_GAMMA_SUPPORTED)
2698 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002699 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002700 sp = row;
2701 shift = 4;
2702 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002703 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002704 if ((png_uint_16)((*sp >> shift) & 0x0f)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002705 == trans_values->gray)
2706 {
2707 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2708 *sp |= (png_byte)(background->gray << shift);
2709 }
2710 else
2711 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002712 png_byte p = (png_byte)((*sp >> shift) & 0x0f);
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002713 png_byte g = (png_byte)((gamma_table[p |
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002714 (p << 4)] >> 4) & 0x0f);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002715 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2716 *sp |= (png_byte)(g << shift);
2717 }
2718 if (!shift)
2719 {
2720 shift = 4;
2721 sp++;
2722 }
2723 else
2724 shift -= 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05002725 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002726 }
2727 else
2728#endif
2729 {
2730 sp = row;
2731 shift = 4;
2732 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002733 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002734 if ((png_uint_16)((*sp >> shift) & 0x0f)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002735 == trans_values->gray)
2736 {
2737 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2738 *sp |= (png_byte)(background->gray << shift);
2739 }
2740 if (!shift)
2741 {
2742 shift = 4;
2743 sp++;
2744 }
2745 else
2746 shift -= 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05002747 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002748 }
2749 break;
2750 }
2751 case 8:
2752 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002753#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002754 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002755 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002756 sp = row;
2757 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002758 {
2759 if (*sp == trans_values->gray)
2760 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002761 *sp = (png_byte)background->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05002762 }
2763 else
2764 {
2765 *sp = gamma_table[*sp];
2766 }
2767 }
2768 }
2769 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002770#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002771 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002772 sp = row;
2773 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002774 {
2775 if (*sp == trans_values->gray)
2776 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002777 *sp = (png_byte)background->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05002778 }
2779 }
2780 }
2781 break;
2782 }
2783 case 16:
2784 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002785#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002786 if (gamma_16 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002787 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002788 sp = row;
2789 for (i = 0; i < row_width; i++, sp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002790 {
2791 png_uint_16 v;
2792
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002793 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05002794 if (v == trans_values->gray)
2795 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002796 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002797 *sp = (png_byte)((background->gray >> 8) & 0xff);
2798 *(sp + 1) = (png_byte)(background->gray & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002799 }
2800 else
2801 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002802 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002803 *sp = (png_byte)((v >> 8) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002804 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002805 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002806 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002807 }
2808 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002809#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002810 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002811 sp = row;
2812 for (i = 0; i < row_width; i++, sp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002813 {
2814 png_uint_16 v;
2815
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002816 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05002817 if (v == trans_values->gray)
2818 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002819 *sp = (png_byte)((background->gray >> 8) & 0xff);
2820 *(sp + 1) = (png_byte)(background->gray & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002821 }
2822 }
2823 }
2824 break;
2825 }
2826 }
2827 break;
2828 }
2829 case PNG_COLOR_TYPE_RGB:
2830 {
2831 if (row_info->bit_depth == 8)
2832 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002833#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002834 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002835 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002836 sp = row;
2837 for (i = 0; i < row_width; i++, sp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002838 {
2839 if (*sp == trans_values->red &&
2840 *(sp + 1) == trans_values->green &&
2841 *(sp + 2) == trans_values->blue)
2842 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002843 *sp = (png_byte)background->red;
2844 *(sp + 1) = (png_byte)background->green;
2845 *(sp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002846 }
2847 else
2848 {
2849 *sp = gamma_table[*sp];
2850 *(sp + 1) = gamma_table[*(sp + 1)];
2851 *(sp + 2) = gamma_table[*(sp + 2)];
2852 }
2853 }
2854 }
2855 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002856#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002857 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002858 sp = row;
2859 for (i = 0; i < row_width; i++, sp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002860 {
2861 if (*sp == trans_values->red &&
2862 *(sp + 1) == trans_values->green &&
2863 *(sp + 2) == trans_values->blue)
2864 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002865 *sp = (png_byte)background->red;
2866 *(sp + 1) = (png_byte)background->green;
2867 *(sp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002868 }
2869 }
2870 }
2871 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002872 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002873 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002874#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002875 if (gamma_16 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002876 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002877 sp = row;
2878 for (i = 0; i < row_width; i++, sp += 6)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002879 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002880 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2881 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2882 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
Andreas Dilger47a0c421997-05-16 02:46:07 -05002883 if (r == trans_values->red && g == trans_values->green &&
Guy Schalnat0d580581995-07-20 02:43:20 -05002884 b == trans_values->blue)
2885 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002886 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002887 *sp = (png_byte)((background->red >> 8) & 0xff);
2888 *(sp + 1) = (png_byte)(background->red & 0xff);
2889 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2890 *(sp + 3) = (png_byte)(background->green & 0xff);
2891 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2892 *(sp + 5) = (png_byte)(background->blue & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002893 }
2894 else
2895 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002896 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002897 *sp = (png_byte)((v >> 8) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002898 *(sp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002899 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002900 *(sp + 2) = (png_byte)((v >> 8) & 0xff);
2901 *(sp + 3) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002902 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002903 *(sp + 4) = (png_byte)((v >> 8) & 0xff);
2904 *(sp + 5) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002905 }
2906 }
2907 }
2908 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002909#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002910 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002911 sp = row;
2912 for (i = 0; i < row_width; i++, sp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05002913 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002914 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
2915 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2916 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
Guy Schalnat0d580581995-07-20 02:43:20 -05002917
Andreas Dilger47a0c421997-05-16 02:46:07 -05002918 if (r == trans_values->red && g == trans_values->green &&
Guy Schalnat0d580581995-07-20 02:43:20 -05002919 b == trans_values->blue)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002920 {
2921 *sp = (png_byte)((background->red >> 8) & 0xff);
2922 *(sp + 1) = (png_byte)(background->red & 0xff);
2923 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2924 *(sp + 3) = (png_byte)(background->green & 0xff);
2925 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2926 *(sp + 5) = (png_byte)(background->blue & 0xff);
2927 }
2928 }
2929 }
2930 }
2931 break;
2932 }
2933 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -05002934 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002935 if (row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05002936 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002937#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002938 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2939 gamma_table != NULL)
2940 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002941 sp = row;
2942 dp = row;
2943 for (i = 0; i < row_width; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002944 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002945 png_uint_16 a = *(sp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002946
Andreas Dilger47a0c421997-05-16 02:46:07 -05002947 if (a == 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002948 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002949 *dp = gamma_table[*sp];
2950 }
2951 else if (a == 0)
2952 {
2953 /* background is already in screen gamma */
2954 *dp = (png_byte)background->gray;
2955 }
2956 else
2957 {
2958 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002959
Andreas Dilger47a0c421997-05-16 02:46:07 -05002960 v = gamma_to_1[*sp];
2961 png_composite(w, v, a, background_1->gray);
2962 *dp = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002963 }
2964 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002965 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002966 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002967#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05002968 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002969 sp = row;
2970 dp = row;
2971 for (i = 0; i < row_width; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002972 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002973 png_byte a = *(sp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002974
Andreas Dilger47a0c421997-05-16 02:46:07 -05002975 if (a == 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002976 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002977 *dp = *sp;
2978 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05002979#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002980 else if (a == 0)
2981 {
2982 *dp = (png_byte)background->gray;
2983 }
2984 else
2985 {
2986 png_composite(*dp, *sp, a, background_1->gray);
Guy Schalnat0d580581995-07-20 02:43:20 -05002987 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05002988#else
2989 *dp = (png_byte)background->gray;
2990#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002991 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002992 }
2993 }
2994 else /* if (png_ptr->bit_depth == 16) */
2995 {
2996#if defined(PNG_READ_GAMMA_SUPPORTED)
2997 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
2998 gamma_16_to_1 != NULL)
2999 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003000 sp = row;
3001 dp = row;
3002 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003003 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003004 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003005
Andreas Dilger47a0c421997-05-16 02:46:07 -05003006 if (a == (png_uint_16)0xffff)
3007 {
3008 png_uint_16 v;
3009
3010 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3011 *dp = (png_byte)((v >> 8) & 0xff);
3012 *(dp + 1) = (png_byte)(v & 0xff);
3013 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003014#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003015 else if (a == 0)
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003016#else
3017 else
3018#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05003019 {
3020 /* background is already in screen gamma */
3021 *dp = (png_byte)((background->gray >> 8) & 0xff);
3022 *(dp + 1) = (png_byte)(background->gray & 0xff);
3023 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003024#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003025 else
3026 {
3027 png_uint_16 g, v, w;
3028
3029 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3030 png_composite_16(v, g, a, background_1->gray);
3031 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3032 *dp = (png_byte)((w >> 8) & 0xff);
3033 *(dp + 1) = (png_byte)(w & 0xff);
3034 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003035#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05003036 }
3037 }
3038 else
3039#endif
3040 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003041 sp = row;
3042 dp = row;
3043 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003044 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003045 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003046 if (a == (png_uint_16)0xffff)
3047 {
3048 png_memcpy(dp, sp, 2);
3049 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003050#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003051 else if (a == 0)
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003052#else
3053 else
3054#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05003055 {
3056 *dp = (png_byte)((background->gray >> 8) & 0xff);
3057 *(dp + 1) = (png_byte)(background->gray & 0xff);
3058 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003059#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003060 else
3061 {
3062 png_uint_16 g, v;
3063
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003064 g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003065 png_composite_16(v, g, a, background_1->gray);
3066 *dp = (png_byte)((v >> 8) & 0xff);
3067 *(dp + 1) = (png_byte)(v & 0xff);
3068 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003069#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05003070 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003071 }
3072 }
3073 break;
3074 }
3075 case PNG_COLOR_TYPE_RGB_ALPHA:
3076 {
3077 if (row_info->bit_depth == 8)
3078 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003079#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003080 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3081 gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05003082 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003083 sp = row;
3084 dp = row;
3085 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05003086 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003087 png_byte a = *(sp + 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003088
Guy Schalnat0d580581995-07-20 02:43:20 -05003089 if (a == 0xff)
3090 {
3091 *dp = gamma_table[*sp];
3092 *(dp + 1) = gamma_table[*(sp + 1)];
3093 *(dp + 2) = gamma_table[*(sp + 2)];
3094 }
3095 else if (a == 0)
3096 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003097 /* background is already in screen gamma */
3098 *dp = (png_byte)background->red;
3099 *(dp + 1) = (png_byte)background->green;
3100 *(dp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003101 }
3102 else
3103 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003104 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05003105
3106 v = gamma_to_1[*sp];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003107 png_composite(w, v, a, background_1->red);
3108 *dp = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05003109 v = gamma_to_1[*(sp + 1)];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003110 png_composite(w, v, a, background_1->green);
3111 *(dp + 1) = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05003112 v = gamma_to_1[*(sp + 2)];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003113 png_composite(w, v, a, background_1->blue);
3114 *(dp + 2) = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05003115 }
3116 }
3117 }
3118 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003119#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003120 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003121 sp = row;
3122 dp = row;
3123 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05003124 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003125 png_byte a = *(sp + 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003126
Guy Schalnat0d580581995-07-20 02:43:20 -05003127 if (a == 0xff)
3128 {
3129 *dp = *sp;
3130 *(dp + 1) = *(sp + 1);
3131 *(dp + 2) = *(sp + 2);
3132 }
3133 else if (a == 0)
3134 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003135 *dp = (png_byte)background->red;
3136 *(dp + 1) = (png_byte)background->green;
3137 *(dp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003138 }
3139 else
3140 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003141 png_composite(*dp, *sp, a, background->red);
3142 png_composite(*(dp + 1), *(sp + 1), a,
3143 background->green);
3144 png_composite(*(dp + 2), *(sp + 2), a,
3145 background->blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05003146 }
3147 }
3148 }
3149 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003150 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003151 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003152#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003153 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3154 gamma_16_to_1 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05003155 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003156 sp = row;
3157 dp = row;
3158 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05003159 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003160 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3161 << 8) + (png_uint_16)(*(sp + 7)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003162 if (a == (png_uint_16)0xffff)
3163 {
3164 png_uint_16 v;
3165
Andreas Dilger47a0c421997-05-16 02:46:07 -05003166 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003167 *dp = (png_byte)((v >> 8) & 0xff);
3168 *(dp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003169 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003170 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3171 *(dp + 3) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003172 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003173 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3174 *(dp + 5) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003175 }
3176 else if (a == 0)
3177 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003178 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003179 *dp = (png_byte)((background->red >> 8) & 0xff);
3180 *(dp + 1) = (png_byte)(background->red & 0xff);
3181 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3182 *(dp + 3) = (png_byte)(background->green & 0xff);
3183 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3184 *(dp + 5) = (png_byte)(background->blue & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003185 }
3186 else
3187 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003188 png_uint_16 v, w, x;
Guy Schalnat0d580581995-07-20 02:43:20 -05003189
Andreas Dilger47a0c421997-05-16 02:46:07 -05003190 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -06003191 png_composite_16(w, v, a, background_1->red);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003192 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3193 *dp = (png_byte)((x >> 8) & 0xff);
3194 *(dp + 1) = (png_byte)(x & 0xff);
3195 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -06003196 png_composite_16(w, v, a, background_1->green);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003197 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3198 *(dp + 2) = (png_byte)((x >> 8) & 0xff);
3199 *(dp + 3) = (png_byte)(x & 0xff);
3200 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -06003201 png_composite_16(w, v, a, background_1->blue);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003202 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3203 *(dp + 4) = (png_byte)((x >> 8) & 0xff);
3204 *(dp + 5) = (png_byte)(x & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003205 }
3206 }
3207 }
3208 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003209#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003210 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003211 sp = row;
3212 dp = row;
3213 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05003214 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003215 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3216 << 8) + (png_uint_16)(*(sp + 7)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003217 if (a == (png_uint_16)0xffff)
3218 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003219 png_memcpy(dp, sp, 6);
Guy Schalnat0d580581995-07-20 02:43:20 -05003220 }
3221 else if (a == 0)
3222 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003223 *dp = (png_byte)((background->red >> 8) & 0xff);
3224 *(dp + 1) = (png_byte)(background->red & 0xff);
3225 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3226 *(dp + 3) = (png_byte)(background->green & 0xff);
3227 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3228 *(dp + 5) = (png_byte)(background->blue & 0xff);
3229 }
3230 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003231 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003232 png_uint_16 v;
Guy Schalnat0d580581995-07-20 02:43:20 -05003233
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003234 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3235 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3236 + *(sp + 3));
3237 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3238 + *(sp + 5));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003239
3240 png_composite_16(v, r, a, background->red);
Guy Schalnat0d580581995-07-20 02:43:20 -05003241 *dp = (png_byte)((v >> 8) & 0xff);
3242 *(dp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003243 png_composite_16(v, g, a, background->green);
Guy Schalnat0d580581995-07-20 02:43:20 -05003244 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3245 *(dp + 3) = (png_byte)(v & 0xff);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003246 png_composite_16(v, b, a, background->blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05003247 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3248 *(dp + 5) = (png_byte)(v & 0xff);
3249 }
3250 }
3251 }
3252 }
3253 break;
3254 }
3255 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003256
Guy Schalnat0d580581995-07-20 02:43:20 -05003257 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3258 {
3259 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
Guy Schalnate5a37791996-06-05 15:50:50 -05003260 row_info->channels--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003261 row_info->pixel_depth = (png_byte)(row_info->channels *
3262 row_info->bit_depth);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003263 row_info->rowbytes = ((row_width *
Guy Schalnat0d580581995-07-20 02:43:20 -05003264 row_info->pixel_depth + 7) >> 3);
3265 }
3266 }
3267}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003268#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003269
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003270#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003271/* Gamma correct the image, avoiding the alpha channel. Make sure
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05003272 * you do this after you deal with the transparency issue on grayscale
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -05003273 * or RGB images. If your bit depth is 8, use gamma_table, if it
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003274 * is 16, use gamma_16_table and gamma_shift. Build these with
3275 * build_gamma_table().
3276 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003277void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003278png_do_gamma(png_row_infop row_info, png_bytep row,
3279 png_bytep gamma_table, png_uint_16pp gamma_16_table,
Guy Schalnat0d580581995-07-20 02:43:20 -05003280 int gamma_shift)
3281{
Guy Schalnat6d764711995-12-19 03:22:19 -06003282 png_bytep sp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003283 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003284 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003285
Andreas Dilger47a0c421997-05-16 02:46:07 -05003286 png_debug(1, "in png_do_gamma\n");
3287 if (
3288#if defined(PNG_USELESS_TESTS_SUPPORTED)
3289 row != NULL && row_info != NULL &&
3290#endif
3291 ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3292 (row_info->bit_depth == 16 && gamma_16_table != NULL)))
Guy Schalnat0d580581995-07-20 02:43:20 -05003293 {
3294 switch (row_info->color_type)
3295 {
3296 case PNG_COLOR_TYPE_RGB:
3297 {
3298 if (row_info->bit_depth == 8)
3299 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003300 sp = row;
3301 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003302 {
3303 *sp = gamma_table[*sp];
3304 sp++;
3305 *sp = gamma_table[*sp];
3306 sp++;
3307 *sp = gamma_table[*sp];
3308 sp++;
3309 }
3310 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003311 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003312 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003313 sp = row;
3314 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003315 {
3316 png_uint_16 v;
3317
Andreas Dilger47a0c421997-05-16 02:46:07 -05003318 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003319 *sp = (png_byte)((v >> 8) & 0xff);
3320 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003321 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003322 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003323 *sp = (png_byte)((v >> 8) & 0xff);
3324 *(sp + 1) = (png_byte)(v & 0xff);
3325 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003326 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003327 *sp = (png_byte)((v >> 8) & 0xff);
3328 *(sp + 1) = (png_byte)(v & 0xff);
3329 sp += 2;
3330 }
3331 }
3332 break;
3333 }
3334 case PNG_COLOR_TYPE_RGB_ALPHA:
3335 {
3336 if (row_info->bit_depth == 8)
3337 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003338 sp = row;
3339 for (i = 0; i < row_width; i++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003340 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003341 *sp = gamma_table[*sp];
3342 sp++;
3343 *sp = gamma_table[*sp];
3344 sp++;
3345 *sp = gamma_table[*sp];
3346 sp++;
3347 sp++;
3348 }
3349 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003350 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003351 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003352 sp = row;
3353 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003354 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003355 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003356 *sp = (png_byte)((v >> 8) & 0xff);
3357 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003358 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003359 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003360 *sp = (png_byte)((v >> 8) & 0xff);
3361 *(sp + 1) = (png_byte)(v & 0xff);
3362 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003363 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003364 *sp = (png_byte)((v >> 8) & 0xff);
3365 *(sp + 1) = (png_byte)(v & 0xff);
3366 sp += 4;
3367 }
3368 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003369 break;
3370 }
3371 case PNG_COLOR_TYPE_GRAY_ALPHA:
3372 {
3373 if (row_info->bit_depth == 8)
3374 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003375 sp = row;
3376 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003377 {
3378 *sp = gamma_table[*sp];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003379 sp += 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05003380 }
3381 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003382 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003383 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003384 sp = row;
3385 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003386 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003387 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003388 *sp = (png_byte)((v >> 8) & 0xff);
3389 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003390 sp += 4;
3391 }
3392 }
3393 break;
3394 }
3395 case PNG_COLOR_TYPE_GRAY:
3396 {
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003397 if (row_info->bit_depth == 2)
3398 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003399 sp = row;
3400 for (i = 0; i < row_width; i += 4)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003401 {
3402 int a = *sp & 0xc0;
3403 int b = *sp & 0x30;
3404 int c = *sp & 0x0c;
3405 int d = *sp & 0x03;
3406
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003407 *sp = (png_byte)(
3408 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003409 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3410 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003411 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003412 sp++;
3413 }
3414 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003415 if (row_info->bit_depth == 4)
Guy Schalnat0d580581995-07-20 02:43:20 -05003416 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003417 sp = row;
3418 for (i = 0; i < row_width; i += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003419 {
3420 int msb = *sp & 0xf0;
3421 int lsb = *sp & 0x0f;
3422
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003423 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3424 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003425 sp++;
3426 }
3427 }
3428 else if (row_info->bit_depth == 8)
3429 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003430 sp = row;
3431 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003432 {
3433 *sp = gamma_table[*sp];
3434 sp++;
3435 }
3436 }
3437 else if (row_info->bit_depth == 16)
3438 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003439 sp = row;
3440 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003441 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003442 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003443 *sp = (png_byte)((v >> 8) & 0xff);
3444 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003445 sp += 2;
3446 }
3447 }
3448 break;
3449 }
3450 }
3451 }
3452}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003453#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003454
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003455#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -05003456/* Expands a palette row to an RGB or RGBA row depending
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003457 * upon whether you supply trans and num_trans.
3458 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003459void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003460png_do_expand_palette(png_row_infop row_info, png_bytep row,
Andreas Dilger47a0c421997-05-16 02:46:07 -05003461 png_colorp palette, png_bytep trans, int num_trans)
Guy Schalnat0d580581995-07-20 02:43:20 -05003462{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003463 int shift, value;
Guy Schalnat6d764711995-12-19 03:22:19 -06003464 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003465 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003466 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003467
Andreas Dilger47a0c421997-05-16 02:46:07 -05003468 png_debug(1, "in png_do_expand_palette\n");
3469 if (
3470#if defined(PNG_USELESS_TESTS_SUPPORTED)
3471 row != NULL && row_info != NULL &&
3472#endif
3473 row_info->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05003474 {
3475 if (row_info->bit_depth < 8)
3476 {
3477 switch (row_info->bit_depth)
3478 {
3479 case 1:
3480 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003481 sp = row + (png_size_t)((row_width - 1) >> 3);
3482 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003483 shift = 7 - (int)((row_width + 7) & 0x07);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003484 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003485 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003486 if ((*sp >> shift) & 0x01)
Guy Schalnat0d580581995-07-20 02:43:20 -05003487 *dp = 1;
3488 else
3489 *dp = 0;
3490 if (shift == 7)
3491 {
3492 shift = 0;
3493 sp--;
3494 }
3495 else
3496 shift++;
3497
3498 dp--;
3499 }
3500 break;
3501 }
3502 case 2:
3503 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003504 sp = row + (png_size_t)((row_width - 1) >> 2);
3505 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003506 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003507 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003508 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003509 value = (*sp >> shift) & 0x03;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003510 *dp = (png_byte)value;
Guy Schalnat0d580581995-07-20 02:43:20 -05003511 if (shift == 6)
3512 {
3513 shift = 0;
3514 sp--;
3515 }
3516 else
3517 shift += 2;
3518
3519 dp--;
3520 }
3521 break;
3522 }
3523 case 4:
3524 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003525 sp = row + (png_size_t)((row_width - 1) >> 1);
3526 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003527 shift = (int)((row_width & 0x01) << 2);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003528 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003529 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003530 value = (*sp >> shift) & 0x0f;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003531 *dp = (png_byte)value;
Guy Schalnat0d580581995-07-20 02:43:20 -05003532 if (shift == 4)
3533 {
3534 shift = 0;
3535 sp--;
3536 }
3537 else
3538 shift += 4;
3539
3540 dp--;
3541 }
3542 break;
3543 }
3544 }
3545 row_info->bit_depth = 8;
3546 row_info->pixel_depth = 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003547 row_info->rowbytes = row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -05003548 }
3549 switch (row_info->bit_depth)
3550 {
3551 case 8:
3552 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003553 if (trans != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05003554 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003555 sp = row + (png_size_t)row_width - 1;
3556 dp = row + (png_size_t)(row_width << 2) - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003557
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003558 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003559 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003560 if ((int)(*sp) >= num_trans)
Guy Schalnat0d580581995-07-20 02:43:20 -05003561 *dp-- = 0xff;
3562 else
3563 *dp-- = trans[*sp];
3564 *dp-- = palette[*sp].blue;
3565 *dp-- = palette[*sp].green;
3566 *dp-- = palette[*sp].red;
3567 sp--;
3568 }
3569 row_info->bit_depth = 8;
3570 row_info->pixel_depth = 32;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003571 row_info->rowbytes = row_width * 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05003572 row_info->color_type = 6;
3573 row_info->channels = 4;
3574 }
3575 else
3576 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003577 sp = row + (png_size_t)row_width - 1;
3578 dp = row + (png_size_t)(row_width * 3) - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003579
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003580 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003581 {
3582 *dp-- = palette[*sp].blue;
3583 *dp-- = palette[*sp].green;
3584 *dp-- = palette[*sp].red;
3585 sp--;
3586 }
3587 row_info->bit_depth = 8;
3588 row_info->pixel_depth = 24;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003589 row_info->rowbytes = row_width * 3;
Guy Schalnat0d580581995-07-20 02:43:20 -05003590 row_info->color_type = 2;
3591 row_info->channels = 3;
3592 }
3593 break;
3594 }
3595 }
3596 }
3597}
3598
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003599/* If the bit depth < 8, it is expanded to 8. Also, if the
3600 * transparency value is supplied, an alpha channel is built.
3601 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003602void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003603png_do_expand(png_row_infop row_info, png_bytep row,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003604 png_color_16p trans_value)
Guy Schalnat0d580581995-07-20 02:43:20 -05003605{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003606 int shift, value;
Guy Schalnat6d764711995-12-19 03:22:19 -06003607 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003608 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003609 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003610
Andreas Dilger47a0c421997-05-16 02:46:07 -05003611 png_debug(1, "in png_do_expand\n");
3612#if defined(PNG_USELESS_TESTS_SUPPORTED)
3613 if (row != NULL && row_info != NULL)
3614#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003615 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003616 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05003617 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003618 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003619
3620 if (row_info->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003621 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003622 switch (row_info->bit_depth)
Guy Schalnat0d580581995-07-20 02:43:20 -05003623 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003624 case 1:
3625 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003626 gray = (png_uint_16)(gray*0xff);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003627 sp = row + (png_size_t)((row_width - 1) >> 3);
3628 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003629 shift = 7 - (int)((row_width + 7) & 0x07);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003630 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003631 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003632 if ((*sp >> shift) & 0x01)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003633 *dp = 0xff;
3634 else
3635 *dp = 0;
3636 if (shift == 7)
3637 {
3638 shift = 0;
3639 sp--;
3640 }
3641 else
3642 shift++;
3643
3644 dp--;
3645 }
3646 break;
3647 }
3648 case 2:
3649 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003650 gray = (png_uint_16)(gray*0x55);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003651 sp = row + (png_size_t)((row_width - 1) >> 2);
3652 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003653 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003654 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003655 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003656 value = (*sp >> shift) & 0x03;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003657 *dp = (png_byte)(value | (value << 2) | (value << 4) |
3658 (value << 6));
3659 if (shift == 6)
3660 {
3661 shift = 0;
3662 sp--;
3663 }
3664 else
3665 shift += 2;
3666
3667 dp--;
3668 }
3669 break;
3670 }
3671 case 4:
3672 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003673 gray = (png_uint_16)(gray*0x11);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003674 sp = row + (png_size_t)((row_width - 1) >> 1);
3675 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003676 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003677 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003678 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003679 value = (*sp >> shift) & 0x0f;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003680 *dp = (png_byte)(value | (value << 4));
3681 if (shift == 4)
3682 {
3683 shift = 0;
3684 sp--;
3685 }
3686 else
3687 shift = 4;
3688
3689 dp--;
3690 }
3691 break;
3692 }
3693 }
3694 row_info->bit_depth = 8;
3695 row_info->pixel_depth = 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003696 row_info->rowbytes = row_width;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003697 }
3698
Andreas Dilger47a0c421997-05-16 02:46:07 -05003699 if (trans_value != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003700 {
3701 if (row_info->bit_depth == 8)
3702 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003703 sp = row + (png_size_t)row_width - 1;
3704 dp = row + (png_size_t)(row_width << 1) - 1;
3705 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003706 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003707 if (*sp == gray)
3708 *dp-- = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003709 else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003710 *dp-- = 0xff;
3711 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003712 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003713 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003714 else if (row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -05003715 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003716 sp = row + row_info->rowbytes - 1;
3717 dp = row + (row_info->rowbytes << 1) - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003718 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003719 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003720 if (((png_uint_16)*(sp) |
3721 ((png_uint_16)*(sp - 1) << 8)) == gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05003722 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003723 *dp-- = 0;
3724 *dp-- = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003725 }
3726 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003727 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003728 *dp-- = 0xff;
3729 *dp-- = 0xff;
Guy Schalnat0d580581995-07-20 02:43:20 -05003730 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003731 *dp-- = *sp--;
3732 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003733 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003734 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003735 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3736 row_info->channels = 2;
3737 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3738 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003739 ((row_width * row_info->pixel_depth) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003740 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003741 }
3742 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3743 {
3744 if (row_info->bit_depth == 8)
3745 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003746 sp = row + (png_size_t)row_info->rowbytes - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003747 dp = row + (png_size_t)(row_width << 2) - 1;
3748 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003749 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003750 if (*(sp - 2) == trans_value->red &&
Guy Schalnat0d580581995-07-20 02:43:20 -05003751 *(sp - 1) == trans_value->green &&
3752 *(sp - 0) == trans_value->blue)
3753 *dp-- = 0;
3754 else
3755 *dp-- = 0xff;
3756 *dp-- = *sp--;
3757 *dp-- = *sp--;
3758 *dp-- = *sp--;
3759 }
3760 }
3761 else if (row_info->bit_depth == 16)
3762 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003763 sp = row + row_info->rowbytes - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003764 dp = row + (png_size_t)(row_width << 3) - 1;
3765 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003766 {
3767 if ((((png_uint_16)*(sp - 4) |
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003768 ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
Guy Schalnat0d580581995-07-20 02:43:20 -05003769 (((png_uint_16)*(sp - 2) |
3770 ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
3771 (((png_uint_16)*(sp - 0) |
3772 ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
3773 {
3774 *dp-- = 0;
3775 *dp-- = 0;
3776 }
3777 else
3778 {
3779 *dp-- = 0xff;
3780 *dp-- = 0xff;
3781 }
3782 *dp-- = *sp--;
3783 *dp-- = *sp--;
3784 *dp-- = *sp--;
3785 *dp-- = *sp--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003786 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003787 *dp-- = *sp--;
3788 }
3789 }
3790 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3791 row_info->channels = 4;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003792 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
Guy Schalnat0d580581995-07-20 02:43:20 -05003793 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003794 ((row_width * row_info->pixel_depth) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003795 }
3796 }
3797}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003798#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003799
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003800#if defined(PNG_READ_DITHER_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003801void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003802png_do_dither(png_row_infop row_info, png_bytep row,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003803 png_bytep palette_lookup, png_bytep dither_lookup)
Guy Schalnat0d580581995-07-20 02:43:20 -05003804{
Guy Schalnat6d764711995-12-19 03:22:19 -06003805 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003806 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003807 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003808
Andreas Dilger47a0c421997-05-16 02:46:07 -05003809 png_debug(1, "in png_do_dither\n");
3810#if defined(PNG_USELESS_TESTS_SUPPORTED)
3811 if (row != NULL && row_info != NULL)
3812#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003813 {
3814 if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3815 palette_lookup && row_info->bit_depth == 8)
3816 {
3817 int r, g, b, p;
Guy Schalnat0d580581995-07-20 02:43:20 -05003818 sp = row;
3819 dp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003820 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003821 {
3822 r = *sp++;
3823 g = *sp++;
3824 b = *sp++;
3825
3826 /* this looks real messy, but the compiler will reduce
3827 it down to a reasonable formula. For example, with
3828 5 bits per color, we get:
3829 p = (((r >> 3) & 0x1f) << 10) |
3830 (((g >> 3) & 0x1f) << 5) |
3831 ((b >> 3) & 0x1f);
3832 */
3833 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3834 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3835 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3836 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003837 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
Guy Schalnat0d580581995-07-20 02:43:20 -05003838 (PNG_DITHER_BLUE_BITS)) |
3839 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3840 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3841
3842 *dp++ = palette_lookup[p];
3843 }
3844 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3845 row_info->channels = 1;
3846 row_info->pixel_depth = row_info->bit_depth;
3847 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003848 ((row_width * row_info->pixel_depth + 7) >> 3);
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;
3877 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003878 ((row_width * row_info->pixel_depth + 7) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003879 }
3880 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
3881 dither_lookup && row_info->bit_depth == 8)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003882 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003883 sp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003884 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003885 {
3886 *sp = dither_lookup[*sp];
3887 }
3888 }
3889 }
3890}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003891#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003892
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003893#ifdef PNG_FLOATING_POINT_SUPPORTED
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003894#if defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003895static int png_gamma_shift[] =
3896 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
3897
Andreas Dilger47a0c421997-05-16 02:46:07 -05003898/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003899 * tables, we don't make a full table if we are reducing to 8-bit in
3900 * the future. Note also how the gamma_16 tables are segmented so that
3901 * we don't need to allocate > 64K chunks for a full 16-bit table.
3902 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003903void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003904png_build_gamma_table(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05003905{
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003906 png_debug(1, "in png_build_gamma_table\n");
3907 if(png_ptr->gamma != 0.0)
3908 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003909 if (png_ptr->bit_depth <= 8)
3910 {
3911 int i;
3912 double g;
3913
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003914 if (png_ptr->screen_gamma > .000001)
3915 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3916 else
3917 g = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003918
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003919 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003920 (png_uint_32)256);
3921
3922 for (i = 0; i < 256; i++)
3923 {
3924 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
3925 g) * 255.0 + .5);
3926 }
3927
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003928#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3929 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003930 if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -05003931 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003932
Guy Schalnat0d580581995-07-20 02:43:20 -05003933 g = 1.0 / (png_ptr->gamma);
3934
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003935 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003936 (png_uint_32)256);
3937
3938 for (i = 0; i < 256; i++)
3939 {
3940 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
3941 g) * 255.0 + .5);
3942 }
3943
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003944
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003945 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003946 (png_uint_32)256);
3947
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003948 if(png_ptr->screen_gamma > 0.000001)
3949 g = 1.0 / png_ptr->screen_gamma;
3950 else
3951 g = png_ptr->gamma; /* probably doing rgb_to_gray */
3952
Guy Schalnat0d580581995-07-20 02:43:20 -05003953 for (i = 0; i < 256; i++)
3954 {
3955 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
3956 g) * 255.0 + .5);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003957
Guy Schalnat0d580581995-07-20 02:43:20 -05003958 }
3959 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003960#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003961 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003962 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003963 {
3964 double g;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003965 int i, j, shift, num;
3966 int sig_bit;
3967 png_uint_32 ig;
Guy Schalnat0d580581995-07-20 02:43:20 -05003968
3969 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003970 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003971 sig_bit = (int)png_ptr->sig_bit.red;
3972 if ((int)png_ptr->sig_bit.green > sig_bit)
3973 sig_bit = png_ptr->sig_bit.green;
3974 if ((int)png_ptr->sig_bit.blue > sig_bit)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003975 sig_bit = png_ptr->sig_bit.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003976 }
3977 else
3978 {
3979 sig_bit = (int)png_ptr->sig_bit.gray;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003980 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003981
3982 if (sig_bit > 0)
3983 shift = 16 - sig_bit;
3984 else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003985 shift = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003986
3987 if (png_ptr->transformations & PNG_16_TO_8)
3988 {
3989 if (shift < (16 - PNG_MAX_GAMMA_8))
3990 shift = (16 - PNG_MAX_GAMMA_8);
3991 }
3992
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003993 if (shift > 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003994 shift = 8;
3995 if (shift < 0)
3996 shift = 0;
3997
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003998 png_ptr->gamma_shift = (png_byte)shift;
Guy Schalnat0d580581995-07-20 02:43:20 -05003999
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004000 num = (1 << (8 - shift));
Guy Schalnat0d580581995-07-20 02:43:20 -05004001
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004002 if (png_ptr->screen_gamma > .000001)
4003 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4004 else
4005 g = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -05004006
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004007 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004008 (png_uint_32)(num * sizeof (png_uint_16p)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004009
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004010 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004011 {
4012 double fin, fout;
4013 png_uint_32 last, max;
Guy Schalnat0d580581995-07-20 02:43:20 -05004014
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004015 for (i = 0; i < num; i++)
4016 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004017 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004018 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004019 }
Guy Schalnat0d580581995-07-20 02:43:20 -05004020
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004021 g = 1.0 / g;
4022 last = 0;
4023 for (i = 0; i < 256; i++)
4024 {
4025 fout = ((double)i + 0.5) / 256.0;
4026 fin = pow(fout, g);
4027 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
4028 while (last <= max)
4029 {
4030 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4031 [(int)(last >> (8 - shift))] = (png_uint_16)(
4032 (png_uint_16)i | ((png_uint_16)i << 8));
4033 last++;
4034 }
4035 }
4036 while (last < ((png_uint_32)num << 8))
4037 {
4038 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
Andreas Dilger47a0c421997-05-16 02:46:07 -05004039 [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004040 last++;
Guy Schalnat6d764711995-12-19 03:22:19 -06004041 }
Guy Schalnat0d580581995-07-20 02:43:20 -05004042 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004043 else
4044 {
4045 for (i = 0; i < num; i++)
4046 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004047 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004048 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004049
Andreas Dilger47a0c421997-05-16 02:46:07 -05004050 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004051 for (j = 0; j < 256; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05004052 {
4053 png_ptr->gamma_16_table[i][j] =
4054 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4055 65535.0, g) * 65535.0 + .5);
4056 }
4057 }
4058 }
4059
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004060#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4061 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4062 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -05004063 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004064
Guy Schalnat0d580581995-07-20 02:43:20 -05004065 g = 1.0 / (png_ptr->gamma);
4066
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004067 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004068 (png_uint_32)(num * sizeof (png_uint_16p )));
Guy Schalnat0d580581995-07-20 02:43:20 -05004069
4070 for (i = 0; i < num; i++)
4071 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004072 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004073 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004074
4075 ig = (((png_uint_32)i *
4076 (png_uint_32)png_gamma_shift[shift]) >> 4);
4077 for (j = 0; j < 256; j++)
4078 {
4079 png_ptr->gamma_16_to_1[i][j] =
4080 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4081 65535.0, g) * 65535.0 + .5);
4082 }
4083 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004084
4085 if(png_ptr->screen_gamma > 0.000001)
4086 g = 1.0 / png_ptr->screen_gamma;
4087 else
4088 g = png_ptr->gamma; /* probably doing rgb_to_gray */
Guy Schalnat0d580581995-07-20 02:43:20 -05004089
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004090 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004091 (png_uint_32)(num * sizeof (png_uint_16p)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004092
4093 for (i = 0; i < num; i++)
4094 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004095 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004096 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004097
4098 ig = (((png_uint_32)i *
4099 (png_uint_32)png_gamma_shift[shift]) >> 4);
4100 for (j = 0; j < 256; j++)
4101 {
4102 png_ptr->gamma_16_from_1[i][j] =
4103 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4104 65535.0, g) * 65535.0 + .5);
4105 }
4106 }
4107 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004108#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05004109 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004110 }
Guy Schalnat0d580581995-07-20 02:43:20 -05004111}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05004112#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06004113/* To do: install integer version of png_build_gamma_table here */
4114#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -05004115
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -06004116#if defined(PNG_MNG_FEATURES_SUPPORTED)
4117/* undoes intrapixel differencing */
4118void /* PRIVATE */
4119png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4120{
4121 png_debug(1, "in png_do_read_intrapixel\n");
4122 if (
4123#if defined(PNG_USELESS_TESTS_SUPPORTED)
4124 row != NULL && row_info != NULL &&
4125#endif
4126 (row_info->color_type & PNG_COLOR_MASK_COLOR))
4127 {
4128 int bytes_per_pixel;
4129 png_uint_32 row_width = row_info->width;
4130 if (row_info->bit_depth == 8)
4131 {
4132 png_bytep rp;
4133 png_uint_32 i;
4134
4135 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4136 bytes_per_pixel = 3;
4137 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4138 bytes_per_pixel = 4;
4139 else
4140 return;
4141
4142 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4143 {
4144 *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
4145 *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
4146 }
4147 }
4148 else if (row_info->bit_depth == 16)
4149 {
4150 png_bytep rp;
4151 png_uint_32 i;
4152
4153 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4154 bytes_per_pixel = 6;
4155 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4156 bytes_per_pixel = 8;
4157 else
4158 return;
4159
4160 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4161 {
4162 png_uint_32 s0=*(rp )<<8 | *(rp+1);
4163 png_uint_32 s1=*(rp+2)<<8 | *(rp+3);
4164 png_uint_32 s2=*(rp+4)<<8 | *(rp+5);
4165 png_uint_32 red=(65536+s0+s1)&0xffff;
4166 png_uint_32 blue=(65536+s2+s1)&0xffff;
4167 *(rp ) = (png_byte)((red>>8)&0xff);
4168 *(rp+1) = (png_byte)(red&0xff);
4169 *(rp+4) = (png_byte)((blue>>8)&0xff);
4170 *(rp+5) = (png_byte)(blue&0xff);
4171 }
4172 }
4173 }
4174}
4175#endif /* PNG_MNG_FEATURES_SUPPORTED */