media/libpng/pngtrans.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1
michael@0 2 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
michael@0 3 *
michael@0 4 * Last changed in libpng 1.6.9 [February 6, 2014]
michael@0 5 * Copyright (c) 1998-2014 Glenn Randers-Pehrson
michael@0 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
michael@0 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
michael@0 8 *
michael@0 9 * This code is released under the libpng license.
michael@0 10 * For conditions of distribution and use, see the disclaimer
michael@0 11 * and license in png.h
michael@0 12 */
michael@0 13
michael@0 14 #include "pngpriv.h"
michael@0 15
michael@0 16 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
michael@0 17
michael@0 18 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
michael@0 19 /* Turn on BGR-to-RGB mapping */
michael@0 20 void PNGAPI
michael@0 21 png_set_bgr(png_structrp png_ptr)
michael@0 22 {
michael@0 23 png_debug(1, "in png_set_bgr");
michael@0 24
michael@0 25 if (png_ptr == NULL)
michael@0 26 return;
michael@0 27
michael@0 28 png_ptr->transformations |= PNG_BGR;
michael@0 29 }
michael@0 30 #endif
michael@0 31
michael@0 32 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
michael@0 33 /* Turn on 16 bit byte swapping */
michael@0 34 void PNGAPI
michael@0 35 png_set_swap(png_structrp png_ptr)
michael@0 36 {
michael@0 37 png_debug(1, "in png_set_swap");
michael@0 38
michael@0 39 if (png_ptr == NULL)
michael@0 40 return;
michael@0 41
michael@0 42 if (png_ptr->bit_depth == 16)
michael@0 43 png_ptr->transformations |= PNG_SWAP_BYTES;
michael@0 44 }
michael@0 45 #endif
michael@0 46
michael@0 47 #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
michael@0 48 /* Turn on pixel packing */
michael@0 49 void PNGAPI
michael@0 50 png_set_packing(png_structrp png_ptr)
michael@0 51 {
michael@0 52 png_debug(1, "in png_set_packing");
michael@0 53
michael@0 54 if (png_ptr == NULL)
michael@0 55 return;
michael@0 56
michael@0 57 if (png_ptr->bit_depth < 8)
michael@0 58 {
michael@0 59 png_ptr->transformations |= PNG_PACK;
michael@0 60 # ifdef PNG_WRITE_SUPPORTED
michael@0 61 png_ptr->usr_bit_depth = 8;
michael@0 62 # endif
michael@0 63 }
michael@0 64 }
michael@0 65 #endif
michael@0 66
michael@0 67 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
michael@0 68 /* Turn on packed pixel swapping */
michael@0 69 void PNGAPI
michael@0 70 png_set_packswap(png_structrp png_ptr)
michael@0 71 {
michael@0 72 png_debug(1, "in png_set_packswap");
michael@0 73
michael@0 74 if (png_ptr == NULL)
michael@0 75 return;
michael@0 76
michael@0 77 if (png_ptr->bit_depth < 8)
michael@0 78 png_ptr->transformations |= PNG_PACKSWAP;
michael@0 79 }
michael@0 80 #endif
michael@0 81
michael@0 82 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
michael@0 83 void PNGAPI
michael@0 84 png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)
michael@0 85 {
michael@0 86 png_debug(1, "in png_set_shift");
michael@0 87
michael@0 88 if (png_ptr == NULL)
michael@0 89 return;
michael@0 90
michael@0 91 png_ptr->transformations |= PNG_SHIFT;
michael@0 92 png_ptr->shift = *true_bits;
michael@0 93 }
michael@0 94 #endif
michael@0 95
michael@0 96 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
michael@0 97 defined(PNG_WRITE_INTERLACING_SUPPORTED)
michael@0 98 int PNGAPI
michael@0 99 png_set_interlace_handling(png_structrp png_ptr)
michael@0 100 {
michael@0 101 png_debug(1, "in png_set_interlace handling");
michael@0 102
michael@0 103 if (png_ptr && png_ptr->interlaced)
michael@0 104 {
michael@0 105 png_ptr->transformations |= PNG_INTERLACE;
michael@0 106 return (7);
michael@0 107 }
michael@0 108
michael@0 109 return (1);
michael@0 110 }
michael@0 111 #endif
michael@0 112
michael@0 113 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
michael@0 114 /* Add a filler byte on read, or remove a filler or alpha byte on write.
michael@0 115 * The filler type has changed in v0.95 to allow future 2-byte fillers
michael@0 116 * for 48-bit input data, as well as to avoid problems with some compilers
michael@0 117 * that don't like bytes as parameters.
michael@0 118 */
michael@0 119 void PNGAPI
michael@0 120 png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
michael@0 121 {
michael@0 122 png_debug(1, "in png_set_filler");
michael@0 123
michael@0 124 if (png_ptr == NULL)
michael@0 125 return;
michael@0 126
michael@0 127 /* In libpng 1.6 it is possible to determine whether this is a read or write
michael@0 128 * operation and therefore to do more checking here for a valid call.
michael@0 129 */
michael@0 130 if (png_ptr->mode & PNG_IS_READ_STRUCT)
michael@0 131 {
michael@0 132 # ifdef PNG_READ_FILLER_SUPPORTED
michael@0 133 /* On read png_set_filler is always valid, regardless of the base PNG
michael@0 134 * format, because other transformations can give a format where the
michael@0 135 * filler code can execute (basically an 8 or 16-bit component RGB or G
michael@0 136 * format.)
michael@0 137 *
michael@0 138 * NOTE: usr_channels is not used by the read code! (This has led to
michael@0 139 * confusion in the past.) The filler is only used in the read code.
michael@0 140 */
michael@0 141 png_ptr->filler = (png_uint_16)filler;
michael@0 142 # else
michael@0 143 png_app_error(png_ptr, "png_set_filler not supported on read");
michael@0 144 PNG_UNUSED(filler) /* not used in the write case */
michael@0 145 return;
michael@0 146 # endif
michael@0 147 }
michael@0 148
michael@0 149 else /* write */
michael@0 150 {
michael@0 151 # ifdef PNG_WRITE_FILLER_SUPPORTED
michael@0 152 /* On write the usr_channels parameter must be set correctly at the
michael@0 153 * start to record the number of channels in the app-supplied data.
michael@0 154 */
michael@0 155 switch (png_ptr->color_type)
michael@0 156 {
michael@0 157 case PNG_COLOR_TYPE_RGB:
michael@0 158 png_ptr->usr_channels = 4;
michael@0 159 break;
michael@0 160
michael@0 161 case PNG_COLOR_TYPE_GRAY:
michael@0 162 if (png_ptr->bit_depth >= 8)
michael@0 163 {
michael@0 164 png_ptr->usr_channels = 2;
michael@0 165 break;
michael@0 166 }
michael@0 167
michael@0 168 else
michael@0 169 {
michael@0 170 /* There simply isn't any code in libpng to strip out bits
michael@0 171 * from bytes when the components are less than a byte in
michael@0 172 * size!
michael@0 173 */
michael@0 174 png_app_error(png_ptr,
michael@0 175 "png_set_filler is invalid for low bit depth gray output");
michael@0 176 return;
michael@0 177 }
michael@0 178
michael@0 179 default:
michael@0 180 png_app_error(png_ptr,
michael@0 181 "png_set_filler: inappropriate color type");
michael@0 182 return;
michael@0 183 }
michael@0 184 # else
michael@0 185 png_app_error(png_ptr, "png_set_filler not supported on write");
michael@0 186 return;
michael@0 187 # endif
michael@0 188 }
michael@0 189
michael@0 190 /* Here on success - libpng supports the operation, set the transformation
michael@0 191 * and the flag to say where the filler channel is.
michael@0 192 */
michael@0 193 png_ptr->transformations |= PNG_FILLER;
michael@0 194
michael@0 195 if (filler_loc == PNG_FILLER_AFTER)
michael@0 196 png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
michael@0 197
michael@0 198 else
michael@0 199 png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
michael@0 200 }
michael@0 201
michael@0 202 /* Added to libpng-1.2.7 */
michael@0 203 void PNGAPI
michael@0 204 png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
michael@0 205 {
michael@0 206 png_debug(1, "in png_set_add_alpha");
michael@0 207
michael@0 208 if (png_ptr == NULL)
michael@0 209 return;
michael@0 210
michael@0 211 png_set_filler(png_ptr, filler, filler_loc);
michael@0 212 /* The above may fail to do anything. */
michael@0 213 if (png_ptr->transformations & PNG_FILLER)
michael@0 214 png_ptr->transformations |= PNG_ADD_ALPHA;
michael@0 215 }
michael@0 216
michael@0 217 #endif
michael@0 218
michael@0 219 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
michael@0 220 defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
michael@0 221 void PNGAPI
michael@0 222 png_set_swap_alpha(png_structrp png_ptr)
michael@0 223 {
michael@0 224 png_debug(1, "in png_set_swap_alpha");
michael@0 225
michael@0 226 if (png_ptr == NULL)
michael@0 227 return;
michael@0 228
michael@0 229 png_ptr->transformations |= PNG_SWAP_ALPHA;
michael@0 230 }
michael@0 231 #endif
michael@0 232
michael@0 233 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
michael@0 234 defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
michael@0 235 void PNGAPI
michael@0 236 png_set_invert_alpha(png_structrp png_ptr)
michael@0 237 {
michael@0 238 png_debug(1, "in png_set_invert_alpha");
michael@0 239
michael@0 240 if (png_ptr == NULL)
michael@0 241 return;
michael@0 242
michael@0 243 png_ptr->transformations |= PNG_INVERT_ALPHA;
michael@0 244 }
michael@0 245 #endif
michael@0 246
michael@0 247 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
michael@0 248 void PNGAPI
michael@0 249 png_set_invert_mono(png_structrp png_ptr)
michael@0 250 {
michael@0 251 png_debug(1, "in png_set_invert_mono");
michael@0 252
michael@0 253 if (png_ptr == NULL)
michael@0 254 return;
michael@0 255
michael@0 256 png_ptr->transformations |= PNG_INVERT_MONO;
michael@0 257 }
michael@0 258
michael@0 259 /* Invert monochrome grayscale data */
michael@0 260 void /* PRIVATE */
michael@0 261 png_do_invert(png_row_infop row_info, png_bytep row)
michael@0 262 {
michael@0 263 png_debug(1, "in png_do_invert");
michael@0 264
michael@0 265 /* This test removed from libpng version 1.0.13 and 1.2.0:
michael@0 266 * if (row_info->bit_depth == 1 &&
michael@0 267 */
michael@0 268 if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
michael@0 269 {
michael@0 270 png_bytep rp = row;
michael@0 271 png_size_t i;
michael@0 272 png_size_t istop = row_info->rowbytes;
michael@0 273
michael@0 274 for (i = 0; i < istop; i++)
michael@0 275 {
michael@0 276 *rp = (png_byte)(~(*rp));
michael@0 277 rp++;
michael@0 278 }
michael@0 279 }
michael@0 280
michael@0 281 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
michael@0 282 row_info->bit_depth == 8)
michael@0 283 {
michael@0 284 png_bytep rp = row;
michael@0 285 png_size_t i;
michael@0 286 png_size_t istop = row_info->rowbytes;
michael@0 287
michael@0 288 for (i = 0; i < istop; i += 2)
michael@0 289 {
michael@0 290 *rp = (png_byte)(~(*rp));
michael@0 291 rp += 2;
michael@0 292 }
michael@0 293 }
michael@0 294
michael@0 295 #ifdef PNG_16BIT_SUPPORTED
michael@0 296 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
michael@0 297 row_info->bit_depth == 16)
michael@0 298 {
michael@0 299 png_bytep rp = row;
michael@0 300 png_size_t i;
michael@0 301 png_size_t istop = row_info->rowbytes;
michael@0 302
michael@0 303 for (i = 0; i < istop; i += 4)
michael@0 304 {
michael@0 305 *rp = (png_byte)(~(*rp));
michael@0 306 *(rp + 1) = (png_byte)(~(*(rp + 1)));
michael@0 307 rp += 4;
michael@0 308 }
michael@0 309 }
michael@0 310 #endif
michael@0 311 }
michael@0 312 #endif
michael@0 313
michael@0 314 #ifdef PNG_16BIT_SUPPORTED
michael@0 315 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
michael@0 316 /* Swaps byte order on 16 bit depth images */
michael@0 317 void /* PRIVATE */
michael@0 318 png_do_swap(png_row_infop row_info, png_bytep row)
michael@0 319 {
michael@0 320 png_debug(1, "in png_do_swap");
michael@0 321
michael@0 322 if (row_info->bit_depth == 16)
michael@0 323 {
michael@0 324 png_bytep rp = row;
michael@0 325 png_uint_32 i;
michael@0 326 png_uint_32 istop= row_info->width * row_info->channels;
michael@0 327
michael@0 328 for (i = 0; i < istop; i++, rp += 2)
michael@0 329 {
michael@0 330 png_byte t = *rp;
michael@0 331 *rp = *(rp + 1);
michael@0 332 *(rp + 1) = t;
michael@0 333 }
michael@0 334 }
michael@0 335 }
michael@0 336 #endif
michael@0 337 #endif
michael@0 338
michael@0 339 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
michael@0 340 static PNG_CONST png_byte onebppswaptable[256] = {
michael@0 341 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
michael@0 342 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
michael@0 343 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
michael@0 344 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
michael@0 345 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
michael@0 346 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
michael@0 347 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
michael@0 348 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
michael@0 349 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
michael@0 350 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
michael@0 351 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
michael@0 352 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
michael@0 353 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
michael@0 354 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
michael@0 355 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
michael@0 356 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
michael@0 357 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
michael@0 358 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
michael@0 359 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
michael@0 360 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
michael@0 361 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
michael@0 362 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
michael@0 363 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
michael@0 364 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
michael@0 365 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
michael@0 366 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
michael@0 367 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
michael@0 368 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
michael@0 369 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
michael@0 370 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
michael@0 371 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
michael@0 372 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
michael@0 373 };
michael@0 374
michael@0 375 static PNG_CONST png_byte twobppswaptable[256] = {
michael@0 376 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
michael@0 377 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
michael@0 378 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
michael@0 379 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
michael@0 380 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
michael@0 381 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
michael@0 382 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
michael@0 383 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
michael@0 384 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
michael@0 385 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
michael@0 386 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
michael@0 387 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
michael@0 388 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
michael@0 389 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
michael@0 390 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
michael@0 391 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
michael@0 392 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
michael@0 393 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
michael@0 394 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
michael@0 395 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
michael@0 396 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
michael@0 397 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
michael@0 398 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
michael@0 399 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
michael@0 400 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
michael@0 401 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
michael@0 402 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
michael@0 403 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
michael@0 404 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
michael@0 405 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
michael@0 406 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
michael@0 407 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
michael@0 408 };
michael@0 409
michael@0 410 static PNG_CONST png_byte fourbppswaptable[256] = {
michael@0 411 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
michael@0 412 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
michael@0 413 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
michael@0 414 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
michael@0 415 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
michael@0 416 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
michael@0 417 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
michael@0 418 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
michael@0 419 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
michael@0 420 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
michael@0 421 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
michael@0 422 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
michael@0 423 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
michael@0 424 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
michael@0 425 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
michael@0 426 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
michael@0 427 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
michael@0 428 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
michael@0 429 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
michael@0 430 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
michael@0 431 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
michael@0 432 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
michael@0 433 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
michael@0 434 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
michael@0 435 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
michael@0 436 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
michael@0 437 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
michael@0 438 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
michael@0 439 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
michael@0 440 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
michael@0 441 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
michael@0 442 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
michael@0 443 };
michael@0 444
michael@0 445 /* Swaps pixel packing order within bytes */
michael@0 446 void /* PRIVATE */
michael@0 447 png_do_packswap(png_row_infop row_info, png_bytep row)
michael@0 448 {
michael@0 449 png_debug(1, "in png_do_packswap");
michael@0 450
michael@0 451 if (row_info->bit_depth < 8)
michael@0 452 {
michael@0 453 png_bytep rp;
michael@0 454 png_const_bytep end, table;
michael@0 455
michael@0 456 end = row + row_info->rowbytes;
michael@0 457
michael@0 458 if (row_info->bit_depth == 1)
michael@0 459 table = onebppswaptable;
michael@0 460
michael@0 461 else if (row_info->bit_depth == 2)
michael@0 462 table = twobppswaptable;
michael@0 463
michael@0 464 else if (row_info->bit_depth == 4)
michael@0 465 table = fourbppswaptable;
michael@0 466
michael@0 467 else
michael@0 468 return;
michael@0 469
michael@0 470 for (rp = row; rp < end; rp++)
michael@0 471 *rp = table[*rp];
michael@0 472 }
michael@0 473 }
michael@0 474 #endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
michael@0 475
michael@0 476 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
michael@0 477 defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
michael@0 478 /* Remove a channel - this used to be 'png_do_strip_filler' but it used a
michael@0 479 * somewhat weird combination of flags to determine what to do. All the calls
michael@0 480 * to png_do_strip_filler are changed in 1.5.2 to call this instead with the
michael@0 481 * correct arguments.
michael@0 482 *
michael@0 483 * The routine isn't general - the channel must be the channel at the start or
michael@0 484 * end (not in the middle) of each pixel.
michael@0 485 */
michael@0 486 void /* PRIVATE */
michael@0 487 png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
michael@0 488 {
michael@0 489 png_bytep sp = row; /* source pointer */
michael@0 490 png_bytep dp = row; /* destination pointer */
michael@0 491 png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
michael@0 492
michael@0 493 /* At the start sp will point to the first byte to copy and dp to where
michael@0 494 * it is copied to. ep always points just beyond the end of the row, so
michael@0 495 * the loop simply copies (channels-1) channels until sp reaches ep.
michael@0 496 *
michael@0 497 * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
michael@0 498 * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
michael@0 499 */
michael@0 500
michael@0 501 /* GA, GX, XG cases */
michael@0 502 if (row_info->channels == 2)
michael@0 503 {
michael@0 504 if (row_info->bit_depth == 8)
michael@0 505 {
michael@0 506 if (at_start) /* Skip initial filler */
michael@0 507 ++sp;
michael@0 508 else /* Skip initial channel and, for sp, the filler */
michael@0 509 sp += 2, ++dp;
michael@0 510
michael@0 511 /* For a 1 pixel wide image there is nothing to do */
michael@0 512 while (sp < ep)
michael@0 513 *dp++ = *sp, sp += 2;
michael@0 514
michael@0 515 row_info->pixel_depth = 8;
michael@0 516 }
michael@0 517
michael@0 518 else if (row_info->bit_depth == 16)
michael@0 519 {
michael@0 520 if (at_start) /* Skip initial filler */
michael@0 521 sp += 2;
michael@0 522 else /* Skip initial channel and, for sp, the filler */
michael@0 523 sp += 4, dp += 2;
michael@0 524
michael@0 525 while (sp < ep)
michael@0 526 *dp++ = *sp++, *dp++ = *sp, sp += 3;
michael@0 527
michael@0 528 row_info->pixel_depth = 16;
michael@0 529 }
michael@0 530
michael@0 531 else
michael@0 532 return; /* bad bit depth */
michael@0 533
michael@0 534 row_info->channels = 1;
michael@0 535
michael@0 536 /* Finally fix the color type if it records an alpha channel */
michael@0 537 if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
michael@0 538 row_info->color_type = PNG_COLOR_TYPE_GRAY;
michael@0 539 }
michael@0 540
michael@0 541 /* RGBA, RGBX, XRGB cases */
michael@0 542 else if (row_info->channels == 4)
michael@0 543 {
michael@0 544 if (row_info->bit_depth == 8)
michael@0 545 {
michael@0 546 if (at_start) /* Skip initial filler */
michael@0 547 ++sp;
michael@0 548 else /* Skip initial channels and, for sp, the filler */
michael@0 549 sp += 4, dp += 3;
michael@0 550
michael@0 551 /* Note that the loop adds 3 to dp and 4 to sp each time. */
michael@0 552 while (sp < ep)
michael@0 553 *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
michael@0 554
michael@0 555 row_info->pixel_depth = 24;
michael@0 556 }
michael@0 557
michael@0 558 else if (row_info->bit_depth == 16)
michael@0 559 {
michael@0 560 if (at_start) /* Skip initial filler */
michael@0 561 sp += 2;
michael@0 562 else /* Skip initial channels and, for sp, the filler */
michael@0 563 sp += 8, dp += 6;
michael@0 564
michael@0 565 while (sp < ep)
michael@0 566 {
michael@0 567 /* Copy 6 bytes, skip 2 */
michael@0 568 *dp++ = *sp++, *dp++ = *sp++;
michael@0 569 *dp++ = *sp++, *dp++ = *sp++;
michael@0 570 *dp++ = *sp++, *dp++ = *sp, sp += 3;
michael@0 571 }
michael@0 572
michael@0 573 row_info->pixel_depth = 48;
michael@0 574 }
michael@0 575
michael@0 576 else
michael@0 577 return; /* bad bit depth */
michael@0 578
michael@0 579 row_info->channels = 3;
michael@0 580
michael@0 581 /* Finally fix the color type if it records an alpha channel */
michael@0 582 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
michael@0 583 row_info->color_type = PNG_COLOR_TYPE_RGB;
michael@0 584 }
michael@0 585
michael@0 586 else
michael@0 587 return; /* The filler channel has gone already */
michael@0 588
michael@0 589 /* Fix the rowbytes value. */
michael@0 590 row_info->rowbytes = dp-row;
michael@0 591 }
michael@0 592 #endif
michael@0 593
michael@0 594 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
michael@0 595 /* Swaps red and blue bytes within a pixel */
michael@0 596 void /* PRIVATE */
michael@0 597 png_do_bgr(png_row_infop row_info, png_bytep row)
michael@0 598 {
michael@0 599 png_debug(1, "in png_do_bgr");
michael@0 600
michael@0 601 if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
michael@0 602 {
michael@0 603 png_uint_32 row_width = row_info->width;
michael@0 604 if (row_info->bit_depth == 8)
michael@0 605 {
michael@0 606 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
michael@0 607 {
michael@0 608 png_bytep rp;
michael@0 609 png_uint_32 i;
michael@0 610
michael@0 611 for (i = 0, rp = row; i < row_width; i++, rp += 3)
michael@0 612 {
michael@0 613 png_byte save = *rp;
michael@0 614 *rp = *(rp + 2);
michael@0 615 *(rp + 2) = save;
michael@0 616 }
michael@0 617 }
michael@0 618
michael@0 619 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
michael@0 620 {
michael@0 621 png_bytep rp;
michael@0 622 png_uint_32 i;
michael@0 623
michael@0 624 for (i = 0, rp = row; i < row_width; i++, rp += 4)
michael@0 625 {
michael@0 626 png_byte save = *rp;
michael@0 627 *rp = *(rp + 2);
michael@0 628 *(rp + 2) = save;
michael@0 629 }
michael@0 630 }
michael@0 631 }
michael@0 632
michael@0 633 #ifdef PNG_16BIT_SUPPORTED
michael@0 634 else if (row_info->bit_depth == 16)
michael@0 635 {
michael@0 636 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
michael@0 637 {
michael@0 638 png_bytep rp;
michael@0 639 png_uint_32 i;
michael@0 640
michael@0 641 for (i = 0, rp = row; i < row_width; i++, rp += 6)
michael@0 642 {
michael@0 643 png_byte save = *rp;
michael@0 644 *rp = *(rp + 4);
michael@0 645 *(rp + 4) = save;
michael@0 646 save = *(rp + 1);
michael@0 647 *(rp + 1) = *(rp + 5);
michael@0 648 *(rp + 5) = save;
michael@0 649 }
michael@0 650 }
michael@0 651
michael@0 652 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
michael@0 653 {
michael@0 654 png_bytep rp;
michael@0 655 png_uint_32 i;
michael@0 656
michael@0 657 for (i = 0, rp = row; i < row_width; i++, rp += 8)
michael@0 658 {
michael@0 659 png_byte save = *rp;
michael@0 660 *rp = *(rp + 4);
michael@0 661 *(rp + 4) = save;
michael@0 662 save = *(rp + 1);
michael@0 663 *(rp + 1) = *(rp + 5);
michael@0 664 *(rp + 5) = save;
michael@0 665 }
michael@0 666 }
michael@0 667 }
michael@0 668 #endif
michael@0 669 }
michael@0 670 }
michael@0 671 #endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
michael@0 672
michael@0 673 #if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
michael@0 674 defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
michael@0 675 /* Added at libpng-1.5.10 */
michael@0 676 void /* PRIVATE */
michael@0 677 png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
michael@0 678 {
michael@0 679 if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
michael@0 680 png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
michael@0 681 {
michael@0 682 /* Calculations moved outside switch in an attempt to stop different
michael@0 683 * compiler warnings. 'padding' is in *bits* within the last byte, it is
michael@0 684 * an 'int' because pixel_depth becomes an 'int' in the expression below,
michael@0 685 * and this calculation is used because it avoids warnings that other
michael@0 686 * forms produced on either GCC or MSVC.
michael@0 687 */
michael@0 688 int padding = (-row_info->pixel_depth * row_info->width) & 7;
michael@0 689 png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
michael@0 690
michael@0 691 switch (row_info->bit_depth)
michael@0 692 {
michael@0 693 case 1:
michael@0 694 {
michael@0 695 /* in this case, all bytes must be 0 so we don't need
michael@0 696 * to unpack the pixels except for the rightmost one.
michael@0 697 */
michael@0 698 for (; rp > png_ptr->row_buf; rp--)
michael@0 699 {
michael@0 700 if (*rp >> padding != 0)
michael@0 701 png_ptr->num_palette_max = 1;
michael@0 702 padding = 0;
michael@0 703 }
michael@0 704
michael@0 705 break;
michael@0 706 }
michael@0 707
michael@0 708 case 2:
michael@0 709 {
michael@0 710 for (; rp > png_ptr->row_buf; rp--)
michael@0 711 {
michael@0 712 int i = ((*rp >> padding) & 0x03);
michael@0 713
michael@0 714 if (i > png_ptr->num_palette_max)
michael@0 715 png_ptr->num_palette_max = i;
michael@0 716
michael@0 717 i = (((*rp >> padding) >> 2) & 0x03);
michael@0 718
michael@0 719 if (i > png_ptr->num_palette_max)
michael@0 720 png_ptr->num_palette_max = i;
michael@0 721
michael@0 722 i = (((*rp >> padding) >> 4) & 0x03);
michael@0 723
michael@0 724 if (i > png_ptr->num_palette_max)
michael@0 725 png_ptr->num_palette_max = i;
michael@0 726
michael@0 727 i = (((*rp >> padding) >> 6) & 0x03);
michael@0 728
michael@0 729 if (i > png_ptr->num_palette_max)
michael@0 730 png_ptr->num_palette_max = i;
michael@0 731
michael@0 732 padding = 0;
michael@0 733 }
michael@0 734
michael@0 735 break;
michael@0 736 }
michael@0 737
michael@0 738 case 4:
michael@0 739 {
michael@0 740 for (; rp > png_ptr->row_buf; rp--)
michael@0 741 {
michael@0 742 int i = ((*rp >> padding) & 0x0f);
michael@0 743
michael@0 744 if (i > png_ptr->num_palette_max)
michael@0 745 png_ptr->num_palette_max = i;
michael@0 746
michael@0 747 i = (((*rp >> padding) >> 4) & 0x0f);
michael@0 748
michael@0 749 if (i > png_ptr->num_palette_max)
michael@0 750 png_ptr->num_palette_max = i;
michael@0 751
michael@0 752 padding = 0;
michael@0 753 }
michael@0 754
michael@0 755 break;
michael@0 756 }
michael@0 757
michael@0 758 case 8:
michael@0 759 {
michael@0 760 for (; rp > png_ptr->row_buf; rp--)
michael@0 761 {
michael@0 762 if (*rp > png_ptr->num_palette_max)
michael@0 763 png_ptr->num_palette_max = (int) *rp;
michael@0 764 }
michael@0 765
michael@0 766 break;
michael@0 767 }
michael@0 768
michael@0 769 default:
michael@0 770 break;
michael@0 771 }
michael@0 772 }
michael@0 773 }
michael@0 774 #endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */
michael@0 775
michael@0 776 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
michael@0 777 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
michael@0 778 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
michael@0 779 void PNGAPI
michael@0 780 png_set_user_transform_info(png_structrp png_ptr, png_voidp
michael@0 781 user_transform_ptr, int user_transform_depth, int user_transform_channels)
michael@0 782 {
michael@0 783 png_debug(1, "in png_set_user_transform_info");
michael@0 784
michael@0 785 if (png_ptr == NULL)
michael@0 786 return;
michael@0 787
michael@0 788 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
michael@0 789 if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
michael@0 790 (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
michael@0 791 {
michael@0 792 png_app_error(png_ptr,
michael@0 793 "info change after png_start_read_image or png_read_update_info");
michael@0 794 return;
michael@0 795 }
michael@0 796 #endif
michael@0 797
michael@0 798 png_ptr->user_transform_ptr = user_transform_ptr;
michael@0 799 png_ptr->user_transform_depth = (png_byte)user_transform_depth;
michael@0 800 png_ptr->user_transform_channels = (png_byte)user_transform_channels;
michael@0 801 }
michael@0 802 #endif
michael@0 803
michael@0 804 /* This function returns a pointer to the user_transform_ptr associated with
michael@0 805 * the user transform functions. The application should free any memory
michael@0 806 * associated with this pointer before png_write_destroy and png_read_destroy
michael@0 807 * are called.
michael@0 808 */
michael@0 809 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
michael@0 810 png_voidp PNGAPI
michael@0 811 png_get_user_transform_ptr(png_const_structrp png_ptr)
michael@0 812 {
michael@0 813 if (png_ptr == NULL)
michael@0 814 return (NULL);
michael@0 815
michael@0 816 return png_ptr->user_transform_ptr;
michael@0 817 }
michael@0 818 #endif
michael@0 819
michael@0 820 #ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
michael@0 821 png_uint_32 PNGAPI
michael@0 822 png_get_current_row_number(png_const_structrp png_ptr)
michael@0 823 {
michael@0 824 /* See the comments in png.h - this is the sub-image row when reading and
michael@0 825 * interlaced image.
michael@0 826 */
michael@0 827 if (png_ptr != NULL)
michael@0 828 return png_ptr->row_number;
michael@0 829
michael@0 830 return PNG_UINT_32_MAX; /* help the app not to fail silently */
michael@0 831 }
michael@0 832
michael@0 833 png_byte PNGAPI
michael@0 834 png_get_current_pass_number(png_const_structrp png_ptr)
michael@0 835 {
michael@0 836 if (png_ptr != NULL)
michael@0 837 return png_ptr->pass;
michael@0 838 return 8; /* invalid */
michael@0 839 }
michael@0 840 #endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */
michael@0 841 #endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
michael@0 842 PNG_WRITE_USER_TRANSFORM_SUPPORTED */
michael@0 843 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */

mercurial