2 /* pngwtran.c - transforms the data in a row for PNG 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 /* Transform the data according to the user's wishes. The order of
15 * transformations is significant.
18 png_do_write_transformations(png_structp png_ptr
)
20 png_debug(1, "in png_do_write_transformations\n");
22 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
23 if (png_ptr
->transformations
& PNG_USER_TRANSFORM
)
24 if(png_ptr
->write_user_transform_fn
!= NULL
)
25 (*(png_ptr
->write_user_transform_fn
)) /* user write transform function */
26 (png_ptr
, /* png_ptr */
27 &(png_ptr
->row_info
), /* row_info: */
28 /* png_uint_32 width; width of row */
29 /* png_uint_32 rowbytes; number of bytes in row */
30 /* png_byte color_type; color type of pixels */
31 /* png_byte bit_depth; bit depth of samples */
32 /* png_byte channels; number of channels (1-4) */
33 /* png_byte pixel_depth; bits per pixel (depth*channels) */
34 png_ptr
->row_buf
+ 1); /* start of pixel data for row */
36 #if defined(PNG_WRITE_FILLER_SUPPORTED)
37 if (png_ptr
->transformations
& PNG_FILLER
)
38 png_do_strip_filler(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
41 #if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
42 if (png_ptr
->transformations
& PNG_PACKSWAP
)
43 png_do_packswap(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
45 #if defined(PNG_WRITE_PACK_SUPPORTED)
46 if (png_ptr
->transformations
& PNG_PACK
)
47 png_do_pack(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
48 (png_uint_32
)png_ptr
->bit_depth
);
50 #if defined(PNG_WRITE_SWAP_SUPPORTED)
51 if (png_ptr
->transformations
& PNG_SWAP_BYTES
)
52 png_do_swap(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
54 #if defined(PNG_WRITE_SHIFT_SUPPORTED)
55 if (png_ptr
->transformations
& PNG_SHIFT
)
56 png_do_shift(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1,
59 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
60 if (png_ptr
->transformations
& PNG_INVERT_ALPHA
)
61 png_do_write_invert_alpha(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
63 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
64 if (png_ptr
->transformations
& PNG_SWAP_ALPHA
)
65 png_do_write_swap_alpha(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
67 #if defined(PNG_WRITE_BGR_SUPPORTED)
68 if (png_ptr
->transformations
& PNG_BGR
)
69 png_do_bgr(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
71 #if defined(PNG_WRITE_INVERT_SUPPORTED)
72 if (png_ptr
->transformations
& PNG_INVERT_MONO
)
73 png_do_invert(&(png_ptr
->row_info
), png_ptr
->row_buf
+ 1);
77 #if defined(PNG_WRITE_PACK_SUPPORTED)
78 /* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
79 * row_info bit depth should be 8 (one pixel per byte). The channels
80 * should be 1 (this only happens on grayscale and paletted images).
83 png_do_pack(png_row_infop row_info
, png_bytep row
, png_uint_32 bit_depth
)
85 png_debug(1, "in png_do_pack\n");
86 if (row_info
->bit_depth
== 8 &&
87 #if defined(PNG_USELESS_TESTS_SUPPORTED)
88 row
!= NULL
&& row_info
!= NULL
&&
90 row_info
->channels
== 1)
92 switch ((int)bit_depth
)
99 png_uint_32 row_width
= row_info
->width
;
106 for (i
= 0; i
< row_width
; i
++)
130 png_uint_32 row_width
= row_info
->width
;
136 for (i
= 0; i
< row_width
; i
++)
140 value
= (png_byte
)(*sp
& 0x3);
141 v
|= (value
<< shift
);
162 png_uint_32 row_width
= row_info
->width
;
168 for (i
= 0; i
< row_width
; i
++)
172 value
= (png_byte
)(*sp
& 0xf);
173 v
|= (value
<< shift
);
192 row_info
->bit_depth
= (png_byte
)bit_depth
;
193 row_info
->pixel_depth
= (png_byte
)(bit_depth
* row_info
->channels
);
195 ((row_info
->width
* row_info
->pixel_depth
+ 7) >> 3);
200 #if defined(PNG_WRITE_SHIFT_SUPPORTED)
201 /* Shift pixel values to take advantage of whole range. Pass the
202 * true number of bits in bit_depth. The row should be packed
203 * according to row_info->bit_depth. Thus, if you had a row of
204 * bit depth 4, but the pixels only had values from 0 to 7, you
205 * would pass 3 as bit_depth, and this routine would translate the
209 png_do_shift(png_row_infop row_info
, png_bytep row
, png_color_8p bit_depth
)
211 png_debug(1, "in png_do_shift\n");
212 #if defined(PNG_USELESS_TESTS_SUPPORTED)
213 if (row
!= NULL
&& row_info
!= NULL
&&
217 row_info
->color_type
!= PNG_COLOR_TYPE_PALETTE
)
219 int shift_start
[4], shift_dec
[4];
222 if (row_info
->color_type
& PNG_COLOR_MASK_COLOR
)
224 shift_start
[channels
] = row_info
->bit_depth
- bit_depth
->red
;
225 shift_dec
[channels
] = bit_depth
->red
;
227 shift_start
[channels
] = row_info
->bit_depth
- bit_depth
->green
;
228 shift_dec
[channels
] = bit_depth
->green
;
230 shift_start
[channels
] = row_info
->bit_depth
- bit_depth
->blue
;
231 shift_dec
[channels
] = bit_depth
->blue
;
236 shift_start
[channels
] = row_info
->bit_depth
- bit_depth
->gray
;
237 shift_dec
[channels
] = bit_depth
->gray
;
240 if (row_info
->color_type
& PNG_COLOR_MASK_ALPHA
)
242 shift_start
[channels
] = row_info
->bit_depth
- bit_depth
->alpha
;
243 shift_dec
[channels
] = bit_depth
->alpha
;
247 /* with low row depths, could only be grayscale, so one channel */
248 if (row_info
->bit_depth
< 8)
253 png_uint_32 row_bytes
= row_info
->rowbytes
;
255 if (bit_depth
->gray
== 1 && row_info
->bit_depth
== 2)
257 else if (row_info
->bit_depth
== 4 && bit_depth
->gray
== 3)
262 for (i
= 0; i
< row_bytes
; i
++, bp
++)
269 for (j
= shift_start
[0]; j
> -shift_dec
[0]; j
-= shift_dec
[0])
272 *bp
|= (png_byte
)((v
<< j
) & 0xff);
274 *bp
|= (png_byte
)((v
>> (-j
)) & mask
);
278 else if (row_info
->bit_depth
== 8)
282 png_uint_32 istop
= channels
* row_info
->width
;
284 for (i
= 0; i
< istop
; i
++, bp
++)
289 int c
= (int)(i%channels
);
293 for (j
= shift_start
[c
]; j
> -shift_dec
[c
]; j
-= shift_dec
[c
])
296 *bp
|= (png_byte
)((v
<< j
) & 0xff);
298 *bp
|= (png_byte
)((v
>> (-j
)) & 0xff);
306 png_uint_32 istop
= channels
* row_info
->width
;
308 for (bp
= row
, i
= 0; i
< istop
; i
++)
310 int c
= (int)(i%channels
);
311 png_uint_16 value
, v
;
314 v
= ((png_uint_16
)(*bp
) << 8) + *(bp
+ 1);
316 for (j
= shift_start
[c
]; j
> -shift_dec
[c
]; j
-= shift_dec
[c
])
319 value
|= (png_uint_16
)((v
<< j
) & (png_uint_16
)0xffff);
321 value
|= (png_uint_16
)((v
>> (-j
)) & (png_uint_16
)0xffff);
323 *bp
++ = (png_byte
)(value
>> 8);
324 *bp
++ = (png_byte
)(value
& 0xff);
331 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
333 png_do_write_swap_alpha(png_row_infop row_info
, png_bytep row
)
335 png_debug(1, "in png_do_write_swap_alpha\n");
336 #if defined(PNG_USELESS_TESTS_SUPPORTED)
337 if (row
!= NULL
&& row_info
!= NULL
)
340 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
342 /* This converts from ARGB to RGBA */
343 if (row_info
->bit_depth
== 8)
347 png_uint_32 row_width
= row_info
->width
;
348 for (i
= 0, sp
= dp
= row
; i
< row_width
; i
++)
350 png_byte save
= *(sp
++);
357 /* This converts from AARRGGBB to RRGGBBAA */
362 png_uint_32 row_width
= row_info
->width
;
364 for (i
= 0, sp
= dp
= row
; i
< row_width
; i
++)
380 else if (row_info
->color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
382 /* This converts from AG to GA */
383 if (row_info
->bit_depth
== 8)
387 png_uint_32 row_width
= row_info
->width
;
389 for (i
= 0, sp
= dp
= row
; i
< row_width
; i
++)
391 png_byte save
= *(sp
++);
396 /* This converts from AAGG to GGAA */
401 png_uint_32 row_width
= row_info
->width
;
403 for (i
= 0, sp
= dp
= row
; i
< row_width
; i
++)
419 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
421 png_do_write_invert_alpha(png_row_infop row_info
, png_bytep row
)
423 png_debug(1, "in png_do_write_invert_alpha\n");
424 #if defined(PNG_USELESS_TESTS_SUPPORTED)
425 if (row
!= NULL
&& row_info
!= NULL
)
428 if (row_info
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
430 /* This inverts the alpha channel in RGBA */
431 if (row_info
->bit_depth
== 8)
435 png_uint_32 row_width
= row_info
->width
;
436 for (i
= 0, sp
= dp
= row
; i
< row_width
; i
++)
441 *(dp
++) = 255 - *(sp
++);
444 /* This inverts the alpha channel in RRGGBBAA */
449 png_uint_32 row_width
= row_info
->width
;
451 for (i
= 0, sp
= dp
= row
; i
< row_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)
471 png_uint_32 row_width
= row_info
->width
;
473 for (i
= 0, sp
= dp
= row
; i
< row_width
; i
++)
476 *(dp
++) = 255 - *(sp
++);
479 /* This inverts the alpha channel in GGAA */
484 png_uint_32 row_width
= row_info
->width
;
486 for (i
= 0, sp
= dp
= row
; i
< row_width
; i
++)
490 *(dp
++) = 255 - *(sp
++);
491 *(dp
++) = 255 - *(sp
++);