]> git.saurik.com Git - wxWidgets.git/blame - src/png/pngtrans.c
Disable wxUSE_ENH_METAFILE for wxGTK builds.
[wxWidgets.git] / src / png / pngtrans.c
CommitLineData
0272a10d
VZ
1
2/* pngtrans.c - transforms the data in a row (used by both readers and writers)
3 *
fff5f7d5
VZ
4 * Last changed in libpng 1.6.2 [April 25, 2013]
5 * Copyright (c) 1998-2013 Glenn Randers-Pehrson
0272a10d
VZ
6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
b61cc19c
PC
8 *
9 * This code is released under the libpng license.
10 * For conditions of distribution and use, see the disclaimer
11 * and license in png.h
0272a10d
VZ
12 */
13
b61cc19c 14#include "pngpriv.h"
970f6abe 15
9c0d9ce3
DS
16#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
17
0272a10d 18#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
b61cc19c 19/* Turn on BGR-to-RGB mapping */
0272a10d 20void PNGAPI
fff5f7d5 21png_set_bgr(png_structrp png_ptr)
0272a10d 22{
970f6abe 23 png_debug(1, "in png_set_bgr");
b61cc19c
PC
24
25 if (png_ptr == NULL)
26 return;
9c0d9ce3 27
0272a10d
VZ
28 png_ptr->transformations |= PNG_BGR;
29}
30#endif
31
32#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
b61cc19c 33/* Turn on 16 bit byte swapping */
0272a10d 34void PNGAPI
fff5f7d5 35png_set_swap(png_structrp png_ptr)
0272a10d 36{
970f6abe 37 png_debug(1, "in png_set_swap");
b61cc19c
PC
38
39 if (png_ptr == NULL)
40 return;
9c0d9ce3 41
0272a10d
VZ
42 if (png_ptr->bit_depth == 16)
43 png_ptr->transformations |= PNG_SWAP_BYTES;
44}
45#endif
46
47#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
b61cc19c 48/* Turn on pixel packing */
0272a10d 49void PNGAPI
fff5f7d5 50png_set_packing(png_structrp png_ptr)
0272a10d 51{
970f6abe 52 png_debug(1, "in png_set_packing");
b61cc19c
PC
53
54 if (png_ptr == NULL)
55 return;
9c0d9ce3 56
0272a10d
VZ
57 if (png_ptr->bit_depth < 8)
58 {
59 png_ptr->transformations |= PNG_PACK;
60 png_ptr->usr_bit_depth = 8;
61 }
62}
63#endif
64
65#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
b61cc19c 66/* Turn on packed pixel swapping */
0272a10d 67void PNGAPI
fff5f7d5 68png_set_packswap(png_structrp png_ptr)
0272a10d 69{
970f6abe 70 png_debug(1, "in png_set_packswap");
b61cc19c
PC
71
72 if (png_ptr == NULL)
73 return;
9c0d9ce3 74
0272a10d
VZ
75 if (png_ptr->bit_depth < 8)
76 png_ptr->transformations |= PNG_PACKSWAP;
77}
78#endif
79
80#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
81void PNGAPI
fff5f7d5 82png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)
0272a10d 83{
970f6abe 84 png_debug(1, "in png_set_shift");
b61cc19c
PC
85
86 if (png_ptr == NULL)
87 return;
9c0d9ce3 88
0272a10d
VZ
89 png_ptr->transformations |= PNG_SHIFT;
90 png_ptr->shift = *true_bits;
91}
92#endif
93
94#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
95 defined(PNG_WRITE_INTERLACING_SUPPORTED)
96int PNGAPI
fff5f7d5 97png_set_interlace_handling(png_structrp png_ptr)
0272a10d 98{
970f6abe 99 png_debug(1, "in png_set_interlace handling");
b61cc19c 100
0272a10d
VZ
101 if (png_ptr && png_ptr->interlaced)
102 {
103 png_ptr->transformations |= PNG_INTERLACE;
104 return (7);
105 }
106
107 return (1);
108}
109#endif
110
111#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
112/* Add a filler byte on read, or remove a filler or alpha byte on write.
113 * The filler type has changed in v0.95 to allow future 2-byte fillers
114 * for 48-bit input data, as well as to avoid problems with some compilers
115 * that don't like bytes as parameters.
116 */
117void PNGAPI
fff5f7d5 118png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
0272a10d 119{
970f6abe 120 png_debug(1, "in png_set_filler");
b61cc19c
PC
121
122 if (png_ptr == NULL)
123 return;
9c0d9ce3 124
fff5f7d5
VZ
125 /* In libpng 1.6 it is possible to determine whether this is a read or write
126 * operation and therefore to do more checking here for a valid call.
127 */
128 if (png_ptr->mode & PNG_IS_READ_STRUCT)
129 {
130# ifdef PNG_READ_FILLER_SUPPORTED
131 /* On read png_set_filler is always valid, regardless of the base PNG
132 * format, because other transformations can give a format where the
133 * filler code can execute (basically an 8 or 16-bit component RGB or G
134 * format.)
135 *
136 * NOTE: usr_channels is not used by the read code! (This has led to
137 * confusion in the past.) The filler is only used in the read code.
138 */
139 png_ptr->filler = (png_uint_16)filler;
140# else
141 png_app_error(png_ptr, "png_set_filler not supported on read");
142 PNG_UNUSED(filler) /* not used in the write case */
143 return;
144# endif
145 }
146
147 else /* write */
148 {
149# ifdef PNG_WRITE_FILLER_SUPPORTED
150 /* On write the usr_channels parameter must be set correctly at the
151 * start to record the number of channels in the app-supplied data.
152 */
153 switch (png_ptr->color_type)
154 {
155 case PNG_COLOR_TYPE_RGB:
156 png_ptr->usr_channels = 4;
157 break;
158
159 case PNG_COLOR_TYPE_GRAY:
160 if (png_ptr->bit_depth >= 8)
161 {
162 png_ptr->usr_channels = 2;
163 break;
164 }
165
166 else
167 {
168 /* There simply isn't any code in libpng to strip out bits
169 * from bytes when the components are less than a byte in
170 * size!
171 */
172 png_app_error(png_ptr,
173 "png_set_filler is invalid for low bit depth gray output");
174 return;
175 }
176
177 default:
178 png_app_error(png_ptr,
179 "png_set_filler: inappropriate color type");
180 return;
181 }
182# else
183 png_app_error(png_ptr, "png_set_filler not supported on write");
184 return;
185# endif
186 }
187
188 /* Here on success - libpng supports the operation, set the transformation
189 * and the flag to say where the filler channel is.
190 */
0272a10d 191 png_ptr->transformations |= PNG_FILLER;
9c0d9ce3 192
0272a10d
VZ
193 if (filler_loc == PNG_FILLER_AFTER)
194 png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
9c0d9ce3 195
0272a10d
VZ
196 else
197 png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
0272a10d
VZ
198}
199
0272a10d
VZ
200/* Added to libpng-1.2.7 */
201void PNGAPI
fff5f7d5 202png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
0272a10d 203{
970f6abe 204 png_debug(1, "in png_set_add_alpha");
b61cc19c
PC
205
206 if (png_ptr == NULL)
207 return;
9c0d9ce3 208
0272a10d 209 png_set_filler(png_ptr, filler, filler_loc);
fff5f7d5
VZ
210 /* The above may fail to do anything. */
211 if (png_ptr->transformations & PNG_FILLER)
212 png_ptr->transformations |= PNG_ADD_ALPHA;
0272a10d 213}
0272a10d
VZ
214
215#endif
216
217#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
218 defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
219void PNGAPI
fff5f7d5 220png_set_swap_alpha(png_structrp png_ptr)
0272a10d 221{
970f6abe 222 png_debug(1, "in png_set_swap_alpha");
b61cc19c
PC
223
224 if (png_ptr == NULL)
225 return;
9c0d9ce3 226
0272a10d
VZ
227 png_ptr->transformations |= PNG_SWAP_ALPHA;
228}
229#endif
230
231#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
232 defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
233void PNGAPI
fff5f7d5 234png_set_invert_alpha(png_structrp png_ptr)
0272a10d 235{
970f6abe 236 png_debug(1, "in png_set_invert_alpha");
b61cc19c
PC
237
238 if (png_ptr == NULL)
239 return;
9c0d9ce3 240
0272a10d
VZ
241 png_ptr->transformations |= PNG_INVERT_ALPHA;
242}
243#endif
244
245#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
246void PNGAPI
fff5f7d5 247png_set_invert_mono(png_structrp png_ptr)
0272a10d 248{
970f6abe 249 png_debug(1, "in png_set_invert_mono");
b61cc19c
PC
250
251 if (png_ptr == NULL)
252 return;
9c0d9ce3 253
0272a10d
VZ
254 png_ptr->transformations |= PNG_INVERT_MONO;
255}
256
b61cc19c 257/* Invert monochrome grayscale data */
0272a10d
VZ
258void /* PRIVATE */
259png_do_invert(png_row_infop row_info, png_bytep row)
260{
970f6abe 261 png_debug(1, "in png_do_invert");
b61cc19c 262
0272a10d
VZ
263 /* This test removed from libpng version 1.0.13 and 1.2.0:
264 * if (row_info->bit_depth == 1 &&
265 */
0272a10d
VZ
266 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
267 {
268 png_bytep rp = row;
9c0d9ce3
DS
269 png_size_t i;
270 png_size_t istop = row_info->rowbytes;
0272a10d
VZ
271
272 for (i = 0; i < istop; i++)
273 {
274 *rp = (png_byte)(~(*rp));
275 rp++;
276 }
277 }
9c0d9ce3 278
0272a10d
VZ
279 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
280 row_info->bit_depth == 8)
281 {
282 png_bytep rp = row;
9c0d9ce3
DS
283 png_size_t i;
284 png_size_t istop = row_info->rowbytes;
0272a10d 285
9c0d9ce3 286 for (i = 0; i < istop; i += 2)
0272a10d
VZ
287 {
288 *rp = (png_byte)(~(*rp));
9c0d9ce3 289 rp += 2;
0272a10d
VZ
290 }
291 }
9c0d9ce3
DS
292
293#ifdef PNG_16BIT_SUPPORTED
0272a10d
VZ
294 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
295 row_info->bit_depth == 16)
296 {
297 png_bytep rp = row;
9c0d9ce3
DS
298 png_size_t i;
299 png_size_t istop = row_info->rowbytes;
0272a10d 300
9c0d9ce3 301 for (i = 0; i < istop; i += 4)
0272a10d
VZ
302 {
303 *rp = (png_byte)(~(*rp));
9c0d9ce3
DS
304 *(rp + 1) = (png_byte)(~(*(rp + 1)));
305 rp += 4;
0272a10d
VZ
306 }
307 }
9c0d9ce3 308#endif
0272a10d
VZ
309}
310#endif
311
9c0d9ce3 312#ifdef PNG_16BIT_SUPPORTED
0272a10d 313#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
b61cc19c 314/* Swaps byte order on 16 bit depth images */
0272a10d
VZ
315void /* PRIVATE */
316png_do_swap(png_row_infop row_info, png_bytep row)
317{
970f6abe 318 png_debug(1, "in png_do_swap");
b61cc19c 319
9c0d9ce3 320 if (row_info->bit_depth == 16)
0272a10d
VZ
321 {
322 png_bytep rp = row;
323 png_uint_32 i;
324 png_uint_32 istop= row_info->width * row_info->channels;
325
326 for (i = 0; i < istop; i++, rp += 2)
327 {
328 png_byte t = *rp;
329 *rp = *(rp + 1);
330 *(rp + 1) = t;
331 }
332 }
333}
334#endif
9c0d9ce3 335#endif
0272a10d
VZ
336
337#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
338static PNG_CONST png_byte onebppswaptable[256] = {
339 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
340 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
341 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
342 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
343 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
344 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
345 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
346 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
347 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
348 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
349 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
350 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
351 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
352 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
353 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
354 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
355 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
356 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
357 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
358 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
359 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
360 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
361 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
362 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
363 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
364 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
365 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
366 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
367 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
368 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
369 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
370 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
371};
372
373static PNG_CONST png_byte twobppswaptable[256] = {
374 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
375 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
376 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
377 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
378 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
379 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
380 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
381 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
382 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
383 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
384 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
385 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
386 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
387 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
388 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
389 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
390 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
391 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
392 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
393 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
394 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
395 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
396 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
397 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
398 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
399 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
400 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
401 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
402 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
403 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
404 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
405 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
406};
407
408static PNG_CONST png_byte fourbppswaptable[256] = {
409 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
410 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
411 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
412 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
413 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
414 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
415 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
416 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
417 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
418 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
419 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
420 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
421 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
422 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
423 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
424 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
425 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
426 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
427 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
428 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
429 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
430 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
431 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
432 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
433 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
434 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
435 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
436 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
437 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
438 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
439 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
440 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
441};
442
b61cc19c 443/* Swaps pixel packing order within bytes */
0272a10d
VZ
444void /* PRIVATE */
445png_do_packswap(png_row_infop row_info, png_bytep row)
446{
970f6abe 447 png_debug(1, "in png_do_packswap");
b61cc19c 448
9c0d9ce3 449 if (row_info->bit_depth < 8)
0272a10d 450 {
9c0d9ce3
DS
451 png_bytep rp;
452 png_const_bytep end, table;
0272a10d
VZ
453
454 end = row + row_info->rowbytes;
455
456 if (row_info->bit_depth == 1)
9c0d9ce3
DS
457 table = onebppswaptable;
458
0272a10d 459 else if (row_info->bit_depth == 2)
9c0d9ce3
DS
460 table = twobppswaptable;
461
0272a10d 462 else if (row_info->bit_depth == 4)
9c0d9ce3
DS
463 table = fourbppswaptable;
464
0272a10d
VZ
465 else
466 return;
467
468 for (rp = row; rp < end; rp++)
469 *rp = table[*rp];
470 }
471}
472#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
473
474#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
475 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
9c0d9ce3
DS
476/* Remove a channel - this used to be 'png_do_strip_filler' but it used a
477 * somewhat weird combination of flags to determine what to do. All the calls
478 * to png_do_strip_filler are changed in 1.5.2 to call this instead with the
479 * correct arguments.
480 *
481 * The routine isn't general - the channel must be the channel at the start or
482 * end (not in the middle) of each pixel.
483 */
0272a10d 484void /* PRIVATE */
9c0d9ce3 485png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
0272a10d 486{
9c0d9ce3
DS
487 png_bytep sp = row; /* source pointer */
488 png_bytep dp = row; /* destination pointer */
489 png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
490
491 /* At the start sp will point to the first byte to copy and dp to where
492 * it is copied to. ep always points just beyond the end of the row, so
493 * the loop simply copies (channels-1) channels until sp reaches ep.
494 *
495 * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
496 * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
497 */
498
499 /* GA, GX, XG cases */
500 if (row_info->channels == 2)
0272a10d 501 {
9c0d9ce3
DS
502 if (row_info->bit_depth == 8)
503 {
504 if (at_start) /* Skip initial filler */
505 ++sp;
506 else /* Skip initial channel and, for sp, the filler */
507 sp += 2, ++dp;
508
509 /* For a 1 pixel wide image there is nothing to do */
510 while (sp < ep)
511 *dp++ = *sp, sp += 2;
0272a10d 512
9c0d9ce3
DS
513 row_info->pixel_depth = 8;
514 }
515
516 else if (row_info->bit_depth == 16)
0272a10d 517 {
9c0d9ce3
DS
518 if (at_start) /* Skip initial filler */
519 sp += 2;
520 else /* Skip initial channel and, for sp, the filler */
521 sp += 4, dp += 2;
522
523 while (sp < ep)
524 *dp++ = *sp++, *dp++ = *sp, sp += 3;
525
526 row_info->pixel_depth = 16;
527 }
528
529 else
530 return; /* bad bit depth */
531
532 row_info->channels = 1;
533
534 /* Finally fix the color type if it records an alpha channel */
535 if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
536 row_info->color_type = PNG_COLOR_TYPE_GRAY;
537 }
538
539 /* RGBA, RGBX, XRGB cases */
540 else if (row_info->channels == 4)
541 {
542 if (row_info->bit_depth == 8)
543 {
544 if (at_start) /* Skip initial filler */
545 ++sp;
546 else /* Skip initial channels and, for sp, the filler */
547 sp += 4, dp += 3;
548
549 /* Note that the loop adds 3 to dp and 4 to sp each time. */
550 while (sp < ep)
551 *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
552
553 row_info->pixel_depth = 24;
0272a10d 554 }
9c0d9ce3
DS
555
556 else if (row_info->bit_depth == 16)
0272a10d 557 {
9c0d9ce3
DS
558 if (at_start) /* Skip initial filler */
559 sp += 2;
560 else /* Skip initial channels and, for sp, the filler */
561 sp += 8, dp += 6;
562
563 while (sp < ep)
0272a10d 564 {
9c0d9ce3
DS
565 /* Copy 6 bytes, skip 2 */
566 *dp++ = *sp++, *dp++ = *sp++;
567 *dp++ = *sp++, *dp++ = *sp++;
568 *dp++ = *sp++, *dp++ = *sp, sp += 3;
0272a10d 569 }
9c0d9ce3
DS
570
571 row_info->pixel_depth = 48;
0272a10d 572 }
9c0d9ce3
DS
573
574 else
575 return; /* bad bit depth */
576
577 row_info->channels = 3;
578
579 /* Finally fix the color type if it records an alpha channel */
580 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
581 row_info->color_type = PNG_COLOR_TYPE_RGB;
0272a10d 582 }
9c0d9ce3
DS
583
584 else
585 return; /* The filler channel has gone already */
586
587 /* Fix the rowbytes value. */
588 row_info->rowbytes = dp-row;
0272a10d
VZ
589}
590#endif
591
592#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
b61cc19c 593/* Swaps red and blue bytes within a pixel */
0272a10d
VZ
594void /* PRIVATE */
595png_do_bgr(png_row_infop row_info, png_bytep row)
596{
970f6abe 597 png_debug(1, "in png_do_bgr");
b61cc19c 598
9c0d9ce3 599 if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
0272a10d
VZ
600 {
601 png_uint_32 row_width = row_info->width;
602 if (row_info->bit_depth == 8)
603 {
604 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
605 {
606 png_bytep rp;
607 png_uint_32 i;
608
609 for (i = 0, rp = row; i < row_width; i++, rp += 3)
610 {
611 png_byte save = *rp;
612 *rp = *(rp + 2);
613 *(rp + 2) = save;
614 }
615 }
9c0d9ce3 616
0272a10d
VZ
617 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
618 {
619 png_bytep rp;
620 png_uint_32 i;
621
622 for (i = 0, rp = row; i < row_width; i++, rp += 4)
623 {
624 png_byte save = *rp;
625 *rp = *(rp + 2);
626 *(rp + 2) = save;
627 }
628 }
629 }
9c0d9ce3
DS
630
631#ifdef PNG_16BIT_SUPPORTED
0272a10d
VZ
632 else if (row_info->bit_depth == 16)
633 {
634 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
635 {
636 png_bytep rp;
637 png_uint_32 i;
638
639 for (i = 0, rp = row; i < row_width; i++, rp += 6)
640 {
641 png_byte save = *rp;
642 *rp = *(rp + 4);
643 *(rp + 4) = save;
644 save = *(rp + 1);
645 *(rp + 1) = *(rp + 5);
646 *(rp + 5) = save;
647 }
648 }
9c0d9ce3 649
0272a10d
VZ
650 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
651 {
652 png_bytep rp;
653 png_uint_32 i;
654
655 for (i = 0, rp = row; i < row_width; i++, rp += 8)
656 {
657 png_byte save = *rp;
658 *rp = *(rp + 4);
659 *(rp + 4) = save;
660 save = *(rp + 1);
661 *(rp + 1) = *(rp + 5);
662 *(rp + 5) = save;
663 }
664 }
665 }
9c0d9ce3 666#endif
0272a10d
VZ
667 }
668}
669#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
670
fff5f7d5
VZ
671#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
672 defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
673/* Added at libpng-1.5.10 */
674void /* PRIVATE */
675png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
676{
677 if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
678 png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
679 {
680 /* Calculations moved outside switch in an attempt to stop different
681 * compiler warnings. 'padding' is in *bits* within the last byte, it is
682 * an 'int' because pixel_depth becomes an 'int' in the expression below,
683 * and this calculation is used because it avoids warnings that other
684 * forms produced on either GCC or MSVC.
685 */
686 int padding = (-row_info->pixel_depth * row_info->width) & 7;
687 png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
688
689 switch (row_info->bit_depth)
690 {
691 case 1:
692 {
693 /* in this case, all bytes must be 0 so we don't need
694 * to unpack the pixels except for the rightmost one.
695 */
696 for (; rp > png_ptr->row_buf; rp--)
697 {
698 if (*rp >> padding != 0)
699 png_ptr->num_palette_max = 1;
700 padding = 0;
701 }
702
703 break;
704 }
705
706 case 2:
707 {
708 for (; rp > png_ptr->row_buf; rp--)
709 {
710 int i = ((*rp >> padding) & 0x03);
711
712 if (i > png_ptr->num_palette_max)
713 png_ptr->num_palette_max = i;
714
715 i = (((*rp >> padding) >> 2) & 0x03);
716
717 if (i > png_ptr->num_palette_max)
718 png_ptr->num_palette_max = i;
719
720 i = (((*rp >> padding) >> 4) & 0x03);
721
722 if (i > png_ptr->num_palette_max)
723 png_ptr->num_palette_max = i;
724
725 i = (((*rp >> padding) >> 6) & 0x03);
726
727 if (i > png_ptr->num_palette_max)
728 png_ptr->num_palette_max = i;
729
730 padding = 0;
731 }
732
733 break;
734 }
735
736 case 4:
737 {
738 for (; rp > png_ptr->row_buf; rp--)
739 {
740 int i = ((*rp >> padding) & 0x0f);
741
742 if (i > png_ptr->num_palette_max)
743 png_ptr->num_palette_max = i;
744
745 i = (((*rp >> padding) >> 4) & 0x0f);
746
747 if (i > png_ptr->num_palette_max)
748 png_ptr->num_palette_max = i;
749
750 padding = 0;
751 }
752
753 break;
754 }
755
756 case 8:
757 {
758 for (; rp > png_ptr->row_buf; rp--)
759 {
760 if (*rp > png_ptr->num_palette_max)
761 png_ptr->num_palette_max = (int) *rp;
762 }
763
764 break;
765 }
766
767 default:
768 break;
769 }
770 }
771}
772#endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */
773
0272a10d 774#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
b61cc19c 775 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
9c0d9ce3 776#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
0272a10d 777void PNGAPI
fff5f7d5 778png_set_user_transform_info(png_structrp png_ptr, png_voidp
0272a10d
VZ
779 user_transform_ptr, int user_transform_depth, int user_transform_channels)
780{
970f6abe 781 png_debug(1, "in png_set_user_transform_info");
b61cc19c
PC
782
783 if (png_ptr == NULL)
784 return;
fff5f7d5
VZ
785
786#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
787 if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
788 (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
789 {
790 png_app_error(png_ptr,
791 "info change after png_start_read_image or png_read_update_info");
792 return;
793 }
794#endif
795
0272a10d
VZ
796 png_ptr->user_transform_ptr = user_transform_ptr;
797 png_ptr->user_transform_depth = (png_byte)user_transform_depth;
798 png_ptr->user_transform_channels = (png_byte)user_transform_channels;
0272a10d 799}
9c0d9ce3 800#endif
0272a10d
VZ
801
802/* This function returns a pointer to the user_transform_ptr associated with
803 * the user transform functions. The application should free any memory
804 * associated with this pointer before png_write_destroy and png_read_destroy
805 * are called.
806 */
9c0d9ce3 807#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
0272a10d 808png_voidp PNGAPI
fff5f7d5 809png_get_user_transform_ptr(png_const_structrp png_ptr)
0272a10d 810{
b61cc19c
PC
811 if (png_ptr == NULL)
812 return (NULL);
9c0d9ce3 813
fff5f7d5 814 return png_ptr->user_transform_ptr;
9c0d9ce3 815}
0272a10d 816#endif
9c0d9ce3
DS
817
818#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
819png_uint_32 PNGAPI
fff5f7d5 820png_get_current_row_number(png_const_structrp png_ptr)
9c0d9ce3
DS
821{
822 /* See the comments in png.h - this is the sub-image row when reading and
823 * interlaced image.
824 */
825 if (png_ptr != NULL)
826 return png_ptr->row_number;
827
828 return PNG_UINT_32_MAX; /* help the app not to fail silently */
829}
830
831png_byte PNGAPI
fff5f7d5 832png_get_current_pass_number(png_const_structrp png_ptr)
9c0d9ce3
DS
833{
834 if (png_ptr != NULL)
835 return png_ptr->pass;
836 return 8; /* invalid */
0272a10d 837}
9c0d9ce3 838#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */
b61cc19c
PC
839#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
840 PNG_WRITE_USER_TRANSFORM_SUPPORTED */
0272a10d 841#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */