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