pngtrans.c 20.0 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 [June 2, 2009]
5
 * For conditions of distribution and use, see copyright notice in png.h
6
 * Copyright (c) 1998-2009 Glenn Randers-Pehrson
7 8
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9
 */
G
Guy Schalnat 已提交
10 11

#include "png.h"
12
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
13
#include "pngpriv.h"
G
Guy Schalnat 已提交
14

G
Guy Schalnat 已提交
15
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
16
/* Turn on BGR-to-RGB mapping */
17
void PNGAPI
G
Guy Schalnat 已提交
18
png_set_bgr(png_structp png_ptr)
G
Guy Schalnat 已提交
19
{
20
   png_debug(1, "in png_set_bgr");
21 22
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
23 24
   png_ptr->transformations |= PNG_BGR;
}
G
Guy Schalnat 已提交
25
#endif
G
Guy Schalnat 已提交
26

G
Guy Schalnat 已提交
27
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
28
/* Turn on 16 bit byte swapping */
29
void PNGAPI
G
Guy Schalnat 已提交
30
png_set_swap(png_structp png_ptr)
G
Guy Schalnat 已提交
31
{
32
   png_debug(1, "in png_set_swap");
33 34
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
35 36 37
   if (png_ptr->bit_depth == 16)
      png_ptr->transformations |= PNG_SWAP_BYTES;
}
G
Guy Schalnat 已提交
38
#endif
G
Guy Schalnat 已提交
39

G
Guy Schalnat 已提交
40
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
41
/* Turn on pixel packing */
42
void PNGAPI
G
Guy Schalnat 已提交
43
png_set_packing(png_structp png_ptr)
G
Guy Schalnat 已提交
44
{
45
   png_debug(1, "in png_set_packing");
46 47
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
48 49 50 51 52 53
   if (png_ptr->bit_depth < 8)
   {
      png_ptr->transformations |= PNG_PACK;
      png_ptr->usr_bit_depth = 8;
   }
}
G
Guy Schalnat 已提交
54
#endif
G
Guy Schalnat 已提交
55

A
Andreas Dilger 已提交
56
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
57
/* Turn on packed pixel swapping */
58
void PNGAPI
A
Andreas Dilger 已提交
59 60
png_set_packswap(png_structp png_ptr)
{
61
   png_debug(1, "in png_set_packswap");
62 63
   if (png_ptr == NULL)
      return;
A
Andreas Dilger 已提交
64 65 66 67 68
   if (png_ptr->bit_depth < 8)
      png_ptr->transformations |= PNG_PACKSWAP;
}
#endif

G
Guy Schalnat 已提交
69
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
70
void PNGAPI
G
Guy Schalnat 已提交
71
png_set_shift(png_structp png_ptr, png_color_8p true_bits)
G
Guy Schalnat 已提交
72
{
73
   png_debug(1, "in png_set_shift");
74 75
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
76 77 78
   png_ptr->transformations |= PNG_SHIFT;
   png_ptr->shift = *true_bits;
}
G
Guy Schalnat 已提交
79
#endif
G
Guy Schalnat 已提交
80

81 82
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
    defined(PNG_WRITE_INTERLACING_SUPPORTED)
83
int PNGAPI
G
Guy Schalnat 已提交
84
png_set_interlace_handling(png_structp png_ptr)
G
Guy Schalnat 已提交
85
{
86
   png_debug(1, "in png_set_interlace handling");
87
   if (png_ptr && png_ptr->interlaced)
G
Guy Schalnat 已提交
88 89
   {
      png_ptr->transformations |= PNG_INTERLACE;
90
      return (7);
G
Guy Schalnat 已提交
91 92
   }

93
   return (1);
G
Guy Schalnat 已提交
94
}
G
Guy Schalnat 已提交
95
#endif
G
Guy Schalnat 已提交
96

G
Guy Schalnat 已提交
97
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
A
Andreas Dilger 已提交
98 99
/* 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
100 101
 * for 48-bit input data, as well as to avoid problems with some compilers
 * that don't like bytes as parameters.
A
Andreas Dilger 已提交
102
 */
103
void PNGAPI
A
Andreas Dilger 已提交
104
png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
G
Guy Schalnat 已提交
105
{
106
   png_debug(1, "in png_set_filler");
107 108
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
109
   png_ptr->transformations |= PNG_FILLER;
A
Andreas Dilger 已提交
110
   png_ptr->filler = (png_byte)filler;
G
Guy Schalnat 已提交
111 112 113 114
   if (filler_loc == PNG_FILLER_AFTER)
      png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
   else
      png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
115

116
   /* This should probably go in the "do_read_filler" routine.
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
    * 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 已提交
133
}
134 135 136 137 138

/* Added to libpng-1.2.7 */
void PNGAPI
png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
{
139
   png_debug(1, "in png_set_add_alpha");
140 141
   if (png_ptr == NULL)
      return;
142 143 144 145
   png_set_filler(png_ptr, filler, filler_loc);
   png_ptr->transformations |= PNG_ADD_ALPHA;
}

A
Andreas Dilger 已提交
146
#endif
G
Guy Schalnat 已提交
147

A
Andreas Dilger 已提交
148 149
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
    defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
150
void PNGAPI
A
Andreas Dilger 已提交
151
png_set_swap_alpha(png_structp png_ptr)
G
Guy Schalnat 已提交
152
{
153
   png_debug(1, "in png_set_swap_alpha");
154 155
   if (png_ptr == NULL)
      return;
A
Andreas Dilger 已提交
156
   png_ptr->transformations |= PNG_SWAP_ALPHA;
G
Guy Schalnat 已提交
157
}
G
Guy Schalnat 已提交
158
#endif
G
Guy Schalnat 已提交
159

160 161
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
    defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
162
void PNGAPI
163 164
png_set_invert_alpha(png_structp png_ptr)
{
165
   png_debug(1, "in png_set_invert_alpha");
166 167
   if (png_ptr == NULL)
      return;
168 169 170 171
   png_ptr->transformations |= PNG_INVERT_ALPHA;
}
#endif

G
Guy Schalnat 已提交
172
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
173
void PNGAPI
G
Guy Schalnat 已提交
174
png_set_invert_mono(png_structp png_ptr)
G
Guy Schalnat 已提交
175
{
176
   png_debug(1, "in png_set_invert_mono");
177 178
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
179 180 181
   png_ptr->transformations |= PNG_INVERT_MONO;
}

182
/* Invert monochrome grayscale data */
183
void /* PRIVATE */
G
Guy Schalnat 已提交
184
png_do_invert(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
185
{
186
   png_debug(1, "in png_do_invert");
187 188 189 190
  /* 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 已提交
191
   {
192
      png_bytep rp = row;
G
Guy Schalnat 已提交
193
      png_uint_32 i;
194
      png_uint_32 istop = row_info->rowbytes;
G
Guy Schalnat 已提交
195

196
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
197
      {
198 199
         *rp = (png_byte)(~(*rp));
         rp++;
G
Guy Schalnat 已提交
200 201
      }
   }
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
   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 已提交
229
}
G
Guy Schalnat 已提交
230
#endif
G
Guy Schalnat 已提交
231

G
Guy Schalnat 已提交
232
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
233
/* Swaps byte order on 16 bit depth images */
234
void /* PRIVATE */
G
Guy Schalnat 已提交
235
png_do_swap(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
236
{
237
   png_debug(1, "in png_do_swap");
A
Andreas Dilger 已提交
238 239
   if (
       row_info->bit_depth == 16)
G
Guy Schalnat 已提交
240
   {
241
      png_bytep rp = row;
G
Guy Schalnat 已提交
242
      png_uint_32 i;
243
      png_uint_32 istop= row_info->width * row_info->channels;
G
Guy Schalnat 已提交
244

245
      for (i = 0; i < istop; i++, rp += 2)
G
Guy Schalnat 已提交
246
      {
247
         png_byte t = *rp;
G
Guy Schalnat 已提交
248 249 250 251 252
         *rp = *(rp + 1);
         *(rp + 1) = t;
      }
   }
}
G
Guy Schalnat 已提交
253
#endif
G
Guy Schalnat 已提交
254

A
Andreas Dilger 已提交
255
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
256
static PNG_CONST png_byte onebppswaptable[256] = {
A
Andreas Dilger 已提交
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
   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
};

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

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

361
/* Swaps pixel packing order within bytes */
362
void /* PRIVATE */
A
Andreas Dilger 已提交
363
png_do_packswap(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
364
{
365
   png_debug(1, "in png_do_packswap");
A
Andreas Dilger 已提交
366 367
   if (
       row_info->bit_depth < 8)
G
Guy Schalnat 已提交
368
   {
A
Andreas Dilger 已提交
369 370 371 372 373
      png_bytep rp, end, table;

      end = row + row_info->rowbytes;

      if (row_info->bit_depth == 1)
374
         table = (png_bytep)onebppswaptable;
A
Andreas Dilger 已提交
375
      else if (row_info->bit_depth == 2)
376
         table = (png_bytep)twobppswaptable;
A
Andreas Dilger 已提交
377
      else if (row_info->bit_depth == 4)
378
         table = (png_bytep)fourbppswaptable;
A
Andreas Dilger 已提交
379 380 381 382 383 384 385 386 387 388 389
      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)
390
/* Remove filler or alpha byte(s) */
391
void /* PRIVATE */
392
png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
A
Andreas Dilger 已提交
393
{
394
   png_debug(1, "in png_do_strip_filler");
A
Andreas Dilger 已提交
395
   {
396 397
      png_bytep sp=row;
      png_bytep dp=row;
398
      png_uint_32 row_width=row_info->width;
399 400
      png_uint_32 i;

401
      if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
402 403 404
          (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
          (flags & PNG_FLAG_STRIP_ALPHA))) &&
          row_info->channels == 4)
G
Guy Schalnat 已提交
405
      {
A
Andreas Dilger 已提交
406 407 408 409 410
         if (row_info->bit_depth == 8)
         {
            /* This converts from RGBX or RGBA to RGB */
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
411
               dp+=3; sp+=4;
412
               for (i = 1; i < row_width; i++)
A
Andreas Dilger 已提交
413 414 415 416 417 418 419 420 421 422
               {
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  sp++;
               }
            }
            /* This converts from XRGB or ARGB to RGB */
            else
            {
423
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
424 425 426 427 428 429 430 431
               {
                  sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 24;
432
            row_info->rowbytes = row_width * 3;
A
Andreas Dilger 已提交
433 434
         }
         else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
435
         {
A
Andreas Dilger 已提交
436 437 438
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
               /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
439
               sp += 8; dp += 6;
440
               for (i = 1; i < row_width; i++)
A
Andreas Dilger 已提交
441
               {
442
                  /* This could be (although png_memcpy is probably slower):
A
Andreas Dilger 已提交
443 444 445 446
                  png_memcpy(dp, sp, 6);
                  sp += 8;
                  dp += 6;
                  */
447

A
Andreas Dilger 已提交
448 449 450 451 452 453 454 455 456 457 458 459
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  sp += 2;
               }
            }
            else
            {
               /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
460
               for (i = 0; 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

468
                  sp+=2;
A
Andreas Dilger 已提交
469 470 471 472 473 474 475 476 477
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 48;
478
            row_info->rowbytes = row_width * 6;
G
Guy Schalnat 已提交
479
         }
A
Andreas Dilger 已提交
480
         row_info->channels = 3;
G
Guy Schalnat 已提交
481
      }
482
      else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
483
         (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
484
         (flags & PNG_FLAG_STRIP_ALPHA))) &&
485
          row_info->channels == 2)
G
Guy Schalnat 已提交
486
      {
A
Andreas Dilger 已提交
487 488 489 490 491
         if (row_info->bit_depth == 8)
         {
            /* This converts from GX or GA to G */
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
492
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
493 494 495 496 497 498 499 500
               {
                  *dp++ = *sp++;
                  sp++;
               }
            }
            /* This converts from XG or AG to G */
            else
            {
501
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
502 503 504 505 506 507
               {
                  sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 8;
508
            row_info->rowbytes = row_width;
A
Andreas Dilger 已提交
509 510
         }
         else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
511
         {
A
Andreas Dilger 已提交
512 513 514
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
               /* This converts from GGXX or GGAA to GG */
515
               sp += 4; dp += 2;
516
               for (i = 1; i < row_width; i++)
A
Andreas Dilger 已提交
517 518 519 520 521 522 523 524 525
               {
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  sp += 2;
               }
            }
            else
            {
               /* This converts from XXGG or AAGG to GG */
526
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
527 528 529 530 531 532 533
               {
                  sp += 2;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 16;
534
            row_info->rowbytes = row_width * 2;
G
Guy Schalnat 已提交
535
         }
A
Andreas Dilger 已提交
536
         row_info->channels = 1;
G
Guy Schalnat 已提交
537
      }
538
      if (flags & PNG_FLAG_STRIP_ALPHA)
539
        row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
A
Andreas Dilger 已提交
540 541 542 543 544
   }
}
#endif

#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
545
/* Swaps red and blue bytes within a pixel */
546
void /* PRIVATE */
A
Andreas Dilger 已提交
547 548
png_do_bgr(png_row_infop row_info, png_bytep row)
{
549
   png_debug(1, "in png_do_bgr");
A
Andreas Dilger 已提交
550 551 552
   if (
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
553
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
554
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
555
      {
A
Andreas Dilger 已提交
556 557 558 559
         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
         {
            png_bytep rp;
            png_uint_32 i;
G
Guy Schalnat 已提交
560

561
            for (i = 0, rp = row; i < row_width; i++, rp += 3)
A
Andreas Dilger 已提交
562
            {
563
               png_byte save = *rp;
A
Andreas Dilger 已提交
564 565 566 567 568
               *rp = *(rp + 2);
               *(rp + 2) = save;
            }
         }
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
G
Guy Schalnat 已提交
569
         {
A
Andreas Dilger 已提交
570 571 572
            png_bytep rp;
            png_uint_32 i;

573
            for (i = 0, rp = row; i < row_width; i++, rp += 4)
A
Andreas Dilger 已提交
574
            {
575
               png_byte save = *rp;
A
Andreas Dilger 已提交
576 577 578
               *rp = *(rp + 2);
               *(rp + 2) = save;
            }
G
Guy Schalnat 已提交
579 580
         }
      }
A
Andreas Dilger 已提交
581
      else if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
582
      {
A
Andreas Dilger 已提交
583 584 585 586
         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
         {
            png_bytep rp;
            png_uint_32 i;
G
Guy Schalnat 已提交
587

588
            for (i = 0, rp = row; i < row_width; i++, rp += 6)
A
Andreas Dilger 已提交
589
            {
590
               png_byte save = *rp;
A
Andreas Dilger 已提交
591
               *rp = *(rp + 4);
592 593
               *(rp + 4) = save;
               save = *(rp + 1);
A
Andreas Dilger 已提交
594
               *(rp + 1) = *(rp + 5);
595
               *(rp + 5) = save;
A
Andreas Dilger 已提交
596 597 598
            }
         }
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
G
Guy Schalnat 已提交
599
         {
A
Andreas Dilger 已提交
600 601 602
            png_bytep rp;
            png_uint_32 i;

603
            for (i = 0, rp = row; i < row_width; i++, rp += 8)
A
Andreas Dilger 已提交
604
            {
605
               png_byte save = *rp;
A
Andreas Dilger 已提交
606
               *rp = *(rp + 4);
607 608
               *(rp + 4) = save;
               save = *(rp + 1);
A
Andreas Dilger 已提交
609
               *(rp + 1) = *(rp + 5);
610
               *(rp + 5) = save;
A
Andreas Dilger 已提交
611
            }
G
Guy Schalnat 已提交
612 613 614 615
         }
      }
   }
}
A
Andreas Dilger 已提交
616
#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
G
Guy Schalnat 已提交
617

618
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
619 620
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
    defined(PNG_LEGACY_SUPPORTED)
621
void PNGAPI
622 623 624
png_set_user_transform_info(png_structp png_ptr, png_voidp
   user_transform_ptr, int user_transform_depth, int user_transform_channels)
{
625
   png_debug(1, "in png_set_user_transform_info");
626 627
   if (png_ptr == NULL)
      return;
628
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
629
   png_ptr->user_transform_ptr = user_transform_ptr;
630 631
   png_ptr->user_transform_depth = (png_byte)user_transform_depth;
   png_ptr->user_transform_channels = (png_byte)user_transform_channels;
632
#else
633
   if (user_transform_ptr || user_transform_depth || user_transform_channels)
634 635 636
      png_warning(png_ptr,
        "This version of libpng does not support user transform info");
#endif
637
}
638
#endif
639 640 641 642 643 644

/* 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.
 */
645
png_voidp PNGAPI
646 647
png_get_user_transform_ptr(png_structp png_ptr)
{
648 649
   if (png_ptr == NULL)
      return (NULL);
650
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
651
   return ((png_voidp)png_ptr->user_transform_ptr);
652
#else
653
   return (NULL);
654
#endif
655
}
656
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */