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