2 /* pngwtran.c - transforms the data in a row for PNG 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 /* Transform the data according to the users wishes. The order of
16 * transformations is significant.
19 png_do_write_transformations(png_structp png_ptr
)
21 png_debug(1, "in png_do_write_transformations\n");
23 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
24 if (png_ptr
->transformations
& PNG_USER_TRANSFORM
)
25 if(png_ptr
->write_user_transform_fn
!= NULL
)
26 (*(png_ptr
->write_user_transform_fn
)) /* user write transform function */
27 (png_ptr
, /* png_ptr */
28 &(png_ptr
->row_info
), /* row_info: */
29 /* png_uint_32 width; width of row */
30 /* png_uint_32 rowbytes; number of bytes in row */
31 /* png_byte color_type; color type of pixels */
32 /* png_byte bit_depth; bit depth of samples */
33 /* png_byte channels; number of channels (1-4) */
34 /* png_byte pixel_depth; bits per pixel (depth*channels) */
35 png_ptr
->row_buf
+ 1); /* start of pixel data for row */
37 #if defined(PNG_WRITE_FILLER_SUPPORTED)
38 if (png_ptr
->transformations
& PNG_FILLER
)
39 png_do_strip_filler(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
42 #if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
43 if (png_ptr
->transformations
& PNG_PACKSWAP
)
44 png_do_packswap(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
46 #if defined(PNG_WRITE_PACK_SUPPORTED)
47 if (png_ptr
->transformations
& PNG_PACK
)
48 png_do_pack(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
49 (png_uint_32
)png_ptr
->bit_depth
);
51 #if defined(PNG_WRITE_SHIFT_SUPPORTED)
52 if (png_ptr
->transformations
& PNG_SHIFT
)
53 png_do_shift(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
56 #if defined(PNG_WRITE_SWAP_SUPPORTED)
57 if (png_ptr
->transformations
& PNG_SWAP_BYTES
)
58 png_do_swap(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
60 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
61 if (png_ptr
->transformations
& PNG_INVERT_ALPHA
)
62 png_do_write_invert_alpha(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
64 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
65 if (png_ptr
->transformations
& PNG_SWAP_ALPHA
)
66 png_do_write_swap_alpha(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
68 #if defined(PNG_WRITE_BGR_SUPPORTED)
69 if (png_ptr
->transformations
& PNG_BGR
)
70 png_do_bgr(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
72 #if defined(PNG_WRITE_INVERT_SUPPORTED)
73 if (png_ptr
->transformations
& PNG_INVERT_MONO
)
74 png_do_invert(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
78 #if defined(PNG_WRITE_PACK_SUPPORTED)
79 /* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
80 * row_info bit depth should be 8 (one pixel per byte). The channels
81 * should be 1 (this only happens on grayscale and paletted images).
84 png_do_pack(png_row_infop row_info
, png_bytep row
, png_uint_32 bit_depth
)
86 png_debug(1, "in png_do_pack\n");
87 if (row_info
->bit_depth
== 8 &&
88 #if defined(PNG_USELESS_TESTS_SUPPORTED)
89 row
!= NULL
&& row_info
!= NULL
&&
91 row_info
->channels
== 1)
93 switch ((int)bit_depth
)
105 for (i
= 0; i
< row_info
->width
; i
++)
134 for (i
= 0; i
< row_info
->width
; i
++)
138 value
= (png_byte
)(*sp
& 0x3);
139 v
|= (value
<< shift
);
165 for (i
= 0; i
< row_info
->width
; i
++)
169 value
= (png_byte
)(*sp
& 0xf);
170 v
|= (value
<< shift
);
189 row_info
->bit_depth
= (png_byte
)bit_depth
;
190 row_info
->pixel_depth
= (png_byte
)(bit_depth
* row_info
->channels
);
192 ((row_info
->width
* row_info
->pixel_depth
+ 7) >> 3);
197 #if defined(PNG_WRITE_SHIFT_SUPPORTED)
198 /* Shift pixel values to take advantage of whole range. Pass the
199 * true number of bits in bit_depth. The row should be packed
200 * according to row_info->bit_depth. Thus, if you had a row of
201 * bit depth 4, but the pixels only had values from 0 to 7, you
202 * would pass 3 as bit_depth, and this routine would translate the
206 png_do_shift(png_row_infop row_info
, png_bytep row
, png_color_8p bit_depth
)
208 png_debug(1, "in png_do_shift\n");
209 #if defined(PNG_USELESS_TESTS_SUPPORTED)
210 if (row
!= NULL
&& row_info
!= NULL
&&
214 row_info
->color_type
!= PNG_COLOR_TYPE_PALETTE
)
216 int shift_start
[4], shift_dec
[4];
217 png_uint_32 channels
;
220 if (row_info
->color_type
& PNG_COLOR_MASK_COLOR
)
222 shift_start
[channels
] = row_info
->bit_depth
- bit_depth
->red
;
223 shift_dec
[channels
] = bit_depth
->red
;
225 shift_start
[channels
] = row_info
->bit_depth
- bit_depth
->green
;
226 shift_dec
[channels
] = bit_depth
->green
;
228 shift_start
[channels
] = row_info
->bit_depth
- bit_depth
->blue
;
229 shift_dec
[channels
] = bit_depth
->blue
;
234 shift_start
[channels
] = row_info
->bit_depth
- bit_depth
->gray
;
235 shift_dec
[channels
] = bit_depth
->gray
;
238 if (row_info
->color_type
& PNG_COLOR_MASK_ALPHA
)
240 shift_start
[channels
] = row_info
->bit_depth
- bit_depth
->alpha
;
241 shift_dec
[channels
] = bit_depth
->alpha
;
245 /* with low row depths, could only be grayscale, so one channel */
246 if (row_info
->bit_depth
< 8)
252 if (bit_depth
->gray
== 1 && row_info
->bit_depth
== 2)
254 else if (row_info
->bit_depth
== 4 && bit_depth
->gray
== 3)
259 for (bp
= row
, i
= 0; i
< row_info
->rowbytes
; i
++, bp
++)
266 for (j
= shift_start
[0]; j
> -shift_dec
[0]; j
-= shift_dec
[0])
269 *bp
|= (png_byte
)((v
<< j
) & 0xff);
271 *bp
|= (png_byte
)((v
>> (-j
)) & mask
);
275 else if (row_info
->bit_depth
== 8)
280 for (bp
= row
, i
= 0; i
< row_info
->width
; i
++)
284 for (c
= 0; c
< channels
; c
++, bp
++)
291 for (j
= shift_start
[c
]; j
> -shift_dec
[c
]; j
-= shift_dec
[c
])
294 *bp
|= (png_byte
)((v
<< j
) & 0xff);
296 *bp
|= (png_byte
)((v
>> (-j
)) & 0xff);
306 for (bp
= row
, i
= 0; i
< row_info
->width
* row_info
->channels
; i
++)
310 for (c
= 0; c
< channels
; c
++, bp
+= 2)
312 png_uint_16 value
, v
;
315 v
= ((png_uint_16
)(*bp
) << 8) + *(bp
+ 1);
317 for (j
= shift_start
[c
]; j
> -shift_dec
[c
]; j
-= shift_dec
[c
])
320 value
|= (png_uint_16
)((v
<< j
) & (png_uint_16
)0xffff);
322 value
|= (png_uint_16
)((v
>> (-j
)) & (png_uint_16
)0xffff);
324 *bp
= (png_byte
)(value
>> 8);
325 *(bp
+ 1) = (png_byte
)(value
& 0xff);
333 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
335 png_do_write_swap_alpha(png_row_infop row_info
, png_bytep row
)
337 png_debug(1, "in png_do_write_swap_alpha\n");
338 #if defined(PNG_USELESS_TESTS_SUPPORTED)
339 if (row
!= NULL
&& row_info
!= NULL
)
342 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
344 /* This converts from ARGB to RGBA */
345 if (row_info
->bit_depth
== 8)
351 for (i
= 0, sp
= dp
= row
; i
< row_info
->width
; i
++)
360 /* This converts from AARRGGBB to RRGGBBAA */
367 for (i
= 0, sp
= dp
= row
; i
< row_info
->width
; i
++)
382 else if (row_info
->color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
384 /* This converts from AG to GA */
385 if (row_info
->bit_depth
== 8)
391 for (i
= 0, sp
= dp
= row
; i
< row_info
->width
; i
++)
398 /* This converts from AAGG to GGAA */
405 for (i
= 0, sp
= dp
= row
; i
< row_info
->width
; i
++)
420 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
422 png_do_write_invert_alpha(png_row_infop row_info
, png_bytep row
)
424 png_debug(1, "in png_do_write_invert_alpha\n");
425 #if defined(PNG_USELESS_TESTS_SUPPORTED)
426 if (row
!= NULL
&& row_info
!= NULL
)
429 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
431 /* This inverts the alpha channel in RGBA */
432 if (row_info
->bit_depth
== 8)
437 for (i
= 0, sp
= dp
= row
; i
< row_info
->width
; i
++)
442 *(dp
++) = 255 - *(sp
++);
445 /* This inverts the alpha channel in RRGGBBAA */
451 for (i
= 0, sp
= dp
= row
; i
< row_info
->width
; i
++)
459 *(dp
++) = 255 - *(sp
++);
460 *(dp
++) = 255 - *(sp
++);
464 else if (row_info
->color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
466 /* This inverts the alpha channel in GA */
467 if (row_info
->bit_depth
== 8)
472 for (i
= 0, sp
= dp
= row
; i
< row_info
->width
; i
++)
475 *(dp
++) = 255 - *(sp
++);
478 /* This inverts the alpha channel in GGAA */
484 for (i
= 0, sp
= dp
= row
; i
< row_info
->width
; i
++)
488 *(dp
++) = 255 - *(sp
++);
489 *(dp
++) = 255 - *(sp
++);