pngtrans.c 20.1 KB
Newer Older
G
Guy Schalnat 已提交
1

A
Andreas Dilger 已提交
2
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
3
 *
4
 * Last changed in libpng 1.5.0 [March 8, 2010]
5
 * Copyright (c) 1998-2010 Glenn Randers-Pehrson
6 7
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8
 *
9
 * This code is released under the libpng license.
10
 * For conditions of distribution and use, see the disclaimer
11
 * and license in png.h
12
 */
G
Guy Schalnat 已提交
13

14
#define PNG_EXPOSE_INTERNAL_STRUCTURES
15
#define PNG_NO_PEDANTIC_WARNINGS
G
Guy Schalnat 已提交
16
#include "png.h"
17
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
18
#include "pngpriv.h"
G
Guy Schalnat 已提交
19

G
Guy Schalnat 已提交
20
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
21
/* Turn on BGR-to-RGB mapping */
22
void PNGAPI
G
Guy Schalnat 已提交
23
png_set_bgr(png_structp png_ptr)
G
Guy Schalnat 已提交
24
{
25
   png_debug(1, "in png_set_bgr");
26

27 28
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
29 30
   png_ptr->transformations |= PNG_BGR;
}
G
Guy Schalnat 已提交
31
#endif
G
Guy Schalnat 已提交
32

G
Guy Schalnat 已提交
33
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
34
/* Turn on 16 bit byte swapping */
35
void PNGAPI
G
Guy Schalnat 已提交
36
png_set_swap(png_structp png_ptr)
G
Guy Schalnat 已提交
37
{
38
   png_debug(1, "in png_set_swap");
39

40 41
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
42 43 44
   if (png_ptr->bit_depth == 16)
      png_ptr->transformations |= PNG_SWAP_BYTES;
}
G
Guy Schalnat 已提交
45
#endif
G
Guy Schalnat 已提交
46

G
Guy Schalnat 已提交
47
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
48
/* Turn on pixel packing */
49
void PNGAPI
G
Guy Schalnat 已提交
50
png_set_packing(png_structp png_ptr)
G
Guy Schalnat 已提交
51
{
52
   png_debug(1, "in png_set_packing");
53

54 55
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
56 57 58 59 60 61
   if (png_ptr->bit_depth < 8)
   {
      png_ptr->transformations |= PNG_PACK;
      png_ptr->usr_bit_depth = 8;
   }
}
G
Guy Schalnat 已提交
62
#endif
G
Guy Schalnat 已提交
63

A
Andreas Dilger 已提交
64
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
65
/* Turn on packed pixel swapping */
66
void PNGAPI
A
Andreas Dilger 已提交
67 68
png_set_packswap(png_structp png_ptr)
{
69
   png_debug(1, "in png_set_packswap");
70

71 72
   if (png_ptr == NULL)
      return;
A
Andreas Dilger 已提交
73 74 75 76 77
   if (png_ptr->bit_depth < 8)
      png_ptr->transformations |= PNG_PACKSWAP;
}
#endif

G
Guy Schalnat 已提交
78
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
79
void PNGAPI
G
Guy Schalnat 已提交
80
png_set_shift(png_structp png_ptr, png_color_8p true_bits)
G
Guy Schalnat 已提交
81
{
82
   png_debug(1, "in png_set_shift");
83

84 85
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
86 87 88
   png_ptr->transformations |= PNG_SHIFT;
   png_ptr->shift = *true_bits;
}
G
Guy Schalnat 已提交
89
#endif
G
Guy Schalnat 已提交
90

91 92
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
    defined(PNG_WRITE_INTERLACING_SUPPORTED)
93
int PNGAPI
G
Guy Schalnat 已提交
94
png_set_interlace_handling(png_structp png_ptr)
G
Guy Schalnat 已提交
95
{
96
   png_debug(1, "in png_set_interlace handling");
97

98
   if (png_ptr && png_ptr->interlaced)
G
Guy Schalnat 已提交
99 100
   {
      png_ptr->transformations |= PNG_INTERLACE;
101
      return (7);
G
Guy Schalnat 已提交
102 103
   }

104
   return (1);
G
Guy Schalnat 已提交
105
}
G
Guy Schalnat 已提交
106
#endif
G
Guy Schalnat 已提交
107

G
Guy Schalnat 已提交
108
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
A
Andreas Dilger 已提交
109 110
/* Add a filler byte on read, or remove a filler or alpha byte on write.
 * The filler type has changed in v0.95 to allow future 2-byte fillers
111 112
 * for 48-bit input data, as well as to avoid problems with some compilers
 * that don't like bytes as parameters.
A
Andreas Dilger 已提交
113
 */
114
void PNGAPI
A
Andreas Dilger 已提交
115
png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
G
Guy Schalnat 已提交
116
{
117
   png_debug(1, "in png_set_filler");
118

119 120
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
121
   png_ptr->transformations |= PNG_FILLER;
122
   png_ptr->filler = (png_uint_16)filler;
G
Guy Schalnat 已提交
123 124 125 126
   if (filler_loc == PNG_FILLER_AFTER)
      png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
   else
      png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
127

128
   /* This should probably go in the "do_read_filler" routine.
129 130 131 132 133 134 135 136 137 138
    * I attempted to do that in libpng-1.0.1a but that caused problems
    * so I restored it in libpng-1.0.2a
   */

   if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
   {
      png_ptr->usr_channels = 4;
   }

   /* Also I added this in libpng-1.0.2a (what happens when we expand
139
    * a less-than-8-bit grayscale to GA?) */
140 141 142 143 144

   if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
   {
      png_ptr->usr_channels = 2;
   }
G
Guy Schalnat 已提交
145
}
146 147 148 149 150

/* Added to libpng-1.2.7 */
void PNGAPI
png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
{
151
   png_debug(1, "in png_set_add_alpha");
152

153 154
   if (png_ptr == NULL)
      return;
155 156 157 158
   png_set_filler(png_ptr, filler, filler_loc);
   png_ptr->transformations |= PNG_ADD_ALPHA;
}

A
Andreas Dilger 已提交
159
#endif
G
Guy Schalnat 已提交
160

A
Andreas Dilger 已提交
161 162
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
    defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
163
void PNGAPI
A
Andreas Dilger 已提交
164
png_set_swap_alpha(png_structp png_ptr)
G
Guy Schalnat 已提交
165
{
166
   png_debug(1, "in png_set_swap_alpha");
167

168 169
   if (png_ptr == NULL)
      return;
A
Andreas Dilger 已提交
170
   png_ptr->transformations |= PNG_SWAP_ALPHA;
G
Guy Schalnat 已提交
171
}
G
Guy Schalnat 已提交
172
#endif
G
Guy Schalnat 已提交
173

174 175
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
    defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
176
void PNGAPI
177 178
png_set_invert_alpha(png_structp png_ptr)
{
179
   png_debug(1, "in png_set_invert_alpha");
180

181 182
   if (png_ptr == NULL)
      return;
183 184 185 186
   png_ptr->transformations |= PNG_INVERT_ALPHA;
}
#endif

G
Guy Schalnat 已提交
187
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
188
void PNGAPI
G
Guy Schalnat 已提交
189
png_set_invert_mono(png_structp png_ptr)
G
Guy Schalnat 已提交
190
{
191
   png_debug(1, "in png_set_invert_mono");
192

193 194
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
195 196 197
   png_ptr->transformations |= PNG_INVERT_MONO;
}

198
/* Invert monochrome grayscale data */
199
void /* PRIVATE */
G
Guy Schalnat 已提交
200
png_do_invert(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
201
{
202
   png_debug(1, "in png_do_invert");
203

204 205 206 207
  /* This test removed from libpng version 1.0.13 and 1.2.0:
   *   if (row_info->bit_depth == 1 &&
   */
   if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
208
   {
209
      png_bytep rp = row;
G
Guy Schalnat 已提交
210
      png_uint_32 i;
211
      png_uint_32 istop = row_info->rowbytes;
G
Guy Schalnat 已提交
212

213
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
214
      {
215 216
         *rp = (png_byte)(~(*rp));
         rp++;
G
Guy Schalnat 已提交
217 218
      }
   }
219 220 221 222 223 224 225
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
      row_info->bit_depth == 8)
   {
      png_bytep rp = row;
      png_uint_32 i;
      png_uint_32 istop = row_info->rowbytes;

226
      for (i = 0; i < istop; i += 2)
227 228
      {
         *rp = (png_byte)(~(*rp));
229
         rp += 2;
230 231 232 233 234 235 236 237 238
      }
   }
   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
      row_info->bit_depth == 16)
   {
      png_bytep rp = row;
      png_uint_32 i;
      png_uint_32 istop = row_info->rowbytes;

239
      for (i = 0; i < istop; i += 4)
240 241
      {
         *rp = (png_byte)(~(*rp));
242 243
         *(rp + 1) = (png_byte)(~(*(rp + 1)));
         rp += 4;
244 245
      }
   }
G
Guy Schalnat 已提交
246
}
G
Guy Schalnat 已提交
247
#endif
G
Guy Schalnat 已提交
248

G
Guy Schalnat 已提交
249
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
250
/* Swaps byte order on 16 bit depth images */
251
void /* PRIVATE */
G
Guy Schalnat 已提交
252
png_do_swap(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
253
{
254
   png_debug(1, "in png_do_swap");
255

A
Andreas Dilger 已提交
256 257
   if (
       row_info->bit_depth == 16)
G
Guy Schalnat 已提交
258
   {
259
      png_bytep rp = row;
G
Guy Schalnat 已提交
260
      png_uint_32 i;
261
      png_uint_32 istop= row_info->width * row_info->channels;
G
Guy Schalnat 已提交
262

263
      for (i = 0; i < istop; i++, rp += 2)
G
Guy Schalnat 已提交
264
      {
265
         png_byte t = *rp;
G
Guy Schalnat 已提交
266 267 268 269 270
         *rp = *(rp + 1);
         *(rp + 1) = t;
      }
   }
}
G
Guy Schalnat 已提交
271
#endif
G
Guy Schalnat 已提交
272

A
Andreas Dilger 已提交
273
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
274
static PNG_CONST png_byte onebppswaptable[256] = {
A
Andreas Dilger 已提交
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
   0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
   0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
   0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
   0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
   0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
   0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
   0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
   0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
   0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
   0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
   0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
   0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
   0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
   0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
   0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
   0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
   0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
   0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
   0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
   0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
   0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
   0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
   0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
   0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
   0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
   0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
   0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
   0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
   0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
   0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
   0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
   0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};

309
static PNG_CONST png_byte twobppswaptable[256] = {
A
Andreas Dilger 已提交
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
   0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
   0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
   0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
   0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
   0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
   0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
   0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
   0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
   0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
   0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
   0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
   0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
   0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
   0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
   0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
   0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
   0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
   0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
   0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
   0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
   0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
   0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
   0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
   0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
   0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
   0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
   0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
   0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
   0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
   0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
   0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
   0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
};

344
static PNG_CONST png_byte fourbppswaptable[256] = {
A
Andreas Dilger 已提交
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
   0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
   0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
   0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
   0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
   0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
   0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
   0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
   0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
   0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
   0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
   0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
   0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
   0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
   0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
   0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
   0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
   0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
   0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
   0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
   0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
   0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
   0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
   0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
   0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
   0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
   0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
   0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
   0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
   0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
   0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
   0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
   0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
};

379
/* Swaps pixel packing order within bytes */
380
void /* PRIVATE */
A
Andreas Dilger 已提交
381
png_do_packswap(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
382
{
383
   png_debug(1, "in png_do_packswap");
384

A
Andreas Dilger 已提交
385 386
   if (
       row_info->bit_depth < 8)
G
Guy Schalnat 已提交
387
   {
A
Andreas Dilger 已提交
388 389 390 391 392
      png_bytep rp, end, table;

      end = row + row_info->rowbytes;

      if (row_info->bit_depth == 1)
393
         table = (png_bytep)onebppswaptable;
A
Andreas Dilger 已提交
394
      else if (row_info->bit_depth == 2)
395
         table = (png_bytep)twobppswaptable;
A
Andreas Dilger 已提交
396
      else if (row_info->bit_depth == 4)
397
         table = (png_bytep)fourbppswaptable;
A
Andreas Dilger 已提交
398 399 400 401 402 403 404 405 406 407 408
      else
         return;

      for (rp = row; rp < end; rp++)
         *rp = table[*rp];
   }
}
#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */

#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
    defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
409
/* Remove filler or alpha byte(s) */
410
void /* PRIVATE */
411
png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
A
Andreas Dilger 已提交
412
{
413
   png_debug(1, "in png_do_strip_filler");
414

A
Andreas Dilger 已提交
415
   {
416 417 418
      png_bytep sp = row;
      png_bytep dp = row;
      png_uint_32 row_width = row_info->width;
419 420
      png_uint_32 i;

421
      if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
422 423 424
          (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
          (flags & PNG_FLAG_STRIP_ALPHA))) &&
          row_info->channels == 4)
G
Guy Schalnat 已提交
425
      {
A
Andreas Dilger 已提交
426 427 428 429 430
         if (row_info->bit_depth == 8)
         {
            /* This converts from RGBX or RGBA to RGB */
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
431
               dp += 3; sp += 4;
432
               for (i = 1; i < row_width; i++)
A
Andreas Dilger 已提交
433 434 435 436 437 438 439 440 441 442
               {
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  sp++;
               }
            }
            /* This converts from XRGB or ARGB to RGB */
            else
            {
443
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
444 445 446 447 448 449 450 451
               {
                  sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 24;
452
            row_info->rowbytes = row_width * 3;
A
Andreas Dilger 已提交
453 454
         }
         else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
455
         {
A
Andreas Dilger 已提交
456 457 458
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
               /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
459
               sp += 8; dp += 6;
460
               for (i = 1; i < row_width; i++)
A
Andreas Dilger 已提交
461
               {
462
                  /* This could be (although png_memcpy is probably slower):
A
Andreas Dilger 已提交
463 464 465 466
                  png_memcpy(dp, sp, 6);
                  sp += 8;
                  dp += 6;
                  */
467

A
Andreas Dilger 已提交
468 469 470 471 472 473 474 475 476 477 478 479
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  sp += 2;
               }
            }
            else
            {
               /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
480
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
481
               {
482
                  /* This could be (although png_memcpy is probably slower):
A
Andreas Dilger 已提交
483 484 485 486
                  png_memcpy(dp, sp, 6);
                  sp += 8;
                  dp += 6;
                  */
487

488
                  sp += 2;
A
Andreas Dilger 已提交
489 490 491 492 493 494 495 496 497
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 48;
498
            row_info->rowbytes = row_width * 6;
G
Guy Schalnat 已提交
499
         }
A
Andreas Dilger 已提交
500
         row_info->channels = 3;
G
Guy Schalnat 已提交
501
      }
502
      else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
503
         (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
504
         (flags & PNG_FLAG_STRIP_ALPHA))) &&
505
          row_info->channels == 2)
G
Guy Schalnat 已提交
506
      {
A
Andreas Dilger 已提交
507 508 509 510
         if (row_info->bit_depth == 8)
         {
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
511
               /* This converts from GX or GA to G */
512
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
513 514 515 516 517 518 519
               {
                  *dp++ = *sp++;
                  sp++;
               }
            }
            else
            {
520
               /* This converts from XG or AG to G */
521
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
522 523 524 525 526 527
               {
                  sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 8;
528
            row_info->rowbytes = row_width;
A
Andreas Dilger 已提交
529 530
         }
         else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
531
         {
A
Andreas Dilger 已提交
532 533 534
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
               /* This converts from GGXX or GGAA to GG */
535
               sp += 4; dp += 2;
536
               for (i = 1; i < row_width; i++)
A
Andreas Dilger 已提交
537 538 539 540 541 542 543 544 545
               {
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  sp += 2;
               }
            }
            else
            {
               /* This converts from XXGG or AAGG to GG */
546
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
547 548 549 550 551 552 553
               {
                  sp += 2;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 16;
554
            row_info->rowbytes = row_width * 2;
G
Guy Schalnat 已提交
555
         }
A
Andreas Dilger 已提交
556
         row_info->channels = 1;
G
Guy Schalnat 已提交
557
      }
558
      if (flags & PNG_FLAG_STRIP_ALPHA)
559
        row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
A
Andreas Dilger 已提交
560 561 562 563 564
   }
}
#endif

#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
565
/* Swaps red and blue bytes within a pixel */
566
void /* PRIVATE */
A
Andreas Dilger 已提交
567 568
png_do_bgr(png_row_infop row_info, png_bytep row)
{
569
   png_debug(1, "in png_do_bgr");
570

A
Andreas Dilger 已提交
571 572 573
   if (
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
574
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
575
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
576
      {
A
Andreas Dilger 已提交
577 578 579 580
         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
         {
            png_bytep rp;
            png_uint_32 i;
G
Guy Schalnat 已提交
581

582
            for (i = 0, rp = row; i < row_width; i++, rp += 3)
A
Andreas Dilger 已提交
583
            {
584
               png_byte save = *rp;
A
Andreas Dilger 已提交
585 586 587 588 589
               *rp = *(rp + 2);
               *(rp + 2) = save;
            }
         }
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
G
Guy Schalnat 已提交
590
         {
A
Andreas Dilger 已提交
591 592 593
            png_bytep rp;
            png_uint_32 i;

594
            for (i = 0, rp = row; i < row_width; i++, rp += 4)
A
Andreas Dilger 已提交
595
            {
596
               png_byte save = *rp;
A
Andreas Dilger 已提交
597 598 599
               *rp = *(rp + 2);
               *(rp + 2) = save;
            }
G
Guy Schalnat 已提交
600 601
         }
      }
A
Andreas Dilger 已提交
602
      else if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
603
      {
A
Andreas Dilger 已提交
604 605 606 607
         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
         {
            png_bytep rp;
            png_uint_32 i;
G
Guy Schalnat 已提交
608

609
            for (i = 0, rp = row; i < row_width; i++, rp += 6)
A
Andreas Dilger 已提交
610
            {
611
               png_byte save = *rp;
A
Andreas Dilger 已提交
612
               *rp = *(rp + 4);
613 614
               *(rp + 4) = save;
               save = *(rp + 1);
A
Andreas Dilger 已提交
615
               *(rp + 1) = *(rp + 5);
616
               *(rp + 5) = save;
A
Andreas Dilger 已提交
617 618 619
            }
         }
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
G
Guy Schalnat 已提交
620
         {
A
Andreas Dilger 已提交
621 622 623
            png_bytep rp;
            png_uint_32 i;

624
            for (i = 0, rp = row; i < row_width; i++, rp += 8)
A
Andreas Dilger 已提交
625
            {
626
               png_byte save = *rp;
A
Andreas Dilger 已提交
627
               *rp = *(rp + 4);
628 629
               *(rp + 4) = save;
               save = *(rp + 1);
A
Andreas Dilger 已提交
630
               *(rp + 1) = *(rp + 5);
631
               *(rp + 5) = save;
A
Andreas Dilger 已提交
632
            }
G
Guy Schalnat 已提交
633 634 635 636
         }
      }
   }
}
A
Andreas Dilger 已提交
637
#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
G
Guy Schalnat 已提交
638

639
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
640
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
641
void PNGAPI
642 643 644
png_set_user_transform_info(png_structp png_ptr, png_voidp
   user_transform_ptr, int user_transform_depth, int user_transform_channels)
{
645
   png_debug(1, "in png_set_user_transform_info");
646

647 648
   if (png_ptr == NULL)
      return;
649
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
650
   png_ptr->user_transform_ptr = user_transform_ptr;
651 652
   png_ptr->user_transform_depth = (png_byte)user_transform_depth;
   png_ptr->user_transform_channels = (png_byte)user_transform_channels;
653
#else
654
   if (user_transform_ptr || user_transform_depth || user_transform_channels)
655 656 657
      png_warning(png_ptr,
        "This version of libpng does not support user transform info");
#endif
658
}
659
#endif
660 661 662 663 664 665

/* This function returns a pointer to the user_transform_ptr associated with
 * the user transform functions.  The application should free any memory
 * associated with this pointer before png_write_destroy and png_read_destroy
 * are called.
 */
666
png_voidp PNGAPI
667 668
png_get_user_transform_ptr(png_structp png_ptr)
{
669 670
   if (png_ptr == NULL)
      return (NULL);
671
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
672
   return ((png_voidp)png_ptr->user_transform_ptr);
673
#else
674
   return (NULL);
675
#endif
676
}
677
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */