pngtrans.c 20.3 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 [August 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;
27

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;
41

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;
56

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

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

72 73
   if (png_ptr == NULL)
      return;
74

A
Andreas Dilger 已提交
75 76 77 78 79
   if (png_ptr->bit_depth < 8)
      png_ptr->transformations |= PNG_PACKSWAP;
}
#endif

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

86 87
   if (png_ptr == NULL)
      return;
88

G
Guy Schalnat 已提交
89 90 91
   png_ptr->transformations |= PNG_SHIFT;
   png_ptr->shift = *true_bits;
}
G
Guy Schalnat 已提交
92
#endif
G
Guy Schalnat 已提交
93

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

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

107
   return (1);
G
Guy Schalnat 已提交
108
}
G
Guy Schalnat 已提交
109
#endif
G
Guy Schalnat 已提交
110

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

122 123
   if (png_ptr == NULL)
      return;
124

G
Guy Schalnat 已提交
125
   png_ptr->transformations |= PNG_FILLER;
126
   png_ptr->filler = (png_uint_16)filler;
127

G
Guy Schalnat 已提交
128 129
   if (filler_loc == PNG_FILLER_AFTER)
      png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
130

G
Guy Schalnat 已提交
131 132
   else
      png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
133

134
   /* This should probably go in the "do_read_filler" routine.
135 136 137 138 139 140 141 142 143 144
    * 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
145
    * a less-than-8-bit grayscale to GA?) */
146 147 148 149 150

   if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
   {
      png_ptr->usr_channels = 2;
   }
G
Guy Schalnat 已提交
151
}
152 153 154 155 156

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

159 160
   if (png_ptr == NULL)
      return;
161

162 163 164 165
   png_set_filler(png_ptr, filler, filler_loc);
   png_ptr->transformations |= PNG_ADD_ALPHA;
}

A
Andreas Dilger 已提交
166
#endif
G
Guy Schalnat 已提交
167

A
Andreas Dilger 已提交
168 169
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
    defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
170
void PNGAPI
A
Andreas Dilger 已提交
171
png_set_swap_alpha(png_structp png_ptr)
G
Guy Schalnat 已提交
172
{
173
   png_debug(1, "in png_set_swap_alpha");
174

175 176
   if (png_ptr == NULL)
      return;
177

A
Andreas Dilger 已提交
178
   png_ptr->transformations |= PNG_SWAP_ALPHA;
G
Guy Schalnat 已提交
179
}
G
Guy Schalnat 已提交
180
#endif
G
Guy Schalnat 已提交
181

182 183
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
    defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
184
void PNGAPI
185 186
png_set_invert_alpha(png_structp png_ptr)
{
187
   png_debug(1, "in png_set_invert_alpha");
188

189 190
   if (png_ptr == NULL)
      return;
191

192 193 194 195
   png_ptr->transformations |= PNG_INVERT_ALPHA;
}
#endif

G
Guy Schalnat 已提交
196
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
197
void PNGAPI
G
Guy Schalnat 已提交
198
png_set_invert_mono(png_structp png_ptr)
G
Guy Schalnat 已提交
199
{
200
   png_debug(1, "in png_set_invert_mono");
201

202 203
   if (png_ptr == NULL)
      return;
204

G
Guy Schalnat 已提交
205 206 207
   png_ptr->transformations |= PNG_INVERT_MONO;
}

208
/* Invert monochrome grayscale data */
209
void /* PRIVATE */
G
Guy Schalnat 已提交
210
png_do_invert(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
211
{
212
   png_debug(1, "in png_do_invert");
213

214 215 216 217
  /* 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 已提交
218
   {
219
      png_bytep rp = row;
G
Guy Schalnat 已提交
220
      png_uint_32 i;
221
      png_uint_32 istop = row_info->rowbytes;
G
Guy Schalnat 已提交
222

223
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
224
      {
225 226
         *rp = (png_byte)(~(*rp));
         rp++;
G
Guy Schalnat 已提交
227 228
      }
   }
229

230 231 232 233 234 235 236
   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;

237
      for (i = 0; i < istop; i += 2)
238 239
      {
         *rp = (png_byte)(~(*rp));
240
         rp += 2;
241 242
      }
   }
243

244
#ifdef PNG_16BIT_SUPPORTED
245 246 247 248 249 250 251
   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;

252
      for (i = 0; i < istop; i += 4)
253 254
      {
         *rp = (png_byte)(~(*rp));
255 256
         *(rp + 1) = (png_byte)(~(*(rp + 1)));
         rp += 4;
257 258
      }
   }
259
#endif
G
Guy Schalnat 已提交
260
}
G
Guy Schalnat 已提交
261
#endif
G
Guy Schalnat 已提交
262

263
#ifdef PNG_16BIT_SUPPORTED
G
Guy Schalnat 已提交
264
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
265
/* Swaps byte order on 16 bit depth images */
266
void /* PRIVATE */
G
Guy Schalnat 已提交
267
png_do_swap(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
268
{
269
   png_debug(1, "in png_do_swap");
270

271
   if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
272
   {
273
      png_bytep rp = row;
G
Guy Schalnat 已提交
274
      png_uint_32 i;
275
      png_uint_32 istop= row_info->width * row_info->channels;
G
Guy Schalnat 已提交
276

277
      for (i = 0; i < istop; i++, rp += 2)
G
Guy Schalnat 已提交
278
      {
279
         png_byte t = *rp;
G
Guy Schalnat 已提交
280 281 282 283 284
         *rp = *(rp + 1);
         *(rp + 1) = t;
      }
   }
}
G
Guy Schalnat 已提交
285
#endif
286
#endif
G
Guy Schalnat 已提交
287

A
Andreas Dilger 已提交
288
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
289
static PNG_CONST png_byte onebppswaptable[256] = {
A
Andreas Dilger 已提交
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
   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
};

324
static PNG_CONST png_byte twobppswaptable[256] = {
A
Andreas Dilger 已提交
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
   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
};

359
static PNG_CONST png_byte fourbppswaptable[256] = {
A
Andreas Dilger 已提交
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
   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
};

394
/* Swaps pixel packing order within bytes */
395
void /* PRIVATE */
A
Andreas Dilger 已提交
396
png_do_packswap(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
397
{
398
   png_debug(1, "in png_do_packswap");
399

400
   if (row_info->bit_depth < 8)
G
Guy Schalnat 已提交
401
   {
402 403
      png_bytep rp;
      png_const_bytep end, table;
A
Andreas Dilger 已提交
404 405 406 407

      end = row + row_info->rowbytes;

      if (row_info->bit_depth == 1)
408
         table = onebppswaptable;
409

A
Andreas Dilger 已提交
410
      else if (row_info->bit_depth == 2)
411
         table = twobppswaptable;
412

A
Andreas Dilger 已提交
413
      else if (row_info->bit_depth == 4)
414
         table = fourbppswaptable;
415

A
Andreas Dilger 已提交
416 417 418 419 420 421 422 423 424 425 426
      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)
427
/* Remove filler or alpha byte(s) */
428
void /* PRIVATE */
429
png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
A
Andreas Dilger 已提交
430
{
431
   png_debug(1, "in png_do_strip_filler");
432

A
Andreas Dilger 已提交
433
   {
434 435 436
      png_bytep sp = row;
      png_bytep dp = row;
      png_uint_32 row_width = row_info->width;
437 438
      png_uint_32 i;

439
      if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
440 441 442
          (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
          (flags & PNG_FLAG_STRIP_ALPHA))) &&
          row_info->channels == 4)
G
Guy Schalnat 已提交
443
      {
A
Andreas Dilger 已提交
444 445 446 447 448
         if (row_info->bit_depth == 8)
         {
            /* This converts from RGBX or RGBA to RGB */
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
449
               dp += 3; sp += 4;
450
               for (i = 1; i < row_width; i++)
A
Andreas Dilger 已提交
451 452 453 454 455 456 457
               {
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  sp++;
               }
            }
458

A
Andreas Dilger 已提交
459 460 461
            /* This converts from XRGB or ARGB to RGB */
            else
            {
462
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
463 464 465 466 467 468 469 470
               {
                  sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 24;
471
            row_info->rowbytes = row_width * 3;
A
Andreas Dilger 已提交
472
         }
473

A
Andreas Dilger 已提交
474
         else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
475
         {
A
Andreas Dilger 已提交
476 477 478
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
               /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
479
               sp += 8; dp += 6;
480
               for (i = 1; 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

A
Andreas Dilger 已提交
488 489 490 491 492 493 494 495 496
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  sp += 2;
               }
            }
497

A
Andreas Dilger 已提交
498 499 500
            else
            {
               /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
501
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
502
               {
503
                  /* This could be (although png_memcpy is probably slower):
A
Andreas Dilger 已提交
504 505 506 507
                  png_memcpy(dp, sp, 6);
                  sp += 8;
                  dp += 6;
                  */
508

509
                  sp += 2;
A
Andreas Dilger 已提交
510 511 512 513 514 515 516 517
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
               }
            }
518

A
Andreas Dilger 已提交
519
            row_info->pixel_depth = 48;
520
            row_info->rowbytes = row_width * 6;
G
Guy Schalnat 已提交
521
         }
A
Andreas Dilger 已提交
522
         row_info->channels = 3;
G
Guy Schalnat 已提交
523
      }
524

525
      else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
526
         (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
527
         (flags & PNG_FLAG_STRIP_ALPHA))) &&
528
          row_info->channels == 2)
G
Guy Schalnat 已提交
529
      {
A
Andreas Dilger 已提交
530 531 532 533
         if (row_info->bit_depth == 8)
         {
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
534
               /* This converts from GX or GA to G */
535
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
536 537 538 539 540
               {
                  *dp++ = *sp++;
                  sp++;
               }
            }
541

A
Andreas Dilger 已提交
542 543
            else
            {
544
               /* This converts from XG or AG to G */
545
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
546 547 548 549 550
               {
                  sp++;
                  *dp++ = *sp++;
               }
            }
551

A
Andreas Dilger 已提交
552
            row_info->pixel_depth = 8;
553
            row_info->rowbytes = row_width;
A
Andreas Dilger 已提交
554
         }
555

A
Andreas Dilger 已提交
556
         else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
557
         {
A
Andreas Dilger 已提交
558 559 560
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
               /* This converts from GGXX or GGAA to GG */
561
               sp += 4; dp += 2;
562
               for (i = 1; i < row_width; i++)
A
Andreas Dilger 已提交
563 564 565 566 567 568
               {
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  sp += 2;
               }
            }
569

A
Andreas Dilger 已提交
570 571 572
            else
            {
               /* This converts from XXGG or AAGG to GG */
573
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
574 575 576 577 578 579
               {
                  sp += 2;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
               }
            }
580

A
Andreas Dilger 已提交
581
            row_info->pixel_depth = 16;
582
            row_info->rowbytes = row_width * 2;
G
Guy Schalnat 已提交
583
         }
A
Andreas Dilger 已提交
584
         row_info->channels = 1;
G
Guy Schalnat 已提交
585
      }
586

587
      if (flags & PNG_FLAG_STRIP_ALPHA)
588 589
        row_info->color_type = (png_byte)(row_info->color_type &
            ~PNG_COLOR_MASK_ALPHA);
A
Andreas Dilger 已提交
590 591 592 593 594
   }
}
#endif

#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
595
/* Swaps red and blue bytes within a pixel */
596
void /* PRIVATE */
A
Andreas Dilger 已提交
597 598
png_do_bgr(png_row_infop row_info, png_bytep row)
{
599
   png_debug(1, "in png_do_bgr");
600

601
   if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
A
Andreas Dilger 已提交
602
   {
603
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
604
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
605
      {
A
Andreas Dilger 已提交
606 607 608 609
         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
         {
            png_bytep rp;
            png_uint_32 i;
G
Guy Schalnat 已提交
610

611
            for (i = 0, rp = row; i < row_width; i++, rp += 3)
A
Andreas Dilger 已提交
612
            {
613
               png_byte save = *rp;
A
Andreas Dilger 已提交
614 615 616 617
               *rp = *(rp + 2);
               *(rp + 2) = save;
            }
         }
618

A
Andreas Dilger 已提交
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 += 4)
A
Andreas Dilger 已提交
625
            {
626
               png_byte save = *rp;
A
Andreas Dilger 已提交
627 628 629
               *rp = *(rp + 2);
               *(rp + 2) = save;
            }
G
Guy Schalnat 已提交
630 631
         }
      }
632

633
#ifdef PNG_16BIT_SUPPORTED
A
Andreas Dilger 已提交
634
      else if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
635
      {
A
Andreas Dilger 已提交
636 637 638 639
         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
         {
            png_bytep rp;
            png_uint_32 i;
G
Guy Schalnat 已提交
640

641
            for (i = 0, rp = row; i < row_width; i++, rp += 6)
A
Andreas Dilger 已提交
642
            {
643
               png_byte save = *rp;
A
Andreas Dilger 已提交
644
               *rp = *(rp + 4);
645 646
               *(rp + 4) = save;
               save = *(rp + 1);
A
Andreas Dilger 已提交
647
               *(rp + 1) = *(rp + 5);
648
               *(rp + 5) = save;
A
Andreas Dilger 已提交
649 650
            }
         }
651

A
Andreas Dilger 已提交
652
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
G
Guy Schalnat 已提交
653
         {
A
Andreas Dilger 已提交
654 655 656
            png_bytep rp;
            png_uint_32 i;

657
            for (i = 0, rp = row; i < row_width; i++, rp += 8)
A
Andreas Dilger 已提交
658
            {
659
               png_byte save = *rp;
A
Andreas Dilger 已提交
660
               *rp = *(rp + 4);
661 662
               *(rp + 4) = save;
               save = *(rp + 1);
A
Andreas Dilger 已提交
663
               *(rp + 1) = *(rp + 5);
664
               *(rp + 5) = save;
A
Andreas Dilger 已提交
665
            }
G
Guy Schalnat 已提交
666 667
         }
      }
668
#endif
G
Guy Schalnat 已提交
669 670
   }
}
A
Andreas Dilger 已提交
671
#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
G
Guy Schalnat 已提交
672

673
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
674
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
675
void PNGAPI
676 677 678
png_set_user_transform_info(png_structp png_ptr, png_voidp
   user_transform_ptr, int user_transform_depth, int user_transform_channels)
{
679
   png_debug(1, "in png_set_user_transform_info");
680

681 682
   if (png_ptr == NULL)
      return;
683
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
684
   png_ptr->user_transform_ptr = user_transform_ptr;
685 686
   png_ptr->user_transform_depth = (png_byte)user_transform_depth;
   png_ptr->user_transform_channels = (png_byte)user_transform_channels;
687
#else
688
   if (user_transform_ptr || user_transform_depth || user_transform_channels)
689 690 691
      png_warning(png_ptr,
        "This version of libpng does not support user transform info");
#endif
692 693 694 695 696 697 698
}

/* 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.
 */
699
png_voidp PNGAPI
700 701
png_get_user_transform_ptr(png_structp png_ptr)
{
702 703
   if (png_ptr == NULL)
      return (NULL);
704

705
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
706
   return ((png_voidp)png_ptr->user_transform_ptr);
707
#else
708
   return (NULL);
709
#endif
710
}
711
#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
712
          PNG_WRITE_USER_TRANSFORM_SUPPORTED */
713
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */