blob: abc132f3bf167a87accde22ae13a86d42347422b [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-Pehrson73d57cb2002-03-25 18:49:08 -06004 * libpng 1.2.2beta5 - March 26, 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 Schalnatb2e01bd1996-01-26 01:38:47 -0600170 png_bytep sort;
Guy Schalnat0d580581995-07-20 02:43:20 -0500171
172 /* initialize an array to sort colors */
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600173 sort = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_palette
174 * sizeof (png_byte)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500175
176 /* initialize the sort array */
177 for (i = 0; i < num_palette; i++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600178 sort[i] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500179
Andreas Dilger47a0c421997-05-16 02:46:07 -0500180 /* Find the least used palette entries by starting a
Guy Schalnat0d580581995-07-20 02:43:20 -0500181 bubble sort, and running it until we have sorted
182 out enough colors. Note that we don't care about
183 sorting all the colors, just finding which are
184 least used. */
185
186 for (i = num_palette - 1; i >= maximum_colors; i--)
187 {
188 int done; /* to stop early if the list is pre-sorted */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600189 int j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500190
191 done = 1;
192 for (j = 0; j < i; j++)
193 {
194 if (histogram[sort[j]] < histogram[sort[j + 1]])
195 {
196 png_byte t;
197
198 t = sort[j];
199 sort[j] = sort[j + 1];
200 sort[j + 1] = t;
201 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-Pehrson0f881d61998-02-07 10:20:57 -0600217 if ((int)sort[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500218 {
219 do
220 j--;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600221 while ((int)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-Pehrson0f881d61998-02-07 10:20:57 -0600235 if ((int)sort[i] >= maximum_colors)
Guy Schalnat0d580581995-07-20 02:43:20 -0500236 {
237 png_color tmp_color;
238
239 do
240 j--;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600241 while ((int)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 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600279 png_free(png_ptr, sort);
Guy Schalnat0d580581995-07-20 02:43:20 -0500280 }
281 else
282 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500283 /* This is much harder to do simply (and quickly). Perhaps
Guy Schalnat0d580581995-07-20 02:43:20 -0500284 we need to go through a median cut routine, but those
285 don't always behave themselves with only a few colors
286 as input. So we will just find the closest two colors,
287 and throw out one of them (chosen somewhat randomly).
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600288 [We don't understand this at all, so if someone wants to
289 work on improving it, be our guest - AED, GRP]
Guy Schalnat0d580581995-07-20 02:43:20 -0500290 */
291 int i;
292 int max_d;
293 int num_new_palette;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600294 png_dsortpp hash;
295 png_bytep index_to_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500296 /* where the original index currently is in the palette */
Guy Schalnat6d764711995-12-19 03:22:19 -0600297 png_bytep palette_to_index;
Guy Schalnat0d580581995-07-20 02:43:20 -0500298 /* which original index points to this palette color */
299
300 /* initialize palette index arrays */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600301 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)));
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600303 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 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600309 index_to_palette[i] = (png_byte)i;
310 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 Schalnat6d764711995-12-19 03:22:19 -0600345 png_dsortp t;
Guy Schalnat0d580581995-07-20 02:43:20 -0500346
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600347 t = (png_dsortp)png_malloc(png_ptr, (png_uint_32)(sizeof
348 (png_dsort)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500349 t->next = hash[d];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600350 t->left = (png_byte)i;
351 t->right = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500352 hash[d] = t;
353 }
354 }
355 }
356
357 for (i = 0; i <= max_d; i++)
358 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500359 if (hash[i] != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500360 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600361 png_dsortp p;
Guy Schalnat0d580581995-07-20 02:43:20 -0500362
363 for (p = hash[i]; p; p = p->next)
364 {
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600365 if ((int)index_to_palette[p->left] < num_new_palette &&
366 (int)index_to_palette[p->right] < num_new_palette)
Guy Schalnat0d580581995-07-20 02:43:20 -0500367 {
368 int j, next_j;
369
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600370 if (num_new_palette & 0x01)
Guy Schalnat0d580581995-07-20 02:43:20 -0500371 {
372 j = p->left;
373 next_j = p->right;
374 }
375 else
376 {
377 j = p->right;
378 next_j = p->left;
379 }
380
381 num_new_palette--;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500382 palette[index_to_palette[j]] = palette[num_new_palette];
Guy Schalnat0d580581995-07-20 02:43:20 -0500383 if (!full_dither)
384 {
385 int k;
386
387 for (k = 0; k < num_palette; k++)
388 {
389 if (png_ptr->dither_index[k] ==
390 index_to_palette[j])
391 png_ptr->dither_index[k] =
392 index_to_palette[next_j];
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600393 if ((int)png_ptr->dither_index[k] ==
Guy Schalnat0d580581995-07-20 02:43:20 -0500394 num_new_palette)
395 png_ptr->dither_index[k] =
396 index_to_palette[j];
397 }
398 }
399
400 index_to_palette[palette_to_index[num_new_palette]] =
401 index_to_palette[j];
402 palette_to_index[index_to_palette[j]] =
403 palette_to_index[num_new_palette];
404
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600405 index_to_palette[j] = (png_byte)num_new_palette;
406 palette_to_index[num_new_palette] = (png_byte)j;
Guy Schalnat0d580581995-07-20 02:43:20 -0500407 }
408 if (num_new_palette <= maximum_colors)
409 break;
410 }
411 if (num_new_palette <= maximum_colors)
412 break;
413 }
414 }
415
416 for (i = 0; i < 769; i++)
417 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500418 if (hash[i] != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500419 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500420 png_dsortp p = hash[i];
Guy Schalnat0d580581995-07-20 02:43:20 -0500421 while (p)
422 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600423 png_dsortp t;
Guy Schalnat0d580581995-07-20 02:43:20 -0500424
425 t = p->next;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600426 png_free(png_ptr, p);
Guy Schalnat0d580581995-07-20 02:43:20 -0500427 p = t;
428 }
429 }
430 hash[i] = 0;
431 }
432 max_d += 96;
433 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600434 png_free(png_ptr, hash);
435 png_free(png_ptr, palette_to_index);
436 png_free(png_ptr, index_to_palette);
Guy Schalnat0d580581995-07-20 02:43:20 -0500437 }
438 num_palette = maximum_colors;
439 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500440 if (png_ptr->palette == NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600441 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500442 png_ptr->palette = palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500443 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600444 png_ptr->num_palette = (png_uint_16)num_palette;
Guy Schalnat0d580581995-07-20 02:43:20 -0500445
446 if (full_dither)
447 {
448 int i;
Guy Schalnat6d764711995-12-19 03:22:19 -0600449 png_bytep distance;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500450 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600451 PNG_DITHER_BLUE_BITS;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500452 int num_red = (1 << PNG_DITHER_RED_BITS);
453 int num_green = (1 << PNG_DITHER_GREEN_BITS);
454 int num_blue = (1 << PNG_DITHER_BLUE_BITS);
455 png_size_t num_entries = ((png_size_t)1 << total_bits);
Guy Schalnat0d580581995-07-20 02:43:20 -0500456
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600457 png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600458 (png_uint_32)(num_entries * sizeof (png_byte)));
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500459
460 png_memset(png_ptr->palette_lookup, 0, num_entries * sizeof (png_byte));
Guy Schalnat0d580581995-07-20 02:43:20 -0500461
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600462 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
463 sizeof(png_byte)));
Glenn Randers-Pehrsone1eff582001-04-14 20:15:41 -0500464
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500465 png_memset(distance, 0xff, num_entries * sizeof(png_byte));
466
467 for (i = 0; i < num_palette; i++)
468 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500469 int ir, ig, ib;
470 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
471 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
472 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
Guy Schalnat0d580581995-07-20 02:43:20 -0500473
474 for (ir = 0; ir < num_red; ir++)
475 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500476 int dr = abs(ir - r);
477 int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
Guy Schalnat0d580581995-07-20 02:43:20 -0500478
Guy Schalnat0d580581995-07-20 02:43:20 -0500479 for (ig = 0; ig < num_green; ig++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600480 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500481 int dg = abs(ig - g);
482 int dt = dr + dg;
483 int dm = ((dr > dg) ? dr : dg);
484 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
Guy Schalnat0d580581995-07-20 02:43:20 -0500485
Guy Schalnat0d580581995-07-20 02:43:20 -0500486 for (ib = 0; ib < num_blue; ib++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600487 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500488 int d_index = index_g | ib;
489 int db = abs(ib - b);
490 int dmax = ((dm > db) ? dm : db);
491 int d = dmax + dt + db;
Guy Schalnat0d580581995-07-20 02:43:20 -0500492
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600493 if (d < (int)distance[d_index])
Guy Schalnat0d580581995-07-20 02:43:20 -0500494 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500495 distance[d_index] = (png_byte)d;
496 png_ptr->palette_lookup[d_index] = (png_byte)i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500497 }
498 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500499 }
500 }
501 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500502
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600503 png_free(png_ptr, distance);
Guy Schalnat0d580581995-07-20 02:43:20 -0500504 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500505}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500506#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500507
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600508#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600509/* Transform the image from the file_gamma to the screen_gamma. We
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600510 * only do transformations on images where the file_gamma and screen_gamma
511 * are not close reciprocals, otherwise it slows things down slightly, and
512 * also needlessly introduces small errors.
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -0600513 *
514 * We will turn off gamma transformation later if no semitransparent entries
515 * are present in the tRNS array for palette images. We can't do it here
516 * because we don't necessarily have the tRNS chunk yet.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600517 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500518void PNGAPI
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600519png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
Guy Schalnat0d580581995-07-20 02:43:20 -0500520{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500521 png_debug(1, "in png_set_gamma\n");
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -0600522 if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
523 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
524 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
525 png_ptr->transformations |= PNG_GAMMA;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500526 png_ptr->gamma = (float)file_gamma;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600527 png_ptr->screen_gamma = (float)scrn_gamma;
Guy Schalnat0d580581995-07-20 02:43:20 -0500528}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500529#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500530
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500531#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -0500532/* Expand paletted images to RGB, expand grayscale images of
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500533 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600534 * to alpha channels.
535 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500536void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600537png_set_expand(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500538{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500539 png_debug(1, "in png_set_expand\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500540 png_ptr->transformations |= PNG_EXPAND;
541}
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500542
543/* GRR 19990627: the following three functions currently are identical
544 * to png_set_expand(). However, it is entirely reasonable that someone
545 * might wish to expand an indexed image to RGB but *not* expand a single,
546 * fully transparent palette entry to a full alpha channel--perhaps instead
547 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
548 * the transparent color with a particular RGB value, or drop tRNS entirely.
549 * IOW, a future version of the library may make the transformations flag
550 * a bit more fine-grained, with separate bits for each of these three
551 * functions.
552 *
553 * More to the point, these functions make it obvious what libpng will be
554 * doing, whereas "expand" can (and does) mean any number of things.
555 */
556
557/* Expand paletted images to RGB. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500558void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500559png_set_palette_to_rgb(png_structp png_ptr)
560{
561 png_debug(1, "in png_set_expand\n");
562 png_ptr->transformations |= PNG_EXPAND;
563}
564
565/* Expand grayscale images of less than 8-bit depth to 8 bits. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500566void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500567png_set_gray_1_2_4_to_8(png_structp png_ptr)
568{
569 png_debug(1, "in png_set_expand\n");
570 png_ptr->transformations |= PNG_EXPAND;
571}
572
573/* Expand tRNS chunks to alpha channels. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500574void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500575png_set_tRNS_to_alpha(png_structp png_ptr)
576{
577 png_debug(1, "in png_set_expand\n");
578 png_ptr->transformations |= PNG_EXPAND;
579}
580#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
Guy Schalnat0d580581995-07-20 02:43:20 -0500581
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500582#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500583void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600584png_set_gray_to_rgb(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500585{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500586 png_debug(1, "in png_set_gray_to_rgb\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500587 png_ptr->transformations |= PNG_GRAY_TO_RGB;
588}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500589#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500590
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600591#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
592#if defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600593/* Convert a RGB image to a grayscale of the same width. This allows us,
594 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600595 */
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600596
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500597void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500598png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600599 double green)
600{
601 int red_fixed = (int)((float)red*100000.0 + 0.5);
602 int green_fixed = (int)((float)green*100000.0 + 0.5);
603 png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
604}
605#endif
606
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500607void PNGAPI
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600608png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
609 png_fixed_point red, png_fixed_point green)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600610{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500611 png_debug(1, "in png_set_rgb_to_gray\n");
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600612 switch(error_action)
613 {
614 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
615 break;
616 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
617 break;
618 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
619 }
620 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
621#if defined(PNG_READ_EXPAND_SUPPORTED)
622 png_ptr->transformations |= PNG_EXPAND;
623#else
624 {
625 png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
626 png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
627 }
628#endif
629 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600630 png_uint_16 red_int, green_int;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600631 if(red < 0 || green < 0)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600632 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600633 red_int = 6968; /* .212671 * 32768 + .5 */
634 green_int = 23434; /* .715160 * 32768 + .5 */
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600635 }
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600636 else if(red + green < 100000L)
637 {
638 red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
639 green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
640 }
641 else
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600642 {
643 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600644 red_int = 6968;
645 green_int = 23434;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600646 }
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600647 png_ptr->rgb_to_gray_red_coeff = red_int;
648 png_ptr->rgb_to_gray_green_coeff = green_int;
649 png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600650 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600651}
652#endif
653
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500654#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
655 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
656 defined(PNG_LEGACY_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500657void PNGAPI
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600658png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
659 read_user_transform_fn)
660{
661 png_debug(1, "in png_set_read_user_transform_fn\n");
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500662#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600663 png_ptr->transformations |= PNG_USER_TRANSFORM;
664 png_ptr->read_user_transform_fn = read_user_transform_fn;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500665#endif
666#ifdef PNG_LEGACY_SUPPORTED
667 if(read_user_transform_fn)
668 png_warning(png_ptr,
669 "This version of libpng does not support user transforms");
670#endif
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600671}
672#endif
673
Andreas Dilger47a0c421997-05-16 02:46:07 -0500674/* Initialize everything needed for the read. This includes modifying
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600675 * the palette.
676 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500677void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600678png_init_read_transformations(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500679{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500680 png_debug(1, "in png_init_read_transformations\n");
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500681#if defined(PNG_USELESS_TESTS_SUPPORTED)
682 if(png_ptr != NULL)
683#endif
684 {
685#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
686 || defined(PNG_READ_GAMMA_SUPPORTED)
687 int color_type = png_ptr->color_type;
688#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500689
Guy Schalnate5a37791996-06-05 15:50:50 -0500690#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600691 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
692 (png_ptr->transformations & PNG_EXPAND))
Guy Schalnat0d580581995-07-20 02:43:20 -0500693 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500694 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
Guy Schalnat0d580581995-07-20 02:43:20 -0500695 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500696 /* expand background chunk. */
Guy Schalnat0d580581995-07-20 02:43:20 -0500697 switch (png_ptr->bit_depth)
698 {
699 case 1:
Guy Schalnate5a37791996-06-05 15:50:50 -0500700 png_ptr->background.gray *= (png_uint_16)0xff;
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600701 png_ptr->background.red = png_ptr->background.green
702 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500703 break;
704 case 2:
Guy Schalnate5a37791996-06-05 15:50:50 -0500705 png_ptr->background.gray *= (png_uint_16)0x55;
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600706 png_ptr->background.red = png_ptr->background.green
707 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500708 break;
709 case 4:
Guy Schalnate5a37791996-06-05 15:50:50 -0500710 png_ptr->background.gray *= (png_uint_16)0x11;
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600711 png_ptr->background.red = png_ptr->background.green
712 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnate5a37791996-06-05 15:50:50 -0500713 break;
714 case 8:
715 case 16:
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600716 png_ptr->background.red = png_ptr->background.green
717 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500718 break;
719 }
720 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500721 else if (color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -0500722 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500723 png_ptr->background.red =
Guy Schalnat0d580581995-07-20 02:43:20 -0500724 png_ptr->palette[png_ptr->background.index].red;
725 png_ptr->background.green =
726 png_ptr->palette[png_ptr->background.index].green;
Guy Schalnate5a37791996-06-05 15:50:50 -0500727 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -0500728 png_ptr->palette[png_ptr->background.index].blue;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600729
730#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
731 if (png_ptr->transformations & PNG_INVERT_ALPHA)
732 {
733#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600734 if (!(png_ptr->transformations & PNG_EXPAND))
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600735#endif
736 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600737 /* invert the alpha channel (in tRNS) unless the pixels are
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600738 going to be expanded, in which case leave it for later */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500739 int i,istop;
740 istop=(int)png_ptr->num_trans;
741 for (i=0; i<istop; i++)
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -0500742 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600743 }
744 }
745#endif
746
Guy Schalnat0d580581995-07-20 02:43:20 -0500747 }
748 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500749#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500750
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -0500751#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500752 png_ptr->background_1 = png_ptr->background;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500753#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600754#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -0600755
756 if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
757 && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
758 < PNG_GAMMA_THRESHOLD))
759 {
760 int i,k;
761 k=0;
762 for (i=0; i<png_ptr->num_trans; i++)
763 {
764 if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
765 k=1; /* partial transparency is present */
766 }
767 if (k == 0)
768 png_ptr->transformations &= (~PNG_GAMMA);
769 }
770
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600771 if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -0500772 {
773 png_build_gamma_table(png_ptr);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500774#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Guy Schalnate5a37791996-06-05 15:50:50 -0500775 if (png_ptr->transformations & PNG_BACKGROUND)
Guy Schalnat0d580581995-07-20 02:43:20 -0500776 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500777 if (color_type == PNG_COLOR_TYPE_PALETTE)
778 {
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -0600779 /* could skip if no transparency and
780 */
Guy Schalnate5a37791996-06-05 15:50:50 -0500781 png_color back, back_1;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500782 png_colorp palette = png_ptr->palette;
783 int num_palette = png_ptr->num_palette;
784 int i;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500785 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
786 {
787 back.red = png_ptr->gamma_table[png_ptr->background.red];
788 back.green = png_ptr->gamma_table[png_ptr->background.green];
789 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
Guy Schalnate5a37791996-06-05 15:50:50 -0500790
Andreas Dilger47a0c421997-05-16 02:46:07 -0500791 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
792 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
793 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
794 }
795 else
796 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600797 double g, gs;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500798
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600799 switch (png_ptr->background_gamma_type)
Glenn Randers-Pehrson4922b1b1998-03-08 22:55:17 -0600800 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600801 case PNG_BACKGROUND_GAMMA_SCREEN:
802 g = (png_ptr->screen_gamma);
803 gs = 1.0;
804 break;
805 case PNG_BACKGROUND_GAMMA_FILE:
806 g = 1.0 / (png_ptr->gamma);
807 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
808 break;
809 case PNG_BACKGROUND_GAMMA_UNIQUE:
810 g = 1.0 / (png_ptr->background_gamma);
811 gs = 1.0 / (png_ptr->background_gamma *
812 png_ptr->screen_gamma);
813 break;
814 default:
815 g = 1.0; /* back_1 */
816 gs = 1.0; /* back */
817 }
818
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -0600819 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600820 {
821 back.red = (png_byte)png_ptr->background.red;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500822 back.green = (png_byte)png_ptr->background.green;
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600823 back.blue = (png_byte)png_ptr->background.blue;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500824 }
825 else
826 {
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600827 back.red = (png_byte)(pow(
828 (double)png_ptr->background.red/255, gs) * 255.0 + .5);
829 back.green = (png_byte)(pow(
830 (double)png_ptr->background.green/255, gs) * 255.0 + .5);
831 back.blue = (png_byte)(pow(
832 (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500833 }
834
Glenn Randers-Pehrson8f8fb6a1998-03-09 23:02:06 -0600835 back_1.red = (png_byte)(pow(
836 (double)png_ptr->background.red/255, g) * 255.0 + .5);
837 back_1.green = (png_byte)(pow(
838 (double)png_ptr->background.green/255, g) * 255.0 + .5);
839 back_1.blue = (png_byte)(pow(
840 (double)png_ptr->background.blue/255, g) * 255.0 + .5);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500841 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500842 for (i = 0; i < num_palette; i++)
843 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500844 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
Guy Schalnate5a37791996-06-05 15:50:50 -0500845 {
846 if (png_ptr->trans[i] == 0)
847 {
848 palette[i] = back;
849 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500850 else /* if (png_ptr->trans[i] != 0xff) */
Guy Schalnate5a37791996-06-05 15:50:50 -0500851 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500852 png_byte v, w;
Guy Schalnate5a37791996-06-05 15:50:50 -0500853
854 v = png_ptr->gamma_to_1[palette[i].red];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500855 png_composite(w, v, png_ptr->trans[i], back_1.red);
Guy Schalnate5a37791996-06-05 15:50:50 -0500856 palette[i].red = png_ptr->gamma_from_1[w];
857
858 v = png_ptr->gamma_to_1[palette[i].green];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500859 png_composite(w, v, png_ptr->trans[i], back_1.green);
Guy Schalnate5a37791996-06-05 15:50:50 -0500860 palette[i].green = png_ptr->gamma_from_1[w];
861
862 v = png_ptr->gamma_to_1[palette[i].blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -0500863 png_composite(w, v, png_ptr->trans[i], back_1.blue);
Guy Schalnate5a37791996-06-05 15:50:50 -0500864 palette[i].blue = png_ptr->gamma_from_1[w];
865 }
866 }
867 else
868 {
869 palette[i].red = png_ptr->gamma_table[palette[i].red];
870 palette[i].green = png_ptr->gamma_table[palette[i].green];
871 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
872 }
873 }
874 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500875 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN)*/
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600876 else
877 /* color_type != PNG_COLOR_TYPE_PALETTE */
Guy Schalnat0d580581995-07-20 02:43:20 -0500878 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500879 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
880 double g = 1.0;
881 double gs = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500882
883 switch (png_ptr->background_gamma_type)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600884 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500885 case PNG_BACKGROUND_GAMMA_SCREEN:
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600886 g = (png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500887 gs = 1.0;
888 break;
889 case PNG_BACKGROUND_GAMMA_FILE:
890 g = 1.0 / (png_ptr->gamma);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600891 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500892 break;
893 case PNG_BACKGROUND_GAMMA_UNIQUE:
894 g = 1.0 / (png_ptr->background_gamma);
895 gs = 1.0 / (png_ptr->background_gamma *
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600896 png_ptr->screen_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500897 break;
898 }
899
Glenn Randers-Pehrson377657d2002-03-08 01:31:27 -0600900 png_ptr->background_1.gray = (png_uint_16)(pow(
901 (double)png_ptr->background.gray / m, g) * m + .5);
902 png_ptr->background.gray = (png_uint_16)(pow(
903 (double)png_ptr->background.gray / m, gs) * m + .5);
904
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600905 if ((png_ptr->background.red != png_ptr->background.green) ||
906 (png_ptr->background.red != png_ptr->background.blue) ||
907 (png_ptr->background.red != png_ptr->background.gray))
Guy Schalnat0d580581995-07-20 02:43:20 -0500908 {
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600909 /* RGB or RGBA with color background */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600910 png_ptr->background_1.red = (png_uint_16)(pow(
Guy Schalnat0d580581995-07-20 02:43:20 -0500911 (double)png_ptr->background.red / m, g) * m + .5);
912 png_ptr->background_1.green = (png_uint_16)(pow(
913 (double)png_ptr->background.green / m, g) * m + .5);
914 png_ptr->background_1.blue = (png_uint_16)(pow(
915 (double)png_ptr->background.blue / m, g) * m + .5);
916 png_ptr->background.red = (png_uint_16)(pow(
917 (double)png_ptr->background.red / m, gs) * m + .5);
918 png_ptr->background.green = (png_uint_16)(pow(
919 (double)png_ptr->background.green / m, gs) * m + .5);
920 png_ptr->background.blue = (png_uint_16)(pow(
921 (double)png_ptr->background.blue / m, gs) * m + .5);
922 }
923 else
924 {
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -0600925 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
926 png_ptr->background_1.red = png_ptr->background_1.green
927 = png_ptr->background_1.blue = png_ptr->background_1.gray;
928 png_ptr->background.red = png_ptr->background.green
929 = png_ptr->background.blue = png_ptr->background.gray;
Guy Schalnat0d580581995-07-20 02:43:20 -0500930 }
931 }
932 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500933 else
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600934 /* transformation does not include PNG_BACKGROUND */
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -0500935#endif /* PNG_READ_BACKGROUND_SUPPORTED */
Guy Schalnate5a37791996-06-05 15:50:50 -0500936 if (color_type == PNG_COLOR_TYPE_PALETTE)
937 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500938 png_colorp palette = png_ptr->palette;
939 int num_palette = png_ptr->num_palette;
940 int i;
Guy Schalnate5a37791996-06-05 15:50:50 -0500941
942 for (i = 0; i < num_palette; i++)
943 {
944 palette[i].red = png_ptr->gamma_table[palette[i].red];
945 palette[i].green = png_ptr->gamma_table[palette[i].green];
946 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
947 }
948 }
949 }
950#if defined(PNG_READ_BACKGROUND_SUPPORTED)
951 else
952#endif
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -0500953#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
Guy Schalnate5a37791996-06-05 15:50:50 -0500954#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -0600955 /* No GAMMA transformation */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600956 if ((png_ptr->transformations & PNG_BACKGROUND) &&
957 (color_type == PNG_COLOR_TYPE_PALETTE))
Guy Schalnate5a37791996-06-05 15:50:50 -0500958 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500959 int i;
960 int istop = (int)png_ptr->num_trans;
Guy Schalnate5a37791996-06-05 15:50:50 -0500961 png_color back;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500962 png_colorp palette = png_ptr->palette;
Guy Schalnate5a37791996-06-05 15:50:50 -0500963
Guy Schalnate5a37791996-06-05 15:50:50 -0500964 back.red = (png_byte)png_ptr->background.red;
965 back.green = (png_byte)png_ptr->background.green;
966 back.blue = (png_byte)png_ptr->background.blue;
967
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500968 for (i = 0; i < istop; i++)
Guy Schalnate5a37791996-06-05 15:50:50 -0500969 {
970 if (png_ptr->trans[i] == 0)
971 {
972 palette[i] = back;
973 }
974 else if (png_ptr->trans[i] != 0xff)
975 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500976 /* The png_composite() macro is defined in png.h */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500977 png_composite(palette[i].red, palette[i].red,
978 png_ptr->trans[i], back.red);
979 png_composite(palette[i].green, palette[i].green,
980 png_ptr->trans[i], back.green);
981 png_composite(palette[i].blue, palette[i].blue,
982 png_ptr->trans[i], back.blue);
Guy Schalnate5a37791996-06-05 15:50:50 -0500983 }
984 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500985 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -0500986#endif /* PNG_READ_BACKGROUND_SUPPORTED */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500987
Guy Schalnat6d764711995-12-19 03:22:19 -0600988#if defined(PNG_READ_SHIFT_SUPPORTED)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500989 if ((png_ptr->transformations & PNG_SHIFT) &&
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600990 (color_type == PNG_COLOR_TYPE_PALETTE))
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500991 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500992 png_uint_16 i;
993 png_uint_16 istop = png_ptr->num_palette;
994 int sr = 8 - png_ptr->sig_bit.red;
995 int sg = 8 - png_ptr->sig_bit.green;
996 int sb = 8 - png_ptr->sig_bit.blue;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500997
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500998 if (sr < 0 || sr > 8)
999 sr = 0;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001000 if (sg < 0 || sg > 8)
1001 sg = 0;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001002 if (sb < 0 || sb > 8)
1003 sb = 0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001004 for (i = 0; i < istop; i++)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001005 {
1006 png_ptr->palette[i].red >>= sr;
1007 png_ptr->palette[i].green >>= sg;
1008 png_ptr->palette[i].blue >>= sb;
1009 }
1010 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05001011#endif /* PNG_READ_SHIFT_SUPPORTED */
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001012 }
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001013#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1014 && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1015 if(png_ptr)
1016 return;
1017#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001018}
1019
Andreas Dilger47a0c421997-05-16 02:46:07 -05001020/* Modify the info structure to reflect the transformations. The
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001021 * info should be updated so a PNG file could be written with it,
1022 * assuming the transformations result in valid PNG data.
1023 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001024void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001025png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001026{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001027 png_debug(1, "in png_read_transform_info\n");
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001028#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001029 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001030 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001031 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1032 {
1033 if (png_ptr->num_trans)
1034 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1035 else
1036 info_ptr->color_type = PNG_COLOR_TYPE_RGB;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001037 info_ptr->bit_depth = 8;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001038 info_ptr->num_trans = 0;
1039 }
1040 else
1041 {
1042 if (png_ptr->num_trans)
1043 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1044 if (info_ptr->bit_depth < 8)
1045 info_ptr->bit_depth = 8;
1046 info_ptr->num_trans = 0;
1047 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001048 }
1049#endif
1050
1051#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1052 if (png_ptr->transformations & PNG_BACKGROUND)
1053 {
1054 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1055 info_ptr->num_trans = 0;
1056 info_ptr->background = png_ptr->background;
1057 }
1058#endif
1059
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001060#if defined(PNG_READ_GAMMA_SUPPORTED)
1061 if (png_ptr->transformations & PNG_GAMMA)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001062 {
1063#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001064 info_ptr->gamma = png_ptr->gamma;
1065#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001066#ifdef PNG_FIXED_POINT_SUPPORTED
1067 info_ptr->int_gamma = png_ptr->int_gamma;
1068#endif
1069 }
1070#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001071
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001072#if defined(PNG_READ_16_TO_8_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001073 if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001074 info_ptr->bit_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001075#endif
1076
1077#if defined(PNG_READ_DITHER_SUPPORTED)
1078 if (png_ptr->transformations & PNG_DITHER)
1079 {
1080 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1081 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1082 png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1083 {
1084 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1085 }
1086 }
1087#endif
1088
1089#if defined(PNG_READ_PACK_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001090 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001091 info_ptr->bit_depth = 8;
1092#endif
1093
1094#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001095 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001096 info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1097#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001098
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001099#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1100 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1101 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1102#endif
1103
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001104 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001105 info_ptr->channels = 1;
1106 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1107 info_ptr->channels = 3;
1108 else
1109 info_ptr->channels = 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001110
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001111#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001112 if (png_ptr->transformations & PNG_STRIP_ALPHA)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001113 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001114#endif
1115
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001116 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1117 info_ptr->channels++;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001118
1119#if defined(PNG_READ_FILLER_SUPPORTED)
1120 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001121 if ((png_ptr->transformations & PNG_FILLER) &&
1122 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1123 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001124 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001125 info_ptr->channels++;
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001126#if 0 /* if adding a true alpha channel not just filler */
1127 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1128#endif
1129 }
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001130#endif
1131
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001132#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1133defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001134 if(png_ptr->transformations & PNG_USER_TRANSFORM)
1135 {
1136 if(info_ptr->bit_depth < png_ptr->user_transform_depth)
1137 info_ptr->bit_depth = png_ptr->user_transform_depth;
1138 if(info_ptr->channels < png_ptr->user_transform_channels)
1139 info_ptr->channels = png_ptr->user_transform_channels;
1140 }
1141#endif
1142
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001143 info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1144 info_ptr->bit_depth);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001145 info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3);
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05001146
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001147#if !defined(PNG_READ_EXPAND_SUPPORTED)
1148 if(png_ptr)
1149 return;
1150#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001151}
1152
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001153/* Transform the row. The order of transformations is significant,
1154 * and is very touchy. If you add a transformation, take care to
1155 * decide how it fits in with the other transformations here.
1156 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001157void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001158png_do_read_transformations(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05001159{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001160 png_debug(1, "in png_do_read_transformations\n");
1161#if !defined(PNG_USELESS_TESTS_SUPPORTED)
1162 if (png_ptr->row_buf == NULL)
1163 {
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -05001164#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001165 char msg[50];
1166
1167 sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
1168 png_ptr->pass);
1169 png_error(png_ptr, msg);
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001170#else
1171 png_error(png_ptr, "NULL row buffer");
1172#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001173 }
1174#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001175
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001176#if defined(PNG_READ_EXPAND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001177 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05001178 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001179 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1180 {
1181 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1182 png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1183 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001184 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001185 {
1186 if (png_ptr->num_trans)
1187 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1188 &(png_ptr->trans_values));
1189 else
1190 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1191 NULL);
1192 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001193 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001194#endif
1195
1196#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1197 if (png_ptr->transformations & PNG_STRIP_ALPHA)
1198 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1199 PNG_FLAG_FILLER_AFTER);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001200#endif
1201
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001202#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1203 if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1204 {
1205 int rgb_error =
1206 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1207 if(rgb_error)
1208 {
1209 png_ptr->rgb_to_gray_status=1;
1210 if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
1211 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1212 if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
1213 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1214 }
1215 }
1216#endif
1217
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001218/*
1219From Andreas Dilger e-mail to png-implement, 26 March 1998:
1220
1221 In most cases, the "simple transparency" should be done prior to doing
1222 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 -06001223 pixel is transparent. You would also need to make sure that the
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001224 transparency information is upgraded to RGB.
1225
1226 To summarize, the current flow is:
1227 - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1228 with background "in place" if transparent,
1229 convert to RGB if necessary
1230 - Gray + alpha -> composite with gray background and remove alpha bytes,
1231 convert to RGB if necessary
1232
1233 To support RGB backgrounds for gray images we need:
1234 - Gray + simple transparency -> convert to RGB + simple transparency, compare
1235 3 or 6 bytes and composite with background
1236 "in place" if transparent (3x compare/pixel
1237 compared to doing composite with gray bkgrnd)
1238 - Gray + alpha -> convert to RGB + alpha, composite with background and
1239 remove alpha bytes (3x float operations/pixel
1240 compared with composite on gray background)
1241
1242 Greg's change will do this. The reason it wasn't done before is for
1243 performance, as this increases the per-pixel operations. If we would check
1244 in advance if the background was gray or RGB, and position the gray-to-RGB
1245 transform appropriately, then it would save a lot of work/time.
1246 */
1247
1248#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1249 /* if gray -> RGB, do so now only if background is non-gray; else do later
1250 * for performance reasons */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001251 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06001252 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001253 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1254#endif
1255
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001256#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001257 if ((png_ptr->transformations & PNG_BACKGROUND) &&
1258 ((png_ptr->num_trans != 0 ) ||
1259 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
Guy Schalnat0d580581995-07-20 02:43:20 -05001260 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05001261 &(png_ptr->trans_values), &(png_ptr->background)
1262#if defined(PNG_READ_GAMMA_SUPPORTED)
1263 , &(png_ptr->background_1),
Guy Schalnat0d580581995-07-20 02:43:20 -05001264 png_ptr->gamma_table, png_ptr->gamma_from_1,
1265 png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1266 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05001267 png_ptr->gamma_shift
1268#endif
1269);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001270#endif
1271
1272#if defined(PNG_READ_GAMMA_SUPPORTED)
1273 if ((png_ptr->transformations & PNG_GAMMA) &&
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001274#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1275 !((png_ptr->transformations & PNG_BACKGROUND) &&
1276 ((png_ptr->num_trans != 0) ||
1277 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1278#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001279 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
Guy Schalnat0d580581995-07-20 02:43:20 -05001280 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1281 png_ptr->gamma_table, png_ptr->gamma_16_table,
1282 png_ptr->gamma_shift);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001283#endif
1284
1285#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001286 if (png_ptr->transformations & PNG_16_TO_8)
1287 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001288#endif
1289
1290#if defined(PNG_READ_DITHER_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001291 if (png_ptr->transformations & PNG_DITHER)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001292 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001293 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1294 png_ptr->palette_lookup, png_ptr->dither_index);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001295 if(png_ptr->row_info.rowbytes == (png_uint_32)0)
1296 png_error(png_ptr, "png_do_dither returned rowbytes=0");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001297 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001298#endif
1299
1300#if defined(PNG_READ_INVERT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001301 if (png_ptr->transformations & PNG_INVERT_MONO)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001302 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001303#endif
1304
1305#if defined(PNG_READ_SHIFT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001306 if (png_ptr->transformations & PNG_SHIFT)
1307 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1308 &(png_ptr->shift));
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001309#endif
1310
1311#if defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001312 if (png_ptr->transformations & PNG_PACK)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001313 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001314#endif
1315
1316#if defined(PNG_READ_BGR_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001317 if (png_ptr->transformations & PNG_BGR)
1318 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001319#endif
1320
Andreas Dilger47a0c421997-05-16 02:46:07 -05001321#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1322 if (png_ptr->transformations & PNG_PACKSWAP)
1323 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1324#endif
1325
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001326#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001327 /* if gray -> RGB, do so now only if we did not do so above */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001328 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1329 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -05001330 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001331#endif
1332
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001333#if defined(PNG_READ_FILLER_SUPPORTED)
1334 if (png_ptr->transformations & PNG_FILLER)
1335 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001336 (png_uint_32)png_ptr->filler, png_ptr->flags);
1337#endif
1338
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001339#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1340 if (png_ptr->transformations & PNG_INVERT_ALPHA)
1341 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1342#endif
1343
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001344#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1345 if (png_ptr->transformations & PNG_SWAP_ALPHA)
1346 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1347#endif
1348
Andreas Dilger47a0c421997-05-16 02:46:07 -05001349#if defined(PNG_READ_SWAP_SUPPORTED)
1350 if (png_ptr->transformations & PNG_SWAP_BYTES)
1351 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001352#endif
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001353
1354#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1355 if (png_ptr->transformations & PNG_USER_TRANSFORM)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001356 {
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001357 if(png_ptr->read_user_transform_fn != NULL)
1358 (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1359 (png_ptr, /* png_ptr */
1360 &(png_ptr->row_info), /* row_info: */
1361 /* png_uint_32 width; width of row */
1362 /* png_uint_32 rowbytes; number of bytes in row */
1363 /* png_byte color_type; color type of pixels */
1364 /* png_byte bit_depth; bit depth of samples */
1365 /* png_byte channels; number of channels (1-4) */
1366 /* png_byte pixel_depth; bits per pixel (depth*channels) */
1367 png_ptr->row_buf + 1); /* start of pixel data for row */
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001368#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001369 if(png_ptr->user_transform_depth)
1370 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1371 if(png_ptr->user_transform_channels)
1372 png_ptr->row_info.channels = png_ptr->user_transform_channels;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001373#endif
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001374 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1375 png_ptr->row_info.channels);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001376 png_ptr->row_info.rowbytes = (png_ptr->row_info.width *
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001377 png_ptr->row_info.pixel_depth+7)>>3;
1378 }
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001379#endif
1380
Guy Schalnat0d580581995-07-20 02:43:20 -05001381}
1382
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001383#if defined(PNG_READ_PACK_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001384/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1385 * without changing the actual values. Thus, if you had a row with
1386 * a bit depth of 1, you would end up with bytes that only contained
1387 * the numbers 0 or 1. If you would rather they contain 0 and 255, use
1388 * png_do_shift() after this.
1389 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001390void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001391png_do_unpack(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001392{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001393 png_debug(1, "in png_do_unpack\n");
1394#if defined(PNG_USELESS_TESTS_SUPPORTED)
1395 if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1396#else
1397 if (row_info->bit_depth < 8)
1398#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001399 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001400 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001401 png_uint_32 row_width=row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001402
Guy Schalnat0d580581995-07-20 02:43:20 -05001403 switch (row_info->bit_depth)
1404 {
1405 case 1:
1406 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001407 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1408 png_bytep dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001409 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001410 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001411 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001412 *dp = (png_byte)((*sp >> shift) & 0x01);
Guy Schalnat0d580581995-07-20 02:43:20 -05001413 if (shift == 7)
1414 {
1415 shift = 0;
1416 sp--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001417 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001418 else
1419 shift++;
1420
1421 dp--;
1422 }
1423 break;
1424 }
1425 case 2:
1426 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001427
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001428 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1429 png_bytep dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001430 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001431 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001432 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001433 *dp = (png_byte)((*sp >> shift) & 0x03);
Guy Schalnat0d580581995-07-20 02:43:20 -05001434 if (shift == 6)
1435 {
1436 shift = 0;
1437 sp--;
1438 }
1439 else
1440 shift += 2;
1441
1442 dp--;
1443 }
1444 break;
1445 }
1446 case 4:
1447 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001448 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1449 png_bytep dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001450 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001451 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001452 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001453 *dp = (png_byte)((*sp >> shift) & 0x0f);
Guy Schalnat0d580581995-07-20 02:43:20 -05001454 if (shift == 4)
1455 {
1456 shift = 0;
1457 sp--;
1458 }
1459 else
1460 shift = 4;
1461
1462 dp--;
1463 }
1464 break;
1465 }
1466 }
1467 row_info->bit_depth = 8;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001468 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001469 row_info->rowbytes = row_width * row_info->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -05001470 }
1471}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001472#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001473
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001474#if defined(PNG_READ_SHIFT_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001475/* Reverse the effects of png_do_shift. This routine merely shifts the
1476 * pixels back to their significant bits values. Thus, if you have
1477 * a row of bit depth 8, but only 5 are significant, this will shift
1478 * the values back to 0 through 31.
1479 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001480void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001481png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
Guy Schalnat0d580581995-07-20 02:43:20 -05001482{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001483 png_debug(1, "in png_do_unshift\n");
1484 if (
1485#if defined(PNG_USELESS_TESTS_SUPPORTED)
1486 row != NULL && row_info != NULL && sig_bits != NULL &&
1487#endif
1488 row_info->color_type != PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05001489 {
1490 int shift[4];
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001491 int channels = 0;
1492 int c;
1493 png_uint_16 value = 0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001494 png_uint_32 row_width = row_info->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001495
Guy Schalnat0d580581995-07-20 02:43:20 -05001496 if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1497 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001498 shift[channels++] = row_info->bit_depth - sig_bits->red;
1499 shift[channels++] = row_info->bit_depth - sig_bits->green;
1500 shift[channels++] = row_info->bit_depth - sig_bits->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05001501 }
1502 else
1503 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001504 shift[channels++] = row_info->bit_depth - sig_bits->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05001505 }
1506 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1507 {
Guy Schalnat6d764711995-12-19 03:22:19 -06001508 shift[channels++] = row_info->bit_depth - sig_bits->alpha;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001509 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001510
Andreas Dilger47a0c421997-05-16 02:46:07 -05001511 for (c = 0; c < channels; c++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001512 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001513 if (shift[c] <= 0)
1514 shift[c] = 0;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001515 else
1516 value = 1;
1517 }
Guy Schalnat0f716451995-11-28 11:22:13 -06001518
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001519 if (!value)
1520 return;
Guy Schalnat0f716451995-11-28 11:22:13 -06001521
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001522 switch (row_info->bit_depth)
Guy Schalnat0d580581995-07-20 02:43:20 -05001523 {
1524 case 2:
1525 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001526 png_bytep bp;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001527 png_uint_32 i;
1528 png_uint_32 istop = row_info->rowbytes;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001529
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001530 for (bp = row, i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001531 {
1532 *bp >>= 1;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001533 *bp++ &= 0x55;
Guy Schalnat0d580581995-07-20 02:43:20 -05001534 }
1535 break;
1536 }
1537 case 4:
1538 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001539 png_bytep bp = row;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001540 png_uint_32 i;
1541 png_uint_32 istop = row_info->rowbytes;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001542 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1543 (png_byte)((int)0xf >> shift[0]));
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001544
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001545 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001546 {
1547 *bp >>= shift[0];
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001548 *bp++ &= mask;
Guy Schalnat0d580581995-07-20 02:43:20 -05001549 }
1550 break;
1551 }
1552 case 8:
1553 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001554 png_bytep bp = row;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001555 png_uint_32 i;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001556 png_uint_32 istop = row_width * channels;
Guy Schalnat0d580581995-07-20 02:43:20 -05001557
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001558 for (i = 0; i < istop; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001559 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001560 *bp++ >>= shift[i%channels];
Guy Schalnat0d580581995-07-20 02:43:20 -05001561 }
1562 break;
1563 }
1564 case 16:
1565 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001566 png_bytep bp = row;
1567 png_uint_32 i;
1568 png_uint_32 istop = channels * row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001569
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001570 for (i = 0; i < istop; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001571 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001572 value = (png_uint_16)((*bp << 8) + *(bp + 1));
1573 value >>= shift[i%channels];
1574 *bp++ = (png_byte)(value >> 8);
1575 *bp++ = (png_byte)(value & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05001576 }
1577 break;
1578 }
1579 }
1580 }
1581}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001582#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001583
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001584#if defined(PNG_READ_16_TO_8_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001585/* chop rows of bit depth 16 down to 8 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001586void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001587png_do_chop(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05001588{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001589 png_debug(1, "in png_do_chop\n");
1590#if defined(PNG_USELESS_TESTS_SUPPORTED)
1591 if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1592#else
1593 if (row_info->bit_depth == 16)
1594#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001595 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001596 png_bytep sp = row;
1597 png_bytep dp = row;
1598 png_uint_32 i;
1599 png_uint_32 istop = row_info->width * row_info->channels;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001600
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001601 for (i = 0; i<istop; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001602 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001603#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001604 /* This does a more accurate scaling of the 16-bit color
1605 * value, rather than a simple low-byte truncation.
1606 *
1607 * What the ideal calculation should be:
1608 * *dp = (((((png_uint_32)(*sp) << 8) |
1609 * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1610 *
1611 * GRR: no, I think this is what it really should be:
1612 * *dp = (((((png_uint_32)(*sp) << 8) |
1613 * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1614 *
1615 * GRR: here's the exact calculation with shifts:
1616 * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1617 * *dp = (temp - (temp >> 8)) >> 8;
1618 *
1619 * Approximate calculation with shift/add instead of multiply/divide:
1620 * *dp = ((((png_uint_32)(*sp) << 8) |
1621 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1622 *
1623 * What we actually do to avoid extra shifting and conversion:
1624 */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001625
Andreas Dilger47a0c421997-05-16 02:46:07 -05001626 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1627#else
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001628 /* Simply discard the low order byte */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001629 *dp = *sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001630#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001631 }
1632 row_info->bit_depth = 8;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001633 row_info->pixel_depth = (png_byte)(8 * row_info->channels);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001634 row_info->rowbytes = row_info->width * row_info->channels;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001635 }
1636}
1637#endif
1638
1639#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001640void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001641png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1642{
1643 png_debug(1, "in png_do_read_swap_alpha\n");
1644#if defined(PNG_USELESS_TESTS_SUPPORTED)
1645 if (row != NULL && row_info != NULL)
1646#endif
1647 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001648 png_uint_32 row_width = row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001649 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1650 {
1651 /* This converts from RGBA to ARGB */
1652 if (row_info->bit_depth == 8)
1653 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001654 png_bytep sp = row + row_info->rowbytes;
1655 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001656 png_byte save;
1657 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001658
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001659 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001660 {
1661 save = *(--sp);
1662 *(--dp) = *(--sp);
1663 *(--dp) = *(--sp);
1664 *(--dp) = *(--sp);
1665 *(--dp) = save;
1666 }
1667 }
1668 /* This converts from RRGGBBAA to AARRGGBB */
1669 else
1670 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001671 png_bytep sp = row + row_info->rowbytes;
1672 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001673 png_byte save[2];
1674 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001675
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001676 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001677 {
1678 save[0] = *(--sp);
1679 save[1] = *(--sp);
1680 *(--dp) = *(--sp);
1681 *(--dp) = *(--sp);
1682 *(--dp) = *(--sp);
1683 *(--dp) = *(--sp);
1684 *(--dp) = *(--sp);
1685 *(--dp) = *(--sp);
1686 *(--dp) = save[0];
1687 *(--dp) = save[1];
1688 }
1689 }
1690 }
1691 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1692 {
1693 /* This converts from GA to AG */
1694 if (row_info->bit_depth == 8)
1695 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001696 png_bytep sp = row + row_info->rowbytes;
1697 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001698 png_byte save;
1699 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001700
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001701 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001702 {
1703 save = *(--sp);
1704 *(--dp) = *(--sp);
1705 *(--dp) = save;
1706 }
1707 }
1708 /* This converts from GGAA to AAGG */
1709 else
1710 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001711 png_bytep sp = row + row_info->rowbytes;
1712 png_bytep dp = sp;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001713 png_byte save[2];
1714 png_uint_32 i;
1715
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001716 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001717 {
1718 save[0] = *(--sp);
1719 save[1] = *(--sp);
1720 *(--dp) = *(--sp);
1721 *(--dp) = *(--sp);
1722 *(--dp) = save[0];
1723 *(--dp) = save[1];
1724 }
1725 }
1726 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001727 }
1728}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001729#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001730
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001731#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001732void /* PRIVATE */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001733png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1734{
1735 png_debug(1, "in png_do_read_invert_alpha\n");
1736#if defined(PNG_USELESS_TESTS_SUPPORTED)
1737 if (row != NULL && row_info != NULL)
1738#endif
1739 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001740 png_uint_32 row_width = row_info->width;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001741 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1742 {
1743 /* This inverts the alpha channel in RGBA */
1744 if (row_info->bit_depth == 8)
1745 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001746 png_bytep sp = row + row_info->rowbytes;
1747 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001748 png_uint_32 i;
1749
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001750 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001751 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001752 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001753
1754/* This does nothing:
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001755 *(--dp) = *(--sp);
1756 *(--dp) = *(--sp);
1757 *(--dp) = *(--sp);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001758 We can replace it with:
1759*/
1760 sp-=3;
1761 dp=sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001762 }
1763 }
1764 /* This inverts the alpha channel in RRGGBBAA */
1765 else
1766 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001767 png_bytep sp = row + row_info->rowbytes;
1768 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001769 png_uint_32 i;
1770
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001771 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001772 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001773 *(--dp) = (png_byte)(255 - *(--sp));
1774 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001775
1776/* This does nothing:
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001777 *(--dp) = *(--sp);
1778 *(--dp) = *(--sp);
1779 *(--dp) = *(--sp);
1780 *(--dp) = *(--sp);
1781 *(--dp) = *(--sp);
1782 *(--dp) = *(--sp);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001783 We can replace it with:
1784*/
1785 sp-=6;
1786 dp=sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001787 }
1788 }
1789 }
1790 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1791 {
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001792 /* This inverts the alpha channel in GA */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001793 if (row_info->bit_depth == 8)
1794 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001795 png_bytep sp = row + row_info->rowbytes;
1796 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001797 png_uint_32 i;
1798
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001799 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001800 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001801 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001802 *(--dp) = *(--sp);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001803 }
1804 }
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001805 /* This inverts the alpha channel in GGAA */
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001806 else
1807 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001808 png_bytep sp = row + row_info->rowbytes;
1809 png_bytep dp = sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001810 png_uint_32 i;
1811
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001812 for (i = 0; i < row_width; i++)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001813 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05001814 *(--dp) = (png_byte)(255 - *(--sp));
1815 *(--dp) = (png_byte)(255 - *(--sp));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001816/*
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001817 *(--dp) = *(--sp);
1818 *(--dp) = *(--sp);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001819*/
1820 sp-=2;
1821 dp=sp;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001822 }
1823 }
1824 }
1825 }
1826}
1827#endif
1828
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001829#if defined(PNG_READ_FILLER_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001830/* Add filler channel if we have RGB color */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001831void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06001832png_do_read_filler(png_row_infop row_info, png_bytep row,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001833 png_uint_32 filler, png_uint_32 flags)
Guy Schalnat0d580581995-07-20 02:43:20 -05001834{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001835 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001836 png_uint_32 row_width = row_info->width;
1837
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05001838 png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001839 png_byte lo_filler = (png_byte)(filler & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001840
1841 png_debug(1, "in png_do_read_filler\n");
1842 if (
1843#if defined(PNG_USELESS_TESTS_SUPPORTED)
1844 row != NULL && row_info != NULL &&
1845#endif
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001846 row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05001847 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001848 if(row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05001849 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001850 /* This changes the data from G to GX */
1851 if (flags & PNG_FLAG_FILLER_AFTER)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001852 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001853 png_bytep sp = row + (png_size_t)row_width;
1854 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001855 for (i = 1; i < row_width; i++)
1856 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001857 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001858 *(--dp) = *(--sp);
1859 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001860 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001861 row_info->channels = 2;
1862 row_info->pixel_depth = 16;
1863 row_info->rowbytes = row_width * 2;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001864 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001865 /* This changes the data from G to XG */
1866 else
1867 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001868 png_bytep sp = row + (png_size_t)row_width;
1869 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001870 for (i = 0; i < row_width; i++)
1871 {
1872 *(--dp) = *(--sp);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001873 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001874 }
1875 row_info->channels = 2;
1876 row_info->pixel_depth = 16;
1877 row_info->rowbytes = row_width * 2;
1878 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001879 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001880 else if(row_info->bit_depth == 16)
1881 {
1882 /* This changes the data from GG to GGXX */
1883 if (flags & PNG_FLAG_FILLER_AFTER)
1884 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001885 png_bytep sp = row + (png_size_t)row_width;
1886 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001887 for (i = 1; i < row_width; i++)
1888 {
1889 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001890 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001891 *(--dp) = *(--sp);
1892 *(--dp) = *(--sp);
1893 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001894 *(--dp) = hi_filler;
1895 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001896 row_info->channels = 2;
1897 row_info->pixel_depth = 32;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001898 row_info->rowbytes = row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001899 }
1900 /* This changes the data from GG to XXGG */
1901 else
1902 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001903 png_bytep sp = row + (png_size_t)row_width;
1904 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001905 for (i = 0; i < row_width; i++)
1906 {
1907 *(--dp) = *(--sp);
1908 *(--dp) = *(--sp);
1909 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001910 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001911 }
1912 row_info->channels = 2;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001913 row_info->pixel_depth = 32;
1914 row_info->rowbytes = row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001915 }
1916 }
1917 } /* COLOR_TYPE == GRAY */
1918 else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
1919 {
1920 if(row_info->bit_depth == 8)
1921 {
1922 /* This changes the data from RGB to RGBX */
1923 if (flags & PNG_FLAG_FILLER_AFTER)
1924 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001925 png_bytep sp = row + (png_size_t)row_width * 3;
1926 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001927 for (i = 1; i < row_width; i++)
1928 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001929 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001930 *(--dp) = *(--sp);
1931 *(--dp) = *(--sp);
1932 *(--dp) = *(--sp);
1933 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001934 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001935 row_info->channels = 4;
1936 row_info->pixel_depth = 32;
1937 row_info->rowbytes = row_width * 4;
1938 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001939 /* This changes the data from RGB to XRGB */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001940 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001941 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001942 png_bytep sp = row + (png_size_t)row_width * 3;
1943 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001944 for (i = 0; i < row_width; i++)
1945 {
1946 *(--dp) = *(--sp);
1947 *(--dp) = *(--sp);
1948 *(--dp) = *(--sp);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001949 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001950 }
1951 row_info->channels = 4;
1952 row_info->pixel_depth = 32;
1953 row_info->rowbytes = row_width * 4;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001954 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001955 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001956 else if(row_info->bit_depth == 16)
1957 {
1958 /* This changes the data from RRGGBB to RRGGBBXX */
1959 if (flags & PNG_FLAG_FILLER_AFTER)
1960 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001961 png_bytep sp = row + (png_size_t)row_width * 3;
1962 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001963 for (i = 1; i < row_width; i++)
1964 {
1965 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001966 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001967 *(--dp) = *(--sp);
1968 *(--dp) = *(--sp);
1969 *(--dp) = *(--sp);
1970 *(--dp) = *(--sp);
1971 *(--dp) = *(--sp);
1972 *(--dp) = *(--sp);
1973 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001974 *(--dp) = hi_filler;
1975 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001976 row_info->channels = 4;
1977 row_info->pixel_depth = 64;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001978 row_info->rowbytes = row_width * 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001979 }
1980 /* This changes the data from RRGGBB to XXRRGGBB */
1981 else
1982 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001983 png_bytep sp = row + (png_size_t)row_width * 3;
1984 png_bytep dp = sp + (png_size_t)row_width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001985 for (i = 0; i < row_width; i++)
1986 {
1987 *(--dp) = *(--sp);
1988 *(--dp) = *(--sp);
1989 *(--dp) = *(--sp);
1990 *(--dp) = *(--sp);
1991 *(--dp) = *(--sp);
1992 *(--dp) = *(--sp);
1993 *(--dp) = hi_filler;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001994 *(--dp) = lo_filler;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001995 }
1996 row_info->channels = 4;
1997 row_info->pixel_depth = 64;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001998 row_info->rowbytes = row_width * 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001999 }
2000 }
2001 } /* COLOR_TYPE == RGB */
Guy Schalnat0d580581995-07-20 02:43:20 -05002002}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002003#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002004
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002005#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002006/* expand grayscale files to RGB, with or without alpha */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002007void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002008png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -05002009{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002010 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002011 png_uint_32 row_width = row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06002012
Andreas Dilger47a0c421997-05-16 02:46:07 -05002013 png_debug(1, "in png_do_gray_to_rgb\n");
2014 if (row_info->bit_depth >= 8 &&
2015#if defined(PNG_USELESS_TESTS_SUPPORTED)
2016 row != NULL && row_info != NULL &&
2017#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002018 !(row_info->color_type & PNG_COLOR_MASK_COLOR))
2019 {
2020 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2021 {
2022 if (row_info->bit_depth == 8)
2023 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002024 png_bytep sp = row + (png_size_t)row_width - 1;
2025 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002026 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002027 {
2028 *(dp--) = *sp;
2029 *(dp--) = *sp;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002030 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05002031 }
2032 }
2033 else
2034 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002035 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2036 png_bytep dp = sp + (png_size_t)row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002037 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002038 {
2039 *(dp--) = *sp;
2040 *(dp--) = *(sp - 1);
2041 *(dp--) = *sp;
2042 *(dp--) = *(sp - 1);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002043 *(dp--) = *(sp--);
2044 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05002045 }
2046 }
2047 }
2048 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2049 {
2050 if (row_info->bit_depth == 8)
2051 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002052 png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2053 png_bytep dp = sp + (png_size_t)row_width * 2;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002054 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002055 {
2056 *(dp--) = *(sp--);
2057 *(dp--) = *sp;
2058 *(dp--) = *sp;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002059 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05002060 }
2061 }
2062 else
2063 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002064 png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2065 png_bytep dp = sp + (png_size_t)row_width * 4;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002066 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002067 {
2068 *(dp--) = *(sp--);
2069 *(dp--) = *(sp--);
2070 *(dp--) = *sp;
2071 *(dp--) = *(sp - 1);
2072 *(dp--) = *sp;
2073 *(dp--) = *(sp - 1);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002074 *(dp--) = *(sp--);
2075 *(dp--) = *(sp--);
Guy Schalnat0d580581995-07-20 02:43:20 -05002076 }
2077 }
2078 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002079 row_info->channels += (png_byte)2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002080 row_info->color_type |= PNG_COLOR_MASK_COLOR;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002081 row_info->pixel_depth = (png_byte)(row_info->channels *
2082 row_info->bit_depth);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002083 row_info->rowbytes = ((row_width *
Guy Schalnat0d580581995-07-20 02:43:20 -05002084 row_info->pixel_depth + 7) >> 3);
2085 }
2086}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002087#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002088
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002089#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002090/* reduce RGB files to grayscale, with or without alpha
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002091 * using the equation given in Poynton's ColorFAQ at
2092 * <http://www.inforamp.net/~poynton/>
2093 * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
2094 *
2095 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2096 *
2097 * We approximate this with
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002098 *
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002099 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002100 *
2101 * which can be expressed with integers as
2102 *
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002103 * Y = (6969 * R + 23434 * G + 2365 * B)/32768
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002104 *
2105 * The calculation is to be done in a linear colorspace.
2106 *
2107 * Other integer coefficents can be used via png_set_rgb_to_gray().
2108 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002109int /* PRIVATE */
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002110png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2111
2112{
2113 png_uint_32 i;
2114
2115 png_uint_32 row_width = row_info->width;
2116 int rgb_error = 0;
2117
2118 png_debug(1, "in png_do_rgb_to_gray\n");
2119 if (
2120#if defined(PNG_USELESS_TESTS_SUPPORTED)
2121 row != NULL && row_info != NULL &&
2122#endif
2123 (row_info->color_type & PNG_COLOR_MASK_COLOR))
2124 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002125 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2126 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2127 png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002128
2129 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2130 {
2131 if (row_info->bit_depth == 8)
2132 {
2133#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2134 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2135 {
2136 png_bytep sp = row;
2137 png_bytep dp = row;
2138
2139 for (i = 0; i < row_width; i++)
2140 {
2141 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2142 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2143 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2144 if(red != green || red != blue)
2145 {
2146 rgb_error |= 1;
2147 *(dp++) = png_ptr->gamma_from_1[
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002148 (rc*red+gc*green+bc*blue)>>15];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002149 }
2150 else
2151 *(dp++) = *(sp-1);
2152 }
2153 }
2154 else
2155#endif
2156 {
2157 png_bytep sp = row;
2158 png_bytep dp = row;
2159 for (i = 0; i < row_width; i++)
2160 {
2161 png_byte red = *(sp++);
2162 png_byte green = *(sp++);
2163 png_byte blue = *(sp++);
2164 if(red != green || red != blue)
2165 {
2166 rgb_error |= 1;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002167 *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002168 }
2169 else
2170 *(dp++) = *(sp-1);
2171 }
2172 }
2173 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002174
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002175 else /* RGB bit_depth == 16 */
2176 {
2177#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2178 if (png_ptr->gamma_16_to_1 != NULL &&
2179 png_ptr->gamma_16_from_1 != NULL)
2180 {
2181 png_bytep sp = row;
2182 png_bytep dp = row;
2183 for (i = 0; i < row_width; i++)
2184 {
2185 png_uint_16 red, green, blue, w;
2186
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002187 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2188 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2189 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002190
2191 if(red == green && red == blue)
2192 w = red;
2193 else
2194 {
2195 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2196 png_ptr->gamma_shift][red>>8];
2197 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2198 png_ptr->gamma_shift][green>>8];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002199 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002200 png_ptr->gamma_shift][blue>>8];
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002201 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002202 + bc*blue_1)>>15);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002203 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2204 png_ptr->gamma_shift][gray16 >> 8];
2205 rgb_error |= 1;
2206 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002207
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002208 *(dp++) = (png_byte)((w>>8) & 0xff);
2209 *(dp++) = (png_byte)(w & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002210 }
2211 }
2212 else
2213#endif
2214 {
2215 png_bytep sp = row;
2216 png_bytep dp = row;
2217 for (i = 0; i < row_width; i++)
2218 {
2219 png_uint_16 red, green, blue, gray16;
2220
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002221 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2222 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2223 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002224
2225 if(red != green || red != blue)
2226 rgb_error |= 1;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002227 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002228 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2229 *(dp++) = (png_byte)(gray16 & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002230 }
2231 }
2232 }
2233 }
2234 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2235 {
2236 if (row_info->bit_depth == 8)
2237 {
2238#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2239 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2240 {
2241 png_bytep sp = row;
2242 png_bytep dp = row;
2243 for (i = 0; i < row_width; i++)
2244 {
2245 png_byte red = png_ptr->gamma_to_1[*(sp++)];
2246 png_byte green = png_ptr->gamma_to_1[*(sp++)];
2247 png_byte blue = png_ptr->gamma_to_1[*(sp++)];
2248 if(red != green || red != blue)
2249 rgb_error |= 1;
2250 *(dp++) = png_ptr->gamma_from_1
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002251 [(rc*red + gc*green + bc*blue)>>15];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002252 *(dp++) = *(sp++); /* alpha */
2253 }
2254 }
2255 else
2256#endif
2257 {
2258 png_bytep sp = row;
2259 png_bytep dp = row;
2260 for (i = 0; i < row_width; i++)
2261 {
2262 png_byte red = *(sp++);
2263 png_byte green = *(sp++);
2264 png_byte blue = *(sp++);
2265 if(red != green || red != blue)
2266 rgb_error |= 1;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002267 *(dp++) = (png_byte)((gc*red + gc*green + bc*blue)>>8);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002268 *(dp++) = *(sp++); /* alpha */
2269 }
2270 }
2271 }
2272 else /* RGBA bit_depth == 16 */
2273 {
2274#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2275 if (png_ptr->gamma_16_to_1 != NULL &&
2276 png_ptr->gamma_16_from_1 != NULL)
2277 {
2278 png_bytep sp = row;
2279 png_bytep dp = row;
2280 for (i = 0; i < row_width; i++)
2281 {
2282 png_uint_16 red, green, blue, w;
2283
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002284 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2285 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2286 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002287
2288 if(red == green && red == blue)
2289 w = red;
2290 else
2291 {
2292 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
2293 png_ptr->gamma_shift][red>>8];
2294 png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2295 png_ptr->gamma_shift][green>>8];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002296 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002297 png_ptr->gamma_shift][blue>>8];
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002298 png_uint_16 gray16 = (png_uint_16)((rc * red_1
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002299 + gc * green_1 + bc * blue_1)>>15);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002300 w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2301 png_ptr->gamma_shift][gray16 >> 8];
2302 rgb_error |= 1;
2303 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002304
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002305 *(dp++) = (png_byte)((w>>8) & 0xff);
2306 *(dp++) = (png_byte)(w & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002307 *(dp++) = *(sp++); /* alpha */
2308 *(dp++) = *(sp++);
2309 }
2310 }
2311 else
2312#endif
2313 {
2314 png_bytep sp = row;
2315 png_bytep dp = row;
2316 for (i = 0; i < row_width; i++)
2317 {
2318 png_uint_16 red, green, blue, gray16;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002319 red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2320 green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2321 blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002322 if(red != green || red != blue)
2323 rgb_error |= 1;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002324 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002325 *(dp++) = (png_byte)((gray16>>8) & 0xff);
2326 *(dp++) = (png_byte)(gray16 & 0xff);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002327 *(dp++) = *(sp++); /* alpha */
2328 *(dp++) = *(sp++);
2329 }
2330 }
2331 }
2332 }
2333 row_info->channels -= (png_byte)2;
2334 row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2335 row_info->pixel_depth = (png_byte)(row_info->channels *
2336 row_info->bit_depth);
2337 row_info->rowbytes = ((row_width *
2338 row_info->pixel_depth + 7) >> 3);
2339 }
2340 return rgb_error;
2341}
2342#endif
2343
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002344/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
2345 * large of png_color. This lets grayscale images be treated as
2346 * paletted. Most useful for gamma correction and simplification
2347 * of code.
2348 */
Glenn Randers-Pehrson73d57cb2002-03-25 18:49:08 -06002349void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -06002350png_build_grayscale_palette(int bit_depth, png_colorp palette)
Guy Schalnat0d580581995-07-20 02:43:20 -05002351{
2352 int num_palette;
2353 int color_inc;
2354 int i;
2355 int v;
2356
Andreas Dilger47a0c421997-05-16 02:46:07 -05002357 png_debug(1, "in png_do_build_grayscale_palette\n");
2358 if (palette == NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002359 return;
2360
2361 switch (bit_depth)
2362 {
2363 case 1:
2364 num_palette = 2;
2365 color_inc = 0xff;
2366 break;
2367 case 2:
2368 num_palette = 4;
2369 color_inc = 0x55;
2370 break;
2371 case 4:
2372 num_palette = 16;
2373 color_inc = 0x11;
2374 break;
2375 case 8:
2376 num_palette = 256;
2377 color_inc = 1;
2378 break;
2379 default:
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002380 num_palette = 0;
Guy Schalnat69b14481996-01-10 02:56:49 -06002381 color_inc = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05002382 break;
2383 }
2384
2385 for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2386 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002387 palette[i].red = (png_byte)v;
2388 palette[i].green = (png_byte)v;
2389 palette[i].blue = (png_byte)v;
Guy Schalnat0d580581995-07-20 02:43:20 -05002390 }
2391}
2392
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002393/* This function is currently unused. Do we really need it? */
2394#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002395void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002396png_correct_palette(png_structp png_ptr, png_colorp palette,
Guy Schalnat0d580581995-07-20 02:43:20 -05002397 int num_palette)
2398{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002399 png_debug(1, "in png_correct_palette\n");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002400#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2401 defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002402 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
Guy Schalnat0d580581995-07-20 02:43:20 -05002403 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002404 png_color back, back_1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002405
Andreas Dilger47a0c421997-05-16 02:46:07 -05002406 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
2407 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002408 back.red = png_ptr->gamma_table[png_ptr->background.red];
2409 back.green = png_ptr->gamma_table[png_ptr->background.green];
2410 back.blue = png_ptr->gamma_table[png_ptr->background.blue];
Guy Schalnat0d580581995-07-20 02:43:20 -05002411
Guy Schalnate5a37791996-06-05 15:50:50 -05002412 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
2413 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
2414 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002415 }
2416 else
2417 {
2418 double g;
Guy Schalnat0d580581995-07-20 02:43:20 -05002419
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06002420 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002421
2422 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2423 fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
Guy Schalnat0d580581995-07-20 02:43:20 -05002424 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002425 back.red = png_ptr->background.red;
2426 back.green = png_ptr->background.green;
2427 back.blue = png_ptr->background.blue;
2428 }
2429 else
2430 {
2431 back.red =
2432 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2433 255.0 + 0.5);
2434 back.green =
2435 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2436 255.0 + 0.5);
2437 back.blue =
2438 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2439 255.0 + 0.5);
2440 }
2441
2442 g = 1.0 / png_ptr->background_gamma;
2443
2444 back_1.red =
2445 (png_byte)(pow((double)png_ptr->background.red/255, g) *
2446 255.0 + 0.5);
2447 back_1.green =
2448 (png_byte)(pow((double)png_ptr->background.green/255, g) *
2449 255.0 + 0.5);
2450 back_1.blue =
2451 (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2452 255.0 + 0.5);
2453 }
2454
2455 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2456 {
2457 png_uint_32 i;
2458
2459 for (i = 0; i < (png_uint_32)num_palette; i++)
2460 {
2461 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -05002462 {
2463 palette[i] = back;
2464 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002465 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002466 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002467 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002468
2469 v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002470 png_composite(w, v, png_ptr->trans[i], back_1.red);
2471 palette[i].red = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002472
2473 v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002474 png_composite(w, v, png_ptr->trans[i], back_1.green);
2475 palette[i].green = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002476
2477 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002478 png_composite(w, v, png_ptr->trans[i], back_1.blue);
2479 palette[i].blue = png_ptr->gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002480 }
2481 else
2482 {
2483 palette[i].red = png_ptr->gamma_table[palette[i].red];
2484 palette[i].green = png_ptr->gamma_table[palette[i].green];
2485 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2486 }
2487 }
2488 }
2489 else
2490 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002491 int i;
Guy Schalnat0d580581995-07-20 02:43:20 -05002492
2493 for (i = 0; i < num_palette; i++)
2494 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002495 if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002496 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002497 palette[i] = back;
Guy Schalnat0d580581995-07-20 02:43:20 -05002498 }
2499 else
2500 {
2501 palette[i].red = png_ptr->gamma_table[palette[i].red];
2502 palette[i].green = png_ptr->gamma_table[palette[i].green];
2503 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2504 }
2505 }
2506 }
2507 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002508 else
2509#endif
2510#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002511 if (png_ptr->transformations & PNG_GAMMA)
Guy Schalnat0d580581995-07-20 02:43:20 -05002512 {
2513 int i;
2514
2515 for (i = 0; i < num_palette; i++)
2516 {
2517 palette[i].red = png_ptr->gamma_table[palette[i].red];
2518 palette[i].green = png_ptr->gamma_table[palette[i].green];
2519 palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2520 }
2521 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002522#if defined(PNG_READ_BACKGROUND_SUPPORTED)
2523 else
2524#endif
2525#endif
2526#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002527 if (png_ptr->transformations & PNG_BACKGROUND)
Guy Schalnat0d580581995-07-20 02:43:20 -05002528 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002529 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05002530 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002531 png_color back;
Guy Schalnat0d580581995-07-20 02:43:20 -05002532
Guy Schalnate5a37791996-06-05 15:50:50 -05002533 back.red = (png_byte)png_ptr->background.red;
2534 back.green = (png_byte)png_ptr->background.green;
2535 back.blue = (png_byte)png_ptr->background.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002536
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06002537 for (i = 0; i < (int)png_ptr->num_trans; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002538 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002539 if (png_ptr->trans[i] == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -05002540 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002541 palette[i].red = back.red;
2542 palette[i].green = back.green;
2543 palette[i].blue = back.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002544 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002545 else if (png_ptr->trans[i] != 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002546 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002547 png_composite(palette[i].red, png_ptr->palette[i].red,
2548 png_ptr->trans[i], back.red);
2549 png_composite(palette[i].green, png_ptr->palette[i].green,
2550 png_ptr->trans[i], back.green);
2551 png_composite(palette[i].blue, png_ptr->palette[i].blue,
2552 png_ptr->trans[i], back.blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05002553 }
2554 }
2555 }
2556 else /* assume grayscale palette (what else could it be?) */
2557 {
2558 int i;
2559
2560 for (i = 0; i < num_palette; i++)
2561 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002562 if (i == (png_byte)png_ptr->trans_values.gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002563 {
Guy Schalnate5a37791996-06-05 15:50:50 -05002564 palette[i].red = (png_byte)png_ptr->background.red;
2565 palette[i].green = (png_byte)png_ptr->background.green;
2566 palette[i].blue = (png_byte)png_ptr->background.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002567 }
2568 }
2569 }
2570 }
Guy Schalnate5a37791996-06-05 15:50:50 -05002571#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002572}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002573#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002574
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002575#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002576/* Replace any alpha or transparency with the supplied background color.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002577 * "background" is already in the screen gamma, while "background_1" is
2578 * at a gamma of 1.0. Paletted files have already been taken care of.
2579 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002580void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002581png_do_background(png_row_infop row_info, png_bytep row,
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05002582 png_color_16p trans_values, png_color_16p background
2583#if defined(PNG_READ_GAMMA_SUPPORTED)
2584 , png_color_16p background_1,
Guy Schalnat6d764711995-12-19 03:22:19 -06002585 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002586 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05002587 png_uint_16pp gamma_16_to_1, int gamma_shift
2588#endif
2589 )
Guy Schalnat0d580581995-07-20 02:43:20 -05002590{
Guy Schalnat6d764711995-12-19 03:22:19 -06002591 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002592 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002593 png_uint_32 row_width=row_info->width;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002594 int shift;
Guy Schalnate5a37791996-06-05 15:50:50 -05002595
Andreas Dilger47a0c421997-05-16 02:46:07 -05002596 png_debug(1, "in png_do_background\n");
2597 if (background != NULL &&
2598#if defined(PNG_USELESS_TESTS_SUPPORTED)
2599 row != NULL && row_info != NULL &&
2600#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002601 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
Andreas Dilger47a0c421997-05-16 02:46:07 -05002602 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
Guy Schalnat0d580581995-07-20 02:43:20 -05002603 {
2604 switch (row_info->color_type)
2605 {
2606 case PNG_COLOR_TYPE_GRAY:
2607 {
2608 switch (row_info->bit_depth)
2609 {
2610 case 1:
2611 {
Guy Schalnat0d580581995-07-20 02:43:20 -05002612 sp = row;
2613 shift = 7;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002614 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002615 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002616 if ((png_uint_16)((*sp >> shift) & 0x01)
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002617 == trans_values->gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05002618 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002619 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2620 *sp |= (png_byte)(background->gray << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05002621 }
2622 if (!shift)
2623 {
2624 shift = 7;
2625 sp++;
2626 }
2627 else
2628 shift--;
2629 }
2630 break;
2631 }
2632 case 2:
2633 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002634#if defined(PNG_READ_GAMMA_SUPPORTED)
2635 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002636 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002637 sp = row;
2638 shift = 6;
2639 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002640 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002641 if ((png_uint_16)((*sp >> shift) & 0x03)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002642 == trans_values->gray)
2643 {
2644 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2645 *sp |= (png_byte)(background->gray << shift);
2646 }
2647 else
2648 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002649 png_byte p = (png_byte)((*sp >> shift) & 0x03);
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002650 png_byte g = (png_byte)((gamma_table [p | (p << 2) |
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002651 (p << 4) | (p << 6)] >> 6) & 0x03);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002652 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2653 *sp |= (png_byte)(g << shift);
2654 }
2655 if (!shift)
2656 {
2657 shift = 6;
2658 sp++;
2659 }
2660 else
2661 shift -= 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002662 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002663 }
2664 else
2665#endif
2666 {
2667 sp = row;
2668 shift = 6;
2669 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002670 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002671 if ((png_uint_16)((*sp >> shift) & 0x03)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002672 == trans_values->gray)
2673 {
2674 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2675 *sp |= (png_byte)(background->gray << shift);
2676 }
2677 if (!shift)
2678 {
2679 shift = 6;
2680 sp++;
2681 }
2682 else
2683 shift -= 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05002684 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002685 }
2686 break;
2687 }
2688 case 4:
2689 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002690#if defined(PNG_READ_GAMMA_SUPPORTED)
2691 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002692 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002693 sp = row;
2694 shift = 4;
2695 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002696 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002697 if ((png_uint_16)((*sp >> shift) & 0x0f)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002698 == trans_values->gray)
2699 {
2700 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2701 *sp |= (png_byte)(background->gray << shift);
2702 }
2703 else
2704 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002705 png_byte p = (png_byte)((*sp >> shift) & 0x0f);
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002706 png_byte g = (png_byte)((gamma_table[p |
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002707 (p << 4)] >> 4) & 0x0f);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002708 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2709 *sp |= (png_byte)(g << shift);
2710 }
2711 if (!shift)
2712 {
2713 shift = 4;
2714 sp++;
2715 }
2716 else
2717 shift -= 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05002718 }
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002719 }
2720 else
2721#endif
2722 {
2723 sp = row;
2724 shift = 4;
2725 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002726 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002727 if ((png_uint_16)((*sp >> shift) & 0x0f)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05002728 == trans_values->gray)
2729 {
2730 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2731 *sp |= (png_byte)(background->gray << shift);
2732 }
2733 if (!shift)
2734 {
2735 shift = 4;
2736 sp++;
2737 }
2738 else
2739 shift -= 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05002740 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002741 }
2742 break;
2743 }
2744 case 8:
2745 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002746#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002747 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002748 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002749 sp = row;
2750 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002751 {
2752 if (*sp == trans_values->gray)
2753 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002754 *sp = (png_byte)background->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05002755 }
2756 else
2757 {
2758 *sp = gamma_table[*sp];
2759 }
2760 }
2761 }
2762 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002763#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002764 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002765 sp = row;
2766 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002767 {
2768 if (*sp == trans_values->gray)
2769 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002770 *sp = (png_byte)background->gray;
Guy Schalnat0d580581995-07-20 02:43:20 -05002771 }
2772 }
2773 }
2774 break;
2775 }
2776 case 16:
2777 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002778#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002779 if (gamma_16 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002780 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002781 sp = row;
2782 for (i = 0; i < row_width; i++, sp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002783 {
2784 png_uint_16 v;
2785
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002786 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05002787 if (v == trans_values->gray)
2788 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002789 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002790 *sp = (png_byte)((background->gray >> 8) & 0xff);
2791 *(sp + 1) = (png_byte)(background->gray & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002792 }
2793 else
2794 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002795 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002796 *sp = (png_byte)((v >> 8) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002797 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002798 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002799 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002800 }
2801 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002802#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002803 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002804 sp = row;
2805 for (i = 0; i < row_width; i++, sp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002806 {
2807 png_uint_16 v;
2808
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002809 v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05002810 if (v == trans_values->gray)
2811 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002812 *sp = (png_byte)((background->gray >> 8) & 0xff);
2813 *(sp + 1) = (png_byte)(background->gray & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002814 }
2815 }
2816 }
2817 break;
2818 }
2819 }
2820 break;
2821 }
2822 case PNG_COLOR_TYPE_RGB:
2823 {
2824 if (row_info->bit_depth == 8)
2825 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002826#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002827 if (gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002828 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002829 sp = row;
2830 for (i = 0; i < row_width; i++, sp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002831 {
2832 if (*sp == trans_values->red &&
2833 *(sp + 1) == trans_values->green &&
2834 *(sp + 2) == trans_values->blue)
2835 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002836 *sp = (png_byte)background->red;
2837 *(sp + 1) = (png_byte)background->green;
2838 *(sp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002839 }
2840 else
2841 {
2842 *sp = gamma_table[*sp];
2843 *(sp + 1) = gamma_table[*(sp + 1)];
2844 *(sp + 2) = gamma_table[*(sp + 2)];
2845 }
2846 }
2847 }
2848 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002849#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002850 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002851 sp = row;
2852 for (i = 0; i < row_width; i++, sp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05002853 {
2854 if (*sp == trans_values->red &&
2855 *(sp + 1) == trans_values->green &&
2856 *(sp + 2) == trans_values->blue)
2857 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002858 *sp = (png_byte)background->red;
2859 *(sp + 1) = (png_byte)background->green;
2860 *(sp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05002861 }
2862 }
2863 }
2864 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002865 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05002866 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002867#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002868 if (gamma_16 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002869 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002870 sp = row;
2871 for (i = 0; i < row_width; i++, sp += 6)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002872 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002873 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2874 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2875 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
Andreas Dilger47a0c421997-05-16 02:46:07 -05002876 if (r == trans_values->red && g == trans_values->green &&
Guy Schalnat0d580581995-07-20 02:43:20 -05002877 b == trans_values->blue)
2878 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002879 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002880 *sp = (png_byte)((background->red >> 8) & 0xff);
2881 *(sp + 1) = (png_byte)(background->red & 0xff);
2882 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2883 *(sp + 3) = (png_byte)(background->green & 0xff);
2884 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2885 *(sp + 5) = (png_byte)(background->blue & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002886 }
2887 else
2888 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002889 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002890 *sp = (png_byte)((v >> 8) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002891 *(sp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002892 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002893 *(sp + 2) = (png_byte)((v >> 8) & 0xff);
2894 *(sp + 3) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002895 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002896 *(sp + 4) = (png_byte)((v >> 8) & 0xff);
2897 *(sp + 5) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05002898 }
2899 }
2900 }
2901 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002902#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002903 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002904 sp = row;
2905 for (i = 0; i < row_width; i++, sp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05002906 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002907 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
2908 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2909 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
Guy Schalnat0d580581995-07-20 02:43:20 -05002910
Andreas Dilger47a0c421997-05-16 02:46:07 -05002911 if (r == trans_values->red && g == trans_values->green &&
Guy Schalnat0d580581995-07-20 02:43:20 -05002912 b == trans_values->blue)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002913 {
2914 *sp = (png_byte)((background->red >> 8) & 0xff);
2915 *(sp + 1) = (png_byte)(background->red & 0xff);
2916 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2917 *(sp + 3) = (png_byte)(background->green & 0xff);
2918 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2919 *(sp + 5) = (png_byte)(background->blue & 0xff);
2920 }
2921 }
2922 }
2923 }
2924 break;
2925 }
2926 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -05002927 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002928 if (row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05002929 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002930#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002931 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2932 gamma_table != NULL)
2933 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002934 sp = row;
2935 dp = row;
2936 for (i = 0; i < row_width; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002937 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002938 png_uint_16 a = *(sp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002939
Andreas Dilger47a0c421997-05-16 02:46:07 -05002940 if (a == 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002941 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002942 *dp = gamma_table[*sp];
2943 }
2944 else if (a == 0)
2945 {
2946 /* background is already in screen gamma */
2947 *dp = (png_byte)background->gray;
2948 }
2949 else
2950 {
2951 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05002952
Andreas Dilger47a0c421997-05-16 02:46:07 -05002953 v = gamma_to_1[*sp];
2954 png_composite(w, v, a, background_1->gray);
2955 *dp = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05002956 }
2957 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002958 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002959 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002960#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05002961 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002962 sp = row;
2963 dp = row;
2964 for (i = 0; i < row_width; i++, sp += 2, dp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002965 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002966 png_byte a = *(sp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002967
Andreas Dilger47a0c421997-05-16 02:46:07 -05002968 if (a == 0xff)
Guy Schalnat0d580581995-07-20 02:43:20 -05002969 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002970 *dp = *sp;
2971 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05002972#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002973 else if (a == 0)
2974 {
2975 *dp = (png_byte)background->gray;
2976 }
2977 else
2978 {
2979 png_composite(*dp, *sp, a, background_1->gray);
Guy Schalnat0d580581995-07-20 02:43:20 -05002980 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05002981#else
2982 *dp = (png_byte)background->gray;
2983#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002984 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002985 }
2986 }
2987 else /* if (png_ptr->bit_depth == 16) */
2988 {
2989#if defined(PNG_READ_GAMMA_SUPPORTED)
2990 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
2991 gamma_16_to_1 != NULL)
2992 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002993 sp = row;
2994 dp = row;
2995 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002996 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05002997 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
Andreas Dilger47a0c421997-05-16 02:46:07 -05002998
Andreas Dilger47a0c421997-05-16 02:46:07 -05002999 if (a == (png_uint_16)0xffff)
3000 {
3001 png_uint_16 v;
3002
3003 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3004 *dp = (png_byte)((v >> 8) & 0xff);
3005 *(dp + 1) = (png_byte)(v & 0xff);
3006 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003007#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003008 else if (a == 0)
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003009#else
3010 else
3011#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05003012 {
3013 /* background is already in screen gamma */
3014 *dp = (png_byte)((background->gray >> 8) & 0xff);
3015 *(dp + 1) = (png_byte)(background->gray & 0xff);
3016 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003017#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003018 else
3019 {
3020 png_uint_16 g, v, w;
3021
3022 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3023 png_composite_16(v, g, a, background_1->gray);
3024 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3025 *dp = (png_byte)((w >> 8) & 0xff);
3026 *(dp + 1) = (png_byte)(w & 0xff);
3027 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003028#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05003029 }
3030 }
3031 else
3032#endif
3033 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003034 sp = row;
3035 dp = row;
3036 for (i = 0; i < row_width; i++, sp += 4, dp += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003037 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003038 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003039 if (a == (png_uint_16)0xffff)
3040 {
3041 png_memcpy(dp, sp, 2);
3042 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003043#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003044 else if (a == 0)
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003045#else
3046 else
3047#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05003048 {
3049 *dp = (png_byte)((background->gray >> 8) & 0xff);
3050 *(dp + 1) = (png_byte)(background->gray & 0xff);
3051 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003052#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003053 else
3054 {
3055 png_uint_16 g, v;
3056
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003057 g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003058 png_composite_16(v, g, a, background_1->gray);
3059 *dp = (png_byte)((v >> 8) & 0xff);
3060 *(dp + 1) = (png_byte)(v & 0xff);
3061 }
Glenn Randers-Pehrson5a0be342001-10-18 20:55:13 -05003062#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05003063 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003064 }
3065 }
3066 break;
3067 }
3068 case PNG_COLOR_TYPE_RGB_ALPHA:
3069 {
3070 if (row_info->bit_depth == 8)
3071 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003072#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003073 if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3074 gamma_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05003075 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003076 sp = row;
3077 dp = row;
3078 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05003079 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003080 png_byte a = *(sp + 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003081
Guy Schalnat0d580581995-07-20 02:43:20 -05003082 if (a == 0xff)
3083 {
3084 *dp = gamma_table[*sp];
3085 *(dp + 1) = gamma_table[*(sp + 1)];
3086 *(dp + 2) = gamma_table[*(sp + 2)];
3087 }
3088 else if (a == 0)
3089 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003090 /* background is already in screen gamma */
3091 *dp = (png_byte)background->red;
3092 *(dp + 1) = (png_byte)background->green;
3093 *(dp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003094 }
3095 else
3096 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003097 png_byte v, w;
Guy Schalnat0d580581995-07-20 02:43:20 -05003098
3099 v = gamma_to_1[*sp];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003100 png_composite(w, v, a, background_1->red);
3101 *dp = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05003102 v = gamma_to_1[*(sp + 1)];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003103 png_composite(w, v, a, background_1->green);
3104 *(dp + 1) = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05003105 v = gamma_to_1[*(sp + 2)];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003106 png_composite(w, v, a, background_1->blue);
3107 *(dp + 2) = gamma_from_1[w];
Guy Schalnat0d580581995-07-20 02:43:20 -05003108 }
3109 }
3110 }
3111 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003112#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003113 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003114 sp = row;
3115 dp = row;
3116 for (i = 0; i < row_width; i++, sp += 4, dp += 3)
Guy Schalnat0d580581995-07-20 02:43:20 -05003117 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003118 png_byte a = *(sp + 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003119
Guy Schalnat0d580581995-07-20 02:43:20 -05003120 if (a == 0xff)
3121 {
3122 *dp = *sp;
3123 *(dp + 1) = *(sp + 1);
3124 *(dp + 2) = *(sp + 2);
3125 }
3126 else if (a == 0)
3127 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003128 *dp = (png_byte)background->red;
3129 *(dp + 1) = (png_byte)background->green;
3130 *(dp + 2) = (png_byte)background->blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003131 }
3132 else
3133 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003134 png_composite(*dp, *sp, a, background->red);
3135 png_composite(*(dp + 1), *(sp + 1), a,
3136 background->green);
3137 png_composite(*(dp + 2), *(sp + 2), a,
3138 background->blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05003139 }
3140 }
3141 }
3142 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003143 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003144 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003145#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003146 if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3147 gamma_16_to_1 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05003148 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003149 sp = row;
3150 dp = row;
3151 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05003152 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003153 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3154 << 8) + (png_uint_16)(*(sp + 7)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003155 if (a == (png_uint_16)0xffff)
3156 {
3157 png_uint_16 v;
3158
Andreas Dilger47a0c421997-05-16 02:46:07 -05003159 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003160 *dp = (png_byte)((v >> 8) & 0xff);
3161 *(dp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003162 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003163 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3164 *(dp + 3) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003165 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003166 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3167 *(dp + 5) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003168 }
3169 else if (a == 0)
3170 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003171 /* background is already in screen gamma */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003172 *dp = (png_byte)((background->red >> 8) & 0xff);
3173 *(dp + 1) = (png_byte)(background->red & 0xff);
3174 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3175 *(dp + 3) = (png_byte)(background->green & 0xff);
3176 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3177 *(dp + 5) = (png_byte)(background->blue & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003178 }
3179 else
3180 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003181 png_uint_16 v, w, x;
Guy Schalnat0d580581995-07-20 02:43:20 -05003182
Andreas Dilger47a0c421997-05-16 02:46:07 -05003183 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -06003184 png_composite_16(w, v, a, background_1->red);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003185 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3186 *dp = (png_byte)((x >> 8) & 0xff);
3187 *(dp + 1) = (png_byte)(x & 0xff);
3188 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -06003189 png_composite_16(w, v, a, background_1->green);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003190 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3191 *(dp + 2) = (png_byte)((x >> 8) & 0xff);
3192 *(dp + 3) = (png_byte)(x & 0xff);
3193 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -06003194 png_composite_16(w, v, a, background_1->blue);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003195 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3196 *(dp + 4) = (png_byte)((x >> 8) & 0xff);
3197 *(dp + 5) = (png_byte)(x & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003198 }
3199 }
3200 }
3201 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003202#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003203 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003204 sp = row;
3205 dp = row;
3206 for (i = 0; i < row_width; i++, sp += 8, dp += 6)
Guy Schalnat0d580581995-07-20 02:43:20 -05003207 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003208 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3209 << 8) + (png_uint_16)(*(sp + 7)));
Guy Schalnat0d580581995-07-20 02:43:20 -05003210 if (a == (png_uint_16)0xffff)
3211 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003212 png_memcpy(dp, sp, 6);
Guy Schalnat0d580581995-07-20 02:43:20 -05003213 }
3214 else if (a == 0)
3215 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003216 *dp = (png_byte)((background->red >> 8) & 0xff);
3217 *(dp + 1) = (png_byte)(background->red & 0xff);
3218 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3219 *(dp + 3) = (png_byte)(background->green & 0xff);
3220 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3221 *(dp + 5) = (png_byte)(background->blue & 0xff);
3222 }
3223 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003224 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003225 png_uint_16 v;
Guy Schalnat0d580581995-07-20 02:43:20 -05003226
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003227 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3228 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3229 + *(sp + 3));
3230 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3231 + *(sp + 5));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003232
3233 png_composite_16(v, r, a, background->red);
Guy Schalnat0d580581995-07-20 02:43:20 -05003234 *dp = (png_byte)((v >> 8) & 0xff);
3235 *(dp + 1) = (png_byte)(v & 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003236 png_composite_16(v, g, a, background->green);
Guy Schalnat0d580581995-07-20 02:43:20 -05003237 *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3238 *(dp + 3) = (png_byte)(v & 0xff);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003239 png_composite_16(v, b, a, background->blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05003240 *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3241 *(dp + 5) = (png_byte)(v & 0xff);
3242 }
3243 }
3244 }
3245 }
3246 break;
3247 }
3248 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003249
Guy Schalnat0d580581995-07-20 02:43:20 -05003250 if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3251 {
3252 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
Guy Schalnate5a37791996-06-05 15:50:50 -05003253 row_info->channels--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003254 row_info->pixel_depth = (png_byte)(row_info->channels *
3255 row_info->bit_depth);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003256 row_info->rowbytes = ((row_width *
Guy Schalnat0d580581995-07-20 02:43:20 -05003257 row_info->pixel_depth + 7) >> 3);
3258 }
3259 }
3260}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003261#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003262
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003263#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003264/* Gamma correct the image, avoiding the alpha channel. Make sure
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05003265 * you do this after you deal with the transparency issue on grayscale
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -05003266 * or RGB images. If your bit depth is 8, use gamma_table, if it
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003267 * is 16, use gamma_16_table and gamma_shift. Build these with
3268 * build_gamma_table().
3269 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003270void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003271png_do_gamma(png_row_infop row_info, png_bytep row,
3272 png_bytep gamma_table, png_uint_16pp gamma_16_table,
Guy Schalnat0d580581995-07-20 02:43:20 -05003273 int gamma_shift)
3274{
Guy Schalnat6d764711995-12-19 03:22:19 -06003275 png_bytep sp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003276 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003277 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003278
Andreas Dilger47a0c421997-05-16 02:46:07 -05003279 png_debug(1, "in png_do_gamma\n");
3280 if (
3281#if defined(PNG_USELESS_TESTS_SUPPORTED)
3282 row != NULL && row_info != NULL &&
3283#endif
3284 ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3285 (row_info->bit_depth == 16 && gamma_16_table != NULL)))
Guy Schalnat0d580581995-07-20 02:43:20 -05003286 {
3287 switch (row_info->color_type)
3288 {
3289 case PNG_COLOR_TYPE_RGB:
3290 {
3291 if (row_info->bit_depth == 8)
3292 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003293 sp = row;
3294 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003295 {
3296 *sp = gamma_table[*sp];
3297 sp++;
3298 *sp = gamma_table[*sp];
3299 sp++;
3300 *sp = gamma_table[*sp];
3301 sp++;
3302 }
3303 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003304 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003305 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003306 sp = row;
3307 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003308 {
3309 png_uint_16 v;
3310
Andreas Dilger47a0c421997-05-16 02:46:07 -05003311 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003312 *sp = (png_byte)((v >> 8) & 0xff);
3313 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003314 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003315 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003316 *sp = (png_byte)((v >> 8) & 0xff);
3317 *(sp + 1) = (png_byte)(v & 0xff);
3318 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003319 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003320 *sp = (png_byte)((v >> 8) & 0xff);
3321 *(sp + 1) = (png_byte)(v & 0xff);
3322 sp += 2;
3323 }
3324 }
3325 break;
3326 }
3327 case PNG_COLOR_TYPE_RGB_ALPHA:
3328 {
3329 if (row_info->bit_depth == 8)
3330 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003331 sp = row;
3332 for (i = 0; i < row_width; i++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003333 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003334 *sp = gamma_table[*sp];
3335 sp++;
3336 *sp = gamma_table[*sp];
3337 sp++;
3338 *sp = gamma_table[*sp];
3339 sp++;
3340 sp++;
3341 }
3342 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003343 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003344 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003345 sp = row;
3346 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003347 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003348 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003349 *sp = (png_byte)((v >> 8) & 0xff);
3350 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003351 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003352 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003353 *sp = (png_byte)((v >> 8) & 0xff);
3354 *(sp + 1) = (png_byte)(v & 0xff);
3355 sp += 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003356 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003357 *sp = (png_byte)((v >> 8) & 0xff);
3358 *(sp + 1) = (png_byte)(v & 0xff);
3359 sp += 4;
3360 }
3361 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003362 break;
3363 }
3364 case PNG_COLOR_TYPE_GRAY_ALPHA:
3365 {
3366 if (row_info->bit_depth == 8)
3367 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003368 sp = row;
3369 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003370 {
3371 *sp = gamma_table[*sp];
Andreas Dilger47a0c421997-05-16 02:46:07 -05003372 sp += 2;
Guy Schalnat0d580581995-07-20 02:43:20 -05003373 }
3374 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003375 else /* if (row_info->bit_depth == 16) */
Guy Schalnat0d580581995-07-20 02:43:20 -05003376 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003377 sp = row;
3378 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003379 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003380 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003381 *sp = (png_byte)((v >> 8) & 0xff);
3382 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003383 sp += 4;
3384 }
3385 }
3386 break;
3387 }
3388 case PNG_COLOR_TYPE_GRAY:
3389 {
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003390 if (row_info->bit_depth == 2)
3391 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003392 sp = row;
3393 for (i = 0; i < row_width; i += 4)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003394 {
3395 int a = *sp & 0xc0;
3396 int b = *sp & 0x30;
3397 int c = *sp & 0x0c;
3398 int d = *sp & 0x03;
3399
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003400 *sp = (png_byte)(
3401 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003402 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3403 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003404 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06003405 sp++;
3406 }
3407 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003408 if (row_info->bit_depth == 4)
Guy Schalnat0d580581995-07-20 02:43:20 -05003409 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003410 sp = row;
3411 for (i = 0; i < row_width; i += 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -05003412 {
3413 int msb = *sp & 0xf0;
3414 int lsb = *sp & 0x0f;
3415
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003416 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3417 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
Andreas Dilger47a0c421997-05-16 02:46:07 -05003418 sp++;
3419 }
3420 }
3421 else if (row_info->bit_depth == 8)
3422 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003423 sp = row;
3424 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003425 {
3426 *sp = gamma_table[*sp];
3427 sp++;
3428 }
3429 }
3430 else if (row_info->bit_depth == 16)
3431 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003432 sp = row;
3433 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003434 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003435 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003436 *sp = (png_byte)((v >> 8) & 0xff);
3437 *(sp + 1) = (png_byte)(v & 0xff);
Guy Schalnat0d580581995-07-20 02:43:20 -05003438 sp += 2;
3439 }
3440 }
3441 break;
3442 }
3443 }
3444 }
3445}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003446#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003447
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003448#if defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -05003449/* Expands a palette row to an RGB or RGBA row depending
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003450 * upon whether you supply trans and num_trans.
3451 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003452void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003453png_do_expand_palette(png_row_infop row_info, png_bytep row,
Andreas Dilger47a0c421997-05-16 02:46:07 -05003454 png_colorp palette, png_bytep trans, int num_trans)
Guy Schalnat0d580581995-07-20 02:43:20 -05003455{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003456 int shift, value;
Guy Schalnat6d764711995-12-19 03:22:19 -06003457 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003458 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003459 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003460
Andreas Dilger47a0c421997-05-16 02:46:07 -05003461 png_debug(1, "in png_do_expand_palette\n");
3462 if (
3463#if defined(PNG_USELESS_TESTS_SUPPORTED)
3464 row != NULL && row_info != NULL &&
3465#endif
3466 row_info->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnat0d580581995-07-20 02:43:20 -05003467 {
3468 if (row_info->bit_depth < 8)
3469 {
3470 switch (row_info->bit_depth)
3471 {
3472 case 1:
3473 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003474 sp = row + (png_size_t)((row_width - 1) >> 3);
3475 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003476 shift = 7 - (int)((row_width + 7) & 0x07);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003477 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003478 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003479 if ((*sp >> shift) & 0x01)
Guy Schalnat0d580581995-07-20 02:43:20 -05003480 *dp = 1;
3481 else
3482 *dp = 0;
3483 if (shift == 7)
3484 {
3485 shift = 0;
3486 sp--;
3487 }
3488 else
3489 shift++;
3490
3491 dp--;
3492 }
3493 break;
3494 }
3495 case 2:
3496 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003497 sp = row + (png_size_t)((row_width - 1) >> 2);
3498 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003499 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003500 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003501 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003502 value = (*sp >> shift) & 0x03;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003503 *dp = (png_byte)value;
Guy Schalnat0d580581995-07-20 02:43:20 -05003504 if (shift == 6)
3505 {
3506 shift = 0;
3507 sp--;
3508 }
3509 else
3510 shift += 2;
3511
3512 dp--;
3513 }
3514 break;
3515 }
3516 case 4:
3517 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003518 sp = row + (png_size_t)((row_width - 1) >> 1);
3519 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003520 shift = (int)((row_width & 0x01) << 2);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003521 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003522 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003523 value = (*sp >> shift) & 0x0f;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003524 *dp = (png_byte)value;
Guy Schalnat0d580581995-07-20 02:43:20 -05003525 if (shift == 4)
3526 {
3527 shift = 0;
3528 sp--;
3529 }
3530 else
3531 shift += 4;
3532
3533 dp--;
3534 }
3535 break;
3536 }
3537 }
3538 row_info->bit_depth = 8;
3539 row_info->pixel_depth = 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003540 row_info->rowbytes = row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -05003541 }
3542 switch (row_info->bit_depth)
3543 {
3544 case 8:
3545 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003546 if (trans != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05003547 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003548 sp = row + (png_size_t)row_width - 1;
3549 dp = row + (png_size_t)(row_width << 2) - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003550
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003551 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003552 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003553 if ((int)(*sp) >= num_trans)
Guy Schalnat0d580581995-07-20 02:43:20 -05003554 *dp-- = 0xff;
3555 else
3556 *dp-- = trans[*sp];
3557 *dp-- = palette[*sp].blue;
3558 *dp-- = palette[*sp].green;
3559 *dp-- = palette[*sp].red;
3560 sp--;
3561 }
3562 row_info->bit_depth = 8;
3563 row_info->pixel_depth = 32;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003564 row_info->rowbytes = row_width * 4;
Guy Schalnat0d580581995-07-20 02:43:20 -05003565 row_info->color_type = 6;
3566 row_info->channels = 4;
3567 }
3568 else
3569 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003570 sp = row + (png_size_t)row_width - 1;
3571 dp = row + (png_size_t)(row_width * 3) - 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003572
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003573 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003574 {
3575 *dp-- = palette[*sp].blue;
3576 *dp-- = palette[*sp].green;
3577 *dp-- = palette[*sp].red;
3578 sp--;
3579 }
3580 row_info->bit_depth = 8;
3581 row_info->pixel_depth = 24;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003582 row_info->rowbytes = row_width * 3;
Guy Schalnat0d580581995-07-20 02:43:20 -05003583 row_info->color_type = 2;
3584 row_info->channels = 3;
3585 }
3586 break;
3587 }
3588 }
3589 }
3590}
3591
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003592/* If the bit depth < 8, it is expanded to 8. Also, if the
3593 * transparency value is supplied, an alpha channel is built.
3594 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003595void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003596png_do_expand(png_row_infop row_info, png_bytep row,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003597 png_color_16p trans_value)
Guy Schalnat0d580581995-07-20 02:43:20 -05003598{
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003599 int shift, value;
Guy Schalnat6d764711995-12-19 03:22:19 -06003600 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003601 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003602 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003603
Andreas Dilger47a0c421997-05-16 02:46:07 -05003604 png_debug(1, "in png_do_expand\n");
3605#if defined(PNG_USELESS_TESTS_SUPPORTED)
3606 if (row != NULL && row_info != NULL)
3607#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003608 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003609 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05003610 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003611 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003612
3613 if (row_info->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003614 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003615 switch (row_info->bit_depth)
Guy Schalnat0d580581995-07-20 02:43:20 -05003616 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003617 case 1:
3618 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003619 gray = (png_uint_16)(gray*0xff);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003620 sp = row + (png_size_t)((row_width - 1) >> 3);
3621 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003622 shift = 7 - (int)((row_width + 7) & 0x07);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003623 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003624 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003625 if ((*sp >> shift) & 0x01)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003626 *dp = 0xff;
3627 else
3628 *dp = 0;
3629 if (shift == 7)
3630 {
3631 shift = 0;
3632 sp--;
3633 }
3634 else
3635 shift++;
3636
3637 dp--;
3638 }
3639 break;
3640 }
3641 case 2:
3642 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003643 gray = (png_uint_16)(gray*0x55);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003644 sp = row + (png_size_t)((row_width - 1) >> 2);
3645 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003646 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003647 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003648 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003649 value = (*sp >> shift) & 0x03;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003650 *dp = (png_byte)(value | (value << 2) | (value << 4) |
3651 (value << 6));
3652 if (shift == 6)
3653 {
3654 shift = 0;
3655 sp--;
3656 }
3657 else
3658 shift += 2;
3659
3660 dp--;
3661 }
3662 break;
3663 }
3664 case 4:
3665 {
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -05003666 gray = (png_uint_16)(gray*0x11);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003667 sp = row + (png_size_t)((row_width - 1) >> 1);
3668 dp = row + (png_size_t)row_width - 1;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003669 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003670 for (i = 0; i < row_width; i++)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003671 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003672 value = (*sp >> shift) & 0x0f;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003673 *dp = (png_byte)(value | (value << 4));
3674 if (shift == 4)
3675 {
3676 shift = 0;
3677 sp--;
3678 }
3679 else
3680 shift = 4;
3681
3682 dp--;
3683 }
3684 break;
3685 }
3686 }
3687 row_info->bit_depth = 8;
3688 row_info->pixel_depth = 8;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003689 row_info->rowbytes = row_width;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003690 }
3691
Andreas Dilger47a0c421997-05-16 02:46:07 -05003692 if (trans_value != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003693 {
3694 if (row_info->bit_depth == 8)
3695 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003696 sp = row + (png_size_t)row_width - 1;
3697 dp = row + (png_size_t)(row_width << 1) - 1;
3698 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003699 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003700 if (*sp == gray)
3701 *dp-- = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003702 else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003703 *dp-- = 0xff;
3704 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003705 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003706 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003707 else if (row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -05003708 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003709 sp = row + row_info->rowbytes - 1;
3710 dp = row + (row_info->rowbytes << 1) - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003711 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003712 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003713 if (((png_uint_16)*(sp) |
3714 ((png_uint_16)*(sp - 1) << 8)) == gray)
Guy Schalnat0d580581995-07-20 02:43:20 -05003715 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003716 *dp-- = 0;
3717 *dp-- = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003718 }
3719 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003720 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003721 *dp-- = 0xff;
3722 *dp-- = 0xff;
Guy Schalnat0d580581995-07-20 02:43:20 -05003723 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003724 *dp-- = *sp--;
3725 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003726 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003727 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003728 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3729 row_info->channels = 2;
3730 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3731 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003732 ((row_width * row_info->pixel_depth) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003733 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003734 }
3735 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3736 {
3737 if (row_info->bit_depth == 8)
3738 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003739 sp = row + (png_size_t)row_info->rowbytes - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003740 dp = row + (png_size_t)(row_width << 2) - 1;
3741 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003742 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003743 if (*(sp - 2) == trans_value->red &&
Guy Schalnat0d580581995-07-20 02:43:20 -05003744 *(sp - 1) == trans_value->green &&
3745 *(sp - 0) == trans_value->blue)
3746 *dp-- = 0;
3747 else
3748 *dp-- = 0xff;
3749 *dp-- = *sp--;
3750 *dp-- = *sp--;
3751 *dp-- = *sp--;
3752 }
3753 }
3754 else if (row_info->bit_depth == 16)
3755 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05003756 sp = row + row_info->rowbytes - 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003757 dp = row + (png_size_t)(row_width << 3) - 1;
3758 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003759 {
3760 if ((((png_uint_16)*(sp - 4) |
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003761 ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
Guy Schalnat0d580581995-07-20 02:43:20 -05003762 (((png_uint_16)*(sp - 2) |
3763 ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
3764 (((png_uint_16)*(sp - 0) |
3765 ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
3766 {
3767 *dp-- = 0;
3768 *dp-- = 0;
3769 }
3770 else
3771 {
3772 *dp-- = 0xff;
3773 *dp-- = 0xff;
3774 }
3775 *dp-- = *sp--;
3776 *dp-- = *sp--;
3777 *dp-- = *sp--;
3778 *dp-- = *sp--;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003779 *dp-- = *sp--;
Guy Schalnat0d580581995-07-20 02:43:20 -05003780 *dp-- = *sp--;
3781 }
3782 }
3783 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3784 row_info->channels = 4;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003785 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
Guy Schalnat0d580581995-07-20 02:43:20 -05003786 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003787 ((row_width * row_info->pixel_depth) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003788 }
3789 }
3790}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003791#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003792
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003793#if defined(PNG_READ_DITHER_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003794void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003795png_do_dither(png_row_infop row_info, png_bytep row,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003796 png_bytep palette_lookup, png_bytep dither_lookup)
Guy Schalnat0d580581995-07-20 02:43:20 -05003797{
Guy Schalnat6d764711995-12-19 03:22:19 -06003798 png_bytep sp, dp;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003799 png_uint_32 i;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003800 png_uint_32 row_width=row_info->width;
Guy Schalnat6d764711995-12-19 03:22:19 -06003801
Andreas Dilger47a0c421997-05-16 02:46:07 -05003802 png_debug(1, "in png_do_dither\n");
3803#if defined(PNG_USELESS_TESTS_SUPPORTED)
3804 if (row != NULL && row_info != NULL)
3805#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003806 {
3807 if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3808 palette_lookup && row_info->bit_depth == 8)
3809 {
3810 int r, g, b, p;
Guy Schalnat0d580581995-07-20 02:43:20 -05003811 sp = row;
3812 dp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003813 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003814 {
3815 r = *sp++;
3816 g = *sp++;
3817 b = *sp++;
3818
3819 /* this looks real messy, but the compiler will reduce
3820 it down to a reasonable formula. For example, with
3821 5 bits per color, we get:
3822 p = (((r >> 3) & 0x1f) << 10) |
3823 (((g >> 3) & 0x1f) << 5) |
3824 ((b >> 3) & 0x1f);
3825 */
3826 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3827 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3828 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3829 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003830 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
Guy Schalnat0d580581995-07-20 02:43:20 -05003831 (PNG_DITHER_BLUE_BITS)) |
3832 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3833 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3834
3835 *dp++ = palette_lookup[p];
3836 }
3837 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3838 row_info->channels = 1;
3839 row_info->pixel_depth = row_info->bit_depth;
3840 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003841 ((row_width * row_info->pixel_depth + 7) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003842 }
3843 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
Andreas Dilger47a0c421997-05-16 02:46:07 -05003844 palette_lookup != NULL && row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003845 {
3846 int r, g, b, p;
Guy Schalnat0d580581995-07-20 02:43:20 -05003847 sp = row;
3848 dp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003849 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003850 {
3851 r = *sp++;
3852 g = *sp++;
3853 b = *sp++;
3854 sp++;
3855
3856 p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003857 ((1 << PNG_DITHER_RED_BITS) - 1)) <<
Guy Schalnat0d580581995-07-20 02:43:20 -05003858 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3859 (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3860 ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3861 (PNG_DITHER_BLUE_BITS)) |
3862 ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3863 ((1 << PNG_DITHER_BLUE_BITS) - 1));
3864
3865 *dp++ = palette_lookup[p];
3866 }
3867 row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3868 row_info->channels = 1;
3869 row_info->pixel_depth = row_info->bit_depth;
3870 row_info->rowbytes =
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003871 ((row_width * row_info->pixel_depth + 7) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -05003872 }
3873 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
3874 dither_lookup && row_info->bit_depth == 8)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003875 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003876 sp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003877 for (i = 0; i < row_width; i++, sp++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003878 {
3879 *sp = dither_lookup[*sp];
3880 }
3881 }
3882 }
3883}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003884#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003885
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003886#ifdef PNG_FLOATING_POINT_SUPPORTED
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003887#if defined(PNG_READ_GAMMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003888static int png_gamma_shift[] =
3889 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
3890
Andreas Dilger47a0c421997-05-16 02:46:07 -05003891/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003892 * tables, we don't make a full table if we are reducing to 8-bit in
3893 * the future. Note also how the gamma_16 tables are segmented so that
3894 * we don't need to allocate > 64K chunks for a full 16-bit table.
3895 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003896void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003897png_build_gamma_table(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05003898{
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003899 png_debug(1, "in png_build_gamma_table\n");
3900 if(png_ptr->gamma != 0.0)
3901 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003902 if (png_ptr->bit_depth <= 8)
3903 {
3904 int i;
3905 double g;
3906
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003907 if (png_ptr->screen_gamma > .000001)
3908 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3909 else
3910 g = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003911
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003912 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003913 (png_uint_32)256);
3914
3915 for (i = 0; i < 256; i++)
3916 {
3917 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
3918 g) * 255.0 + .5);
3919 }
3920
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003921#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3922 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06003923 if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -05003924 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003925
Guy Schalnat0d580581995-07-20 02:43:20 -05003926 g = 1.0 / (png_ptr->gamma);
3927
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003928 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003929 (png_uint_32)256);
3930
3931 for (i = 0; i < 256; i++)
3932 {
3933 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
3934 g) * 255.0 + .5);
3935 }
3936
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003937
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003938 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
Guy Schalnat0d580581995-07-20 02:43:20 -05003939 (png_uint_32)256);
3940
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003941 if(png_ptr->screen_gamma > 0.000001)
3942 g = 1.0 / png_ptr->screen_gamma;
3943 else
3944 g = png_ptr->gamma; /* probably doing rgb_to_gray */
3945
Guy Schalnat0d580581995-07-20 02:43:20 -05003946 for (i = 0; i < 256; i++)
3947 {
3948 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
3949 g) * 255.0 + .5);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003950
Guy Schalnat0d580581995-07-20 02:43:20 -05003951 }
3952 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003953#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003954 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003955 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003956 {
3957 double g;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003958 int i, j, shift, num;
3959 int sig_bit;
3960 png_uint_32 ig;
Guy Schalnat0d580581995-07-20 02:43:20 -05003961
3962 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003963 {
Guy Schalnat0d580581995-07-20 02:43:20 -05003964 sig_bit = (int)png_ptr->sig_bit.red;
3965 if ((int)png_ptr->sig_bit.green > sig_bit)
3966 sig_bit = png_ptr->sig_bit.green;
3967 if ((int)png_ptr->sig_bit.blue > sig_bit)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003968 sig_bit = png_ptr->sig_bit.blue;
Guy Schalnat0d580581995-07-20 02:43:20 -05003969 }
3970 else
3971 {
3972 sig_bit = (int)png_ptr->sig_bit.gray;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003973 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003974
3975 if (sig_bit > 0)
3976 shift = 16 - sig_bit;
3977 else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003978 shift = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003979
3980 if (png_ptr->transformations & PNG_16_TO_8)
3981 {
3982 if (shift < (16 - PNG_MAX_GAMMA_8))
3983 shift = (16 - PNG_MAX_GAMMA_8);
3984 }
3985
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003986 if (shift > 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003987 shift = 8;
3988 if (shift < 0)
3989 shift = 0;
3990
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003991 png_ptr->gamma_shift = (png_byte)shift;
Guy Schalnat0d580581995-07-20 02:43:20 -05003992
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06003993 num = (1 << (8 - shift));
Guy Schalnat0d580581995-07-20 02:43:20 -05003994
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003995 if (png_ptr->screen_gamma > .000001)
3996 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3997 else
3998 g = 1.0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003999
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004000 png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004001 (png_uint_32)(num * sizeof (png_uint_16p)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004002
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004003 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004004 {
4005 double fin, fout;
4006 png_uint_32 last, max;
Guy Schalnat0d580581995-07-20 02:43:20 -05004007
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004008 for (i = 0; i < num; i++)
4009 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004010 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004011 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004012 }
Guy Schalnat0d580581995-07-20 02:43:20 -05004013
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004014 g = 1.0 / g;
4015 last = 0;
4016 for (i = 0; i < 256; i++)
4017 {
4018 fout = ((double)i + 0.5) / 256.0;
4019 fin = pow(fout, g);
4020 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
4021 while (last <= max)
4022 {
4023 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4024 [(int)(last >> (8 - shift))] = (png_uint_16)(
4025 (png_uint_16)i | ((png_uint_16)i << 8));
4026 last++;
4027 }
4028 }
4029 while (last < ((png_uint_32)num << 8))
4030 {
4031 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
Andreas Dilger47a0c421997-05-16 02:46:07 -05004032 [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004033 last++;
Guy Schalnat6d764711995-12-19 03:22:19 -06004034 }
Guy Schalnat0d580581995-07-20 02:43:20 -05004035 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004036 else
4037 {
4038 for (i = 0; i < num; i++)
4039 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004040 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004041 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004042
Andreas Dilger47a0c421997-05-16 02:46:07 -05004043 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06004044 for (j = 0; j < 256; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05004045 {
4046 png_ptr->gamma_16_table[i][j] =
4047 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4048 65535.0, g) * 65535.0 + .5);
4049 }
4050 }
4051 }
4052
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004053#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4054 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4055 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
Guy Schalnat0d580581995-07-20 02:43:20 -05004056 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004057
Guy Schalnat0d580581995-07-20 02:43:20 -05004058 g = 1.0 / (png_ptr->gamma);
4059
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004060 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004061 (png_uint_32)(num * sizeof (png_uint_16p )));
Guy Schalnat0d580581995-07-20 02:43:20 -05004062
4063 for (i = 0; i < num; i++)
4064 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004065 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004066 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004067
4068 ig = (((png_uint_32)i *
4069 (png_uint_32)png_gamma_shift[shift]) >> 4);
4070 for (j = 0; j < 256; j++)
4071 {
4072 png_ptr->gamma_16_to_1[i][j] =
4073 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4074 65535.0, g) * 65535.0 + .5);
4075 }
4076 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004077
4078 if(png_ptr->screen_gamma > 0.000001)
4079 g = 1.0 / png_ptr->screen_gamma;
4080 else
4081 g = png_ptr->gamma; /* probably doing rgb_to_gray */
Guy Schalnat0d580581995-07-20 02:43:20 -05004082
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004083 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004084 (png_uint_32)(num * sizeof (png_uint_16p)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004085
4086 for (i = 0; i < num; i++)
4087 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004088 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06004089 (png_uint_32)(256 * sizeof (png_uint_16)));
Guy Schalnat0d580581995-07-20 02:43:20 -05004090
4091 ig = (((png_uint_32)i *
4092 (png_uint_32)png_gamma_shift[shift]) >> 4);
4093 for (j = 0; j < 256; j++)
4094 {
4095 png_ptr->gamma_16_from_1[i][j] =
4096 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4097 65535.0, g) * 65535.0 + .5);
4098 }
4099 }
4100 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004101#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05004102 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06004103 }
Guy Schalnat0d580581995-07-20 02:43:20 -05004104}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05004105#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06004106/* To do: install integer version of png_build_gamma_table here */
4107#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -05004108
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -06004109#if defined(PNG_MNG_FEATURES_SUPPORTED)
4110/* undoes intrapixel differencing */
4111void /* PRIVATE */
4112png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4113{
4114 png_debug(1, "in png_do_read_intrapixel\n");
4115 if (
4116#if defined(PNG_USELESS_TESTS_SUPPORTED)
4117 row != NULL && row_info != NULL &&
4118#endif
4119 (row_info->color_type & PNG_COLOR_MASK_COLOR))
4120 {
4121 int bytes_per_pixel;
4122 png_uint_32 row_width = row_info->width;
4123 if (row_info->bit_depth == 8)
4124 {
4125 png_bytep rp;
4126 png_uint_32 i;
4127
4128 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4129 bytes_per_pixel = 3;
4130 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4131 bytes_per_pixel = 4;
4132 else
4133 return;
4134
4135 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4136 {
4137 *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
4138 *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
4139 }
4140 }
4141 else if (row_info->bit_depth == 16)
4142 {
4143 png_bytep rp;
4144 png_uint_32 i;
4145
4146 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4147 bytes_per_pixel = 6;
4148 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4149 bytes_per_pixel = 8;
4150 else
4151 return;
4152
4153 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4154 {
4155 png_uint_32 s0=*(rp )<<8 | *(rp+1);
4156 png_uint_32 s1=*(rp+2)<<8 | *(rp+3);
4157 png_uint_32 s2=*(rp+4)<<8 | *(rp+5);
4158 png_uint_32 red=(65536+s0+s1)&0xffff;
4159 png_uint_32 blue=(65536+s2+s1)&0xffff;
4160 *(rp ) = (png_byte)((red>>8)&0xff);
4161 *(rp+1) = (png_byte)(red&0xff);
4162 *(rp+4) = (png_byte)((blue>>8)&0xff);
4163 *(rp+5) = (png_byte)(blue&0xff);
4164 }
4165 }
4166 }
4167}
4168#endif /* PNG_MNG_FEATURES_SUPPORTED */