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