blob: 98f75d58347f4a5105671ade3ceabe86ff98f81f [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-Pehrson05670152014-03-08 12:39:52 -06004 * Last changed in libpng 1.6.11 [(PENDING RELEASE)]
Glenn Randers-Pehrson95a19732013-12-31 21:10:13 -06005 * Copyright (c) 1998-2014 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05006 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrson3e61d792009-06-24 09:31:28 -05008 *
Glenn Randers-Pehrsonbfbf8652009-06-26 21:46:52 -05009 * This code is released under the libpng license.
Glenn Randers-Pehrsonc332bbc2009-06-25 13:43:50 -050010 * For conditions of distribution and use, see the disclaimer
Glenn Randers-Pehrson037023b2009-06-24 10:27:36 -050011 * and license in png.h
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060012 */
Guy Schalnat0d580581995-07-20 02:43:20 -050013
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050014#include "pngpriv.h"
Guy Schalnat0d580581995-07-20 02:43:20 -050015
Glenn Randers-Pehrsonc3cd22b2010-03-08 21:10:25 -060016#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
17
Guy Schalnat51f0eb41995-09-26 05:22:39 -050018#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050019/* Turn on BGR-to-RGB mapping */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050020void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060021png_set_bgr(png_structrp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050022{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -050023 png_debug(1, "in png_set_bgr");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -050024
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050025 if (png_ptr == NULL)
26 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050027
Guy Schalnat0d580581995-07-20 02:43:20 -050028 png_ptr->transformations |= PNG_BGR;
29}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050030#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050031
Guy Schalnat51f0eb41995-09-26 05:22:39 -050032#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -050033/* Turn on 16 bit byte swapping */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050034void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060035png_set_swap(png_structrp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050036{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -050037 png_debug(1, "in png_set_swap");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -050038
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050039 if (png_ptr == NULL)
40 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050041
Guy Schalnat0d580581995-07-20 02:43:20 -050042 if (png_ptr->bit_depth == 16)
43 png_ptr->transformations |= PNG_SWAP_BYTES;
44}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050045#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050046
Guy Schalnat51f0eb41995-09-26 05:22:39 -050047#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -050048/* Turn on pixel packing */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050049void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060050png_set_packing(png_structrp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050051{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -050052 png_debug(1, "in png_set_packing");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -050053
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050054 if (png_ptr == NULL)
55 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050056
Guy Schalnat0d580581995-07-20 02:43:20 -050057 if (png_ptr->bit_depth < 8)
58 {
59 png_ptr->transformations |= PNG_PACK;
Glenn Randers-Pehrson88ecac62013-12-28 12:52:59 -060060# ifdef PNG_WRITE_SUPPORTED
61 png_ptr->usr_bit_depth = 8;
62# endif
Guy Schalnat0d580581995-07-20 02:43:20 -050063 }
64}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050065#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050066
Andreas Dilger47a0c421997-05-16 02:46:07 -050067#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -050068/* Turn on packed pixel swapping */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050069void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060070png_set_packswap(png_structrp png_ptr)
Andreas Dilger47a0c421997-05-16 02:46:07 -050071{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -050072 png_debug(1, "in png_set_packswap");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -050073
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050074 if (png_ptr == NULL)
75 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050076
Andreas Dilger47a0c421997-05-16 02:46:07 -050077 if (png_ptr->bit_depth < 8)
78 png_ptr->transformations |= PNG_PACKSWAP;
79}
80#endif
81
Guy Schalnat51f0eb41995-09-26 05:22:39 -050082#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050083void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060084png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)
Guy Schalnat0d580581995-07-20 02:43:20 -050085{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -050086 png_debug(1, "in png_set_shift");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -050087
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050088 if (png_ptr == NULL)
89 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050090
Guy Schalnat0d580581995-07-20 02:43:20 -050091 png_ptr->transformations |= PNG_SHIFT;
92 png_ptr->shift = *true_bits;
93}
Guy Schalnat51f0eb41995-09-26 05:22:39 -050094#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050095
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -060096#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
97 defined(PNG_WRITE_INTERLACING_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050098int PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060099png_set_interlace_handling(png_structrp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500100{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500101 png_debug(1, "in png_set_interlace handling");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500102
Glenn Randers-Pehrson6b12c082006-11-14 10:53:30 -0600103 if (png_ptr && png_ptr->interlaced)
Guy Schalnat0d580581995-07-20 02:43:20 -0500104 {
105 png_ptr->transformations |= PNG_INTERLACE;
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600106 return (7);
Guy Schalnat0d580581995-07-20 02:43:20 -0500107 }
108
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600109 return (1);
Guy Schalnat0d580581995-07-20 02:43:20 -0500110}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500111#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500112
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500113#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500114/* Add a filler byte on read, or remove a filler or alpha byte on write.
115 * The filler type has changed in v0.95 to allow future 2-byte fillers
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500116 * for 48-bit input data, as well as to avoid problems with some compilers
117 * that don't like bytes as parameters.
Andreas Dilger47a0c421997-05-16 02:46:07 -0500118 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500119void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600120png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
Guy Schalnat0d580581995-07-20 02:43:20 -0500121{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500122 png_debug(1, "in png_set_filler");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500123
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500124 if (png_ptr == NULL)
125 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500126
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600127 /* In libpng 1.6 it is possible to determine whether this is a read or write
128 * operation and therefore to do more checking here for a valid call.
129 */
130 if (png_ptr->mode & PNG_IS_READ_STRUCT)
131 {
132# ifdef PNG_READ_FILLER_SUPPORTED
133 /* On read png_set_filler is always valid, regardless of the base PNG
134 * format, because other transformations can give a format where the
135 * filler code can execute (basically an 8 or 16-bit component RGB or G
136 * format.)
137 *
138 * NOTE: usr_channels is not used by the read code! (This has led to
139 * confusion in the past.) The filler is only used in the read code.
140 */
141 png_ptr->filler = (png_uint_16)filler;
142# else
143 png_app_error(png_ptr, "png_set_filler not supported on read");
144 PNG_UNUSED(filler) /* not used in the write case */
145 return;
146# endif
147 }
148
149 else /* write */
150 {
151# ifdef PNG_WRITE_FILLER_SUPPORTED
152 /* On write the usr_channels parameter must be set correctly at the
153 * start to record the number of channels in the app-supplied data.
154 */
155 switch (png_ptr->color_type)
156 {
157 case PNG_COLOR_TYPE_RGB:
158 png_ptr->usr_channels = 4;
159 break;
160
161 case PNG_COLOR_TYPE_GRAY:
162 if (png_ptr->bit_depth >= 8)
163 {
164 png_ptr->usr_channels = 2;
165 break;
166 }
167
168 else
169 {
170 /* There simply isn't any code in libpng to strip out bits
171 * from bytes when the components are less than a byte in
172 * size!
173 */
174 png_app_error(png_ptr,
175 "png_set_filler is invalid for low bit depth gray output");
176 return;
177 }
178
179 default:
180 png_app_error(png_ptr,
181 "png_set_filler: inappropriate color type");
182 return;
183 }
184# else
185 png_app_error(png_ptr, "png_set_filler not supported on write");
186 return;
187# endif
188 }
189
190 /* Here on success - libpng supports the operation, set the transformation
191 * and the flag to say where the filler channel is.
192 */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500193 png_ptr->transformations |= PNG_FILLER;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500194
Guy Schalnate5a37791996-06-05 15:50:50 -0500195 if (filler_loc == PNG_FILLER_AFTER)
196 png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500197
Guy Schalnate5a37791996-06-05 15:50:50 -0500198 else
199 png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
Guy Schalnat0d580581995-07-20 02:43:20 -0500200}
Glenn Randers-Pehrson67864af2004-08-28 23:30:07 -0500201
Glenn Randers-Pehrson67864af2004-08-28 23:30:07 -0500202/* Added to libpng-1.2.7 */
203void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600204png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
Glenn Randers-Pehrson67864af2004-08-28 23:30:07 -0500205{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500206 png_debug(1, "in png_set_add_alpha");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500207
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500208 if (png_ptr == NULL)
209 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500210
Glenn Randers-Pehrson67864af2004-08-28 23:30:07 -0500211 png_set_filler(png_ptr, filler, filler_loc);
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600212 /* The above may fail to do anything. */
213 if (png_ptr->transformations & PNG_FILLER)
214 png_ptr->transformations |= PNG_ADD_ALPHA;
Glenn Randers-Pehrson67864af2004-08-28 23:30:07 -0500215}
Glenn Randers-Pehrson67864af2004-08-28 23:30:07 -0500216
Andreas Dilger47a0c421997-05-16 02:46:07 -0500217#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500218
Andreas Dilger47a0c421997-05-16 02:46:07 -0500219#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
220 defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500221void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600222png_set_swap_alpha(png_structrp png_ptr)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500223{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500224 png_debug(1, "in png_set_swap_alpha");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500225
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500226 if (png_ptr == NULL)
227 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500228
Andreas Dilger47a0c421997-05-16 02:46:07 -0500229 png_ptr->transformations |= PNG_SWAP_ALPHA;
Guy Schalnat0d580581995-07-20 02:43:20 -0500230}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500231#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500232
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600233#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
234 defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500235void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600236png_set_invert_alpha(png_structrp png_ptr)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600237{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500238 png_debug(1, "in png_set_invert_alpha");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500239
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500240 if (png_ptr == NULL)
241 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500242
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600243 png_ptr->transformations |= PNG_INVERT_ALPHA;
244}
245#endif
246
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500247#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500248void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600249png_set_invert_mono(png_structrp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500250{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500251 png_debug(1, "in png_set_invert_mono");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500252
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500253 if (png_ptr == NULL)
254 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500255
Guy Schalnat0d580581995-07-20 02:43:20 -0500256 png_ptr->transformations |= PNG_INVERT_MONO;
257}
258
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500259/* Invert monochrome grayscale data */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500260void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600261png_do_invert(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500262{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500263 png_debug(1, "in png_do_invert");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500264
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500265 /* This test removed from libpng version 1.0.13 and 1.2.0:
266 * if (row_info->bit_depth == 1 &&
267 */
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500268 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -0500269 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500270 png_bytep rp = row;
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500271 png_size_t i;
272 png_size_t istop = row_info->rowbytes;
Guy Schalnat0d580581995-07-20 02:43:20 -0500273
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500274 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500275 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500276 *rp = (png_byte)(~(*rp));
277 rp++;
Guy Schalnat0d580581995-07-20 02:43:20 -0500278 }
279 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500280
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500281 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
282 row_info->bit_depth == 8)
283 {
284 png_bytep rp = row;
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500285 png_size_t i;
286 png_size_t istop = row_info->rowbytes;
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500287
Glenn Randers-Pehrson45624d62010-03-03 11:40:43 -0600288 for (i = 0; i < istop; i += 2)
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500289 {
290 *rp = (png_byte)(~(*rp));
Glenn Randers-Pehrson45624d62010-03-03 11:40:43 -0600291 rp += 2;
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500292 }
293 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500294
Glenn Randers-Pehrson9c690912010-08-27 11:39:38 -0500295#ifdef PNG_16BIT_SUPPORTED
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500296 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
297 row_info->bit_depth == 16)
298 {
299 png_bytep rp = row;
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500300 png_size_t i;
301 png_size_t istop = row_info->rowbytes;
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500302
Glenn Randers-Pehrson45624d62010-03-03 11:40:43 -0600303 for (i = 0; i < istop; i += 4)
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500304 {
305 *rp = (png_byte)(~(*rp));
Glenn Randers-Pehrson45624d62010-03-03 11:40:43 -0600306 *(rp + 1) = (png_byte)(~(*(rp + 1)));
307 rp += 4;
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500308 }
309 }
Glenn Randers-Pehrson925d23b2010-08-26 21:43:18 -0500310#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500311}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500312#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500313
Glenn Randers-Pehrson925d23b2010-08-26 21:43:18 -0500314#ifdef PNG_16BIT_SUPPORTED
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500315#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500316/* Swaps byte order on 16 bit depth images */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500317void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600318png_do_swap(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500319{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500320 png_debug(1, "in png_do_swap");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500321
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500322 if (row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -0500323 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500324 png_bytep rp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -0500325 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500326 png_uint_32 istop= row_info->width * row_info->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500327
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500328 for (i = 0; i < istop; i++, rp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -0500329 {
Glenn Randers-Pehrsonc4b37182014-04-06 08:59:57 -0500330#ifdef PNG_BUILTIN_BSWAP16_SUPPORTED
331 *(png_uint_16*)rp = __builtin_bswap16(*(png_uint_16*)rp);
332#else
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500333 png_byte t = *rp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500334 *rp = *(rp + 1);
335 *(rp + 1) = t;
Glenn Randers-Pehrsonc4b37182014-04-06 08:59:57 -0500336#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500337 }
338 }
339}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500340#endif
Glenn Randers-Pehrson925d23b2010-08-26 21:43:18 -0500341#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500342
Andreas Dilger47a0c421997-05-16 02:46:07 -0500343#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
Glenn Randers-Pehrsonc3d51c12006-03-02 07:23:18 -0600344static PNG_CONST png_byte onebppswaptable[256] = {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500345 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
346 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
347 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
348 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
349 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
350 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
351 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
352 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
353 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
354 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
355 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
356 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
357 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
358 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
359 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
360 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
361 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
362 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
363 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
364 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
365 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
366 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
367 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
368 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
369 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
370 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
371 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
372 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
373 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
374 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
375 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
376 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
377};
378
Glenn Randers-Pehrsonc3d51c12006-03-02 07:23:18 -0600379static PNG_CONST png_byte twobppswaptable[256] = {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500380 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
381 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
382 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
383 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
384 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
385 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
386 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
387 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
388 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
389 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
390 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
391 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
392 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
393 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
394 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
395 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
396 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
397 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
398 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
399 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
400 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
401 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
402 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
403 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
404 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
405 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
406 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
407 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
408 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
409 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
410 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
411 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
412};
413
Glenn Randers-Pehrsonc3d51c12006-03-02 07:23:18 -0600414static PNG_CONST png_byte fourbppswaptable[256] = {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500415 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
416 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
417 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
418 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
419 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
420 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
421 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
422 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
423 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
424 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
425 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
426 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
427 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
428 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
429 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
430 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
431 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
432 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
433 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
434 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
435 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
436 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
437 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
438 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
439 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
440 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
441 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
442 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
443 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
444 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
445 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
446 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
447};
448
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500449/* Swaps pixel packing order within bytes */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500450void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500451png_do_packswap(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500452{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500453 png_debug(1, "in png_do_packswap");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500454
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500455 if (row_info->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -0500456 {
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500457 png_bytep rp;
458 png_const_bytep end, table;
Guy Schalnat0d580581995-07-20 02:43:20 -0500459
Andreas Dilger47a0c421997-05-16 02:46:07 -0500460 end = row + row_info->rowbytes;
461
462 if (row_info->bit_depth == 1)
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500463 table = onebppswaptable;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500464
Andreas Dilger47a0c421997-05-16 02:46:07 -0500465 else if (row_info->bit_depth == 2)
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500466 table = twobppswaptable;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500467
Andreas Dilger47a0c421997-05-16 02:46:07 -0500468 else if (row_info->bit_depth == 4)
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500469 table = fourbppswaptable;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500470
Andreas Dilger47a0c421997-05-16 02:46:07 -0500471 else
472 return;
473
474 for (rp = row; rp < end; rp++)
475 *rp = table[*rp];
476 }
477}
478#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
479
480#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
481 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
John Bowler9b872f42011-02-12 09:00:16 -0600482/* Remove a channel - this used to be 'png_do_strip_filler' but it used a
483 * somewhat weird combination of flags to determine what to do. All the calls
484 * to png_do_strip_filler are changed in 1.5.2 to call this instead with the
485 * correct arguments.
486 *
487 * The routine isn't general - the channel must be the channel at the start or
488 * end (not in the middle) of each pixel.
489 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500490void /* PRIVATE */
John Bowler9b872f42011-02-12 09:00:16 -0600491png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500492{
John Bowler9b872f42011-02-12 09:00:16 -0600493 png_bytep sp = row; /* source pointer */
494 png_bytep dp = row; /* destination pointer */
495 png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500496
John Bowler9b872f42011-02-12 09:00:16 -0600497 /* At the start sp will point to the first byte to copy and dp to where
498 * it is copied to. ep always points just beyond the end of the row, so
499 * the loop simply copies (channels-1) channels until sp reaches ep.
Glenn Randers-Pehrsoncb1aee22011-04-16 19:27:34 -0500500 *
Glenn Randers-Pehrsone1018a52011-05-05 21:03:07 -0500501 * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
502 * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
John Bowler9b872f42011-02-12 09:00:16 -0600503 */
Glenn Randers-Pehrsoncb1aee22011-04-16 19:27:34 -0500504
John Bowler9b872f42011-02-12 09:00:16 -0600505 /* GA, GX, XG cases */
506 if (row_info->channels == 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500507 {
John Bowler9b872f42011-02-12 09:00:16 -0600508 if (row_info->bit_depth == 8)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500509 {
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -0600510 if (at_start != 0) /* Skip initial filler */
John Bowler9b872f42011-02-12 09:00:16 -0600511 ++sp;
Glenn Randers-Pehrsone1018a52011-05-05 21:03:07 -0500512 else /* Skip initial channel and, for sp, the filler */
John Bowler9b872f42011-02-12 09:00:16 -0600513 sp += 2, ++dp;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500514
John Bowler9b872f42011-02-12 09:00:16 -0600515 /* For a 1 pixel wide image there is nothing to do */
516 while (sp < ep)
517 *dp++ = *sp, sp += 2;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500518
John Bowler9b872f42011-02-12 09:00:16 -0600519 row_info->pixel_depth = 8;
Guy Schalnat0d580581995-07-20 02:43:20 -0500520 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500521
John Bowler9b872f42011-02-12 09:00:16 -0600522 else if (row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -0500523 {
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -0600524 if (at_start != 0) /* Skip initial filler */
John Bowler9b872f42011-02-12 09:00:16 -0600525 sp += 2;
Glenn Randers-Pehrsone1018a52011-05-05 21:03:07 -0500526 else /* Skip initial channel and, for sp, the filler */
John Bowler9b872f42011-02-12 09:00:16 -0600527 sp += 4, dp += 2;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500528
John Bowler9b872f42011-02-12 09:00:16 -0600529 while (sp < ep)
530 *dp++ = *sp++, *dp++ = *sp, sp += 3;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500531
John Bowler9b872f42011-02-12 09:00:16 -0600532 row_info->pixel_depth = 16;
Guy Schalnat0d580581995-07-20 02:43:20 -0500533 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500534
John Bowler9b872f42011-02-12 09:00:16 -0600535 else
536 return; /* bad bit depth */
537
538 row_info->channels = 1;
539
540 /* Finally fix the color type if it records an alpha channel */
541 if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
542 row_info->color_type = PNG_COLOR_TYPE_GRAY;
Guy Schalnat0d580581995-07-20 02:43:20 -0500543 }
John Bowler9b872f42011-02-12 09:00:16 -0600544
545 /* RGBA, RGBX, XRGB cases */
546 else if (row_info->channels == 4)
547 {
548 if (row_info->bit_depth == 8)
549 {
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -0600550 if (at_start != 0) /* Skip initial filler */
John Bowler9b872f42011-02-12 09:00:16 -0600551 ++sp;
552 else /* Skip initial channels and, for sp, the filler */
553 sp += 4, dp += 3;
554
555 /* Note that the loop adds 3 to dp and 4 to sp each time. */
556 while (sp < ep)
557 *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
558
559 row_info->pixel_depth = 24;
560 }
561
562 else if (row_info->bit_depth == 16)
563 {
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -0600564 if (at_start != 0) /* Skip initial filler */
John Bowler9b872f42011-02-12 09:00:16 -0600565 sp += 2;
Glenn Randers-Pehrsone1018a52011-05-05 21:03:07 -0500566 else /* Skip initial channels and, for sp, the filler */
John Bowler9b872f42011-02-12 09:00:16 -0600567 sp += 8, dp += 6;
568
569 while (sp < ep)
570 {
571 /* Copy 6 bytes, skip 2 */
572 *dp++ = *sp++, *dp++ = *sp++;
573 *dp++ = *sp++, *dp++ = *sp++;
574 *dp++ = *sp++, *dp++ = *sp, sp += 3;
575 }
576
577 row_info->pixel_depth = 48;
578 }
579
580 else
581 return; /* bad bit depth */
582
583 row_info->channels = 3;
584
585 /* Finally fix the color type if it records an alpha channel */
586 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
587 row_info->color_type = PNG_COLOR_TYPE_RGB;
588 }
589
590 else
591 return; /* The filler channel has gone already */
592
593 /* Fix the rowbytes value. */
594 row_info->rowbytes = dp-row;
Guy Schalnat0d580581995-07-20 02:43:20 -0500595}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500596#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500597
Andreas Dilger47a0c421997-05-16 02:46:07 -0500598#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500599/* Swaps red and blue bytes within a pixel */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500600void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500601png_do_bgr(png_row_infop row_info, png_bytep row)
602{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500603 png_debug(1, "in png_do_bgr");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500604
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500605 if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
Andreas Dilger47a0c421997-05-16 02:46:07 -0500606 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500607 png_uint_32 row_width = row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500608 if (row_info->bit_depth == 8)
609 {
610 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
611 {
612 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500613 png_uint_32 i;
614
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500615 for (i = 0, rp = row; i < row_width; i++, rp += 3)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500616 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500617 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500618 *rp = *(rp + 2);
619 *(rp + 2) = save;
620 }
621 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500622
Andreas Dilger47a0c421997-05-16 02:46:07 -0500623 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
624 {
625 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500626 png_uint_32 i;
627
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500628 for (i = 0, rp = row; i < row_width; i++, rp += 4)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500629 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500630 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500631 *rp = *(rp + 2);
632 *(rp + 2) = save;
633 }
634 }
635 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500636
Glenn Randers-Pehrson925d23b2010-08-26 21:43:18 -0500637#ifdef PNG_16BIT_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500638 else if (row_info->bit_depth == 16)
639 {
640 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
641 {
642 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500643 png_uint_32 i;
644
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500645 for (i = 0, rp = row; i < row_width; i++, rp += 6)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500646 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500647 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500648 *rp = *(rp + 4);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500649 *(rp + 4) = save;
650 save = *(rp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500651 *(rp + 1) = *(rp + 5);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500652 *(rp + 5) = save;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500653 }
654 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500655
Andreas Dilger47a0c421997-05-16 02:46:07 -0500656 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
657 {
658 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500659 png_uint_32 i;
660
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500661 for (i = 0, rp = row; i < row_width; i++, rp += 8)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500662 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500663 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500664 *rp = *(rp + 4);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500665 *(rp + 4) = save;
666 save = *(rp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500667 *(rp + 1) = *(rp + 5);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500668 *(rp + 5) = save;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500669 }
670 }
671 }
Glenn Randers-Pehrson925d23b2010-08-26 21:43:18 -0500672#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500673 }
674}
675#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
676
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600677#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
678 defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
679/* Added at libpng-1.5.10 */
680void /* PRIVATE */
681png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
682{
683 if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
684 png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
685 {
686 /* Calculations moved outside switch in an attempt to stop different
687 * compiler warnings. 'padding' is in *bits* within the last byte, it is
688 * an 'int' because pixel_depth becomes an 'int' in the expression below,
689 * and this calculation is used because it avoids warnings that other
690 * forms produced on either GCC or MSVC.
691 */
692 int padding = (-row_info->pixel_depth * row_info->width) & 7;
693 png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
694
695 switch (row_info->bit_depth)
696 {
697 case 1:
698 {
699 /* in this case, all bytes must be 0 so we don't need
700 * to unpack the pixels except for the rightmost one.
701 */
702 for (; rp > png_ptr->row_buf; rp--)
703 {
704 if (*rp >> padding != 0)
705 png_ptr->num_palette_max = 1;
706 padding = 0;
707 }
708
709 break;
710 }
711
712 case 2:
713 {
714 for (; rp > png_ptr->row_buf; rp--)
715 {
716 int i = ((*rp >> padding) & 0x03);
717
718 if (i > png_ptr->num_palette_max)
719 png_ptr->num_palette_max = i;
720
721 i = (((*rp >> padding) >> 2) & 0x03);
722
723 if (i > png_ptr->num_palette_max)
724 png_ptr->num_palette_max = i;
725
726 i = (((*rp >> padding) >> 4) & 0x03);
727
728 if (i > png_ptr->num_palette_max)
729 png_ptr->num_palette_max = i;
730
731 i = (((*rp >> padding) >> 6) & 0x03);
732
733 if (i > png_ptr->num_palette_max)
734 png_ptr->num_palette_max = i;
735
736 padding = 0;
737 }
738
739 break;
740 }
741
742 case 4:
743 {
744 for (; rp > png_ptr->row_buf; rp--)
745 {
746 int i = ((*rp >> padding) & 0x0f);
747
748 if (i > png_ptr->num_palette_max)
749 png_ptr->num_palette_max = i;
750
751 i = (((*rp >> padding) >> 4) & 0x0f);
752
753 if (i > png_ptr->num_palette_max)
754 png_ptr->num_palette_max = i;
755
756 padding = 0;
757 }
758
759 break;
760 }
761
762 case 8:
763 {
764 for (; rp > png_ptr->row_buf; rp--)
765 {
766 if (*rp > png_ptr->num_palette_max)
767 png_ptr->num_palette_max = (int) *rp;
768 }
769
770 break;
771 }
772
773 default:
774 break;
775 }
776 }
777}
778#endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */
779
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500780#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
Glenn Randers-Pehrson33188ac2009-06-16 14:12:35 -0500781 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
John Bowler0a5c9c02011-01-22 17:36:34 -0600782#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500783void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600784png_set_user_transform_info(png_structrp png_ptr, png_voidp
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500785 user_transform_ptr, int user_transform_depth, int user_transform_channels)
786{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500787 png_debug(1, "in png_set_user_transform_info");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500788
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500789 if (png_ptr == NULL)
790 return;
John Bowlerb44cd592013-04-12 22:12:19 -0500791
792#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
793 if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
794 (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
John Bowlera8715ca2013-04-13 12:25:16 -0500795 {
796 png_app_error(png_ptr,
John Bowlerb44cd592013-04-12 22:12:19 -0500797 "info change after png_start_read_image or png_read_update_info");
798 return;
John Bowlera8715ca2013-04-13 12:25:16 -0500799 }
John Bowlerb44cd592013-04-12 22:12:19 -0500800#endif
801
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500802 png_ptr->user_transform_ptr = user_transform_ptr;
Glenn Randers-Pehrsonab1e5831999-10-06 04:57:42 -0500803 png_ptr->user_transform_depth = (png_byte)user_transform_depth;
804 png_ptr->user_transform_channels = (png_byte)user_transform_channels;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500805}
John Bowler0a5c9c02011-01-22 17:36:34 -0600806#endif
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500807
808/* This function returns a pointer to the user_transform_ptr associated with
809 * the user transform functions. The application should free any memory
810 * associated with this pointer before png_write_destroy and png_read_destroy
811 * are called.
812 */
John Bowler0a5c9c02011-01-22 17:36:34 -0600813#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500814png_voidp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600815png_get_user_transform_ptr(png_const_structrp png_ptr)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500816{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500817 if (png_ptr == NULL)
818 return (NULL);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500819
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600820 return png_ptr->user_transform_ptr;
John Bowler0a5c9c02011-01-22 17:36:34 -0600821}
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500822#endif
John Bowler0a5c9c02011-01-22 17:36:34 -0600823
John Bowler5432c012011-02-12 08:59:17 -0600824#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
John Bowler0a5c9c02011-01-22 17:36:34 -0600825png_uint_32 PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600826png_get_current_row_number(png_const_structrp png_ptr)
John Bowler0a5c9c02011-01-22 17:36:34 -0600827{
John Bowler9616ad92011-02-16 06:13:46 -0600828 /* See the comments in png.h - this is the sub-image row when reading and
829 * interlaced image.
830 */
John Bowler0a5c9c02011-01-22 17:36:34 -0600831 if (png_ptr != NULL)
John Bowler9616ad92011-02-16 06:13:46 -0600832 return png_ptr->row_number;
John Bowler5432c012011-02-12 08:59:17 -0600833
John Bowler0a5c9c02011-01-22 17:36:34 -0600834 return PNG_UINT_32_MAX; /* help the app not to fail silently */
835}
836
837png_byte PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600838png_get_current_pass_number(png_const_structrp png_ptr)
John Bowler0a5c9c02011-01-22 17:36:34 -0600839{
840 if (png_ptr != NULL)
841 return png_ptr->pass;
842 return 8; /* invalid */
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500843}
John Bowler5432c012011-02-12 08:59:17 -0600844#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */
Glenn Randers-Pehrsoncf2fd3b2010-04-28 21:25:18 -0500845#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
Glenn Randers-Pehrson4eb18e92010-07-30 14:46:52 -0500846 PNG_WRITE_USER_TRANSFORM_SUPPORTED */
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -0600847#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */