blob: 1c213a80010f04b77dfd7dfb722baf877e89d345 [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-Pehrson761bf9f2002-10-31 19:53:20 -06004 * libpng 1.2.6beta2 - November 1, 2002
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * For conditions of distribution and use, see copyright notice in png.h
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -06006 * Copyright (c) 1998-2002 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
Guy Schalnat51f0eb41995-09-26 05:22:39 -050014#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
Glenn Randers-Pehrson352ca6b1999-09-18 15:49:20 -050015/* turn on BGR-to-RGB mapping */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050016void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060017png_set_bgr(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050018{
Andreas Dilger47a0c421997-05-16 02:46:07 -050019 png_debug(1, "in png_set_bgr\n");
Guy Schalnat0d580581995-07-20 02:43:20 -050020 png_ptr->transformations |= PNG_BGR;
21}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050022#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050023
Guy Schalnat51f0eb41995-09-26 05:22:39 -050024#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050025/* turn on 16 bit byte swapping */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050026void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060027png_set_swap(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050028{
Andreas Dilger47a0c421997-05-16 02:46:07 -050029 png_debug(1, "in png_set_swap\n");
Guy Schalnat0d580581995-07-20 02:43:20 -050030 if (png_ptr->bit_depth == 16)
31 png_ptr->transformations |= PNG_SWAP_BYTES;
32}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050033#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050034
Guy Schalnat51f0eb41995-09-26 05:22:39 -050035#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050036/* turn on pixel packing */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050037void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060038png_set_packing(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050039{
Andreas Dilger47a0c421997-05-16 02:46:07 -050040 png_debug(1, "in png_set_packing\n");
Guy Schalnat0d580581995-07-20 02:43:20 -050041 if (png_ptr->bit_depth < 8)
42 {
43 png_ptr->transformations |= PNG_PACK;
44 png_ptr->usr_bit_depth = 8;
45 }
46}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050047#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050048
Andreas Dilger47a0c421997-05-16 02:46:07 -050049#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
50/* turn on packed pixel swapping */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050051void PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050052png_set_packswap(png_structp png_ptr)
53{
54 png_debug(1, "in png_set_packswap\n");
55 if (png_ptr->bit_depth < 8)
56 png_ptr->transformations |= PNG_PACKSWAP;
57}
58#endif
59
Guy Schalnat51f0eb41995-09-26 05:22:39 -050060#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050061void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060062png_set_shift(png_structp png_ptr, png_color_8p true_bits)
Guy Schalnat0d580581995-07-20 02:43:20 -050063{
Andreas Dilger47a0c421997-05-16 02:46:07 -050064 png_debug(1, "in png_set_shift\n");
Guy Schalnat0d580581995-07-20 02:43:20 -050065 png_ptr->transformations |= PNG_SHIFT;
66 png_ptr->shift = *true_bits;
67}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050068#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050069
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -060070#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
71 defined(PNG_WRITE_INTERLACING_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050072int PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060073png_set_interlace_handling(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050074{
Andreas Dilger47a0c421997-05-16 02:46:07 -050075 png_debug(1, "in png_set_interlace handling\n");
Guy Schalnat0d580581995-07-20 02:43:20 -050076 if (png_ptr->interlaced)
77 {
78 png_ptr->transformations |= PNG_INTERLACE;
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060079 return (7);
Guy Schalnat0d580581995-07-20 02:43:20 -050080 }
81
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060082 return (1);
Guy Schalnat0d580581995-07-20 02:43:20 -050083}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050084#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050085
Guy Schalnat51f0eb41995-09-26 05:22:39 -050086#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -050087/* 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
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050089 * for 48-bit input data, as well as to avoid problems with some compilers
90 * that don't like bytes as parameters.
Andreas Dilger47a0c421997-05-16 02:46:07 -050091 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050092void PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050093png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
Guy Schalnat0d580581995-07-20 02:43:20 -050094{
Andreas Dilger47a0c421997-05-16 02:46:07 -050095 png_debug(1, "in png_set_filler\n");
Guy Schalnat51f0eb41995-09-26 05:22:39 -050096 png_ptr->transformations |= PNG_FILLER;
Andreas Dilger47a0c421997-05-16 02:46:07 -050097 png_ptr->filler = (png_byte)filler;
Guy Schalnate5a37791996-06-05 15:50:50 -050098 if (filler_loc == PNG_FILLER_AFTER)
99 png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
100 else
101 png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600102
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
106 */
107
108 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
109 {
110 png_ptr->usr_channels = 4;
111 }
112
113 /* Also I added this in libpng-1.0.2a (what happens when we expand
114 * a less-than-8-bit grayscale to GA? */
115
116 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
117 {
118 png_ptr->usr_channels = 2;
119 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500120}
Andreas Dilger47a0c421997-05-16 02:46:07 -0500121#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500122
Andreas Dilger47a0c421997-05-16 02:46:07 -0500123#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
124 defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500125void PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -0500126png_set_swap_alpha(png_structp png_ptr)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500127{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500128 png_debug(1, "in png_set_swap_alpha\n");
129 png_ptr->transformations |= PNG_SWAP_ALPHA;
Guy Schalnat0d580581995-07-20 02:43:20 -0500130}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500131#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500132
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600133#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
134 defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500135void PNGAPI
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600136png_set_invert_alpha(png_structp png_ptr)
137{
138 png_debug(1, "in png_set_invert_alpha\n");
139 png_ptr->transformations |= PNG_INVERT_ALPHA;
140}
141#endif
142
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500143#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500144void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600145png_set_invert_mono(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500146{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500147 png_debug(1, "in png_set_invert_mono\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500148 png_ptr->transformations |= PNG_INVERT_MONO;
149}
150
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500151/* invert monochrome grayscale data */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500152void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600153png_do_invert(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500154{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500155 png_debug(1, "in png_do_invert\n");
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500156 /* This test removed from libpng version 1.0.13 and 1.2.0:
157 * if (row_info->bit_depth == 1 &&
158 */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500159#if defined(PNG_USELESS_TESTS_SUPPORTED)
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500160 if (row == NULL || row_info == NULL)
161 return;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500162#endif
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500163 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -0500164 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500165 png_bytep rp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -0500166 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500167 png_uint_32 istop = row_info->rowbytes;
Guy Schalnat0d580581995-07-20 02:43:20 -0500168
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500169 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500170 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500171 *rp = (png_byte)(~(*rp));
172 rp++;
Guy Schalnat0d580581995-07-20 02:43:20 -0500173 }
174 }
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500175 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
176 row_info->bit_depth == 8)
177 {
178 png_bytep rp = row;
179 png_uint_32 i;
180 png_uint_32 istop = row_info->rowbytes;
181
182 for (i = 0; i < istop; i+=2)
183 {
184 *rp = (png_byte)(~(*rp));
185 rp+=2;
186 }
187 }
188 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
189 row_info->bit_depth == 16)
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+=4)
196 {
197 *rp = (png_byte)(~(*rp));
198 *(rp+1) = (png_byte)(~(*(rp+1)));
199 rp+=4;
200 }
201 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500202}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500203#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500204
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500205#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500206/* swaps byte order on 16 bit depth images */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500207void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600208png_do_swap(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500209{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500210 png_debug(1, "in png_do_swap\n");
211 if (
212#if defined(PNG_USELESS_TESTS_SUPPORTED)
213 row != NULL && row_info != NULL &&
214#endif
215 row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -0500216 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500217 png_bytep rp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -0500218 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500219 png_uint_32 istop= row_info->width * row_info->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500220
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500221 for (i = 0; i < istop; i++, rp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -0500222 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500223 png_byte t = *rp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500224 *rp = *(rp + 1);
225 *(rp + 1) = t;
226 }
227 }
228}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500229#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500230
Andreas Dilger47a0c421997-05-16 02:46:07 -0500231#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
232static png_byte onebppswaptable[256] = {
233 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
234 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
235 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
236 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
237 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
238 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
239 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
240 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
241 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
242 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
243 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
244 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
245 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
246 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
247 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
248 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
249 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
250 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
251 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
252 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
253 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
254 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
255 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
256 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
257 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
258 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
259 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
260 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
261 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
262 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
263 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
264 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
265};
266
267static png_byte twobppswaptable[256] = {
268 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
269 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
270 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
271 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
272 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
273 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
274 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
275 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
276 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
277 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
278 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
279 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
280 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
281 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
282 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
283 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
284 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
285 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
286 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
287 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
288 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
289 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
290 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
291 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
292 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
293 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
294 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
295 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
296 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
297 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
298 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
299 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
300};
301
302static png_byte fourbppswaptable[256] = {
303 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
304 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
305 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
306 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
307 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
308 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
309 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
310 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
311 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
312 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
313 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
314 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
315 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
316 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
317 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
318 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
319 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
320 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
321 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
322 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
323 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
324 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
325 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
326 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
327 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
328 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
329 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
330 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
331 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
332 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
333 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
334 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
335};
336
337/* swaps pixel packing order within bytes */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500338void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500339png_do_packswap(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500340{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500341 png_debug(1, "in png_do_packswap\n");
342 if (
343#if defined(PNG_USELESS_TESTS_SUPPORTED)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600344 row != NULL && row_info != NULL &&
Andreas Dilger47a0c421997-05-16 02:46:07 -0500345#endif
346 row_info->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -0500347 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500348 png_bytep rp, end, table;
Guy Schalnat0d580581995-07-20 02:43:20 -0500349
Andreas Dilger47a0c421997-05-16 02:46:07 -0500350 end = row + row_info->rowbytes;
351
352 if (row_info->bit_depth == 1)
353 table = onebppswaptable;
354 else if (row_info->bit_depth == 2)
355 table = twobppswaptable;
356 else if (row_info->bit_depth == 4)
357 table = fourbppswaptable;
358 else
359 return;
360
361 for (rp = row; rp < end; rp++)
362 *rp = table[*rp];
363 }
364}
365#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
366
367#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
368 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
369/* remove filler or alpha byte(s) */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500370void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500371png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
372{
373 png_debug(1, "in png_do_strip_filler\n");
374#if defined(PNG_USELESS_TESTS_SUPPORTED)
375 if (row != NULL && row_info != NULL)
376#endif
377 {
378/*
379 if (row_info->color_type == PNG_COLOR_TYPE_RGB ||
380 row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
381*/
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500382 png_bytep sp=row;
383 png_bytep dp=row;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500384 png_uint_32 row_width=row_info->width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500385 png_uint_32 i;
386
Andreas Dilger47a0c421997-05-16 02:46:07 -0500387 if (row_info->channels == 4)
388 {
389 if (row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -0500390 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500391 /* This converts from RGBX or RGBA to RGB */
392 if (flags & PNG_FLAG_FILLER_AFTER)
393 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500394 dp+=3; sp+=4;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500395 for (i = 1; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500396 {
397 *dp++ = *sp++;
398 *dp++ = *sp++;
399 *dp++ = *sp++;
400 sp++;
401 }
402 }
403 /* This converts from XRGB or ARGB to RGB */
404 else
405 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500406 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500407 {
408 sp++;
409 *dp++ = *sp++;
410 *dp++ = *sp++;
411 *dp++ = *sp++;
412 }
413 }
414 row_info->pixel_depth = 24;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500415 row_info->rowbytes = row_width * 3;
Guy Schalnat0d580581995-07-20 02:43:20 -0500416 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500417 else /* if (row_info->bit_depth == 16) */
418 {
419 if (flags & PNG_FLAG_FILLER_AFTER)
420 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500421 /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500422 sp += 8; dp += 6;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500423 for (i = 1; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500424 {
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500425 /* This could be (although png_memcpy is probably slower):
Andreas Dilger47a0c421997-05-16 02:46:07 -0500426 png_memcpy(dp, sp, 6);
427 sp += 8;
428 dp += 6;
429 */
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500430
Andreas Dilger47a0c421997-05-16 02:46:07 -0500431 *dp++ = *sp++;
432 *dp++ = *sp++;
433 *dp++ = *sp++;
434 *dp++ = *sp++;
435 *dp++ = *sp++;
436 *dp++ = *sp++;
437 sp += 2;
438 }
439 }
440 else
441 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500442 /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500443 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500444 {
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500445 /* This could be (although png_memcpy is probably slower):
Andreas Dilger47a0c421997-05-16 02:46:07 -0500446 png_memcpy(dp, sp, 6);
447 sp += 8;
448 dp += 6;
449 */
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500450
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500451 sp+=2;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500452 *dp++ = *sp++;
453 *dp++ = *sp++;
454 *dp++ = *sp++;
455 *dp++ = *sp++;
456 *dp++ = *sp++;
457 *dp++ = *sp++;
458 }
459 }
460 row_info->pixel_depth = 48;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500461 row_info->rowbytes = row_width * 6;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500462 }
463 row_info->channels = 3;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500464 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
Guy Schalnat0d580581995-07-20 02:43:20 -0500465 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500466/*
467 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY ||
468 row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
469*/
470 else if (row_info->channels == 2)
Guy Schalnat0d580581995-07-20 02:43:20 -0500471 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500472 if (row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -0500473 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500474 /* This converts from GX or GA to G */
475 if (flags & PNG_FLAG_FILLER_AFTER)
476 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500477 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500478 {
479 *dp++ = *sp++;
480 sp++;
481 }
482 }
483 /* This converts from XG or AG to G */
484 else
485 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500486 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500487 {
488 sp++;
489 *dp++ = *sp++;
490 }
491 }
492 row_info->pixel_depth = 8;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500493 row_info->rowbytes = row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -0500494 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500495 else /* if (row_info->bit_depth == 16) */
496 {
497 if (flags & PNG_FLAG_FILLER_AFTER)
498 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500499 /* This converts from GGXX or GGAA to GG */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500500 sp += 4; dp += 2;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500501 for (i = 1; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500502 {
503 *dp++ = *sp++;
504 *dp++ = *sp++;
505 sp += 2;
506 }
507 }
508 else
509 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500510 /* This converts from XXGG or AAGG to GG */
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500511 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500512 {
513 sp += 2;
514 *dp++ = *sp++;
515 *dp++ = *sp++;
516 }
517 }
518 row_info->pixel_depth = 16;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500519 row_info->rowbytes = row_width * 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500520 }
521 row_info->channels = 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500522 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
Guy Schalnat0d580581995-07-20 02:43:20 -0500523 }
524 }
525}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500526#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500527
Andreas Dilger47a0c421997-05-16 02:46:07 -0500528#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
529/* swaps red and blue bytes within a pixel */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500530void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500531png_do_bgr(png_row_infop row_info, png_bytep row)
532{
533 png_debug(1, "in png_do_bgr\n");
534 if (
535#if defined(PNG_USELESS_TESTS_SUPPORTED)
536 row != NULL && row_info != NULL &&
537#endif
538 (row_info->color_type & PNG_COLOR_MASK_COLOR))
539 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500540 png_uint_32 row_width = row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500541 if (row_info->bit_depth == 8)
542 {
543 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
544 {
545 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500546 png_uint_32 i;
547
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500548 for (i = 0, rp = row; i < row_width; i++, rp += 3)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500549 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500550 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500551 *rp = *(rp + 2);
552 *(rp + 2) = save;
553 }
554 }
555 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
556 {
557 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500558 png_uint_32 i;
559
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500560 for (i = 0, rp = row; i < row_width; i++, rp += 4)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500561 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500562 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500563 *rp = *(rp + 2);
564 *(rp + 2) = save;
565 }
566 }
567 }
568 else if (row_info->bit_depth == 16)
569 {
570 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
571 {
572 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500573 png_uint_32 i;
574
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500575 for (i = 0, rp = row; i < row_width; i++, rp += 6)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500576 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500577 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500578 *rp = *(rp + 4);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500579 *(rp + 4) = save;
580 save = *(rp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500581 *(rp + 1) = *(rp + 5);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500582 *(rp + 5) = save;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500583 }
584 }
585 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
586 {
587 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500588 png_uint_32 i;
589
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500590 for (i = 0, rp = row; i < row_width; i++, rp += 8)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500591 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500592 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500593 *rp = *(rp + 4);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500594 *(rp + 4) = save;
595 save = *(rp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500596 *(rp + 1) = *(rp + 5);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500597 *(rp + 5) = save;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500598 }
599 }
600 }
601 }
602}
603#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
604
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500605#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500606 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
607 defined(PNG_LEGACY_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500608void PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500609png_set_user_transform_info(png_structp png_ptr, png_voidp
610 user_transform_ptr, int user_transform_depth, int user_transform_channels)
611{
612 png_debug(1, "in png_set_user_transform_info\n");
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500613#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500614 png_ptr->user_transform_ptr = user_transform_ptr;
Glenn Randers-Pehrsonab1e5831999-10-06 04:57:42 -0500615 png_ptr->user_transform_depth = (png_byte)user_transform_depth;
616 png_ptr->user_transform_channels = (png_byte)user_transform_channels;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500617#else
618 if(user_transform_ptr || user_transform_depth || user_transform_channels)
619 png_warning(png_ptr,
620 "This version of libpng does not support user transform info");
621#endif
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500622}
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500623#endif
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500624
625/* This function returns a pointer to the user_transform_ptr associated with
626 * the user transform functions. The application should free any memory
627 * associated with this pointer before png_write_destroy and png_read_destroy
628 * are called.
629 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500630png_voidp PNGAPI
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500631png_get_user_transform_ptr(png_structp png_ptr)
632{
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500633#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500634 return ((png_voidp)png_ptr->user_transform_ptr);
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500635#else
636 if(png_ptr)
637 return (NULL);
638 return (NULL);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500639#endif
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500640}