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.4.0 [December 22, 2009]
5
 * Copyright (c) 1998-2009 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_NO_PEDANTIC_WARNINGS
G
Guy Schalnat 已提交
15
#include "png.h"
16
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
17
#include "pngpriv.h"
G
Guy Schalnat 已提交
18

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

212
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
213
      {
214 215
         *rp = (png_byte)(~(*rp));
         rp++;
G
Guy Schalnat 已提交
216 217
      }
   }
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
   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;

      for (i = 0; i < istop; i+=2)
      {
         *rp = (png_byte)(~(*rp));
         rp+=2;
      }
   }
   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;

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

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

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

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

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

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

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

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

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

      end = row + row_info->rowbytes;

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

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

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

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

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

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

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

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

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

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

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

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

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

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