1 /*- 2 * pngstest.c 3 * 4 * Copyright (c) 2013-2016 John Cunningham Bowler 5 * 6 * Last changed in libpng 1.6.24 [August 4, 2016] 7 * 8 * This code is released under the libpng license. 9 * For conditions of distribution and use, see the disclaimer 10 * and license in png.h 11 * 12 * Test for the PNG 'simplified' APIs. 13 */ 14 #define _ISOC90_SOURCE 1 15 #define MALLOC_CHECK_ 2/*glibc facility: turn on debugging*/ 16 17 #include <stddef.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <stdio.h> 21 #include <errno.h> 22 #include <ctype.h> 23 #include <math.h> 24 25 #if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) 26 # include <config.h> 27 #endif 28 29 /* Define the following to use this test against your installed libpng, rather 30 * than the one being built here: 31 */ 32 #ifdef PNG_FREESTANDING_TESTS 33 # include <png.h> 34 #else 35 # include "../../png.h" 36 #endif 37 38 /* 1.6.1 added support for the configure test harness, which uses 77 to indicate 39 * a skipped test, in earlier versions we need to succeed on a skipped test, so: 40 */ 41 #if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H) 42 # define SKIP 77 43 #else 44 # define SKIP 0 45 #endif 46 47 #ifdef PNG_SIMPLIFIED_READ_SUPPORTED /* Else nothing can be done */ 48 #include "../tools/sRGB.h" 49 50 /* KNOWN ISSUES 51 * 52 * These defines switch on alternate algorithms for format conversions to match 53 * the current libpng implementation; they are set to allow pngstest to pass 54 * even though libpng is producing answers that are not as correct as they 55 * should be. 56 */ 57 #define ALLOW_UNUSED_GPC 0 58 /* If true include unused static GPC functions and declare an external array 59 * of them to hide the fact that they are unused. This is for development 60 * use while testing the correct function to use to take into account libpng 61 * misbehavior, such as using a simple power law to correct sRGB to linear. 62 */ 63 64 /* The following is to support direct compilation of this file as C++ */ 65 #ifdef __cplusplus 66 # define voidcast(type, value) static_cast<type>(value) 67 # define aligncastconst(type, value) \ 68 static_cast<type>(static_cast<const void*>(value)) 69 #else 70 # define voidcast(type, value) (value) 71 # define aligncastconst(type, value) ((const void*)(value)) 72 #endif /* __cplusplus */ 73 74 /* During parallel runs of pngstest each temporary file needs a unique name, 75 * this is used to permit uniqueness using a command line argument which can be 76 * up to 22 characters long. 77 */ 78 static char tmpf[23] = "TMP"; 79 80 /* Generate random bytes. This uses a boring repeatable algorithm and it 81 * is implemented here so that it gives the same set of numbers on every 82 * architecture. It's a linear congruential generator (Knuth or Sedgewick 83 * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and 84 * Hill, "The Art of Electronics". 85 */ 86 static void 87 make_random_bytes(png_uint_32* seed, void* pv, size_t size) 88 { 89 png_uint_32 u0 = seed[0], u1 = seed[1]; 90 png_bytep bytes = voidcast(png_bytep, pv); 91 92 /* There are thirty three bits, the next bit in the sequence is bit-33 XOR 93 * bit-20. The top 1 bit is in u1, the bottom 32 are in u0. 94 */ 95 size_t i; 96 for (i=0; i<size; ++i) 97 { 98 /* First generate 8 new bits then shift them in at the end. */ 99 png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff; 100 u1 <<= 8; 101 u1 |= u0 >> 24; 102 u0 <<= 8; 103 u0 |= u; 104 *bytes++ = (png_byte)u; 105 } 106 107 seed[0] = u0; 108 seed[1] = u1; 109 } 110 111 static png_uint_32 color_seed[2]; 112 113 static void 114 reseed(void) 115 { 116 color_seed[0] = 0x12345678U; 117 color_seed[1] = 0x9abcdefU; 118 } 119 120 static void 121 random_color(png_colorp color) 122 { 123 make_random_bytes(color_seed, color, sizeof *color); 124 } 125 126 /* Math support - neither Cygwin nor Visual Studio have C99 support and we need 127 * a predictable rounding function, so make one here: 128 */ 129 static double 130 closestinteger(double x) 131 { 132 return floor(x + .5); 133 } 134 135 /* Cast support: remove GCC whines. */ 136 static png_byte 137 u8d(double d) 138 { 139 d = closestinteger(d); 140 return (png_byte)d; 141 } 142 143 static png_uint_16 144 u16d(double d) 145 { 146 d = closestinteger(d); 147 return (png_uint_16)d; 148 } 149 150 /* sRGB support: use exact calculations rounded to the nearest int, see the 151 * fesetround() call in main(). sRGB_to_d optimizes the 8 to 16-bit conversion. 152 */ 153 static double sRGB_to_d[256]; 154 static double g22_to_d[256]; 155 156 static void 157 init_sRGB_to_d(void) 158 { 159 int i; 160 161 sRGB_to_d[0] = 0; 162 for (i=1; i<255; ++i) 163 sRGB_to_d[i] = linear_from_sRGB(i/255.); 164 sRGB_to_d[255] = 1; 165 166 g22_to_d[0] = 0; 167 for (i=1; i<255; ++i) 168 g22_to_d[i] = pow(i/255., 1/.45455); 169 g22_to_d[255] = 1; 170 } 171 172 static png_byte 173 sRGB(double linear /*range 0.0 .. 1.0*/) 174 { 175 return u8d(255 * sRGB_from_linear(linear)); 176 } 177 178 static png_byte 179 isRGB(int fixed_linear) 180 { 181 return sRGB(fixed_linear / 65535.); 182 } 183 184 #if 0 /* not used */ 185 static png_byte 186 unpremultiply(int component, int alpha) 187 { 188 if (alpha <= component) 189 return 255; /* Arbitrary, but consistent with the libpng code */ 190 191 else if (alpha >= 65535) 192 return isRGB(component); 193 194 else 195 return sRGB((double)component / alpha); 196 } 197 #endif 198 199 static png_uint_16 200 ilinear(int fixed_srgb) 201 { 202 return u16d(65535 * sRGB_to_d[fixed_srgb]); 203 } 204 205 static png_uint_16 206 ilineara(int fixed_srgb, int alpha) 207 { 208 return u16d((257 * alpha) * sRGB_to_d[fixed_srgb]); 209 } 210 211 static png_uint_16 212 ilinear_g22(int fixed_srgb) 213 { 214 return u16d(65535 * g22_to_d[fixed_srgb]); 215 } 216 217 #if ALLOW_UNUSED_GPC 218 static png_uint_16 219 ilineara_g22(int fixed_srgb, int alpha) 220 { 221 return u16d((257 * alpha) * g22_to_d[fixed_srgb]); 222 } 223 #endif 224 225 static double 226 YfromRGBint(int ir, int ig, int ib) 227 { 228 double r = ir; 229 double g = ig; 230 double b = ib; 231 return YfromRGB(r, g, b); 232 } 233 234 #if 0 /* unused */ 235 /* The error that results from using a 2.2 power law in place of the correct 236 * sRGB transform, given an 8-bit value which might be either sRGB or power-law. 237 */ 238 static int 239 power_law_error8(int value) 240 { 241 if (value > 0 && value < 255) 242 { 243 double vd = value / 255.; 244 double e = fabs( 245 pow(sRGB_to_d[value], 1/2.2) - sRGB_from_linear(pow(vd, 2.2))); 246 247 /* Always allow an extra 1 here for rounding errors */ 248 e = 1+floor(255 * e); 249 return (int)e; 250 } 251 252 return 0; 253 } 254 255 static int error_in_sRGB_roundtrip = 56; /* by experiment */ 256 static int 257 power_law_error16(int value) 258 { 259 if (value > 0 && value < 65535) 260 { 261 /* Round trip the value through an 8-bit representation but using 262 * non-matching to/from conversions. 263 */ 264 double vd = value / 65535.; 265 double e = fabs( 266 pow(sRGB_from_linear(vd), 2.2) - linear_from_sRGB(pow(vd, 1/2.2))); 267 268 /* Always allow an extra 1 here for rounding errors */ 269 e = error_in_sRGB_roundtrip+floor(65535 * e); 270 return (int)e; 271 } 272 273 return 0; 274 } 275 276 static int 277 compare_8bit(int v1, int v2, int error_limit, int multiple_algorithms) 278 { 279 int e = abs(v1-v2); 280 int ev1, ev2; 281 282 if (e <= error_limit) 283 return 1; 284 285 if (!multiple_algorithms) 286 return 0; 287 288 ev1 = power_law_error8(v1); 289 if (e <= ev1) 290 return 1; 291 292 ev2 = power_law_error8(v2); 293 if (e <= ev2) 294 return 1; 295 296 return 0; 297 } 298 299 static int 300 compare_16bit(int v1, int v2, int error_limit, int multiple_algorithms) 301 { 302 int e = abs(v1-v2); 303 int ev1, ev2; 304 305 if (e <= error_limit) 306 return 1; 307 308 /* "multiple_algorithms" in this case means that a color-map has been 309 * involved somewhere, so we can deduce that the values were forced to 8-bit 310 * (like the via_linear case for 8-bit.) 311 */ 312 if (!multiple_algorithms) 313 return 0; 314 315 ev1 = power_law_error16(v1); 316 if (e <= ev1) 317 return 1; 318 319 ev2 = power_law_error16(v2); 320 if (e <= ev2) 321 return 1; 322 323 return 0; 324 } 325 #endif /* unused */ 326 327 #define USE_FILE 1 /* else memory */ 328 #define USE_STDIO 2 /* else use file name */ 329 #define STRICT 4 /* fail on warnings too */ 330 #define VERBOSE 8 331 #define KEEP_TMPFILES 16 /* else delete temporary files */ 332 #define KEEP_GOING 32 333 #define ACCUMULATE 64 334 #define FAST_WRITE 128 335 #define sRGB_16BIT 256 336 #define NO_RESEED 512 /* do not reseed on each new file */ 337 #define GBG_ERROR 1024 /* do not ignore the gamma+background_rgb_to_gray 338 * libpng warning. */ 339 340 static void 341 print_opts(png_uint_32 opts) 342 { 343 if (opts & USE_FILE) 344 printf(" --file"); 345 if (opts & USE_STDIO) 346 printf(" --stdio"); 347 if (!(opts & STRICT)) 348 printf(" --nostrict"); 349 if (opts & VERBOSE) 350 printf(" --verbose"); 351 if (opts & KEEP_TMPFILES) 352 printf(" --preserve"); 353 if (opts & KEEP_GOING) 354 printf(" --keep-going"); 355 if (opts & ACCUMULATE) 356 printf(" --accumulate"); 357 if (!(opts & FAST_WRITE)) /* --fast is currently the default */ 358 printf(" --slow"); 359 if (opts & sRGB_16BIT) 360 printf(" --sRGB-16bit"); 361 if (opts & NO_RESEED) 362 printf(" --noreseed"); 363 #if PNG_LIBPNG_VER < 10700 /* else on by default */ 364 if (opts & GBG_ERROR) 365 printf(" --fault-gbg-warning"); 366 #endif 367 } 368 369 #define FORMAT_NO_CHANGE 0x80000000 /* additional flag */ 370 371 /* A name table for all the formats - defines the format of the '+' arguments to 372 * pngstest. 373 */ 374 #define FORMAT_COUNT 64 375 #define FORMAT_MASK 0x3f 376 static PNG_CONST char * PNG_CONST format_names[FORMAT_COUNT] = 377 { 378 "sRGB-gray", 379 "sRGB-gray+alpha", 380 "sRGB-rgb", 381 "sRGB-rgb+alpha", 382 "linear-gray", 383 "linear-gray+alpha", 384 "linear-rgb", 385 "linear-rgb+alpha", 386 387 "color-mapped-sRGB-gray", 388 "color-mapped-sRGB-gray+alpha", 389 "color-mapped-sRGB-rgb", 390 "color-mapped-sRGB-rgb+alpha", 391 "color-mapped-linear-gray", 392 "color-mapped-linear-gray+alpha", 393 "color-mapped-linear-rgb", 394 "color-mapped-linear-rgb+alpha", 395 396 "sRGB-gray", 397 "sRGB-gray+alpha", 398 "sRGB-bgr", 399 "sRGB-bgr+alpha", 400 "linear-gray", 401 "linear-gray+alpha", 402 "linear-bgr", 403 "linear-bgr+alpha", 404 405 "color-mapped-sRGB-gray", 406 "color-mapped-sRGB-gray+alpha", 407 "color-mapped-sRGB-bgr", 408 "color-mapped-sRGB-bgr+alpha", 409 "color-mapped-linear-gray", 410 "color-mapped-linear-gray+alpha", 411 "color-mapped-linear-bgr", 412 "color-mapped-linear-bgr+alpha", 413 414 "sRGB-gray", 415 "alpha+sRGB-gray", 416 "sRGB-rgb", 417 "alpha+sRGB-rgb", 418 "linear-gray", 419 "alpha+linear-gray", 420 "linear-rgb", 421 "alpha+linear-rgb", 422 423 "color-mapped-sRGB-gray", 424 "color-mapped-alpha+sRGB-gray", 425 "color-mapped-sRGB-rgb", 426 "color-mapped-alpha+sRGB-rgb", 427 "color-mapped-linear-gray", 428 "color-mapped-alpha+linear-gray", 429 "color-mapped-linear-rgb", 430 "color-mapped-alpha+linear-rgb", 431 432 "sRGB-gray", 433 "alpha+sRGB-gray", 434 "sRGB-bgr", 435 "alpha+sRGB-bgr", 436 "linear-gray", 437 "alpha+linear-gray", 438 "linear-bgr", 439 "alpha+linear-bgr", 440 441 "color-mapped-sRGB-gray", 442 "color-mapped-alpha+sRGB-gray", 443 "color-mapped-sRGB-bgr", 444 "color-mapped-alpha+sRGB-bgr", 445 "color-mapped-linear-gray", 446 "color-mapped-alpha+linear-gray", 447 "color-mapped-linear-bgr", 448 "color-mapped-alpha+linear-bgr", 449 }; 450 451 /* Decode an argument to a format number. */ 452 static png_uint_32 453 formatof(const char *arg) 454 { 455 char *ep; 456 unsigned long format = strtoul(arg, &ep, 0); 457 458 if (ep > arg && *ep == 0 && format < FORMAT_COUNT) 459 return (png_uint_32)format; 460 461 else for (format=0; format < FORMAT_COUNT; ++format) 462 { 463 if (strcmp(format_names[format], arg) == 0) 464 return (png_uint_32)format; 465 } 466 467 fprintf(stderr, "pngstest: format name '%s' invalid\n", arg); 468 return FORMAT_COUNT; 469 } 470 471 /* Bitset/test functions for formats */ 472 #define FORMAT_SET_COUNT (FORMAT_COUNT / 32) 473 typedef struct 474 { 475 png_uint_32 bits[FORMAT_SET_COUNT]; 476 } 477 format_list; 478 479 static void format_init(format_list *pf) 480 { 481 int i; 482 for (i=0; i<FORMAT_SET_COUNT; ++i) 483 pf->bits[i] = 0; /* All off */ 484 } 485 486 #if 0 /* currently unused */ 487 static void format_clear(format_list *pf) 488 { 489 int i; 490 for (i=0; i<FORMAT_SET_COUNT; ++i) 491 pf->bits[i] = 0; 492 } 493 #endif 494 495 static int format_is_initial(format_list *pf) 496 { 497 int i; 498 for (i=0; i<FORMAT_SET_COUNT; ++i) 499 if (pf->bits[i] != 0) 500 return 0; 501 502 return 1; 503 } 504 505 static int format_set(format_list *pf, png_uint_32 format) 506 { 507 if (format < FORMAT_COUNT) 508 return pf->bits[format >> 5] |= ((png_uint_32)1) << (format & 31); 509 510 return 0; 511 } 512 513 #if 0 /* currently unused */ 514 static int format_unset(format_list *pf, png_uint_32 format) 515 { 516 if (format < FORMAT_COUNT) 517 return pf->bits[format >> 5] &= ~((png_uint_32)1) << (format & 31); 518 519 return 0; 520 } 521 #endif 522 523 static int format_isset(format_list *pf, png_uint_32 format) 524 { 525 return format < FORMAT_COUNT && 526 (pf->bits[format >> 5] & (((png_uint_32)1) << (format & 31))) != 0; 527 } 528 529 static void format_default(format_list *pf, int redundant) 530 { 531 if (redundant) 532 { 533 int i; 534 535 /* set everything, including flags that are pointless */ 536 for (i=0; i<FORMAT_SET_COUNT; ++i) 537 pf->bits[i] = ~(png_uint_32)0; 538 } 539 540 else 541 { 542 png_uint_32 f; 543 544 for (f=0; f<FORMAT_COUNT; ++f) 545 { 546 /* Eliminate redundant and unsupported settings. */ 547 # ifdef PNG_FORMAT_BGR_SUPPORTED 548 /* BGR is meaningless if no color: */ 549 if ((f & PNG_FORMAT_FLAG_COLOR) == 0 && 550 (f & PNG_FORMAT_FLAG_BGR) != 0) 551 # else 552 if ((f & 0x10U/*HACK: fixed value*/) != 0) 553 # endif 554 continue; 555 556 /* AFIRST is meaningless if no alpha: */ 557 # ifdef PNG_FORMAT_AFIRST_SUPPORTED 558 if ((f & PNG_FORMAT_FLAG_ALPHA) == 0 && 559 (f & PNG_FORMAT_FLAG_AFIRST) != 0) 560 # else 561 if ((f & 0x20U/*HACK: fixed value*/) != 0) 562 # endif 563 continue; 564 565 format_set(pf, f); 566 } 567 } 568 } 569 570 /* THE Image STRUCTURE */ 571 /* The super-class of a png_image, contains the decoded image plus the input 572 * data necessary to re-read the file with a different format. 573 */ 574 typedef struct 575 { 576 png_image image; 577 png_uint_32 opts; 578 const char *file_name; 579 int stride_extra; 580 FILE *input_file; 581 png_voidp input_memory; 582 png_size_t input_memory_size; 583 png_bytep buffer; 584 ptrdiff_t stride; 585 png_size_t bufsize; 586 png_size_t allocsize; 587 char tmpfile_name[32]; 588 png_uint_16 colormap[256*4]; 589 } 590 Image; 591 592 /* Initializer: also sets the permitted error limit for 16-bit operations. */ 593 static void 594 newimage(Image *image) 595 { 596 memset(image, 0, sizeof *image); 597 } 598 599 /* Reset the image to be read again - only needs to rewind the FILE* at present. 600 */ 601 static void 602 resetimage(Image *image) 603 { 604 if (image->input_file != NULL) 605 rewind(image->input_file); 606 } 607 608 /* Free the image buffer; the buffer is re-used on a re-read, this is just for 609 * cleanup. 610 */ 611 static void 612 freebuffer(Image *image) 613 { 614 if (image->buffer) free(image->buffer); 615 image->buffer = NULL; 616 image->bufsize = 0; 617 image->allocsize = 0; 618 } 619 620 /* Delete function; cleans out all the allocated data and the temporary file in 621 * the image. 622 */ 623 static void 624 freeimage(Image *image) 625 { 626 freebuffer(image); 627 png_image_free(&image->image); 628 629 if (image->input_file != NULL) 630 { 631 fclose(image->input_file); 632 image->input_file = NULL; 633 } 634 635 if (image->input_memory != NULL) 636 { 637 free(image->input_memory); 638 image->input_memory = NULL; 639 image->input_memory_size = 0; 640 } 641 642 if (image->tmpfile_name[0] != 0 && (image->opts & KEEP_TMPFILES) == 0) 643 { 644 (void)remove(image->tmpfile_name); 645 image->tmpfile_name[0] = 0; 646 } 647 } 648 649 /* This is actually a re-initializer; allows an image structure to be re-used by 650 * freeing everything that relates to an old image. 651 */ 652 static void initimage(Image *image, png_uint_32 opts, const char *file_name, 653 int stride_extra) 654 { 655 freeimage(image); 656 memset(&image->image, 0, sizeof image->image); 657 image->opts = opts; 658 image->file_name = file_name; 659 image->stride_extra = stride_extra; 660 } 661 662 /* Make sure the image buffer is big enough; allows re-use of the buffer if the 663 * image is re-read. 664 */ 665 #define BUFFER_INIT8 73 666 static void 667 allocbuffer(Image *image) 668 { 669 png_size_t size = PNG_IMAGE_BUFFER_SIZE(image->image, image->stride); 670 671 if (size+32 > image->bufsize) 672 { 673 freebuffer(image); 674 image->buffer = voidcast(png_bytep, malloc(size+32)); 675 if (image->buffer == NULL) 676 { 677 fflush(stdout); 678 fprintf(stderr, 679 "simpletest: out of memory allocating %lu(+32) byte buffer\n", 680 (unsigned long)size); 681 exit(1); 682 } 683 image->bufsize = size+32; 684 } 685 686 memset(image->buffer, 95, image->bufsize); 687 memset(image->buffer+16, BUFFER_INIT8, size); 688 image->allocsize = size; 689 } 690 691 /* Make sure 16 bytes match the given byte. */ 692 static int 693 check16(png_const_bytep bp, int b) 694 { 695 int i = 16; 696 697 do 698 if (*bp != b) return 1; 699 while (--i); 700 701 return 0; 702 } 703 704 /* Check for overwrite in the image buffer. */ 705 static void 706 checkbuffer(Image *image, const char *arg) 707 { 708 if (check16(image->buffer, 95)) 709 { 710 fflush(stdout); 711 fprintf(stderr, "%s: overwrite at start of image buffer\n", arg); 712 exit(1); 713 } 714 715 if (check16(image->buffer+16+image->allocsize, 95)) 716 { 717 fflush(stdout); 718 fprintf(stderr, "%s: overwrite at end of image buffer\n", arg); 719 exit(1); 720 } 721 } 722 723 /* ERROR HANDLING */ 724 /* Log a terminal error, also frees the libpng part of the image if necessary. 725 */ 726 static int 727 logerror(Image *image, const char *a1, const char *a2, const char *a3) 728 { 729 fflush(stdout); 730 if (image->image.warning_or_error) 731 fprintf(stderr, "%s%s%s: %s\n", a1, a2, a3, image->image.message); 732 733 else 734 fprintf(stderr, "%s%s%s\n", a1, a2, a3); 735 736 if (image->image.opaque != NULL) 737 { 738 fprintf(stderr, "%s: image opaque pointer non-NULL on error\n", 739 image->file_name); 740 png_image_free(&image->image); 741 } 742 743 return 0; 744 } 745 746 /* Log an error and close a file (just a utility to do both things in one 747 * function call.) 748 */ 749 static int 750 logclose(Image *image, FILE *f, const char *name, const char *operation) 751 { 752 int e = errno; 753 754 fclose(f); 755 return logerror(image, name, operation, strerror(e)); 756 } 757 758 /* Make sure the png_image has been freed - validates that libpng is doing what 759 * the spec says and freeing the image. 760 */ 761 static int 762 checkopaque(Image *image) 763 { 764 if (image->image.opaque != NULL) 765 { 766 png_image_free(&image->image); 767 return logerror(image, image->file_name, ": opaque not NULL", ""); 768 } 769 770 /* Separate out the gamma+background_rgb_to_gray warning because it may 771 * produce opaque component errors: 772 */ 773 else if (image->image.warning_or_error != 0 && 774 (strcmp(image->image.message, 775 "libpng does not support gamma+background+rgb_to_gray") == 0 ? 776 (image->opts & GBG_ERROR) != 0 : (image->opts & STRICT) != 0)) 777 return logerror(image, image->file_name, (image->opts & GBG_ERROR) != 0 ? 778 " --fault-gbg-warning" : " --strict", ""); 779 780 else 781 return 1; 782 } 783 784 /* IMAGE COMPARISON/CHECKING */ 785 /* Compare the pixels of two images, which should be the same but aren't. The 786 * images must have been checked for a size match. 787 */ 788 typedef struct 789 { 790 /* The components, for grayscale images the gray value is in 'g' and if alpha 791 * is not present 'a' is set to 255 or 65535 according to format. 792 */ 793 int r, g, b, a; 794 } Pixel; 795 796 typedef struct 797 { 798 /* The background as the original sRGB 8-bit value converted to the final 799 * integer format and as a double precision linear value in the range 0..1 800 * for with partially transparent pixels. 801 */ 802 int ir, ig, ib; 803 double dr, dg, db; /* linear r,g,b scaled to 0..1 */ 804 } Background; 805 806 /* Basic image formats; control the data but not the layout thereof. */ 807 #define BASE_FORMATS\ 808 (PNG_FORMAT_FLAG_ALPHA|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_LINEAR) 809 810 /* Read a Pixel from a buffer. The code below stores the correct routine for 811 * the format in a function pointer, these are the routines: 812 */ 813 static void 814 gp_g8(Pixel *p, png_const_voidp pb) 815 { 816 png_const_bytep pp = voidcast(png_const_bytep, pb); 817 818 p->r = p->g = p->b = pp[0]; 819 p->a = 255; 820 } 821 822 static void 823 gp_ga8(Pixel *p, png_const_voidp pb) 824 { 825 png_const_bytep pp = voidcast(png_const_bytep, pb); 826 827 p->r = p->g = p->b = pp[0]; 828 p->a = pp[1]; 829 } 830 831 #ifdef PNG_FORMAT_AFIRST_SUPPORTED 832 static void 833 gp_ag8(Pixel *p, png_const_voidp pb) 834 { 835 png_const_bytep pp = voidcast(png_const_bytep, pb); 836 837 p->r = p->g = p->b = pp[1]; 838 p->a = pp[0]; 839 } 840 #endif 841 842 static void 843 gp_rgb8(Pixel *p, png_const_voidp pb) 844 { 845 png_const_bytep pp = voidcast(png_const_bytep, pb); 846 847 p->r = pp[0]; 848 p->g = pp[1]; 849 p->b = pp[2]; 850 p->a = 255; 851 } 852 853 #ifdef PNG_FORMAT_BGR_SUPPORTED 854 static void 855 gp_bgr8(Pixel *p, png_const_voidp pb) 856 { 857 png_const_bytep pp = voidcast(png_const_bytep, pb); 858 859 p->r = pp[2]; 860 p->g = pp[1]; 861 p->b = pp[0]; 862 p->a = 255; 863 } 864 #endif 865 866 static void 867 gp_rgba8(Pixel *p, png_const_voidp pb) 868 { 869 png_const_bytep pp = voidcast(png_const_bytep, pb); 870 871 p->r = pp[0]; 872 p->g = pp[1]; 873 p->b = pp[2]; 874 p->a = pp[3]; 875 } 876 877 #ifdef PNG_FORMAT_BGR_SUPPORTED 878 static void 879 gp_bgra8(Pixel *p, png_const_voidp pb) 880 { 881 png_const_bytep pp = voidcast(png_const_bytep, pb); 882 883 p->r = pp[2]; 884 p->g = pp[1]; 885 p->b = pp[0]; 886 p->a = pp[3]; 887 } 888 #endif 889 890 #ifdef PNG_FORMAT_AFIRST_SUPPORTED 891 static void 892 gp_argb8(Pixel *p, png_const_voidp pb) 893 { 894 png_const_bytep pp = voidcast(png_const_bytep, pb); 895 896 p->r = pp[1]; 897 p->g = pp[2]; 898 p->b = pp[3]; 899 p->a = pp[0]; 900 } 901 #endif 902 903 #if defined(PNG_FORMAT_AFIRST_SUPPORTED) && defined(PNG_FORMAT_BGR_SUPPORTED) 904 static void 905 gp_abgr8(Pixel *p, png_const_voidp pb) 906 { 907 png_const_bytep pp = voidcast(png_const_bytep, pb); 908 909 p->r = pp[3]; 910 p->g = pp[2]; 911 p->b = pp[1]; 912 p->a = pp[0]; 913 } 914 #endif 915 916 static void 917 gp_g16(Pixel *p, png_const_voidp pb) 918 { 919 png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 920 921 p->r = p->g = p->b = pp[0]; 922 p->a = 65535; 923 } 924 925 static void 926 gp_ga16(Pixel *p, png_const_voidp pb) 927 { 928 png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 929 930 p->r = p->g = p->b = pp[0]; 931 p->a = pp[1]; 932 } 933 934 #ifdef PNG_FORMAT_AFIRST_SUPPORTED 935 static void 936 gp_ag16(Pixel *p, png_const_voidp pb) 937 { 938 png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 939 940 p->r = p->g = p->b = pp[1]; 941 p->a = pp[0]; 942 } 943 #endif 944 945 static void 946 gp_rgb16(Pixel *p, png_const_voidp pb) 947 { 948 png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 949 950 p->r = pp[0]; 951 p->g = pp[1]; 952 p->b = pp[2]; 953 p->a = 65535; 954 } 955 956 #ifdef PNG_FORMAT_BGR_SUPPORTED 957 static void 958 gp_bgr16(Pixel *p, png_const_voidp pb) 959 { 960 png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 961 962 p->r = pp[2]; 963 p->g = pp[1]; 964 p->b = pp[0]; 965 p->a = 65535; 966 } 967 #endif 968 969 static void 970 gp_rgba16(Pixel *p, png_const_voidp pb) 971 { 972 png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 973 974 p->r = pp[0]; 975 p->g = pp[1]; 976 p->b = pp[2]; 977 p->a = pp[3]; 978 } 979 980 #ifdef PNG_FORMAT_BGR_SUPPORTED 981 static void 982 gp_bgra16(Pixel *p, png_const_voidp pb) 983 { 984 png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 985 986 p->r = pp[2]; 987 p->g = pp[1]; 988 p->b = pp[0]; 989 p->a = pp[3]; 990 } 991 #endif 992 993 #ifdef PNG_FORMAT_AFIRST_SUPPORTED 994 static void 995 gp_argb16(Pixel *p, png_const_voidp pb) 996 { 997 png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 998 999 p->r = pp[1]; 1000 p->g = pp[2]; 1001 p->b = pp[3]; 1002 p->a = pp[0]; 1003 } 1004 #endif 1005 1006 #if defined(PNG_FORMAT_AFIRST_SUPPORTED) && defined(PNG_FORMAT_BGR_SUPPORTED) 1007 static void 1008 gp_abgr16(Pixel *p, png_const_voidp pb) 1009 { 1010 png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); 1011 1012 p->r = pp[3]; 1013 p->g = pp[2]; 1014 p->b = pp[1]; 1015 p->a = pp[0]; 1016 } 1017 #endif 1018 1019 /* Given a format, return the correct one of the above functions. */ 1020 static void (* 1021 get_pixel(png_uint_32 format))(Pixel *p, png_const_voidp pb) 1022 { 1023 /* The color-map flag is irrelevant here - the caller of the function 1024 * returned must either pass the buffer or, for a color-mapped image, the 1025 * correct entry in the color-map. 1026 */ 1027 if (format & PNG_FORMAT_FLAG_LINEAR) 1028 { 1029 if (format & PNG_FORMAT_FLAG_COLOR) 1030 { 1031 # ifdef PNG_FORMAT_BGR_SUPPORTED 1032 if (format & PNG_FORMAT_FLAG_BGR) 1033 { 1034 if (format & PNG_FORMAT_FLAG_ALPHA) 1035 { 1036 # ifdef PNG_FORMAT_AFIRST_SUPPORTED 1037 if (format & PNG_FORMAT_FLAG_AFIRST) 1038 return gp_abgr16; 1039 1040 else 1041 # endif 1042 return gp_bgra16; 1043 } 1044 1045 else 1046 return gp_bgr16; 1047 } 1048 1049 else 1050 # endif 1051 { 1052 if (format & PNG_FORMAT_FLAG_ALPHA) 1053 { 1054 # ifdef PNG_FORMAT_AFIRST_SUPPORTED 1055 if (format & PNG_FORMAT_FLAG_AFIRST) 1056 return gp_argb16; 1057 1058 else 1059 # endif 1060 return gp_rgba16; 1061 } 1062 1063 else 1064 return gp_rgb16; 1065 } 1066 } 1067 1068 else 1069 { 1070 if (format & PNG_FORMAT_FLAG_ALPHA) 1071 { 1072 # ifdef PNG_FORMAT_AFIRST_SUPPORTED 1073 if (format & PNG_FORMAT_FLAG_AFIRST) 1074 return gp_ag16; 1075 1076 else 1077 # endif 1078 return gp_ga16; 1079 } 1080 1081 else 1082 return gp_g16; 1083 } 1084 } 1085 1086 else 1087 { 1088 if (format & PNG_FORMAT_FLAG_COLOR) 1089 { 1090 # ifdef PNG_FORMAT_BGR_SUPPORTED 1091 if (format & PNG_FORMAT_FLAG_BGR) 1092 { 1093 if (format & PNG_FORMAT_FLAG_ALPHA) 1094 { 1095 # ifdef PNG_FORMAT_AFIRST_SUPPORTED 1096 if (format & PNG_FORMAT_FLAG_AFIRST) 1097 return gp_abgr8; 1098 1099 else 1100 # endif 1101 return gp_bgra8; 1102 } 1103 1104 else 1105 return gp_bgr8; 1106 } 1107 1108 else 1109 # endif 1110 { 1111 if (format & PNG_FORMAT_FLAG_ALPHA) 1112 { 1113 # ifdef PNG_FORMAT_AFIRST_SUPPORTED 1114 if (format & PNG_FORMAT_FLAG_AFIRST) 1115 return gp_argb8; 1116 1117 else 1118 # endif 1119 return gp_rgba8; 1120 } 1121 1122 else 1123 return gp_rgb8; 1124 } 1125 } 1126 1127 else 1128 { 1129 if (format & PNG_FORMAT_FLAG_ALPHA) 1130 { 1131 # ifdef PNG_FORMAT_AFIRST_SUPPORTED 1132 if (format & PNG_FORMAT_FLAG_AFIRST) 1133 return gp_ag8; 1134 1135 else 1136 # endif 1137 return gp_ga8; 1138 } 1139 1140 else 1141 return gp_g8; 1142 } 1143 } 1144 } 1145 1146 /* Convertion between pixel formats. The code above effectively eliminates the 1147 * component ordering changes leaving three basic changes: 1148 * 1149 * 1) Remove an alpha channel by pre-multiplication or compositing on a 1150 * background color. (Adding an alpha channel is a no-op.) 1151 * 1152 * 2) Remove color by mapping to grayscale. (Grayscale to color is a no-op.) 1153 * 1154 * 3) Convert between 8-bit and 16-bit components. (Both directtions are 1155 * relevant.) 1156 * 1157 * This gives the following base format conversion matrix: 1158 * 1159 * OUT: ----- 8-bit ----- ----- 16-bit ----- 1160 * IN G GA RGB RGBA G GA RGB RGBA 1161 * 8 G . . . . lin lin lin lin 1162 * 8 GA bckg . bckc . pre' pre pre' pre 1163 * 8 RGB g8 g8 . . glin glin lin lin 1164 * 8 RGBA g8b g8 bckc . gpr' gpre pre' pre 1165 * 16 G sRGB sRGB sRGB sRGB . . . . 1166 * 16 GA b16g unpg b16c unpc A . A . 1167 * 16 RGB sG sG sRGB sRGB g16 g16 . . 1168 * 16 RGBA gb16 sGp cb16 sCp g16 g16' A . 1169 * 1170 * 8-bit to 8-bit: 1171 * bckg: composite on gray background 1172 * bckc: composite on color background 1173 * g8: convert sRGB components to sRGB grayscale 1174 * g8b: convert sRGB components to grayscale and composite on gray background 1175 * 1176 * 8-bit to 16-bit: 1177 * lin: make sRGB components linear, alpha := 65535 1178 * pre: make sRGB components linear and premultiply by alpha (scale alpha) 1179 * pre': as 'pre' but alpha := 65535 1180 * glin: make sRGB components linear, convert to grayscale, alpha := 65535 1181 * gpre: make sRGB components grayscale and linear and premultiply by alpha 1182 * gpr': as 'gpre' but alpha := 65535 1183 * 1184 * 16-bit to 8-bit: 1185 * sRGB: convert linear components to sRGB, alpha := 255 1186 * unpg: unpremultiply gray component and convert to sRGB (scale alpha) 1187 * unpc: unpremultiply color components and convert to sRGB (scale alpha) 1188 * b16g: composite linear onto gray background and convert the result to sRGB 1189 * b16c: composite linear onto color background and convert the result to sRGB 1190 * sG: convert linear RGB to sRGB grayscale 1191 * sGp: unpremultiply RGB then convert to sRGB grayscale 1192 * sCp: unpremultiply RGB then convert to sRGB 1193 * gb16: composite linear onto background and convert to sRGB grayscale 1194 * (order doesn't matter, the composite and grayscale operations permute) 1195 * cb16: composite linear onto background and convert to sRGB 1196 * 1197 * 16-bit to 16-bit: 1198 * A: set alpha to 65535 1199 * g16: convert linear RGB to linear grayscale (alpha := 65535) 1200 * g16': as 'g16' but alpha is unchanged 1201 */ 1202 /* Simple copy: */ 1203 static void 1204 gpc_noop(Pixel *out, const Pixel *in, const Background *back) 1205 { 1206 (void)back; 1207 out->r = in->r; 1208 out->g = in->g; 1209 out->b = in->b; 1210 out->a = in->a; 1211 } 1212 1213 #if ALLOW_UNUSED_GPC 1214 static void 1215 gpc_nop8(Pixel *out, const Pixel *in, const Background *back) 1216 { 1217 (void)back; 1218 if (in->a == 0) 1219 out->r = out->g = out->b = 255; 1220 1221 else 1222 { 1223 out->r = in->r; 1224 out->g = in->g; 1225 out->b = in->b; 1226 } 1227 1228 out->a = in->a; 1229 } 1230 #endif 1231 1232 #if ALLOW_UNUSED_GPC 1233 static void 1234 gpc_nop6(Pixel *out, const Pixel *in, const Background *back) 1235 { 1236 (void)back; 1237 if (in->a == 0) 1238 out->r = out->g = out->b = 65535; 1239 1240 else 1241 { 1242 out->r = in->r; 1243 out->g = in->g; 1244 out->b = in->b; 1245 } 1246 1247 out->a = in->a; 1248 } 1249 #endif 1250 1251 /* 8-bit to 8-bit conversions */ 1252 /* bckg: composite on gray background */ 1253 static void 1254 gpc_bckg(Pixel *out, const Pixel *in, const Background *back) 1255 { 1256 if (in->a <= 0) 1257 out->r = out->g = out->b = back->ig; 1258 1259 else if (in->a >= 255) 1260 out->r = out->g = out->b = in->g; 1261 1262 else 1263 { 1264 double a = in->a / 255.; 1265 1266 out->r = out->g = out->b = sRGB(sRGB_to_d[in->g] * a + back->dg * (1-a)); 1267 } 1268 1269 out->a = 255; 1270 } 1271 1272 /* bckc: composite on color background */ 1273 static void 1274 gpc_bckc(Pixel *out, const Pixel *in, const Background *back) 1275 { 1276 if (in->a <= 0) 1277 { 1278 out->r = back->ir; 1279 out->g = back->ig; 1280 out->b = back->ib; 1281 } 1282 1283 else if (in->a >= 255) 1284 { 1285 out->r = in->r; 1286 out->g = in->g; 1287 out->b = in->b; 1288 } 1289 1290 else 1291 { 1292 double a = in->a / 255.; 1293 1294 out->r = sRGB(sRGB_to_d[in->r] * a + back->dr * (1-a)); 1295 out->g = sRGB(sRGB_to_d[in->g] * a + back->dg * (1-a)); 1296 out->b = sRGB(sRGB_to_d[in->b] * a + back->db * (1-a)); 1297 } 1298 1299 out->a = 255; 1300 } 1301 1302 /* g8: convert sRGB components to sRGB grayscale */ 1303 static void 1304 gpc_g8(Pixel *out, const Pixel *in, const Background *back) 1305 { 1306 (void)back; 1307 1308 if (in->r == in->g && in->g == in->b) 1309 out->r = out->g = out->b = in->g; 1310 1311 else 1312 out->r = out->g = out->b = 1313 sRGB(YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); 1314 1315 out->a = in->a; 1316 } 1317 1318 /* g8b: convert sRGB components to grayscale and composite on gray background */ 1319 static void 1320 gpc_g8b(Pixel *out, const Pixel *in, const Background *back) 1321 { 1322 if (in->a <= 0) 1323 out->r = out->g = out->b = back->ig; 1324 1325 else if (in->a >= 255) 1326 { 1327 if (in->r == in->g && in->g == in->b) 1328 out->r = out->g = out->b = in->g; 1329 1330 else 1331 out->r = out->g = out->b = sRGB(YfromRGB( 1332 sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); 1333 } 1334 1335 else 1336 { 1337 double a = in->a/255.; 1338 1339 out->r = out->g = out->b = sRGB(a * YfromRGB(sRGB_to_d[in->r], 1340 sRGB_to_d[in->g], sRGB_to_d[in->b]) + back->dg * (1-a)); 1341 } 1342 1343 out->a = 255; 1344 } 1345 1346 /* 8-bit to 16-bit conversions */ 1347 /* lin: make sRGB components linear, alpha := 65535 */ 1348 static void 1349 gpc_lin(Pixel *out, const Pixel *in, const Background *back) 1350 { 1351 (void)back; 1352 1353 out->r = ilinear(in->r); 1354 1355 if (in->g == in->r) 1356 { 1357 out->g = out->r; 1358 1359 if (in->b == in->r) 1360 out->b = out->r; 1361 1362 else 1363 out->b = ilinear(in->b); 1364 } 1365 1366 else 1367 { 1368 out->g = ilinear(in->g); 1369 1370 if (in->b == in->r) 1371 out->b = out->r; 1372 1373 else if (in->b == in->g) 1374 out->b = out->g; 1375 1376 else 1377 out->b = ilinear(in->b); 1378 } 1379 1380 out->a = 65535; 1381 } 1382 1383 /* pre: make sRGB components linear and premultiply by alpha (scale alpha) */ 1384 static void 1385 gpc_pre(Pixel *out, const Pixel *in, const Background *back) 1386 { 1387 (void)back; 1388 1389 out->r = ilineara(in->r, in->a); 1390 1391 if (in->g == in->r) 1392 { 1393 out->g = out->r; 1394 1395 if (in->b == in->r) 1396 out->b = out->r; 1397 1398 else 1399 out->b = ilineara(in->b, in->a); 1400 } 1401 1402 else 1403 { 1404 out->g = ilineara(in->g, in->a); 1405 1406 if (in->b == in->r) 1407 out->b = out->r; 1408 1409 else if (in->b == in->g) 1410 out->b = out->g; 1411 1412 else 1413 out->b = ilineara(in->b, in->a); 1414 } 1415 1416 out->a = in->a * 257; 1417 } 1418 1419 /* pre': as 'pre' but alpha := 65535 */ 1420 static void 1421 gpc_preq(Pixel *out, const Pixel *in, const Background *back) 1422 { 1423 (void)back; 1424 1425 out->r = ilineara(in->r, in->a); 1426 1427 if (in->g == in->r) 1428 { 1429 out->g = out->r; 1430 1431 if (in->b == in->r) 1432 out->b = out->r; 1433 1434 else 1435 out->b = ilineara(in->b, in->a); 1436 } 1437 1438 else 1439 { 1440 out->g = ilineara(in->g, in->a); 1441 1442 if (in->b == in->r) 1443 out->b = out->r; 1444 1445 else if (in->b == in->g) 1446 out->b = out->g; 1447 1448 else 1449 out->b = ilineara(in->b, in->a); 1450 } 1451 1452 out->a = 65535; 1453 } 1454 1455 /* glin: make sRGB components linear, convert to grayscale, alpha := 65535 */ 1456 static void 1457 gpc_glin(Pixel *out, const Pixel *in, const Background *back) 1458 { 1459 (void)back; 1460 1461 if (in->r == in->g && in->g == in->b) 1462 out->r = out->g = out->b = ilinear(in->g); 1463 1464 else 1465 out->r = out->g = out->b = u16d(65535 * 1466 YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); 1467 1468 out->a = 65535; 1469 } 1470 1471 /* gpre: make sRGB components grayscale and linear and premultiply by alpha */ 1472 static void 1473 gpc_gpre(Pixel *out, const Pixel *in, const Background *back) 1474 { 1475 (void)back; 1476 1477 if (in->r == in->g && in->g == in->b) 1478 out->r = out->g = out->b = ilineara(in->g, in->a); 1479 1480 else 1481 out->r = out->g = out->b = u16d(in->a * 257 * 1482 YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); 1483 1484 out->a = 257 * in->a; 1485 } 1486 1487 /* gpr': as 'gpre' but alpha := 65535 */ 1488 static void 1489 gpc_gprq(Pixel *out, const Pixel *in, const Background *back) 1490 { 1491 (void)back; 1492 1493 if (in->r == in->g && in->g == in->b) 1494 out->r = out->g = out->b = ilineara(in->g, in->a); 1495 1496 else 1497 out->r = out->g = out->b = u16d(in->a * 257 * 1498 YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); 1499 1500 out->a = 65535; 1501 } 1502 1503 /* 8-bit to 16-bit conversions for gAMA 45455 encoded values */ 1504 /* Lin: make gAMA 45455 components linear, alpha := 65535 */ 1505 static void 1506 gpc_Lin(Pixel *out, const Pixel *in, const Background *back) 1507 { 1508 (void)back; 1509 1510 out->r = ilinear_g22(in->r); 1511 1512 if (in->g == in->r) 1513 { 1514 out->g = out->r; 1515 1516 if (in->b == in->r) 1517 out->b = out->r; 1518 1519 else 1520 out->b = ilinear_g22(in->b); 1521 } 1522 1523 else 1524 { 1525 out->g = ilinear_g22(in->g); 1526 1527 if (in->b == in->r) 1528 out->b = out->r; 1529 1530 else if (in->b == in->g) 1531 out->b = out->g; 1532 1533 else 1534 out->b = ilinear_g22(in->b); 1535 } 1536 1537 out->a = 65535; 1538 } 1539 1540 #if ALLOW_UNUSED_GPC 1541 /* Pre: make gAMA 45455 components linear and premultiply by alpha (scale alpha) 1542 */ 1543 static void 1544 gpc_Pre(Pixel *out, const Pixel *in, const Background *back) 1545 { 1546 (void)back; 1547 1548 out->r = ilineara_g22(in->r, in->a); 1549 1550 if (in->g == in->r) 1551 { 1552 out->g = out->r; 1553 1554 if (in->b == in->r) 1555 out->b = out->r; 1556 1557 else 1558 out->b = ilineara_g22(in->b, in->a); 1559 } 1560 1561 else 1562 { 1563 out->g = ilineara_g22(in->g, in->a); 1564 1565 if (in->b == in->r) 1566 out->b = out->r; 1567 1568 else if (in->b == in->g) 1569 out->b = out->g; 1570 1571 else 1572 out->b = ilineara_g22(in->b, in->a); 1573 } 1574 1575 out->a = in->a * 257; 1576 } 1577 #endif 1578 1579 #if ALLOW_UNUSED_GPC 1580 /* Pre': as 'Pre' but alpha := 65535 */ 1581 static void 1582 gpc_Preq(Pixel *out, const Pixel *in, const Background *back) 1583 { 1584 (void)back; 1585 1586 out->r = ilineara_g22(in->r, in->a); 1587 1588 if (in->g == in->r) 1589 { 1590 out->g = out->r; 1591 1592 if (in->b == in->r) 1593 out->b = out->r; 1594 1595 else 1596 out->b = ilineara_g22(in->b, in->a); 1597 } 1598 1599 else 1600 { 1601 out->g = ilineara_g22(in->g, in->a); 1602 1603 if (in->b == in->r) 1604 out->b = out->r; 1605 1606 else if (in->b == in->g) 1607 out->b = out->g; 1608 1609 else 1610 out->b = ilineara_g22(in->b, in->a); 1611 } 1612 1613 out->a = 65535; 1614 } 1615 #endif 1616 1617 #if ALLOW_UNUSED_GPC 1618 /* Glin: make gAMA 45455 components linear, convert to grayscale, alpha := 65535 1619 */ 1620 static void 1621 gpc_Glin(Pixel *out, const Pixel *in, const Background *back) 1622 { 1623 (void)back; 1624 1625 if (in->r == in->g && in->g == in->b) 1626 out->r = out->g = out->b = ilinear_g22(in->g); 1627 1628 else 1629 out->r = out->g = out->b = u16d(65535 * 1630 YfromRGB(g22_to_d[in->r], g22_to_d[in->g], g22_to_d[in->b])); 1631 1632 out->a = 65535; 1633 } 1634 #endif 1635 1636 #if ALLOW_UNUSED_GPC 1637 /* Gpre: make gAMA 45455 components grayscale and linear and premultiply by 1638 * alpha. 1639 */ 1640 static void 1641 gpc_Gpre(Pixel *out, const Pixel *in, const Background *back) 1642 { 1643 (void)back; 1644 1645 if (in->r == in->g && in->g == in->b) 1646 out->r = out->g = out->b = ilineara_g22(in->g, in->a); 1647 1648 else 1649 out->r = out->g = out->b = u16d(in->a * 257 * 1650 YfromRGB(g22_to_d[in->r], g22_to_d[in->g], g22_to_d[in->b])); 1651 1652 out->a = 257 * in->a; 1653 } 1654 #endif 1655 1656 #if ALLOW_UNUSED_GPC 1657 /* Gpr': as 'Gpre' but alpha := 65535 */ 1658 static void 1659 gpc_Gprq(Pixel *out, const Pixel *in, const Background *back) 1660 { 1661 (void)back; 1662 1663 if (in->r == in->g && in->g == in->b) 1664 out->r = out->g = out->b = ilineara_g22(in->g, in->a); 1665 1666 else 1667 out->r = out->g = out->b = u16d(in->a * 257 * 1668 YfromRGB(g22_to_d[in->r], g22_to_d[in->g], g22_to_d[in->b])); 1669 1670 out->a = 65535; 1671 } 1672 #endif 1673 1674 /* 16-bit to 8-bit conversions */ 1675 /* sRGB: convert linear components to sRGB, alpha := 255 */ 1676 static void 1677 gpc_sRGB(Pixel *out, const Pixel *in, const Background *back) 1678 { 1679 (void)back; 1680 1681 out->r = isRGB(in->r); 1682 1683 if (in->g == in->r) 1684 { 1685 out->g = out->r; 1686 1687 if (in->b == in->r) 1688 out->b = out->r; 1689 1690 else 1691 out->b = isRGB(in->b); 1692 } 1693 1694 else 1695 { 1696 out->g = isRGB(in->g); 1697 1698 if (in->b == in->r) 1699 out->b = out->r; 1700 1701 else if (in->b == in->g) 1702 out->b = out->g; 1703 1704 else 1705 out->b = isRGB(in->b); 1706 } 1707 1708 out->a = 255; 1709 } 1710 1711 /* unpg: unpremultiply gray component and convert to sRGB (scale alpha) */ 1712 static void 1713 gpc_unpg(Pixel *out, const Pixel *in, const Background *back) 1714 { 1715 (void)back; 1716 1717 if (in->a <= 128) 1718 { 1719 out->r = out->g = out->b = 255; 1720 out->a = 0; 1721 } 1722 1723 else 1724 { 1725 out->r = out->g = out->b = sRGB((double)in->g / in->a); 1726 out->a = u8d(in->a / 257.); 1727 } 1728 } 1729 1730 /* unpc: unpremultiply color components and convert to sRGB (scale alpha) */ 1731 static void 1732 gpc_unpc(Pixel *out, const Pixel *in, const Background *back) 1733 { 1734 (void)back; 1735 1736 if (in->a <= 128) 1737 { 1738 out->r = out->g = out->b = 255; 1739 out->a = 0; 1740 } 1741 1742 else 1743 { 1744 out->r = sRGB((double)in->r / in->a); 1745 out->g = sRGB((double)in->g / in->a); 1746 out->b = sRGB((double)in->b / in->a); 1747 out->a = u8d(in->a / 257.); 1748 } 1749 } 1750 1751 /* b16g: composite linear onto gray background and convert the result to sRGB */ 1752 static void 1753 gpc_b16g(Pixel *out, const Pixel *in, const Background *back) 1754 { 1755 if (in->a <= 0) 1756 out->r = out->g = out->b = back->ig; 1757 1758 else 1759 { 1760 double a = in->a/65535.; 1761 double a1 = 1-a; 1762 1763 a /= 65535; 1764 out->r = out->g = out->b = sRGB(in->g * a + back->dg * a1); 1765 } 1766 1767 out->a = 255; 1768 } 1769 1770 /* b16c: composite linear onto color background and convert the result to sRGB*/ 1771 static void 1772 gpc_b16c(Pixel *out, const Pixel *in, const Background *back) 1773 { 1774 if (in->a <= 0) 1775 { 1776 out->r = back->ir; 1777 out->g = back->ig; 1778 out->b = back->ib; 1779 } 1780 1781 else 1782 { 1783 double a = in->a/65535.; 1784 double a1 = 1-a; 1785 1786 a /= 65535; 1787 out->r = sRGB(in->r * a + back->dr * a1); 1788 out->g = sRGB(in->g * a + back->dg * a1); 1789 out->b = sRGB(in->b * a + back->db * a1); 1790 } 1791 1792 out->a = 255; 1793 } 1794 1795 /* sG: convert linear RGB to sRGB grayscale */ 1796 static void 1797 gpc_sG(Pixel *out, const Pixel *in, const Background *back) 1798 { 1799 (void)back; 1800 1801 out->r = out->g = out->b = sRGB(YfromRGBint(in->r, in->g, in->b)/65535); 1802 out->a = 255; 1803 } 1804 1805 /* sGp: unpremultiply RGB then convert to sRGB grayscale */ 1806 static void 1807 gpc_sGp(Pixel *out, const Pixel *in, const Background *back) 1808 { 1809 (void)back; 1810 1811 if (in->a <= 128) 1812 { 1813 out->r = out->g = out->b = 255; 1814 out->a = 0; 1815 } 1816 1817 else 1818 { 1819 out->r = out->g = out->b = sRGB(YfromRGBint(in->r, in->g, in->b)/in->a); 1820 out->a = u8d(in->a / 257.); 1821 } 1822 } 1823 1824 /* sCp: unpremultiply RGB then convert to sRGB */ 1825 static void 1826 gpc_sCp(Pixel *out, const Pixel *in, const Background *back) 1827 { 1828 (void)back; 1829 1830 if (in->a <= 128) 1831 { 1832 out->r = out->g = out->b = 255; 1833 out->a = 0; 1834 } 1835 1836 else 1837 { 1838 out->r = sRGB((double)in->r / in->a); 1839 out->g = sRGB((double)in->g / in->a); 1840 out->b = sRGB((double)in->b / in->a); 1841 out->a = u8d(in->a / 257.); 1842 } 1843 } 1844 1845 /* gb16: composite linear onto background and convert to sRGB grayscale */ 1846 /* (order doesn't matter, the composite and grayscale operations permute) */ 1847 static void 1848 gpc_gb16(Pixel *out, const Pixel *in, const Background *back) 1849 { 1850 if (in->a <= 0) 1851 out->r = out->g = out->b = back->ig; 1852 1853 else if (in->a >= 65535) 1854 out->r = out->g = out->b = isRGB(in->g); 1855 1856 else 1857 { 1858 double a = in->a / 65535.; 1859 double a1 = 1-a; 1860 1861 a /= 65535; 1862 out->r = out->g = out->b = sRGB(in->g * a + back->dg * a1); 1863 } 1864 1865 out->a = 255; 1866 } 1867 1868 /* cb16: composite linear onto background and convert to sRGB */ 1869 static void 1870 gpc_cb16(Pixel *out, const Pixel *in, const Background *back) 1871 { 1872 if (in->a <= 0) 1873 { 1874 out->r = back->ir; 1875 out->g = back->ig; 1876 out->b = back->ib; 1877 } 1878 1879 else if (in->a >= 65535) 1880 { 1881 out->r = isRGB(in->r); 1882 out->g = isRGB(in->g); 1883 out->b = isRGB(in->b); 1884 } 1885 1886 else 1887 { 1888 double a = in->a / 65535.; 1889 double a1 = 1-a; 1890 1891 a /= 65535; 1892 out->r = sRGB(in->r * a + back->dr * a1); 1893 out->g = sRGB(in->g * a + back->dg * a1); 1894 out->b = sRGB(in->b * a + back->db * a1); 1895 } 1896 1897 out->a = 255; 1898 } 1899 1900 /* 16-bit to 16-bit conversions */ 1901 /* A: set alpha to 65535 */ 1902 static void 1903 gpc_A(Pixel *out, const Pixel *in, const Background *back) 1904 { 1905 (void)back; 1906 out->r = in->r; 1907 out->g = in->g; 1908 out->b = in->b; 1909 out->a = 65535; 1910 } 1911 1912 /* g16: convert linear RGB to linear grayscale (alpha := 65535) */ 1913 static void 1914 gpc_g16(Pixel *out, const Pixel *in, const Background *back) 1915 { 1916 (void)back; 1917 out->r = out->g = out->b = u16d(YfromRGBint(in->r, in->g, in->b)); 1918 out->a = 65535; 1919 } 1920 1921 /* g16': as 'g16' but alpha is unchanged */ 1922 static void 1923 gpc_g16q(Pixel *out, const Pixel *in, const Background *back) 1924 { 1925 (void)back; 1926 out->r = out->g = out->b = u16d(YfromRGBint(in->r, in->g, in->b)); 1927 out->a = in->a; 1928 } 1929 1930 #if ALLOW_UNUSED_GPC 1931 /* Unused functions (to hide them from GCC unused function warnings) */ 1932 void (* const gpc_unused[]) 1933 (Pixel *out, const Pixel *in, const Background *back) = 1934 { 1935 gpc_Pre, gpc_Preq, gpc_Glin, gpc_Gpre, gpc_Gprq, gpc_nop8, gpc_nop6 1936 }; 1937 #endif 1938 1939 /* OUT: ----- 8-bit ----- ----- 16-bit ----- 1940 * IN G GA RGB RGBA G GA RGB RGBA 1941 * 8 G . . . . lin lin lin lin 1942 * 8 GA bckg . bckc . pre' pre pre' pre 1943 * 8 RGB g8 g8 . . glin glin lin lin 1944 * 8 RGBA g8b g8 bckc . gpr' gpre pre' pre 1945 * 16 G sRGB sRGB sRGB sRGB . . . . 1946 * 16 GA b16g unpg b16c unpc A . A . 1947 * 16 RGB sG sG sRGB sRGB g16 g16 . . 1948 * 16 RGBA gb16 sGp cb16 sCp g16 g16' A . 1949 * 1950 * The matrix is held in an array indexed thus: 1951 * 1952 * gpc_fn[out_format & BASE_FORMATS][in_format & BASE_FORMATS]; 1953 */ 1954 /* This will produce a compile time error if the FORMAT_FLAG values don't 1955 * match the above matrix! 1956 */ 1957 #if PNG_FORMAT_FLAG_ALPHA == 1 && PNG_FORMAT_FLAG_COLOR == 2 &&\ 1958 PNG_FORMAT_FLAG_LINEAR == 4 1959 static void (* const gpc_fn[8/*in*/][8/*out*/]) 1960 (Pixel *out, const Pixel *in, const Background *back) = 1961 { 1962 /*out: G-8 GA-8 RGB-8 RGBA-8 G-16 GA-16 RGB-16 RGBA-16 */ 1963 {gpc_noop,gpc_noop,gpc_noop,gpc_noop, gpc_Lin, gpc_Lin, gpc_Lin, gpc_Lin }, 1964 {gpc_bckg,gpc_noop,gpc_bckc,gpc_noop, gpc_preq,gpc_pre, gpc_preq,gpc_pre }, 1965 {gpc_g8, gpc_g8, gpc_noop,gpc_noop, gpc_glin,gpc_glin,gpc_lin, gpc_lin }, 1966 {gpc_g8b, gpc_g8, gpc_bckc,gpc_noop, gpc_gprq,gpc_gpre,gpc_preq,gpc_pre }, 1967 {gpc_sRGB,gpc_sRGB,gpc_sRGB,gpc_sRGB, gpc_noop,gpc_noop,gpc_noop,gpc_noop}, 1968 {gpc_b16g,gpc_unpg,gpc_b16c,gpc_unpc, gpc_A, gpc_noop,gpc_A, gpc_noop}, 1969 {gpc_sG, gpc_sG, gpc_sRGB,gpc_sRGB, gpc_g16, gpc_g16, gpc_noop,gpc_noop}, 1970 {gpc_gb16,gpc_sGp, gpc_cb16,gpc_sCp, gpc_g16, gpc_g16q,gpc_A, gpc_noop} 1971 }; 1972 1973 /* The array is repeated for the cases where both the input and output are color 1974 * mapped because then different algorithms are used. 1975 */ 1976 static void (* const gpc_fn_colormapped[8/*in*/][8/*out*/]) 1977 (Pixel *out, const Pixel *in, const Background *back) = 1978 { 1979 /*out: G-8 GA-8 RGB-8 RGBA-8 G-16 GA-16 RGB-16 RGBA-16 */ 1980 {gpc_noop,gpc_noop,gpc_noop,gpc_noop, gpc_lin, gpc_lin, gpc_lin, gpc_lin }, 1981 {gpc_bckg,gpc_noop,gpc_bckc,gpc_noop, gpc_preq,gpc_pre, gpc_preq,gpc_pre }, 1982 {gpc_g8, gpc_g8, gpc_noop,gpc_noop, gpc_glin,gpc_glin,gpc_lin, gpc_lin }, 1983 {gpc_g8b, gpc_g8, gpc_bckc,gpc_noop, gpc_gprq,gpc_gpre,gpc_preq,gpc_pre }, 1984 {gpc_sRGB,gpc_sRGB,gpc_sRGB,gpc_sRGB, gpc_noop,gpc_noop,gpc_noop,gpc_noop}, 1985 {gpc_b16g,gpc_unpg,gpc_b16c,gpc_unpc, gpc_A, gpc_noop,gpc_A, gpc_noop}, 1986 {gpc_sG, gpc_sG, gpc_sRGB,gpc_sRGB, gpc_g16, gpc_g16, gpc_noop,gpc_noop}, 1987 {gpc_gb16,gpc_sGp, gpc_cb16,gpc_sCp, gpc_g16, gpc_g16q,gpc_A, gpc_noop} 1988 }; 1989 1990 /* The error arrays record the error in the same matrix; 64 entries, however 1991 * the different algorithms used in libpng for colormap and direct conversions 1992 * mean that four separate matrices are used (for each combination of 1993 * colormapped and direct.) 1994 * 1995 * In some cases the conversion between sRGB formats goes via a linear 1996 * intermediate; an sRGB to linear conversion (as above) is followed by a simple 1997 * linear to sRGB step with no other conversions. This is done by a separate 1998 * error array from an arbitrary 'in' format to one of the four basic outputs 1999 * (since final output is always sRGB not colormapped). 2000 * 2001 * These arrays may be modified if the --accumulate flag is set during the run; 2002 * then instead of logging errors they are simply added in. 2003 * 2004 * The three entries are currently for transparent, partially transparent and 2005 * opaque input pixel values. Notice that alpha should be exact in each case. 2006 * 2007 * Errors in alpha should only occur when converting from a direct format 2008 * to a colormapped format, when alpha is effectively smashed (so large 2009 * errors can occur.) There should be no error in the '0' and 'opaque' 2010 * values. The fourth entry in the array is used for the alpha error (and it 2011 * should always be zero for the 'via linear' case since this is never color 2012 * mapped.) 2013 * 2014 * Mapping to a colormap smashes the colors, it is necessary to have separate 2015 * values for these cases because they are much larger; it is very much 2016 * impossible to obtain a reasonable result, these are held in 2017 * gpc_error_to_colormap. 2018 */ 2019 #if PNG_FORMAT_FLAG_COLORMAP == 8 /* extra check also required */ 2020 # include "pngstest-errors.h" /* machine generated */ 2021 #endif /* COLORMAP flag check */ 2022 #endif /* flag checks */ 2023 2024 typedef struct 2025 { 2026 /* Basic pixel information: */ 2027 Image* in_image; /* Input image */ 2028 const Image* out_image; /* Output image */ 2029 2030 /* 'background' is the value passed to the gpc_ routines, it may be NULL if 2031 * it should not be used (*this* program has an error if it crashes as a 2032 * result!) 2033 */ 2034 Background background_color; 2035 const Background* background; 2036 2037 /* Precalculated values: */ 2038 int in_opaque; /* Value of input alpha that is opaque */ 2039 int is_palette; /* Sample values come from the palette */ 2040 int accumulate; /* Accumlate component errors (don't log) */ 2041 int output_8bit; /* Output is 8-bit (else 16-bit) */ 2042 2043 void (*in_gp)(Pixel*, png_const_voidp); 2044 void (*out_gp)(Pixel*, png_const_voidp); 2045 2046 void (*transform)(Pixel *out, const Pixel *in, const Background *back); 2047 /* A function to perform the required transform */ 2048 2049 void (*from_linear)(Pixel *out, const Pixel *in, const Background *back); 2050 /* For 'via_linear' transforms the final, from linear, step, else NULL */ 2051 2052 png_uint_16 error[4]; 2053 /* Three error values for transparent, partially transparent and opaque 2054 * input pixels (in turn). 2055 */ 2056 2057 png_uint_16 *error_ptr; 2058 /* Where these are stored in the static array (for 'accumulate') */ 2059 } 2060 Transform; 2061 2062 /* Return a 'transform' as above for the given format conversion. */ 2063 static void 2064 transform_from_formats(Transform *result, Image *in_image, 2065 const Image *out_image, png_const_colorp background, int via_linear) 2066 { 2067 png_uint_32 in_format, out_format; 2068 png_uint_32 in_base, out_base; 2069 2070 memset(result, 0, sizeof *result); 2071 2072 /* Store the original images for error messages */ 2073 result->in_image = in_image; 2074 result->out_image = out_image; 2075 2076 in_format = in_image->image.format; 2077 out_format = out_image->image.format; 2078 2079 if (in_format & PNG_FORMAT_FLAG_LINEAR) 2080 result->in_opaque = 65535; 2081 else 2082 result->in_opaque = 255; 2083 2084 result->output_8bit = (out_format & PNG_FORMAT_FLAG_LINEAR) == 0; 2085 2086 result->is_palette = 0; /* set by caller if required */ 2087 result->accumulate = (in_image->opts & ACCUMULATE) != 0; 2088 2089 /* The loaders (which need the ordering information) */ 2090 result->in_gp = get_pixel(in_format); 2091 result->out_gp = get_pixel(out_format); 2092 2093 /* Remove the ordering information: */ 2094 in_format &= BASE_FORMATS | PNG_FORMAT_FLAG_COLORMAP; 2095 in_base = in_format & BASE_FORMATS; 2096 out_format &= BASE_FORMATS | PNG_FORMAT_FLAG_COLORMAP; 2097 out_base = out_format & BASE_FORMATS; 2098 2099 if (via_linear) 2100 { 2101 /* Check for an error in this program: */ 2102 if (out_format & (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLORMAP)) 2103 { 2104 fprintf(stderr, "internal transform via linear error 0x%x->0x%x\n", 2105 in_format, out_format); 2106 exit(1); 2107 } 2108 2109 result->transform = gpc_fn[in_base][out_base | PNG_FORMAT_FLAG_LINEAR]; 2110 result->from_linear = gpc_fn[out_base | PNG_FORMAT_FLAG_LINEAR][out_base]; 2111 result->error_ptr = gpc_error_via_linear[in_format][out_format]; 2112 } 2113 2114 else if (~in_format & out_format & PNG_FORMAT_FLAG_COLORMAP) 2115 { 2116 /* The input is not colormapped but the output is, the errors will 2117 * typically be large (only the grayscale-no-alpha case permits preserving 2118 * even 8-bit values.) 2119 */ 2120 result->transform = gpc_fn[in_base][out_base]; 2121 result->from_linear = NULL; 2122 result->error_ptr = gpc_error_to_colormap[in_base][out_base]; 2123 } 2124 2125 else 2126 { 2127 /* The caller handles the colormap->pixel value conversion, so the 2128 * transform function just gets a pixel value, however because libpng 2129 * currently contains a different implementation for mapping a colormap if 2130 * both input and output are colormapped we need different conversion 2131 * functions to deal with errors in the libpng implementation. 2132 */ 2133 if (in_format & out_format & PNG_FORMAT_FLAG_COLORMAP) 2134 result->transform = gpc_fn_colormapped[in_base][out_base]; 2135 else 2136 result->transform = gpc_fn[in_base][out_base]; 2137 result->from_linear = NULL; 2138 result->error_ptr = gpc_error[in_format][out_format]; 2139 } 2140 2141 /* Follow the libpng simplified API rules to work out what to pass to the gpc 2142 * routines as a background value, if one is not required pass NULL so that 2143 * this program crashes in the even of a programming error. 2144 */ 2145 result->background = NULL; /* default: not required */ 2146 2147 /* Rule 1: background only need be supplied if alpha is to be removed */ 2148 if (in_format & ~out_format & PNG_FORMAT_FLAG_ALPHA) 2149 { 2150 /* The input value is 'NULL' to use the background and (otherwise) an sRGB 2151 * background color (to use a solid color). The code above uses a fixed 2152 * byte value, BUFFER_INIT8, for buffer even for 16-bit output. For 2153 * linear (16-bit) output the sRGB background color is ignored; the 2154 * composition is always on the background (so BUFFER_INIT8 * 257), except 2155 * that for the colormap (i.e. linear colormapped output) black is used. 2156 */ 2157 result->background = &result->background_color; 2158 2159 if (out_format & PNG_FORMAT_FLAG_LINEAR || via_linear) 2160 { 2161 if (out_format & PNG_FORMAT_FLAG_COLORMAP) 2162 { 2163 result->background_color.ir = 2164 result->background_color.ig = 2165 result->background_color.ib = 0; 2166 result->background_color.dr = 2167 result->background_color.dg = 2168 result->background_color.db = 0; 2169 } 2170 2171 else 2172 { 2173 result->background_color.ir = 2174 result->background_color.ig = 2175 result->background_color.ib = BUFFER_INIT8 * 257; 2176 result->background_color.dr = 2177 result->background_color.dg = 2178 result->background_color.db = 0; 2179 } 2180 } 2181 2182 else /* sRGB output */ 2183 { 2184 if (background != NULL) 2185 { 2186 if (out_format & PNG_FORMAT_FLAG_COLOR) 2187 { 2188 result->background_color.ir = background->red; 2189 result->background_color.ig = background->green; 2190 result->background_color.ib = background->blue; 2191 /* TODO: sometimes libpng uses the power law conversion here, how 2192 * to handle this? 2193 */ 2194 result->background_color.dr = sRGB_to_d[background->red]; 2195 result->background_color.dg = sRGB_to_d[background->green]; 2196 result->background_color.db = sRGB_to_d[background->blue]; 2197 } 2198 2199 else /* grayscale: libpng only looks at 'g' */ 2200 { 2201 result->background_color.ir = 2202 result->background_color.ig = 2203 result->background_color.ib = background->green; 2204 /* TODO: sometimes libpng uses the power law conversion here, how 2205 * to handle this? 2206 */ 2207 result->background_color.dr = 2208 result->background_color.dg = 2209 result->background_color.db = sRGB_to_d[background->green]; 2210 } 2211 } 2212 2213 else if ((out_format & PNG_FORMAT_FLAG_COLORMAP) == 0) 2214 { 2215 result->background_color.ir = 2216 result->background_color.ig = 2217 result->background_color.ib = BUFFER_INIT8; 2218 /* TODO: sometimes libpng uses the power law conversion here, how 2219 * to handle this? 2220 */ 2221 result->background_color.dr = 2222 result->background_color.dg = 2223 result->background_color.db = sRGB_to_d[BUFFER_INIT8]; 2224 } 2225 2226 /* Else the output is colormapped and a background color must be 2227 * provided; if pngstest crashes then that is a bug in this program 2228 * (though libpng should png_error as well.) 2229 */ 2230 else 2231 result->background = NULL; 2232 } 2233 } 2234 2235 if (result->background == NULL) 2236 { 2237 result->background_color.ir = 2238 result->background_color.ig = 2239 result->background_color.ib = -1; /* not used */ 2240 result->background_color.dr = 2241 result->background_color.dg = 2242 result->background_color.db = 1E30; /* not used */ 2243 } 2244 2245 2246 /* Copy the error values into the Transform: */ 2247 result->error[0] = result->error_ptr[0]; 2248 result->error[1] = result->error_ptr[1]; 2249 result->error[2] = result->error_ptr[2]; 2250 result->error[3] = result->error_ptr[3]; 2251 } 2252 2253 2254 /* Compare two pixels. 2255 * 2256 * OLD error values: 2257 static int error_to_linear = 811; * by experiment * 2258 static int error_to_linear_grayscale = 424; * by experiment * 2259 static int error_to_sRGB = 6; * by experiment * 2260 static int error_to_sRGB_grayscale = 17; * libpng error by calculation + 2261 2 by experiment * 2262 static int error_in_compose = 2; * by experiment * 2263 static int error_in_premultiply = 1; 2264 * 2265 * The following is *just* the result of a round trip from 8-bit sRGB to linear 2266 * then back to 8-bit sRGB when it is done by libpng. There are two problems: 2267 * 2268 * 1) libpng currently uses a 2.2 power law with no linear segment, this results 2269 * in instability in the low values and even with 16-bit precision sRGB(1) ends 2270 * up mapping to sRGB(0) as a result of rounding in the 16-bit representation. 2271 * This gives an error of 1 in the handling of value 1 only. 2272 * 2273 * 2) libpng currently uses an intermediate 8-bit linear value in gamma 2274 * correction of 8-bit values. This results in many more errors, the worse of 2275 * which is mapping sRGB(14) to sRGB(0). 2276 * 2277 * The general 'error_via_linear' is more complex because of pre-multiplication, 2278 * this compounds the 8-bit errors according to the alpha value of the pixel. 2279 * As a result 256 values are pre-calculated for error_via_linear. 2280 */ 2281 #if 0 2282 static int error_in_libpng_gamma; 2283 static int error_via_linear[256]; /* Indexed by 8-bit alpha */ 2284 2285 static void 2286 init_error_via_linear(void) 2287 { 2288 int alpha; 2289 2290 error_via_linear[0] = 255; /* transparent pixel */ 2291 2292 for (alpha=1; alpha<=255; ++alpha) 2293 { 2294 /* 16-bit values less than 128.5 get rounded to 8-bit 0 and so the worst 2295 * case error arises with 16-bit 128.5, work out what sRGB 2296 * (non-associated) value generates 128.5; any value less than this is 2297 * going to map to 0, so the worst error is floor(value). 2298 * 2299 * Note that errors are considerably higher (more than a factor of 2) 2300 * because libpng uses a simple power law for sRGB data at present. 2301 * 2302 * Add .1 for arithmetic errors inside libpng. 2303 */ 2304 double v = floor(255*pow(.5/*(128.5 * 255 / 65535)*/ / alpha, 1/2.2)+.1); 2305 2306 error_via_linear[alpha] = (int)v; 2307 } 2308 2309 /* This is actually 14.99, but, despite the closeness to 15, 14 seems to work 2310 * ok in this case. 2311 */ 2312 error_in_libpng_gamma = 14; 2313 } 2314 #endif 2315 2316 static void 2317 print_pixel(char string[64], const Pixel *pixel, png_uint_32 format) 2318 { 2319 switch (format & (PNG_FORMAT_FLAG_ALPHA|PNG_FORMAT_FLAG_COLOR)) 2320 { 2321 case 0: 2322 sprintf(string, "%s(%d)", format_names[format], pixel->g); 2323 break; 2324 2325 case PNG_FORMAT_FLAG_ALPHA: 2326 sprintf(string, "%s(%d,%d)", format_names[format], pixel->g, 2327 pixel->a); 2328 break; 2329 2330 case PNG_FORMAT_FLAG_COLOR: 2331 sprintf(string, "%s(%d,%d,%d)", format_names[format], 2332 pixel->r, pixel->g, pixel->b); 2333 break; 2334 2335 case PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA: 2336 sprintf(string, "%s(%d,%d,%d,%d)", format_names[format], 2337 pixel->r, pixel->g, pixel->b, pixel->a); 2338 break; 2339 2340 default: 2341 sprintf(string, "invalid-format"); 2342 break; 2343 } 2344 } 2345 2346 static int 2347 logpixel(const Transform *transform, png_uint_32 x, png_uint_32 y, 2348 const Pixel *in, const Pixel *calc, const Pixel *out, const char *reason) 2349 { 2350 const png_uint_32 in_format = transform->in_image->image.format; 2351 const png_uint_32 out_format = transform->out_image->image.format; 2352 2353 png_uint_32 back_format = out_format & ~PNG_FORMAT_FLAG_ALPHA; 2354 const char *via_linear = ""; 2355 2356 char pixel_in[64], pixel_calc[64], pixel_out[64], pixel_loc[64]; 2357 char background_info[100]; 2358 2359 print_pixel(pixel_in, in, in_format); 2360 print_pixel(pixel_calc, calc, out_format); 2361 print_pixel(pixel_out, out, out_format); 2362 2363 if (transform->is_palette) 2364 sprintf(pixel_loc, "palette: %lu", (unsigned long)y); 2365 else 2366 sprintf(pixel_loc, "%lu,%lu", (unsigned long)x, (unsigned long)y); 2367 2368 if (transform->from_linear != NULL) 2369 { 2370 via_linear = " (via linear)"; 2371 /* And as a result the *read* format which did any background processing 2372 * was itself linear, so the background color information is also 2373 * linear. 2374 */ 2375 back_format |= PNG_FORMAT_FLAG_LINEAR; 2376 } 2377 2378 if (transform->background != NULL) 2379 { 2380 Pixel back; 2381 char pixel_back[64]; 2382 2383 back.r = transform->background->ir; 2384 back.g = transform->background->ig; 2385 back.b = transform->background->ib; 2386 back.a = -1; /* not used */ 2387 2388 print_pixel(pixel_back, &back, back_format); 2389 sprintf(background_info, " on background %s", pixel_back); 2390 } 2391 2392 else 2393 background_info[0] = 0; 2394 2395 if (transform->in_image->file_name != transform->out_image->file_name) 2396 { 2397 char error_buffer[512]; 2398 sprintf(error_buffer, 2399 "(%s) %s error%s:\n %s%s ->\n %s\n not: %s.\n" 2400 "Use --preserve and examine: ", pixel_loc, reason, via_linear, 2401 pixel_in, background_info, pixel_out, pixel_calc); 2402 return logerror(transform->in_image, transform->in_image->file_name, 2403 error_buffer, transform->out_image->file_name); 2404 } 2405 2406 else 2407 { 2408 char error_buffer[512]; 2409 sprintf(error_buffer, 2410 "(%s) %s error%s:\n %s%s ->\n %s\n not: %s.\n" 2411 " The error happened when reading the original file with this format.", 2412 pixel_loc, reason, via_linear, pixel_in, background_info, pixel_out, 2413 pixel_calc); 2414 return logerror(transform->in_image, transform->in_image->file_name, 2415 error_buffer, ""); 2416 } 2417 } 2418 2419 static int 2420 cmppixel(Transform *transform, png_const_voidp in, png_const_voidp out, 2421 png_uint_32 x, png_uint_32 y/*or palette index*/) 2422 { 2423 int maxerr; 2424 png_const_charp errmsg; 2425 Pixel pixel_in, pixel_calc, pixel_out; 2426 2427 transform->in_gp(&pixel_in, in); 2428 2429 if (transform->from_linear == NULL) 2430 transform->transform(&pixel_calc, &pixel_in, transform->background); 2431 2432 else 2433 { 2434 transform->transform(&pixel_out, &pixel_in, transform->background); 2435 transform->from_linear(&pixel_calc, &pixel_out, NULL); 2436 } 2437 2438 transform->out_gp(&pixel_out, out); 2439 2440 /* Eliminate the case where the input and output values match exactly. */ 2441 if (pixel_calc.a == pixel_out.a && pixel_calc.r == pixel_out.r && 2442 pixel_calc.g == pixel_out.g && pixel_calc.b == pixel_out.b) 2443 return 1; 2444 2445 /* Eliminate the case where the output pixel is transparent and the output 2446 * is 8-bit - any component values are valid. Don't check the input alpha 2447 * here to also skip the 16-bit small alpha cases. 2448 */ 2449 if (transform->output_8bit && pixel_calc.a == 0 && pixel_out.a == 0) 2450 return 1; 2451 2452 /* Check for alpha errors first; an alpha error can damage the components too 2453 * so avoid spurious checks on components if one is found. 2454 */ 2455 errmsg = NULL; 2456 { 2457 int err_a = abs(pixel_calc.a-pixel_out.a); 2458 2459 if (err_a > transform->error[3]) 2460 { 2461 /* If accumulating check the components too */ 2462 if (transform->accumulate) 2463 transform->error[3] = (png_uint_16)err_a; 2464 2465 else 2466 errmsg = "alpha"; 2467 } 2468 } 2469 2470 /* Now if *either* of the output alphas are 0 but alpha is within tolerance 2471 * eliminate the 8-bit component comparison. 2472 */ 2473 if (errmsg == NULL && transform->output_8bit && 2474 (pixel_calc.a == 0 || pixel_out.a == 0)) 2475 return 1; 2476 2477 if (errmsg == NULL) /* else just signal an alpha error */ 2478 { 2479 int err_r = abs(pixel_calc.r - pixel_out.r); 2480 int err_g = abs(pixel_calc.g - pixel_out.g); 2481 int err_b = abs(pixel_calc.b - pixel_out.b); 2482 int limit; 2483 2484 if ((err_r | err_g | err_b) == 0) 2485 return 1; /* exact match */ 2486 2487 /* Mismatch on a component, check the input alpha */ 2488 if (pixel_in.a >= transform->in_opaque) 2489 { 2490 errmsg = "opaque component"; 2491 limit = 2; /* opaque */ 2492 } 2493 2494 else if (pixel_in.a > 0) 2495 { 2496 errmsg = "alpha component"; 2497 limit = 1; /* partially transparent */ 2498 } 2499 2500 else 2501 { 2502 errmsg = "transparent component (background)"; 2503 limit = 0; /* transparent */ 2504 } 2505 2506 maxerr = err_r; 2507 if (maxerr < err_g) maxerr = err_g; 2508 if (maxerr < err_b) maxerr = err_b; 2509 2510 if (maxerr <= transform->error[limit]) 2511 return 1; /* within the error limits */ 2512 2513 /* Handle a component mis-match; log it, just return an error code, or 2514 * accumulate it. 2515 */ 2516 if (transform->accumulate) 2517 { 2518 transform->error[limit] = (png_uint_16)maxerr; 2519 return 1; /* to cause the caller to keep going */ 2520 } 2521 } 2522 2523 /* Failure to match and not accumulating, so the error must be logged. */ 2524 return logpixel(transform, x, y, &pixel_in, &pixel_calc, &pixel_out, errmsg); 2525 } 2526 2527 static png_byte 2528 component_loc(png_byte loc[4], png_uint_32 format) 2529 { 2530 /* Given a format return the number of channels and the location of 2531 * each channel. 2532 * 2533 * The mask 'loc' contains the component offset of the channels in the 2534 * following order. Note that if 'format' is grayscale the entries 1-3 must 2535 * all contain the location of the gray channel. 2536 * 2537 * 0: alpha 2538 * 1: red or gray 2539 * 2: green or gray 2540 * 3: blue or gray 2541 */ 2542 png_byte channels; 2543 2544 if (format & PNG_FORMAT_FLAG_COLOR) 2545 { 2546 channels = 3; 2547 2548 loc[2] = 1; 2549 2550 # ifdef PNG_FORMAT_BGR_SUPPORTED 2551 if (format & PNG_FORMAT_FLAG_BGR) 2552 { 2553 loc[1] = 2; 2554 loc[3] = 0; 2555 } 2556 2557 else 2558 # endif 2559 { 2560 loc[1] = 0; 2561 loc[3] = 2; 2562 } 2563 } 2564 2565 else 2566 { 2567 channels = 1; 2568 loc[1] = loc[2] = loc[3] = 0; 2569 } 2570 2571 if (format & PNG_FORMAT_FLAG_ALPHA) 2572 { 2573 # ifdef PNG_FORMAT_AFIRST_SUPPORTED 2574 if (format & PNG_FORMAT_FLAG_AFIRST) 2575 { 2576 loc[0] = 0; 2577 ++loc[1]; 2578 ++loc[2]; 2579 ++loc[3]; 2580 } 2581 2582 else 2583 # endif 2584 loc[0] = channels; 2585 2586 ++channels; 2587 } 2588 2589 else 2590 loc[0] = 4; /* not present */ 2591 2592 return channels; 2593 } 2594 2595 /* Compare two images, the original 'a', which was written out then read back in 2596 * to * give image 'b'. The formats may have been changed. 2597 */ 2598 static int 2599 compare_two_images(Image *a, Image *b, int via_linear, 2600 png_const_colorp background) 2601 { 2602 ptrdiff_t stridea = a->stride; 2603 ptrdiff_t strideb = b->stride; 2604 png_const_bytep rowa = a->buffer+16; 2605 png_const_bytep rowb = b->buffer+16; 2606 const png_uint_32 width = a->image.width; 2607 const png_uint_32 height = a->image.height; 2608 const png_uint_32 formata = a->image.format; 2609 const png_uint_32 formatb = b->image.format; 2610 const unsigned int a_sample = PNG_IMAGE_SAMPLE_SIZE(formata); 2611 const unsigned int b_sample = PNG_IMAGE_SAMPLE_SIZE(formatb); 2612 int alpha_added, alpha_removed; 2613 int bchannels; 2614 int btoa[4]; 2615 png_uint_32 y; 2616 Transform tr; 2617 2618 /* This should never happen: */ 2619 if (width != b->image.width || height != b->image.height) 2620 return logerror(a, a->file_name, ": width x height changed: ", 2621 b->file_name); 2622 2623 /* Set up the background and the transform */ 2624 transform_from_formats(&tr, a, b, background, via_linear); 2625 2626 /* Find the first row and inter-row space. */ 2627 if (!(formata & PNG_FORMAT_FLAG_COLORMAP) && 2628 (formata & PNG_FORMAT_FLAG_LINEAR)) 2629 stridea *= 2; 2630 2631 if (!(formatb & PNG_FORMAT_FLAG_COLORMAP) && 2632 (formatb & PNG_FORMAT_FLAG_LINEAR)) 2633 strideb *= 2; 2634 2635 if (stridea < 0) rowa += (height-1) * (-stridea); 2636 if (strideb < 0) rowb += (height-1) * (-strideb); 2637 2638 /* First shortcut the two colormap case by comparing the image data; if it 2639 * matches then we expect the colormaps to match, although this is not 2640 * absolutely necessary for an image match. If the colormaps fail to match 2641 * then there is a problem in libpng. 2642 */ 2643 if (formata & formatb & PNG_FORMAT_FLAG_COLORMAP) 2644 { 2645 /* Only check colormap entries that actually exist; */ 2646 png_const_bytep ppa, ppb; 2647 int match; 2648 png_byte in_use[256], amax = 0, bmax = 0; 2649 2650 memset(in_use, 0, sizeof in_use); 2651 2652 ppa = rowa; 2653 ppb = rowb; 2654 2655 /* Do this the slow way to accumulate the 'in_use' flags, don't break out 2656 * of the loop until the end; this validates the color-mapped data to 2657 * ensure all pixels are valid color-map indexes. 2658 */ 2659 for (y=0, match=1; y<height && match; ++y, ppa += stridea, ppb += strideb) 2660 { 2661 png_uint_32 x; 2662 2663 for (x=0; x<width; ++x) 2664 { 2665 png_byte bval = ppb[x]; 2666 png_byte aval = ppa[x]; 2667 2668 if (bval > bmax) 2669 bmax = bval; 2670 2671 if (bval != aval) 2672 match = 0; 2673 2674 in_use[aval] = 1; 2675 if (aval > amax) 2676 amax = aval; 2677 } 2678 } 2679 2680 /* If the buffers match then the colormaps must too. */ 2681 if (match) 2682 { 2683 /* Do the color-maps match, entry by entry? Only check the 'in_use' 2684 * entries. An error here should be logged as a color-map error. 2685 */ 2686 png_const_bytep a_cmap = (png_const_bytep)a->colormap; 2687 png_const_bytep b_cmap = (png_const_bytep)b->colormap; 2688 int result = 1; /* match by default */ 2689 2690 /* This is used in logpixel to get the error message correct. */ 2691 tr.is_palette = 1; 2692 2693 for (y=0; y<256; ++y, a_cmap += a_sample, b_cmap += b_sample) 2694 if (in_use[y]) 2695 { 2696 /* The colormap entries should be valid, but because libpng doesn't 2697 * do any checking at present the original image may contain invalid 2698 * pixel values. These cause an error here (at present) unless 2699 * accumulating errors in which case the program just ignores them. 2700 */ 2701 if (y >= a->image.colormap_entries) 2702 { 2703 if ((a->opts & ACCUMULATE) == 0) 2704 { 2705 char pindex[9]; 2706 sprintf(pindex, "%lu[%lu]", (unsigned long)y, 2707 (unsigned long)a->image.colormap_entries); 2708 logerror(a, a->file_name, ": bad pixel index: ", pindex); 2709 } 2710 result = 0; 2711 } 2712 2713 else if (y >= b->image.colormap_entries) 2714 { 2715 if ((b->opts & ACCUMULATE) == 0) 2716 { 2717 char pindex[9]; 2718 sprintf(pindex, "%lu[%lu]", (unsigned long)y, 2719 (unsigned long)b->image.colormap_entries); 2720 logerror(b, b->file_name, ": bad pixel index: ", pindex); 2721 } 2722 result = 0; 2723 } 2724 2725 /* All the mismatches are logged here; there can only be 256! */ 2726 else if (!cmppixel(&tr, a_cmap, b_cmap, 0, y)) 2727 result = 0; 2728 } 2729 2730 /* If reqested copy the error values back from the Transform. */ 2731 if (a->opts & ACCUMULATE) 2732 { 2733 tr.error_ptr[0] = tr.error[0]; 2734 tr.error_ptr[1] = tr.error[1]; 2735 tr.error_ptr[2] = tr.error[2]; 2736 tr.error_ptr[3] = tr.error[3]; 2737 result = 1; /* force a continue */ 2738 } 2739 2740 return result; 2741 } 2742 2743 /* else the image buffers don't match pixel-wise so compare sample values 2744 * instead, but first validate that the pixel indexes are in range (but 2745 * only if not accumulating, when the error is ignored.) 2746 */ 2747 else if ((a->opts & ACCUMULATE) == 0) 2748 { 2749 /* Check the original image first, 2750 * TODO: deal with input images with bad pixel values? 2751 */ 2752 if (amax >= a->image.colormap_entries) 2753 { 2754 char pindex[9]; 2755 sprintf(pindex, "%d[%lu]", amax, 2756 (unsigned long)a->image.colormap_entries); 2757 return logerror(a, a->file_name, ": bad pixel index: ", pindex); 2758 } 2759 2760 else if (bmax >= b->image.colormap_entries) 2761 { 2762 char pindex[9]; 2763 sprintf(pindex, "%d[%lu]", bmax, 2764 (unsigned long)b->image.colormap_entries); 2765 return logerror(b, b->file_name, ": bad pixel index: ", pindex); 2766 } 2767 } 2768 } 2769 2770 /* We can directly compare pixel values without the need to use the read 2771 * or transform support (i.e. a memory compare) if: 2772 * 2773 * 1) The bit depth has not changed. 2774 * 2) RGB to grayscale has not been done (the reverse is ok; we just compare 2775 * the three RGB values to the original grayscale.) 2776 * 3) An alpha channel has not been removed from an 8-bit format, or the 2777 * 8-bit alpha value of the pixel was 255 (opaque). 2778 * 2779 * If an alpha channel has been *added* then it must have the relevant opaque 2780 * value (255 or 65535). 2781 * 2782 * The fist two the tests (in the order given above) (using the boolean 2783 * equivalence !a && !b == !(a || b)) 2784 */ 2785 if (!(((formata ^ formatb) & PNG_FORMAT_FLAG_LINEAR) | 2786 (formata & (formatb ^ PNG_FORMAT_FLAG_COLOR) & PNG_FORMAT_FLAG_COLOR))) 2787 { 2788 /* Was an alpha channel changed? */ 2789 const png_uint_32 alpha_changed = (formata ^ formatb) & 2790 PNG_FORMAT_FLAG_ALPHA; 2791 2792 /* Was an alpha channel removed? (The third test.) If so the direct 2793 * comparison is only possible if the input alpha is opaque. 2794 */ 2795 alpha_removed = (formata & alpha_changed) != 0; 2796 2797 /* Was an alpha channel added? */ 2798 alpha_added = (formatb & alpha_changed) != 0; 2799 2800 /* The channels may have been moved between input and output, this finds 2801 * out how, recording the result in the btoa array, which says where in 2802 * 'a' to find each channel of 'b'. If alpha was added then btoa[alpha] 2803 * ends up as 4 (and is not used.) 2804 */ 2805 { 2806 int i; 2807 png_byte aloc[4]; 2808 png_byte bloc[4]; 2809 2810 /* The following are used only if the formats match, except that 2811 * 'bchannels' is a flag for matching formats. btoa[x] says, for each 2812 * channel in b, where to find the corresponding value in a, for the 2813 * bchannels. achannels may be different for a gray to rgb transform 2814 * (a will be 1 or 2, b will be 3 or 4 channels.) 2815 */ 2816 (void)component_loc(aloc, formata); 2817 bchannels = component_loc(bloc, formatb); 2818 2819 /* Hence the btoa array. */ 2820 for (i=0; i<4; ++i) if (bloc[i] < 4) 2821 btoa[bloc[i]] = aloc[i]; /* may be '4' for alpha */ 2822 2823 if (alpha_added) 2824 alpha_added = bloc[0]; /* location of alpha channel in image b */ 2825 2826 else 2827 alpha_added = 4; /* Won't match an image b channel */ 2828 2829 if (alpha_removed) 2830 alpha_removed = aloc[0]; /* location of alpha channel in image a */ 2831 2832 else 2833 alpha_removed = 4; 2834 } 2835 } 2836 2837 else 2838 { 2839 /* Direct compare is not possible, cancel out all the corresponding local 2840 * variables. 2841 */ 2842 bchannels = 0; 2843 alpha_removed = alpha_added = 4; 2844 btoa[3] = btoa[2] = btoa[1] = btoa[0] = 4; /* 4 == not present */ 2845 } 2846 2847 for (y=0; y<height; ++y, rowa += stridea, rowb += strideb) 2848 { 2849 png_const_bytep ppa, ppb; 2850 png_uint_32 x; 2851 2852 for (x=0, ppa=rowa, ppb=rowb; x<width; ++x) 2853 { 2854 png_const_bytep psa, psb; 2855 2856 if (formata & PNG_FORMAT_FLAG_COLORMAP) 2857 psa = (png_const_bytep)a->colormap + a_sample * *ppa++; 2858 else 2859 psa = ppa, ppa += a_sample; 2860 2861 if (formatb & PNG_FORMAT_FLAG_COLORMAP) 2862 psb = (png_const_bytep)b->colormap + b_sample * *ppb++; 2863 else 2864 psb = ppb, ppb += b_sample; 2865 2866 /* Do the fast test if possible. */ 2867 if (bchannels) 2868 { 2869 /* Check each 'b' channel against either the corresponding 'a' 2870 * channel or the opaque alpha value, as appropriate. If 2871 * alpha_removed value is set (not 4) then also do this only if the 2872 * 'a' alpha channel (alpha_removed) is opaque; only relevant for 2873 * the 8-bit case. 2874 */ 2875 if (formatb & PNG_FORMAT_FLAG_LINEAR) /* 16-bit checks */ 2876 { 2877 png_const_uint_16p pua = aligncastconst(png_const_uint_16p, psa); 2878 png_const_uint_16p pub = aligncastconst(png_const_uint_16p, psb); 2879 2880 switch (bchannels) 2881 { 2882 case 4: 2883 if (pua[btoa[3]] != pub[3]) break; 2884 case 3: 2885 if (pua[btoa[2]] != pub[2]) break; 2886 case 2: 2887 if (pua[btoa[1]] != pub[1]) break; 2888 case 1: 2889 if (pua[btoa[0]] != pub[0]) break; 2890 if (alpha_added != 4 && pub[alpha_added] != 65535) break; 2891 continue; /* x loop */ 2892 default: 2893 break; /* impossible */ 2894 } 2895 } 2896 2897 else if (alpha_removed == 4 || psa[alpha_removed] == 255) 2898 { 2899 switch (bchannels) 2900 { 2901 case 4: 2902 if (psa[btoa[3]] != psb[3]) break; 2903 case 3: 2904 if (psa[btoa[2]] != psb[2]) break; 2905 case 2: 2906 if (psa[btoa[1]] != psb[1]) break; 2907 case 1: 2908 if (psa[btoa[0]] != psb[0]) break; 2909 if (alpha_added != 4 && psb[alpha_added] != 255) break; 2910 continue; /* x loop */ 2911 default: 2912 break; /* impossible */ 2913 } 2914 } 2915 } 2916 2917 /* If we get to here the fast match failed; do the slow match for this 2918 * pixel. 2919 */ 2920 if (!cmppixel(&tr, psa, psb, x, y) && (a->opts & KEEP_GOING) == 0) 2921 return 0; /* error case */ 2922 } 2923 } 2924 2925 /* If reqested copy the error values back from the Transform. */ 2926 if (a->opts & ACCUMULATE) 2927 { 2928 tr.error_ptr[0] = tr.error[0]; 2929 tr.error_ptr[1] = tr.error[1]; 2930 tr.error_ptr[2] = tr.error[2]; 2931 tr.error_ptr[3] = tr.error[3]; 2932 } 2933 2934 return 1; 2935 } 2936 2937 /* Read the file; how the read gets done depends on which of input_file and 2938 * input_memory have been set. 2939 */ 2940 static int 2941 read_file(Image *image, png_uint_32 format, png_const_colorp background) 2942 { 2943 memset(&image->image, 0, sizeof image->image); 2944 image->image.version = PNG_IMAGE_VERSION; 2945 2946 if (image->input_memory != NULL) 2947 { 2948 if (!png_image_begin_read_from_memory(&image->image, image->input_memory, 2949 image->input_memory_size)) 2950 return logerror(image, "memory init: ", image->file_name, ""); 2951 } 2952 2953 # ifdef PNG_STDIO_SUPPORTED 2954 else if (image->input_file != NULL) 2955 { 2956 if (!png_image_begin_read_from_stdio(&image->image, image->input_file)) 2957 return logerror(image, "stdio init: ", image->file_name, ""); 2958 } 2959 2960 else 2961 { 2962 if (!png_image_begin_read_from_file(&image->image, image->file_name)) 2963 return logerror(image, "file init: ", image->file_name, ""); 2964 } 2965 # else 2966 else 2967 { 2968 return logerror(image, "unsupported file/stdio init: ", 2969 image->file_name, ""); 2970 } 2971 # endif 2972 2973 /* This must be set after the begin_read call: */ 2974 if (image->opts & sRGB_16BIT) 2975 image->image.flags |= PNG_IMAGE_FLAG_16BIT_sRGB; 2976 2977 /* Have an initialized image with all the data we need plus, maybe, an 2978 * allocated file (myfile) or buffer (mybuffer) that need to be freed. 2979 */ 2980 { 2981 int result; 2982 png_uint_32 image_format; 2983 2984 /* Print both original and output formats. */ 2985 image_format = image->image.format; 2986 2987 if (image->opts & VERBOSE) 2988 { 2989 printf("%s %lu x %lu %s -> %s", image->file_name, 2990 (unsigned long)image->image.width, 2991 (unsigned long)image->image.height, 2992 format_names[image_format & FORMAT_MASK], 2993 (format & FORMAT_NO_CHANGE) != 0 || image->image.format == format 2994 ? "no change" : format_names[format & FORMAT_MASK]); 2995 2996 if (background != NULL) 2997 printf(" background(%d,%d,%d)\n", background->red, 2998 background->green, background->blue); 2999 else 3000 printf("\n"); 3001 3002 fflush(stdout); 3003 } 3004 3005 /* 'NO_CHANGE' combined with the color-map flag forces the base format 3006 * flags to be set on read to ensure that the original representation is 3007 * not lost in the pass through a colormap format. 3008 */ 3009 if ((format & FORMAT_NO_CHANGE) != 0) 3010 { 3011 if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0 && 3012 (image_format & PNG_FORMAT_FLAG_COLORMAP) != 0) 3013 format = (image_format & ~BASE_FORMATS) | (format & BASE_FORMATS); 3014 3015 else 3016 format = image_format; 3017 } 3018 3019 image->image.format = format; 3020 3021 image->stride = PNG_IMAGE_ROW_STRIDE(image->image) + image->stride_extra; 3022 allocbuffer(image); 3023 3024 result = png_image_finish_read(&image->image, background, 3025 image->buffer+16, (png_int_32)image->stride, image->colormap); 3026 3027 checkbuffer(image, image->file_name); 3028 3029 if (result) 3030 return checkopaque(image); 3031 3032 else 3033 return logerror(image, image->file_name, ": image read failed", ""); 3034 } 3035 } 3036 3037 /* Reads from a filename, which must be in image->file_name, but uses 3038 * image->opts to choose the method. The file is always read in its native 3039 * format (the one the simplified API suggests). 3040 */ 3041 static int 3042 read_one_file(Image *image) 3043 { 3044 if (!(image->opts & USE_FILE) || (image->opts & USE_STDIO)) 3045 { 3046 /* memory or stdio. */ 3047 FILE *f = fopen(image->file_name, "rb"); 3048 3049 if (f != NULL) 3050 { 3051 if (image->opts & USE_FILE) 3052 image->input_file = f; 3053 3054 else /* memory */ 3055 { 3056 if (fseek(f, 0, SEEK_END) == 0) 3057 { 3058 long int cb = ftell(f); 3059 3060 if (cb > 0) 3061 { 3062 #ifndef __COVERITY__ 3063 if ((unsigned long int)cb <= (size_t)~(size_t)0) 3064 #endif 3065 { 3066 png_bytep b = voidcast(png_bytep, malloc((size_t)cb)); 3067 3068 if (b != NULL) 3069 { 3070 rewind(f); 3071 3072 if (fread(b, (size_t)cb, 1, f) == 1) 3073 { 3074 fclose(f); 3075 image->input_memory_size = cb; 3076 image->input_memory = b; 3077 } 3078 3079 else 3080 { 3081 free(b); 3082 return logclose(image, f, image->file_name, 3083 ": read failed: "); 3084 } 3085 } 3086 3087 else 3088 return logclose(image, f, image->file_name, 3089 ": out of memory: "); 3090 } 3091 3092 else 3093 return logclose(image, f, image->file_name, 3094 ": file too big for this architecture: "); 3095 /* cb is the length of the file as a (long) and 3096 * this is greater than the maximum amount of 3097 * memory that can be requested from malloc. 3098 */ 3099 } 3100 3101 else if (cb == 0) 3102 return logclose(image, f, image->file_name, 3103 ": zero length: "); 3104 3105 else 3106 return logclose(image, f, image->file_name, 3107 ": tell failed: "); 3108 } 3109 3110 else 3111 return logclose(image, f, image->file_name, ": seek failed: "); 3112 } 3113 } 3114 3115 else 3116 return logerror(image, image->file_name, ": open failed: ", 3117 strerror(errno)); 3118 } 3119 3120 return read_file(image, FORMAT_NO_CHANGE, NULL); 3121 } 3122 3123 #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED 3124 static int 3125 write_one_file(Image *output, Image *image, int convert_to_8bit) 3126 { 3127 if (image->opts & FAST_WRITE) 3128 image->image.flags |= PNG_IMAGE_FLAG_FAST; 3129 3130 if (image->opts & USE_STDIO) 3131 { 3132 #ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED 3133 #ifndef __COVERITY__ 3134 FILE *f = tmpfile(); 3135 #else 3136 /* Experimental. Coverity says tmpfile() is insecure because it 3137 * generates predictable names. 3138 * 3139 * It is possible to satisfy Coverity by using mkstemp(); however, 3140 * any platform supporting mkstemp() undoubtedly has a secure tmpfile() 3141 * implementation as well, and doesn't need the fix. Note that 3142 * the fix won't work on platforms that don't support mkstemp(). 3143 * 3144 * https://www.securecoding.cert.org/confluence/display/c/ 3145 * FIO21-C.+Do+not+create+temporary+files+in+shared+directories 3146 * says that most historic implementations of tmpfile() provide 3147 * only a limited number of possible temporary file names 3148 * (usually 26) before file names are recycled. That article also 3149 * provides a secure solution that unfortunately depends upon mkstemp(). 3150 */ 3151 char tmpfile[] = "pngstest-XXXXXX"; 3152 int filedes; 3153 FILE *f; 3154 umask(0177); 3155 filedes = mkstemp(tmpfile); 3156 if (filedes < 0) 3157 f = NULL; 3158 else 3159 { 3160 f = fdopen(filedes,"w+"); 3161 /* Hide the filename immediately and ensure that the file does 3162 * not exist after the program ends 3163 */ 3164 (void) unlink(tmpfile); 3165 } 3166 #endif 3167 3168 if (f != NULL) 3169 { 3170 if (png_image_write_to_stdio(&image->image, f, convert_to_8bit, 3171 image->buffer+16, (png_int_32)image->stride, image->colormap)) 3172 { 3173 if (fflush(f) == 0) 3174 { 3175 rewind(f); 3176 initimage(output, image->opts, "tmpfile", image->stride_extra); 3177 output->input_file = f; 3178 if (!checkopaque(image)) 3179 return 0; 3180 } 3181 3182 else 3183 return logclose(image, f, "tmpfile", ": flush: "); 3184 } 3185 3186 else 3187 { 3188 fclose(f); 3189 return logerror(image, "tmpfile", ": write failed", ""); 3190 } 3191 } 3192 3193 else 3194 return logerror(image, "tmpfile", ": open: ", strerror(errno)); 3195 #else /* SIMPLIFIED_WRITE_STDIO */ 3196 return logerror(image, "tmpfile", ": open: unsupported", ""); 3197 #endif /* SIMPLIFIED_WRITE_STDIO */ 3198 } 3199 3200 else if (image->opts & USE_FILE) 3201 { 3202 #ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED 3203 static int counter = 0; 3204 char name[32]; 3205 3206 sprintf(name, "%s%d.png", tmpf, ++counter); 3207 3208 if (png_image_write_to_file(&image->image, name, convert_to_8bit, 3209 image->buffer+16, (png_int_32)image->stride, image->colormap)) 3210 { 3211 initimage(output, image->opts, output->tmpfile_name, 3212 image->stride_extra); 3213 /* Afterwards, or freeimage will delete it! */ 3214 strcpy(output->tmpfile_name, name); 3215 3216 if (!checkopaque(image)) 3217 return 0; 3218 } 3219 3220 else 3221 return logerror(image, name, ": write failed", ""); 3222 #else /* SIMPLIFIED_WRITE_STDIO */ 3223 return logerror(image, "stdio", ": open: unsupported", ""); 3224 #endif /* SIMPLIFIED_WRITE_STDIO */ 3225 } 3226 3227 else /* use memory */ 3228 { 3229 png_alloc_size_t size; 3230 3231 if (png_image_write_get_memory_size(image->image, size, convert_to_8bit, 3232 image->buffer+16, (png_int_32)image->stride, image->colormap)) 3233 { 3234 /* This is non-fatal but ignoring it was causing serious problems in 3235 * the macro to be ignored: 3236 */ 3237 if (size > PNG_IMAGE_PNG_SIZE_MAX(image->image)) 3238 return logerror(image, "memory", ": PNG_IMAGE_SIZE_MAX wrong", ""); 3239 3240 initimage(output, image->opts, "memory", image->stride_extra); 3241 output->input_memory = malloc(size); 3242 3243 if (output->input_memory != NULL) 3244 { 3245 output->input_memory_size = size; 3246 3247 if (png_image_write_to_memory(&image->image, output->input_memory, 3248 &output->input_memory_size, convert_to_8bit, image->buffer+16, 3249 (png_int_32)image->stride, image->colormap)) 3250 { 3251 /* This is also non-fatal but it safes safer to error out anyway: 3252 */ 3253 if (size != output->input_memory_size) 3254 return logerror(image, "memory", ": memory size wrong", ""); 3255 } 3256 3257 else 3258 return logerror(image, "memory", ": write failed", ""); 3259 } 3260 3261 else 3262 return logerror(image, "memory", ": out of memory", ""); 3263 } 3264 3265 else 3266 return logerror(image, "memory", ": get size:", ""); 3267 } 3268 3269 /* 'output' has an initialized temporary image, read this back in and compare 3270 * this against the original: there should be no change since the original 3271 * format was written unmodified unless 'convert_to_8bit' was specified. 3272 * However, if the original image was color-mapped, a simple read will zap 3273 * the linear, color and maybe alpha flags, this will cause spurious failures 3274 * under some circumstances. 3275 */ 3276 if (read_file(output, image->image.format | FORMAT_NO_CHANGE, NULL)) 3277 { 3278 png_uint_32 original_format = image->image.format; 3279 3280 if (convert_to_8bit) 3281 original_format &= ~PNG_FORMAT_FLAG_LINEAR; 3282 3283 if ((output->image.format & BASE_FORMATS) != 3284 (original_format & BASE_FORMATS)) 3285 return logerror(image, image->file_name, ": format changed on read: ", 3286 output->file_name); 3287 3288 return compare_two_images(image, output, 0/*via linear*/, NULL); 3289 } 3290 3291 else 3292 return logerror(output, output->tmpfile_name, 3293 ": read of new file failed", ""); 3294 } 3295 #endif 3296 3297 static int 3298 testimage(Image *image, png_uint_32 opts, format_list *pf) 3299 { 3300 int result; 3301 Image copy; 3302 3303 /* Copy the original data, stealing it from 'image' */ 3304 checkopaque(image); 3305 copy = *image; 3306 3307 copy.opts = opts; 3308 copy.buffer = NULL; 3309 copy.bufsize = 0; 3310 copy.allocsize = 0; 3311 3312 image->input_file = NULL; 3313 image->input_memory = NULL; 3314 image->input_memory_size = 0; 3315 image->tmpfile_name[0] = 0; 3316 3317 { 3318 png_uint_32 counter; 3319 Image output; 3320 3321 newimage(&output); 3322 3323 result = 1; 3324 3325 /* Use the low bit of 'counter' to indicate whether or not to do alpha 3326 * removal with a background color or by composting onto the image; this 3327 * step gets skipped if it isn't relevant 3328 */ 3329 for (counter=0; counter<2*FORMAT_COUNT; ++counter) 3330 if (format_isset(pf, counter >> 1)) 3331 { 3332 png_uint_32 format = counter >> 1; 3333 3334 png_color background_color; 3335 png_colorp background = NULL; 3336 3337 /* If there is a format change that removes the alpha channel then 3338 * the background is relevant. If the output is 8-bit color-mapped 3339 * then a background color *must* be provided, otherwise there are 3340 * two tests to do - one with a color, the other with NULL. The 3341 * NULL test happens second. 3342 */ 3343 if ((counter & 1) == 0) 3344 { 3345 if ((format & PNG_FORMAT_FLAG_ALPHA) == 0 && 3346 (image->image.format & PNG_FORMAT_FLAG_ALPHA) != 0) 3347 { 3348 /* Alpha/transparency will be removed, the background is 3349 * relevant: make it a color the first time 3350 */ 3351 random_color(&background_color); 3352 background = &background_color; 3353 3354 /* BUT if the output is to a color-mapped 8-bit format then 3355 * the background must always be a color, so increment 'counter' 3356 * to skip the NULL test. 3357 */ 3358 if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0 && 3359 (format & PNG_FORMAT_FLAG_LINEAR) == 0) 3360 ++counter; 3361 } 3362 3363 /* Otherwise an alpha channel is not being eliminated, just leave 3364 * background NULL and skip the (counter & 1) NULL test. 3365 */ 3366 else 3367 ++counter; 3368 } 3369 /* else just use NULL for background */ 3370 3371 resetimage(©); 3372 copy.opts = opts; /* in case read_file needs to change it */ 3373 3374 result = read_file(©, format, background); 3375 if (!result) 3376 break; 3377 3378 /* Make sure the file just read matches the original file. */ 3379 result = compare_two_images(image, ©, 0/*via linear*/, background); 3380 if (!result) 3381 break; 3382 3383 # ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED 3384 /* Write the *copy* just made to a new file to make sure the write 3385 * side works ok. Check the conversion to sRGB if the copy is 3386 * linear. 3387 */ 3388 output.opts = opts; 3389 result = write_one_file(&output, ©, 0/*convert to 8bit*/); 3390 if (!result) 3391 break; 3392 3393 /* Validate against the original too; the background is needed here 3394 * as well so that compare_two_images knows what color was used. 3395 */ 3396 result = compare_two_images(image, &output, 0, background); 3397 if (!result) 3398 break; 3399 3400 if ((format & PNG_FORMAT_FLAG_LINEAR) != 0 && 3401 (format & PNG_FORMAT_FLAG_COLORMAP) == 0) 3402 { 3403 /* 'output' is linear, convert to the corresponding sRGB format. 3404 */ 3405 output.opts = opts; 3406 result = write_one_file(&output, ©, 1/*convert to 8bit*/); 3407 if (!result) 3408 break; 3409 3410 /* This may involve a conversion via linear; in the ideal world 3411 * this would round-trip correctly, but libpng 1.5.7 is not the 3412 * ideal world so allow a drift (error_via_linear). 3413 * 3414 * 'image' has an alpha channel but 'output' does not then there 3415 * will a strip-alpha-channel operation (because 'output' is 3416 * linear), handle this by composing on black when doing the 3417 * comparison. 3418 */ 3419 result = compare_two_images(image, &output, 1/*via_linear*/, 3420 background); 3421 if (!result) 3422 break; 3423 } 3424 # endif /* PNG_SIMPLIFIED_WRITE_SUPPORTED */ 3425 } 3426 3427 freeimage(&output); 3428 } 3429 3430 freeimage(©); 3431 3432 return result; 3433 } 3434 3435 static int 3436 test_one_file(const char *file_name, format_list *formats, png_uint_32 opts, 3437 int stride_extra, int log_pass) 3438 { 3439 int result; 3440 Image image; 3441 3442 if (!(opts & NO_RESEED)) 3443 reseed(); /* ensure that the random numbers don't depend on file order */ 3444 newimage(&image); 3445 initimage(&image, opts, file_name, stride_extra); 3446 result = read_one_file(&image); 3447 if (result) 3448 result = testimage(&image, opts, formats); 3449 freeimage(&image); 3450 3451 /* Ensure that stderr is flushed into any log file */ 3452 fflush(stderr); 3453 3454 if (log_pass) 3455 { 3456 if (result) 3457 printf("PASS:"); 3458 3459 else 3460 printf("FAIL:"); 3461 3462 # ifndef PNG_SIMPLIFIED_WRITE_SUPPORTED 3463 printf(" (no write)"); 3464 # endif 3465 3466 print_opts(opts); 3467 printf(" %s\n", file_name); 3468 /* stdout may not be line-buffered if it is piped to a file, so: */ 3469 fflush(stdout); 3470 } 3471 3472 else if (!result) 3473 exit(1); 3474 3475 return result; 3476 } 3477 3478 int 3479 main(int argc, char **argv) 3480 { 3481 png_uint_32 opts = FAST_WRITE | STRICT; 3482 format_list formats; 3483 const char *touch = NULL; 3484 int log_pass = 0; 3485 int redundant = 0; 3486 int stride_extra = 0; 3487 int retval = 0; 3488 int c; 3489 3490 #if PNG_LIBPNG_VER >= 10700 3491 /* This error should not exist in 1.7 or later: */ 3492 opts |= GBG_ERROR; 3493 #endif 3494 3495 init_sRGB_to_d(); 3496 #if 0 3497 init_error_via_linear(); 3498 #endif 3499 format_init(&formats); 3500 reseed(); /* initialize random number seeds */ 3501 3502 for (c=1; c<argc; ++c) 3503 { 3504 const char *arg = argv[c]; 3505 3506 if (strcmp(arg, "--log") == 0) 3507 log_pass = 1; 3508 else if (strcmp(arg, "--fresh") == 0) 3509 { 3510 memset(gpc_error, 0, sizeof gpc_error); 3511 memset(gpc_error_via_linear, 0, sizeof gpc_error_via_linear); 3512 } 3513 else if (strcmp(arg, "--file") == 0) 3514 # ifdef PNG_STDIO_SUPPORTED 3515 opts |= USE_FILE; 3516 # else 3517 return SKIP; /* skipped: no support */ 3518 # endif 3519 else if (strcmp(arg, "--memory") == 0) 3520 opts &= ~USE_FILE; 3521 else if (strcmp(arg, "--stdio") == 0) 3522 # ifdef PNG_STDIO_SUPPORTED 3523 opts |= USE_STDIO; 3524 # else 3525 return SKIP; /* skipped: no support */ 3526 # endif 3527 else if (strcmp(arg, "--name") == 0) 3528 opts &= ~USE_STDIO; 3529 else if (strcmp(arg, "--verbose") == 0) 3530 opts |= VERBOSE; 3531 else if (strcmp(arg, "--quiet") == 0) 3532 opts &= ~VERBOSE; 3533 else if (strcmp(arg, "--preserve") == 0) 3534 opts |= KEEP_TMPFILES; 3535 else if (strcmp(arg, "--nopreserve") == 0) 3536 opts &= ~KEEP_TMPFILES; 3537 else if (strcmp(arg, "--keep-going") == 0) 3538 opts |= KEEP_GOING; 3539 else if (strcmp(arg, "--fast") == 0) 3540 opts |= FAST_WRITE; 3541 else if (strcmp(arg, "--slow") == 0) 3542 opts &= ~FAST_WRITE; 3543 else if (strcmp(arg, "--accumulate") == 0) 3544 opts |= ACCUMULATE; 3545 else if (strcmp(arg, "--redundant") == 0) 3546 redundant = 1; 3547 else if (strcmp(arg, "--stop") == 0) 3548 opts &= ~KEEP_GOING; 3549 else if (strcmp(arg, "--strict") == 0) 3550 opts |= STRICT; 3551 else if (strcmp(arg, "--nostrict") == 0) 3552 opts &= ~STRICT; 3553 else if (strcmp(arg, "--sRGB-16bit") == 0) 3554 opts |= sRGB_16BIT; 3555 else if (strcmp(arg, "--linear-16bit") == 0) 3556 opts &= ~sRGB_16BIT; 3557 else if (strcmp(arg, "--noreseed") == 0) 3558 opts |= NO_RESEED; 3559 else if (strcmp(arg, "--fault-gbg-warning") == 0) 3560 opts |= GBG_ERROR; 3561 else if (strcmp(arg, "--tmpfile") == 0) 3562 { 3563 if (c+1 < argc) 3564 { 3565 if (strlen(argv[++c]) >= sizeof tmpf) 3566 { 3567 fflush(stdout); 3568 fprintf(stderr, "%s: %s is too long for a temp file prefix\n", 3569 argv[0], argv[c]); 3570 exit(99); 3571 } 3572 3573 /* Safe: checked above */ 3574 strncpy(tmpf, argv[c], sizeof (tmpf)-1); 3575 } 3576 3577 else 3578 { 3579 fflush(stdout); 3580 fprintf(stderr, "%s: %s requires a temporary file prefix\n", 3581 argv[0], arg); 3582 exit(99); 3583 } 3584 } 3585 else if (strcmp(arg, "--touch") == 0) 3586 { 3587 if (c+1 < argc) 3588 touch = argv[++c]; 3589 3590 else 3591 { 3592 fflush(stdout); 3593 fprintf(stderr, "%s: %s requires a file name argument\n", 3594 argv[0], arg); 3595 exit(99); 3596 } 3597 } 3598 else if (arg[0] == '+') 3599 { 3600 png_uint_32 format = formatof(arg+1); 3601 3602 if (format > FORMAT_COUNT) 3603 exit(99); 3604 3605 format_set(&formats, format); 3606 } 3607 else if (arg[0] == '-' && arg[1] != 0 && (arg[1] != '0' || arg[2] != 0)) 3608 { 3609 fflush(stdout); 3610 fprintf(stderr, "%s: unknown option: %s\n", argv[0], arg); 3611 exit(99); 3612 } 3613 else 3614 { 3615 if (format_is_initial(&formats)) 3616 format_default(&formats, redundant); 3617 3618 if (arg[0] == '-') 3619 { 3620 const int term = (arg[1] == '0' ? 0 : '\n'); 3621 unsigned int ich = 0; 3622 3623 /* Loop reading files, use a static buffer to simplify this and just 3624 * stop if the name gets to long. 3625 */ 3626 static char buffer[4096]; 3627 3628 do 3629 { 3630 int ch = getchar(); 3631 3632 /* Don't allow '\0' in file names, and terminate with '\n' or, 3633 * for -0, just '\0' (use -print0 to find to make this work!) 3634 */ 3635 if (ch == EOF || ch == term || ch == 0) 3636 { 3637 buffer[ich] = 0; 3638 3639 if (ich > 0 && !test_one_file(buffer, &formats, opts, 3640 stride_extra, log_pass)) 3641 retval = 1; 3642 3643 if (ch == EOF) 3644 break; 3645 3646 ich = 0; 3647 --ich; /* so that the increment below sets it to 0 again */ 3648 } 3649 3650 else 3651 buffer[ich] = (char)ch; 3652 } while (++ich < sizeof buffer); 3653 3654 if (ich) 3655 { 3656 buffer[32] = 0; 3657 buffer[4095] = 0; 3658 fprintf(stderr, "%s...%s: file name too long\n", buffer, 3659 buffer+(4096-32)); 3660 exit(99); 3661 } 3662 } 3663 3664 else if (!test_one_file(arg, &formats, opts, stride_extra, log_pass)) 3665 retval = 1; 3666 } 3667 } 3668 3669 if (opts & ACCUMULATE) 3670 { 3671 unsigned int in; 3672 3673 printf("/* contrib/libtests/pngstest-errors.h\n"); 3674 printf(" *\n"); 3675 printf(" * BUILT USING:" PNG_HEADER_VERSION_STRING); 3676 printf(" *\n"); 3677 printf(" * This code is released under the libpng license.\n"); 3678 printf(" * For conditions of distribution and use, see the disclaimer\n"); 3679 printf(" * and license in png.h\n"); 3680 printf(" *\n"); 3681 printf(" * THIS IS A MACHINE GENERATED FILE: do not edit it directly!\n"); 3682 printf(" * Instead run:\n"); 3683 printf(" *\n"); 3684 printf(" * pngstest --accumulate\n"); 3685 printf(" *\n"); 3686 printf(" * on as many PNG files as possible; at least PNGSuite and\n"); 3687 printf(" * contrib/libtests/testpngs.\n"); 3688 printf(" */\n"); 3689 3690 printf("static png_uint_16 gpc_error[16/*in*/][16/*out*/][4/*a*/] =\n"); 3691 printf("{\n"); 3692 for (in=0; in<16; ++in) 3693 { 3694 unsigned int out; 3695 printf(" { /* input: %s */\n ", format_names[in]); 3696 for (out=0; out<16; ++out) 3697 { 3698 unsigned int alpha; 3699 printf(" {"); 3700 for (alpha=0; alpha<4; ++alpha) 3701 { 3702 printf(" %d", gpc_error[in][out][alpha]); 3703 if (alpha < 3) putchar(','); 3704 } 3705 printf(" }"); 3706 if (out < 15) 3707 { 3708 putchar(','); 3709 if (out % 4 == 3) printf("\n "); 3710 } 3711 } 3712 printf("\n }"); 3713 3714 if (in < 15) 3715 putchar(','); 3716 else 3717 putchar('\n'); 3718 } 3719 printf("};\n"); 3720 3721 printf("static png_uint_16 gpc_error_via_linear[16][4/*out*/][4] =\n"); 3722 printf("{\n"); 3723 for (in=0; in<16; ++in) 3724 { 3725 unsigned int out; 3726 printf(" { /* input: %s */\n ", format_names[in]); 3727 for (out=0; out<4; ++out) 3728 { 3729 unsigned int alpha; 3730 printf(" {"); 3731 for (alpha=0; alpha<4; ++alpha) 3732 { 3733 printf(" %d", gpc_error_via_linear[in][out][alpha]); 3734 if (alpha < 3) putchar(','); 3735 } 3736 printf(" }"); 3737 if (out < 3) 3738 putchar(','); 3739 } 3740 printf("\n }"); 3741 3742 if (in < 15) 3743 putchar(','); 3744 else 3745 putchar('\n'); 3746 } 3747 printf("};\n"); 3748 3749 printf("static png_uint_16 gpc_error_to_colormap[8/*i*/][8/*o*/][4] =\n"); 3750 printf("{\n"); 3751 for (in=0; in<8; ++in) 3752 { 3753 unsigned int out; 3754 printf(" { /* input: %s */\n ", format_names[in]); 3755 for (out=0; out<8; ++out) 3756 { 3757 unsigned int alpha; 3758 printf(" {"); 3759 for (alpha=0; alpha<4; ++alpha) 3760 { 3761 printf(" %d", gpc_error_to_colormap[in][out][alpha]); 3762 if (alpha < 3) putchar(','); 3763 } 3764 printf(" }"); 3765 if (out < 7) 3766 { 3767 putchar(','); 3768 if (out % 4 == 3) printf("\n "); 3769 } 3770 } 3771 printf("\n }"); 3772 3773 if (in < 7) 3774 putchar(','); 3775 else 3776 putchar('\n'); 3777 } 3778 printf("};\n"); 3779 printf("/* END MACHINE GENERATED */\n"); 3780 } 3781 3782 if (retval == 0 && touch != NULL) 3783 { 3784 FILE *fsuccess = fopen(touch, "wt"); 3785 3786 if (fsuccess != NULL) 3787 { 3788 int error = 0; 3789 fprintf(fsuccess, "PNG simple API tests succeeded\n"); 3790 fflush(fsuccess); 3791 error = ferror(fsuccess); 3792 3793 if (fclose(fsuccess) || error) 3794 { 3795 fflush(stdout); 3796 fprintf(stderr, "%s: write failed\n", touch); 3797 exit(99); 3798 } 3799 } 3800 3801 else 3802 { 3803 fflush(stdout); 3804 fprintf(stderr, "%s: open failed\n", touch); 3805 exit(99); 3806 } 3807 } 3808 3809 return retval; 3810 } 3811 3812 #else /* !PNG_SIMPLIFIED_READ_SUPPORTED */ 3813 int main(void) 3814 { 3815 fprintf(stderr, "pngstest: no read support in libpng, test skipped\n"); 3816 /* So the test is skipped: */ 3817 return SKIP; 3818 } 3819 #endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ 3820