blob: fcb13cc9f7174397c904890e76263dd611027499 [file] [log] [blame]
Guy Schalnat0d580581995-07-20 02:43:20 -05001
Andreas Dilger47a0c421997-05-16 02:46:07 -05002/* pngtrans.c - transforms the data in a row (used by both readers and writers)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003 *
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06004 * libpng 1.2.9beta1 - February 21, 2006
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * For conditions of distribution and use, see copyright notice in png.h
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06006 * Copyright (c) 1998-2006 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05007 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06009 */
Guy Schalnat0d580581995-07-20 02:43:20 -050010
11#define PNG_INTERNAL
12#include "png.h"
13
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060014#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
Guy Schalnat51f0eb41995-09-26 05:22:39 -050015#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -050016/* turn on BGR-to-RGB mapping */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050017void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060018png_set_bgr(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050019{
Andreas Dilger47a0c421997-05-16 02:46:07 -050020 png_debug(1, "in png_set_bgr\n");
Guy Schalnat0d580581995-07-20 02:43:20 -050021 png_ptr->transformations |= PNG_BGR;
22}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050023#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050024
Guy Schalnat51f0eb41995-09-26 05:22:39 -050025#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050026/* turn on 16 bit byte swapping */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050027void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060028png_set_swap(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050029{
Andreas Dilger47a0c421997-05-16 02:46:07 -050030 png_debug(1, "in png_set_swap\n");
Guy Schalnat0d580581995-07-20 02:43:20 -050031 if (png_ptr->bit_depth == 16)
32 png_ptr->transformations |= PNG_SWAP_BYTES;
33}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050034#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050035
Guy Schalnat51f0eb41995-09-26 05:22:39 -050036#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050037/* turn on pixel packing */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050038void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060039png_set_packing(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050040{
Andreas Dilger47a0c421997-05-16 02:46:07 -050041 png_debug(1, "in png_set_packing\n");
Guy Schalnat0d580581995-07-20 02:43:20 -050042 if (png_ptr->bit_depth < 8)
43 {
44 png_ptr->transformations |= PNG_PACK;
45 png_ptr->usr_bit_depth = 8;
46 }
47}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050048#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050049
Andreas Dilger47a0c421997-05-16 02:46:07 -050050#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
51/* turn on packed pixel swapping */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050052void PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050053png_set_packswap(png_structp png_ptr)
54{
55 png_debug(1, "in png_set_packswap\n");
56 if (png_ptr->bit_depth < 8)
57 png_ptr->transformations |= PNG_PACKSWAP;
58}
59#endif
60
Guy Schalnat51f0eb41995-09-26 05:22:39 -050061#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050062void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060063png_set_shift(png_structp png_ptr, png_color_8p true_bits)
Guy Schalnat0d580581995-07-20 02:43:20 -050064{
Andreas Dilger47a0c421997-05-16 02:46:07 -050065 png_debug(1, "in png_set_shift\n");
Guy Schalnat0d580581995-07-20 02:43:20 -050066 png_ptr->transformations |= PNG_SHIFT;
67 png_ptr->shift = *true_bits;
68}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050069#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050070
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -060071#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
72 defined(PNG_WRITE_INTERLACING_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050073int PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060074png_set_interlace_handling(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050075{
Andreas Dilger47a0c421997-05-16 02:46:07 -050076 png_debug(1, "in png_set_interlace handling\n");
Guy Schalnat0d580581995-07-20 02:43:20 -050077 if (png_ptr->interlaced)
78 {
79 png_ptr->transformations |= PNG_INTERLACE;
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060080 return (7);
Guy Schalnat0d580581995-07-20 02:43:20 -050081 }
82
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060083 return (1);
Guy Schalnat0d580581995-07-20 02:43:20 -050084}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050085#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050086
Guy Schalnat51f0eb41995-09-26 05:22:39 -050087#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -050088/* 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
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050090 * for 48-bit input data, as well as to avoid problems with some compilers
91 * that don't like bytes as parameters.
Andreas Dilger47a0c421997-05-16 02:46:07 -050092 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050093void PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050094png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
Guy Schalnat0d580581995-07-20 02:43:20 -050095{
Andreas Dilger47a0c421997-05-16 02:46:07 -050096 png_debug(1, "in png_set_filler\n");
Guy Schalnat51f0eb41995-09-26 05:22:39 -050097 png_ptr->transformations |= PNG_FILLER;
Andreas Dilger47a0c421997-05-16 02:46:07 -050098 png_ptr->filler = (png_byte)filler;
Guy Schalnate5a37791996-06-05 15:50:50 -050099 if (filler_loc == PNG_FILLER_AFTER)
100 png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
101 else
102 png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600103
Glenn Randers-Pehrson5b779162004-09-04 13:25:08 -0500104 /* This should probably go in the "do_read_filler" routine.
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600105 * I attempted to do that in libpng-1.0.1a but that caused problems
106 * so I restored it in libpng-1.0.2a
107 */
108
109 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
110 {
111 png_ptr->usr_channels = 4;
112 }
113
114 /* Also I added this in libpng-1.0.2a (what happens when we expand
115 * a less-than-8-bit grayscale to GA? */
116
117 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
118 {
119 png_ptr->usr_channels = 2;
120 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500121}
Glenn Randers-Pehrson67864af2004-08-28 23:30:07 -0500122
123#if !defined(PNG_1_0_X)
124/* Added to libpng-1.2.7 */
125void PNGAPI
126png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
127{
128 png_debug(1, "in png_set_add_alpha\n");
129 png_set_filler(png_ptr, filler, filler_loc);
130 png_ptr->transformations |= PNG_ADD_ALPHA;
131}
132#endif
133
Andreas Dilger47a0c421997-05-16 02:46:07 -0500134#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500135
Andreas Dilger47a0c421997-05-16 02:46:07 -0500136#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
137 defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500138void PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -0500139png_set_swap_alpha(png_structp png_ptr)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500140{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500141 png_debug(1, "in png_set_swap_alpha\n");
142 png_ptr->transformations |= PNG_SWAP_ALPHA;
Guy Schalnat0d580581995-07-20 02:43:20 -0500143}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500144#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500145
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600146#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
147 defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500148void PNGAPI
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600149png_set_invert_alpha(png_structp png_ptr)
150{
151 png_debug(1, "in png_set_invert_alpha\n");
152 png_ptr->transformations |= PNG_INVERT_ALPHA;
153}
154#endif
155
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500156#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500157void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600158png_set_invert_mono(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500159{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500160 png_debug(1, "in png_set_invert_mono\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500161 png_ptr->transformations |= PNG_INVERT_MONO;
162}
163
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500164/* invert monochrome grayscale data */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500165void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600166png_do_invert(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500167{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500168 png_debug(1, "in png_do_invert\n");
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500169 /* This test removed from libpng version 1.0.13 and 1.2.0:
170 * if (row_info->bit_depth == 1 &&
171 */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500172#if defined(PNG_USELESS_TESTS_SUPPORTED)
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500173 if (row == NULL || row_info == NULL)
174 return;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500175#endif
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500176 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -0500177 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500178 png_bytep rp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -0500179 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500180 png_uint_32 istop = row_info->rowbytes;
Guy Schalnat0d580581995-07-20 02:43:20 -0500181
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500182 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500183 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500184 *rp = (png_byte)(~(*rp));
185 rp++;
Guy Schalnat0d580581995-07-20 02:43:20 -0500186 }
187 }
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500188 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
189 row_info->bit_depth == 8)
190 {
191 png_bytep rp = row;
192 png_uint_32 i;
193 png_uint_32 istop = row_info->rowbytes;
194
195 for (i = 0; i < istop; i+=2)
196 {
197 *rp = (png_byte)(~(*rp));
198 rp+=2;
199 }
200 }
201 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
202 row_info->bit_depth == 16)
203 {
204 png_bytep rp = row;
205 png_uint_32 i;
206 png_uint_32 istop = row_info->rowbytes;
207
208 for (i = 0; i < istop; i+=4)
209 {
210 *rp = (png_byte)(~(*rp));
211 *(rp+1) = (png_byte)(~(*(rp+1)));
212 rp+=4;
213 }
214 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500215}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500216#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500217
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500218#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500219/* swaps byte order on 16 bit depth images */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500220void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600221png_do_swap(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500222{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500223 png_debug(1, "in png_do_swap\n");
224 if (
225#if defined(PNG_USELESS_TESTS_SUPPORTED)
226 row != NULL && row_info != NULL &&
227#endif
228 row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -0500229 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500230 png_bytep rp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -0500231 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500232 png_uint_32 istop= row_info->width * row_info->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500233
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500234 for (i = 0; i < istop; i++, rp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -0500235 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500236 png_byte t = *rp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500237 *rp = *(rp + 1);
238 *(rp + 1) = t;
239 }
240 }
241}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500242#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500243
Andreas Dilger47a0c421997-05-16 02:46:07 -0500244#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
245static png_byte onebppswaptable[256] = {
246 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
247 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
248 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
249 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
250 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
251 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
252 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
253 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
254 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
255 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
256 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
257 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
258 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
259 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
260 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
261 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
262 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
263 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
264 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
265 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
266 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
267 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
268 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
269 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
270 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
271 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
272 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
273 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
274 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
275 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
276 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
277 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
278};
279
280static png_byte twobppswaptable[256] = {
281 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
282 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
283 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
284 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
285 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
286 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
287 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
288 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
289 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
290 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
291 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
292 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
293 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
294 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
295 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
296 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
297 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
298 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
299 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
300 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
301 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
302 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
303 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
304 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
305 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
306 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
307 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
308 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
309 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
310 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
311 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
312 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
313};
314
315static png_byte fourbppswaptable[256] = {
316 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
317 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
318 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
319 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
320 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
321 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
322 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
323 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
324 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
325 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
326 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
327 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
328 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
329 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
330 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
331 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
332 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
333 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
334 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
335 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
336 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
337 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
338 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
339 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
340 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
341 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
342 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
343 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
344 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
345 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
346 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
347 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
348};
349
350/* swaps pixel packing order within bytes */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500351void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500352png_do_packswap(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500353{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500354 png_debug(1, "in png_do_packswap\n");
355 if (
356#if defined(PNG_USELESS_TESTS_SUPPORTED)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600357 row != NULL && row_info != NULL &&
Andreas Dilger47a0c421997-05-16 02:46:07 -0500358#endif
359 row_info->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -0500360 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500361 png_bytep rp, end, table;
Guy Schalnat0d580581995-07-20 02:43:20 -0500362
Andreas Dilger47a0c421997-05-16 02:46:07 -0500363 end = row + row_info->rowbytes;
364
365 if (row_info->bit_depth == 1)
366 table = onebppswaptable;
367 else if (row_info->bit_depth == 2)
368 table = twobppswaptable;
369 else if (row_info->bit_depth == 4)
370 table = fourbppswaptable;
371 else
372 return;
373
374 for (rp = row; rp < end; rp++)
375 *rp = table[*rp];
376 }
377}
378#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
379
380#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
381 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
382/* remove filler or alpha byte(s) */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500383void /* PRIVATE */
Glenn Randers-Pehrson40936072004-11-20 11:18:40 -0600384png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500385{
386 png_debug(1, "in png_do_strip_filler\n");
387#if defined(PNG_USELESS_TESTS_SUPPORTED)
388 if (row != NULL && row_info != NULL)
389#endif
390 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500391 png_bytep sp=row;
392 png_bytep dp=row;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500393 png_uint_32 row_width=row_info->width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500394 png_uint_32 i;
395
Glenn Randers-Pehrson16e11662004-11-01 14:13:40 -0600396 if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
Glenn Randers-Pehrson94d93622004-11-01 22:38:54 -0600397 (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
Glenn Randers-Pehrson40936072004-11-20 11:18:40 -0600398 (flags & PNG_FLAG_STRIP_ALPHA))) &&
Glenn Randers-Pehrson5b779162004-09-04 13:25:08 -0500399 row_info->channels == 4)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500400 {
401 if (row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -0500402 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500403 /* This converts from RGBX or RGBA to RGB */
404 if (flags & PNG_FLAG_FILLER_AFTER)
405 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500406 dp+=3; sp+=4;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500407 for (i = 1; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500408 {
409 *dp++ = *sp++;
410 *dp++ = *sp++;
411 *dp++ = *sp++;
412 sp++;
413 }
414 }
415 /* This converts from XRGB or ARGB to RGB */
416 else
417 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500418 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500419 {
420 sp++;
421 *dp++ = *sp++;
422 *dp++ = *sp++;
423 *dp++ = *sp++;
424 }
425 }
426 row_info->pixel_depth = 24;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500427 row_info->rowbytes = row_width * 3;
Guy Schalnat0d580581995-07-20 02:43:20 -0500428 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500429 else /* if (row_info->bit_depth == 16) */
430 {
431 if (flags & PNG_FLAG_FILLER_AFTER)
432 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500433 /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500434 sp += 8; dp += 6;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500435 for (i = 1; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500436 {
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500437 /* This could be (although png_memcpy is probably slower):
Andreas Dilger47a0c421997-05-16 02:46:07 -0500438 png_memcpy(dp, sp, 6);
439 sp += 8;
440 dp += 6;
441 */
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500442
Andreas Dilger47a0c421997-05-16 02:46:07 -0500443 *dp++ = *sp++;
444 *dp++ = *sp++;
445 *dp++ = *sp++;
446 *dp++ = *sp++;
447 *dp++ = *sp++;
448 *dp++ = *sp++;
449 sp += 2;
450 }
451 }
452 else
453 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500454 /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500455 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500456 {
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500457 /* This could be (although png_memcpy is probably slower):
Andreas Dilger47a0c421997-05-16 02:46:07 -0500458 png_memcpy(dp, sp, 6);
459 sp += 8;
460 dp += 6;
461 */
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500462
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500463 sp+=2;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500464 *dp++ = *sp++;
465 *dp++ = *sp++;
466 *dp++ = *sp++;
467 *dp++ = *sp++;
468 *dp++ = *sp++;
469 *dp++ = *sp++;
470 }
471 }
472 row_info->pixel_depth = 48;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500473 row_info->rowbytes = row_width * 6;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500474 }
475 row_info->channels = 3;
Guy Schalnat0d580581995-07-20 02:43:20 -0500476 }
Glenn Randers-Pehrson94d93622004-11-01 22:38:54 -0600477 else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
Glenn Randers-Pehrson16e11662004-11-01 14:13:40 -0600478 (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
Glenn Randers-Pehrson40936072004-11-20 11:18:40 -0600479 (flags & PNG_FLAG_STRIP_ALPHA))) &&
Glenn Randers-Pehrson5b779162004-09-04 13:25:08 -0500480 row_info->channels == 2)
Guy Schalnat0d580581995-07-20 02:43:20 -0500481 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500482 if (row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -0500483 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500484 /* This converts from GX or GA to G */
485 if (flags & PNG_FLAG_FILLER_AFTER)
486 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500487 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500488 {
489 *dp++ = *sp++;
490 sp++;
491 }
492 }
493 /* This converts from XG or AG to G */
494 else
495 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500496 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500497 {
498 sp++;
499 *dp++ = *sp++;
500 }
501 }
502 row_info->pixel_depth = 8;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500503 row_info->rowbytes = row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -0500504 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500505 else /* if (row_info->bit_depth == 16) */
506 {
507 if (flags & PNG_FLAG_FILLER_AFTER)
508 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500509 /* This converts from GGXX or GGAA to GG */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500510 sp += 4; dp += 2;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500511 for (i = 1; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500512 {
513 *dp++ = *sp++;
514 *dp++ = *sp++;
515 sp += 2;
516 }
517 }
518 else
519 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500520 /* This converts from XXGG or AAGG to GG */
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500521 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500522 {
523 sp += 2;
524 *dp++ = *sp++;
525 *dp++ = *sp++;
526 }
527 }
528 row_info->pixel_depth = 16;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500529 row_info->rowbytes = row_width * 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500530 }
531 row_info->channels = 1;
Guy Schalnat0d580581995-07-20 02:43:20 -0500532 }
Glenn Randers-Pehrson40936072004-11-20 11:18:40 -0600533 if (flags & PNG_FLAG_STRIP_ALPHA)
Glenn Randers-Pehrson94d93622004-11-01 22:38:54 -0600534 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
Guy Schalnat0d580581995-07-20 02:43:20 -0500535 }
536}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500537#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500538
Andreas Dilger47a0c421997-05-16 02:46:07 -0500539#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
540/* swaps red and blue bytes within a pixel */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500541void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500542png_do_bgr(png_row_infop row_info, png_bytep row)
543{
544 png_debug(1, "in png_do_bgr\n");
545 if (
546#if defined(PNG_USELESS_TESTS_SUPPORTED)
547 row != NULL && row_info != NULL &&
548#endif
549 (row_info->color_type & PNG_COLOR_MASK_COLOR))
550 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500551 png_uint_32 row_width = row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500552 if (row_info->bit_depth == 8)
553 {
554 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
555 {
556 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500557 png_uint_32 i;
558
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500559 for (i = 0, rp = row; i < row_width; i++, rp += 3)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500560 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500561 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500562 *rp = *(rp + 2);
563 *(rp + 2) = save;
564 }
565 }
566 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
567 {
568 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500569 png_uint_32 i;
570
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500571 for (i = 0, rp = row; i < row_width; i++, rp += 4)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500572 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500573 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500574 *rp = *(rp + 2);
575 *(rp + 2) = save;
576 }
577 }
578 }
579 else if (row_info->bit_depth == 16)
580 {
581 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
582 {
583 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500584 png_uint_32 i;
585
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500586 for (i = 0, rp = row; i < row_width; i++, rp += 6)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500587 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500588 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500589 *rp = *(rp + 4);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500590 *(rp + 4) = save;
591 save = *(rp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500592 *(rp + 1) = *(rp + 5);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500593 *(rp + 5) = save;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500594 }
595 }
596 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
597 {
598 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500599 png_uint_32 i;
600
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500601 for (i = 0, rp = row; i < row_width; i++, rp += 8)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500602 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500603 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500604 *rp = *(rp + 4);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500605 *(rp + 4) = save;
606 save = *(rp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500607 *(rp + 1) = *(rp + 5);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500608 *(rp + 5) = save;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500609 }
610 }
611 }
612 }
613}
614#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
615
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500616#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500617 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
618 defined(PNG_LEGACY_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500619void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500620png_set_user_transform_info(png_structp png_ptr, png_voidp
621 user_transform_ptr, int user_transform_depth, int user_transform_channels)
622{
623 png_debug(1, "in png_set_user_transform_info\n");
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500624#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500625 png_ptr->user_transform_ptr = user_transform_ptr;
Glenn Randers-Pehrsonab1e5831999-10-06 04:57:42 -0500626 png_ptr->user_transform_depth = (png_byte)user_transform_depth;
627 png_ptr->user_transform_channels = (png_byte)user_transform_channels;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500628#else
629 if(user_transform_ptr || user_transform_depth || user_transform_channels)
630 png_warning(png_ptr,
631 "This version of libpng does not support user transform info");
632#endif
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500633}
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500634#endif
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500635
636/* This function returns a pointer to the user_transform_ptr associated with
637 * the user transform functions. The application should free any memory
638 * associated with this pointer before png_write_destroy and png_read_destroy
639 * are called.
640 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500641png_voidp PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500642png_get_user_transform_ptr(png_structp png_ptr)
643{
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500644#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500645 return ((png_voidp)png_ptr->user_transform_ptr);
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500646#else
647 if(png_ptr)
648 return (NULL);
649 return (NULL);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500650#endif
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500651}
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600652#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */