pngtrans.c 18.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
 * libpng 1.0.6h - April 24, 2000
5 6 7
 * For conditions of distribution and use, see copyright notice in png.h
 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
 * Copyright (c) 1996, 1997 Andreas Dilger
8
 * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
9
 */
G
Guy Schalnat 已提交
10 11 12 13

#define PNG_INTERNAL
#include "png.h"

G
Guy Schalnat 已提交
14
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
15
/* turn on BGR-to-RGB mapping */
G
Guy Schalnat 已提交
16
void
G
Guy Schalnat 已提交
17
png_set_bgr(png_structp png_ptr)
G
Guy Schalnat 已提交
18
{
A
Andreas Dilger 已提交
19
   png_debug(1, "in png_set_bgr\n");
G
Guy Schalnat 已提交
20 21
   png_ptr->transformations |= PNG_BGR;
}
G
Guy Schalnat 已提交
22
#endif
G
Guy Schalnat 已提交
23

G
Guy Schalnat 已提交
24
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
G
Guy Schalnat 已提交
25 26
/* turn on 16 bit byte swapping */
void
G
Guy Schalnat 已提交
27
png_set_swap(png_structp png_ptr)
G
Guy Schalnat 已提交
28
{
A
Andreas Dilger 已提交
29
   png_debug(1, "in png_set_swap\n");
G
Guy Schalnat 已提交
30 31 32
   if (png_ptr->bit_depth == 16)
      png_ptr->transformations |= PNG_SWAP_BYTES;
}
G
Guy Schalnat 已提交
33
#endif
G
Guy Schalnat 已提交
34

G
Guy Schalnat 已提交
35
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
G
Guy Schalnat 已提交
36 37
/* turn on pixel packing */
void
G
Guy Schalnat 已提交
38
png_set_packing(png_structp png_ptr)
G
Guy Schalnat 已提交
39
{
A
Andreas Dilger 已提交
40
   png_debug(1, "in png_set_packing\n");
G
Guy Schalnat 已提交
41 42 43 44 45 46
   if (png_ptr->bit_depth < 8)
   {
      png_ptr->transformations |= PNG_PACK;
      png_ptr->usr_bit_depth = 8;
   }
}
G
Guy Schalnat 已提交
47
#endif
G
Guy Schalnat 已提交
48

A
Andreas Dilger 已提交
49 50 51 52 53 54 55 56 57 58 59
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
/* turn on packed pixel swapping */
void
png_set_packswap(png_structp png_ptr)
{
   png_debug(1, "in png_set_packswap\n");
   if (png_ptr->bit_depth < 8)
      png_ptr->transformations |= PNG_PACKSWAP;
}
#endif

G
Guy Schalnat 已提交
60
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
G
Guy Schalnat 已提交
61
void
G
Guy Schalnat 已提交
62
png_set_shift(png_structp png_ptr, png_color_8p true_bits)
G
Guy Schalnat 已提交
63
{
A
Andreas Dilger 已提交
64
   png_debug(1, "in png_set_shift\n");
G
Guy Schalnat 已提交
65 66 67
   png_ptr->transformations |= PNG_SHIFT;
   png_ptr->shift = *true_bits;
}
G
Guy Schalnat 已提交
68
#endif
G
Guy Schalnat 已提交
69

70 71
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
    defined(PNG_WRITE_INTERLACING_SUPPORTED)
G
Guy Schalnat 已提交
72
int
G
Guy Schalnat 已提交
73
png_set_interlace_handling(png_structp png_ptr)
G
Guy Schalnat 已提交
74
{
A
Andreas Dilger 已提交
75
   png_debug(1, "in png_set_interlace handling\n");
G
Guy Schalnat 已提交
76 77 78
   if (png_ptr->interlaced)
   {
      png_ptr->transformations |= PNG_INTERLACE;
79
      return (7);
G
Guy Schalnat 已提交
80 81
   }

82
   return (1);
G
Guy Schalnat 已提交
83
}
G
Guy Schalnat 已提交
84
#endif
G
Guy Schalnat 已提交
85

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

   /* This should probably go in the "do_filler" routine.
    * 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 已提交
120
}
A
Andreas Dilger 已提交
121
#endif
G
Guy Schalnat 已提交
122

A
Andreas Dilger 已提交
123 124
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
    defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
G
Guy Schalnat 已提交
125
void
A
Andreas Dilger 已提交
126
png_set_swap_alpha(png_structp png_ptr)
G
Guy Schalnat 已提交
127
{
A
Andreas Dilger 已提交
128 129
   png_debug(1, "in png_set_swap_alpha\n");
   png_ptr->transformations |= PNG_SWAP_ALPHA;
G
Guy Schalnat 已提交
130
}
G
Guy Schalnat 已提交
131
#endif
G
Guy Schalnat 已提交
132

133 134 135 136 137 138 139 140 141 142
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
    defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
void
png_set_invert_alpha(png_structp png_ptr)
{
   png_debug(1, "in png_set_invert_alpha\n");
   png_ptr->transformations |= PNG_INVERT_ALPHA;
}
#endif

G
Guy Schalnat 已提交
143
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
G
Guy Schalnat 已提交
144
void
G
Guy Schalnat 已提交
145
png_set_invert_mono(png_structp png_ptr)
G
Guy Schalnat 已提交
146
{
A
Andreas Dilger 已提交
147
   png_debug(1, "in png_set_invert_mono\n");
G
Guy Schalnat 已提交
148 149 150
   png_ptr->transformations |= PNG_INVERT_MONO;
}

151
/* invert monochrome grayscale data */
G
Guy Schalnat 已提交
152
void
G
Guy Schalnat 已提交
153
png_do_invert(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
154
{
A
Andreas Dilger 已提交
155 156 157 158 159 160
   png_debug(1, "in png_do_invert\n");
   if (row_info->bit_depth == 1 &&
#if defined(PNG_USELESS_TESTS_SUPPORTED)
       row != NULL && row_info != NULL &&
#endif
       row_info->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
161
   {
162
      png_bytep rp = row;
G
Guy Schalnat 已提交
163
      png_uint_32 i;
164
      png_uint_32 istop = row_info->rowbytes;
G
Guy Schalnat 已提交
165

166
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
167
      {
168 169
         *rp = (png_byte)(~(*rp));
         rp++;
G
Guy Schalnat 已提交
170 171 172
      }
   }
}
G
Guy Schalnat 已提交
173
#endif
G
Guy Schalnat 已提交
174

G
Guy Schalnat 已提交
175
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
G
Guy Schalnat 已提交
176 177
/* swaps byte order on 16 bit depth images */
void
G
Guy Schalnat 已提交
178
png_do_swap(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
179
{
A
Andreas Dilger 已提交
180 181 182 183 184 185
   png_debug(1, "in png_do_swap\n");
   if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
       row != NULL && row_info != NULL &&
#endif
       row_info->bit_depth == 16)
G
Guy Schalnat 已提交
186
   {
187
      png_bytep rp = row;
G
Guy Schalnat 已提交
188
      png_uint_32 i;
189
      png_uint_32 istop= row_info->width * row_info->channels;
G
Guy Schalnat 已提交
190

191
      for (i = 0; i < istop; i++, rp += 2)
G
Guy Schalnat 已提交
192
      {
193
         png_byte t = *rp;
G
Guy Schalnat 已提交
194 195 196 197 198
         *rp = *(rp + 1);
         *(rp + 1) = t;
      }
   }
}
G
Guy Schalnat 已提交
199
#endif
G
Guy Schalnat 已提交
200

A
Andreas Dilger 已提交
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 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 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 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
static png_byte onebppswaptable[256] = {
   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
};

static png_byte twobppswaptable[256] = {
   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
};

static png_byte fourbppswaptable[256] = {
   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
};

/* swaps pixel packing order within bytes */
G
Guy Schalnat 已提交
308
void
A
Andreas Dilger 已提交
309
png_do_packswap(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
310
{
A
Andreas Dilger 已提交
311 312 313
   png_debug(1, "in png_do_packswap\n");
   if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
314
       row != NULL && row_info != NULL &&
A
Andreas Dilger 已提交
315 316
#endif
       row_info->bit_depth < 8)
G
Guy Schalnat 已提交
317
   {
A
Andreas Dilger 已提交
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
      png_bytep rp, end, table;

      end = row + row_info->rowbytes;

      if (row_info->bit_depth == 1)
         table = onebppswaptable;
      else if (row_info->bit_depth == 2)
         table = twobppswaptable;
      else if (row_info->bit_depth == 4)
         table = fourbppswaptable;
      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)
/* remove filler or alpha byte(s) */
void
png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
{
   png_debug(1, "in png_do_strip_filler\n");
#if defined(PNG_USELESS_TESTS_SUPPORTED)
   if (row != NULL && row_info != NULL)
#endif
   {
/*
      if (row_info->color_type == PNG_COLOR_TYPE_RGB ||
          row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
*/
352 353
      png_bytep sp=row;
      png_bytep dp=row;
354
      png_uint_32 row_width=row_info->width;
355 356
      png_uint_32 i;

A
Andreas Dilger 已提交
357
      if (row_info->channels == 4)
G
Guy Schalnat 已提交
358
      {
A
Andreas Dilger 已提交
359 360 361 362 363
         if (row_info->bit_depth == 8)
         {
            /* This converts from RGBX or RGBA to RGB */
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
364
               dp+=3; sp+=4;
365
               for (i = 1; i < row_width; i++)
A
Andreas Dilger 已提交
366 367 368 369 370 371 372 373 374 375
               {
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  sp++;
               }
            }
            /* This converts from XRGB or ARGB to RGB */
            else
            {
376
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
377 378 379 380 381 382 383 384
               {
                  sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 24;
385
            row_info->rowbytes = row_width * 3;
A
Andreas Dilger 已提交
386 387
         }
         else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
388
         {
A
Andreas Dilger 已提交
389 390 391
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
               /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
392
               sp += 8; dp += 6;
393
               for (i = 1; i < row_width; i++)
A
Andreas Dilger 已提交
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
               {
                  /* This could be (although memcpy is probably slower):
                  png_memcpy(dp, sp, 6);
                  sp += 8;
                  dp += 6;
                  */
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  sp += 2;
               }
            }
            else
            {
               /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
412
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
413 414 415 416 417 418
               {
                  /* This could be (although memcpy is probably slower):
                  png_memcpy(dp, sp, 6);
                  sp += 8;
                  dp += 6;
                  */
419
                  sp+=2;
A
Andreas Dilger 已提交
420 421 422 423 424 425 426 427 428
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 48;
429
            row_info->rowbytes = row_width * 6;
G
Guy Schalnat 已提交
430
         }
A
Andreas Dilger 已提交
431
         row_info->channels = 3;
432
         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
G
Guy Schalnat 已提交
433
      }
A
Andreas Dilger 已提交
434 435 436 437 438
/*
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY ||
               row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
*/
      else if (row_info->channels == 2)
G
Guy Schalnat 已提交
439
      {
A
Andreas Dilger 已提交
440 441 442 443 444
         if (row_info->bit_depth == 8)
         {
            /* This converts from GX or GA to G */
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
445
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
446 447 448 449 450 451 452 453
               {
                  *dp++ = *sp++;
                  sp++;
               }
            }
            /* This converts from XG or AG to G */
            else
            {
454
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
455 456 457 458 459 460
               {
                  sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 8;
461
            row_info->rowbytes = row_width;
A
Andreas Dilger 已提交
462 463
         }
         else /* if (row_info->bit_depth == 16) */
G
Guy Schalnat 已提交
464
         {
A
Andreas Dilger 已提交
465 466 467
            if (flags & PNG_FLAG_FILLER_AFTER)
            {
               /* This converts from GGXX or GGAA to GG */
468
               sp += 4; dp += 2;
469
               for (i = 1; i < row_width; i++)
A
Andreas Dilger 已提交
470 471 472 473 474 475 476 477 478
               {
                  *dp++ = *sp++;
                  *dp++ = *sp++;
                  sp += 2;
               }
            }
            else
            {
               /* This converts from XXGG or AAGG to GG */
479
               for (i = 0; i < row_width; i++)
A
Andreas Dilger 已提交
480 481 482 483 484 485 486
               {
                  sp += 2;
                  *dp++ = *sp++;
                  *dp++ = *sp++;
               }
            }
            row_info->pixel_depth = 16;
487
            row_info->rowbytes = row_width * 2;
G
Guy Schalnat 已提交
488
         }
A
Andreas Dilger 已提交
489
         row_info->channels = 1;
490
         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
G
Guy Schalnat 已提交
491
      }
A
Andreas Dilger 已提交
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
   }
}
#endif

#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
/* swaps red and blue bytes within a pixel */
void
png_do_bgr(png_row_infop row_info, png_bytep row)
{
   png_debug(1, "in png_do_bgr\n");
   if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
       row != NULL && row_info != NULL &&
#endif
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
   {
508
      png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
509
      if (row_info->bit_depth == 8)
G
Guy Schalnat 已提交
510
      {
A
Andreas Dilger 已提交
511 512 513 514
         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
         {
            png_bytep rp;
            png_uint_32 i;
G
Guy Schalnat 已提交
515

516
            for (i = 0, rp = row; i < row_width; i++, rp += 3)
A
Andreas Dilger 已提交
517
            {
518
               png_byte save = *rp;
A
Andreas Dilger 已提交
519 520 521 522 523
               *rp = *(rp + 2);
               *(rp + 2) = save;
            }
         }
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
G
Guy Schalnat 已提交
524
         {
A
Andreas Dilger 已提交
525 526 527
            png_bytep rp;
            png_uint_32 i;

528
            for (i = 0, rp = row; i < row_width; i++, rp += 4)
A
Andreas Dilger 已提交
529
            {
530
               png_byte save = *rp;
A
Andreas Dilger 已提交
531 532 533
               *rp = *(rp + 2);
               *(rp + 2) = save;
            }
G
Guy Schalnat 已提交
534 535
         }
      }
A
Andreas Dilger 已提交
536
      else if (row_info->bit_depth == 16)
G
Guy Schalnat 已提交
537
      {
A
Andreas Dilger 已提交
538 539 540 541
         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
         {
            png_bytep rp;
            png_uint_32 i;
G
Guy Schalnat 已提交
542

543
            for (i = 0, rp = row; i < row_width; i++, rp += 6)
A
Andreas Dilger 已提交
544
            {
545
               png_byte save = *rp;
A
Andreas Dilger 已提交
546
               *rp = *(rp + 4);
547 548
               *(rp + 4) = save;
               save = *(rp + 1);
A
Andreas Dilger 已提交
549
               *(rp + 1) = *(rp + 5);
550
               *(rp + 5) = save;
A
Andreas Dilger 已提交
551 552 553
            }
         }
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
G
Guy Schalnat 已提交
554
         {
A
Andreas Dilger 已提交
555 556 557
            png_bytep rp;
            png_uint_32 i;

558
            for (i = 0, rp = row; i < row_width; i++, rp += 8)
A
Andreas Dilger 已提交
559
            {
560
               png_byte save = *rp;
A
Andreas Dilger 已提交
561
               *rp = *(rp + 4);
562 563
               *(rp + 4) = save;
               save = *(rp + 1);
A
Andreas Dilger 已提交
564
               *(rp + 1) = *(rp + 5);
565
               *(rp + 5) = save;
A
Andreas Dilger 已提交
566
            }
G
Guy Schalnat 已提交
567 568 569 570
         }
      }
   }
}
A
Andreas Dilger 已提交
571
#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
G
Guy Schalnat 已提交
572

573 574 575 576 577 578 579 580
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
void
png_set_user_transform_info(png_structp png_ptr, png_voidp
   user_transform_ptr, int user_transform_depth, int user_transform_channels)
{
   png_debug(1, "in png_set_user_transform_info\n");
   png_ptr->user_transform_ptr = user_transform_ptr;
581 582
   png_ptr->user_transform_depth = (png_byte)user_transform_depth;
   png_ptr->user_transform_channels = (png_byte)user_transform_channels;
583 584 585 586 587 588 589 590 591 592 593 594 595
}

/* 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.
 */
png_voidp
png_get_user_transform_ptr(png_structp png_ptr)
{
   return ((png_voidp)png_ptr->user_transform_ptr);
}
#endif