blob: e5d8770f0b40ae4f32623788f8680acc6e3e6f4b [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-Pehrsonf8b008c1999-09-18 10:54:36 -05004 * libpng 1.0.4 - September 18, 1999
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * 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
Glenn Randers-Pehrsonc9442291999-01-06 21:50:16 -06008 * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
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)
Guy Schalnat0d580581995-07-20 02:43:20 -050015/* turn on bgr to rgb mapping */
16void
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 */
26void
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 */
37void
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 */
51void
52png_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)
Guy Schalnat0d580581995-07-20 02:43:20 -050061void
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)
Guy Schalnat0d580581995-07-20 02:43:20 -050072int
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 */
Guy Schalnat0d580581995-07-20 02:43:20 -050092void
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)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500125void
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)
135void
136png_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)
Guy Schalnat0d580581995-07-20 02:43:20 -0500144void
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 */
Guy Schalnat0d580581995-07-20 02:43:20 -0500152void
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");
156 if (row_info->bit_depth == 1 &&
157#if defined(PNG_USELESS_TESTS_SUPPORTED)
158 row != NULL && row_info != NULL &&
159#endif
160 row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -0500161 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500162 png_bytep rp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -0500163 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500164 png_uint_32 istop = row_info->rowbytes;
Guy Schalnat0d580581995-07-20 02:43:20 -0500165
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500166 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500167 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500168 *rp = (png_byte)(~(*rp));
169 rp++;
Guy Schalnat0d580581995-07-20 02:43:20 -0500170 }
171 }
172}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500173#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500174
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500175#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500176/* swaps byte order on 16 bit depth images */
177void
Guy Schalnat6d764711995-12-19 03:22:19 -0600178png_do_swap(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500179{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500180 png_debug(1, "in png_do_swap\n");
181 if (
182#if defined(PNG_USELESS_TESTS_SUPPORTED)
183 row != NULL && row_info != NULL &&
184#endif
185 row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -0500186 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500187 png_bytep rp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -0500188 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500189 png_uint_32 istop= row_info->width * row_info->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500190
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500191 for (i = 0; i < istop; i++, rp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -0500192 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500193 png_byte t = *rp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500194 *rp = *(rp + 1);
195 *(rp + 1) = t;
196 }
197 }
198}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500199#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500200
Andreas Dilger47a0c421997-05-16 02:46:07 -0500201#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
202static 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
235};
236
237static 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
270};
271
272static 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
305};
306
307/* swaps pixel packing order within bytes */
Guy Schalnat0d580581995-07-20 02:43:20 -0500308void
Andreas Dilger47a0c421997-05-16 02:46:07 -0500309png_do_packswap(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500310{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500311 png_debug(1, "in png_do_packswap\n");
312 if (
313#if defined(PNG_USELESS_TESTS_SUPPORTED)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600314 row != NULL && row_info != NULL &&
Andreas Dilger47a0c421997-05-16 02:46:07 -0500315#endif
316 row_info->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -0500317 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500318 png_bytep rp, end, table;
Guy Schalnat0d580581995-07-20 02:43:20 -0500319
Andreas Dilger47a0c421997-05-16 02:46:07 -0500320 end = row + row_info->rowbytes;
321
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;
328 else
329 return;
330
331 for (rp = row; rp < end; rp++)
332 *rp = table[*rp];
333 }
334}
335#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
336
337#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
338 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
339/* remove filler or alpha byte(s) */
340void
341png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
342{
343 png_debug(1, "in png_do_strip_filler\n");
344#if defined(PNG_USELESS_TESTS_SUPPORTED)
345 if (row != NULL && row_info != NULL)
346#endif
347 {
348/*
349 if (row_info->color_type == PNG_COLOR_TYPE_RGB ||
350 row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
351*/
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500352 png_bytep sp=row;
353 png_bytep dp=row;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500354 png_uint_32 row_width=row_info->width;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500355 png_uint_32 i;
356
Andreas Dilger47a0c421997-05-16 02:46:07 -0500357 if (row_info->channels == 4)
358 {
359 if (row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -0500360 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500361 /* This converts from RGBX or RGBA to RGB */
362 if (flags & PNG_FLAG_FILLER_AFTER)
363 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500364 dp+=3; sp+=4;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500365 for (i = 1; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500366 {
367 *dp++ = *sp++;
368 *dp++ = *sp++;
369 *dp++ = *sp++;
370 sp++;
371 }
372 }
373 /* This converts from XRGB or ARGB to RGB */
374 else
375 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500376 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500377 {
378 sp++;
379 *dp++ = *sp++;
380 *dp++ = *sp++;
381 *dp++ = *sp++;
382 }
383 }
384 row_info->pixel_depth = 24;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500385 row_info->rowbytes = row_width * 3;
Guy Schalnat0d580581995-07-20 02:43:20 -0500386 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500387 else /* if (row_info->bit_depth == 16) */
388 {
389 if (flags & PNG_FLAG_FILLER_AFTER)
390 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500391 /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500392 sp += 8; dp += 6;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500393 for (i = 1; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500394 {
395 /* This could be (although memcpy is probably slower):
396 png_memcpy(dp, sp, 6);
397 sp += 8;
398 dp += 6;
399 */
400 *dp++ = *sp++;
401 *dp++ = *sp++;
402 *dp++ = *sp++;
403 *dp++ = *sp++;
404 *dp++ = *sp++;
405 *dp++ = *sp++;
406 sp += 2;
407 }
408 }
409 else
410 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500411 /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500412 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500413 {
414 /* This could be (although memcpy is probably slower):
415 png_memcpy(dp, sp, 6);
416 sp += 8;
417 dp += 6;
418 */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500419 sp+=2;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500420 *dp++ = *sp++;
421 *dp++ = *sp++;
422 *dp++ = *sp++;
423 *dp++ = *sp++;
424 *dp++ = *sp++;
425 *dp++ = *sp++;
426 }
427 }
428 row_info->pixel_depth = 48;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500429 row_info->rowbytes = row_width * 6;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500430 }
431 row_info->channels = 3;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500432 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
Guy Schalnat0d580581995-07-20 02:43:20 -0500433 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500434/*
435 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY ||
436 row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
437*/
438 else if (row_info->channels == 2)
Guy Schalnat0d580581995-07-20 02:43:20 -0500439 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500440 if (row_info->bit_depth == 8)
Guy Schalnat0d580581995-07-20 02:43:20 -0500441 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500442 /* This converts from GX or GA to G */
443 if (flags & PNG_FLAG_FILLER_AFTER)
444 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500445 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500446 {
447 *dp++ = *sp++;
448 sp++;
449 }
450 }
451 /* This converts from XG or AG to G */
452 else
453 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500454 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500455 {
456 sp++;
457 *dp++ = *sp++;
458 }
459 }
460 row_info->pixel_depth = 8;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500461 row_info->rowbytes = row_width;
Guy Schalnat0d580581995-07-20 02:43:20 -0500462 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500463 else /* if (row_info->bit_depth == 16) */
464 {
465 if (flags & PNG_FLAG_FILLER_AFTER)
466 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500467 /* This converts from GGXX or GGAA to GG */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500468 sp += 4; dp += 2;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500469 for (i = 1; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500470 {
471 *dp++ = *sp++;
472 *dp++ = *sp++;
473 sp += 2;
474 }
475 }
476 else
477 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500478 /* This converts from XXGG or AAGG to GG */
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500479 for (i = 0; i < row_width; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500480 {
481 sp += 2;
482 *dp++ = *sp++;
483 *dp++ = *sp++;
484 }
485 }
486 row_info->pixel_depth = 16;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500487 row_info->rowbytes = row_width * 2;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500488 }
489 row_info->channels = 1;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500490 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
Guy Schalnat0d580581995-07-20 02:43:20 -0500491 }
492 }
493}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500494#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500495
Andreas Dilger47a0c421997-05-16 02:46:07 -0500496#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
497/* swaps red and blue bytes within a pixel */
498void
499png_do_bgr(png_row_infop row_info, png_bytep row)
500{
501 png_debug(1, "in png_do_bgr\n");
502 if (
503#if defined(PNG_USELESS_TESTS_SUPPORTED)
504 row != NULL && row_info != NULL &&
505#endif
506 (row_info->color_type & PNG_COLOR_MASK_COLOR))
507 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500508 png_uint_32 row_width = row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500509 if (row_info->bit_depth == 8)
510 {
511 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
512 {
513 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500514 png_uint_32 i;
515
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500516 for (i = 0, rp = row; i < row_width; i++, rp += 3)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500517 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500518 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500519 *rp = *(rp + 2);
520 *(rp + 2) = save;
521 }
522 }
523 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
524 {
525 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500526 png_uint_32 i;
527
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500528 for (i = 0, rp = row; i < row_width; i++, rp += 4)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500529 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500530 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500531 *rp = *(rp + 2);
532 *(rp + 2) = save;
533 }
534 }
535 }
536 else if (row_info->bit_depth == 16)
537 {
538 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
539 {
540 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500541 png_uint_32 i;
542
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500543 for (i = 0, rp = row; i < row_width; i++, rp += 6)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500544 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500545 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500546 *rp = *(rp + 4);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500547 *(rp + 4) = save;
548 save = *(rp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500549 *(rp + 1) = *(rp + 5);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500550 *(rp + 5) = save;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500551 }
552 }
553 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
554 {
555 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500556 png_uint_32 i;
557
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500558 for (i = 0, rp = row; i < row_width; i++, rp += 8)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500559 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500560 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500561 *rp = *(rp + 4);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500562 *(rp + 4) = save;
563 save = *(rp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500564 *(rp + 1) = *(rp + 5);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500565 *(rp + 5) = save;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500566 }
567 }
568 }
569 }
570}
571#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
572
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500573#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
574 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
575void
576png_set_user_transform_info(png_structp png_ptr, png_voidp
577 user_transform_ptr, int user_transform_depth, int user_transform_channels)
578{
579 png_debug(1, "in png_set_user_transform_info\n");
580 png_ptr->user_transform_ptr = user_transform_ptr;
581 png_ptr->user_transform_depth = user_transform_depth;
582 png_ptr->user_transform_channels = user_transform_channels;
583}
584
585/* This function returns a pointer to the user_transform_ptr associated with
586 * the user transform functions. The application should free any memory
587 * associated with this pointer before png_write_destroy and png_read_destroy
588 * are called.
589 */
590png_voidp
591png_get_user_transform_ptr(png_structp png_ptr)
592{
593 return ((png_voidp)png_ptr->user_transform_ptr);
594}
595#endif