]> git.saurik.com Git - wxWidgets.git/blame - src/png/pngtrans.c
Document wxHelpControllerBase so the type can be used in Phoenix
[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 *
9c0d9ce3
DS
4 * Last changed in libpng 1.5.4 [July 7, 2011]
5 * Copyright (c) 1998-2011 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
VZ
20void PNGAPI
21png_set_bgr(png_structp png_ptr)
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
VZ
34void PNGAPI
35png_set_swap(png_structp png_ptr)
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
VZ
49void PNGAPI
50png_set_packing(png_structp png_ptr)
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
VZ
67void PNGAPI
68png_set_packswap(png_structp png_ptr)
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
9c0d9ce3 82png_set_shift(png_structp 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
97png_set_interlace_handling(png_structp png_ptr)
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
118png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
119{
970f6abe 120 png_debug(1, "in png_set_filler");
b61cc19c
PC
121
122 if (png_ptr == NULL)
123 return;
9c0d9ce3 124
0272a10d 125 png_ptr->transformations |= PNG_FILLER;
b61cc19c 126 png_ptr->filler = (png_uint_16)filler;
9c0d9ce3 127
0272a10d
VZ
128 if (filler_loc == PNG_FILLER_AFTER)
129 png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
9c0d9ce3 130
0272a10d
VZ
131 else
132 png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
133
134 /* This should probably go in the "do_read_filler" routine.
135 * I attempted to do that in libpng-1.0.1a but that caused problems
136 * so I restored it in libpng-1.0.2a
137 */
138
139 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
140 {
141 png_ptr->usr_channels = 4;
142 }
143
144 /* Also I added this in libpng-1.0.2a (what happens when we expand
9c0d9ce3 145 * a less-than-8-bit grayscale to GA?) */
0272a10d
VZ
146
147 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
148 {
149 png_ptr->usr_channels = 2;
150 }
151}
152
0272a10d
VZ
153/* Added to libpng-1.2.7 */
154void PNGAPI
155png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
156{
970f6abe 157 png_debug(1, "in png_set_add_alpha");
b61cc19c
PC
158
159 if (png_ptr == NULL)
160 return;
9c0d9ce3 161
0272a10d
VZ
162 png_set_filler(png_ptr, filler, filler_loc);
163 png_ptr->transformations |= PNG_ADD_ALPHA;
164}
0272a10d
VZ
165
166#endif
167
168#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
169 defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
170void PNGAPI
171png_set_swap_alpha(png_structp png_ptr)
172{
970f6abe 173 png_debug(1, "in png_set_swap_alpha");
b61cc19c
PC
174
175 if (png_ptr == NULL)
176 return;
9c0d9ce3 177
0272a10d
VZ
178 png_ptr->transformations |= PNG_SWAP_ALPHA;
179}
180#endif
181
182#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
183 defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
184void PNGAPI
185png_set_invert_alpha(png_structp png_ptr)
186{
970f6abe 187 png_debug(1, "in png_set_invert_alpha");
b61cc19c
PC
188
189 if (png_ptr == NULL)
190 return;
9c0d9ce3 191
0272a10d
VZ
192 png_ptr->transformations |= PNG_INVERT_ALPHA;
193}
194#endif
195
196#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
197void PNGAPI
198png_set_invert_mono(png_structp png_ptr)
199{
970f6abe 200 png_debug(1, "in png_set_invert_mono");
b61cc19c
PC
201
202 if (png_ptr == NULL)
203 return;
9c0d9ce3 204
0272a10d
VZ
205 png_ptr->transformations |= PNG_INVERT_MONO;
206}
207
b61cc19c 208/* Invert monochrome grayscale data */
0272a10d
VZ
209void /* PRIVATE */
210png_do_invert(png_row_infop row_info, png_bytep row)
211{
970f6abe 212 png_debug(1, "in png_do_invert");
b61cc19c 213
0272a10d
VZ
214 /* This test removed from libpng version 1.0.13 and 1.2.0:
215 * if (row_info->bit_depth == 1 &&
216 */
0272a10d
VZ
217 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
218 {
219 png_bytep rp = row;
9c0d9ce3
DS
220 png_size_t i;
221 png_size_t istop = row_info->rowbytes;
0272a10d
VZ
222
223 for (i = 0; i < istop; i++)
224 {
225 *rp = (png_byte)(~(*rp));
226 rp++;
227 }
228 }
9c0d9ce3 229
0272a10d
VZ
230 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
231 row_info->bit_depth == 8)
232 {
233 png_bytep rp = row;
9c0d9ce3
DS
234 png_size_t i;
235 png_size_t istop = row_info->rowbytes;
0272a10d 236
9c0d9ce3 237 for (i = 0; i < istop; i += 2)
0272a10d
VZ
238 {
239 *rp = (png_byte)(~(*rp));
9c0d9ce3 240 rp += 2;
0272a10d
VZ
241 }
242 }
9c0d9ce3
DS
243
244#ifdef PNG_16BIT_SUPPORTED
0272a10d
VZ
245 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
246 row_info->bit_depth == 16)
247 {
248 png_bytep rp = row;
9c0d9ce3
DS
249 png_size_t i;
250 png_size_t istop = row_info->rowbytes;
0272a10d 251
9c0d9ce3 252 for (i = 0; i < istop; i += 4)
0272a10d
VZ
253 {
254 *rp = (png_byte)(~(*rp));
9c0d9ce3
DS
255 *(rp + 1) = (png_byte)(~(*(rp + 1)));
256 rp += 4;
0272a10d
VZ
257 }
258 }
9c0d9ce3 259#endif
0272a10d
VZ
260}
261#endif
262
9c0d9ce3 263#ifdef PNG_16BIT_SUPPORTED
0272a10d 264#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
b61cc19c 265/* Swaps byte order on 16 bit depth images */
0272a10d
VZ
266void /* PRIVATE */
267png_do_swap(png_row_infop row_info, png_bytep row)
268{
970f6abe 269 png_debug(1, "in png_do_swap");
b61cc19c 270
9c0d9ce3 271 if (row_info->bit_depth == 16)
0272a10d
VZ
272 {
273 png_bytep rp = row;
274 png_uint_32 i;
275 png_uint_32 istop= row_info->width * row_info->channels;
276
277 for (i = 0; i < istop; i++, rp += 2)
278 {
279 png_byte t = *rp;
280 *rp = *(rp + 1);
281 *(rp + 1) = t;
282 }
283 }
284}
285#endif
9c0d9ce3 286#endif
0272a10d
VZ
287
288#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
289static PNG_CONST png_byte onebppswaptable[256] = {
290 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
291 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
292 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
293 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
294 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
295 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
296 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
297 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
298 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
299 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
300 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
301 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
302 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
303 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
304 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
305 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
306 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
307 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
308 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
309 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
310 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
311 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
312 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
313 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
314 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
315 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
316 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
317 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
318 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
319 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
320 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
321 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
322};
323
324static PNG_CONST png_byte twobppswaptable[256] = {
325 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
326 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
327 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
328 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
329 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
330 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
331 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
332 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
333 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
334 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
335 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
336 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
337 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
338 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
339 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
340 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
341 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
342 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
343 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
344 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
345 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
346 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
347 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
348 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
349 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
350 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
351 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
352 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
353 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
354 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
355 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
356 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
357};
358
359static PNG_CONST png_byte fourbppswaptable[256] = {
360 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
361 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
362 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
363 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
364 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
365 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
366 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
367 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
368 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
369 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
370 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
371 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
372 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
373 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
374 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
375 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
376 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
377 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
378 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
379 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
380 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
381 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
382 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
383 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
384 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
385 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
386 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
387 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
388 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
389 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
390 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
391 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
392};
393
b61cc19c 394/* Swaps pixel packing order within bytes */
0272a10d
VZ
395void /* PRIVATE */
396png_do_packswap(png_row_infop row_info, png_bytep row)
397{
970f6abe 398 png_debug(1, "in png_do_packswap");
b61cc19c 399
9c0d9ce3 400 if (row_info->bit_depth < 8)
0272a10d 401 {
9c0d9ce3
DS
402 png_bytep rp;
403 png_const_bytep end, table;
0272a10d
VZ
404
405 end = row + row_info->rowbytes;
406
407 if (row_info->bit_depth == 1)
9c0d9ce3
DS
408 table = onebppswaptable;
409
0272a10d 410 else if (row_info->bit_depth == 2)
9c0d9ce3
DS
411 table = twobppswaptable;
412
0272a10d 413 else if (row_info->bit_depth == 4)
9c0d9ce3
DS
414 table = fourbppswaptable;
415
0272a10d
VZ
416 else
417 return;
418
419 for (rp = row; rp < end; rp++)
420 *rp = table[*rp];
421 }
422}
423#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
424
425#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
426 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
9c0d9ce3
DS
427/* Remove a channel - this used to be 'png_do_strip_filler' but it used a
428 * somewhat weird combination of flags to determine what to do. All the calls
429 * to png_do_strip_filler are changed in 1.5.2 to call this instead with the
430 * correct arguments.
431 *
432 * The routine isn't general - the channel must be the channel at the start or
433 * end (not in the middle) of each pixel.
434 */
0272a10d 435void /* PRIVATE */
9c0d9ce3 436png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
0272a10d 437{
9c0d9ce3
DS
438 png_bytep sp = row; /* source pointer */
439 png_bytep dp = row; /* destination pointer */
440 png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
441
442 /* At the start sp will point to the first byte to copy and dp to where
443 * it is copied to. ep always points just beyond the end of the row, so
444 * the loop simply copies (channels-1) channels until sp reaches ep.
445 *
446 * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
447 * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
448 */
449
450 /* GA, GX, XG cases */
451 if (row_info->channels == 2)
0272a10d 452 {
9c0d9ce3
DS
453 if (row_info->bit_depth == 8)
454 {
455 if (at_start) /* Skip initial filler */
456 ++sp;
457 else /* Skip initial channel and, for sp, the filler */
458 sp += 2, ++dp;
459
460 /* For a 1 pixel wide image there is nothing to do */
461 while (sp < ep)
462 *dp++ = *sp, sp += 2;
0272a10d 463
9c0d9ce3
DS
464 row_info->pixel_depth = 8;
465 }
466
467 else if (row_info->bit_depth == 16)
0272a10d 468 {
9c0d9ce3
DS
469 if (at_start) /* Skip initial filler */
470 sp += 2;
471 else /* Skip initial channel and, for sp, the filler */
472 sp += 4, dp += 2;
473
474 while (sp < ep)
475 *dp++ = *sp++, *dp++ = *sp, sp += 3;
476
477 row_info->pixel_depth = 16;
478 }
479
480 else
481 return; /* bad bit depth */
482
483 row_info->channels = 1;
484
485 /* Finally fix the color type if it records an alpha channel */
486 if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
487 row_info->color_type = PNG_COLOR_TYPE_GRAY;
488 }
489
490 /* RGBA, RGBX, XRGB cases */
491 else if (row_info->channels == 4)
492 {
493 if (row_info->bit_depth == 8)
494 {
495 if (at_start) /* Skip initial filler */
496 ++sp;
497 else /* Skip initial channels and, for sp, the filler */
498 sp += 4, dp += 3;
499
500 /* Note that the loop adds 3 to dp and 4 to sp each time. */
501 while (sp < ep)
502 *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
503
504 row_info->pixel_depth = 24;
0272a10d 505 }
9c0d9ce3
DS
506
507 else if (row_info->bit_depth == 16)
0272a10d 508 {
9c0d9ce3
DS
509 if (at_start) /* Skip initial filler */
510 sp += 2;
511 else /* Skip initial channels and, for sp, the filler */
512 sp += 8, dp += 6;
513
514 while (sp < ep)
0272a10d 515 {
9c0d9ce3
DS
516 /* Copy 6 bytes, skip 2 */
517 *dp++ = *sp++, *dp++ = *sp++;
518 *dp++ = *sp++, *dp++ = *sp++;
519 *dp++ = *sp++, *dp++ = *sp, sp += 3;
0272a10d 520 }
9c0d9ce3
DS
521
522 row_info->pixel_depth = 48;
0272a10d 523 }
9c0d9ce3
DS
524
525 else
526 return; /* bad bit depth */
527
528 row_info->channels = 3;
529
530 /* Finally fix the color type if it records an alpha channel */
531 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
532 row_info->color_type = PNG_COLOR_TYPE_RGB;
0272a10d 533 }
9c0d9ce3
DS
534
535 else
536 return; /* The filler channel has gone already */
537
538 /* Fix the rowbytes value. */
539 row_info->rowbytes = dp-row;
0272a10d
VZ
540}
541#endif
542
543#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
b61cc19c 544/* Swaps red and blue bytes within a pixel */
0272a10d
VZ
545void /* PRIVATE */
546png_do_bgr(png_row_infop row_info, png_bytep row)
547{
970f6abe 548 png_debug(1, "in png_do_bgr");
b61cc19c 549
9c0d9ce3 550 if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
0272a10d
VZ
551 {
552 png_uint_32 row_width = row_info->width;
553 if (row_info->bit_depth == 8)
554 {
555 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
556 {
557 png_bytep rp;
558 png_uint_32 i;
559
560 for (i = 0, rp = row; i < row_width; i++, rp += 3)
561 {
562 png_byte save = *rp;
563 *rp = *(rp + 2);
564 *(rp + 2) = save;
565 }
566 }
9c0d9ce3 567
0272a10d
VZ
568 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
569 {
570 png_bytep rp;
571 png_uint_32 i;
572
573 for (i = 0, rp = row; i < row_width; i++, rp += 4)
574 {
575 png_byte save = *rp;
576 *rp = *(rp + 2);
577 *(rp + 2) = save;
578 }
579 }
580 }
9c0d9ce3
DS
581
582#ifdef PNG_16BIT_SUPPORTED
0272a10d
VZ
583 else if (row_info->bit_depth == 16)
584 {
585 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
586 {
587 png_bytep rp;
588 png_uint_32 i;
589
590 for (i = 0, rp = row; i < row_width; i++, rp += 6)
591 {
592 png_byte save = *rp;
593 *rp = *(rp + 4);
594 *(rp + 4) = save;
595 save = *(rp + 1);
596 *(rp + 1) = *(rp + 5);
597 *(rp + 5) = save;
598 }
599 }
9c0d9ce3 600
0272a10d
VZ
601 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
602 {
603 png_bytep rp;
604 png_uint_32 i;
605
606 for (i = 0, rp = row; i < row_width; i++, rp += 8)
607 {
608 png_byte save = *rp;
609 *rp = *(rp + 4);
610 *(rp + 4) = save;
611 save = *(rp + 1);
612 *(rp + 1) = *(rp + 5);
613 *(rp + 5) = save;
614 }
615 }
616 }
9c0d9ce3 617#endif
0272a10d
VZ
618 }
619}
620#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
621
622#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
b61cc19c 623 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
9c0d9ce3 624#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
0272a10d
VZ
625void PNGAPI
626png_set_user_transform_info(png_structp png_ptr, png_voidp
627 user_transform_ptr, int user_transform_depth, int user_transform_channels)
628{
970f6abe 629 png_debug(1, "in png_set_user_transform_info");
b61cc19c
PC
630
631 if (png_ptr == NULL)
632 return;
0272a10d
VZ
633 png_ptr->user_transform_ptr = user_transform_ptr;
634 png_ptr->user_transform_depth = (png_byte)user_transform_depth;
635 png_ptr->user_transform_channels = (png_byte)user_transform_channels;
0272a10d 636}
9c0d9ce3 637#endif
0272a10d
VZ
638
639/* This function returns a pointer to the user_transform_ptr associated with
640 * the user transform functions. The application should free any memory
641 * associated with this pointer before png_write_destroy and png_read_destroy
642 * are called.
643 */
9c0d9ce3 644#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
0272a10d 645png_voidp PNGAPI
9c0d9ce3 646png_get_user_transform_ptr(png_const_structp png_ptr)
0272a10d 647{
b61cc19c
PC
648 if (png_ptr == NULL)
649 return (NULL);
9c0d9ce3 650
0272a10d 651 return ((png_voidp)png_ptr->user_transform_ptr);
9c0d9ce3 652}
0272a10d 653#endif
9c0d9ce3
DS
654
655#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
656png_uint_32 PNGAPI
657png_get_current_row_number(png_const_structp png_ptr)
658{
659 /* See the comments in png.h - this is the sub-image row when reading and
660 * interlaced image.
661 */
662 if (png_ptr != NULL)
663 return png_ptr->row_number;
664
665 return PNG_UINT_32_MAX; /* help the app not to fail silently */
666}
667
668png_byte PNGAPI
669png_get_current_pass_number(png_const_structp png_ptr)
670{
671 if (png_ptr != NULL)
672 return png_ptr->pass;
673 return 8; /* invalid */
0272a10d 674}
9c0d9ce3 675#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */
b61cc19c
PC
676#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
677 PNG_WRITE_USER_TRANSFORM_SUPPORTED */
0272a10d 678#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */