1 2 /* pngrtran.c - transforms the data in a row for PNG readers 3 * 4 * Last changed in libpng 1.2.43 [February 25, 2010] 5 * Copyright (c) 1998-2010 Glenn Randers-Pehrson 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 8 * 9 * This code is released under the libpng license. 10 * For conditions of distribution and use, see the disclaimer 11 * and license in png.h 12 * 13 * This file contains functions optionally called by an application 14 * in order to tell libpng how to handle data when reading a PNG. 15 * Transformations that are used in both reading and writing are 16 * in pngtrans.c. 17 */ 18 19 #define PNG_INTERNAL 20 #define PNG_NO_PEDANTIC_WARNINGS 21 #include "png.h" 22 #ifdef PNG_READ_SUPPORTED 23 24 /* Set the action on getting a CRC error for an ancillary or critical chunk. */ 25 void PNGAPI 26 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) 27 { 28 png_debug(1, "in png_set_crc_action"); 29 30 if (png_ptr == NULL) 31 return; 32 33 /* Tell libpng how we react to CRC errors in critical chunks */ 34 switch (crit_action) 35 { 36 case PNG_CRC_NO_CHANGE: /* Leave setting as is */ 37 break; 38 39 case PNG_CRC_WARN_USE: /* Warn/use data */ 40 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 41 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; 42 break; 43 44 case PNG_CRC_QUIET_USE: /* Quiet/use data */ 45 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 46 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | 47 PNG_FLAG_CRC_CRITICAL_IGNORE; 48 break; 49 50 case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ 51 png_warning(png_ptr, 52 "Can't discard critical data on CRC error."); 53 case PNG_CRC_ERROR_QUIT: /* Error/quit */ 54 55 case PNG_CRC_DEFAULT: 56 default: 57 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; 58 break; 59 } 60 61 /* Tell libpng how we react to CRC errors in ancillary chunks */ 62 switch (ancil_action) 63 { 64 case PNG_CRC_NO_CHANGE: /* Leave setting as is */ 65 break; 66 67 case PNG_CRC_WARN_USE: /* Warn/use data */ 68 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 69 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; 70 break; 71 72 case PNG_CRC_QUIET_USE: /* Quiet/use data */ 73 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 74 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | 75 PNG_FLAG_CRC_ANCILLARY_NOWARN; 76 break; 77 78 case PNG_CRC_ERROR_QUIT: /* Error/quit */ 79 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 80 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; 81 break; 82 83 case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ 84 85 case PNG_CRC_DEFAULT: 86 default: 87 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; 88 break; 89 } 90 } 91 92 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 93 defined(PNG_FLOATING_POINT_SUPPORTED) 94 /* Handle alpha and tRNS via a background color */ 95 void PNGAPI 96 png_set_background(png_structp png_ptr, 97 png_color_16p background_color, int background_gamma_code, 98 int need_expand, double background_gamma) 99 { 100 png_debug(1, "in png_set_background"); 101 102 if (png_ptr == NULL) 103 return; 104 if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) 105 { 106 png_warning(png_ptr, "Application must supply a known background gamma"); 107 return; 108 } 109 110 png_ptr->transformations |= PNG_BACKGROUND; 111 png_memcpy(&(png_ptr->background), background_color, 112 png_sizeof(png_color_16)); 113 png_ptr->background_gamma = (float)background_gamma; 114 png_ptr->background_gamma_type = (png_byte)(background_gamma_code); 115 png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); 116 } 117 #endif 118 119 #ifdef PNG_READ_16_TO_8_SUPPORTED 120 /* Strip 16 bit depth files to 8 bit depth */ 121 void PNGAPI 122 png_set_strip_16(png_structp png_ptr) 123 { 124 png_debug(1, "in png_set_strip_16"); 125 126 if (png_ptr == NULL) 127 return; 128 png_ptr->transformations |= PNG_16_TO_8; 129 } 130 #endif 131 132 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 133 void PNGAPI 134 png_set_strip_alpha(png_structp png_ptr) 135 { 136 png_debug(1, "in png_set_strip_alpha"); 137 138 if (png_ptr == NULL) 139 return; 140 png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; 141 } 142 #endif 143 144 #ifdef PNG_READ_DITHER_SUPPORTED 145 /* Dither file to 8 bit. Supply a palette, the current number 146 * of elements in the palette, the maximum number of elements 147 * allowed, and a histogram if possible. If the current number 148 * of colors is greater then the maximum number, the palette will be 149 * modified to fit in the maximum number. "full_dither" indicates 150 * whether we need a dithering cube set up for RGB images, or if we 151 * simply are reducing the number of colors in a paletted image. 152 */ 153 154 typedef struct png_dsort_struct 155 { 156 struct png_dsort_struct FAR * next; 157 png_byte left; 158 png_byte right; 159 } png_dsort; 160 typedef png_dsort FAR * png_dsortp; 161 typedef png_dsort FAR * FAR * png_dsortpp; 162 163 void PNGAPI 164 png_set_dither(png_structp png_ptr, png_colorp palette, 165 int num_palette, int maximum_colors, png_uint_16p histogram, 166 int full_dither) 167 { 168 png_debug(1, "in png_set_dither"); 169 170 if (png_ptr == NULL) 171 return; 172 png_ptr->transformations |= PNG_DITHER; 173 174 if (!full_dither) 175 { 176 int i; 177 178 png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, 179 (png_uint_32)(num_palette * png_sizeof(png_byte))); 180 for (i = 0; i < num_palette; i++) 181 png_ptr->dither_index[i] = (png_byte)i; 182 } 183 184 if (num_palette > maximum_colors) 185 { 186 if (histogram != NULL) 187 { 188 /* This is easy enough, just throw out the least used colors. 189 * Perhaps not the best solution, but good enough. 190 */ 191 192 int i; 193 194 /* Initialize an array to sort colors */ 195 png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr, 196 (png_uint_32)(num_palette * png_sizeof(png_byte))); 197 198 /* Initialize the dither_sort array */ 199 for (i = 0; i < num_palette; i++) 200 png_ptr->dither_sort[i] = (png_byte)i; 201 202 /* Find the least used palette entries by starting a 203 * bubble sort, and running it until we have sorted 204 * out enough colors. Note that we don't care about 205 * sorting all the colors, just finding which are 206 * least used. 207 */ 208 209 for (i = num_palette - 1; i >= maximum_colors; i--) 210 { 211 int done; /* To stop early if the list is pre-sorted */ 212 int j; 213 214 done = 1; 215 for (j = 0; j < i; j++) 216 { 217 if (histogram[png_ptr->dither_sort[j]] 218 < histogram[png_ptr->dither_sort[j + 1]]) 219 { 220 png_byte t; 221 222 t = png_ptr->dither_sort[j]; 223 png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1]; 224 png_ptr->dither_sort[j + 1] = t; 225 done = 0; 226 } 227 } 228 if (done) 229 break; 230 } 231 232 /* Swap the palette around, and set up a table, if necessary */ 233 if (full_dither) 234 { 235 int j = num_palette; 236 237 /* Put all the useful colors within the max, but don't 238 * move the others. 239 */ 240 for (i = 0; i < maximum_colors; i++) 241 { 242 if ((int)png_ptr->dither_sort[i] >= maximum_colors) 243 { 244 do 245 j--; 246 while ((int)png_ptr->dither_sort[j] >= maximum_colors); 247 palette[i] = palette[j]; 248 } 249 } 250 } 251 else 252 { 253 int j = num_palette; 254 255 /* Move all the used colors inside the max limit, and 256 * develop a translation table. 257 */ 258 for (i = 0; i < maximum_colors; i++) 259 { 260 /* Only move the colors we need to */ 261 if ((int)png_ptr->dither_sort[i] >= maximum_colors) 262 { 263 png_color tmp_color; 264 265 do 266 j--; 267 while ((int)png_ptr->dither_sort[j] >= maximum_colors); 268 269 tmp_color = palette[j]; 270 palette[j] = palette[i]; 271 palette[i] = tmp_color; 272 /* Indicate where the color went */ 273 png_ptr->dither_index[j] = (png_byte)i; 274 png_ptr->dither_index[i] = (png_byte)j; 275 } 276 } 277 278 /* Find closest color for those colors we are not using */ 279 for (i = 0; i < num_palette; i++) 280 { 281 if ((int)png_ptr->dither_index[i] >= maximum_colors) 282 { 283 int min_d, k, min_k, d_index; 284 285 /* Find the closest color to one we threw out */ 286 d_index = png_ptr->dither_index[i]; 287 min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); 288 for (k = 1, min_k = 0; k < maximum_colors; k++) 289 { 290 int d; 291 292 d = PNG_COLOR_DIST(palette[d_index], palette[k]); 293 294 if (d < min_d) 295 { 296 min_d = d; 297 min_k = k; 298 } 299 } 300 /* Point to closest color */ 301 png_ptr->dither_index[i] = (png_byte)min_k; 302 } 303 } 304 } 305 png_free(png_ptr, png_ptr->dither_sort); 306 png_ptr->dither_sort = NULL; 307 } 308 else 309 { 310 /* This is much harder to do simply (and quickly). Perhaps 311 * we need to go through a median cut routine, but those 312 * don't always behave themselves with only a few colors 313 * as input. So we will just find the closest two colors, 314 * and throw out one of them (chosen somewhat randomly). 315 * [We don't understand this at all, so if someone wants to 316 * work on improving it, be our guest - AED, GRP] 317 */ 318 int i; 319 int max_d; 320 int num_new_palette; 321 png_dsortp t; 322 png_dsortpp hash; 323 324 t = NULL; 325 326 /* Initialize palette index arrays */ 327 png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, 328 (png_uint_32)(num_palette * png_sizeof(png_byte))); 329 png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, 330 (png_uint_32)(num_palette * png_sizeof(png_byte))); 331 332 /* Initialize the sort array */ 333 for (i = 0; i < num_palette; i++) 334 { 335 png_ptr->index_to_palette[i] = (png_byte)i; 336 png_ptr->palette_to_index[i] = (png_byte)i; 337 } 338 339 hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * 340 png_sizeof(png_dsortp))); 341 342 num_new_palette = num_palette; 343 344 /* Initial wild guess at how far apart the farthest pixel 345 * pair we will be eliminating will be. Larger 346 * numbers mean more areas will be allocated, Smaller 347 * numbers run the risk of not saving enough data, and 348 * having to do this all over again. 349 * 350 * I have not done extensive checking on this number. 351 */ 352 max_d = 96; 353 354 while (num_new_palette > maximum_colors) 355 { 356 for (i = 0; i < num_new_palette - 1; i++) 357 { 358 int j; 359 360 for (j = i + 1; j < num_new_palette; j++) 361 { 362 int d; 363 364 d = PNG_COLOR_DIST(palette[i], palette[j]); 365 366 if (d <= max_d) 367 { 368 369 t = (png_dsortp)png_malloc_warn(png_ptr, 370 (png_uint_32)(png_sizeof(png_dsort))); 371 if (t == NULL) 372 break; 373 t->next = hash[d]; 374 t->left = (png_byte)i; 375 t->right = (png_byte)j; 376 hash[d] = t; 377 } 378 } 379 if (t == NULL) 380 break; 381 } 382 383 if (t != NULL) 384 for (i = 0; i <= max_d; i++) 385 { 386 if (hash[i] != NULL) 387 { 388 png_dsortp p; 389 390 for (p = hash[i]; p; p = p->next) 391 { 392 if ((int)png_ptr->index_to_palette[p->left] 393 < num_new_palette && 394 (int)png_ptr->index_to_palette[p->right] 395 < num_new_palette) 396 { 397 int j, next_j; 398 399 if (num_new_palette & 0x01) 400 { 401 j = p->left; 402 next_j = p->right; 403 } 404 else 405 { 406 j = p->right; 407 next_j = p->left; 408 } 409 410 num_new_palette--; 411 palette[png_ptr->index_to_palette[j]] 412 = palette[num_new_palette]; 413 if (!full_dither) 414 { 415 int k; 416 417 for (k = 0; k < num_palette; k++) 418 { 419 if (png_ptr->dither_index[k] == 420 png_ptr->index_to_palette[j]) 421 png_ptr->dither_index[k] = 422 png_ptr->index_to_palette[next_j]; 423 if ((int)png_ptr->dither_index[k] == 424 num_new_palette) 425 png_ptr->dither_index[k] = 426 png_ptr->index_to_palette[j]; 427 } 428 } 429 430 png_ptr->index_to_palette[png_ptr->palette_to_index 431 [num_new_palette]] = png_ptr->index_to_palette[j]; 432 png_ptr->palette_to_index[png_ptr->index_to_palette[j]] 433 = png_ptr->palette_to_index[num_new_palette]; 434 435 png_ptr->index_to_palette[j] = 436 (png_byte)num_new_palette; 437 png_ptr->palette_to_index[num_new_palette] = 438 (png_byte)j; 439 } 440 if (num_new_palette <= maximum_colors) 441 break; 442 } 443 if (num_new_palette <= maximum_colors) 444 break; 445 } 446 } 447 448 for (i = 0; i < 769; i++) 449 { 450 if (hash[i] != NULL) 451 { 452 png_dsortp p = hash[i]; 453 while (p) 454 { 455 t = p->next; 456 png_free(png_ptr, p); 457 p = t; 458 } 459 } 460 hash[i] = 0; 461 } 462 max_d += 96; 463 } 464 png_free(png_ptr, hash); 465 png_free(png_ptr, png_ptr->palette_to_index); 466 png_free(png_ptr, png_ptr->index_to_palette); 467 png_ptr->palette_to_index = NULL; 468 png_ptr->index_to_palette = NULL; 469 } 470 num_palette = maximum_colors; 471 } 472 if (png_ptr->palette == NULL) 473 { 474 png_ptr->palette = palette; 475 } 476 png_ptr->num_palette = (png_uint_16)num_palette; 477 478 if (full_dither) 479 { 480 int i; 481 png_bytep distance; 482 int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + 483 PNG_DITHER_BLUE_BITS; 484 int num_red = (1 << PNG_DITHER_RED_BITS); 485 int num_green = (1 << PNG_DITHER_GREEN_BITS); 486 int num_blue = (1 << PNG_DITHER_BLUE_BITS); 487 png_size_t num_entries = ((png_size_t)1 << total_bits); 488 489 png_ptr->palette_lookup = (png_bytep )png_calloc(png_ptr, 490 (png_uint_32)(num_entries * png_sizeof(png_byte))); 491 492 distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * 493 png_sizeof(png_byte))); 494 png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); 495 496 for (i = 0; i < num_palette; i++) 497 { 498 int ir, ig, ib; 499 int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); 500 int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); 501 int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); 502 503 for (ir = 0; ir < num_red; ir++) 504 { 505 /* int dr = abs(ir - r); */ 506 int dr = ((ir > r) ? ir - r : r - ir); 507 int index_r = (ir << (PNG_DITHER_BLUE_BITS + 508 PNG_DITHER_GREEN_BITS)); 509 510 for (ig = 0; ig < num_green; ig++) 511 { 512 /* int dg = abs(ig - g); */ 513 int dg = ((ig > g) ? ig - g : g - ig); 514 int dt = dr + dg; 515 int dm = ((dr > dg) ? dr : dg); 516 int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); 517 518 for (ib = 0; ib < num_blue; ib++) 519 { 520 int d_index = index_g | ib; 521 /* int db = abs(ib - b); */ 522 int db = ((ib > b) ? ib - b : b - ib); 523 int dmax = ((dm > db) ? dm : db); 524 int d = dmax + dt + db; 525 526 if (d < (int)distance[d_index]) 527 { 528 distance[d_index] = (png_byte)d; 529 png_ptr->palette_lookup[d_index] = (png_byte)i; 530 } 531 } 532 } 533 } 534 } 535 536 png_free(png_ptr, distance); 537 } 538 } 539 #endif 540 541 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) 542 /* Transform the image from the file_gamma to the screen_gamma. We 543 * only do transformations on images where the file_gamma and screen_gamma 544 * are not close reciprocals, otherwise it slows things down slightly, and 545 * also needlessly introduces small errors. 546 * 547 * We will turn off gamma transformation later if no semitransparent entries 548 * are present in the tRNS array for palette images. We can't do it here 549 * because we don't necessarily have the tRNS chunk yet. 550 */ 551 void PNGAPI 552 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) 553 { 554 png_debug(1, "in png_set_gamma"); 555 556 if (png_ptr == NULL) 557 return; 558 559 if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) || 560 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || 561 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) 562 png_ptr->transformations |= PNG_GAMMA; 563 png_ptr->gamma = (float)file_gamma; 564 png_ptr->screen_gamma = (float)scrn_gamma; 565 } 566 #endif 567 568 #ifdef PNG_READ_EXPAND_SUPPORTED 569 /* Expand paletted images to RGB, expand grayscale images of 570 * less than 8-bit depth to 8-bit depth, and expand tRNS chunks 571 * to alpha channels. 572 */ 573 void PNGAPI 574 png_set_expand(png_structp png_ptr) 575 { 576 png_debug(1, "in png_set_expand"); 577 578 if (png_ptr == NULL) 579 return; 580 581 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 582 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 583 } 584 585 /* GRR 19990627: the following three functions currently are identical 586 * to png_set_expand(). However, it is entirely reasonable that someone 587 * might wish to expand an indexed image to RGB but *not* expand a single, 588 * fully transparent palette entry to a full alpha channel--perhaps instead 589 * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace 590 * the transparent color with a particular RGB value, or drop tRNS entirely. 591 * IOW, a future version of the library may make the transformations flag 592 * a bit more fine-grained, with separate bits for each of these three 593 * functions. 594 * 595 * More to the point, these functions make it obvious what libpng will be 596 * doing, whereas "expand" can (and does) mean any number of things. 597 * 598 * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified 599 * to expand only the sample depth but not to expand the tRNS to alpha 600 * and its name was changed to png_set_expand_gray_1_2_4_to_8(). 601 */ 602 603 /* Expand paletted images to RGB. */ 604 void PNGAPI 605 png_set_palette_to_rgb(png_structp png_ptr) 606 { 607 png_debug(1, "in png_set_palette_to_rgb"); 608 609 if (png_ptr == NULL) 610 return; 611 612 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 613 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 614 } 615 616 #ifndef PNG_1_0_X 617 /* Expand grayscale images of less than 8-bit depth to 8 bits. */ 618 void PNGAPI 619 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) 620 { 621 png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); 622 623 if (png_ptr == NULL) 624 return; 625 626 png_ptr->transformations |= PNG_EXPAND; 627 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 628 } 629 #endif 630 631 #if defined(PNG_1_0_X) || defined(PNG_1_2_X) 632 /* Expand grayscale images of less than 8-bit depth to 8 bits. */ 633 /* Deprecated as of libpng-1.2.9 */ 634 void PNGAPI 635 png_set_gray_1_2_4_to_8(png_structp png_ptr) 636 { 637 png_debug(1, "in png_set_gray_1_2_4_to_8"); 638 639 if (png_ptr == NULL) 640 return; 641 642 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 643 } 644 #endif 645 646 647 /* Expand tRNS chunks to alpha channels. */ 648 void PNGAPI 649 png_set_tRNS_to_alpha(png_structp png_ptr) 650 { 651 png_debug(1, "in png_set_tRNS_to_alpha"); 652 653 png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); 654 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 655 } 656 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ 657 658 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 659 void PNGAPI 660 png_set_gray_to_rgb(png_structp png_ptr) 661 { 662 png_debug(1, "in png_set_gray_to_rgb"); 663 664 png_ptr->transformations |= PNG_GRAY_TO_RGB; 665 png_ptr->flags &= ~PNG_FLAG_ROW_INIT; 666 } 667 #endif 668 669 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 670 #ifdef PNG_FLOATING_POINT_SUPPORTED 671 /* Convert a RGB image to a grayscale of the same width. This allows us, 672 * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. 673 */ 674 675 void PNGAPI 676 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, 677 double green) 678 { 679 int red_fixed = (int)((float)red*100000.0 + 0.5); 680 int green_fixed = (int)((float)green*100000.0 + 0.5); 681 if (png_ptr == NULL) 682 return; 683 png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); 684 } 685 #endif 686 687 void PNGAPI 688 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, 689 png_fixed_point red, png_fixed_point green) 690 { 691 png_debug(1, "in png_set_rgb_to_gray"); 692 693 if (png_ptr == NULL) 694 return; 695 696 switch(error_action) 697 { 698 case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; 699 break; 700 701 case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; 702 break; 703 704 case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; 705 } 706 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 707 #ifdef PNG_READ_EXPAND_SUPPORTED 708 png_ptr->transformations |= PNG_EXPAND; 709 #else 710 { 711 png_warning(png_ptr, 712 "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); 713 png_ptr->transformations &= ~PNG_RGB_TO_GRAY; 714 } 715 #endif 716 { 717 png_uint_16 red_int, green_int; 718 if (red < 0 || green < 0) 719 { 720 red_int = 6968; /* .212671 * 32768 + .5 */ 721 green_int = 23434; /* .715160 * 32768 + .5 */ 722 } 723 else if (red + green < 100000L) 724 { 725 red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); 726 green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); 727 } 728 else 729 { 730 png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); 731 red_int = 6968; 732 green_int = 23434; 733 } 734 png_ptr->rgb_to_gray_red_coeff = red_int; 735 png_ptr->rgb_to_gray_green_coeff = green_int; 736 png_ptr->rgb_to_gray_blue_coeff = 737 (png_uint_16)(32768 - red_int - green_int); 738 } 739 } 740 #endif 741 742 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ 743 defined(PNG_LEGACY_SUPPORTED) || \ 744 defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) 745 void PNGAPI 746 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr 747 read_user_transform_fn) 748 { 749 png_debug(1, "in png_set_read_user_transform_fn"); 750 751 if (png_ptr == NULL) 752 return; 753 754 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 755 png_ptr->transformations |= PNG_USER_TRANSFORM; 756 png_ptr->read_user_transform_fn = read_user_transform_fn; 757 #endif 758 #ifdef PNG_LEGACY_SUPPORTED 759 if (read_user_transform_fn) 760 png_warning(png_ptr, 761 "This version of libpng does not support user transforms"); 762 #endif 763 } 764 #endif 765 766 /* Initialize everything needed for the read. This includes modifying 767 * the palette. 768 */ 769 void /* PRIVATE */ 770 png_init_read_transformations(png_structp png_ptr) 771 { 772 png_debug(1, "in png_init_read_transformations"); 773 774 #ifdef PNG_USELESS_TESTS_SUPPORTED 775 if (png_ptr != NULL) 776 #endif 777 { 778 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ 779 defined(PNG_READ_SHIFT_SUPPORTED) || \ 780 defined(PNG_READ_GAMMA_SUPPORTED) 781 int color_type = png_ptr->color_type; 782 #endif 783 784 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) 785 786 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 787 /* Detect gray background and attempt to enable optimization 788 * for gray --> RGB case 789 * 790 * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or 791 * RGB_ALPHA (in which case need_expand is superfluous anyway), the 792 * background color might actually be gray yet not be flagged as such. 793 * This is not a problem for the current code, which uses 794 * PNG_BACKGROUND_IS_GRAY only to decide when to do the 795 * png_do_gray_to_rgb() transformation. 796 */ 797 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 798 !(color_type & PNG_COLOR_MASK_COLOR)) 799 { 800 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; 801 } else if ((png_ptr->transformations & PNG_BACKGROUND) && 802 !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 803 (png_ptr->transformations & PNG_GRAY_TO_RGB) && 804 png_ptr->background.red == png_ptr->background.green && 805 png_ptr->background.red == png_ptr->background.blue) 806 { 807 png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; 808 png_ptr->background.gray = png_ptr->background.red; 809 } 810 #endif 811 812 if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && 813 (png_ptr->transformations & PNG_EXPAND)) 814 { 815 if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ 816 { 817 /* Expand background and tRNS chunks */ 818 switch (png_ptr->bit_depth) 819 { 820 case 1: 821 png_ptr->background.gray *= (png_uint_16)0xff; 822 png_ptr->background.red = png_ptr->background.green 823 = png_ptr->background.blue = png_ptr->background.gray; 824 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 825 { 826 png_ptr->trans_values.gray *= (png_uint_16)0xff; 827 png_ptr->trans_values.red = png_ptr->trans_values.green 828 = png_ptr->trans_values.blue = png_ptr->trans_values.gray; 829 } 830 break; 831 832 case 2: 833 png_ptr->background.gray *= (png_uint_16)0x55; 834 png_ptr->background.red = png_ptr->background.green 835 = png_ptr->background.blue = png_ptr->background.gray; 836 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 837 { 838 png_ptr->trans_values.gray *= (png_uint_16)0x55; 839 png_ptr->trans_values.red = png_ptr->trans_values.green 840 = png_ptr->trans_values.blue = png_ptr->trans_values.gray; 841 } 842 break; 843 844 case 4: 845 png_ptr->background.gray *= (png_uint_16)0x11; 846 png_ptr->background.red = png_ptr->background.green 847 = png_ptr->background.blue = png_ptr->background.gray; 848 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 849 { 850 png_ptr->trans_values.gray *= (png_uint_16)0x11; 851 png_ptr->trans_values.red = png_ptr->trans_values.green 852 = png_ptr->trans_values.blue = png_ptr->trans_values.gray; 853 } 854 break; 855 856 case 8: 857 858 case 16: 859 png_ptr->background.red = png_ptr->background.green 860 = png_ptr->background.blue = png_ptr->background.gray; 861 break; 862 } 863 } 864 else if (color_type == PNG_COLOR_TYPE_PALETTE) 865 { 866 png_ptr->background.red = 867 png_ptr->palette[png_ptr->background.index].red; 868 png_ptr->background.green = 869 png_ptr->palette[png_ptr->background.index].green; 870 png_ptr->background.blue = 871 png_ptr->palette[png_ptr->background.index].blue; 872 873 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 874 if (png_ptr->transformations & PNG_INVERT_ALPHA) 875 { 876 #ifdef PNG_READ_EXPAND_SUPPORTED 877 if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) 878 #endif 879 { 880 /* Invert the alpha channel (in tRNS) unless the pixels are 881 * going to be expanded, in which case leave it for later 882 */ 883 int i, istop; 884 istop=(int)png_ptr->num_trans; 885 for (i=0; i<istop; i++) 886 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]); 887 } 888 } 889 #endif 890 891 } 892 } 893 #endif 894 895 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) 896 png_ptr->background_1 = png_ptr->background; 897 #endif 898 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) 899 900 if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) 901 && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) 902 < PNG_GAMMA_THRESHOLD)) 903 { 904 int i, k; 905 k=0; 906 for (i=0; i<png_ptr->num_trans; i++) 907 { 908 if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff) 909 k=1; /* Partial transparency is present */ 910 } 911 if (k == 0) 912 png_ptr->transformations &= ~PNG_GAMMA; 913 } 914 915 if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && 916 png_ptr->gamma != 0.0) 917 { 918 png_build_gamma_table(png_ptr); 919 920 #ifdef PNG_READ_BACKGROUND_SUPPORTED 921 if (png_ptr->transformations & PNG_BACKGROUND) 922 { 923 if (color_type == PNG_COLOR_TYPE_PALETTE) 924 { 925 /* Could skip if no transparency */ 926 png_color back, back_1; 927 png_colorp palette = png_ptr->palette; 928 int num_palette = png_ptr->num_palette; 929 int i; 930 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) 931 { 932 back.red = png_ptr->gamma_table[png_ptr->background.red]; 933 back.green = png_ptr->gamma_table[png_ptr->background.green]; 934 back.blue = png_ptr->gamma_table[png_ptr->background.blue]; 935 936 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; 937 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; 938 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; 939 } 940 else 941 { 942 double g, gs; 943 944 switch (png_ptr->background_gamma_type) 945 { 946 case PNG_BACKGROUND_GAMMA_SCREEN: 947 g = (png_ptr->screen_gamma); 948 gs = 1.0; 949 break; 950 951 case PNG_BACKGROUND_GAMMA_FILE: 952 g = 1.0 / (png_ptr->gamma); 953 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); 954 break; 955 956 case PNG_BACKGROUND_GAMMA_UNIQUE: 957 g = 1.0 / (png_ptr->background_gamma); 958 gs = 1.0 / (png_ptr->background_gamma * 959 png_ptr->screen_gamma); 960 break; 961 default: 962 g = 1.0; /* back_1 */ 963 gs = 1.0; /* back */ 964 } 965 966 if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) 967 { 968 back.red = (png_byte)png_ptr->background.red; 969 back.green = (png_byte)png_ptr->background.green; 970 back.blue = (png_byte)png_ptr->background.blue; 971 } 972 else 973 { 974 back.red = (png_byte)(pow( 975 (double)png_ptr->background.red/255, gs) * 255.0 + .5); 976 back.green = (png_byte)(pow( 977 (double)png_ptr->background.green/255, gs) * 255.0 978 + .5); 979 back.blue = (png_byte)(pow( 980 (double)png_ptr->background.blue/255, gs) * 255.0 + .5); 981 } 982 983 back_1.red = (png_byte)(pow( 984 (double)png_ptr->background.red/255, g) * 255.0 + .5); 985 back_1.green = (png_byte)(pow( 986 (double)png_ptr->background.green/255, g) * 255.0 + .5); 987 back_1.blue = (png_byte)(pow( 988 (double)png_ptr->background.blue/255, g) * 255.0 + .5); 989 } 990 for (i = 0; i < num_palette; i++) 991 { 992 if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) 993 { 994 if (png_ptr->trans[i] == 0) 995 { 996 palette[i] = back; 997 } 998 else /* if (png_ptr->trans[i] != 0xff) */ 999 { 1000 png_byte v, w; 1001 1002 v = png_ptr->gamma_to_1[palette[i].red]; 1003 png_composite(w, v, png_ptr->trans[i], back_1.red); 1004 palette[i].red = png_ptr->gamma_from_1[w]; 1005 1006 v = png_ptr->gamma_to_1[palette[i].green]; 1007 png_composite(w, v, png_ptr->trans[i], back_1.green); 1008 palette[i].green = png_ptr->gamma_from_1[w]; 1009 1010 v = png_ptr->gamma_to_1[palette[i].blue]; 1011 png_composite(w, v, png_ptr->trans[i], back_1.blue); 1012 palette[i].blue = png_ptr->gamma_from_1[w]; 1013 } 1014 } 1015 else 1016 { 1017 palette[i].red = png_ptr->gamma_table[palette[i].red]; 1018 palette[i].green = png_ptr->gamma_table[palette[i].green]; 1019 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 1020 } 1021 } 1022 /* Prevent the transformations being done again, and make sure 1023 * that the now spurious alpha channel is stripped - the code 1024 * has just reduced background composition and gamma correction 1025 * to a simple alpha channel strip. 1026 */ 1027 png_ptr->transformations &= ~PNG_BACKGROUND; 1028 png_ptr->transformations &= ~PNG_GAMMA; 1029 png_ptr->transformations |= PNG_STRIP_ALPHA; 1030 } 1031 /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ 1032 else 1033 /* color_type != PNG_COLOR_TYPE_PALETTE */ 1034 { 1035 double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); 1036 double g = 1.0; 1037 double gs = 1.0; 1038 1039 switch (png_ptr->background_gamma_type) 1040 { 1041 case PNG_BACKGROUND_GAMMA_SCREEN: 1042 g = (png_ptr->screen_gamma); 1043 gs = 1.0; 1044 break; 1045 1046 case PNG_BACKGROUND_GAMMA_FILE: 1047 g = 1.0 / (png_ptr->gamma); 1048 gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); 1049 break; 1050 1051 case PNG_BACKGROUND_GAMMA_UNIQUE: 1052 g = 1.0 / (png_ptr->background_gamma); 1053 gs = 1.0 / (png_ptr->background_gamma * 1054 png_ptr->screen_gamma); 1055 break; 1056 } 1057 1058 png_ptr->background_1.gray = (png_uint_16)(pow( 1059 (double)png_ptr->background.gray / m, g) * m + .5); 1060 png_ptr->background.gray = (png_uint_16)(pow( 1061 (double)png_ptr->background.gray / m, gs) * m + .5); 1062 1063 if ((png_ptr->background.red != png_ptr->background.green) || 1064 (png_ptr->background.red != png_ptr->background.blue) || 1065 (png_ptr->background.red != png_ptr->background.gray)) 1066 { 1067 /* RGB or RGBA with color background */ 1068 png_ptr->background_1.red = (png_uint_16)(pow( 1069 (double)png_ptr->background.red / m, g) * m + .5); 1070 png_ptr->background_1.green = (png_uint_16)(pow( 1071 (double)png_ptr->background.green / m, g) * m + .5); 1072 png_ptr->background_1.blue = (png_uint_16)(pow( 1073 (double)png_ptr->background.blue / m, g) * m + .5); 1074 png_ptr->background.red = (png_uint_16)(pow( 1075 (double)png_ptr->background.red / m, gs) * m + .5); 1076 png_ptr->background.green = (png_uint_16)(pow( 1077 (double)png_ptr->background.green / m, gs) * m + .5); 1078 png_ptr->background.blue = (png_uint_16)(pow( 1079 (double)png_ptr->background.blue / m, gs) * m + .5); 1080 } 1081 else 1082 { 1083 /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ 1084 png_ptr->background_1.red = png_ptr->background_1.green 1085 = png_ptr->background_1.blue = png_ptr->background_1.gray; 1086 png_ptr->background.red = png_ptr->background.green 1087 = png_ptr->background.blue = png_ptr->background.gray; 1088 } 1089 } 1090 } 1091 else 1092 /* Transformation does not include PNG_BACKGROUND */ 1093 #endif /* PNG_READ_BACKGROUND_SUPPORTED */ 1094 if (color_type == PNG_COLOR_TYPE_PALETTE) 1095 { 1096 png_colorp palette = png_ptr->palette; 1097 int num_palette = png_ptr->num_palette; 1098 int i; 1099 1100 for (i = 0; i < num_palette; i++) 1101 { 1102 palette[i].red = png_ptr->gamma_table[palette[i].red]; 1103 palette[i].green = png_ptr->gamma_table[palette[i].green]; 1104 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 1105 } 1106 1107 /* Done the gamma correction. */ 1108 png_ptr->transformations &= ~PNG_GAMMA; 1109 } 1110 } 1111 #ifdef PNG_READ_BACKGROUND_SUPPORTED 1112 else 1113 #endif 1114 #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */ 1115 #ifdef PNG_READ_BACKGROUND_SUPPORTED 1116 /* No GAMMA transformation */ 1117 if ((png_ptr->transformations & PNG_BACKGROUND) && 1118 (color_type == PNG_COLOR_TYPE_PALETTE)) 1119 { 1120 int i; 1121 int istop = (int)png_ptr->num_trans; 1122 png_color back; 1123 png_colorp palette = png_ptr->palette; 1124 1125 back.red = (png_byte)png_ptr->background.red; 1126 back.green = (png_byte)png_ptr->background.green; 1127 back.blue = (png_byte)png_ptr->background.blue; 1128 1129 for (i = 0; i < istop; i++) 1130 { 1131 if (png_ptr->trans[i] == 0) 1132 { 1133 palette[i] = back; 1134 } 1135 else if (png_ptr->trans[i] != 0xff) 1136 { 1137 /* The png_composite() macro is defined in png.h */ 1138 png_composite(palette[i].red, palette[i].red, 1139 png_ptr->trans[i], back.red); 1140 png_composite(palette[i].green, palette[i].green, 1141 png_ptr->trans[i], back.green); 1142 png_composite(palette[i].blue, palette[i].blue, 1143 png_ptr->trans[i], back.blue); 1144 } 1145 } 1146 1147 /* Handled alpha, still need to strip the channel. */ 1148 png_ptr->transformations &= ~PNG_BACKGROUND; 1149 png_ptr->transformations |= PNG_STRIP_ALPHA; 1150 } 1151 #endif /* PNG_READ_BACKGROUND_SUPPORTED */ 1152 1153 #ifdef PNG_READ_SHIFT_SUPPORTED 1154 if ((png_ptr->transformations & PNG_SHIFT) && 1155 (color_type == PNG_COLOR_TYPE_PALETTE)) 1156 { 1157 png_uint_16 i; 1158 png_uint_16 istop = png_ptr->num_palette; 1159 int sr = 8 - png_ptr->sig_bit.red; 1160 int sg = 8 - png_ptr->sig_bit.green; 1161 int sb = 8 - png_ptr->sig_bit.blue; 1162 1163 if (sr < 0 || sr > 8) 1164 sr = 0; 1165 if (sg < 0 || sg > 8) 1166 sg = 0; 1167 if (sb < 0 || sb > 8) 1168 sb = 0; 1169 for (i = 0; i < istop; i++) 1170 { 1171 png_ptr->palette[i].red >>= sr; 1172 png_ptr->palette[i].green >>= sg; 1173 png_ptr->palette[i].blue >>= sb; 1174 } 1175 } 1176 #endif /* PNG_READ_SHIFT_SUPPORTED */ 1177 } 1178 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ 1179 && !defined(PNG_READ_BACKGROUND_SUPPORTED) 1180 if (png_ptr) 1181 return; 1182 #endif 1183 } 1184 1185 /* Modify the info structure to reflect the transformations. The 1186 * info should be updated so a PNG file could be written with it, 1187 * assuming the transformations result in valid PNG data. 1188 */ 1189 void /* PRIVATE */ 1190 png_read_transform_info(png_structp png_ptr, png_infop info_ptr) 1191 { 1192 png_debug(1, "in png_read_transform_info"); 1193 1194 #ifdef PNG_READ_EXPAND_SUPPORTED 1195 if (png_ptr->transformations & PNG_EXPAND) 1196 { 1197 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1198 { 1199 if (png_ptr->num_trans && 1200 (png_ptr->transformations & PNG_EXPAND_tRNS)) 1201 info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; 1202 else 1203 info_ptr->color_type = PNG_COLOR_TYPE_RGB; 1204 info_ptr->bit_depth = 8; 1205 info_ptr->num_trans = 0; 1206 } 1207 else 1208 { 1209 if (png_ptr->num_trans) 1210 { 1211 if (png_ptr->transformations & PNG_EXPAND_tRNS) 1212 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; 1213 } 1214 if (info_ptr->bit_depth < 8) 1215 info_ptr->bit_depth = 8; 1216 info_ptr->num_trans = 0; 1217 } 1218 } 1219 #endif 1220 1221 #ifdef PNG_READ_BACKGROUND_SUPPORTED 1222 if (png_ptr->transformations & PNG_BACKGROUND) 1223 { 1224 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; 1225 info_ptr->num_trans = 0; 1226 info_ptr->background = png_ptr->background; 1227 } 1228 #endif 1229 1230 #ifdef PNG_READ_GAMMA_SUPPORTED 1231 if (png_ptr->transformations & PNG_GAMMA) 1232 { 1233 #ifdef PNG_FLOATING_POINT_SUPPORTED 1234 info_ptr->gamma = png_ptr->gamma; 1235 #endif 1236 #ifdef PNG_FIXED_POINT_SUPPORTED 1237 info_ptr->int_gamma = png_ptr->int_gamma; 1238 #endif 1239 } 1240 #endif 1241 1242 #ifdef PNG_READ_16_TO_8_SUPPORTED 1243 if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) 1244 info_ptr->bit_depth = 8; 1245 #endif 1246 1247 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 1248 if (png_ptr->transformations & PNG_GRAY_TO_RGB) 1249 info_ptr->color_type |= PNG_COLOR_MASK_COLOR; 1250 #endif 1251 1252 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 1253 if (png_ptr->transformations & PNG_RGB_TO_GRAY) 1254 info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; 1255 #endif 1256 1257 #ifdef PNG_READ_DITHER_SUPPORTED 1258 if (png_ptr->transformations & PNG_DITHER) 1259 { 1260 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || 1261 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && 1262 png_ptr->palette_lookup && info_ptr->bit_depth == 8) 1263 { 1264 info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; 1265 } 1266 } 1267 #endif 1268 1269 #ifdef PNG_READ_PACK_SUPPORTED 1270 if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) 1271 info_ptr->bit_depth = 8; 1272 #endif 1273 1274 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1275 info_ptr->channels = 1; 1276 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) 1277 info_ptr->channels = 3; 1278 else 1279 info_ptr->channels = 1; 1280 1281 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 1282 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) 1283 info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; 1284 #endif 1285 1286 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) 1287 info_ptr->channels++; 1288 1289 #ifdef PNG_READ_FILLER_SUPPORTED 1290 /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ 1291 if ((png_ptr->transformations & PNG_FILLER) && 1292 ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || 1293 (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) 1294 { 1295 info_ptr->channels++; 1296 /* If adding a true alpha channel not just filler */ 1297 #ifndef PNG_1_0_X 1298 if (png_ptr->transformations & PNG_ADD_ALPHA) 1299 info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; 1300 #endif 1301 } 1302 #endif 1303 1304 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ 1305 defined(PNG_READ_USER_TRANSFORM_SUPPORTED) 1306 if (png_ptr->transformations & PNG_USER_TRANSFORM) 1307 { 1308 if (info_ptr->bit_depth < png_ptr->user_transform_depth) 1309 info_ptr->bit_depth = png_ptr->user_transform_depth; 1310 if (info_ptr->channels < png_ptr->user_transform_channels) 1311 info_ptr->channels = png_ptr->user_transform_channels; 1312 } 1313 #endif 1314 1315 info_ptr->pixel_depth = (png_byte)(info_ptr->channels * 1316 info_ptr->bit_depth); 1317 1318 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); 1319 1320 #ifndef PNG_READ_EXPAND_SUPPORTED 1321 if (png_ptr) 1322 return; 1323 #endif 1324 } 1325 1326 /* Transform the row. The order of transformations is significant, 1327 * and is very touchy. If you add a transformation, take care to 1328 * decide how it fits in with the other transformations here. 1329 */ 1330 void /* PRIVATE */ 1331 png_do_read_transformations(png_structp png_ptr) 1332 { 1333 png_debug(1, "in png_do_read_transformations"); 1334 1335 if (png_ptr->row_buf == NULL) 1336 { 1337 #if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) 1338 char msg[50]; 1339 1340 png_snprintf2(msg, 50, 1341 "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number, 1342 png_ptr->pass); 1343 png_error(png_ptr, msg); 1344 #else 1345 png_error(png_ptr, "NULL row buffer"); 1346 #endif 1347 } 1348 #ifdef PNG_WARN_UNINITIALIZED_ROW 1349 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) 1350 /* Application has failed to call either png_read_start_image() 1351 * or png_read_update_info() after setting transforms that expand 1352 * pixels. This check added to libpng-1.2.19 1353 */ 1354 #if (PNG_WARN_UNINITIALIZED_ROW==1) 1355 png_error(png_ptr, "Uninitialized row"); 1356 #else 1357 png_warning(png_ptr, "Uninitialized row"); 1358 #endif 1359 #endif 1360 1361 #ifdef PNG_READ_EXPAND_SUPPORTED 1362 if (png_ptr->transformations & PNG_EXPAND) 1363 { 1364 if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) 1365 { 1366 png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, 1367 png_ptr->palette, png_ptr->trans, png_ptr->num_trans); 1368 } 1369 else 1370 { 1371 if (png_ptr->num_trans && 1372 (png_ptr->transformations & PNG_EXPAND_tRNS)) 1373 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, 1374 &(png_ptr->trans_values)); 1375 else 1376 png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, 1377 NULL); 1378 } 1379 } 1380 #endif 1381 1382 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 1383 if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) 1384 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, 1385 PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); 1386 #endif 1387 1388 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 1389 if (png_ptr->transformations & PNG_RGB_TO_GRAY) 1390 { 1391 int rgb_error = 1392 png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), 1393 png_ptr->row_buf + 1); 1394 if (rgb_error) 1395 { 1396 png_ptr->rgb_to_gray_status=1; 1397 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 1398 PNG_RGB_TO_GRAY_WARN) 1399 png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); 1400 if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 1401 PNG_RGB_TO_GRAY_ERR) 1402 png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); 1403 } 1404 } 1405 #endif 1406 1407 /* From Andreas Dilger e-mail to png-implement, 26 March 1998: 1408 * 1409 * In most cases, the "simple transparency" should be done prior to doing 1410 * gray-to-RGB, or you will have to test 3x as many bytes to check if a 1411 * pixel is transparent. You would also need to make sure that the 1412 * transparency information is upgraded to RGB. 1413 * 1414 * To summarize, the current flow is: 1415 * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite 1416 * with background "in place" if transparent, 1417 * convert to RGB if necessary 1418 * - Gray + alpha -> composite with gray background and remove alpha bytes, 1419 * convert to RGB if necessary 1420 * 1421 * To support RGB backgrounds for gray images we need: 1422 * - Gray + simple transparency -> convert to RGB + simple transparency, 1423 * compare 3 or 6 bytes and composite with 1424 * background "in place" if transparent 1425 * (3x compare/pixel compared to doing 1426 * composite with gray bkgrnd) 1427 * - Gray + alpha -> convert to RGB + alpha, composite with background and 1428 * remove alpha bytes (3x float 1429 * operations/pixel compared with composite 1430 * on gray background) 1431 * 1432 * Greg's change will do this. The reason it wasn't done before is for 1433 * performance, as this increases the per-pixel operations. If we would check 1434 * in advance if the background was gray or RGB, and position the gray-to-RGB 1435 * transform appropriately, then it would save a lot of work/time. 1436 */ 1437 1438 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 1439 /* If gray -> RGB, do so now only if background is non-gray; else do later 1440 * for performance reasons 1441 */ 1442 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && 1443 !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) 1444 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); 1445 #endif 1446 1447 #ifdef PNG_READ_BACKGROUND_SUPPORTED 1448 if ((png_ptr->transformations & PNG_BACKGROUND) && 1449 ((png_ptr->num_trans != 0 ) || 1450 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) 1451 png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, 1452 &(png_ptr->trans_values), &(png_ptr->background) 1453 #ifdef PNG_READ_GAMMA_SUPPORTED 1454 , &(png_ptr->background_1), 1455 png_ptr->gamma_table, png_ptr->gamma_from_1, 1456 png_ptr->gamma_to_1, png_ptr->gamma_16_table, 1457 png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, 1458 png_ptr->gamma_shift 1459 #endif 1460 ); 1461 #endif 1462 1463 #ifdef PNG_READ_GAMMA_SUPPORTED 1464 if ((png_ptr->transformations & PNG_GAMMA) && 1465 #ifdef PNG_READ_BACKGROUND_SUPPORTED 1466 !((png_ptr->transformations & PNG_BACKGROUND) && 1467 ((png_ptr->num_trans != 0) || 1468 (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && 1469 #endif 1470 (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) 1471 png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, 1472 png_ptr->gamma_table, png_ptr->gamma_16_table, 1473 png_ptr->gamma_shift); 1474 #endif 1475 1476 #ifdef PNG_READ_16_TO_8_SUPPORTED 1477 if (png_ptr->transformations & PNG_16_TO_8) 1478 png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); 1479 #endif 1480 1481 #ifdef PNG_READ_DITHER_SUPPORTED 1482 if (png_ptr->transformations & PNG_DITHER) 1483 { 1484 png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, 1485 png_ptr->palette_lookup, png_ptr->dither_index); 1486 if (png_ptr->row_info.rowbytes == (png_uint_32)0) 1487 png_error(png_ptr, "png_do_dither returned rowbytes=0"); 1488 } 1489 #endif 1490 1491 #ifdef PNG_READ_INVERT_SUPPORTED 1492 if (png_ptr->transformations & PNG_INVERT_MONO) 1493 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); 1494 #endif 1495 1496 #ifdef PNG_READ_SHIFT_SUPPORTED 1497 if (png_ptr->transformations & PNG_SHIFT) 1498 png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, 1499 &(png_ptr->shift)); 1500 #endif 1501 1502 #ifdef PNG_READ_PACK_SUPPORTED 1503 if (png_ptr->transformations & PNG_PACK) 1504 png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); 1505 #endif 1506 1507 #ifdef PNG_READ_BGR_SUPPORTED 1508 if (png_ptr->transformations & PNG_BGR) 1509 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); 1510 #endif 1511 1512 #ifdef PNG_READ_PACKSWAP_SUPPORTED 1513 if (png_ptr->transformations & PNG_PACKSWAP) 1514 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); 1515 #endif 1516 1517 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 1518 /* If gray -> RGB, do so now only if we did not do so above */ 1519 if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && 1520 (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) 1521 png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); 1522 #endif 1523 1524 #ifdef PNG_READ_FILLER_SUPPORTED 1525 if (png_ptr->transformations & PNG_FILLER) 1526 png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, 1527 (png_uint_32)png_ptr->filler, png_ptr->flags); 1528 #endif 1529 1530 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 1531 if (png_ptr->transformations & PNG_INVERT_ALPHA) 1532 png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); 1533 #endif 1534 1535 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 1536 if (png_ptr->transformations & PNG_SWAP_ALPHA) 1537 png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); 1538 #endif 1539 1540 #ifdef PNG_READ_SWAP_SUPPORTED 1541 if (png_ptr->transformations & PNG_SWAP_BYTES) 1542 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); 1543 #endif 1544 1545 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 1546 if (png_ptr->transformations & PNG_USER_TRANSFORM) 1547 { 1548 if (png_ptr->read_user_transform_fn != NULL) 1549 (*(png_ptr->read_user_transform_fn)) /* User read transform function */ 1550 (png_ptr, /* png_ptr */ 1551 &(png_ptr->row_info), /* row_info: */ 1552 /* png_uint_32 width; width of row */ 1553 /* png_uint_32 rowbytes; number of bytes in row */ 1554 /* png_byte color_type; color type of pixels */ 1555 /* png_byte bit_depth; bit depth of samples */ 1556 /* png_byte channels; number of channels (1-4) */ 1557 /* png_byte pixel_depth; bits per pixel (depth*channels) */ 1558 png_ptr->row_buf + 1); /* start of pixel data for row */ 1559 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED 1560 if (png_ptr->user_transform_depth) 1561 png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; 1562 if (png_ptr->user_transform_channels) 1563 png_ptr->row_info.channels = png_ptr->user_transform_channels; 1564 #endif 1565 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * 1566 png_ptr->row_info.channels); 1567 png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, 1568 png_ptr->row_info.width); 1569 } 1570 #endif 1571 1572 } 1573 1574 #ifdef PNG_READ_PACK_SUPPORTED 1575 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, 1576 * without changing the actual values. Thus, if you had a row with 1577 * a bit depth of 1, you would end up with bytes that only contained 1578 * the numbers 0 or 1. If you would rather they contain 0 and 255, use 1579 * png_do_shift() after this. 1580 */ 1581 void /* PRIVATE */ 1582 png_do_unpack(png_row_infop row_info, png_bytep row) 1583 { 1584 png_debug(1, "in png_do_unpack"); 1585 1586 #ifdef PNG_USELESS_TESTS_SUPPORTED 1587 if (row != NULL && row_info != NULL && row_info->bit_depth < 8) 1588 #else 1589 if (row_info->bit_depth < 8) 1590 #endif 1591 { 1592 png_uint_32 i; 1593 png_uint_32 row_width=row_info->width; 1594 1595 switch (row_info->bit_depth) 1596 { 1597 case 1: 1598 { 1599 png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); 1600 png_bytep dp = row + (png_size_t)row_width - 1; 1601 png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); 1602 for (i = 0; i < row_width; i++) 1603 { 1604 *dp = (png_byte)((*sp >> shift) & 0x01); 1605 if (shift == 7) 1606 { 1607 shift = 0; 1608 sp--; 1609 } 1610 else 1611 shift++; 1612 1613 dp--; 1614 } 1615 break; 1616 } 1617 1618 case 2: 1619 { 1620 1621 png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); 1622 png_bytep dp = row + (png_size_t)row_width - 1; 1623 png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 1624 for (i = 0; i < row_width; i++) 1625 { 1626 *dp = (png_byte)((*sp >> shift) & 0x03); 1627 if (shift == 6) 1628 { 1629 shift = 0; 1630 sp--; 1631 } 1632 else 1633 shift += 2; 1634 1635 dp--; 1636 } 1637 break; 1638 } 1639 1640 case 4: 1641 { 1642 png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); 1643 png_bytep dp = row + (png_size_t)row_width - 1; 1644 png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); 1645 for (i = 0; i < row_width; i++) 1646 { 1647 *dp = (png_byte)((*sp >> shift) & 0x0f); 1648 if (shift == 4) 1649 { 1650 shift = 0; 1651 sp--; 1652 } 1653 else 1654 shift = 4; 1655 1656 dp--; 1657 } 1658 break; 1659 } 1660 } 1661 row_info->bit_depth = 8; 1662 row_info->pixel_depth = (png_byte)(8 * row_info->channels); 1663 row_info->rowbytes = row_width * row_info->channels; 1664 } 1665 } 1666 #endif 1667 1668 #ifdef PNG_READ_SHIFT_SUPPORTED 1669 /* Reverse the effects of png_do_shift. This routine merely shifts the 1670 * pixels back to their significant bits values. Thus, if you have 1671 * a row of bit depth 8, but only 5 are significant, this will shift 1672 * the values back to 0 through 31. 1673 */ 1674 void /* PRIVATE */ 1675 png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) 1676 { 1677 png_debug(1, "in png_do_unshift"); 1678 1679 if ( 1680 #ifdef PNG_USELESS_TESTS_SUPPORTED 1681 row != NULL && row_info != NULL && sig_bits != NULL && 1682 #endif 1683 row_info->color_type != PNG_COLOR_TYPE_PALETTE) 1684 { 1685 int shift[4]; 1686 int channels = 0; 1687 int c; 1688 png_uint_16 value = 0; 1689 png_uint_32 row_width = row_info->width; 1690 1691 if (row_info->color_type & PNG_COLOR_MASK_COLOR) 1692 { 1693 shift[channels++] = row_info->bit_depth - sig_bits->red; 1694 shift[channels++] = row_info->bit_depth - sig_bits->green; 1695 shift[channels++] = row_info->bit_depth - sig_bits->blue; 1696 } 1697 else 1698 { 1699 shift[channels++] = row_info->bit_depth - sig_bits->gray; 1700 } 1701 if (row_info->color_type & PNG_COLOR_MASK_ALPHA) 1702 { 1703 shift[channels++] = row_info->bit_depth - sig_bits->alpha; 1704 } 1705 1706 for (c = 0; c < channels; c++) 1707 { 1708 if (shift[c] <= 0) 1709 shift[c] = 0; 1710 else 1711 value = 1; 1712 } 1713 1714 if (!value) 1715 return; 1716 1717 switch (row_info->bit_depth) 1718 { 1719 case 2: 1720 { 1721 png_bytep bp; 1722 png_uint_32 i; 1723 png_uint_32 istop = row_info->rowbytes; 1724 1725 for (bp = row, i = 0; i < istop; i++) 1726 { 1727 *bp >>= 1; 1728 *bp++ &= 0x55; 1729 } 1730 break; 1731 } 1732 1733 case 4: 1734 { 1735 png_bytep bp = row; 1736 png_uint_32 i; 1737 png_uint_32 istop = row_info->rowbytes; 1738 png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | 1739 (png_byte)((int)0xf >> shift[0])); 1740 1741 for (i = 0; i < istop; i++) 1742 { 1743 *bp >>= shift[0]; 1744 *bp++ &= mask; 1745 } 1746 break; 1747 } 1748 1749 case 8: 1750 { 1751 png_bytep bp = row; 1752 png_uint_32 i; 1753 png_uint_32 istop = row_width * channels; 1754 1755 for (i = 0; i < istop; i++) 1756 { 1757 *bp++ >>= shift[i%channels]; 1758 } 1759 break; 1760 } 1761 1762 case 16: 1763 { 1764 png_bytep bp = row; 1765 png_uint_32 i; 1766 png_uint_32 istop = channels * row_width; 1767 1768 for (i = 0; i < istop; i++) 1769 { 1770 value = (png_uint_16)((*bp << 8) + *(bp + 1)); 1771 value >>= shift[i%channels]; 1772 *bp++ = (png_byte)(value >> 8); 1773 *bp++ = (png_byte)(value & 0xff); 1774 } 1775 break; 1776 } 1777 } 1778 } 1779 } 1780 #endif 1781 1782 #ifdef PNG_READ_16_TO_8_SUPPORTED 1783 /* Chop rows of bit depth 16 down to 8 */ 1784 void /* PRIVATE */ 1785 png_do_chop(png_row_infop row_info, png_bytep row) 1786 { 1787 png_debug(1, "in png_do_chop"); 1788 1789 #ifdef PNG_USELESS_TESTS_SUPPORTED 1790 if (row != NULL && row_info != NULL && row_info->bit_depth == 16) 1791 #else 1792 if (row_info->bit_depth == 16) 1793 #endif 1794 { 1795 png_bytep sp = row; 1796 png_bytep dp = row; 1797 png_uint_32 i; 1798 png_uint_32 istop = row_info->width * row_info->channels; 1799 1800 for (i = 0; i<istop; i++, sp += 2, dp++) 1801 { 1802 #ifdef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED 1803 /* This does a more accurate scaling of the 16-bit color 1804 * value, rather than a simple low-byte truncation. 1805 * 1806 * What the ideal calculation should be: 1807 * *dp = (((((png_uint_32)(*sp) << 8) | 1808 * (png_uint_32)(*(sp + 1))) * 255 + 127) 1809 * / (png_uint_32)65535L; 1810 * 1811 * GRR: no, I think this is what it really should be: 1812 * *dp = (((((png_uint_32)(*sp) << 8) | 1813 * (png_uint_32)(*(sp + 1))) + 128L) 1814 * / (png_uint_32)257L; 1815 * 1816 * GRR: here's the exact calculation with shifts: 1817 * temp = (((png_uint_32)(*sp) << 8) | 1818 * (png_uint_32)(*(sp + 1))) + 128L; 1819 * *dp = (temp - (temp >> 8)) >> 8; 1820 * 1821 * Approximate calculation with shift/add instead of multiply/divide: 1822 * *dp = ((((png_uint_32)(*sp) << 8) | 1823 * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; 1824 * 1825 * What we actually do to avoid extra shifting and conversion: 1826 */ 1827 1828 *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); 1829 #else 1830 /* Simply discard the low order byte */ 1831 *dp = *sp; 1832 #endif 1833 } 1834 row_info->bit_depth = 8; 1835 row_info->pixel_depth = (png_byte)(8 * row_info->channels); 1836 row_info->rowbytes = row_info->width * row_info->channels; 1837 } 1838 } 1839 #endif 1840 1841 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 1842 void /* PRIVATE */ 1843 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) 1844 { 1845 png_debug(1, "in png_do_read_swap_alpha"); 1846 1847 #ifdef PNG_USELESS_TESTS_SUPPORTED 1848 if (row != NULL && row_info != NULL) 1849 #endif 1850 { 1851 png_uint_32 row_width = row_info->width; 1852 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 1853 { 1854 /* This converts from RGBA to ARGB */ 1855 if (row_info->bit_depth == 8) 1856 { 1857 png_bytep sp = row + row_info->rowbytes; 1858 png_bytep dp = sp; 1859 png_byte save; 1860 png_uint_32 i; 1861 1862 for (i = 0; i < row_width; i++) 1863 { 1864 save = *(--sp); 1865 *(--dp) = *(--sp); 1866 *(--dp) = *(--sp); 1867 *(--dp) = *(--sp); 1868 *(--dp) = save; 1869 } 1870 } 1871 /* This converts from RRGGBBAA to AARRGGBB */ 1872 else 1873 { 1874 png_bytep sp = row + row_info->rowbytes; 1875 png_bytep dp = sp; 1876 png_byte save[2]; 1877 png_uint_32 i; 1878 1879 for (i = 0; i < row_width; i++) 1880 { 1881 save[0] = *(--sp); 1882 save[1] = *(--sp); 1883 *(--dp) = *(--sp); 1884 *(--dp) = *(--sp); 1885 *(--dp) = *(--sp); 1886 *(--dp) = *(--sp); 1887 *(--dp) = *(--sp); 1888 *(--dp) = *(--sp); 1889 *(--dp) = save[0]; 1890 *(--dp) = save[1]; 1891 } 1892 } 1893 } 1894 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 1895 { 1896 /* This converts from GA to AG */ 1897 if (row_info->bit_depth == 8) 1898 { 1899 png_bytep sp = row + row_info->rowbytes; 1900 png_bytep dp = sp; 1901 png_byte save; 1902 png_uint_32 i; 1903 1904 for (i = 0; i < row_width; i++) 1905 { 1906 save = *(--sp); 1907 *(--dp) = *(--sp); 1908 *(--dp) = save; 1909 } 1910 } 1911 /* This converts from GGAA to AAGG */ 1912 else 1913 { 1914 png_bytep sp = row + row_info->rowbytes; 1915 png_bytep dp = sp; 1916 png_byte save[2]; 1917 png_uint_32 i; 1918 1919 for (i = 0; i < row_width; i++) 1920 { 1921 save[0] = *(--sp); 1922 save[1] = *(--sp); 1923 *(--dp) = *(--sp); 1924 *(--dp) = *(--sp); 1925 *(--dp) = save[0]; 1926 *(--dp) = save[1]; 1927 } 1928 } 1929 } 1930 } 1931 } 1932 #endif 1933 1934 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 1935 void /* PRIVATE */ 1936 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) 1937 { 1938 png_debug(1, "in png_do_read_invert_alpha"); 1939 1940 #ifdef PNG_USELESS_TESTS_SUPPORTED 1941 if (row != NULL && row_info != NULL) 1942 #endif 1943 { 1944 png_uint_32 row_width = row_info->width; 1945 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 1946 { 1947 /* This inverts the alpha channel in RGBA */ 1948 if (row_info->bit_depth == 8) 1949 { 1950 png_bytep sp = row + row_info->rowbytes; 1951 png_bytep dp = sp; 1952 png_uint_32 i; 1953 1954 for (i = 0; i < row_width; i++) 1955 { 1956 *(--dp) = (png_byte)(255 - *(--sp)); 1957 1958 /* This does nothing: 1959 *(--dp) = *(--sp); 1960 *(--dp) = *(--sp); 1961 *(--dp) = *(--sp); 1962 We can replace it with: 1963 */ 1964 sp-=3; 1965 dp=sp; 1966 } 1967 } 1968 /* This inverts the alpha channel in RRGGBBAA */ 1969 else 1970 { 1971 png_bytep sp = row + row_info->rowbytes; 1972 png_bytep dp = sp; 1973 png_uint_32 i; 1974 1975 for (i = 0; i < row_width; i++) 1976 { 1977 *(--dp) = (png_byte)(255 - *(--sp)); 1978 *(--dp) = (png_byte)(255 - *(--sp)); 1979 1980 /* This does nothing: 1981 *(--dp) = *(--sp); 1982 *(--dp) = *(--sp); 1983 *(--dp) = *(--sp); 1984 *(--dp) = *(--sp); 1985 *(--dp) = *(--sp); 1986 *(--dp) = *(--sp); 1987 We can replace it with: 1988 */ 1989 sp-=6; 1990 dp=sp; 1991 } 1992 } 1993 } 1994 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 1995 { 1996 /* This inverts the alpha channel in GA */ 1997 if (row_info->bit_depth == 8) 1998 { 1999 png_bytep sp = row + row_info->rowbytes; 2000 png_bytep dp = sp; 2001 png_uint_32 i; 2002 2003 for (i = 0; i < row_width; i++) 2004 { 2005 *(--dp) = (png_byte)(255 - *(--sp)); 2006 *(--dp) = *(--sp); 2007 } 2008 } 2009 /* This inverts the alpha channel in GGAA */ 2010 else 2011 { 2012 png_bytep sp = row + row_info->rowbytes; 2013 png_bytep dp = sp; 2014 png_uint_32 i; 2015 2016 for (i = 0; i < row_width; i++) 2017 { 2018 *(--dp) = (png_byte)(255 - *(--sp)); 2019 *(--dp) = (png_byte)(255 - *(--sp)); 2020 /* 2021 *(--dp) = *(--sp); 2022 *(--dp) = *(--sp); 2023 */ 2024 sp-=2; 2025 dp=sp; 2026 } 2027 } 2028 } 2029 } 2030 } 2031 #endif 2032 2033 #ifdef PNG_READ_FILLER_SUPPORTED 2034 /* Add filler channel if we have RGB color */ 2035 void /* PRIVATE */ 2036 png_do_read_filler(png_row_infop row_info, png_bytep row, 2037 png_uint_32 filler, png_uint_32 flags) 2038 { 2039 png_uint_32 i; 2040 png_uint_32 row_width = row_info->width; 2041 2042 png_byte hi_filler = (png_byte)((filler>>8) & 0xff); 2043 png_byte lo_filler = (png_byte)(filler & 0xff); 2044 2045 png_debug(1, "in png_do_read_filler"); 2046 2047 if ( 2048 #ifdef PNG_USELESS_TESTS_SUPPORTED 2049 row != NULL && row_info != NULL && 2050 #endif 2051 row_info->color_type == PNG_COLOR_TYPE_GRAY) 2052 { 2053 if (row_info->bit_depth == 8) 2054 { 2055 /* This changes the data from G to GX */ 2056 if (flags & PNG_FLAG_FILLER_AFTER) 2057 { 2058 png_bytep sp = row + (png_size_t)row_width; 2059 png_bytep dp = sp + (png_size_t)row_width; 2060 for (i = 1; i < row_width; i++) 2061 { 2062 *(--dp) = lo_filler; 2063 *(--dp) = *(--sp); 2064 } 2065 *(--dp) = lo_filler; 2066 row_info->channels = 2; 2067 row_info->pixel_depth = 16; 2068 row_info->rowbytes = row_width * 2; 2069 } 2070 /* This changes the data from G to XG */ 2071 else 2072 { 2073 png_bytep sp = row + (png_size_t)row_width; 2074 png_bytep dp = sp + (png_size_t)row_width; 2075 for (i = 0; i < row_width; i++) 2076 { 2077 *(--dp) = *(--sp); 2078 *(--dp) = lo_filler; 2079 } 2080 row_info->channels = 2; 2081 row_info->pixel_depth = 16; 2082 row_info->rowbytes = row_width * 2; 2083 } 2084 } 2085 else if (row_info->bit_depth == 16) 2086 { 2087 /* This changes the data from GG to GGXX */ 2088 if (flags & PNG_FLAG_FILLER_AFTER) 2089 { 2090 png_bytep sp = row + (png_size_t)row_width * 2; 2091 png_bytep dp = sp + (png_size_t)row_width * 2; 2092 for (i = 1; i < row_width; i++) 2093 { 2094 *(--dp) = hi_filler; 2095 *(--dp) = lo_filler; 2096 *(--dp) = *(--sp); 2097 *(--dp) = *(--sp); 2098 } 2099 *(--dp) = hi_filler; 2100 *(--dp) = lo_filler; 2101 row_info->channels = 2; 2102 row_info->pixel_depth = 32; 2103 row_info->rowbytes = row_width * 4; 2104 } 2105 /* This changes the data from GG to XXGG */ 2106 else 2107 { 2108 png_bytep sp = row + (png_size_t)row_width * 2; 2109 png_bytep dp = sp + (png_size_t)row_width * 2; 2110 for (i = 0; i < row_width; i++) 2111 { 2112 *(--dp) = *(--sp); 2113 *(--dp) = *(--sp); 2114 *(--dp) = hi_filler; 2115 *(--dp) = lo_filler; 2116 } 2117 row_info->channels = 2; 2118 row_info->pixel_depth = 32; 2119 row_info->rowbytes = row_width * 4; 2120 } 2121 } 2122 } /* COLOR_TYPE == GRAY */ 2123 else if (row_info->color_type == PNG_COLOR_TYPE_RGB) 2124 { 2125 if (row_info->bit_depth == 8) 2126 { 2127 /* This changes the data from RGB to RGBX */ 2128 if (flags & PNG_FLAG_FILLER_AFTER) 2129 { 2130 png_bytep sp = row + (png_size_t)row_width * 3; 2131 png_bytep dp = sp + (png_size_t)row_width; 2132 for (i = 1; i < row_width; i++) 2133 { 2134 *(--dp) = lo_filler; 2135 *(--dp) = *(--sp); 2136 *(--dp) = *(--sp); 2137 *(--dp) = *(--sp); 2138 } 2139 *(--dp) = lo_filler; 2140 row_info->channels = 4; 2141 row_info->pixel_depth = 32; 2142 row_info->rowbytes = row_width * 4; 2143 } 2144 /* This changes the data from RGB to XRGB */ 2145 else 2146 { 2147 png_bytep sp = row + (png_size_t)row_width * 3; 2148 png_bytep dp = sp + (png_size_t)row_width; 2149 for (i = 0; i < row_width; i++) 2150 { 2151 *(--dp) = *(--sp); 2152 *(--dp) = *(--sp); 2153 *(--dp) = *(--sp); 2154 *(--dp) = lo_filler; 2155 } 2156 row_info->channels = 4; 2157 row_info->pixel_depth = 32; 2158 row_info->rowbytes = row_width * 4; 2159 } 2160 } 2161 else if (row_info->bit_depth == 16) 2162 { 2163 /* This changes the data from RRGGBB to RRGGBBXX */ 2164 if (flags & PNG_FLAG_FILLER_AFTER) 2165 { 2166 png_bytep sp = row + (png_size_t)row_width * 6; 2167 png_bytep dp = sp + (png_size_t)row_width * 2; 2168 for (i = 1; i < row_width; i++) 2169 { 2170 *(--dp) = hi_filler; 2171 *(--dp) = lo_filler; 2172 *(--dp) = *(--sp); 2173 *(--dp) = *(--sp); 2174 *(--dp) = *(--sp); 2175 *(--dp) = *(--sp); 2176 *(--dp) = *(--sp); 2177 *(--dp) = *(--sp); 2178 } 2179 *(--dp) = hi_filler; 2180 *(--dp) = lo_filler; 2181 row_info->channels = 4; 2182 row_info->pixel_depth = 64; 2183 row_info->rowbytes = row_width * 8; 2184 } 2185 /* This changes the data from RRGGBB to XXRRGGBB */ 2186 else 2187 { 2188 png_bytep sp = row + (png_size_t)row_width * 6; 2189 png_bytep dp = sp + (png_size_t)row_width * 2; 2190 for (i = 0; i < row_width; i++) 2191 { 2192 *(--dp) = *(--sp); 2193 *(--dp) = *(--sp); 2194 *(--dp) = *(--sp); 2195 *(--dp) = *(--sp); 2196 *(--dp) = *(--sp); 2197 *(--dp) = *(--sp); 2198 *(--dp) = hi_filler; 2199 *(--dp) = lo_filler; 2200 } 2201 row_info->channels = 4; 2202 row_info->pixel_depth = 64; 2203 row_info->rowbytes = row_width * 8; 2204 } 2205 } 2206 } /* COLOR_TYPE == RGB */ 2207 } 2208 #endif 2209 2210 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 2211 /* Expand grayscale files to RGB, with or without alpha */ 2212 void /* PRIVATE */ 2213 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) 2214 { 2215 png_uint_32 i; 2216 png_uint_32 row_width = row_info->width; 2217 2218 png_debug(1, "in png_do_gray_to_rgb"); 2219 2220 if (row_info->bit_depth >= 8 && 2221 #ifdef PNG_USELESS_TESTS_SUPPORTED 2222 row != NULL && row_info != NULL && 2223 #endif 2224 !(row_info->color_type & PNG_COLOR_MASK_COLOR)) 2225 { 2226 if (row_info->color_type == PNG_COLOR_TYPE_GRAY) 2227 { 2228 if (row_info->bit_depth == 8) 2229 { 2230 png_bytep sp = row + (png_size_t)row_width - 1; 2231 png_bytep dp = sp + (png_size_t)row_width * 2; 2232 for (i = 0; i < row_width; i++) 2233 { 2234 *(dp--) = *sp; 2235 *(dp--) = *sp; 2236 *(dp--) = *(sp--); 2237 } 2238 } 2239 else 2240 { 2241 png_bytep sp = row + (png_size_t)row_width * 2 - 1; 2242 png_bytep dp = sp + (png_size_t)row_width * 4; 2243 for (i = 0; i < row_width; i++) 2244 { 2245 *(dp--) = *sp; 2246 *(dp--) = *(sp - 1); 2247 *(dp--) = *sp; 2248 *(dp--) = *(sp - 1); 2249 *(dp--) = *(sp--); 2250 *(dp--) = *(sp--); 2251 } 2252 } 2253 } 2254 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 2255 { 2256 if (row_info->bit_depth == 8) 2257 { 2258 png_bytep sp = row + (png_size_t)row_width * 2 - 1; 2259 png_bytep dp = sp + (png_size_t)row_width * 2; 2260 for (i = 0; i < row_width; i++) 2261 { 2262 *(dp--) = *(sp--); 2263 *(dp--) = *sp; 2264 *(dp--) = *sp; 2265 *(dp--) = *(sp--); 2266 } 2267 } 2268 else 2269 { 2270 png_bytep sp = row + (png_size_t)row_width * 4 - 1; 2271 png_bytep dp = sp + (png_size_t)row_width * 4; 2272 for (i = 0; i < row_width; i++) 2273 { 2274 *(dp--) = *(sp--); 2275 *(dp--) = *(sp--); 2276 *(dp--) = *sp; 2277 *(dp--) = *(sp - 1); 2278 *(dp--) = *sp; 2279 *(dp--) = *(sp - 1); 2280 *(dp--) = *(sp--); 2281 *(dp--) = *(sp--); 2282 } 2283 } 2284 } 2285 row_info->channels += (png_byte)2; 2286 row_info->color_type |= PNG_COLOR_MASK_COLOR; 2287 row_info->pixel_depth = (png_byte)(row_info->channels * 2288 row_info->bit_depth); 2289 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 2290 } 2291 } 2292 #endif 2293 2294 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 2295 /* Reduce RGB files to grayscale, with or without alpha 2296 * using the equation given in Poynton's ColorFAQ at 2297 * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008) 2298 * New link: 2299 * <http://www.poynton.com/notes/colour_and_gamma/> 2300 * Charles Poynton poynton at poynton.com 2301 * 2302 * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B 2303 * 2304 * We approximate this with 2305 * 2306 * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B 2307 * 2308 * which can be expressed with integers as 2309 * 2310 * Y = (6969 * R + 23434 * G + 2365 * B)/32768 2311 * 2312 * The calculation is to be done in a linear colorspace. 2313 * 2314 * Other integer coefficents can be used via png_set_rgb_to_gray(). 2315 */ 2316 int /* PRIVATE */ 2317 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) 2318 2319 { 2320 png_uint_32 i; 2321 2322 png_uint_32 row_width = row_info->width; 2323 int rgb_error = 0; 2324 2325 png_debug(1, "in png_do_rgb_to_gray"); 2326 2327 if ( 2328 #ifdef PNG_USELESS_TESTS_SUPPORTED 2329 row != NULL && row_info != NULL && 2330 #endif 2331 (row_info->color_type & PNG_COLOR_MASK_COLOR)) 2332 { 2333 png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; 2334 png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; 2335 png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; 2336 2337 if (row_info->color_type == PNG_COLOR_TYPE_RGB) 2338 { 2339 if (row_info->bit_depth == 8) 2340 { 2341 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 2342 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) 2343 { 2344 png_bytep sp = row; 2345 png_bytep dp = row; 2346 2347 for (i = 0; i < row_width; i++) 2348 { 2349 png_byte red = png_ptr->gamma_to_1[*(sp++)]; 2350 png_byte green = png_ptr->gamma_to_1[*(sp++)]; 2351 png_byte blue = png_ptr->gamma_to_1[*(sp++)]; 2352 if (red != green || red != blue) 2353 { 2354 rgb_error |= 1; 2355 *(dp++) = png_ptr->gamma_from_1[ 2356 (rc*red + gc*green + bc*blue)>>15]; 2357 } 2358 else 2359 *(dp++) = *(sp - 1); 2360 } 2361 } 2362 else 2363 #endif 2364 { 2365 png_bytep sp = row; 2366 png_bytep dp = row; 2367 for (i = 0; i < row_width; i++) 2368 { 2369 png_byte red = *(sp++); 2370 png_byte green = *(sp++); 2371 png_byte blue = *(sp++); 2372 if (red != green || red != blue) 2373 { 2374 rgb_error |= 1; 2375 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); 2376 } 2377 else 2378 *(dp++) = *(sp - 1); 2379 } 2380 } 2381 } 2382 2383 else /* RGB bit_depth == 16 */ 2384 { 2385 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 2386 if (png_ptr->gamma_16_to_1 != NULL && 2387 png_ptr->gamma_16_from_1 != NULL) 2388 { 2389 png_bytep sp = row; 2390 png_bytep dp = row; 2391 for (i = 0; i < row_width; i++) 2392 { 2393 png_uint_16 red, green, blue, w; 2394 2395 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 2396 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 2397 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 2398 2399 if (red == green && red == blue) 2400 w = red; 2401 else 2402 { 2403 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> 2404 png_ptr->gamma_shift][red>>8]; 2405 png_uint_16 green_1 = 2406 png_ptr->gamma_16_to_1[(green&0xff) >> 2407 png_ptr->gamma_shift][green>>8]; 2408 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> 2409 png_ptr->gamma_shift][blue>>8]; 2410 png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 2411 + bc*blue_1)>>15); 2412 w = png_ptr->gamma_16_from_1[(gray16&0xff) >> 2413 png_ptr->gamma_shift][gray16 >> 8]; 2414 rgb_error |= 1; 2415 } 2416 2417 *(dp++) = (png_byte)((w>>8) & 0xff); 2418 *(dp++) = (png_byte)(w & 0xff); 2419 } 2420 } 2421 else 2422 #endif 2423 { 2424 png_bytep sp = row; 2425 png_bytep dp = row; 2426 for (i = 0; i < row_width; i++) 2427 { 2428 png_uint_16 red, green, blue, gray16; 2429 2430 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 2431 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 2432 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 2433 2434 if (red != green || red != blue) 2435 rgb_error |= 1; 2436 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); 2437 *(dp++) = (png_byte)((gray16>>8) & 0xff); 2438 *(dp++) = (png_byte)(gray16 & 0xff); 2439 } 2440 } 2441 } 2442 } 2443 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 2444 { 2445 if (row_info->bit_depth == 8) 2446 { 2447 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 2448 if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) 2449 { 2450 png_bytep sp = row; 2451 png_bytep dp = row; 2452 for (i = 0; i < row_width; i++) 2453 { 2454 png_byte red = png_ptr->gamma_to_1[*(sp++)]; 2455 png_byte green = png_ptr->gamma_to_1[*(sp++)]; 2456 png_byte blue = png_ptr->gamma_to_1[*(sp++)]; 2457 if (red != green || red != blue) 2458 rgb_error |= 1; 2459 *(dp++) = png_ptr->gamma_from_1 2460 [(rc*red + gc*green + bc*blue)>>15]; 2461 *(dp++) = *(sp++); /* alpha */ 2462 } 2463 } 2464 else 2465 #endif 2466 { 2467 png_bytep sp = row; 2468 png_bytep dp = row; 2469 for (i = 0; i < row_width; i++) 2470 { 2471 png_byte red = *(sp++); 2472 png_byte green = *(sp++); 2473 png_byte blue = *(sp++); 2474 if (red != green || red != blue) 2475 rgb_error |= 1; 2476 *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); 2477 *(dp++) = *(sp++); /* alpha */ 2478 } 2479 } 2480 } 2481 else /* RGBA bit_depth == 16 */ 2482 { 2483 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 2484 if (png_ptr->gamma_16_to_1 != NULL && 2485 png_ptr->gamma_16_from_1 != NULL) 2486 { 2487 png_bytep sp = row; 2488 png_bytep dp = row; 2489 for (i = 0; i < row_width; i++) 2490 { 2491 png_uint_16 red, green, blue, w; 2492 2493 red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 2494 green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 2495 blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; 2496 2497 if (red == green && red == blue) 2498 w = red; 2499 else 2500 { 2501 png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> 2502 png_ptr->gamma_shift][red>>8]; 2503 png_uint_16 green_1 = 2504 png_ptr->gamma_16_to_1[(green&0xff) >> 2505 png_ptr->gamma_shift][green>>8]; 2506 png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> 2507 png_ptr->gamma_shift][blue>>8]; 2508 png_uint_16 gray16 = (png_uint_16)((rc * red_1 2509 + gc * green_1 + bc * blue_1)>>15); 2510 w = png_ptr->gamma_16_from_1[(gray16&0xff) >> 2511 png_ptr->gamma_shift][gray16 >> 8]; 2512 rgb_error |= 1; 2513 } 2514 2515 *(dp++) = (png_byte)((w>>8) & 0xff); 2516 *(dp++) = (png_byte)(w & 0xff); 2517 *(dp++) = *(sp++); /* alpha */ 2518 *(dp++) = *(sp++); 2519 } 2520 } 2521 else 2522 #endif 2523 { 2524 png_bytep sp = row; 2525 png_bytep dp = row; 2526 for (i = 0; i < row_width; i++) 2527 { 2528 png_uint_16 red, green, blue, gray16; 2529 red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; 2530 green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; 2531 blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; 2532 if (red != green || red != blue) 2533 rgb_error |= 1; 2534 gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); 2535 *(dp++) = (png_byte)((gray16>>8) & 0xff); 2536 *(dp++) = (png_byte)(gray16 & 0xff); 2537 *(dp++) = *(sp++); /* alpha */ 2538 *(dp++) = *(sp++); 2539 } 2540 } 2541 } 2542 } 2543 row_info->channels -= (png_byte)2; 2544 row_info->color_type &= ~PNG_COLOR_MASK_COLOR; 2545 row_info->pixel_depth = (png_byte)(row_info->channels * 2546 row_info->bit_depth); 2547 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 2548 } 2549 return rgb_error; 2550 } 2551 #endif 2552 2553 /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth 2554 * large of png_color. This lets grayscale images be treated as 2555 * paletted. Most useful for gamma correction and simplification 2556 * of code. 2557 */ 2558 void PNGAPI 2559 png_build_grayscale_palette(int bit_depth, png_colorp palette) 2560 { 2561 int num_palette; 2562 int color_inc; 2563 int i; 2564 int v; 2565 2566 png_debug(1, "in png_do_build_grayscale_palette"); 2567 2568 if (palette == NULL) 2569 return; 2570 2571 switch (bit_depth) 2572 { 2573 case 1: 2574 num_palette = 2; 2575 color_inc = 0xff; 2576 break; 2577 2578 case 2: 2579 num_palette = 4; 2580 color_inc = 0x55; 2581 break; 2582 2583 case 4: 2584 num_palette = 16; 2585 color_inc = 0x11; 2586 break; 2587 2588 case 8: 2589 num_palette = 256; 2590 color_inc = 1; 2591 break; 2592 2593 default: 2594 num_palette = 0; 2595 color_inc = 0; 2596 break; 2597 } 2598 2599 for (i = 0, v = 0; i < num_palette; i++, v += color_inc) 2600 { 2601 palette[i].red = (png_byte)v; 2602 palette[i].green = (png_byte)v; 2603 palette[i].blue = (png_byte)v; 2604 } 2605 } 2606 2607 /* This function is currently unused. Do we really need it? */ 2608 #if defined(PNG_READ_DITHER_SUPPORTED) && \ 2609 defined(PNG_CORRECT_PALETTE_SUPPORTED) 2610 void /* PRIVATE */ 2611 png_correct_palette(png_structp png_ptr, png_colorp palette, 2612 int num_palette) 2613 { 2614 png_debug(1, "in png_correct_palette"); 2615 2616 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ 2617 defined(PNG_READ_GAMMA_SUPPORTED) && \ 2618 defined(PNG_FLOATING_POINT_SUPPORTED) 2619 if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) 2620 { 2621 png_color back, back_1; 2622 2623 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) 2624 { 2625 back.red = png_ptr->gamma_table[png_ptr->background.red]; 2626 back.green = png_ptr->gamma_table[png_ptr->background.green]; 2627 back.blue = png_ptr->gamma_table[png_ptr->background.blue]; 2628 2629 back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; 2630 back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; 2631 back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; 2632 } 2633 else 2634 { 2635 double g; 2636 2637 g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); 2638 2639 if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN 2640 || fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) 2641 { 2642 back.red = png_ptr->background.red; 2643 back.green = png_ptr->background.green; 2644 back.blue = png_ptr->background.blue; 2645 } 2646 else 2647 { 2648 back.red = 2649 (png_byte)(pow((double)png_ptr->background.red/255, g) * 2650 255.0 + 0.5); 2651 back.green = 2652 (png_byte)(pow((double)png_ptr->background.green/255, g) * 2653 255.0 + 0.5); 2654 back.blue = 2655 (png_byte)(pow((double)png_ptr->background.blue/255, g) * 2656 255.0 + 0.5); 2657 } 2658 2659 g = 1.0 / png_ptr->background_gamma; 2660 2661 back_1.red = 2662 (png_byte)(pow((double)png_ptr->background.red/255, g) * 2663 255.0 + 0.5); 2664 back_1.green = 2665 (png_byte)(pow((double)png_ptr->background.green/255, g) * 2666 255.0 + 0.5); 2667 back_1.blue = 2668 (png_byte)(pow((double)png_ptr->background.blue/255, g) * 2669 255.0 + 0.5); 2670 } 2671 2672 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 2673 { 2674 png_uint_32 i; 2675 2676 for (i = 0; i < (png_uint_32)num_palette; i++) 2677 { 2678 if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) 2679 { 2680 palette[i] = back; 2681 } 2682 else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) 2683 { 2684 png_byte v, w; 2685 2686 v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; 2687 png_composite(w, v, png_ptr->trans[i], back_1.red); 2688 palette[i].red = png_ptr->gamma_from_1[w]; 2689 2690 v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; 2691 png_composite(w, v, png_ptr->trans[i], back_1.green); 2692 palette[i].green = png_ptr->gamma_from_1[w]; 2693 2694 v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; 2695 png_composite(w, v, png_ptr->trans[i], back_1.blue); 2696 palette[i].blue = png_ptr->gamma_from_1[w]; 2697 } 2698 else 2699 { 2700 palette[i].red = png_ptr->gamma_table[palette[i].red]; 2701 palette[i].green = png_ptr->gamma_table[palette[i].green]; 2702 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 2703 } 2704 } 2705 } 2706 else 2707 { 2708 int i; 2709 2710 for (i = 0; i < num_palette; i++) 2711 { 2712 if (palette[i].red == (png_byte)png_ptr->trans_values.gray) 2713 { 2714 palette[i] = back; 2715 } 2716 else 2717 { 2718 palette[i].red = png_ptr->gamma_table[palette[i].red]; 2719 palette[i].green = png_ptr->gamma_table[palette[i].green]; 2720 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 2721 } 2722 } 2723 } 2724 } 2725 else 2726 #endif 2727 #ifdef PNG_READ_GAMMA_SUPPORTED 2728 if (png_ptr->transformations & PNG_GAMMA) 2729 { 2730 int i; 2731 2732 for (i = 0; i < num_palette; i++) 2733 { 2734 palette[i].red = png_ptr->gamma_table[palette[i].red]; 2735 palette[i].green = png_ptr->gamma_table[palette[i].green]; 2736 palette[i].blue = png_ptr->gamma_table[palette[i].blue]; 2737 } 2738 } 2739 #ifdef PNG_READ_BACKGROUND_SUPPORTED 2740 else 2741 #endif 2742 #endif 2743 #ifdef PNG_READ_BACKGROUND_SUPPORTED 2744 if (png_ptr->transformations & PNG_BACKGROUND) 2745 { 2746 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 2747 { 2748 png_color back; 2749 2750 back.red = (png_byte)png_ptr->background.red; 2751 back.green = (png_byte)png_ptr->background.green; 2752 back.blue = (png_byte)png_ptr->background.blue; 2753 2754 for (i = 0; i < (int)png_ptr->num_trans; i++) 2755 { 2756 if (png_ptr->trans[i] == 0) 2757 { 2758 palette[i].red = back.red; 2759 palette[i].green = back.green; 2760 palette[i].blue = back.blue; 2761 } 2762 else if (png_ptr->trans[i] != 0xff) 2763 { 2764 png_composite(palette[i].red, png_ptr->palette[i].red, 2765 png_ptr->trans[i], back.red); 2766 png_composite(palette[i].green, png_ptr->palette[i].green, 2767 png_ptr->trans[i], back.green); 2768 png_composite(palette[i].blue, png_ptr->palette[i].blue, 2769 png_ptr->trans[i], back.blue); 2770 } 2771 } 2772 } 2773 else /* Assume grayscale palette (what else could it be?) */ 2774 { 2775 int i; 2776 2777 for (i = 0; i < num_palette; i++) 2778 { 2779 if (i == (png_byte)png_ptr->trans_values.gray) 2780 { 2781 palette[i].red = (png_byte)png_ptr->background.red; 2782 palette[i].green = (png_byte)png_ptr->background.green; 2783 palette[i].blue = (png_byte)png_ptr->background.blue; 2784 } 2785 } 2786 } 2787 } 2788 #endif 2789 } 2790 #endif 2791 2792 #ifdef PNG_READ_BACKGROUND_SUPPORTED 2793 /* Replace any alpha or transparency with the supplied background color. 2794 * "background" is already in the screen gamma, while "background_1" is 2795 * at a gamma of 1.0. Paletted files have already been taken care of. 2796 */ 2797 void /* PRIVATE */ 2798 png_do_background(png_row_infop row_info, png_bytep row, 2799 png_color_16p trans_values, png_color_16p background 2800 #ifdef PNG_READ_GAMMA_SUPPORTED 2801 , png_color_16p background_1, 2802 png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, 2803 png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, 2804 png_uint_16pp gamma_16_to_1, int gamma_shift 2805 #endif 2806 ) 2807 { 2808 png_bytep sp, dp; 2809 png_uint_32 i; 2810 png_uint_32 row_width=row_info->width; 2811 int shift; 2812 2813 png_debug(1, "in png_do_background"); 2814 2815 if (background != NULL && 2816 #ifdef PNG_USELESS_TESTS_SUPPORTED 2817 row != NULL && row_info != NULL && 2818 #endif 2819 (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || 2820 (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) 2821 { 2822 switch (row_info->color_type) 2823 { 2824 case PNG_COLOR_TYPE_GRAY: 2825 { 2826 switch (row_info->bit_depth) 2827 { 2828 case 1: 2829 { 2830 sp = row; 2831 shift = 7; 2832 for (i = 0; i < row_width; i++) 2833 { 2834 if ((png_uint_16)((*sp >> shift) & 0x01) 2835 == trans_values->gray) 2836 { 2837 *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); 2838 *sp |= (png_byte)(background->gray << shift); 2839 } 2840 if (!shift) 2841 { 2842 shift = 7; 2843 sp++; 2844 } 2845 else 2846 shift--; 2847 } 2848 break; 2849 } 2850 2851 case 2: 2852 { 2853 #ifdef PNG_READ_GAMMA_SUPPORTED 2854 if (gamma_table != NULL) 2855 { 2856 sp = row; 2857 shift = 6; 2858 for (i = 0; i < row_width; i++) 2859 { 2860 if ((png_uint_16)((*sp >> shift) & 0x03) 2861 == trans_values->gray) 2862 { 2863 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 2864 *sp |= (png_byte)(background->gray << shift); 2865 } 2866 else 2867 { 2868 png_byte p = (png_byte)((*sp >> shift) & 0x03); 2869 png_byte g = (png_byte)((gamma_table [p | (p << 2) | 2870 (p << 4) | (p << 6)] >> 6) & 0x03); 2871 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 2872 *sp |= (png_byte)(g << shift); 2873 } 2874 if (!shift) 2875 { 2876 shift = 6; 2877 sp++; 2878 } 2879 else 2880 shift -= 2; 2881 } 2882 } 2883 else 2884 #endif 2885 { 2886 sp = row; 2887 shift = 6; 2888 for (i = 0; i < row_width; i++) 2889 { 2890 if ((png_uint_16)((*sp >> shift) & 0x03) 2891 == trans_values->gray) 2892 { 2893 *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); 2894 *sp |= (png_byte)(background->gray << shift); 2895 } 2896 if (!shift) 2897 { 2898 shift = 6; 2899 sp++; 2900 } 2901 else 2902 shift -= 2; 2903 } 2904 } 2905 break; 2906 } 2907 2908 case 4: 2909 { 2910 #ifdef PNG_READ_GAMMA_SUPPORTED 2911 if (gamma_table != NULL) 2912 { 2913 sp = row; 2914 shift = 4; 2915 for (i = 0; i < row_width; i++) 2916 { 2917 if ((png_uint_16)((*sp >> shift) & 0x0f) 2918 == trans_values->gray) 2919 { 2920 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 2921 *sp |= (png_byte)(background->gray << shift); 2922 } 2923 else 2924 { 2925 png_byte p = (png_byte)((*sp >> shift) & 0x0f); 2926 png_byte g = (png_byte)((gamma_table[p | 2927 (p << 4)] >> 4) & 0x0f); 2928 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 2929 *sp |= (png_byte)(g << shift); 2930 } 2931 if (!shift) 2932 { 2933 shift = 4; 2934 sp++; 2935 } 2936 else 2937 shift -= 4; 2938 } 2939 } 2940 else 2941 #endif 2942 { 2943 sp = row; 2944 shift = 4; 2945 for (i = 0; i < row_width; i++) 2946 { 2947 if ((png_uint_16)((*sp >> shift) & 0x0f) 2948 == trans_values->gray) 2949 { 2950 *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); 2951 *sp |= (png_byte)(background->gray << shift); 2952 } 2953 if (!shift) 2954 { 2955 shift = 4; 2956 sp++; 2957 } 2958 else 2959 shift -= 4; 2960 } 2961 } 2962 break; 2963 } 2964 2965 case 8: 2966 { 2967 #ifdef PNG_READ_GAMMA_SUPPORTED 2968 if (gamma_table != NULL) 2969 { 2970 sp = row; 2971 for (i = 0; i < row_width; i++, sp++) 2972 { 2973 if (*sp == trans_values->gray) 2974 { 2975 *sp = (png_byte)background->gray; 2976 } 2977 else 2978 { 2979 *sp = gamma_table[*sp]; 2980 } 2981 } 2982 } 2983 else 2984 #endif 2985 { 2986 sp = row; 2987 for (i = 0; i < row_width; i++, sp++) 2988 { 2989 if (*sp == trans_values->gray) 2990 { 2991 *sp = (png_byte)background->gray; 2992 } 2993 } 2994 } 2995 break; 2996 } 2997 2998 case 16: 2999 { 3000 #ifdef PNG_READ_GAMMA_SUPPORTED 3001 if (gamma_16 != NULL) 3002 { 3003 sp = row; 3004 for (i = 0; i < row_width; i++, sp += 2) 3005 { 3006 png_uint_16 v; 3007 3008 v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 3009 if (v == trans_values->gray) 3010 { 3011 /* Background is already in screen gamma */ 3012 *sp = (png_byte)((background->gray >> 8) & 0xff); 3013 *(sp + 1) = (png_byte)(background->gray & 0xff); 3014 } 3015 else 3016 { 3017 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 3018 *sp = (png_byte)((v >> 8) & 0xff); 3019 *(sp + 1) = (png_byte)(v & 0xff); 3020 } 3021 } 3022 } 3023 else 3024 #endif 3025 { 3026 sp = row; 3027 for (i = 0; i < row_width; i++, sp += 2) 3028 { 3029 png_uint_16 v; 3030 3031 v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 3032 if (v == trans_values->gray) 3033 { 3034 *sp = (png_byte)((background->gray >> 8) & 0xff); 3035 *(sp + 1) = (png_byte)(background->gray & 0xff); 3036 } 3037 } 3038 } 3039 break; 3040 } 3041 } 3042 break; 3043 } 3044 3045 case PNG_COLOR_TYPE_RGB: 3046 { 3047 if (row_info->bit_depth == 8) 3048 { 3049 #ifdef PNG_READ_GAMMA_SUPPORTED 3050 if (gamma_table != NULL) 3051 { 3052 sp = row; 3053 for (i = 0; i < row_width; i++, sp += 3) 3054 { 3055 if (*sp == trans_values->red && 3056 *(sp + 1) == trans_values->green && 3057 *(sp + 2) == trans_values->blue) 3058 { 3059 *sp = (png_byte)background->red; 3060 *(sp + 1) = (png_byte)background->green; 3061 *(sp + 2) = (png_byte)background->blue; 3062 } 3063 else 3064 { 3065 *sp = gamma_table[*sp]; 3066 *(sp + 1) = gamma_table[*(sp + 1)]; 3067 *(sp + 2) = gamma_table[*(sp + 2)]; 3068 } 3069 } 3070 } 3071 else 3072 #endif 3073 { 3074 sp = row; 3075 for (i = 0; i < row_width; i++, sp += 3) 3076 { 3077 if (*sp == trans_values->red && 3078 *(sp + 1) == trans_values->green && 3079 *(sp + 2) == trans_values->blue) 3080 { 3081 *sp = (png_byte)background->red; 3082 *(sp + 1) = (png_byte)background->green; 3083 *(sp + 2) = (png_byte)background->blue; 3084 } 3085 } 3086 } 3087 } 3088 else /* if (row_info->bit_depth == 16) */ 3089 { 3090 #ifdef PNG_READ_GAMMA_SUPPORTED 3091 if (gamma_16 != NULL) 3092 { 3093 sp = row; 3094 for (i = 0; i < row_width; i++, sp += 6) 3095 { 3096 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 3097 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); 3098 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); 3099 if (r == trans_values->red && g == trans_values->green && 3100 b == trans_values->blue) 3101 { 3102 /* Background is already in screen gamma */ 3103 *sp = (png_byte)((background->red >> 8) & 0xff); 3104 *(sp + 1) = (png_byte)(background->red & 0xff); 3105 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); 3106 *(sp + 3) = (png_byte)(background->green & 0xff); 3107 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); 3108 *(sp + 5) = (png_byte)(background->blue & 0xff); 3109 } 3110 else 3111 { 3112 png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 3113 *sp = (png_byte)((v >> 8) & 0xff); 3114 *(sp + 1) = (png_byte)(v & 0xff); 3115 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; 3116 *(sp + 2) = (png_byte)((v >> 8) & 0xff); 3117 *(sp + 3) = (png_byte)(v & 0xff); 3118 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; 3119 *(sp + 4) = (png_byte)((v >> 8) & 0xff); 3120 *(sp + 5) = (png_byte)(v & 0xff); 3121 } 3122 } 3123 } 3124 else 3125 #endif 3126 { 3127 sp = row; 3128 for (i = 0; i < row_width; i++, sp += 6) 3129 { 3130 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); 3131 png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); 3132 png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); 3133 3134 if (r == trans_values->red && g == trans_values->green && 3135 b == trans_values->blue) 3136 { 3137 *sp = (png_byte)((background->red >> 8) & 0xff); 3138 *(sp + 1) = (png_byte)(background->red & 0xff); 3139 *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); 3140 *(sp + 3) = (png_byte)(background->green & 0xff); 3141 *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); 3142 *(sp + 5) = (png_byte)(background->blue & 0xff); 3143 } 3144 } 3145 } 3146 } 3147 break; 3148 } 3149 3150 case PNG_COLOR_TYPE_GRAY_ALPHA: 3151 { 3152 if (row_info->bit_depth == 8) 3153 { 3154 #ifdef PNG_READ_GAMMA_SUPPORTED 3155 if (gamma_to_1 != NULL && gamma_from_1 != NULL && 3156 gamma_table != NULL) 3157 { 3158 sp = row; 3159 dp = row; 3160 for (i = 0; i < row_width; i++, sp += 2, dp++) 3161 { 3162 png_uint_16 a = *(sp + 1); 3163 3164 if (a == 0xff) 3165 { 3166 *dp = gamma_table[*sp]; 3167 } 3168 else if (a == 0) 3169 { 3170 /* Background is already in screen gamma */ 3171 *dp = (png_byte)background->gray; 3172 } 3173 else 3174 { 3175 png_byte v, w; 3176 3177 v = gamma_to_1[*sp]; 3178 png_composite(w, v, a, background_1->gray); 3179 *dp = gamma_from_1[w]; 3180 } 3181 } 3182 } 3183 else 3184 #endif 3185 { 3186 sp = row; 3187 dp = row; 3188 for (i = 0; i < row_width; i++, sp += 2, dp++) 3189 { 3190 png_byte a = *(sp + 1); 3191 3192 if (a == 0xff) 3193 { 3194 *dp = *sp; 3195 } 3196 #ifdef PNG_READ_GAMMA_SUPPORTED 3197 else if (a == 0) 3198 { 3199 *dp = (png_byte)background->gray; 3200 } 3201 else 3202 { 3203 png_composite(*dp, *sp, a, background_1->gray); 3204 } 3205 #else 3206 *dp = (png_byte)background->gray; 3207 #endif 3208 } 3209 } 3210 } 3211 else /* if (png_ptr->bit_depth == 16) */ 3212 { 3213 #ifdef PNG_READ_GAMMA_SUPPORTED 3214 if (gamma_16 != NULL && gamma_16_from_1 != NULL && 3215 gamma_16_to_1 != NULL) 3216 { 3217 sp = row; 3218 dp = row; 3219 for (i = 0; i < row_width; i++, sp += 4, dp += 2) 3220 { 3221 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); 3222 3223 if (a == (png_uint_16)0xffff) 3224 { 3225 png_uint_16 v; 3226 3227 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 3228 *dp = (png_byte)((v >> 8) & 0xff); 3229 *(dp + 1) = (png_byte)(v & 0xff); 3230 } 3231 #ifdef PNG_READ_GAMMA_SUPPORTED 3232 else if (a == 0) 3233 #else 3234 else 3235 #endif 3236 { 3237 /* Background is already in screen gamma */ 3238 *dp = (png_byte)((background->gray >> 8) & 0xff); 3239 *(dp + 1) = (png_byte)(background->gray & 0xff); 3240 } 3241 #ifdef PNG_READ_GAMMA_SUPPORTED 3242 else 3243 { 3244 png_uint_16 g, v, w; 3245 3246 g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; 3247 png_composite_16(v, g, a, background_1->gray); 3248 w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; 3249 *dp = (png_byte)((w >> 8) & 0xff); 3250 *(dp + 1) = (png_byte)(w & 0xff); 3251 } 3252 #endif 3253 } 3254 } 3255 else 3256 #endif 3257 { 3258 sp = row; 3259 dp = row; 3260 for (i = 0; i < row_width; i++, sp += 4, dp += 2) 3261 { 3262 png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); 3263 if (a == (png_uint_16)0xffff) 3264 { 3265 png_memcpy(dp, sp, 2); 3266 } 3267 #ifdef PNG_READ_GAMMA_SUPPORTED 3268 else if (a == 0) 3269 #else 3270 else 3271 #endif 3272 { 3273 *dp = (png_byte)((background->gray >> 8) & 0xff); 3274 *(dp + 1) = (png_byte)(background->gray & 0xff); 3275 } 3276 #ifdef PNG_READ_GAMMA_SUPPORTED 3277 else 3278 { 3279 png_uint_16 g, v; 3280 3281 g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 3282 png_composite_16(v, g, a, background_1->gray); 3283 *dp = (png_byte)((v >> 8) & 0xff); 3284 *(dp + 1) = (png_byte)(v & 0xff); 3285 } 3286 #endif 3287 } 3288 } 3289 } 3290 break; 3291 } 3292 3293 case PNG_COLOR_TYPE_RGB_ALPHA: 3294 { 3295 if (row_info->bit_depth == 8) 3296 { 3297 #ifdef PNG_READ_GAMMA_SUPPORTED 3298 if (gamma_to_1 != NULL && gamma_from_1 != NULL && 3299 gamma_table != NULL) 3300 { 3301 sp = row; 3302 dp = row; 3303 for (i = 0; i < row_width; i++, sp += 4, dp += 3) 3304 { 3305 png_byte a = *(sp + 3); 3306 3307 if (a == 0xff) 3308 { 3309 *dp = gamma_table[*sp]; 3310 *(dp + 1) = gamma_table[*(sp + 1)]; 3311 *(dp + 2) = gamma_table[*(sp + 2)]; 3312 } 3313 else if (a == 0) 3314 { 3315 /* Background is already in screen gamma */ 3316 *dp = (png_byte)background->red; 3317 *(dp + 1) = (png_byte)background->green; 3318 *(dp + 2) = (png_byte)background->blue; 3319 } 3320 else 3321 { 3322 png_byte v, w; 3323 3324 v = gamma_to_1[*sp]; 3325 png_composite(w, v, a, background_1->red); 3326 *dp = gamma_from_1[w]; 3327 v = gamma_to_1[*(sp + 1)]; 3328 png_composite(w, v, a, background_1->green); 3329 *(dp + 1) = gamma_from_1[w]; 3330 v = gamma_to_1[*(sp + 2)]; 3331 png_composite(w, v, a, background_1->blue); 3332 *(dp + 2) = gamma_from_1[w]; 3333 } 3334 } 3335 } 3336 else 3337 #endif 3338 { 3339 sp = row; 3340 dp = row; 3341 for (i = 0; i < row_width; i++, sp += 4, dp += 3) 3342 { 3343 png_byte a = *(sp + 3); 3344 3345 if (a == 0xff) 3346 { 3347 *dp = *sp; 3348 *(dp + 1) = *(sp + 1); 3349 *(dp + 2) = *(sp + 2); 3350 } 3351 else if (a == 0) 3352 { 3353 *dp = (png_byte)background->red; 3354 *(dp + 1) = (png_byte)background->green; 3355 *(dp + 2) = (png_byte)background->blue; 3356 } 3357 else 3358 { 3359 png_composite(*dp, *sp, a, background->red); 3360 png_composite(*(dp + 1), *(sp + 1), a, 3361 background->green); 3362 png_composite(*(dp + 2), *(sp + 2), a, 3363 background->blue); 3364 } 3365 } 3366 } 3367 } 3368 else /* if (row_info->bit_depth == 16) */ 3369 { 3370 #ifdef PNG_READ_GAMMA_SUPPORTED 3371 if (gamma_16 != NULL && gamma_16_from_1 != NULL && 3372 gamma_16_to_1 != NULL) 3373 { 3374 sp = row; 3375 dp = row; 3376 for (i = 0; i < row_width; i++, sp += 8, dp += 6) 3377 { 3378 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) 3379 << 8) + (png_uint_16)(*(sp + 7))); 3380 if (a == (png_uint_16)0xffff) 3381 { 3382 png_uint_16 v; 3383 3384 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; 3385 *dp = (png_byte)((v >> 8) & 0xff); 3386 *(dp + 1) = (png_byte)(v & 0xff); 3387 v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; 3388 *(dp + 2) = (png_byte)((v >> 8) & 0xff); 3389 *(dp + 3) = (png_byte)(v & 0xff); 3390 v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; 3391 *(dp + 4) = (png_byte)((v >> 8) & 0xff); 3392 *(dp + 5) = (png_byte)(v & 0xff); 3393 } 3394 else if (a == 0) 3395 { 3396 /* Background is already in screen gamma */ 3397 *dp = (png_byte)((background->red >> 8) & 0xff); 3398 *(dp + 1) = (png_byte)(background->red & 0xff); 3399 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); 3400 *(dp + 3) = (png_byte)(background->green & 0xff); 3401 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); 3402 *(dp + 5) = (png_byte)(background->blue & 0xff); 3403 } 3404 else 3405 { 3406 png_uint_16 v, w, x; 3407 3408 v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; 3409 png_composite_16(w, v, a, background_1->red); 3410 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; 3411 *dp = (png_byte)((x >> 8) & 0xff); 3412 *(dp + 1) = (png_byte)(x & 0xff); 3413 v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; 3414 png_composite_16(w, v, a, background_1->green); 3415 x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; 3416 *(dp + 2) = (png_byte)((x >> 8) & 0xff); 3417 *(dp + 3) = (png_byte)(x & 0xff); 3418 v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; 3419 png_composite_16(w, v, a, background_1->blue); 3420 x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; 3421 *(dp + 4) = (png_byte)((x >> 8) & 0xff); 3422 *(dp + 5) = (png_byte)(x & 0xff); 3423 } 3424 } 3425 } 3426 else 3427 #endif 3428 { 3429 sp = row; 3430 dp = row; 3431 for (i = 0; i < row_width; i++, sp += 8, dp += 6) 3432 { 3433 png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) 3434 << 8) + (png_uint_16)(*(sp + 7))); 3435 if (a == (png_uint_16)0xffff) 3436 { 3437 png_memcpy(dp, sp, 6); 3438 } 3439 else if (a == 0) 3440 { 3441 *dp = (png_byte)((background->red >> 8) & 0xff); 3442 *(dp + 1) = (png_byte)(background->red & 0xff); 3443 *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); 3444 *(dp + 3) = (png_byte)(background->green & 0xff); 3445 *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); 3446 *(dp + 5) = (png_byte)(background->blue & 0xff); 3447 } 3448 else 3449 { 3450 png_uint_16 v; 3451 3452 png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); 3453 png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) 3454 + *(sp + 3)); 3455 png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) 3456 + *(sp + 5)); 3457 3458 png_composite_16(v, r, a, background->red); 3459 *dp = (png_byte)((v >> 8) & 0xff); 3460 *(dp + 1) = (png_byte)(v & 0xff); 3461 png_composite_16(v, g, a, background->green); 3462 *(dp + 2) = (png_byte)((v >> 8) & 0xff); 3463 *(dp + 3) = (png_byte)(v & 0xff); 3464 png_composite_16(v, b, a, background->blue); 3465 *(dp + 4) = (png_byte)((v >> 8) & 0xff); 3466 *(dp + 5) = (png_byte)(v & 0xff); 3467 } 3468 } 3469 } 3470 } 3471 break; 3472 } 3473 } 3474 3475 if (row_info->color_type & PNG_COLOR_MASK_ALPHA) 3476 { 3477 row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; 3478 row_info->channels--; 3479 row_info->pixel_depth = (png_byte)(row_info->channels * 3480 row_info->bit_depth); 3481 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 3482 } 3483 } 3484 } 3485 #endif 3486 3487 #ifdef PNG_READ_GAMMA_SUPPORTED 3488 /* Gamma correct the image, avoiding the alpha channel. Make sure 3489 * you do this after you deal with the transparency issue on grayscale 3490 * or RGB images. If your bit depth is 8, use gamma_table, if it 3491 * is 16, use gamma_16_table and gamma_shift. Build these with 3492 * build_gamma_table(). 3493 */ 3494 void /* PRIVATE */ 3495 png_do_gamma(png_row_infop row_info, png_bytep row, 3496 png_bytep gamma_table, png_uint_16pp gamma_16_table, 3497 int gamma_shift) 3498 { 3499 png_bytep sp; 3500 png_uint_32 i; 3501 png_uint_32 row_width=row_info->width; 3502 3503 png_debug(1, "in png_do_gamma"); 3504 3505 if ( 3506 #ifdef PNG_USELESS_TESTS_SUPPORTED 3507 row != NULL && row_info != NULL && 3508 #endif 3509 ((row_info->bit_depth <= 8 && gamma_table != NULL) || 3510 (row_info->bit_depth == 16 && gamma_16_table != NULL))) 3511 { 3512 switch (row_info->color_type) 3513 { 3514 case PNG_COLOR_TYPE_RGB: 3515 { 3516 if (row_info->bit_depth == 8) 3517 { 3518 sp = row; 3519 for (i = 0; i < row_width; i++) 3520 { 3521 *sp = gamma_table[*sp]; 3522 sp++; 3523 *sp = gamma_table[*sp]; 3524 sp++; 3525 *sp = gamma_table[*sp]; 3526 sp++; 3527 } 3528 } 3529 else /* if (row_info->bit_depth == 16) */ 3530 { 3531 sp = row; 3532 for (i = 0; i < row_width; i++) 3533 { 3534 png_uint_16 v; 3535 3536 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 3537 *sp = (png_byte)((v >> 8) & 0xff); 3538 *(sp + 1) = (png_byte)(v & 0xff); 3539 sp += 2; 3540 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 3541 *sp = (png_byte)((v >> 8) & 0xff); 3542 *(sp + 1) = (png_byte)(v & 0xff); 3543 sp += 2; 3544 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 3545 *sp = (png_byte)((v >> 8) & 0xff); 3546 *(sp + 1) = (png_byte)(v & 0xff); 3547 sp += 2; 3548 } 3549 } 3550 break; 3551 } 3552 3553 case PNG_COLOR_TYPE_RGB_ALPHA: 3554 { 3555 if (row_info->bit_depth == 8) 3556 { 3557 sp = row; 3558 for (i = 0; i < row_width; i++) 3559 { 3560 *sp = gamma_table[*sp]; 3561 sp++; 3562 *sp = gamma_table[*sp]; 3563 sp++; 3564 *sp = gamma_table[*sp]; 3565 sp++; 3566 sp++; 3567 } 3568 } 3569 else /* if (row_info->bit_depth == 16) */ 3570 { 3571 sp = row; 3572 for (i = 0; i < row_width; i++) 3573 { 3574 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 3575 *sp = (png_byte)((v >> 8) & 0xff); 3576 *(sp + 1) = (png_byte)(v & 0xff); 3577 sp += 2; 3578 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 3579 *sp = (png_byte)((v >> 8) & 0xff); 3580 *(sp + 1) = (png_byte)(v & 0xff); 3581 sp += 2; 3582 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 3583 *sp = (png_byte)((v >> 8) & 0xff); 3584 *(sp + 1) = (png_byte)(v & 0xff); 3585 sp += 4; 3586 } 3587 } 3588 break; 3589 } 3590 3591 case PNG_COLOR_TYPE_GRAY_ALPHA: 3592 { 3593 if (row_info->bit_depth == 8) 3594 { 3595 sp = row; 3596 for (i = 0; i < row_width; i++) 3597 { 3598 *sp = gamma_table[*sp]; 3599 sp += 2; 3600 } 3601 } 3602 else /* if (row_info->bit_depth == 16) */ 3603 { 3604 sp = row; 3605 for (i = 0; i < row_width; i++) 3606 { 3607 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 3608 *sp = (png_byte)((v >> 8) & 0xff); 3609 *(sp + 1) = (png_byte)(v & 0xff); 3610 sp += 4; 3611 } 3612 } 3613 break; 3614 } 3615 3616 case PNG_COLOR_TYPE_GRAY: 3617 { 3618 if (row_info->bit_depth == 2) 3619 { 3620 sp = row; 3621 for (i = 0; i < row_width; i += 4) 3622 { 3623 int a = *sp & 0xc0; 3624 int b = *sp & 0x30; 3625 int c = *sp & 0x0c; 3626 int d = *sp & 0x03; 3627 3628 *sp = (png_byte)( 3629 ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| 3630 ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| 3631 ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| 3632 ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); 3633 sp++; 3634 } 3635 } 3636 3637 if (row_info->bit_depth == 4) 3638 { 3639 sp = row; 3640 for (i = 0; i < row_width; i += 2) 3641 { 3642 int msb = *sp & 0xf0; 3643 int lsb = *sp & 0x0f; 3644 3645 *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) 3646 | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); 3647 sp++; 3648 } 3649 } 3650 3651 else if (row_info->bit_depth == 8) 3652 { 3653 sp = row; 3654 for (i = 0; i < row_width; i++) 3655 { 3656 *sp = gamma_table[*sp]; 3657 sp++; 3658 } 3659 } 3660 3661 else if (row_info->bit_depth == 16) 3662 { 3663 sp = row; 3664 for (i = 0; i < row_width; i++) 3665 { 3666 png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; 3667 *sp = (png_byte)((v >> 8) & 0xff); 3668 *(sp + 1) = (png_byte)(v & 0xff); 3669 sp += 2; 3670 } 3671 } 3672 break; 3673 } 3674 } 3675 } 3676 } 3677 #endif 3678 3679 #ifdef PNG_READ_EXPAND_SUPPORTED 3680 /* Expands a palette row to an RGB or RGBA row depending 3681 * upon whether you supply trans and num_trans. 3682 */ 3683 void /* PRIVATE */ 3684 png_do_expand_palette(png_row_infop row_info, png_bytep row, 3685 png_colorp palette, png_bytep trans, int num_trans) 3686 { 3687 int shift, value; 3688 png_bytep sp, dp; 3689 png_uint_32 i; 3690 png_uint_32 row_width=row_info->width; 3691 3692 png_debug(1, "in png_do_expand_palette"); 3693 3694 if ( 3695 #ifdef PNG_USELESS_TESTS_SUPPORTED 3696 row != NULL && row_info != NULL && 3697 #endif 3698 row_info->color_type == PNG_COLOR_TYPE_PALETTE) 3699 { 3700 if (row_info->bit_depth < 8) 3701 { 3702 switch (row_info->bit_depth) 3703 { 3704 case 1: 3705 { 3706 sp = row + (png_size_t)((row_width - 1) >> 3); 3707 dp = row + (png_size_t)row_width - 1; 3708 shift = 7 - (int)((row_width + 7) & 0x07); 3709 for (i = 0; i < row_width; i++) 3710 { 3711 if ((*sp >> shift) & 0x01) 3712 *dp = 1; 3713 else 3714 *dp = 0; 3715 if (shift == 7) 3716 { 3717 shift = 0; 3718 sp--; 3719 } 3720 else 3721 shift++; 3722 3723 dp--; 3724 } 3725 break; 3726 } 3727 3728 case 2: 3729 { 3730 sp = row + (png_size_t)((row_width - 1) >> 2); 3731 dp = row + (png_size_t)row_width - 1; 3732 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 3733 for (i = 0; i < row_width; i++) 3734 { 3735 value = (*sp >> shift) & 0x03; 3736 *dp = (png_byte)value; 3737 if (shift == 6) 3738 { 3739 shift = 0; 3740 sp--; 3741 } 3742 else 3743 shift += 2; 3744 3745 dp--; 3746 } 3747 break; 3748 } 3749 3750 case 4: 3751 { 3752 sp = row + (png_size_t)((row_width - 1) >> 1); 3753 dp = row + (png_size_t)row_width - 1; 3754 shift = (int)((row_width & 0x01) << 2); 3755 for (i = 0; i < row_width; i++) 3756 { 3757 value = (*sp >> shift) & 0x0f; 3758 *dp = (png_byte)value; 3759 if (shift == 4) 3760 { 3761 shift = 0; 3762 sp--; 3763 } 3764 else 3765 shift += 4; 3766 3767 dp--; 3768 } 3769 break; 3770 } 3771 } 3772 row_info->bit_depth = 8; 3773 row_info->pixel_depth = 8; 3774 row_info->rowbytes = row_width; 3775 } 3776 switch (row_info->bit_depth) 3777 { 3778 case 8: 3779 { 3780 if (trans != NULL) 3781 { 3782 sp = row + (png_size_t)row_width - 1; 3783 dp = row + (png_size_t)(row_width << 2) - 1; 3784 3785 for (i = 0; i < row_width; i++) 3786 { 3787 if ((int)(*sp) >= num_trans) 3788 *dp-- = 0xff; 3789 else 3790 *dp-- = trans[*sp]; 3791 *dp-- = palette[*sp].blue; 3792 *dp-- = palette[*sp].green; 3793 *dp-- = palette[*sp].red; 3794 sp--; 3795 } 3796 row_info->bit_depth = 8; 3797 row_info->pixel_depth = 32; 3798 row_info->rowbytes = row_width * 4; 3799 row_info->color_type = 6; 3800 row_info->channels = 4; 3801 } 3802 else 3803 { 3804 sp = row + (png_size_t)row_width - 1; 3805 dp = row + (png_size_t)(row_width * 3) - 1; 3806 3807 for (i = 0; i < row_width; i++) 3808 { 3809 *dp-- = palette[*sp].blue; 3810 *dp-- = palette[*sp].green; 3811 *dp-- = palette[*sp].red; 3812 sp--; 3813 } 3814 3815 row_info->bit_depth = 8; 3816 row_info->pixel_depth = 24; 3817 row_info->rowbytes = row_width * 3; 3818 row_info->color_type = 2; 3819 row_info->channels = 3; 3820 } 3821 break; 3822 } 3823 } 3824 } 3825 } 3826 3827 /* If the bit depth < 8, it is expanded to 8. Also, if the already 3828 * expanded transparency value is supplied, an alpha channel is built. 3829 */ 3830 void /* PRIVATE */ 3831 png_do_expand(png_row_infop row_info, png_bytep row, 3832 png_color_16p trans_value) 3833 { 3834 int shift, value; 3835 png_bytep sp, dp; 3836 png_uint_32 i; 3837 png_uint_32 row_width=row_info->width; 3838 3839 png_debug(1, "in png_do_expand"); 3840 3841 #ifdef PNG_USELESS_TESTS_SUPPORTED 3842 if (row != NULL && row_info != NULL) 3843 #endif 3844 { 3845 if (row_info->color_type == PNG_COLOR_TYPE_GRAY) 3846 { 3847 png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); 3848 3849 if (row_info->bit_depth < 8) 3850 { 3851 switch (row_info->bit_depth) 3852 { 3853 case 1: 3854 { 3855 gray = (png_uint_16)((gray&0x01)*0xff); 3856 sp = row + (png_size_t)((row_width - 1) >> 3); 3857 dp = row + (png_size_t)row_width - 1; 3858 shift = 7 - (int)((row_width + 7) & 0x07); 3859 for (i = 0; i < row_width; i++) 3860 { 3861 if ((*sp >> shift) & 0x01) 3862 *dp = 0xff; 3863 else 3864 *dp = 0; 3865 if (shift == 7) 3866 { 3867 shift = 0; 3868 sp--; 3869 } 3870 else 3871 shift++; 3872 3873 dp--; 3874 } 3875 break; 3876 } 3877 3878 case 2: 3879 { 3880 gray = (png_uint_16)((gray&0x03)*0x55); 3881 sp = row + (png_size_t)((row_width - 1) >> 2); 3882 dp = row + (png_size_t)row_width - 1; 3883 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); 3884 for (i = 0; i < row_width; i++) 3885 { 3886 value = (*sp >> shift) & 0x03; 3887 *dp = (png_byte)(value | (value << 2) | (value << 4) | 3888 (value << 6)); 3889 if (shift == 6) 3890 { 3891 shift = 0; 3892 sp--; 3893 } 3894 else 3895 shift += 2; 3896 3897 dp--; 3898 } 3899 break; 3900 } 3901 3902 case 4: 3903 { 3904 gray = (png_uint_16)((gray&0x0f)*0x11); 3905 sp = row + (png_size_t)((row_width - 1) >> 1); 3906 dp = row + (png_size_t)row_width - 1; 3907 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); 3908 for (i = 0; i < row_width; i++) 3909 { 3910 value = (*sp >> shift) & 0x0f; 3911 *dp = (png_byte)(value | (value << 4)); 3912 if (shift == 4) 3913 { 3914 shift = 0; 3915 sp--; 3916 } 3917 else 3918 shift = 4; 3919 3920 dp--; 3921 } 3922 break; 3923 } 3924 } 3925 3926 row_info->bit_depth = 8; 3927 row_info->pixel_depth = 8; 3928 row_info->rowbytes = row_width; 3929 } 3930 3931 if (trans_value != NULL) 3932 { 3933 if (row_info->bit_depth == 8) 3934 { 3935 gray = gray & 0xff; 3936 sp = row + (png_size_t)row_width - 1; 3937 dp = row + (png_size_t)(row_width << 1) - 1; 3938 for (i = 0; i < row_width; i++) 3939 { 3940 if (*sp == gray) 3941 *dp-- = 0; 3942 else 3943 *dp-- = 0xff; 3944 *dp-- = *sp--; 3945 } 3946 } 3947 3948 else if (row_info->bit_depth == 16) 3949 { 3950 png_byte gray_high = (gray >> 8) & 0xff; 3951 png_byte gray_low = gray & 0xff; 3952 sp = row + row_info->rowbytes - 1; 3953 dp = row + (row_info->rowbytes << 1) - 1; 3954 for (i = 0; i < row_width; i++) 3955 { 3956 if (*(sp - 1) == gray_high && *(sp) == gray_low) 3957 { 3958 *dp-- = 0; 3959 *dp-- = 0; 3960 } 3961 else 3962 { 3963 *dp-- = 0xff; 3964 *dp-- = 0xff; 3965 } 3966 *dp-- = *sp--; 3967 *dp-- = *sp--; 3968 } 3969 } 3970 3971 row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; 3972 row_info->channels = 2; 3973 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); 3974 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 3975 row_width); 3976 } 3977 } 3978 else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) 3979 { 3980 if (row_info->bit_depth == 8) 3981 { 3982 png_byte red = trans_value->red & 0xff; 3983 png_byte green = trans_value->green & 0xff; 3984 png_byte blue = trans_value->blue & 0xff; 3985 sp = row + (png_size_t)row_info->rowbytes - 1; 3986 dp = row + (png_size_t)(row_width << 2) - 1; 3987 for (i = 0; i < row_width; i++) 3988 { 3989 if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) 3990 *dp-- = 0; 3991 else 3992 *dp-- = 0xff; 3993 *dp-- = *sp--; 3994 *dp-- = *sp--; 3995 *dp-- = *sp--; 3996 } 3997 } 3998 else if (row_info->bit_depth == 16) 3999 { 4000 png_byte red_high = (trans_value->red >> 8) & 0xff; 4001 png_byte green_high = (trans_value->green >> 8) & 0xff; 4002 png_byte blue_high = (trans_value->blue >> 8) & 0xff; 4003 png_byte red_low = trans_value->red & 0xff; 4004 png_byte green_low = trans_value->green & 0xff; 4005 png_byte blue_low = trans_value->blue & 0xff; 4006 sp = row + row_info->rowbytes - 1; 4007 dp = row + (png_size_t)(row_width << 3) - 1; 4008 for (i = 0; i < row_width; i++) 4009 { 4010 if (*(sp - 5) == red_high && 4011 *(sp - 4) == red_low && 4012 *(sp - 3) == green_high && 4013 *(sp - 2) == green_low && 4014 *(sp - 1) == blue_high && 4015 *(sp ) == blue_low) 4016 { 4017 *dp-- = 0; 4018 *dp-- = 0; 4019 } 4020 else 4021 { 4022 *dp-- = 0xff; 4023 *dp-- = 0xff; 4024 } 4025 *dp-- = *sp--; 4026 *dp-- = *sp--; 4027 *dp-- = *sp--; 4028 *dp-- = *sp--; 4029 *dp-- = *sp--; 4030 *dp-- = *sp--; 4031 } 4032 } 4033 row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; 4034 row_info->channels = 4; 4035 row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); 4036 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 4037 } 4038 } 4039 } 4040 #endif 4041 4042 #ifdef PNG_READ_DITHER_SUPPORTED 4043 void /* PRIVATE */ 4044 png_do_dither(png_row_infop row_info, png_bytep row, 4045 png_bytep palette_lookup, png_bytep dither_lookup) 4046 { 4047 png_bytep sp, dp; 4048 png_uint_32 i; 4049 png_uint_32 row_width=row_info->width; 4050 4051 png_debug(1, "in png_do_dither"); 4052 4053 #ifdef PNG_USELESS_TESTS_SUPPORTED 4054 if (row != NULL && row_info != NULL) 4055 #endif 4056 { 4057 if (row_info->color_type == PNG_COLOR_TYPE_RGB && 4058 palette_lookup && row_info->bit_depth == 8) 4059 { 4060 int r, g, b, p; 4061 sp = row; 4062 dp = row; 4063 for (i = 0; i < row_width; i++) 4064 { 4065 r = *sp++; 4066 g = *sp++; 4067 b = *sp++; 4068 4069 /* This looks real messy, but the compiler will reduce 4070 * it down to a reasonable formula. For example, with 4071 * 5 bits per color, we get: 4072 * p = (((r >> 3) & 0x1f) << 10) | 4073 * (((g >> 3) & 0x1f) << 5) | 4074 * ((b >> 3) & 0x1f); 4075 */ 4076 p = (((r >> (8 - PNG_DITHER_RED_BITS)) & 4077 ((1 << PNG_DITHER_RED_BITS) - 1)) << 4078 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | 4079 (((g >> (8 - PNG_DITHER_GREEN_BITS)) & 4080 ((1 << PNG_DITHER_GREEN_BITS) - 1)) << 4081 (PNG_DITHER_BLUE_BITS)) | 4082 ((b >> (8 - PNG_DITHER_BLUE_BITS)) & 4083 ((1 << PNG_DITHER_BLUE_BITS) - 1)); 4084 4085 *dp++ = palette_lookup[p]; 4086 } 4087 row_info->color_type = PNG_COLOR_TYPE_PALETTE; 4088 row_info->channels = 1; 4089 row_info->pixel_depth = row_info->bit_depth; 4090 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 4091 } 4092 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && 4093 palette_lookup != NULL && row_info->bit_depth == 8) 4094 { 4095 int r, g, b, p; 4096 sp = row; 4097 dp = row; 4098 for (i = 0; i < row_width; i++) 4099 { 4100 r = *sp++; 4101 g = *sp++; 4102 b = *sp++; 4103 sp++; 4104 4105 p = (((r >> (8 - PNG_DITHER_RED_BITS)) & 4106 ((1 << PNG_DITHER_RED_BITS) - 1)) << 4107 (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | 4108 (((g >> (8 - PNG_DITHER_GREEN_BITS)) & 4109 ((1 << PNG_DITHER_GREEN_BITS) - 1)) << 4110 (PNG_DITHER_BLUE_BITS)) | 4111 ((b >> (8 - PNG_DITHER_BLUE_BITS)) & 4112 ((1 << PNG_DITHER_BLUE_BITS) - 1)); 4113 4114 *dp++ = palette_lookup[p]; 4115 } 4116 row_info->color_type = PNG_COLOR_TYPE_PALETTE; 4117 row_info->channels = 1; 4118 row_info->pixel_depth = row_info->bit_depth; 4119 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); 4120 } 4121 else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && 4122 dither_lookup && row_info->bit_depth == 8) 4123 { 4124 sp = row; 4125 for (i = 0; i < row_width; i++, sp++) 4126 { 4127 *sp = dither_lookup[*sp]; 4128 } 4129 } 4130 } 4131 } 4132 #endif 4133 4134 #ifdef PNG_FLOATING_POINT_SUPPORTED 4135 #ifdef PNG_READ_GAMMA_SUPPORTED 4136 static PNG_CONST int png_gamma_shift[] = 4137 {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00}; 4138 4139 /* We build the 8- or 16-bit gamma tables here. Note that for 16-bit 4140 * tables, we don't make a full table if we are reducing to 8-bit in 4141 * the future. Note also how the gamma_16 tables are segmented so that 4142 * we don't need to allocate > 64K chunks for a full 16-bit table. 4143 * 4144 * See the PNG extensions document for an integer algorithm for creating 4145 * the gamma tables. Maybe we will implement that here someday. 4146 * 4147 * We should only reach this point if 4148 * 4149 * the file_gamma is known (i.e., the gAMA or sRGB chunk is present, 4150 * or the application has provided a file_gamma) 4151 * 4152 * AND 4153 * { 4154 * the screen_gamma is known 4155 * OR 4156 * 4157 * RGB_to_gray transformation is being performed 4158 * } 4159 * 4160 * AND 4161 * { 4162 * the screen_gamma is different from the reciprocal of the 4163 * file_gamma by more than the specified threshold 4164 * 4165 * OR 4166 * 4167 * a background color has been specified and the file_gamma 4168 * and screen_gamma are not 1.0, within the specified threshold. 4169 * } 4170 */ 4171 4172 void /* PRIVATE */ 4173 png_build_gamma_table(png_structp png_ptr) 4174 { 4175 png_debug(1, "in png_build_gamma_table"); 4176 4177 if (png_ptr->bit_depth <= 8) 4178 { 4179 int i; 4180 double g; 4181 4182 if (png_ptr->screen_gamma > .000001) 4183 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); 4184 4185 else 4186 g = 1.0; 4187 4188 png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, 4189 (png_uint_32)256); 4190 4191 for (i = 0; i < 256; i++) 4192 { 4193 png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, 4194 g) * 255.0 + .5); 4195 } 4196 4197 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ 4198 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 4199 if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) 4200 { 4201 4202 g = 1.0 / (png_ptr->gamma); 4203 4204 png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, 4205 (png_uint_32)256); 4206 4207 for (i = 0; i < 256; i++) 4208 { 4209 png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, 4210 g) * 255.0 + .5); 4211 } 4212 4213 4214 png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, 4215 (png_uint_32)256); 4216 4217 if (png_ptr->screen_gamma > 0.000001) 4218 g = 1.0 / png_ptr->screen_gamma; 4219 4220 else 4221 g = png_ptr->gamma; /* Probably doing rgb_to_gray */ 4222 4223 for (i = 0; i < 256; i++) 4224 { 4225 png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, 4226 g) * 255.0 + .5); 4227 4228 } 4229 } 4230 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ 4231 } 4232 else 4233 { 4234 double g; 4235 int i, j, shift, num; 4236 int sig_bit; 4237 png_uint_32 ig; 4238 4239 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) 4240 { 4241 sig_bit = (int)png_ptr->sig_bit.red; 4242 4243 if ((int)png_ptr->sig_bit.green > sig_bit) 4244 sig_bit = png_ptr->sig_bit.green; 4245 4246 if ((int)png_ptr->sig_bit.blue > sig_bit) 4247 sig_bit = png_ptr->sig_bit.blue; 4248 } 4249 else 4250 { 4251 sig_bit = (int)png_ptr->sig_bit.gray; 4252 } 4253 4254 if (sig_bit > 0) 4255 shift = 16 - sig_bit; 4256 4257 else 4258 shift = 0; 4259 4260 if (png_ptr->transformations & PNG_16_TO_8) 4261 { 4262 if (shift < (16 - PNG_MAX_GAMMA_8)) 4263 shift = (16 - PNG_MAX_GAMMA_8); 4264 } 4265 4266 if (shift > 8) 4267 shift = 8; 4268 4269 if (shift < 0) 4270 shift = 0; 4271 4272 png_ptr->gamma_shift = (png_byte)shift; 4273 4274 num = (1 << (8 - shift)); 4275 4276 if (png_ptr->screen_gamma > .000001) 4277 g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); 4278 else 4279 g = 1.0; 4280 4281 png_ptr->gamma_16_table = (png_uint_16pp)png_calloc(png_ptr, 4282 (png_uint_32)(num * png_sizeof(png_uint_16p))); 4283 4284 if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) 4285 { 4286 double fin, fout; 4287 png_uint_32 last, max; 4288 4289 for (i = 0; i < num; i++) 4290 { 4291 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, 4292 (png_uint_32)(256 * png_sizeof(png_uint_16))); 4293 } 4294 4295 g = 1.0 / g; 4296 last = 0; 4297 for (i = 0; i < 256; i++) 4298 { 4299 fout = ((double)i + 0.5) / 256.0; 4300 fin = pow(fout, g); 4301 max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); 4302 while (last <= max) 4303 { 4304 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] 4305 [(int)(last >> (8 - shift))] = (png_uint_16)( 4306 (png_uint_16)i | ((png_uint_16)i << 8)); 4307 last++; 4308 } 4309 } 4310 while (last < ((png_uint_32)num << 8)) 4311 { 4312 png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] 4313 [(int)(last >> (8 - shift))] = (png_uint_16)65535L; 4314 last++; 4315 } 4316 } 4317 else 4318 { 4319 for (i = 0; i < num; i++) 4320 { 4321 png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, 4322 (png_uint_32)(256 * png_sizeof(png_uint_16))); 4323 4324 ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); 4325 4326 for (j = 0; j < 256; j++) 4327 { 4328 png_ptr->gamma_16_table[i][j] = 4329 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / 4330 65535.0, g) * 65535.0 + .5); 4331 } 4332 } 4333 } 4334 4335 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ 4336 defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 4337 if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) 4338 { 4339 4340 g = 1.0 / (png_ptr->gamma); 4341 4342 png_ptr->gamma_16_to_1 = (png_uint_16pp)png_calloc(png_ptr, 4343 (png_uint_32)(num * png_sizeof(png_uint_16p ))); 4344 4345 for (i = 0; i < num; i++) 4346 { 4347 png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, 4348 (png_uint_32)(256 * png_sizeof(png_uint_16))); 4349 4350 ig = (((png_uint_32)i * 4351 (png_uint_32)png_gamma_shift[shift]) >> 4); 4352 for (j = 0; j < 256; j++) 4353 { 4354 png_ptr->gamma_16_to_1[i][j] = 4355 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / 4356 65535.0, g) * 65535.0 + .5); 4357 } 4358 } 4359 4360 if (png_ptr->screen_gamma > 0.000001) 4361 g = 1.0 / png_ptr->screen_gamma; 4362 4363 else 4364 g = png_ptr->gamma; /* Probably doing rgb_to_gray */ 4365 4366 png_ptr->gamma_16_from_1 = (png_uint_16pp)png_calloc(png_ptr, 4367 (png_uint_32)(num * png_sizeof(png_uint_16p))); 4368 4369 for (i = 0; i < num; i++) 4370 { 4371 png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, 4372 (png_uint_32)(256 * png_sizeof(png_uint_16))); 4373 4374 ig = (((png_uint_32)i * 4375 (png_uint_32)png_gamma_shift[shift]) >> 4); 4376 4377 for (j = 0; j < 256; j++) 4378 { 4379 png_ptr->gamma_16_from_1[i][j] = 4380 (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / 4381 65535.0, g) * 65535.0 + .5); 4382 } 4383 } 4384 } 4385 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ 4386 } 4387 } 4388 #endif 4389 /* To do: install integer version of png_build_gamma_table here */ 4390 #endif 4391 4392 #ifdef PNG_MNG_FEATURES_SUPPORTED 4393 /* Undoes intrapixel differencing */ 4394 void /* PRIVATE */ 4395 png_do_read_intrapixel(png_row_infop row_info, png_bytep row) 4396 { 4397 png_debug(1, "in png_do_read_intrapixel"); 4398 4399 if ( 4400 #ifdef PNG_USELESS_TESTS_SUPPORTED 4401 row != NULL && row_info != NULL && 4402 #endif 4403 (row_info->color_type & PNG_COLOR_MASK_COLOR)) 4404 { 4405 int bytes_per_pixel; 4406 png_uint_32 row_width = row_info->width; 4407 if (row_info->bit_depth == 8) 4408 { 4409 png_bytep rp; 4410 png_uint_32 i; 4411 4412 if (row_info->color_type == PNG_COLOR_TYPE_RGB) 4413 bytes_per_pixel = 3; 4414 4415 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 4416 bytes_per_pixel = 4; 4417 4418 else 4419 return; 4420 4421 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 4422 { 4423 *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); 4424 *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); 4425 } 4426 } 4427 else if (row_info->bit_depth == 16) 4428 { 4429 png_bytep rp; 4430 png_uint_32 i; 4431 4432 if (row_info->color_type == PNG_COLOR_TYPE_RGB) 4433 bytes_per_pixel = 6; 4434 4435 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 4436 bytes_per_pixel = 8; 4437 4438 else 4439 return; 4440 4441 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 4442 { 4443 png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); 4444 png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); 4445 png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); 4446 png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL); 4447 png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL); 4448 *(rp ) = (png_byte)((red >> 8) & 0xff); 4449 *(rp+1) = (png_byte)(red & 0xff); 4450 *(rp+4) = (png_byte)((blue >> 8) & 0xff); 4451 *(rp+5) = (png_byte)(blue & 0xff); 4452 } 4453 } 4454 } 4455 } 4456 #endif /* PNG_MNG_FEATURES_SUPPORTED */ 4457 #endif /* PNG_READ_SUPPORTED */ 4458