2 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
4 * libpng 1.0.3 - January 14, 1999
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, 1999 Glenn Randers-Pehrson
14 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
15 /* turn on bgr to rgb mapping */
17 png_set_bgr(png_structp png_ptr
)
19 png_debug(1, "in png_set_bgr\n");
20 png_ptr
->transformations
|= PNG_BGR
;
24 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
25 /* turn on 16 bit byte swapping */
27 png_set_swap(png_structp png_ptr
)
29 png_debug(1, "in png_set_swap\n");
30 if (png_ptr
->bit_depth
== 16)
31 png_ptr
->transformations
|= PNG_SWAP_BYTES
;
35 #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
36 /* turn on pixel packing */
38 png_set_packing(png_structp png_ptr
)
40 png_debug(1, "in png_set_packing\n");
41 if (png_ptr
->bit_depth
< 8)
43 png_ptr
->transformations
|= PNG_PACK
;
44 png_ptr
->usr_bit_depth
= 8;
49 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
50 /* turn on packed pixel swapping */
52 png_set_packswap(png_structp png_ptr
)
54 png_debug(1, "in png_set_packswap\n");
55 if (png_ptr
->bit_depth
< 8)
56 png_ptr
->transformations
|= PNG_PACKSWAP
;
60 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
62 png_set_shift(png_structp png_ptr
, png_color_8p true_bits
)
64 png_debug(1, "in png_set_shift\n");
65 png_ptr
->transformations
|= PNG_SHIFT
;
66 png_ptr
->shift
= *true_bits
;
70 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
71 defined(PNG_WRITE_INTERLACING_SUPPORTED)
73 png_set_interlace_handling(png_structp png_ptr
)
75 png_debug(1, "in png_set_interlace handling\n");
76 if (png_ptr
->interlaced
)
78 png_ptr
->transformations
|= PNG_INTERLACE
;
86 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
87 /* Add a filler byte on read, or remove a filler or alpha byte on write.
88 * The filler type has changed in v0.95 to allow future 2-byte fillers
89 * for 48-bit input data, as well as to avoid problems with some compilers
90 * that don't like bytes as parameters.
93 png_set_filler(png_structp png_ptr
, png_uint_32 filler
, int filler_loc
)
95 png_debug(1, "in png_set_filler\n");
96 png_ptr
->transformations
|= PNG_FILLER
;
97 png_ptr
->filler
= (png_byte
)filler
;
98 if (filler_loc
== PNG_FILLER_AFTER
)
99 png_ptr
->flags
|= PNG_FLAG_FILLER_AFTER
;
101 png_ptr
->flags
&= ~PNG_FLAG_FILLER_AFTER
;
103 /* This should probably go in the "do_filler" routine.
104 * I attempted to do that in libpng-1.0.1a but that caused problems
105 * so I restored it in libpng-1.0.2a
108 if (png_ptr
->color_type
== PNG_COLOR_TYPE_RGB
)
110 png_ptr
->usr_channels
= 4;
113 /* Also I added this in libpng-1.0.2a (what happens when we expand
114 * a less-than-8-bit grayscale to GA? */
116 if (png_ptr
->color_type
== PNG_COLOR_TYPE_GRAY
&& png_ptr
->bit_depth
>= 8)
118 png_ptr
->usr_channels
= 2;
123 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
124 defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
126 png_set_swap_alpha(png_structp png_ptr
)
128 png_debug(1, "in png_set_swap_alpha\n");
129 png_ptr
->transformations
|= PNG_SWAP_ALPHA
;
133 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
134 defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
136 png_set_invert_alpha(png_structp png_ptr
)
138 png_debug(1, "in png_set_invert_alpha\n");
139 png_ptr
->transformations
|= PNG_INVERT_ALPHA
;
143 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
145 png_set_invert_mono(png_structp png_ptr
)
147 png_debug(1, "in png_set_invert_mono\n");
148 png_ptr
->transformations
|= PNG_INVERT_MONO
;
151 /* invert monochrome grayscale data */
153 png_do_invert(png_row_infop row_info
, png_bytep row
)
155 png_debug(1, "in png_do_invert\n");
156 if (row_info
->bit_depth
== 1 &&
157 #if defined(PNG_USELESS_TESTS_SUPPORTED)
158 row
!= NULL
&& row_info
!= NULL
&&
160 row_info
->color_type
== PNG_COLOR_TYPE_GRAY
)
164 png_uint_32 istop
= row_info
->rowbytes
;
166 for (i
= 0; i
< istop
; i
++)
168 *rp
= (png_byte
)(~(*rp
));
175 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
176 /* swaps byte order on 16 bit depth images */
178 png_do_swap(png_row_infop row_info
, png_bytep row
)
180 png_debug(1, "in png_do_swap\n");
182 #if defined(PNG_USELESS_TESTS_SUPPORTED)
183 row
!= NULL
&& row_info
!= NULL
&&
185 row_info
->bit_depth
== 16)
189 png_uint_32 istop
= row_info
->width
* row_info
->channels
;
191 for (i
= 0; i
< istop
; i
++, rp
+= 2)
201 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
202 static png_byte onebppswaptable
[256] = {
203 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
204 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
205 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
206 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
207 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
208 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
209 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
210 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
211 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
212 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
213 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
214 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
215 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
216 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
217 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
218 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
219 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
220 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
221 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
222 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
223 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
224 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
225 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
226 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
227 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
228 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
229 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
230 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
231 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
232 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
233 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
234 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
237 static png_byte twobppswaptable
[256] = {
238 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
239 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
240 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
241 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
242 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
243 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
244 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
245 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
246 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
247 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
248 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
249 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
250 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
251 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
252 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
253 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
254 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
255 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
256 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
257 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
258 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
259 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
260 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
261 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
262 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
263 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
264 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
265 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
266 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
267 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
268 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
269 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
272 static png_byte fourbppswaptable
[256] = {
273 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
274 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
275 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
276 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
277 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
278 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
279 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
280 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
281 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
282 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
283 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
284 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
285 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
286 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
287 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
288 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
289 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
290 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
291 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
292 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
293 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
294 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
295 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
296 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
297 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
298 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
299 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
300 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
301 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
302 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
303 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
304 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
307 /* swaps pixel packing order within bytes */
309 png_do_packswap(png_row_infop row_info
, png_bytep row
)
311 png_debug(1, "in png_do_packswap\n");
313 #if defined(PNG_USELESS_TESTS_SUPPORTED)
314 row
!= NULL
&& row_info
!= NULL
&&
316 row_info
->bit_depth
< 8)
318 png_bytep rp
, end
, table
;
320 end
= row
+ row_info
->rowbytes
;
322 if (row_info
->bit_depth
== 1)
323 table
= onebppswaptable
;
324 else if (row_info
->bit_depth
== 2)
325 table
= twobppswaptable
;
326 else if (row_info
->bit_depth
== 4)
327 table
= fourbppswaptable
;
331 for (rp
= row
; rp
< end
; rp
++)
335 #endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
337 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
338 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
339 /* remove filler or alpha byte(s) */
341 png_do_strip_filler(png_row_infop row_info
, png_bytep row
, png_uint_32 flags
)
343 png_debug(1, "in png_do_strip_filler\n");
344 #if defined(PNG_USELESS_TESTS_SUPPORTED)
345 if (row
!= NULL
&& row_info
!= NULL
)
349 if (row_info->color_type == PNG_COLOR_TYPE_RGB ||
350 row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
354 png_uint_32 row_width
=row_info
->width
;
357 if (row_info
->channels
== 4)
359 if (row_info
->bit_depth
== 8)
361 /* This converts from RGBX or RGBA to RGB */
362 if (flags
& PNG_FLAG_FILLER_AFTER
)
365 for (i
= 1; i
< row_width
; i
++)
373 /* This converts from XRGB or ARGB to RGB */
376 for (i
= 0; i
< row_width
; i
++)
384 row_info
->pixel_depth
= 24;
385 row_info
->rowbytes
= row_width
* 3;
387 else /* if (row_info->bit_depth == 16) */
389 if (flags
& PNG_FLAG_FILLER_AFTER
)
391 /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
393 for (i
= 1; i
< row_width
; i
++)
395 /* This could be (although memcpy is probably slower):
396 png_memcpy(dp, sp, 6);
411 /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
412 for (i
= 0; i
< row_width
; i
++)
414 /* This could be (although memcpy is probably slower):
415 png_memcpy(dp, sp, 6);
428 row_info
->pixel_depth
= 48;
429 row_info
->rowbytes
= row_width
* 6;
431 row_info
->channels
= 3;
432 row_info
->color_type
&= ~PNG_COLOR_MASK_ALPHA
;
435 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY ||
436 row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
438 else if (row_info
->channels
== 2)
440 if (row_info
->bit_depth
== 8)
442 /* This converts from GX or GA to G */
443 if (flags
& PNG_FLAG_FILLER_AFTER
)
445 for (i
= 0; i
< row_width
; i
++)
451 /* This converts from XG or AG to G */
454 for (i
= 0; i
< row_width
; i
++)
460 row_info
->pixel_depth
= 8;
461 row_info
->rowbytes
= row_width
;
463 else /* if (row_info->bit_depth == 16) */
465 if (flags
& PNG_FLAG_FILLER_AFTER
)
467 /* This converts from GGXX or GGAA to GG */
469 for (i
= 1; i
< row_width
; i
++)
478 /* This converts from XXGG or AAGG to GG */
479 for (i
= 0; i
< row_width
; i
++)
486 row_info
->pixel_depth
= 16;
487 row_info
->rowbytes
= row_width
* 2;
489 row_info
->channels
= 1;
490 row_info
->color_type
&= ~PNG_COLOR_MASK_ALPHA
;
496 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
497 /* swaps red and blue bytes within a pixel */
499 png_do_bgr(png_row_infop row_info
, png_bytep row
)
501 png_debug(1, "in png_do_bgr\n");
503 #if defined(PNG_USELESS_TESTS_SUPPORTED)
504 row
!= NULL
&& row_info
!= NULL
&&
506 (row_info
->color_type
& PNG_COLOR_MASK_COLOR
))
508 png_uint_32 row_width
= row_info
->width
;
509 if (row_info
->bit_depth
== 8)
511 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB
)
516 for (i
= 0, rp
= row
; i
< row_width
; i
++, rp
+= 3)
523 else if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
528 for (i
= 0, rp
= row
; i
< row_width
; i
++, rp
+= 4)
536 else if (row_info
->bit_depth
== 16)
538 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB
)
543 for (i
= 0, rp
= row
; i
< row_width
; i
++, rp
+= 6)
549 *(rp
+ 1) = *(rp
+ 5);
553 else if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
558 for (i
= 0, rp
= row
; i
< row_width
; i
++, rp
+= 8)
564 *(rp
+ 1) = *(rp
+ 5);
571 #endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */