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