2 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
7 * Copyright (c) 1996, 1997 Andreas Dilger
8 * Copyright (c) 1998, Glenn Randers-Pehrson
13 #include "../png/png.h"
15 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
16 /* turn on bgr to rgb mapping */
18 png_set_bgr(png_structp png_ptr
)
20 png_debug(1, "in png_set_bgr\n");
21 png_ptr
->transformations
|= PNG_BGR
;
25 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
26 /* turn on 16 bit byte swapping */
28 png_set_swap(png_structp png_ptr
)
30 png_debug(1, "in png_set_swap\n");
31 if (png_ptr
->bit_depth
== 16)
32 png_ptr
->transformations
|= PNG_SWAP_BYTES
;
36 #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
37 /* turn on pixel packing */
39 png_set_packing(png_structp png_ptr
)
41 png_debug(1, "in png_set_packing\n");
42 if (png_ptr
->bit_depth
< 8)
44 png_ptr
->transformations
|= PNG_PACK
;
45 png_ptr
->usr_bit_depth
= 8;
50 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
51 /* turn on packed pixel swapping */
53 png_set_packswap(png_structp png_ptr
)
55 png_debug(1, "in png_set_packswap\n");
56 if (png_ptr
->bit_depth
< 8)
57 png_ptr
->transformations
|= PNG_PACKSWAP
;
61 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
63 png_set_shift(png_structp png_ptr
, png_color_8p true_bits
)
65 png_debug(1, "in png_set_shift\n");
66 png_ptr
->transformations
|= PNG_SHIFT
;
67 png_ptr
->shift
= *true_bits
;
71 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
72 defined(PNG_WRITE_INTERLACING_SUPPORTED)
74 png_set_interlace_handling(png_structp png_ptr
)
76 png_debug(1, "in png_set_interlace handling\n");
77 if (png_ptr
->interlaced
)
79 png_ptr
->transformations
|= PNG_INTERLACE
;
87 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
88 /* Add a filler byte on read, or remove a filler or alpha byte on write.
89 * The filler type has changed in v0.95 to allow future 2-byte fillers
90 * for 48-bit input data, as well as avoiding problems with some compilers
91 * which don't like bytes as parameters.
94 png_set_filler(png_structp png_ptr
, png_uint_32 filler
, int filler_loc
)
96 png_debug(1, "in png_set_filler\n");
97 png_ptr
->transformations
|= PNG_FILLER
;
98 png_ptr
->filler
= (png_byte
)filler
;
99 if (filler_loc
== PNG_FILLER_AFTER
)
100 png_ptr
->flags
|= PNG_FLAG_FILLER_AFTER
;
102 png_ptr
->flags
&= ~PNG_FLAG_FILLER_AFTER
;
104 /* This should probably go in the "do_filler" routine */
105 if (png_ptr
->color_type
== PNG_COLOR_TYPE_RGB
&& png_ptr
->bit_depth
== 8)
107 png_ptr
->usr_channels
= 4;
112 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
113 defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
115 png_set_swap_alpha(png_structp png_ptr
)
117 png_debug(1, "in png_set_swap_alpha\n");
118 png_ptr
->transformations
|= PNG_SWAP_ALPHA
;
122 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
123 defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
125 png_set_invert_alpha(png_structp png_ptr
)
127 png_debug(1, "in png_set_invert_alpha\n");
128 png_ptr
->transformations
|= PNG_INVERT_ALPHA
;
132 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
134 png_set_invert_mono(png_structp png_ptr
)
136 png_debug(1, "in png_set_invert_mono\n");
137 png_ptr
->transformations
|= PNG_INVERT_MONO
;
140 /* invert monocrome grayscale data */
142 png_do_invert(png_row_infop row_info
, png_bytep row
)
144 png_debug(1, "in png_do_invert\n");
145 if (row_info
->bit_depth
== 1 &&
146 #if defined(PNG_USELESS_TESTS_SUPPORTED)
147 row
!= NULL
&& row_info
!= NULL
&&
149 row_info
->color_type
== PNG_COLOR_TYPE_GRAY
)
154 for (i
= 0, rp
= row
; i
< row_info
->rowbytes
; i
++, rp
++)
156 *rp
= (png_byte
)(~(*rp
));
162 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
163 /* swaps byte order on 16 bit depth images */
165 png_do_swap(png_row_infop row_info
, png_bytep row
)
167 png_debug(1, "in png_do_swap\n");
169 #if defined(PNG_USELESS_TESTS_SUPPORTED)
170 row
!= NULL
&& row_info
!= NULL
&&
172 row_info
->bit_depth
== 16)
178 for (i
= 0, rp
= row
;
179 i
< row_info
->width
* row_info
->channels
;
190 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
191 static png_byte onebppswaptable
[256] = {
192 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
193 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
194 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
195 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
196 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
197 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
198 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
199 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
200 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
201 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
202 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
203 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
204 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
205 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
206 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
207 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
208 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
209 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
210 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
211 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
212 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
213 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
214 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
215 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
216 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
217 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
218 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
219 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
220 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
221 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
222 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
223 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
226 static png_byte twobppswaptable
[256] = {
227 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
228 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
229 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
230 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
231 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
232 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
233 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
234 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
235 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
236 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
237 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
238 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
239 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
240 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
241 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
242 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
243 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
244 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
245 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
246 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
247 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
248 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
249 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
250 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
251 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
252 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
253 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
254 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
255 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
256 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
257 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
258 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
261 static png_byte fourbppswaptable
[256] = {
262 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
263 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
264 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
265 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
266 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
267 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
268 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
269 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
270 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
271 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
272 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
273 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
274 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
275 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
276 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
277 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
278 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
279 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
280 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
281 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
282 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
283 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
284 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
285 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
286 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
287 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
288 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
289 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
290 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
291 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
292 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
293 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
296 /* swaps pixel packing order within bytes */
298 png_do_packswap(png_row_infop row_info
, png_bytep row
)
300 png_debug(1, "in png_do_packswap\n");
302 #if defined(PNG_USELESS_TESTS_SUPPORTED)
303 row
!= NULL
&& row_info
!= NULL
&&
305 row_info
->bit_depth
< 8)
307 png_bytep rp
, end
, table
;
309 end
= row
+ row_info
->rowbytes
;
311 if (row_info
->bit_depth
== 1)
312 table
= onebppswaptable
;
313 else if (row_info
->bit_depth
== 2)
314 table
= twobppswaptable
;
315 else if (row_info
->bit_depth
== 4)
316 table
= fourbppswaptable
;
320 for (rp
= row
; rp
< end
; rp
++)
324 #endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
326 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
327 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
328 /* remove filler or alpha byte(s) */
330 png_do_strip_filler(png_row_infop row_info
, png_bytep row
, png_uint_32 flags
)
332 png_debug(1, "in png_do_strip_filler\n");
333 #if defined(PNG_USELESS_TESTS_SUPPORTED)
334 if (row
!= NULL
&& row_info
!= NULL
)
338 if (row_info->color_type == PNG_COLOR_TYPE_RGB ||
339 row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
341 if (row_info
->channels
== 4)
343 if (row_info
->bit_depth
== 8)
345 /* This converts from RGBX or RGBA to RGB */
346 if (flags
& PNG_FLAG_FILLER_AFTER
)
351 for (i
= 1, sp
= row
+ 4, dp
= row
+ 3; i
< row_info
->width
; i
++)
359 /* This converts from XRGB or ARGB to RGB */
365 for (i
= 0, sp
= row
, dp
= row
; i
< row_info
->width
; i
++)
373 row_info
->pixel_depth
= 24;
374 row_info
->rowbytes
= row_info
->width
* 3;
376 else /* if (row_info->bit_depth == 16) */
378 if (flags
& PNG_FLAG_FILLER_AFTER
)
383 /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
384 for (i
= 1, sp
= row
+ 8, dp
= row
+ 6; i
< row_info
->width
; i
++)
386 /* This could be (although memcpy is probably slower):
387 png_memcpy(dp, sp, 6);
405 /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
406 for (i
= 0, sp
= row
+ 2, dp
= row
; i
< row_info
->width
; i
++)
408 /* This could be (although memcpy is probably slower):
409 png_memcpy(dp, sp, 6);
421 row_info
->pixel_depth
= 48;
422 row_info
->rowbytes
= row_info
->width
* 6;
424 row_info
->channels
= 3;
427 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY ||
428 row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
430 else if (row_info
->channels
== 2)
432 if (row_info
->bit_depth
== 8)
434 /* This converts from GX or GA to G */
435 if (flags
& PNG_FLAG_FILLER_AFTER
)
440 for (i
= 1, sp
= row
+ 2, dp
= row
+ 1; i
< row_info
->width
; i
++)
446 /* This converts from XG or AG to G */
452 for (i
= 0, sp
= row
, dp
= row
; i
< row_info
->width
; i
++)
458 row_info
->pixel_depth
= 8;
459 row_info
->rowbytes
= row_info
->width
;
461 else /* if (row_info->bit_depth == 16) */
463 if (flags
& PNG_FLAG_FILLER_AFTER
)
468 /* This converts from GGXX or GGAA to GG */
469 for (i
= 1, sp
= row
+ 4, dp
= row
+ 2; i
< row_info
->width
; i
++)
481 /* This converts from XXGG or AAGG to GG */
482 for (i
= 0, sp
= row
, dp
= row
; i
< row_info
->width
; i
++)
489 row_info
->pixel_depth
= 16;
490 row_info
->rowbytes
= row_info
->width
* 2;
492 row_info
->channels
= 1;
498 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
499 /* swaps red and blue bytes within a pixel */
501 png_do_bgr(png_row_infop row_info
, png_bytep row
)
503 png_debug(1, "in png_do_bgr\n");
505 #if defined(PNG_USELESS_TESTS_SUPPORTED)
506 row
!= NULL
&& row_info
!= NULL
&&
508 (row_info
->color_type
& PNG_COLOR_MASK_COLOR
))
510 if (row_info
->bit_depth
== 8)
512 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB
)
518 for (i
= 0, rp
= row
; i
< row_info
->width
; i
++, rp
+= 3)
525 else if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
531 for (i
= 0, rp
= row
; i
< row_info
->width
; i
++, rp
+= 4)
539 else if (row_info
->bit_depth
== 16)
541 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB
)
547 for (i
= 0, rp
= row
; i
< row_info
->width
; i
++, rp
+= 6)
552 *(rp
+ 1) = *(rp
+ 5);
557 else if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
563 for (i
= 0, rp
= row
; i
< row_info
->width
; i
++, rp
+= 8)
568 *(rp
+ 1) = *(rp
+ 5);
576 #endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */