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 [April 28, 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
#include "pngpriv.h"
G
Guy Schalnat 已提交
15

16 17
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)

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

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

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

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

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

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

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

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

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

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

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

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

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

G
Guy Schalnat 已提交
106
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
A
Andreas Dilger 已提交
107 108
/* 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
109 110
 * for 48-bit input data, as well as to avoid problems with some compilers
 * that don't like bytes as parameters.
A
Andreas Dilger 已提交
111
 */
112
void PNGAPI
A
Andreas Dilger 已提交
113
png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
G
Guy Schalnat 已提交
114
{
115
   png_debug(1, "in png_set_filler");
116

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

126
   /* This should probably go in the "do_read_filler" routine.
127 128 129 130 131 132 133 134 135 136
    * 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
137
    * a less-than-8-bit grayscale to GA?) */
138 139 140 141 142

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

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

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

A
Andreas Dilger 已提交
157
#endif
G
Guy Schalnat 已提交
158

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

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

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

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

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

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

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

202 203 204 205
  /* 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 已提交
206
   {
207
      png_bytep rp = row;
G
Guy Schalnat 已提交
208
      png_uint_32 i;
209
      png_uint_32 istop = row_info->rowbytes;
G
Guy Schalnat 已提交
210

211
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
212
      {
213 214
         *rp = (png_byte)(~(*rp));
         rp++;
G
Guy Schalnat 已提交
215 216
      }
   }
217 218 219 220 221 222 223
   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;

224
      for (i = 0; i < istop; i += 2)
225 226
      {
         *rp = (png_byte)(~(*rp));
227
         rp += 2;
228 229 230 231 232 233 234 235 236
      }
   }
   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;

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

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

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

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

A
Andreas Dilger 已提交
271
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
272
static PNG_CONST png_byte onebppswaptable[256] = {
A
Andreas Dilger 已提交
273 274 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
   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
};

307
static PNG_CONST png_byte twobppswaptable[256] = {
A
Andreas Dilger 已提交
308 309 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
   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
};

342
static PNG_CONST png_byte fourbppswaptable[256] = {
A
Andreas Dilger 已提交
343 344 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
   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
};

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

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

      end = row + row_info->rowbytes;

      if (row_info->bit_depth == 1)
391
         table = (png_bytep)onebppswaptable;
A
Andreas Dilger 已提交
392
      else if (row_info->bit_depth == 2)
393
         table = (png_bytep)twobppswaptable;
A
Andreas Dilger 已提交
394
      else if (row_info->bit_depth == 4)
395
         table = (png_bytep)fourbppswaptable;
A
Andreas Dilger 已提交
396 397 398 399 400 401 402 403 404 405 406
      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)
407
/* Remove filler or alpha byte(s) */
408
void /* PRIVATE */
409
png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
A
Andreas Dilger 已提交
410
{
411
   png_debug(1, "in png_do_strip_filler");
412

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

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

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

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

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

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

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

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

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

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

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

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

/* 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.
 */
664
png_voidp PNGAPI
665 666
png_get_user_transform_ptr(png_structp png_ptr)
{
667 668
   if (png_ptr == NULL)
      return (NULL);
669
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
670
   return ((png_voidp)png_ptr->user_transform_ptr);
671
#else
672
   return (NULL);
673
#endif
674
}
675
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */