blob: 1100f46ebec27b509b8bdb2a726e74e0c151daa4 [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 *
Cosmin Trutaa8738932018-07-28 18:47:21 -04004 * Copyright (c) 2018 Cosmin Truta
Cosmin Truta46aedd82018-07-15 23:58:00 -04005 * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
Cosmin Trutaa8738932018-07-28 18:47:21 -04006 * Copyright (c) 1996-1997 Andreas Dilger
7 * 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-Pehrson8b83ff32015-08-13 20:57:18 -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-Pehrson5d713fe2014-10-31 20:48:55 -0500103 if (png_ptr != 0 && png_ptr->interlaced != 0)
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-Pehrson01a0e802015-09-24 22:39:53 -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 */
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500130 if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600131 {
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,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500175 "png_set_filler is invalid for"
176 " low bit depth gray output");
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600177 return;
178 }
179
180 default:
181 png_app_error(png_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500182 "png_set_filler: inappropriate color type");
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600183 return;
184 }
185# else
186 png_app_error(png_ptr, "png_set_filler not supported on write");
187 return;
188# endif
189 }
190
191 /* Here on success - libpng supports the operation, set the transformation
192 * and the flag to say where the filler channel is.
193 */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500194 png_ptr->transformations |= PNG_FILLER;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500195
Guy Schalnate5a37791996-06-05 15:50:50 -0500196 if (filler_loc == PNG_FILLER_AFTER)
197 png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500198
Guy Schalnate5a37791996-06-05 15:50:50 -0500199 else
200 png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
Guy Schalnat0d580581995-07-20 02:43:20 -0500201}
Glenn Randers-Pehrson67864af2004-08-28 23:30:07 -0500202
Glenn Randers-Pehrson67864af2004-08-28 23:30:07 -0500203/* Added to libpng-1.2.7 */
204void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600205png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
Glenn Randers-Pehrson67864af2004-08-28 23:30:07 -0500206{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500207 png_debug(1, "in png_set_add_alpha");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500208
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500209 if (png_ptr == NULL)
210 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500211
Glenn Randers-Pehrson01a0e802015-09-24 22:39:53 -0500212 png_set_filler(png_ptr, filler, filler_loc);
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600213 /* The above may fail to do anything. */
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500214 if ((png_ptr->transformations & PNG_FILLER) != 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600215 png_ptr->transformations |= PNG_ADD_ALPHA;
Glenn Randers-Pehrson67864af2004-08-28 23:30:07 -0500216}
Glenn Randers-Pehrson67864af2004-08-28 23:30:07 -0500217
Andreas Dilger47a0c421997-05-16 02:46:07 -0500218#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500219
Andreas Dilger47a0c421997-05-16 02:46:07 -0500220#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
221 defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500222void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600223png_set_swap_alpha(png_structrp png_ptr)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500224{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500225 png_debug(1, "in png_set_swap_alpha");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500226
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500227 if (png_ptr == NULL)
228 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500229
Andreas Dilger47a0c421997-05-16 02:46:07 -0500230 png_ptr->transformations |= PNG_SWAP_ALPHA;
Guy Schalnat0d580581995-07-20 02:43:20 -0500231}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500232#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500233
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600234#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
235 defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500236void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600237png_set_invert_alpha(png_structrp png_ptr)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600238{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500239 png_debug(1, "in png_set_invert_alpha");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500240
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500241 if (png_ptr == NULL)
242 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500243
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600244 png_ptr->transformations |= PNG_INVERT_ALPHA;
245}
246#endif
247
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500248#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500249void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600250png_set_invert_mono(png_structrp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500251{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500252 png_debug(1, "in png_set_invert_mono");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500253
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500254 if (png_ptr == NULL)
255 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500256
Guy Schalnat0d580581995-07-20 02:43:20 -0500257 png_ptr->transformations |= PNG_INVERT_MONO;
258}
259
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500260/* Invert monochrome grayscale data */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500261void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600262png_do_invert(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500263{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500264 png_debug(1, "in png_do_invert");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500265
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500266 /* This test removed from libpng version 1.0.13 and 1.2.0:
267 * if (row_info->bit_depth == 1 &&
268 */
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500269 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -0500270 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500271 png_bytep rp = row;
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400272 size_t i;
273 size_t istop = row_info->rowbytes;
Guy Schalnat0d580581995-07-20 02:43:20 -0500274
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500275 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500276 {
Glenn Randers-Pehrsonc5370ed2015-03-21 11:54:32 -0500277 *rp = (png_byte)(~(*rp));
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500278 rp++;
Guy Schalnat0d580581995-07-20 02:43:20 -0500279 }
280 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500281
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500282 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
283 row_info->bit_depth == 8)
284 {
285 png_bytep rp = row;
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400286 size_t i;
287 size_t istop = row_info->rowbytes;
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500288
Glenn Randers-Pehrson45624d62010-03-03 11:40:43 -0600289 for (i = 0; i < istop; i += 2)
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500290 {
Glenn Randers-Pehrsonc5370ed2015-03-21 11:54:32 -0500291 *rp = (png_byte)(~(*rp));
Glenn Randers-Pehrson45624d62010-03-03 11:40:43 -0600292 rp += 2;
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500293 }
294 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500295
Glenn Randers-Pehrson9c690912010-08-27 11:39:38 -0500296#ifdef PNG_16BIT_SUPPORTED
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500297 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
298 row_info->bit_depth == 16)
299 {
300 png_bytep rp = row;
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400301 size_t i;
302 size_t istop = row_info->rowbytes;
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500303
Glenn Randers-Pehrson45624d62010-03-03 11:40:43 -0600304 for (i = 0; i < istop; i += 4)
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500305 {
Glenn Randers-Pehrsonc5370ed2015-03-21 11:54:32 -0500306 *rp = (png_byte)(~(*rp));
307 *(rp + 1) = (png_byte)(~(*(rp + 1)));
Glenn Randers-Pehrson45624d62010-03-03 11:40:43 -0600308 rp += 4;
Glenn Randers-Pehrson1ea0ff32001-08-07 22:25:59 -0500309 }
310 }
Glenn Randers-Pehrson925d23b2010-08-26 21:43:18 -0500311#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500312}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500313#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500314
Glenn Randers-Pehrson925d23b2010-08-26 21:43:18 -0500315#ifdef PNG_16BIT_SUPPORTED
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500316#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
Glenn Randers-Pehrson8b83ff32015-08-13 20:57:18 -0500317/* Swaps byte order on 16-bit depth images */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500318void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -0600319png_do_swap(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500320{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500321 png_debug(1, "in png_do_swap");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500322
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500323 if (row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -0500324 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500325 png_bytep rp = row;
Guy Schalnat0d580581995-07-20 02:43:20 -0500326 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500327 png_uint_32 istop= row_info->width * row_info->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500328
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500329 for (i = 0; i < istop; i++, rp += 2)
Guy Schalnat0d580581995-07-20 02:43:20 -0500330 {
Glenn Randers-Pehrsonc4b37182014-04-06 08:59:57 -0500331#ifdef PNG_BUILTIN_BSWAP16_SUPPORTED
Glenn Randers-Pehrsond1c5f482014-05-09 21:06:27 -0500332 /* Feature added to libpng-1.6.11 for testing purposes, not
333 * enabled by default.
334 */
Glenn Randers-Pehrsonc4b37182014-04-06 08:59:57 -0500335 *(png_uint_16*)rp = __builtin_bswap16(*(png_uint_16*)rp);
336#else
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500337 png_byte t = *rp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500338 *rp = *(rp + 1);
339 *(rp + 1) = t;
Glenn Randers-Pehrsonc4b37182014-04-06 08:59:57 -0500340#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500341 }
342 }
343}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500344#endif
Glenn Randers-Pehrson925d23b2010-08-26 21:43:18 -0500345#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500346
Andreas Dilger47a0c421997-05-16 02:46:07 -0500347#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
Cosmin Truta1ef88822018-08-18 21:01:02 -0400348static const png_byte onebppswaptable[256] = {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500349 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
350 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
351 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
352 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
353 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
354 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
355 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
356 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
357 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
358 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
359 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
360 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
361 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
362 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
363 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
364 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
365 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
366 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
367 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
368 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
369 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
370 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
371 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
372 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
373 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
374 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
375 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
376 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
377 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
378 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
379 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
380 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
381};
382
Cosmin Truta1ef88822018-08-18 21:01:02 -0400383static const png_byte twobppswaptable[256] = {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500384 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
385 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
386 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
387 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
388 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
389 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
390 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
391 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
392 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
393 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
394 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
395 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
396 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
397 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
398 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
399 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
400 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
401 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
402 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
403 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
404 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
405 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
406 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
407 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
408 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
409 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
410 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
411 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
412 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
413 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
414 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
415 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
416};
417
Cosmin Truta1ef88822018-08-18 21:01:02 -0400418static const png_byte fourbppswaptable[256] = {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500419 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
420 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
421 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
422 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
423 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
424 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
425 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
426 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
427 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
428 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
429 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
430 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
431 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
432 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
433 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
434 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
435 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
436 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
437 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
438 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
439 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
440 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
441 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
442 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
443 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
444 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
445 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
446 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
447 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
448 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
449 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
450 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
451};
452
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500453/* Swaps pixel packing order within bytes */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500454void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500455png_do_packswap(png_row_infop row_info, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500456{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500457 png_debug(1, "in png_do_packswap");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500458
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500459 if (row_info->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -0500460 {
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500461 png_bytep rp;
462 png_const_bytep end, table;
Guy Schalnat0d580581995-07-20 02:43:20 -0500463
Andreas Dilger47a0c421997-05-16 02:46:07 -0500464 end = row + row_info->rowbytes;
465
466 if (row_info->bit_depth == 1)
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500467 table = onebppswaptable;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500468
Andreas Dilger47a0c421997-05-16 02:46:07 -0500469 else if (row_info->bit_depth == 2)
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500470 table = twobppswaptable;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500471
Andreas Dilger47a0c421997-05-16 02:46:07 -0500472 else if (row_info->bit_depth == 4)
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -0500473 table = fourbppswaptable;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500474
Andreas Dilger47a0c421997-05-16 02:46:07 -0500475 else
476 return;
477
478 for (rp = row; rp < end; rp++)
479 *rp = table[*rp];
480 }
481}
Glenn Randers-Pehrsoncda68df2014-11-06 22:11:39 -0600482#endif /* PACKSWAP || WRITE_PACKSWAP */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500483
484#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
485 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
John Bowler9b872f42011-02-12 09:00:16 -0600486/* Remove a channel - this used to be 'png_do_strip_filler' but it used a
487 * somewhat weird combination of flags to determine what to do. All the calls
488 * to png_do_strip_filler are changed in 1.5.2 to call this instead with the
489 * correct arguments.
490 *
491 * The routine isn't general - the channel must be the channel at the start or
492 * end (not in the middle) of each pixel.
493 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500494void /* PRIVATE */
John Bowler9b872f42011-02-12 09:00:16 -0600495png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500496{
John Bowler9b872f42011-02-12 09:00:16 -0600497 png_bytep sp = row; /* source pointer */
498 png_bytep dp = row; /* destination pointer */
499 png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500500
John Bowler9b872f42011-02-12 09:00:16 -0600501 /* At the start sp will point to the first byte to copy and dp to where
502 * it is copied to. ep always points just beyond the end of the row, so
503 * the loop simply copies (channels-1) channels until sp reaches ep.
Glenn Randers-Pehrsoncb1aee22011-04-16 19:27:34 -0500504 *
Glenn Randers-Pehrsone1018a52011-05-05 21:03:07 -0500505 * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
506 * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
John Bowler9b872f42011-02-12 09:00:16 -0600507 */
Glenn Randers-Pehrsoncb1aee22011-04-16 19:27:34 -0500508
John Bowler9b872f42011-02-12 09:00:16 -0600509 /* GA, GX, XG cases */
510 if (row_info->channels == 2)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500511 {
John Bowler9b872f42011-02-12 09:00:16 -0600512 if (row_info->bit_depth == 8)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500513 {
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -0600514 if (at_start != 0) /* Skip initial filler */
John Bowler9b872f42011-02-12 09:00:16 -0600515 ++sp;
Glenn Randers-Pehrsone1018a52011-05-05 21:03:07 -0500516 else /* Skip initial channel and, for sp, the filler */
Viktor Szakats8c50acb2017-03-29 23:54:40 +0000517 {
518 sp += 2; ++dp;
519 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500520
John Bowler9b872f42011-02-12 09:00:16 -0600521 /* For a 1 pixel wide image there is nothing to do */
522 while (sp < ep)
Viktor Szakats8c50acb2017-03-29 23:54:40 +0000523 {
524 *dp++ = *sp; sp += 2;
525 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500526
John Bowler9b872f42011-02-12 09:00:16 -0600527 row_info->pixel_depth = 8;
Guy Schalnat0d580581995-07-20 02:43:20 -0500528 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500529
John Bowler9b872f42011-02-12 09:00:16 -0600530 else if (row_info->bit_depth == 16)
Guy Schalnat0d580581995-07-20 02:43:20 -0500531 {
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -0600532 if (at_start != 0) /* Skip initial filler */
John Bowler9b872f42011-02-12 09:00:16 -0600533 sp += 2;
Glenn Randers-Pehrsone1018a52011-05-05 21:03:07 -0500534 else /* Skip initial channel and, for sp, the filler */
Viktor Szakats8c50acb2017-03-29 23:54:40 +0000535 {
536 sp += 4; dp += 2;
537 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500538
John Bowler9b872f42011-02-12 09:00:16 -0600539 while (sp < ep)
Viktor Szakats8c50acb2017-03-29 23:54:40 +0000540 {
541 *dp++ = *sp++; *dp++ = *sp; sp += 3;
542 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500543
John Bowler9b872f42011-02-12 09:00:16 -0600544 row_info->pixel_depth = 16;
Guy Schalnat0d580581995-07-20 02:43:20 -0500545 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500546
John Bowler9b872f42011-02-12 09:00:16 -0600547 else
548 return; /* bad bit depth */
549
550 row_info->channels = 1;
551
552 /* Finally fix the color type if it records an alpha channel */
553 if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
554 row_info->color_type = PNG_COLOR_TYPE_GRAY;
Guy Schalnat0d580581995-07-20 02:43:20 -0500555 }
John Bowler9b872f42011-02-12 09:00:16 -0600556
557 /* RGBA, RGBX, XRGB cases */
558 else if (row_info->channels == 4)
559 {
560 if (row_info->bit_depth == 8)
561 {
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -0600562 if (at_start != 0) /* Skip initial filler */
John Bowler9b872f42011-02-12 09:00:16 -0600563 ++sp;
564 else /* Skip initial channels and, for sp, the filler */
Viktor Szakats8c50acb2017-03-29 23:54:40 +0000565 {
566 sp += 4; dp += 3;
567 }
John Bowler9b872f42011-02-12 09:00:16 -0600568
569 /* Note that the loop adds 3 to dp and 4 to sp each time. */
570 while (sp < ep)
Viktor Szakats8c50acb2017-03-29 23:54:40 +0000571 {
572 *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp; sp += 2;
573 }
John Bowler9b872f42011-02-12 09:00:16 -0600574
575 row_info->pixel_depth = 24;
576 }
577
578 else if (row_info->bit_depth == 16)
579 {
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -0600580 if (at_start != 0) /* Skip initial filler */
John Bowler9b872f42011-02-12 09:00:16 -0600581 sp += 2;
Glenn Randers-Pehrsone1018a52011-05-05 21:03:07 -0500582 else /* Skip initial channels and, for sp, the filler */
Viktor Szakats8c50acb2017-03-29 23:54:40 +0000583 {
584 sp += 8; dp += 6;
585 }
John Bowler9b872f42011-02-12 09:00:16 -0600586
587 while (sp < ep)
588 {
589 /* Copy 6 bytes, skip 2 */
Viktor Szakats8c50acb2017-03-29 23:54:40 +0000590 *dp++ = *sp++; *dp++ = *sp++;
591 *dp++ = *sp++; *dp++ = *sp++;
592 *dp++ = *sp++; *dp++ = *sp; sp += 3;
John Bowler9b872f42011-02-12 09:00:16 -0600593 }
594
595 row_info->pixel_depth = 48;
596 }
597
598 else
599 return; /* bad bit depth */
600
601 row_info->channels = 3;
602
603 /* Finally fix the color type if it records an alpha channel */
604 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
605 row_info->color_type = PNG_COLOR_TYPE_RGB;
606 }
607
608 else
609 return; /* The filler channel has gone already */
610
611 /* Fix the rowbytes value. */
Cosmin Trutaa74aa9a2018-06-17 22:37:44 -0400612 row_info->rowbytes = (size_t)(dp-row);
Guy Schalnat0d580581995-07-20 02:43:20 -0500613}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500614#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500615
Andreas Dilger47a0c421997-05-16 02:46:07 -0500616#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500617/* Swaps red and blue bytes within a pixel */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500618void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500619png_do_bgr(png_row_infop row_info, png_bytep row)
620{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500621 png_debug(1, "in png_do_bgr");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500622
Glenn Randers-Pehrson5d713fe2014-10-31 20:48:55 -0500623 if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500624 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500625 png_uint_32 row_width = row_info->width;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500626 if (row_info->bit_depth == 8)
627 {
628 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
629 {
630 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500631 png_uint_32 i;
632
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500633 for (i = 0, rp = row; i < row_width; i++, rp += 3)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500634 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500635 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500636 *rp = *(rp + 2);
637 *(rp + 2) = save;
638 }
639 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500640
Andreas Dilger47a0c421997-05-16 02:46:07 -0500641 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
642 {
643 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500644 png_uint_32 i;
645
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500646 for (i = 0, rp = row; i < row_width; i++, rp += 4)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500647 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500648 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500649 *rp = *(rp + 2);
650 *(rp + 2) = save;
651 }
652 }
653 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500654
Glenn Randers-Pehrson925d23b2010-08-26 21:43:18 -0500655#ifdef PNG_16BIT_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500656 else if (row_info->bit_depth == 16)
657 {
658 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
659 {
660 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500661 png_uint_32 i;
662
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500663 for (i = 0, rp = row; i < row_width; i++, rp += 6)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500664 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500665 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500666 *rp = *(rp + 4);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500667 *(rp + 4) = save;
668 save = *(rp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500669 *(rp + 1) = *(rp + 5);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500670 *(rp + 5) = save;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500671 }
672 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500673
Andreas Dilger47a0c421997-05-16 02:46:07 -0500674 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
675 {
676 png_bytep rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500677 png_uint_32 i;
678
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500679 for (i = 0, rp = row; i < row_width; i++, rp += 8)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500680 {
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500681 png_byte save = *rp;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500682 *rp = *(rp + 4);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500683 *(rp + 4) = save;
684 save = *(rp + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500685 *(rp + 1) = *(rp + 5);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500686 *(rp + 5) = save;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500687 }
688 }
689 }
Glenn Randers-Pehrson925d23b2010-08-26 21:43:18 -0500690#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500691 }
692}
Glenn Randers-Pehrsoncda68df2014-11-06 22:11:39 -0600693#endif /* READ_BGR || WRITE_BGR */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500694
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600695#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
696 defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
697/* Added at libpng-1.5.10 */
698void /* PRIVATE */
699png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
700{
701 if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
702 png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
703 {
704 /* Calculations moved outside switch in an attempt to stop different
705 * compiler warnings. 'padding' is in *bits* within the last byte, it is
706 * an 'int' because pixel_depth becomes an 'int' in the expression below,
707 * and this calculation is used because it avoids warnings that other
708 * forms produced on either GCC or MSVC.
709 */
John Bowler319c9852016-09-30 18:37:22 -0700710 int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width);
Glenn Randers-Pehrsond2b9af02017-08-28 11:58:11 -0500711 png_bytep rp = png_ptr->row_buf + row_info->rowbytes - 1;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600712
713 switch (row_info->bit_depth)
714 {
715 case 1:
716 {
717 /* in this case, all bytes must be 0 so we don't need
718 * to unpack the pixels except for the rightmost one.
719 */
720 for (; rp > png_ptr->row_buf; rp--)
721 {
Glenn Randers-Pehrsonc861dc82015-04-01 12:06:01 -0500722 if ((*rp >> padding) != 0)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600723 png_ptr->num_palette_max = 1;
724 padding = 0;
725 }
726
727 break;
728 }
729
730 case 2:
731 {
732 for (; rp > png_ptr->row_buf; rp--)
733 {
734 int i = ((*rp >> padding) & 0x03);
735
736 if (i > png_ptr->num_palette_max)
737 png_ptr->num_palette_max = i;
738
739 i = (((*rp >> padding) >> 2) & 0x03);
740
741 if (i > png_ptr->num_palette_max)
742 png_ptr->num_palette_max = i;
743
744 i = (((*rp >> padding) >> 4) & 0x03);
745
746 if (i > png_ptr->num_palette_max)
747 png_ptr->num_palette_max = i;
748
749 i = (((*rp >> padding) >> 6) & 0x03);
750
751 if (i > png_ptr->num_palette_max)
752 png_ptr->num_palette_max = i;
753
754 padding = 0;
755 }
756
757 break;
758 }
759
760 case 4:
761 {
762 for (; rp > png_ptr->row_buf; rp--)
763 {
764 int i = ((*rp >> padding) & 0x0f);
765
766 if (i > png_ptr->num_palette_max)
767 png_ptr->num_palette_max = i;
768
769 i = (((*rp >> padding) >> 4) & 0x0f);
770
771 if (i > png_ptr->num_palette_max)
772 png_ptr->num_palette_max = i;
773
774 padding = 0;
775 }
776
777 break;
778 }
779
780 case 8:
781 {
782 for (; rp > png_ptr->row_buf; rp--)
783 {
784 if (*rp > png_ptr->num_palette_max)
785 png_ptr->num_palette_max = (int) *rp;
786 }
787
788 break;
789 }
790
791 default:
792 break;
793 }
794 }
795}
Glenn Randers-Pehrsoncda68df2014-11-06 22:11:39 -0600796#endif /* CHECK_FOR_INVALID_INDEX */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600797
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500798#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
Glenn Randers-Pehrson33188ac2009-06-16 14:12:35 -0500799 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
John Bowler0a5c9c02011-01-22 17:36:34 -0600800#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500801void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600802png_set_user_transform_info(png_structrp png_ptr, png_voidp
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500803 user_transform_ptr, int user_transform_depth, int user_transform_channels)
804{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500805 png_debug(1, "in png_set_user_transform_info");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -0500806
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500807 if (png_ptr == NULL)
808 return;
John Bowlerb44cd592013-04-12 22:12:19 -0500809
810#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
811 if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
812 (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
John Bowlera8715ca2013-04-13 12:25:16 -0500813 {
814 png_app_error(png_ptr,
Glenn Randers-Pehrsondd706042016-07-15 11:20:46 -0500815 "info change after png_start_read_image or png_read_update_info");
John Bowlerb44cd592013-04-12 22:12:19 -0500816 return;
John Bowlera8715ca2013-04-13 12:25:16 -0500817 }
John Bowlerb44cd592013-04-12 22:12:19 -0500818#endif
819
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500820 png_ptr->user_transform_ptr = user_transform_ptr;
Glenn Randers-Pehrsonc5370ed2015-03-21 11:54:32 -0500821 png_ptr->user_transform_depth = (png_byte)user_transform_depth;
822 png_ptr->user_transform_channels = (png_byte)user_transform_channels;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500823}
John Bowler0a5c9c02011-01-22 17:36:34 -0600824#endif
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500825
826/* This function returns a pointer to the user_transform_ptr associated with
827 * the user transform functions. The application should free any memory
828 * associated with this pointer before png_write_destroy and png_read_destroy
829 * are called.
830 */
John Bowler0a5c9c02011-01-22 17:36:34 -0600831#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500832png_voidp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600833png_get_user_transform_ptr(png_const_structrp png_ptr)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500834{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500835 if (png_ptr == NULL)
836 return (NULL);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500837
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600838 return png_ptr->user_transform_ptr;
John Bowler0a5c9c02011-01-22 17:36:34 -0600839}
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500840#endif
John Bowler0a5c9c02011-01-22 17:36:34 -0600841
John Bowler5432c012011-02-12 08:59:17 -0600842#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
John Bowler0a5c9c02011-01-22 17:36:34 -0600843png_uint_32 PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600844png_get_current_row_number(png_const_structrp png_ptr)
John Bowler0a5c9c02011-01-22 17:36:34 -0600845{
Glenn Randers-Pehrson91271382014-10-03 20:23:31 -0500846 /* See the comments in png.h - this is the sub-image row when reading an
John Bowler9616ad92011-02-16 06:13:46 -0600847 * interlaced image.
848 */
John Bowler0a5c9c02011-01-22 17:36:34 -0600849 if (png_ptr != NULL)
John Bowler9616ad92011-02-16 06:13:46 -0600850 return png_ptr->row_number;
John Bowler5432c012011-02-12 08:59:17 -0600851
John Bowler0a5c9c02011-01-22 17:36:34 -0600852 return PNG_UINT_32_MAX; /* help the app not to fail silently */
853}
854
855png_byte PNGAPI
John Bowler5d567862011-12-24 09:12:00 -0600856png_get_current_pass_number(png_const_structrp png_ptr)
John Bowler0a5c9c02011-01-22 17:36:34 -0600857{
858 if (png_ptr != NULL)
859 return png_ptr->pass;
860 return 8; /* invalid */
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500861}
Glenn Randers-Pehrsoncda68df2014-11-06 22:11:39 -0600862#endif /* USER_TRANSFORM_INFO */
863#endif /* READ_USER_TRANSFORM || WRITE_USER_TRANSFORM */
864#endif /* READ || WRITE */