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