1 2 /* pngvalid.c - validate libpng by constructing then reading png files. 3 * 4 * Last changed in libpng 1.6.22 [(PENDING RELEASE)] 5 * Copyright (c) 2014-2016 Glenn Randers-Pehrson 6 * Written by John Cunningham Bowler 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 * NOTES: 13 * This is a C program that is intended to be linked against libpng. It 14 * generates bitmaps internally, stores them as PNG files (using the 15 * sequential write code) then reads them back (using the sequential 16 * read code) and validates that the result has the correct data. 17 * 18 * The program can be modified and extended to test the correctness of 19 * transformations performed by libpng. 20 */ 21 22 #define _POSIX_SOURCE 1 23 #define _ISOC99_SOURCE 1 /* For floating point */ 24 #define _GNU_SOURCE 1 /* For the floating point exception extension */ 25 26 #include <signal.h> 27 #include <stdio.h> 28 29 #if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) 30 # include <config.h> 31 #endif 32 33 #ifdef HAVE_FEENABLEEXCEPT /* from config.h, if included */ 34 # include <fenv.h> 35 #endif 36 37 #ifndef FE_DIVBYZERO 38 # define FE_DIVBYZERO 0 39 #endif 40 #ifndef FE_INVALID 41 # define FE_INVALID 0 42 #endif 43 #ifndef FE_OVERFLOW 44 # define FE_OVERFLOW 0 45 #endif 46 47 /* Define the following to use this test against your installed libpng, rather 48 * than the one being built here: 49 */ 50 #ifdef PNG_FREESTANDING_TESTS 51 # include <png.h> 52 #else 53 # include "../../png.h" 54 #endif 55 56 #ifdef PNG_ZLIB_HEADER 57 # include PNG_ZLIB_HEADER 58 #else 59 # include <zlib.h> /* For crc32 */ 60 #endif 61 62 /* 1.6.1 added support for the configure test harness, which uses 77 to indicate 63 * a skipped test, in earlier versions we need to succeed on a skipped test, so: 64 */ 65 #if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H) 66 # define SKIP 77 67 #else 68 # define SKIP 0 69 #endif 70 71 /* pngvalid requires write support and one of the fixed or floating point APIs. 72 */ 73 #if defined(PNG_WRITE_SUPPORTED) &&\ 74 (defined(PNG_FIXED_POINT_SUPPORTED) || defined(PNG_FLOATING_POINT_SUPPORTED)) 75 76 #if PNG_LIBPNG_VER < 10500 77 /* This deliberately lacks the const. */ 78 typedef png_byte *png_const_bytep; 79 80 /* This is copied from 1.5.1 png.h: */ 81 #define PNG_INTERLACE_ADAM7_PASSES 7 82 #define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7) 83 #define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7) 84 #define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) 85 #define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) 86 #define PNG_PASS_ROWS(height, pass) (((height)+(((1<<PNG_PASS_ROW_SHIFT(pass))\ 87 -1)-PNG_PASS_START_ROW(pass)))>>PNG_PASS_ROW_SHIFT(pass)) 88 #define PNG_PASS_COLS(width, pass) (((width)+(((1<<PNG_PASS_COL_SHIFT(pass))\ 89 -1)-PNG_PASS_START_COL(pass)))>>PNG_PASS_COL_SHIFT(pass)) 90 #define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ 91 (((yIn)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass)) 92 #define PNG_COL_FROM_PASS_COL(xIn, pass) \ 93 (((xIn)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass)) 94 #define PNG_PASS_MASK(pass,off) ( \ 95 ((0x110145AFU>>(((7-(off))-(pass))<<2)) & 0xFU) | \ 96 ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U)) 97 #define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ 98 ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) 99 #define PNG_COL_IN_INTERLACE_PASS(x, pass) \ 100 ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) 101 102 /* These are needed too for the default build: */ 103 #define PNG_WRITE_16BIT_SUPPORTED 104 #define PNG_READ_16BIT_SUPPORTED 105 106 /* This comes from pnglibconf.h afer 1.5: */ 107 #define PNG_FP_1 100000 108 #define PNG_GAMMA_THRESHOLD_FIXED\ 109 ((png_fixed_point)(PNG_GAMMA_THRESHOLD * PNG_FP_1)) 110 #endif 111 112 #if PNG_LIBPNG_VER < 10600 113 /* 1.6.0 constifies many APIs, the following exists to allow pngvalid to be 114 * compiled against earlier versions. 115 */ 116 # define png_const_structp png_structp 117 #endif 118 119 #ifndef RELEASE_BUILD 120 /* RELEASE_BUILD is true for releases and release candidates: */ 121 # define RELEASE_BUILD (PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC) 122 #endif 123 #if RELEASE_BUILD 124 # define debugonly(something) 125 #else /* !RELEASE_BUILD */ 126 # define debugonly(something) something 127 #endif /* !RELEASE_BUILD */ 128 129 #include <float.h> /* For floating point constants */ 130 #include <stdlib.h> /* For malloc */ 131 #include <string.h> /* For memcpy, memset */ 132 #include <math.h> /* For floor */ 133 134 /* Unused formal parameter errors are removed using the following macro which is 135 * expected to have no bad effects on performance. 136 */ 137 #ifndef UNUSED 138 # if defined(__GNUC__) || defined(_MSC_VER) 139 # define UNUSED(param) (void)param; 140 # else 141 # define UNUSED(param) 142 # endif 143 #endif 144 145 /***************************** EXCEPTION HANDLING *****************************/ 146 #ifdef PNG_FREESTANDING_TESTS 147 # include <cexcept.h> 148 #else 149 # include "../visupng/cexcept.h" 150 #endif 151 152 #ifdef __cplusplus 153 # define this not_the_cpp_this 154 # define new not_the_cpp_new 155 # define voidcast(type, value) static_cast<type>(value) 156 #else 157 # define voidcast(type, value) (value) 158 #endif /* __cplusplus */ 159 160 struct png_store; 161 define_exception_type(struct png_store*); 162 163 /* The following are macros to reduce typing everywhere where the well known 164 * name 'the_exception_context' must be defined. 165 */ 166 #define anon_context(ps) struct exception_context *the_exception_context = \ 167 &(ps)->exception_context 168 #define context(ps,fault) anon_context(ps); png_store *fault 169 170 /* This macro returns the number of elements in an array as an (unsigned int), 171 * it is necessary to avoid the inability of certain versions of GCC to use 172 * the value of a compile-time constant when performing range checks. It must 173 * be passed an array name. 174 */ 175 #define ARRAY_SIZE(a) ((unsigned int)((sizeof (a))/(sizeof (a)[0]))) 176 177 /* GCC BUG 66447 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66447) requires 178 * some broken GCC versions to be fixed up to avoid invalid whining about auto 179 * variables that are *not* changed within the scope of a setjmp being changed. 180 * 181 * Feel free to extend the list of broken versions. 182 */ 183 #define is_gnu(major,minor)\ 184 (defined __GNUC__) && __GNUC__ == (major) && __GNUC_MINOR__ == (minor) 185 #define is_gnu_patch(major,minor,patch)\ 186 is_gnu(major,minor) && __GNUC_PATCHLEVEL__ == 0 187 /* For the moment just do it always; all versions of GCC seem to be broken: */ 188 #ifdef __GNUC__ 189 const void * volatile make_volatile_for_gnu; 190 # define gnu_volatile(x) make_volatile_for_gnu = &x; 191 #else /* !GNUC broken versions */ 192 # define gnu_volatile(x) 193 #endif /* !GNUC broken versions */ 194 195 /******************************* UTILITIES ************************************/ 196 /* Error handling is particularly problematic in production code - error 197 * handlers often themselves have bugs which lead to programs that detect 198 * minor errors crashing. The following functions deal with one very 199 * common class of errors in error handlers - attempting to format error or 200 * warning messages into buffers that are too small. 201 */ 202 static size_t safecat(char *buffer, size_t bufsize, size_t pos, 203 const char *cat) 204 { 205 while (pos < bufsize && cat != NULL && *cat != 0) 206 buffer[pos++] = *cat++; 207 208 if (pos >= bufsize) 209 pos = bufsize-1; 210 211 buffer[pos] = 0; 212 return pos; 213 } 214 215 static size_t safecatn(char *buffer, size_t bufsize, size_t pos, int n) 216 { 217 char number[64]; 218 sprintf(number, "%d", n); 219 return safecat(buffer, bufsize, pos, number); 220 } 221 222 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 223 static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d, 224 int precision) 225 { 226 char number[64]; 227 sprintf(number, "%.*f", precision, d); 228 return safecat(buffer, bufsize, pos, number); 229 } 230 #endif 231 232 static const char invalid[] = "invalid"; 233 static const char sep[] = ": "; 234 235 static const char *colour_types[8] = 236 { 237 "grayscale", invalid, "truecolour", "indexed-colour", 238 "grayscale with alpha", invalid, "truecolour with alpha", invalid 239 }; 240 241 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 242 /* Convert a double precision value to fixed point. */ 243 static png_fixed_point 244 fix(double d) 245 { 246 d = floor(d * PNG_FP_1 + .5); 247 return (png_fixed_point)d; 248 } 249 #endif /* PNG_READ_SUPPORTED */ 250 251 /* Generate random bytes. This uses a boring repeatable algorithm and it 252 * is implemented here so that it gives the same set of numbers on every 253 * architecture. It's a linear congruential generator (Knuth or Sedgewick 254 * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and 255 * Hill, "The Art of Electronics" (Pseudo-Random Bit Sequences and Noise 256 * Generation.) 257 */ 258 static void 259 make_random_bytes(png_uint_32* seed, void* pv, size_t size) 260 { 261 png_uint_32 u0 = seed[0], u1 = seed[1]; 262 png_bytep bytes = voidcast(png_bytep, pv); 263 264 /* There are thirty three bits, the next bit in the sequence is bit-33 XOR 265 * bit-20. The top 1 bit is in u1, the bottom 32 are in u0. 266 */ 267 size_t i; 268 for (i=0; i<size; ++i) 269 { 270 /* First generate 8 new bits then shift them in at the end. */ 271 png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff; 272 u1 <<= 8; 273 u1 |= u0 >> 24; 274 u0 <<= 8; 275 u0 |= u; 276 *bytes++ = (png_byte)u; 277 } 278 279 seed[0] = u0; 280 seed[1] = u1; 281 } 282 283 static void 284 make_four_random_bytes(png_uint_32* seed, png_bytep bytes) 285 { 286 make_random_bytes(seed, bytes, 4); 287 } 288 289 #if defined PNG_READ_SUPPORTED || defined PNG_WRITE_tRNS_SUPPORTED ||\ 290 defined PNG_WRITE_FILTER_SUPPORTED 291 static void 292 randomize(void *pv, size_t size) 293 { 294 static png_uint_32 random_seed[2] = {0x56789abc, 0xd}; 295 make_random_bytes(random_seed, pv, size); 296 } 297 298 #define R8(this) randomize(&(this), sizeof (this)) 299 300 static void r16(png_uint_16p p16, size_t count) 301 { 302 size_t i; 303 304 for (i=0; i<count; ++i) 305 { 306 unsigned char b2[2]; 307 randomize(b2, sizeof b2); 308 *p16++ = png_get_uint_16(b2); 309 } 310 } 311 312 #define R16(this) r16(&(this), (sizeof (this))/(sizeof (png_uint_16))) 313 #define R16_1(this) r16(&(this), (size_t) 1U) 314 315 #if defined PNG_READ_RGB_TO_GRAY_SUPPORTED ||\ 316 defined PNG_READ_FILLER_SUPPORTED 317 static void r32(png_uint_32p p32, size_t count) 318 { 319 size_t i; 320 321 for (i=0; i<count; ++i) 322 { 323 unsigned char b4[4]; 324 randomize(b4, sizeof b4); 325 *p32++ = png_get_uint_32(b4); 326 } 327 } 328 329 #define R32(this) r32(&(this), (sizeof (this))/(sizeof (png_uint_32))) 330 #define R32_1(this) r32(&(this), (size_t) 1U) 331 332 #endif /* READ_FILLER || READ_RGB_TO_GRAY */ 333 334 #endif /* READ || WRITE_tRNS || WRITE_FILTER */ 335 336 #if defined PNG_READ_TRANSFORMS_SUPPORTED ||\ 337 defined PNG_WRITE_FILTER_SUPPORTED 338 static unsigned int 339 random_mod(unsigned int max) 340 { 341 png_uint_16 x; 342 343 R16_1(x); 344 345 return x % max; /* 0 .. max-1 */ 346 } 347 #endif /* READ_TRANSFORMS || WRITE_FILTER */ 348 349 #if (defined PNG_READ_RGB_TO_GRAY_SUPPORTED) ||\ 350 (defined PNG_READ_FILLER_SUPPORTED) 351 static int 352 random_choice(void) 353 { 354 unsigned char x; 355 356 R8(x); 357 358 return x & 1; 359 } 360 #endif /* READ_RGB_TO_GRAY || READ_FILLER */ 361 362 /* A numeric ID based on PNG file characteristics. The 'do_interlace' field 363 * simply records whether pngvalid did the interlace itself or whether it 364 * was done by libpng. Width and height must be less than 256. 'palette' is an 365 * index of the palette to use for formats with a palette otherwise a boolean 366 * indicating if a tRNS chunk was generated. 367 */ 368 #define FILEID(col, depth, palette, interlace, width, height, do_interlace) \ 369 ((png_uint_32)((col) + ((depth)<<3) + ((palette)<<8) + ((interlace)<<13) + \ 370 (((do_interlace)!=0)<<15) + ((width)<<16) + ((height)<<24))) 371 372 #define COL_FROM_ID(id) ((png_byte)((id)& 0x7U)) 373 #define DEPTH_FROM_ID(id) ((png_byte)(((id) >> 3) & 0x1fU)) 374 #define PALETTE_FROM_ID(id) (((id) >> 8) & 0x1f) 375 #define INTERLACE_FROM_ID(id) ((png_byte)(((id) >> 13) & 0x3)) 376 #define DO_INTERLACE_FROM_ID(id) ((int)(((id)>>15) & 1)) 377 #define WIDTH_FROM_ID(id) (((id)>>16) & 0xff) 378 #define HEIGHT_FROM_ID(id) (((id)>>24) & 0xff) 379 380 /* Utility to construct a standard name for a standard image. */ 381 static size_t 382 standard_name(char *buffer, size_t bufsize, size_t pos, png_byte colour_type, 383 int bit_depth, unsigned int npalette, int interlace_type, 384 png_uint_32 w, png_uint_32 h, int do_interlace) 385 { 386 pos = safecat(buffer, bufsize, pos, colour_types[colour_type]); 387 if (colour_type == 3) /* must have a palette */ 388 { 389 pos = safecat(buffer, bufsize, pos, "["); 390 pos = safecatn(buffer, bufsize, pos, npalette); 391 pos = safecat(buffer, bufsize, pos, "]"); 392 } 393 394 else if (npalette != 0) 395 pos = safecat(buffer, bufsize, pos, "+tRNS"); 396 397 pos = safecat(buffer, bufsize, pos, " "); 398 pos = safecatn(buffer, bufsize, pos, bit_depth); 399 pos = safecat(buffer, bufsize, pos, " bit"); 400 401 if (interlace_type != PNG_INTERLACE_NONE) 402 { 403 pos = safecat(buffer, bufsize, pos, " interlaced"); 404 if (do_interlace) 405 pos = safecat(buffer, bufsize, pos, "(pngvalid)"); 406 else 407 pos = safecat(buffer, bufsize, pos, "(libpng)"); 408 } 409 410 if (w > 0 || h > 0) 411 { 412 pos = safecat(buffer, bufsize, pos, " "); 413 pos = safecatn(buffer, bufsize, pos, w); 414 pos = safecat(buffer, bufsize, pos, "x"); 415 pos = safecatn(buffer, bufsize, pos, h); 416 } 417 418 return pos; 419 } 420 421 static size_t 422 standard_name_from_id(char *buffer, size_t bufsize, size_t pos, png_uint_32 id) 423 { 424 return standard_name(buffer, bufsize, pos, COL_FROM_ID(id), 425 DEPTH_FROM_ID(id), PALETTE_FROM_ID(id), INTERLACE_FROM_ID(id), 426 WIDTH_FROM_ID(id), HEIGHT_FROM_ID(id), DO_INTERLACE_FROM_ID(id)); 427 } 428 429 /* Convenience API and defines to list valid formats. Note that 16 bit read and 430 * write support is required to do 16 bit read tests (we must be able to make a 431 * 16 bit image to test!) 432 */ 433 #ifdef PNG_WRITE_16BIT_SUPPORTED 434 # define WRITE_BDHI 4 435 # ifdef PNG_READ_16BIT_SUPPORTED 436 # define READ_BDHI 4 437 # define DO_16BIT 438 # endif 439 #else 440 # define WRITE_BDHI 3 441 #endif 442 #ifndef DO_16BIT 443 # define READ_BDHI 3 444 #endif 445 446 /* The following defines the number of different palettes to generate for 447 * each log bit depth of a colour type 3 standard image. 448 */ 449 #define PALETTE_COUNT(bit_depth) ((bit_depth) > 4 ? 1U : 16U) 450 451 static int 452 next_format(png_bytep colour_type, png_bytep bit_depth, 453 unsigned int* palette_number, int low_depth_gray, int tRNS) 454 { 455 if (*bit_depth == 0) 456 { 457 *colour_type = 0; 458 if (low_depth_gray) 459 *bit_depth = 1; 460 else 461 *bit_depth = 8; 462 *palette_number = 0; 463 return 1; 464 } 465 466 if (*colour_type < 4/*no alpha channel*/) 467 { 468 /* Add multiple palettes for colour type 3, one image with tRNS 469 * and one without for other non-alpha formats: 470 */ 471 unsigned int pn = ++*palette_number; 472 png_byte ct = *colour_type; 473 474 if (((ct == 0/*GRAY*/ || ct/*RGB*/ == 2) && tRNS && pn < 2) || 475 (ct == 3/*PALETTE*/ && pn < PALETTE_COUNT(*bit_depth))) 476 return 1; 477 478 /* No: next bit depth */ 479 *palette_number = 0; 480 } 481 482 *bit_depth = (png_byte)(*bit_depth << 1); 483 484 /* Palette images are restricted to 8 bit depth */ 485 if (*bit_depth <= 8 486 #ifdef DO_16BIT 487 || (*colour_type != 3 && *bit_depth <= 16) 488 #endif 489 ) 490 return 1; 491 492 /* Move to the next color type, or return 0 at the end. */ 493 switch (*colour_type) 494 { 495 case 0: 496 *colour_type = 2; 497 *bit_depth = 8; 498 return 1; 499 500 case 2: 501 *colour_type = 3; 502 *bit_depth = 1; 503 return 1; 504 505 case 3: 506 *colour_type = 4; 507 *bit_depth = 8; 508 return 1; 509 510 case 4: 511 *colour_type = 6; 512 *bit_depth = 8; 513 return 1; 514 515 default: 516 return 0; 517 } 518 } 519 520 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 521 static unsigned int 522 sample(png_const_bytep row, png_byte colour_type, png_byte bit_depth, 523 png_uint_32 x, unsigned int sample_index, int swap16, int littleendian) 524 { 525 png_uint_32 bit_index, result; 526 527 /* Find a sample index for the desired sample: */ 528 x *= bit_depth; 529 bit_index = x; 530 531 if ((colour_type & 1) == 0) /* !palette */ 532 { 533 if (colour_type & 2) 534 bit_index *= 3; 535 536 if (colour_type & 4) 537 bit_index += x; /* Alpha channel */ 538 539 /* Multiple channels; select one: */ 540 if (colour_type & (2+4)) 541 bit_index += sample_index * bit_depth; 542 } 543 544 /* Return the sample from the row as an integer. */ 545 row += bit_index >> 3; 546 result = *row; 547 548 if (bit_depth == 8) 549 return result; 550 551 else if (bit_depth > 8) 552 { 553 if (swap16) 554 return (*++row << 8) + result; 555 else 556 return (result << 8) + *++row; 557 } 558 559 /* Less than 8 bits per sample. By default PNG has the big end of 560 * the egg on the left of the screen, but if littleendian is set 561 * then the big end is on the right. 562 */ 563 bit_index &= 7; 564 565 if (!littleendian) 566 bit_index = 8-bit_index-bit_depth; 567 568 return (result >> bit_index) & ((1U<<bit_depth)-1); 569 } 570 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 571 572 /* Copy a single pixel, of a given size, from one buffer to another - 573 * while this is basically bit addressed there is an implicit assumption 574 * that pixels 8 or more bits in size are byte aligned and that pixels 575 * do not otherwise cross byte boundaries. (This is, so far as I know, 576 * universally true in bitmap computer graphics. [JCB 20101212]) 577 * 578 * NOTE: The to and from buffers may be the same. 579 */ 580 static void 581 pixel_copy(png_bytep toBuffer, png_uint_32 toIndex, 582 png_const_bytep fromBuffer, png_uint_32 fromIndex, unsigned int pixelSize, 583 int littleendian) 584 { 585 /* Assume we can multiply by 'size' without overflow because we are 586 * just working in a single buffer. 587 */ 588 toIndex *= pixelSize; 589 fromIndex *= pixelSize; 590 if (pixelSize < 8) /* Sub-byte */ 591 { 592 /* Mask to select the location of the copied pixel: */ 593 unsigned int destMask = ((1U<<pixelSize)-1) << 594 (littleendian ? toIndex&7 : 8-pixelSize-(toIndex&7)); 595 /* The following read the entire pixels and clears the extra: */ 596 unsigned int destByte = toBuffer[toIndex >> 3] & ~destMask; 597 unsigned int sourceByte = fromBuffer[fromIndex >> 3]; 598 599 /* Don't rely on << or >> supporting '0' here, just in case: */ 600 fromIndex &= 7; 601 if (littleendian) 602 { 603 if (fromIndex > 0) sourceByte >>= fromIndex; 604 if ((toIndex & 7) > 0) sourceByte <<= toIndex & 7; 605 } 606 607 else 608 { 609 if (fromIndex > 0) sourceByte <<= fromIndex; 610 if ((toIndex & 7) > 0) sourceByte >>= toIndex & 7; 611 } 612 613 toBuffer[toIndex >> 3] = (png_byte)(destByte | (sourceByte & destMask)); 614 } 615 else /* One or more bytes */ 616 memmove(toBuffer+(toIndex>>3), fromBuffer+(fromIndex>>3), pixelSize>>3); 617 } 618 619 #ifdef PNG_READ_SUPPORTED 620 /* Copy a complete row of pixels, taking into account potential partial 621 * bytes at the end. 622 */ 623 static void 624 row_copy(png_bytep toBuffer, png_const_bytep fromBuffer, unsigned int bitWidth, 625 int littleendian) 626 { 627 memcpy(toBuffer, fromBuffer, bitWidth >> 3); 628 629 if ((bitWidth & 7) != 0) 630 { 631 unsigned int mask; 632 633 toBuffer += bitWidth >> 3; 634 fromBuffer += bitWidth >> 3; 635 if (littleendian) 636 mask = 0xff << (bitWidth & 7); 637 else 638 mask = 0xff >> (bitWidth & 7); 639 *toBuffer = (png_byte)((*toBuffer & mask) | (*fromBuffer & ~mask)); 640 } 641 } 642 643 /* Compare pixels - they are assumed to start at the first byte in the 644 * given buffers. 645 */ 646 static int 647 pixel_cmp(png_const_bytep pa, png_const_bytep pb, png_uint_32 bit_width) 648 { 649 #if PNG_LIBPNG_VER < 10506 650 if (memcmp(pa, pb, bit_width>>3) == 0) 651 { 652 png_uint_32 p; 653 654 if ((bit_width & 7) == 0) return 0; 655 656 /* Ok, any differences? */ 657 p = pa[bit_width >> 3]; 658 p ^= pb[bit_width >> 3]; 659 660 if (p == 0) return 0; 661 662 /* There are, but they may not be significant, remove the bits 663 * after the end (the low order bits in PNG.) 664 */ 665 bit_width &= 7; 666 p >>= 8-bit_width; 667 668 if (p == 0) return 0; 669 } 670 #else 671 /* From libpng-1.5.6 the overwrite should be fixed, so compare the trailing 672 * bits too: 673 */ 674 if (memcmp(pa, pb, (bit_width+7)>>3) == 0) 675 return 0; 676 #endif 677 678 /* Return the index of the changed byte. */ 679 { 680 png_uint_32 where = 0; 681 682 while (pa[where] == pb[where]) ++where; 683 return 1+where; 684 } 685 } 686 #endif /* PNG_READ_SUPPORTED */ 687 688 /*************************** BASIC PNG FILE WRITING ***************************/ 689 /* A png_store takes data from the sequential writer or provides data 690 * to the sequential reader. It can also store the result of a PNG 691 * write for later retrieval. 692 */ 693 #define STORE_BUFFER_SIZE 500 /* arbitrary */ 694 typedef struct png_store_buffer 695 { 696 struct png_store_buffer* prev; /* NOTE: stored in reverse order */ 697 png_byte buffer[STORE_BUFFER_SIZE]; 698 } png_store_buffer; 699 700 #define FILE_NAME_SIZE 64 701 702 typedef struct store_palette_entry /* record of a single palette entry */ 703 { 704 png_byte red; 705 png_byte green; 706 png_byte blue; 707 png_byte alpha; 708 } store_palette_entry, store_palette[256]; 709 710 typedef struct png_store_file 711 { 712 struct png_store_file* next; /* as many as you like... */ 713 char name[FILE_NAME_SIZE]; 714 png_uint_32 id; /* must be correct (see FILEID) */ 715 png_size_t datacount; /* In this (the last) buffer */ 716 png_store_buffer data; /* Last buffer in file */ 717 int npalette; /* Number of entries in palette */ 718 store_palette_entry* palette; /* May be NULL */ 719 } png_store_file; 720 721 /* The following is a pool of memory allocated by a single libpng read or write 722 * operation. 723 */ 724 typedef struct store_pool 725 { 726 struct png_store *store; /* Back pointer */ 727 struct store_memory *list; /* List of allocated memory */ 728 png_byte mark[4]; /* Before and after data */ 729 730 /* Statistics for this run. */ 731 png_alloc_size_t max; /* Maximum single allocation */ 732 png_alloc_size_t current; /* Current allocation */ 733 png_alloc_size_t limit; /* Highest current allocation */ 734 png_alloc_size_t total; /* Total allocation */ 735 736 /* Overall statistics (retained across successive runs). */ 737 png_alloc_size_t max_max; 738 png_alloc_size_t max_limit; 739 png_alloc_size_t max_total; 740 } store_pool; 741 742 typedef struct png_store 743 { 744 /* For cexcept.h exception handling - simply store one of these; 745 * the context is a self pointer but it may point to a different 746 * png_store (in fact it never does in this program.) 747 */ 748 struct exception_context 749 exception_context; 750 751 unsigned int verbose :1; 752 unsigned int treat_warnings_as_errors :1; 753 unsigned int expect_error :1; 754 unsigned int expect_warning :1; 755 unsigned int saw_warning :1; 756 unsigned int speed :1; 757 unsigned int progressive :1; /* use progressive read */ 758 unsigned int validated :1; /* used as a temporary flag */ 759 int nerrors; 760 int nwarnings; 761 int noptions; /* number of options below: */ 762 struct { 763 unsigned char option; /* option number, 0..30 */ 764 unsigned char setting; /* setting (unset,invalid,on,off) */ 765 } options[16]; 766 char test[128]; /* Name of test */ 767 char error[256]; 768 769 /* Read fields */ 770 png_structp pread; /* Used to read a saved file */ 771 png_infop piread; 772 png_store_file* current; /* Set when reading */ 773 png_store_buffer* next; /* Set when reading */ 774 png_size_t readpos; /* Position in *next */ 775 png_byte* image; /* Buffer for reading interlaced images */ 776 png_size_t cb_image; /* Size of this buffer */ 777 png_size_t cb_row; /* Row size of the image(s) */ 778 png_uint_32 image_h; /* Number of rows in a single image */ 779 store_pool read_memory_pool; 780 781 /* Write fields */ 782 png_store_file* saved; 783 png_structp pwrite; /* Used when writing a new file */ 784 png_infop piwrite; 785 png_size_t writepos; /* Position in .new */ 786 char wname[FILE_NAME_SIZE]; 787 png_store_buffer new; /* The end of the new PNG file being written. */ 788 store_pool write_memory_pool; 789 store_palette_entry* palette; 790 int npalette; 791 } png_store; 792 793 /* Initialization and cleanup */ 794 static void 795 store_pool_mark(png_bytep mark) 796 { 797 static png_uint_32 store_seed[2] = { 0x12345678, 1}; 798 799 make_four_random_bytes(store_seed, mark); 800 } 801 802 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 803 /* Use this for random 32 bit values; this function makes sure the result is 804 * non-zero. 805 */ 806 static png_uint_32 807 random_32(void) 808 { 809 810 for (;;) 811 { 812 png_byte mark[4]; 813 png_uint_32 result; 814 815 store_pool_mark(mark); 816 result = png_get_uint_32(mark); 817 818 if (result != 0) 819 return result; 820 } 821 } 822 #endif /* PNG_READ_SUPPORTED */ 823 824 static void 825 store_pool_init(png_store *ps, store_pool *pool) 826 { 827 memset(pool, 0, sizeof *pool); 828 829 pool->store = ps; 830 pool->list = NULL; 831 pool->max = pool->current = pool->limit = pool->total = 0; 832 pool->max_max = pool->max_limit = pool->max_total = 0; 833 store_pool_mark(pool->mark); 834 } 835 836 static void 837 store_init(png_store* ps) 838 { 839 memset(ps, 0, sizeof *ps); 840 init_exception_context(&ps->exception_context); 841 store_pool_init(ps, &ps->read_memory_pool); 842 store_pool_init(ps, &ps->write_memory_pool); 843 ps->verbose = 0; 844 ps->treat_warnings_as_errors = 0; 845 ps->expect_error = 0; 846 ps->expect_warning = 0; 847 ps->saw_warning = 0; 848 ps->speed = 0; 849 ps->progressive = 0; 850 ps->validated = 0; 851 ps->nerrors = ps->nwarnings = 0; 852 ps->pread = NULL; 853 ps->piread = NULL; 854 ps->saved = ps->current = NULL; 855 ps->next = NULL; 856 ps->readpos = 0; 857 ps->image = NULL; 858 ps->cb_image = 0; 859 ps->cb_row = 0; 860 ps->image_h = 0; 861 ps->pwrite = NULL; 862 ps->piwrite = NULL; 863 ps->writepos = 0; 864 ps->new.prev = NULL; 865 ps->palette = NULL; 866 ps->npalette = 0; 867 ps->noptions = 0; 868 } 869 870 static void 871 store_freebuffer(png_store_buffer* psb) 872 { 873 if (psb->prev) 874 { 875 store_freebuffer(psb->prev); 876 free(psb->prev); 877 psb->prev = NULL; 878 } 879 } 880 881 static void 882 store_freenew(png_store *ps) 883 { 884 store_freebuffer(&ps->new); 885 ps->writepos = 0; 886 if (ps->palette != NULL) 887 { 888 free(ps->palette); 889 ps->palette = NULL; 890 ps->npalette = 0; 891 } 892 } 893 894 static void 895 store_storenew(png_store *ps) 896 { 897 png_store_buffer *pb; 898 899 if (ps->writepos != STORE_BUFFER_SIZE) 900 png_error(ps->pwrite, "invalid store call"); 901 902 pb = voidcast(png_store_buffer*, malloc(sizeof *pb)); 903 904 if (pb == NULL) 905 png_error(ps->pwrite, "store new: OOM"); 906 907 *pb = ps->new; 908 ps->new.prev = pb; 909 ps->writepos = 0; 910 } 911 912 static void 913 store_freefile(png_store_file **ppf) 914 { 915 if (*ppf != NULL) 916 { 917 store_freefile(&(*ppf)->next); 918 919 store_freebuffer(&(*ppf)->data); 920 (*ppf)->datacount = 0; 921 if ((*ppf)->palette != NULL) 922 { 923 free((*ppf)->palette); 924 (*ppf)->palette = NULL; 925 (*ppf)->npalette = 0; 926 } 927 free(*ppf); 928 *ppf = NULL; 929 } 930 } 931 932 /* Main interface to file storeage, after writing a new PNG file (see the API 933 * below) call store_storefile to store the result with the given name and id. 934 */ 935 static void 936 store_storefile(png_store *ps, png_uint_32 id) 937 { 938 png_store_file *pf = voidcast(png_store_file*, malloc(sizeof *pf)); 939 if (pf == NULL) 940 png_error(ps->pwrite, "storefile: OOM"); 941 safecat(pf->name, sizeof pf->name, 0, ps->wname); 942 pf->id = id; 943 pf->data = ps->new; 944 pf->datacount = ps->writepos; 945 ps->new.prev = NULL; 946 ps->writepos = 0; 947 pf->palette = ps->palette; 948 pf->npalette = ps->npalette; 949 ps->palette = 0; 950 ps->npalette = 0; 951 952 /* And save it. */ 953 pf->next = ps->saved; 954 ps->saved = pf; 955 } 956 957 /* Generate an error message (in the given buffer) */ 958 static size_t 959 store_message(png_store *ps, png_const_structp pp, char *buffer, size_t bufsize, 960 size_t pos, const char *msg) 961 { 962 if (pp != NULL && pp == ps->pread) 963 { 964 /* Reading a file */ 965 pos = safecat(buffer, bufsize, pos, "read: "); 966 967 if (ps->current != NULL) 968 { 969 pos = safecat(buffer, bufsize, pos, ps->current->name); 970 pos = safecat(buffer, bufsize, pos, sep); 971 } 972 } 973 974 else if (pp != NULL && pp == ps->pwrite) 975 { 976 /* Writing a file */ 977 pos = safecat(buffer, bufsize, pos, "write: "); 978 pos = safecat(buffer, bufsize, pos, ps->wname); 979 pos = safecat(buffer, bufsize, pos, sep); 980 } 981 982 else 983 { 984 /* Neither reading nor writing (or a memory error in struct delete) */ 985 pos = safecat(buffer, bufsize, pos, "pngvalid: "); 986 } 987 988 if (ps->test[0] != 0) 989 { 990 pos = safecat(buffer, bufsize, pos, ps->test); 991 pos = safecat(buffer, bufsize, pos, sep); 992 } 993 pos = safecat(buffer, bufsize, pos, msg); 994 return pos; 995 } 996 997 /* Verbose output to the error stream: */ 998 static void 999 store_verbose(png_store *ps, png_const_structp pp, png_const_charp prefix, 1000 png_const_charp message) 1001 { 1002 char buffer[512]; 1003 1004 if (prefix) 1005 fputs(prefix, stderr); 1006 1007 (void)store_message(ps, pp, buffer, sizeof buffer, 0, message); 1008 fputs(buffer, stderr); 1009 fputc('\n', stderr); 1010 } 1011 1012 /* Log an error or warning - the relevant count is always incremented. */ 1013 static void 1014 store_log(png_store* ps, png_const_structp pp, png_const_charp message, 1015 int is_error) 1016 { 1017 /* The warning is copied to the error buffer if there are no errors and it is 1018 * the first warning. The error is copied to the error buffer if it is the 1019 * first error (overwriting any prior warnings). 1020 */ 1021 if (is_error ? (ps->nerrors)++ == 0 : 1022 (ps->nwarnings)++ == 0 && ps->nerrors == 0) 1023 store_message(ps, pp, ps->error, sizeof ps->error, 0, message); 1024 1025 if (ps->verbose) 1026 store_verbose(ps, pp, is_error ? "error: " : "warning: ", message); 1027 } 1028 1029 #ifdef PNG_READ_SUPPORTED 1030 /* Internal error function, called with a png_store but no libpng stuff. */ 1031 static void 1032 internal_error(png_store *ps, png_const_charp message) 1033 { 1034 store_log(ps, NULL, message, 1 /* error */); 1035 1036 /* And finally throw an exception. */ 1037 { 1038 struct exception_context *the_exception_context = &ps->exception_context; 1039 Throw ps; 1040 } 1041 } 1042 #endif /* PNG_READ_SUPPORTED */ 1043 1044 /* Functions to use as PNG callbacks. */ 1045 static void PNGCBAPI 1046 store_error(png_structp ppIn, png_const_charp message) /* PNG_NORETURN */ 1047 { 1048 png_const_structp pp = ppIn; 1049 png_store *ps = voidcast(png_store*, png_get_error_ptr(pp)); 1050 1051 if (!ps->expect_error) 1052 store_log(ps, pp, message, 1 /* error */); 1053 1054 /* And finally throw an exception. */ 1055 { 1056 struct exception_context *the_exception_context = &ps->exception_context; 1057 Throw ps; 1058 } 1059 } 1060 1061 static void PNGCBAPI 1062 store_warning(png_structp ppIn, png_const_charp message) 1063 { 1064 png_const_structp pp = ppIn; 1065 png_store *ps = voidcast(png_store*, png_get_error_ptr(pp)); 1066 1067 if (!ps->expect_warning) 1068 store_log(ps, pp, message, 0 /* warning */); 1069 else 1070 ps->saw_warning = 1; 1071 } 1072 1073 /* These somewhat odd functions are used when reading an image to ensure that 1074 * the buffer is big enough, the png_structp is for errors. 1075 */ 1076 /* Return a single row from the correct image. */ 1077 static png_bytep 1078 store_image_row(const png_store* ps, png_const_structp pp, int nImage, 1079 png_uint_32 y) 1080 { 1081 png_size_t coffset = (nImage * ps->image_h + y) * (ps->cb_row + 5) + 2; 1082 1083 if (ps->image == NULL) 1084 png_error(pp, "no allocated image"); 1085 1086 if (coffset + ps->cb_row + 3 > ps->cb_image) 1087 png_error(pp, "image too small"); 1088 1089 return ps->image + coffset; 1090 } 1091 1092 static void 1093 store_image_free(png_store *ps, png_const_structp pp) 1094 { 1095 if (ps->image != NULL) 1096 { 1097 png_bytep image = ps->image; 1098 1099 if (image[-1] != 0xed || image[ps->cb_image] != 0xfe) 1100 { 1101 if (pp != NULL) 1102 png_error(pp, "png_store image overwrite (1)"); 1103 else 1104 store_log(ps, NULL, "png_store image overwrite (2)", 1); 1105 } 1106 1107 ps->image = NULL; 1108 ps->cb_image = 0; 1109 --image; 1110 free(image); 1111 } 1112 } 1113 1114 static void 1115 store_ensure_image(png_store *ps, png_const_structp pp, int nImages, 1116 png_size_t cbRow, png_uint_32 cRows) 1117 { 1118 png_size_t cb = nImages * cRows * (cbRow + 5); 1119 1120 if (ps->cb_image < cb) 1121 { 1122 png_bytep image; 1123 1124 store_image_free(ps, pp); 1125 1126 /* The buffer is deliberately mis-aligned. */ 1127 image = voidcast(png_bytep, malloc(cb+2)); 1128 if (image == NULL) 1129 { 1130 /* Called from the startup - ignore the error for the moment. */ 1131 if (pp == NULL) 1132 return; 1133 1134 png_error(pp, "OOM allocating image buffer"); 1135 } 1136 1137 /* These magic tags are used to detect overwrites above. */ 1138 ++image; 1139 image[-1] = 0xed; 1140 image[cb] = 0xfe; 1141 1142 ps->image = image; 1143 ps->cb_image = cb; 1144 } 1145 1146 /* We have an adequate sized image; lay out the rows. There are 2 bytes at 1147 * the start and three at the end of each (this ensures that the row 1148 * alignment starts out odd - 2+1 and changes for larger images on each row.) 1149 */ 1150 ps->cb_row = cbRow; 1151 ps->image_h = cRows; 1152 1153 /* For error checking, the whole buffer is set to 10110010 (0xb2 - 178). 1154 * This deliberately doesn't match the bits in the size test image which are 1155 * outside the image; these are set to 0xff (all 1). To make the row 1156 * comparison work in the 'size' test case the size rows are pre-initialized 1157 * to the same value prior to calling 'standard_row'. 1158 */ 1159 memset(ps->image, 178, cb); 1160 1161 /* Then put in the marks. */ 1162 while (--nImages >= 0) 1163 { 1164 png_uint_32 y; 1165 1166 for (y=0; y<cRows; ++y) 1167 { 1168 png_bytep row = store_image_row(ps, pp, nImages, y); 1169 1170 /* The markers: */ 1171 row[-2] = 190; 1172 row[-1] = 239; 1173 row[cbRow] = 222; 1174 row[cbRow+1] = 173; 1175 row[cbRow+2] = 17; 1176 } 1177 } 1178 } 1179 1180 #ifdef PNG_READ_SUPPORTED 1181 static void 1182 store_image_check(const png_store* ps, png_const_structp pp, int iImage) 1183 { 1184 png_const_bytep image = ps->image; 1185 1186 if (image[-1] != 0xed || image[ps->cb_image] != 0xfe) 1187 png_error(pp, "image overwrite"); 1188 else 1189 { 1190 png_size_t cbRow = ps->cb_row; 1191 png_uint_32 rows = ps->image_h; 1192 1193 image += iImage * (cbRow+5) * ps->image_h; 1194 1195 image += 2; /* skip image first row markers */ 1196 1197 while (rows-- > 0) 1198 { 1199 if (image[-2] != 190 || image[-1] != 239) 1200 png_error(pp, "row start overwritten"); 1201 1202 if (image[cbRow] != 222 || image[cbRow+1] != 173 || 1203 image[cbRow+2] != 17) 1204 png_error(pp, "row end overwritten"); 1205 1206 image += cbRow+5; 1207 } 1208 } 1209 } 1210 #endif /* PNG_READ_SUPPORTED */ 1211 1212 static void PNGCBAPI 1213 store_write(png_structp ppIn, png_bytep pb, png_size_t st) 1214 { 1215 png_const_structp pp = ppIn; 1216 png_store *ps = voidcast(png_store*, png_get_io_ptr(pp)); 1217 1218 if (ps->pwrite != pp) 1219 png_error(pp, "store state damaged"); 1220 1221 while (st > 0) 1222 { 1223 size_t cb; 1224 1225 if (ps->writepos >= STORE_BUFFER_SIZE) 1226 store_storenew(ps); 1227 1228 cb = st; 1229 1230 if (cb > STORE_BUFFER_SIZE - ps->writepos) 1231 cb = STORE_BUFFER_SIZE - ps->writepos; 1232 1233 memcpy(ps->new.buffer + ps->writepos, pb, cb); 1234 pb += cb; 1235 st -= cb; 1236 ps->writepos += cb; 1237 } 1238 } 1239 1240 static void PNGCBAPI 1241 store_flush(png_structp ppIn) 1242 { 1243 UNUSED(ppIn) /*DOES NOTHING*/ 1244 } 1245 1246 #ifdef PNG_READ_SUPPORTED 1247 static size_t 1248 store_read_buffer_size(png_store *ps) 1249 { 1250 /* Return the bytes available for read in the current buffer. */ 1251 if (ps->next != &ps->current->data) 1252 return STORE_BUFFER_SIZE; 1253 1254 return ps->current->datacount; 1255 } 1256 1257 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 1258 /* Return total bytes available for read. */ 1259 static size_t 1260 store_read_buffer_avail(png_store *ps) 1261 { 1262 if (ps->current != NULL && ps->next != NULL) 1263 { 1264 png_store_buffer *next = &ps->current->data; 1265 size_t cbAvail = ps->current->datacount; 1266 1267 while (next != ps->next && next != NULL) 1268 { 1269 next = next->prev; 1270 cbAvail += STORE_BUFFER_SIZE; 1271 } 1272 1273 if (next != ps->next) 1274 png_error(ps->pread, "buffer read error"); 1275 1276 if (cbAvail > ps->readpos) 1277 return cbAvail - ps->readpos; 1278 } 1279 1280 return 0; 1281 } 1282 #endif 1283 1284 static int 1285 store_read_buffer_next(png_store *ps) 1286 { 1287 png_store_buffer *pbOld = ps->next; 1288 png_store_buffer *pbNew = &ps->current->data; 1289 if (pbOld != pbNew) 1290 { 1291 while (pbNew != NULL && pbNew->prev != pbOld) 1292 pbNew = pbNew->prev; 1293 1294 if (pbNew != NULL) 1295 { 1296 ps->next = pbNew; 1297 ps->readpos = 0; 1298 return 1; 1299 } 1300 1301 png_error(ps->pread, "buffer lost"); 1302 } 1303 1304 return 0; /* EOF or error */ 1305 } 1306 1307 /* Need separate implementation and callback to allow use of the same code 1308 * during progressive read, where the io_ptr is set internally by libpng. 1309 */ 1310 static void 1311 store_read_imp(png_store *ps, png_bytep pb, png_size_t st) 1312 { 1313 if (ps->current == NULL || ps->next == NULL) 1314 png_error(ps->pread, "store state damaged"); 1315 1316 while (st > 0) 1317 { 1318 size_t cbAvail = store_read_buffer_size(ps) - ps->readpos; 1319 1320 if (cbAvail > 0) 1321 { 1322 if (cbAvail > st) cbAvail = st; 1323 memcpy(pb, ps->next->buffer + ps->readpos, cbAvail); 1324 st -= cbAvail; 1325 pb += cbAvail; 1326 ps->readpos += cbAvail; 1327 } 1328 1329 else if (!store_read_buffer_next(ps)) 1330 png_error(ps->pread, "read beyond end of file"); 1331 } 1332 } 1333 1334 static void PNGCBAPI 1335 store_read(png_structp ppIn, png_bytep pb, png_size_t st) 1336 { 1337 png_const_structp pp = ppIn; 1338 png_store *ps = voidcast(png_store*, png_get_io_ptr(pp)); 1339 1340 if (ps == NULL || ps->pread != pp) 1341 png_error(pp, "bad store read call"); 1342 1343 store_read_imp(ps, pb, st); 1344 } 1345 1346 static void 1347 store_progressive_read(png_store *ps, png_structp pp, png_infop pi) 1348 { 1349 /* Notice that a call to store_read will cause this function to fail because 1350 * readpos will be set. 1351 */ 1352 if (ps->pread != pp || ps->current == NULL || ps->next == NULL) 1353 png_error(pp, "store state damaged (progressive)"); 1354 1355 do 1356 { 1357 if (ps->readpos != 0) 1358 png_error(pp, "store_read called during progressive read"); 1359 1360 png_process_data(pp, pi, ps->next->buffer, store_read_buffer_size(ps)); 1361 } 1362 while (store_read_buffer_next(ps)); 1363 } 1364 #endif /* PNG_READ_SUPPORTED */ 1365 1366 /* The caller must fill this in: */ 1367 static store_palette_entry * 1368 store_write_palette(png_store *ps, int npalette) 1369 { 1370 if (ps->pwrite == NULL) 1371 store_log(ps, NULL, "attempt to write palette without write stream", 1); 1372 1373 if (ps->palette != NULL) 1374 png_error(ps->pwrite, "multiple store_write_palette calls"); 1375 1376 /* This function can only return NULL if called with '0'! */ 1377 if (npalette > 0) 1378 { 1379 ps->palette = voidcast(store_palette_entry*, malloc(npalette * 1380 sizeof *ps->palette)); 1381 1382 if (ps->palette == NULL) 1383 png_error(ps->pwrite, "store new palette: OOM"); 1384 1385 ps->npalette = npalette; 1386 } 1387 1388 return ps->palette; 1389 } 1390 1391 #ifdef PNG_READ_SUPPORTED 1392 static store_palette_entry * 1393 store_current_palette(png_store *ps, int *npalette) 1394 { 1395 /* This is an internal error (the call has been made outside a read 1396 * operation.) 1397 */ 1398 if (ps->current == NULL) 1399 { 1400 store_log(ps, ps->pread, "no current stream for palette", 1); 1401 return NULL; 1402 } 1403 1404 /* The result may be null if there is no palette. */ 1405 *npalette = ps->current->npalette; 1406 return ps->current->palette; 1407 } 1408 #endif /* PNG_READ_SUPPORTED */ 1409 1410 /***************************** MEMORY MANAGEMENT*** ***************************/ 1411 #ifdef PNG_USER_MEM_SUPPORTED 1412 /* A store_memory is simply the header for an allocated block of memory. The 1413 * pointer returned to libpng is just after the end of the header block, the 1414 * allocated memory is followed by a second copy of the 'mark'. 1415 */ 1416 typedef struct store_memory 1417 { 1418 store_pool *pool; /* Originating pool */ 1419 struct store_memory *next; /* Singly linked list */ 1420 png_alloc_size_t size; /* Size of memory allocated */ 1421 png_byte mark[4]; /* ID marker */ 1422 } store_memory; 1423 1424 /* Handle a fatal error in memory allocation. This calls png_error if the 1425 * libpng struct is non-NULL, else it outputs a message and returns. This means 1426 * that a memory problem while libpng is running will abort (png_error) the 1427 * handling of particular file while one in cleanup (after the destroy of the 1428 * struct has returned) will simply keep going and free (or attempt to free) 1429 * all the memory. 1430 */ 1431 static void 1432 store_pool_error(png_store *ps, png_const_structp pp, const char *msg) 1433 { 1434 if (pp != NULL) 1435 png_error(pp, msg); 1436 1437 /* Else we have to do it ourselves. png_error eventually calls store_log, 1438 * above. store_log accepts a NULL png_structp - it just changes what gets 1439 * output by store_message. 1440 */ 1441 store_log(ps, pp, msg, 1 /* error */); 1442 } 1443 1444 static void 1445 store_memory_free(png_const_structp pp, store_pool *pool, store_memory *memory) 1446 { 1447 /* Note that pp may be NULL (see store_pool_delete below), the caller has 1448 * found 'memory' in pool->list *and* unlinked this entry, so this is a valid 1449 * pointer (for sure), but the contents may have been trashed. 1450 */ 1451 if (memory->pool != pool) 1452 store_pool_error(pool->store, pp, "memory corrupted (pool)"); 1453 1454 else if (memcmp(memory->mark, pool->mark, sizeof memory->mark) != 0) 1455 store_pool_error(pool->store, pp, "memory corrupted (start)"); 1456 1457 /* It should be safe to read the size field now. */ 1458 else 1459 { 1460 png_alloc_size_t cb = memory->size; 1461 1462 if (cb > pool->max) 1463 store_pool_error(pool->store, pp, "memory corrupted (size)"); 1464 1465 else if (memcmp((png_bytep)(memory+1)+cb, pool->mark, sizeof pool->mark) 1466 != 0) 1467 store_pool_error(pool->store, pp, "memory corrupted (end)"); 1468 1469 /* Finally give the library a chance to find problems too: */ 1470 else 1471 { 1472 pool->current -= cb; 1473 free(memory); 1474 } 1475 } 1476 } 1477 1478 static void 1479 store_pool_delete(png_store *ps, store_pool *pool) 1480 { 1481 if (pool->list != NULL) 1482 { 1483 fprintf(stderr, "%s: %s %s: memory lost (list follows):\n", ps->test, 1484 pool == &ps->read_memory_pool ? "read" : "write", 1485 pool == &ps->read_memory_pool ? (ps->current != NULL ? 1486 ps->current->name : "unknown file") : ps->wname); 1487 ++ps->nerrors; 1488 1489 do 1490 { 1491 store_memory *next = pool->list; 1492 pool->list = next->next; 1493 next->next = NULL; 1494 1495 fprintf(stderr, "\t%lu bytes @ %p\n", 1496 (unsigned long)next->size, (const void*)(next+1)); 1497 /* The NULL means this will always return, even if the memory is 1498 * corrupted. 1499 */ 1500 store_memory_free(NULL, pool, next); 1501 } 1502 while (pool->list != NULL); 1503 } 1504 1505 /* And reset the other fields too for the next time. */ 1506 if (pool->max > pool->max_max) pool->max_max = pool->max; 1507 pool->max = 0; 1508 if (pool->current != 0) /* unexpected internal error */ 1509 fprintf(stderr, "%s: %s %s: memory counter mismatch (internal error)\n", 1510 ps->test, pool == &ps->read_memory_pool ? "read" : "write", 1511 pool == &ps->read_memory_pool ? (ps->current != NULL ? 1512 ps->current->name : "unknown file") : ps->wname); 1513 pool->current = 0; 1514 1515 if (pool->limit > pool->max_limit) 1516 pool->max_limit = pool->limit; 1517 1518 pool->limit = 0; 1519 1520 if (pool->total > pool->max_total) 1521 pool->max_total = pool->total; 1522 1523 pool->total = 0; 1524 1525 /* Get a new mark too. */ 1526 store_pool_mark(pool->mark); 1527 } 1528 1529 /* The memory callbacks: */ 1530 static png_voidp PNGCBAPI 1531 store_malloc(png_structp ppIn, png_alloc_size_t cb) 1532 { 1533 png_const_structp pp = ppIn; 1534 store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp)); 1535 store_memory *new = voidcast(store_memory*, malloc(cb + (sizeof *new) + 1536 (sizeof pool->mark))); 1537 1538 if (new != NULL) 1539 { 1540 if (cb > pool->max) 1541 pool->max = cb; 1542 1543 pool->current += cb; 1544 1545 if (pool->current > pool->limit) 1546 pool->limit = pool->current; 1547 1548 pool->total += cb; 1549 1550 new->size = cb; 1551 memcpy(new->mark, pool->mark, sizeof new->mark); 1552 memcpy((png_byte*)(new+1) + cb, pool->mark, sizeof pool->mark); 1553 new->pool = pool; 1554 new->next = pool->list; 1555 pool->list = new; 1556 ++new; 1557 } 1558 1559 else 1560 { 1561 /* NOTE: the PNG user malloc function cannot use the png_ptr it is passed 1562 * other than to retrieve the allocation pointer! libpng calls the 1563 * store_malloc callback in two basic cases: 1564 * 1565 * 1) From png_malloc; png_malloc will do a png_error itself if NULL is 1566 * returned. 1567 * 2) From png_struct or png_info structure creation; png_malloc is 1568 * to return so cleanup can be performed. 1569 * 1570 * To handle this store_malloc can log a message, but can't do anything 1571 * else. 1572 */ 1573 store_log(pool->store, pp, "out of memory", 1 /* is_error */); 1574 } 1575 1576 return new; 1577 } 1578 1579 static void PNGCBAPI 1580 store_free(png_structp ppIn, png_voidp memory) 1581 { 1582 png_const_structp pp = ppIn; 1583 store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp)); 1584 store_memory *this = voidcast(store_memory*, memory), **test; 1585 1586 /* Because libpng calls store_free with a dummy png_struct when deleting 1587 * png_struct or png_info via png_destroy_struct_2 it is necessary to check 1588 * the passed in png_structp to ensure it is valid, and not pass it to 1589 * png_error if it is not. 1590 */ 1591 if (pp != pool->store->pread && pp != pool->store->pwrite) 1592 pp = NULL; 1593 1594 /* First check that this 'memory' really is valid memory - it must be in the 1595 * pool list. If it is, use the shared memory_free function to free it. 1596 */ 1597 --this; 1598 for (test = &pool->list; *test != this; test = &(*test)->next) 1599 { 1600 if (*test == NULL) 1601 { 1602 store_pool_error(pool->store, pp, "bad pointer to free"); 1603 return; 1604 } 1605 } 1606 1607 /* Unlink this entry, *test == this. */ 1608 *test = this->next; 1609 this->next = NULL; 1610 store_memory_free(pp, pool, this); 1611 } 1612 #endif /* PNG_USER_MEM_SUPPORTED */ 1613 1614 /* Setup functions. */ 1615 /* Cleanup when aborting a write or after storing the new file. */ 1616 static void 1617 store_write_reset(png_store *ps) 1618 { 1619 if (ps->pwrite != NULL) 1620 { 1621 anon_context(ps); 1622 1623 Try 1624 png_destroy_write_struct(&ps->pwrite, &ps->piwrite); 1625 1626 Catch_anonymous 1627 { 1628 /* memory corruption: continue. */ 1629 } 1630 1631 ps->pwrite = NULL; 1632 ps->piwrite = NULL; 1633 } 1634 1635 /* And make sure that all the memory has been freed - this will output 1636 * spurious errors in the case of memory corruption above, but this is safe. 1637 */ 1638 # ifdef PNG_USER_MEM_SUPPORTED 1639 store_pool_delete(ps, &ps->write_memory_pool); 1640 # endif 1641 1642 store_freenew(ps); 1643 } 1644 1645 /* The following is the main write function, it returns a png_struct and, 1646 * optionally, a png_info suitable for writiing a new PNG file. Use 1647 * store_storefile above to record this file after it has been written. The 1648 * returned libpng structures as destroyed by store_write_reset above. 1649 */ 1650 static png_structp 1651 set_store_for_write(png_store *ps, png_infopp ppi, const char *name) 1652 { 1653 anon_context(ps); 1654 1655 Try 1656 { 1657 if (ps->pwrite != NULL) 1658 png_error(ps->pwrite, "write store already in use"); 1659 1660 store_write_reset(ps); 1661 safecat(ps->wname, sizeof ps->wname, 0, name); 1662 1663 /* Don't do the slow memory checks if doing a speed test, also if user 1664 * memory is not supported we can't do it anyway. 1665 */ 1666 # ifdef PNG_USER_MEM_SUPPORTED 1667 if (!ps->speed) 1668 ps->pwrite = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, 1669 ps, store_error, store_warning, &ps->write_memory_pool, 1670 store_malloc, store_free); 1671 1672 else 1673 # endif 1674 ps->pwrite = png_create_write_struct(PNG_LIBPNG_VER_STRING, 1675 ps, store_error, store_warning); 1676 1677 png_set_write_fn(ps->pwrite, ps, store_write, store_flush); 1678 1679 # ifdef PNG_SET_OPTION_SUPPORTED 1680 { 1681 int opt; 1682 for (opt=0; opt<ps->noptions; ++opt) 1683 if (png_set_option(ps->pwrite, ps->options[opt].option, 1684 ps->options[opt].setting) == PNG_OPTION_INVALID) 1685 png_error(ps->pwrite, "png option invalid"); 1686 } 1687 # endif 1688 1689 if (ppi != NULL) 1690 *ppi = ps->piwrite = png_create_info_struct(ps->pwrite); 1691 } 1692 1693 Catch_anonymous 1694 return NULL; 1695 1696 return ps->pwrite; 1697 } 1698 1699 /* Cleanup when finished reading (either due to error or in the success case). 1700 * This routine exists even when there is no read support to make the code 1701 * tidier (avoid a mass of ifdefs) and so easier to maintain. 1702 */ 1703 static void 1704 store_read_reset(png_store *ps) 1705 { 1706 # ifdef PNG_READ_SUPPORTED 1707 if (ps->pread != NULL) 1708 { 1709 anon_context(ps); 1710 1711 Try 1712 png_destroy_read_struct(&ps->pread, &ps->piread, NULL); 1713 1714 Catch_anonymous 1715 { 1716 /* error already output: continue */ 1717 } 1718 1719 ps->pread = NULL; 1720 ps->piread = NULL; 1721 } 1722 # endif 1723 1724 # ifdef PNG_USER_MEM_SUPPORTED 1725 /* Always do this to be safe. */ 1726 store_pool_delete(ps, &ps->read_memory_pool); 1727 # endif 1728 1729 ps->current = NULL; 1730 ps->next = NULL; 1731 ps->readpos = 0; 1732 ps->validated = 0; 1733 } 1734 1735 #ifdef PNG_READ_SUPPORTED 1736 static void 1737 store_read_set(png_store *ps, png_uint_32 id) 1738 { 1739 png_store_file *pf = ps->saved; 1740 1741 while (pf != NULL) 1742 { 1743 if (pf->id == id) 1744 { 1745 ps->current = pf; 1746 ps->next = NULL; 1747 store_read_buffer_next(ps); 1748 return; 1749 } 1750 1751 pf = pf->next; 1752 } 1753 1754 { 1755 size_t pos; 1756 char msg[FILE_NAME_SIZE+64]; 1757 1758 pos = standard_name_from_id(msg, sizeof msg, 0, id); 1759 pos = safecat(msg, sizeof msg, pos, ": file not found"); 1760 png_error(ps->pread, msg); 1761 } 1762 } 1763 1764 /* The main interface for reading a saved file - pass the id number of the file 1765 * to retrieve. Ids must be unique or the earlier file will be hidden. The API 1766 * returns a png_struct and, optionally, a png_info. Both of these will be 1767 * destroyed by store_read_reset above. 1768 */ 1769 static png_structp 1770 set_store_for_read(png_store *ps, png_infopp ppi, png_uint_32 id, 1771 const char *name) 1772 { 1773 /* Set the name for png_error */ 1774 safecat(ps->test, sizeof ps->test, 0, name); 1775 1776 if (ps->pread != NULL) 1777 png_error(ps->pread, "read store already in use"); 1778 1779 store_read_reset(ps); 1780 1781 /* Both the create APIs can return NULL if used in their default mode 1782 * (because there is no other way of handling an error because the jmp_buf 1783 * by default is stored in png_struct and that has not been allocated!) 1784 * However, given that store_error works correctly in these circumstances 1785 * we don't ever expect NULL in this program. 1786 */ 1787 # ifdef PNG_USER_MEM_SUPPORTED 1788 if (!ps->speed) 1789 ps->pread = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, ps, 1790 store_error, store_warning, &ps->read_memory_pool, store_malloc, 1791 store_free); 1792 1793 else 1794 # endif 1795 ps->pread = png_create_read_struct(PNG_LIBPNG_VER_STRING, ps, store_error, 1796 store_warning); 1797 1798 if (ps->pread == NULL) 1799 { 1800 struct exception_context *the_exception_context = &ps->exception_context; 1801 1802 store_log(ps, NULL, "png_create_read_struct returned NULL (unexpected)", 1803 1 /*error*/); 1804 1805 Throw ps; 1806 } 1807 1808 # ifdef PNG_SET_OPTION_SUPPORTED 1809 { 1810 int opt; 1811 for (opt=0; opt<ps->noptions; ++opt) 1812 if (png_set_option(ps->pread, ps->options[opt].option, 1813 ps->options[opt].setting) == PNG_OPTION_INVALID) 1814 png_error(ps->pread, "png option invalid"); 1815 } 1816 # endif 1817 1818 store_read_set(ps, id); 1819 1820 if (ppi != NULL) 1821 *ppi = ps->piread = png_create_info_struct(ps->pread); 1822 1823 return ps->pread; 1824 } 1825 #endif /* PNG_READ_SUPPORTED */ 1826 1827 /* The overall cleanup of a store simply calls the above then removes all the 1828 * saved files. This does not delete the store itself. 1829 */ 1830 static void 1831 store_delete(png_store *ps) 1832 { 1833 store_write_reset(ps); 1834 store_read_reset(ps); 1835 store_freefile(&ps->saved); 1836 store_image_free(ps, NULL); 1837 } 1838 1839 /*********************** PNG FILE MODIFICATION ON READ ************************/ 1840 /* Files may be modified on read. The following structure contains a complete 1841 * png_store together with extra members to handle modification and a special 1842 * read callback for libpng. To use this the 'modifications' field must be set 1843 * to a list of png_modification structures that actually perform the 1844 * modification, otherwise a png_modifier is functionally equivalent to a 1845 * png_store. There is a special read function, set_modifier_for_read, which 1846 * replaces set_store_for_read. 1847 */ 1848 typedef enum modifier_state 1849 { 1850 modifier_start, /* Initial value */ 1851 modifier_signature, /* Have a signature */ 1852 modifier_IHDR /* Have an IHDR */ 1853 } modifier_state; 1854 1855 typedef struct CIE_color 1856 { 1857 /* A single CIE tristimulus value, representing the unique response of a 1858 * standard observer to a variety of light spectra. The observer recognizes 1859 * all spectra that produce this response as the same color, therefore this 1860 * is effectively a description of a color. 1861 */ 1862 double X, Y, Z; 1863 } CIE_color; 1864 1865 typedef struct color_encoding 1866 { 1867 /* A description of an (R,G,B) encoding of color (as defined above); this 1868 * includes the actual colors of the (R,G,B) triples (1,0,0), (0,1,0) and 1869 * (0,0,1) plus an encoding value that is used to encode the linear 1870 * components R, G and B to give the actual values R^gamma, G^gamma and 1871 * B^gamma that are stored. 1872 */ 1873 double gamma; /* Encoding (file) gamma of space */ 1874 CIE_color red, green, blue; /* End points */ 1875 } color_encoding; 1876 1877 #ifdef PNG_READ_SUPPORTED 1878 #if defined PNG_READ_TRANSFORMS_SUPPORTED && defined PNG_READ_cHRM_SUPPORTED 1879 static double 1880 chromaticity_x(CIE_color c) 1881 { 1882 return c.X / (c.X + c.Y + c.Z); 1883 } 1884 1885 static double 1886 chromaticity_y(CIE_color c) 1887 { 1888 return c.Y / (c.X + c.Y + c.Z); 1889 } 1890 1891 static CIE_color 1892 white_point(const color_encoding *encoding) 1893 { 1894 CIE_color white; 1895 1896 white.X = encoding->red.X + encoding->green.X + encoding->blue.X; 1897 white.Y = encoding->red.Y + encoding->green.Y + encoding->blue.Y; 1898 white.Z = encoding->red.Z + encoding->green.Z + encoding->blue.Z; 1899 1900 return white; 1901 } 1902 #endif /* READ_TRANSFORMS && READ_cHRM */ 1903 1904 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 1905 static void 1906 normalize_color_encoding(color_encoding *encoding) 1907 { 1908 const double whiteY = encoding->red.Y + encoding->green.Y + 1909 encoding->blue.Y; 1910 1911 if (whiteY != 1) 1912 { 1913 encoding->red.X /= whiteY; 1914 encoding->red.Y /= whiteY; 1915 encoding->red.Z /= whiteY; 1916 encoding->green.X /= whiteY; 1917 encoding->green.Y /= whiteY; 1918 encoding->green.Z /= whiteY; 1919 encoding->blue.X /= whiteY; 1920 encoding->blue.Y /= whiteY; 1921 encoding->blue.Z /= whiteY; 1922 } 1923 } 1924 #endif 1925 1926 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 1927 static size_t 1928 safecat_color_encoding(char *buffer, size_t bufsize, size_t pos, 1929 const color_encoding *e, double encoding_gamma) 1930 { 1931 if (e != 0) 1932 { 1933 if (encoding_gamma != 0) 1934 pos = safecat(buffer, bufsize, pos, "("); 1935 pos = safecat(buffer, bufsize, pos, "R("); 1936 pos = safecatd(buffer, bufsize, pos, e->red.X, 4); 1937 pos = safecat(buffer, bufsize, pos, ","); 1938 pos = safecatd(buffer, bufsize, pos, e->red.Y, 4); 1939 pos = safecat(buffer, bufsize, pos, ","); 1940 pos = safecatd(buffer, bufsize, pos, e->red.Z, 4); 1941 pos = safecat(buffer, bufsize, pos, "),G("); 1942 pos = safecatd(buffer, bufsize, pos, e->green.X, 4); 1943 pos = safecat(buffer, bufsize, pos, ","); 1944 pos = safecatd(buffer, bufsize, pos, e->green.Y, 4); 1945 pos = safecat(buffer, bufsize, pos, ","); 1946 pos = safecatd(buffer, bufsize, pos, e->green.Z, 4); 1947 pos = safecat(buffer, bufsize, pos, "),B("); 1948 pos = safecatd(buffer, bufsize, pos, e->blue.X, 4); 1949 pos = safecat(buffer, bufsize, pos, ","); 1950 pos = safecatd(buffer, bufsize, pos, e->blue.Y, 4); 1951 pos = safecat(buffer, bufsize, pos, ","); 1952 pos = safecatd(buffer, bufsize, pos, e->blue.Z, 4); 1953 pos = safecat(buffer, bufsize, pos, ")"); 1954 if (encoding_gamma != 0) 1955 pos = safecat(buffer, bufsize, pos, ")"); 1956 } 1957 1958 if (encoding_gamma != 0) 1959 { 1960 pos = safecat(buffer, bufsize, pos, "^"); 1961 pos = safecatd(buffer, bufsize, pos, encoding_gamma, 5); 1962 } 1963 1964 return pos; 1965 } 1966 #endif /* READ_TRANSFORMS */ 1967 #endif /* PNG_READ_SUPPORTED */ 1968 1969 typedef struct png_modifier 1970 { 1971 png_store this; /* I am a png_store */ 1972 struct png_modification *modifications; /* Changes to make */ 1973 1974 modifier_state state; /* My state */ 1975 1976 /* Information from IHDR: */ 1977 png_byte bit_depth; /* From IHDR */ 1978 png_byte colour_type; /* From IHDR */ 1979 1980 /* While handling PLTE, IDAT and IEND these chunks may be pended to allow 1981 * other chunks to be inserted. 1982 */ 1983 png_uint_32 pending_len; 1984 png_uint_32 pending_chunk; 1985 1986 /* Test values */ 1987 double *gammas; 1988 unsigned int ngammas; 1989 unsigned int ngamma_tests; /* Number of gamma tests to run*/ 1990 double current_gamma; /* 0 if not set */ 1991 const color_encoding *encodings; 1992 unsigned int nencodings; 1993 const color_encoding *current_encoding; /* If an encoding has been set */ 1994 unsigned int encoding_counter; /* For iteration */ 1995 int encoding_ignored; /* Something overwrote it */ 1996 1997 /* Control variables used to iterate through possible encodings, the 1998 * following must be set to 0 and tested by the function that uses the 1999 * png_modifier because the modifier only sets it to 1 (true.) 2000 */ 2001 unsigned int repeat :1; /* Repeat this transform test. */ 2002 unsigned int test_uses_encoding :1; 2003 2004 /* Lowest sbit to test (pre-1.7 libpng fails for sbit < 8) */ 2005 png_byte sbitlow; 2006 2007 /* Error control - these are the limits on errors accepted by the gamma tests 2008 * below. 2009 */ 2010 double maxout8; /* Maximum output value error */ 2011 double maxabs8; /* Absolute sample error 0..1 */ 2012 double maxcalc8; /* Absolute sample error 0..1 */ 2013 double maxpc8; /* Percentage sample error 0..100% */ 2014 double maxout16; /* Maximum output value error */ 2015 double maxabs16; /* Absolute sample error 0..1 */ 2016 double maxcalc16;/* Absolute sample error 0..1 */ 2017 double maxcalcG; /* Absolute sample error 0..1 */ 2018 double maxpc16; /* Percentage sample error 0..100% */ 2019 2020 /* This is set by transforms that need to allow a higher limit, it is an 2021 * internal check on pngvalid to ensure that the calculated error limits are 2022 * not ridiculous; without this it is too easy to make a mistake in pngvalid 2023 * that allows any value through. 2024 * 2025 * NOTE: this is not checked in release builds. 2026 */ 2027 double limit; /* limit on error values, normally 4E-3 */ 2028 2029 /* Log limits - values above this are logged, but not necessarily 2030 * warned. 2031 */ 2032 double log8; /* Absolute error in 8 bits to log */ 2033 double log16; /* Absolute error in 16 bits to log */ 2034 2035 /* Logged 8 and 16 bit errors ('output' values): */ 2036 double error_gray_2; 2037 double error_gray_4; 2038 double error_gray_8; 2039 double error_gray_16; 2040 double error_color_8; 2041 double error_color_16; 2042 double error_indexed; 2043 2044 /* Flags: */ 2045 /* Whether to call png_read_update_info, not png_read_start_image, and how 2046 * many times to call it. 2047 */ 2048 int use_update_info; 2049 2050 /* Whether or not to interlace. */ 2051 int interlace_type :9; /* int, but must store '1' */ 2052 2053 /* Run the standard tests? */ 2054 unsigned int test_standard :1; 2055 2056 /* Run the odd-sized image and interlace read/write tests? */ 2057 unsigned int test_size :1; 2058 2059 /* Run tests on reading with a combination of transforms, */ 2060 unsigned int test_transform :1; 2061 unsigned int test_tRNS :1; /* Includes tRNS images */ 2062 2063 /* When to use the use_input_precision option, this controls the gamma 2064 * validation code checks. If set any value that is within the transformed 2065 * range input-.5 to input+.5 will be accepted, otherwise the value must be 2066 * within the normal limits. It should not be necessary to set this; the 2067 * result should always be exact within the permitted error limits. 2068 */ 2069 unsigned int use_input_precision :1; 2070 unsigned int use_input_precision_sbit :1; 2071 unsigned int use_input_precision_16to8 :1; 2072 2073 /* If set assume that the calculation bit depth is set by the input 2074 * precision, not the output precision. 2075 */ 2076 unsigned int calculations_use_input_precision :1; 2077 2078 /* If set assume that the calculations are done in 16 bits even if the sample 2079 * depth is 8 bits. 2080 */ 2081 unsigned int assume_16_bit_calculations :1; 2082 2083 /* Which gamma tests to run: */ 2084 unsigned int test_gamma_threshold :1; 2085 unsigned int test_gamma_transform :1; /* main tests */ 2086 unsigned int test_gamma_sbit :1; 2087 unsigned int test_gamma_scale16 :1; 2088 unsigned int test_gamma_background :1; 2089 unsigned int test_gamma_alpha_mode :1; 2090 unsigned int test_gamma_expand16 :1; 2091 unsigned int test_exhaustive :1; 2092 2093 /* Whether or not to run the low-bit-depth grayscale tests. This fails on 2094 * gamma images in some cases because of gross inaccuracies in the grayscale 2095 * gamma handling for low bit depth. 2096 */ 2097 unsigned int test_lbg :1; 2098 unsigned int test_lbg_gamma_threshold :1; 2099 unsigned int test_lbg_gamma_transform :1; 2100 unsigned int test_lbg_gamma_sbit :1; 2101 unsigned int test_lbg_gamma_composition :1; 2102 2103 unsigned int log :1; /* Log max error */ 2104 2105 /* Buffer information, the buffer size limits the size of the chunks that can 2106 * be modified - they must fit (including header and CRC) into the buffer! 2107 */ 2108 size_t flush; /* Count of bytes to flush */ 2109 size_t buffer_count; /* Bytes in buffer */ 2110 size_t buffer_position; /* Position in buffer */ 2111 png_byte buffer[1024]; 2112 } png_modifier; 2113 2114 /* This returns true if the test should be stopped now because it has already 2115 * failed and it is running silently. 2116 */ 2117 static int fail(png_modifier *pm) 2118 { 2119 return !pm->log && !pm->this.verbose && (pm->this.nerrors > 0 || 2120 (pm->this.treat_warnings_as_errors && pm->this.nwarnings > 0)); 2121 } 2122 2123 static void 2124 modifier_init(png_modifier *pm) 2125 { 2126 memset(pm, 0, sizeof *pm); 2127 store_init(&pm->this); 2128 pm->modifications = NULL; 2129 pm->state = modifier_start; 2130 pm->sbitlow = 1U; 2131 pm->ngammas = 0; 2132 pm->ngamma_tests = 0; 2133 pm->gammas = 0; 2134 pm->current_gamma = 0; 2135 pm->encodings = 0; 2136 pm->nencodings = 0; 2137 pm->current_encoding = 0; 2138 pm->encoding_counter = 0; 2139 pm->encoding_ignored = 0; 2140 pm->repeat = 0; 2141 pm->test_uses_encoding = 0; 2142 pm->maxout8 = pm->maxpc8 = pm->maxabs8 = pm->maxcalc8 = 0; 2143 pm->maxout16 = pm->maxpc16 = pm->maxabs16 = pm->maxcalc16 = 0; 2144 pm->maxcalcG = 0; 2145 pm->limit = 4E-3; 2146 pm->log8 = pm->log16 = 0; /* Means 'off' */ 2147 pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0; 2148 pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0; 2149 pm->error_indexed = 0; 2150 pm->use_update_info = 0; 2151 pm->interlace_type = PNG_INTERLACE_NONE; 2152 pm->test_standard = 0; 2153 pm->test_size = 0; 2154 pm->test_transform = 0; 2155 # ifdef PNG_WRITE_tRNS_SUPPORTED 2156 pm->test_tRNS = 1; 2157 # else 2158 pm->test_tRNS = 0; 2159 # endif 2160 pm->use_input_precision = 0; 2161 pm->use_input_precision_sbit = 0; 2162 pm->use_input_precision_16to8 = 0; 2163 pm->calculations_use_input_precision = 0; 2164 pm->assume_16_bit_calculations = 0; 2165 pm->test_gamma_threshold = 0; 2166 pm->test_gamma_transform = 0; 2167 pm->test_gamma_sbit = 0; 2168 pm->test_gamma_scale16 = 0; 2169 pm->test_gamma_background = 0; 2170 pm->test_gamma_alpha_mode = 0; 2171 pm->test_gamma_expand16 = 0; 2172 pm->test_lbg = 1; 2173 pm->test_lbg_gamma_threshold = 1; 2174 pm->test_lbg_gamma_transform = 1; 2175 pm->test_lbg_gamma_sbit = 1; 2176 pm->test_lbg_gamma_composition = 1; 2177 pm->test_exhaustive = 0; 2178 pm->log = 0; 2179 2180 /* Rely on the memset for all the other fields - there are no pointers */ 2181 } 2182 2183 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 2184 2185 /* This controls use of checks that explicitly know how libpng digitizes the 2186 * samples in calculations; setting this circumvents simple error limit checking 2187 * in the rgb_to_gray check, replacing it with an exact copy of the libpng 1.5 2188 * algorithm. 2189 */ 2190 #define DIGITIZE PNG_LIBPNG_VER < 10700 2191 2192 /* If pm->calculations_use_input_precision is set then operations will happen 2193 * with the precision of the input, not the precision of the output depth. 2194 * 2195 * If pm->assume_16_bit_calculations is set then even 8 bit calculations use 16 2196 * bit precision. This only affects those of the following limits that pertain 2197 * to a calculation - not a digitization operation - unless the following API is 2198 * called directly. 2199 */ 2200 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 2201 #if DIGITIZE 2202 static double digitize(double value, int depth, int do_round) 2203 { 2204 /* 'value' is in the range 0 to 1, the result is the same value rounded to a 2205 * multiple of the digitization factor - 8 or 16 bits depending on both the 2206 * sample depth and the 'assume' setting. Digitization is normally by 2207 * rounding and 'do_round' should be 1, if it is 0 the digitized value will 2208 * be truncated. 2209 */ 2210 const unsigned int digitization_factor = (1U << depth) -1; 2211 2212 /* Limiting the range is done as a convenience to the caller - it's easier to 2213 * do it once here than every time at the call site. 2214 */ 2215 if (value <= 0) 2216 value = 0; 2217 2218 else if (value >= 1) 2219 value = 1; 2220 2221 value *= digitization_factor; 2222 if (do_round) value += .5; 2223 return floor(value)/digitization_factor; 2224 } 2225 #endif 2226 #endif /* RGB_TO_GRAY */ 2227 2228 #ifdef PNG_READ_GAMMA_SUPPORTED 2229 static double abserr(const png_modifier *pm, int in_depth, int out_depth) 2230 { 2231 /* Absolute error permitted in linear values - affected by the bit depth of 2232 * the calculations. 2233 */ 2234 if (pm->assume_16_bit_calculations || 2235 (pm->calculations_use_input_precision ? in_depth : out_depth) == 16) 2236 return pm->maxabs16; 2237 else 2238 return pm->maxabs8; 2239 } 2240 2241 static double calcerr(const png_modifier *pm, int in_depth, int out_depth) 2242 { 2243 /* Error in the linear composition arithmetic - only relevant when 2244 * composition actually happens (0 < alpha < 1). 2245 */ 2246 if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16) 2247 return pm->maxcalc16; 2248 else if (pm->assume_16_bit_calculations) 2249 return pm->maxcalcG; 2250 else 2251 return pm->maxcalc8; 2252 } 2253 2254 static double pcerr(const png_modifier *pm, int in_depth, int out_depth) 2255 { 2256 /* Percentage error permitted in the linear values. Note that the specified 2257 * value is a percentage but this routine returns a simple number. 2258 */ 2259 if (pm->assume_16_bit_calculations || 2260 (pm->calculations_use_input_precision ? in_depth : out_depth) == 16) 2261 return pm->maxpc16 * .01; 2262 else 2263 return pm->maxpc8 * .01; 2264 } 2265 2266 /* Output error - the error in the encoded value. This is determined by the 2267 * digitization of the output so can be +/-0.5 in the actual output value. In 2268 * the expand_16 case with the current code in libpng the expand happens after 2269 * all the calculations are done in 8 bit arithmetic, so even though the output 2270 * depth is 16 the output error is determined by the 8 bit calculation. 2271 * 2272 * This limit is not determined by the bit depth of internal calculations. 2273 * 2274 * The specified parameter does *not* include the base .5 digitization error but 2275 * it is added here. 2276 */ 2277 static double outerr(const png_modifier *pm, int in_depth, int out_depth) 2278 { 2279 /* There is a serious error in the 2 and 4 bit grayscale transform because 2280 * the gamma table value (8 bits) is simply shifted, not rounded, so the 2281 * error in 4 bit grayscale gamma is up to the value below. This is a hack 2282 * to allow pngvalid to succeed: 2283 * 2284 * TODO: fix this in libpng 2285 */ 2286 if (out_depth == 2) 2287 return .73182-.5; 2288 2289 if (out_depth == 4) 2290 return .90644-.5; 2291 2292 if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16) 2293 return pm->maxout16; 2294 2295 /* This is the case where the value was calculated at 8-bit precision then 2296 * scaled to 16 bits. 2297 */ 2298 else if (out_depth == 16) 2299 return pm->maxout8 * 257; 2300 2301 else 2302 return pm->maxout8; 2303 } 2304 2305 /* This does the same thing as the above however it returns the value to log, 2306 * rather than raising a warning. This is useful for debugging to track down 2307 * exactly what set of parameters cause high error values. 2308 */ 2309 static double outlog(const png_modifier *pm, int in_depth, int out_depth) 2310 { 2311 /* The command line parameters are either 8 bit (0..255) or 16 bit (0..65535) 2312 * and so must be adjusted for low bit depth grayscale: 2313 */ 2314 if (out_depth <= 8) 2315 { 2316 if (pm->log8 == 0) /* switched off */ 2317 return 256; 2318 2319 if (out_depth < 8) 2320 return pm->log8 / 255 * ((1<<out_depth)-1); 2321 2322 return pm->log8; 2323 } 2324 2325 if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16) 2326 { 2327 if (pm->log16 == 0) 2328 return 65536; 2329 2330 return pm->log16; 2331 } 2332 2333 /* This is the case where the value was calculated at 8-bit precision then 2334 * scaled to 16 bits. 2335 */ 2336 if (pm->log8 == 0) 2337 return 65536; 2338 2339 return pm->log8 * 257; 2340 } 2341 2342 /* This complements the above by providing the appropriate quantization for the 2343 * final value. Normally this would just be quantization to an integral value, 2344 * but in the 8 bit calculation case it's actually quantization to a multiple of 2345 * 257! 2346 */ 2347 static int output_quantization_factor(const png_modifier *pm, int in_depth, 2348 int out_depth) 2349 { 2350 if (out_depth == 16 && in_depth != 16 && 2351 pm->calculations_use_input_precision) 2352 return 257; 2353 else 2354 return 1; 2355 } 2356 #endif /* PNG_READ_GAMMA_SUPPORTED */ 2357 2358 /* One modification structure must be provided for each chunk to be modified (in 2359 * fact more than one can be provided if multiple separate changes are desired 2360 * for a single chunk.) Modifications include adding a new chunk when a 2361 * suitable chunk does not exist. 2362 * 2363 * The caller of modify_fn will reset the CRC of the chunk and record 'modified' 2364 * or 'added' as appropriate if the modify_fn returns 1 (true). If the 2365 * modify_fn is NULL the chunk is simply removed. 2366 */ 2367 typedef struct png_modification 2368 { 2369 struct png_modification *next; 2370 png_uint_32 chunk; 2371 2372 /* If the following is NULL all matching chunks will be removed: */ 2373 int (*modify_fn)(struct png_modifier *pm, 2374 struct png_modification *me, int add); 2375 2376 /* If the following is set to PLTE, IDAT or IEND and the chunk has not been 2377 * found and modified (and there is a modify_fn) the modify_fn will be called 2378 * to add the chunk before the relevant chunk. 2379 */ 2380 png_uint_32 add; 2381 unsigned int modified :1; /* Chunk was modified */ 2382 unsigned int added :1; /* Chunk was added */ 2383 unsigned int removed :1; /* Chunk was removed */ 2384 } png_modification; 2385 2386 static void 2387 modification_reset(png_modification *pmm) 2388 { 2389 if (pmm != NULL) 2390 { 2391 pmm->modified = 0; 2392 pmm->added = 0; 2393 pmm->removed = 0; 2394 modification_reset(pmm->next); 2395 } 2396 } 2397 2398 static void 2399 modification_init(png_modification *pmm) 2400 { 2401 memset(pmm, 0, sizeof *pmm); 2402 pmm->next = NULL; 2403 pmm->chunk = 0; 2404 pmm->modify_fn = NULL; 2405 pmm->add = 0; 2406 modification_reset(pmm); 2407 } 2408 2409 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 2410 static void 2411 modifier_current_encoding(const png_modifier *pm, color_encoding *ce) 2412 { 2413 if (pm->current_encoding != 0) 2414 *ce = *pm->current_encoding; 2415 2416 else 2417 memset(ce, 0, sizeof *ce); 2418 2419 ce->gamma = pm->current_gamma; 2420 } 2421 #endif 2422 2423 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 2424 static size_t 2425 safecat_current_encoding(char *buffer, size_t bufsize, size_t pos, 2426 const png_modifier *pm) 2427 { 2428 pos = safecat_color_encoding(buffer, bufsize, pos, pm->current_encoding, 2429 pm->current_gamma); 2430 2431 if (pm->encoding_ignored) 2432 pos = safecat(buffer, bufsize, pos, "[overridden]"); 2433 2434 return pos; 2435 } 2436 #endif 2437 2438 /* Iterate through the usefully testable color encodings. An encoding is one 2439 * of: 2440 * 2441 * 1) Nothing (no color space, no gamma). 2442 * 2) Just a gamma value from the gamma array (including 1.0) 2443 * 3) A color space from the encodings array with the corresponding gamma. 2444 * 4) The same, but with gamma 1.0 (only really useful with 16 bit calculations) 2445 * 2446 * The iterator selects these in turn, the randomizer selects one at random, 2447 * which is used depends on the setting of the 'test_exhaustive' flag. Notice 2448 * that this function changes the colour space encoding so it must only be 2449 * called on completion of the previous test. This is what 'modifier_reset' 2450 * does, below. 2451 * 2452 * After the function has been called the 'repeat' flag will still be set; the 2453 * caller of modifier_reset must reset it at the start of each run of the test! 2454 */ 2455 static unsigned int 2456 modifier_total_encodings(const png_modifier *pm) 2457 { 2458 return 1 + /* (1) nothing */ 2459 pm->ngammas + /* (2) gamma values to test */ 2460 pm->nencodings + /* (3) total number of encodings */ 2461 /* The following test only works after the first time through the 2462 * png_modifier code because 'bit_depth' is set when the IHDR is read. 2463 * modifier_reset, below, preserves the setting until after it has called 2464 * the iterate function (also below.) 2465 * 2466 * For this reason do not rely on this function outside a call to 2467 * modifier_reset. 2468 */ 2469 ((pm->bit_depth == 16 || pm->assume_16_bit_calculations) ? 2470 pm->nencodings : 0); /* (4) encodings with gamma == 1.0 */ 2471 } 2472 2473 static void 2474 modifier_encoding_iterate(png_modifier *pm) 2475 { 2476 if (!pm->repeat && /* Else something needs the current encoding again. */ 2477 pm->test_uses_encoding) /* Some transform is encoding dependent */ 2478 { 2479 if (pm->test_exhaustive) 2480 { 2481 if (++pm->encoding_counter >= modifier_total_encodings(pm)) 2482 pm->encoding_counter = 0; /* This will stop the repeat */ 2483 } 2484 2485 else 2486 { 2487 /* Not exhaustive - choose an encoding at random; generate a number in 2488 * the range 1..(max-1), so the result is always non-zero: 2489 */ 2490 if (pm->encoding_counter == 0) 2491 pm->encoding_counter = random_mod(modifier_total_encodings(pm)-1)+1; 2492 else 2493 pm->encoding_counter = 0; 2494 } 2495 2496 if (pm->encoding_counter > 0) 2497 pm->repeat = 1; 2498 } 2499 2500 else if (!pm->repeat) 2501 pm->encoding_counter = 0; 2502 } 2503 2504 static void 2505 modifier_reset(png_modifier *pm) 2506 { 2507 store_read_reset(&pm->this); 2508 pm->limit = 4E-3; 2509 pm->pending_len = pm->pending_chunk = 0; 2510 pm->flush = pm->buffer_count = pm->buffer_position = 0; 2511 pm->modifications = NULL; 2512 pm->state = modifier_start; 2513 modifier_encoding_iterate(pm); 2514 /* The following must be set in the next run. In particular 2515 * test_uses_encodings must be set in the _ini function of each transform 2516 * that looks at the encodings. (Not the 'add' function!) 2517 */ 2518 pm->test_uses_encoding = 0; 2519 pm->current_gamma = 0; 2520 pm->current_encoding = 0; 2521 pm->encoding_ignored = 0; 2522 /* These only become value after IHDR is read: */ 2523 pm->bit_depth = pm->colour_type = 0; 2524 } 2525 2526 /* The following must be called before anything else to get the encoding set up 2527 * on the modifier. In particular it must be called before the transform init 2528 * functions are called. 2529 */ 2530 static void 2531 modifier_set_encoding(png_modifier *pm) 2532 { 2533 /* Set the encoding to the one specified by the current encoding counter, 2534 * first clear out all the settings - this corresponds to an encoding_counter 2535 * of 0. 2536 */ 2537 pm->current_gamma = 0; 2538 pm->current_encoding = 0; 2539 pm->encoding_ignored = 0; /* not ignored yet - happens in _ini functions. */ 2540 2541 /* Now, if required, set the gamma and encoding fields. */ 2542 if (pm->encoding_counter > 0) 2543 { 2544 /* The gammas[] array is an array of screen gammas, not encoding gammas, 2545 * so we need the inverse: 2546 */ 2547 if (pm->encoding_counter <= pm->ngammas) 2548 pm->current_gamma = 1/pm->gammas[pm->encoding_counter-1]; 2549 2550 else 2551 { 2552 unsigned int i = pm->encoding_counter - pm->ngammas; 2553 2554 if (i >= pm->nencodings) 2555 { 2556 i %= pm->nencodings; 2557 pm->current_gamma = 1; /* Linear, only in the 16 bit case */ 2558 } 2559 2560 else 2561 pm->current_gamma = pm->encodings[i].gamma; 2562 2563 pm->current_encoding = pm->encodings + i; 2564 } 2565 } 2566 } 2567 2568 /* Enquiry functions to find out what is set. Notice that there is an implicit 2569 * assumption below that the first encoding in the list is the one for sRGB. 2570 */ 2571 static int 2572 modifier_color_encoding_is_sRGB(const png_modifier *pm) 2573 { 2574 return pm->current_encoding != 0 && pm->current_encoding == pm->encodings && 2575 pm->current_encoding->gamma == pm->current_gamma; 2576 } 2577 2578 static int 2579 modifier_color_encoding_is_set(const png_modifier *pm) 2580 { 2581 return pm->current_gamma != 0; 2582 } 2583 2584 /* Convenience macros. */ 2585 #define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d)) 2586 #define CHUNK_IHDR CHUNK(73,72,68,82) 2587 #define CHUNK_PLTE CHUNK(80,76,84,69) 2588 #define CHUNK_IDAT CHUNK(73,68,65,84) 2589 #define CHUNK_IEND CHUNK(73,69,78,68) 2590 #define CHUNK_cHRM CHUNK(99,72,82,77) 2591 #define CHUNK_gAMA CHUNK(103,65,77,65) 2592 #define CHUNK_sBIT CHUNK(115,66,73,84) 2593 #define CHUNK_sRGB CHUNK(115,82,71,66) 2594 2595 /* The guts of modification are performed during a read. */ 2596 static void 2597 modifier_crc(png_bytep buffer) 2598 { 2599 /* Recalculate the chunk CRC - a complete chunk must be in 2600 * the buffer, at the start. 2601 */ 2602 uInt datalen = png_get_uint_32(buffer); 2603 uLong crc = crc32(0, buffer+4, datalen+4); 2604 /* The cast to png_uint_32 is safe because a crc32 is always a 32 bit value. 2605 */ 2606 png_save_uint_32(buffer+datalen+8, (png_uint_32)crc); 2607 } 2608 2609 static void 2610 modifier_setbuffer(png_modifier *pm) 2611 { 2612 modifier_crc(pm->buffer); 2613 pm->buffer_count = png_get_uint_32(pm->buffer)+12; 2614 pm->buffer_position = 0; 2615 } 2616 2617 /* Separate the callback into the actual implementation (which is passed the 2618 * png_modifier explicitly) and the callback, which gets the modifier from the 2619 * png_struct. 2620 */ 2621 static void 2622 modifier_read_imp(png_modifier *pm, png_bytep pb, png_size_t st) 2623 { 2624 while (st > 0) 2625 { 2626 size_t cb; 2627 png_uint_32 len, chunk; 2628 png_modification *mod; 2629 2630 if (pm->buffer_position >= pm->buffer_count) switch (pm->state) 2631 { 2632 static png_byte sign[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; 2633 case modifier_start: 2634 store_read_imp(&pm->this, pm->buffer, 8); /* size of signature. */ 2635 pm->buffer_count = 8; 2636 pm->buffer_position = 0; 2637 2638 if (memcmp(pm->buffer, sign, 8) != 0) 2639 png_error(pm->this.pread, "invalid PNG file signature"); 2640 pm->state = modifier_signature; 2641 break; 2642 2643 case modifier_signature: 2644 store_read_imp(&pm->this, pm->buffer, 13+12); /* size of IHDR */ 2645 pm->buffer_count = 13+12; 2646 pm->buffer_position = 0; 2647 2648 if (png_get_uint_32(pm->buffer) != 13 || 2649 png_get_uint_32(pm->buffer+4) != CHUNK_IHDR) 2650 png_error(pm->this.pread, "invalid IHDR"); 2651 2652 /* Check the list of modifiers for modifications to the IHDR. */ 2653 mod = pm->modifications; 2654 while (mod != NULL) 2655 { 2656 if (mod->chunk == CHUNK_IHDR && mod->modify_fn && 2657 (*mod->modify_fn)(pm, mod, 0)) 2658 { 2659 mod->modified = 1; 2660 modifier_setbuffer(pm); 2661 } 2662 2663 /* Ignore removal or add if IHDR! */ 2664 mod = mod->next; 2665 } 2666 2667 /* Cache information from the IHDR (the modified one.) */ 2668 pm->bit_depth = pm->buffer[8+8]; 2669 pm->colour_type = pm->buffer[8+8+1]; 2670 2671 pm->state = modifier_IHDR; 2672 pm->flush = 0; 2673 break; 2674 2675 case modifier_IHDR: 2676 default: 2677 /* Read a new chunk and process it until we see PLTE, IDAT or 2678 * IEND. 'flush' indicates that there is still some data to 2679 * output from the preceding chunk. 2680 */ 2681 if ((cb = pm->flush) > 0) 2682 { 2683 if (cb > st) cb = st; 2684 pm->flush -= cb; 2685 store_read_imp(&pm->this, pb, cb); 2686 pb += cb; 2687 st -= cb; 2688 if (st == 0) return; 2689 } 2690 2691 /* No more bytes to flush, read a header, or handle a pending 2692 * chunk. 2693 */ 2694 if (pm->pending_chunk != 0) 2695 { 2696 png_save_uint_32(pm->buffer, pm->pending_len); 2697 png_save_uint_32(pm->buffer+4, pm->pending_chunk); 2698 pm->pending_len = 0; 2699 pm->pending_chunk = 0; 2700 } 2701 else 2702 store_read_imp(&pm->this, pm->buffer, 8); 2703 2704 pm->buffer_count = 8; 2705 pm->buffer_position = 0; 2706 2707 /* Check for something to modify or a terminator chunk. */ 2708 len = png_get_uint_32(pm->buffer); 2709 chunk = png_get_uint_32(pm->buffer+4); 2710 2711 /* Terminators first, they may have to be delayed for added 2712 * chunks 2713 */ 2714 if (chunk == CHUNK_PLTE || chunk == CHUNK_IDAT || 2715 chunk == CHUNK_IEND) 2716 { 2717 mod = pm->modifications; 2718 2719 while (mod != NULL) 2720 { 2721 if ((mod->add == chunk || 2722 (mod->add == CHUNK_PLTE && chunk == CHUNK_IDAT)) && 2723 mod->modify_fn != NULL && !mod->modified && !mod->added) 2724 { 2725 /* Regardless of what the modify function does do not run 2726 * this again. 2727 */ 2728 mod->added = 1; 2729 2730 if ((*mod->modify_fn)(pm, mod, 1 /*add*/)) 2731 { 2732 /* Reset the CRC on a new chunk */ 2733 if (pm->buffer_count > 0) 2734 modifier_setbuffer(pm); 2735 2736 else 2737 { 2738 pm->buffer_position = 0; 2739 mod->removed = 1; 2740 } 2741 2742 /* The buffer has been filled with something (we assume) 2743 * so output this. Pend the current chunk. 2744 */ 2745 pm->pending_len = len; 2746 pm->pending_chunk = chunk; 2747 break; /* out of while */ 2748 } 2749 } 2750 2751 mod = mod->next; 2752 } 2753 2754 /* Don't do any further processing if the buffer was modified - 2755 * otherwise the code will end up modifying a chunk that was 2756 * just added. 2757 */ 2758 if (mod != NULL) 2759 break; /* out of switch */ 2760 } 2761 2762 /* If we get to here then this chunk may need to be modified. To 2763 * do this it must be less than 1024 bytes in total size, otherwise 2764 * it just gets flushed. 2765 */ 2766 if (len+12 <= sizeof pm->buffer) 2767 { 2768 store_read_imp(&pm->this, pm->buffer+pm->buffer_count, 2769 len+12-pm->buffer_count); 2770 pm->buffer_count = len+12; 2771 2772 /* Check for a modification, else leave it be. */ 2773 mod = pm->modifications; 2774 while (mod != NULL) 2775 { 2776 if (mod->chunk == chunk) 2777 { 2778 if (mod->modify_fn == NULL) 2779 { 2780 /* Remove this chunk */ 2781 pm->buffer_count = pm->buffer_position = 0; 2782 mod->removed = 1; 2783 break; /* Terminate the while loop */ 2784 } 2785 2786 else if ((*mod->modify_fn)(pm, mod, 0)) 2787 { 2788 mod->modified = 1; 2789 /* The chunk may have been removed: */ 2790 if (pm->buffer_count == 0) 2791 { 2792 pm->buffer_position = 0; 2793 break; 2794 } 2795 modifier_setbuffer(pm); 2796 } 2797 } 2798 2799 mod = mod->next; 2800 } 2801 } 2802 2803 else 2804 pm->flush = len+12 - pm->buffer_count; /* data + crc */ 2805 2806 /* Take the data from the buffer (if there is any). */ 2807 break; 2808 } 2809 2810 /* Here to read from the modifier buffer (not directly from 2811 * the store, as in the flush case above.) 2812 */ 2813 cb = pm->buffer_count - pm->buffer_position; 2814 2815 if (cb > st) 2816 cb = st; 2817 2818 memcpy(pb, pm->buffer + pm->buffer_position, cb); 2819 st -= cb; 2820 pb += cb; 2821 pm->buffer_position += cb; 2822 } 2823 } 2824 2825 /* The callback: */ 2826 static void PNGCBAPI 2827 modifier_read(png_structp ppIn, png_bytep pb, png_size_t st) 2828 { 2829 png_const_structp pp = ppIn; 2830 png_modifier *pm = voidcast(png_modifier*, png_get_io_ptr(pp)); 2831 2832 if (pm == NULL || pm->this.pread != pp) 2833 png_error(pp, "bad modifier_read call"); 2834 2835 modifier_read_imp(pm, pb, st); 2836 } 2837 2838 /* Like store_progressive_read but the data is getting changed as we go so we 2839 * need a local buffer. 2840 */ 2841 static void 2842 modifier_progressive_read(png_modifier *pm, png_structp pp, png_infop pi) 2843 { 2844 if (pm->this.pread != pp || pm->this.current == NULL || 2845 pm->this.next == NULL) 2846 png_error(pp, "store state damaged (progressive)"); 2847 2848 /* This is another Horowitz and Hill random noise generator. In this case 2849 * the aim is to stress the progressive reader with truly horrible variable 2850 * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers 2851 * is generated. We could probably just count from 1 to 32767 and get as 2852 * good a result. 2853 */ 2854 for (;;) 2855 { 2856 static png_uint_32 noise = 1; 2857 png_size_t cb, cbAvail; 2858 png_byte buffer[512]; 2859 2860 /* Generate 15 more bits of stuff: */ 2861 noise = (noise << 9) | ((noise ^ (noise >> (9-5))) & 0x1ff); 2862 cb = noise & 0x1ff; 2863 2864 /* Check that this number of bytes are available (in the current buffer.) 2865 * (This doesn't quite work - the modifier might delete a chunk; unlikely 2866 * but possible, it doesn't happen at present because the modifier only 2867 * adds chunks to standard images.) 2868 */ 2869 cbAvail = store_read_buffer_avail(&pm->this); 2870 if (pm->buffer_count > pm->buffer_position) 2871 cbAvail += pm->buffer_count - pm->buffer_position; 2872 2873 if (cb > cbAvail) 2874 { 2875 /* Check for EOF: */ 2876 if (cbAvail == 0) 2877 break; 2878 2879 cb = cbAvail; 2880 } 2881 2882 modifier_read_imp(pm, buffer, cb); 2883 png_process_data(pp, pi, buffer, cb); 2884 } 2885 2886 /* Check the invariants at the end (if this fails it's a problem in this 2887 * file!) 2888 */ 2889 if (pm->buffer_count > pm->buffer_position || 2890 pm->this.next != &pm->this.current->data || 2891 pm->this.readpos < pm->this.current->datacount) 2892 png_error(pp, "progressive read implementation error"); 2893 } 2894 2895 /* Set up a modifier. */ 2896 static png_structp 2897 set_modifier_for_read(png_modifier *pm, png_infopp ppi, png_uint_32 id, 2898 const char *name) 2899 { 2900 /* Do this first so that the modifier fields are cleared even if an error 2901 * happens allocating the png_struct. No allocation is done here so no 2902 * cleanup is required. 2903 */ 2904 pm->state = modifier_start; 2905 pm->bit_depth = 0; 2906 pm->colour_type = 255; 2907 2908 pm->pending_len = 0; 2909 pm->pending_chunk = 0; 2910 pm->flush = 0; 2911 pm->buffer_count = 0; 2912 pm->buffer_position = 0; 2913 2914 return set_store_for_read(&pm->this, ppi, id, name); 2915 } 2916 2917 2918 /******************************** MODIFICATIONS *******************************/ 2919 /* Standard modifications to add chunks. These do not require the _SUPPORTED 2920 * macros because the chunks can be there regardless of whether this specific 2921 * libpng supports them. 2922 */ 2923 typedef struct gama_modification 2924 { 2925 png_modification this; 2926 png_fixed_point gamma; 2927 } gama_modification; 2928 2929 static int 2930 gama_modify(png_modifier *pm, png_modification *me, int add) 2931 { 2932 UNUSED(add) 2933 /* This simply dumps the given gamma value into the buffer. */ 2934 png_save_uint_32(pm->buffer, 4); 2935 png_save_uint_32(pm->buffer+4, CHUNK_gAMA); 2936 png_save_uint_32(pm->buffer+8, ((gama_modification*)me)->gamma); 2937 return 1; 2938 } 2939 2940 static void 2941 gama_modification_init(gama_modification *me, png_modifier *pm, double gammad) 2942 { 2943 double g; 2944 2945 modification_init(&me->this); 2946 me->this.chunk = CHUNK_gAMA; 2947 me->this.modify_fn = gama_modify; 2948 me->this.add = CHUNK_PLTE; 2949 g = fix(gammad); 2950 me->gamma = (png_fixed_point)g; 2951 me->this.next = pm->modifications; 2952 pm->modifications = &me->this; 2953 } 2954 2955 typedef struct chrm_modification 2956 { 2957 png_modification this; 2958 const color_encoding *encoding; 2959 png_fixed_point wx, wy, rx, ry, gx, gy, bx, by; 2960 } chrm_modification; 2961 2962 static int 2963 chrm_modify(png_modifier *pm, png_modification *me, int add) 2964 { 2965 UNUSED(add) 2966 /* As with gAMA this just adds the required cHRM chunk to the buffer. */ 2967 png_save_uint_32(pm->buffer , 32); 2968 png_save_uint_32(pm->buffer+ 4, CHUNK_cHRM); 2969 png_save_uint_32(pm->buffer+ 8, ((chrm_modification*)me)->wx); 2970 png_save_uint_32(pm->buffer+12, ((chrm_modification*)me)->wy); 2971 png_save_uint_32(pm->buffer+16, ((chrm_modification*)me)->rx); 2972 png_save_uint_32(pm->buffer+20, ((chrm_modification*)me)->ry); 2973 png_save_uint_32(pm->buffer+24, ((chrm_modification*)me)->gx); 2974 png_save_uint_32(pm->buffer+28, ((chrm_modification*)me)->gy); 2975 png_save_uint_32(pm->buffer+32, ((chrm_modification*)me)->bx); 2976 png_save_uint_32(pm->buffer+36, ((chrm_modification*)me)->by); 2977 return 1; 2978 } 2979 2980 static void 2981 chrm_modification_init(chrm_modification *me, png_modifier *pm, 2982 const color_encoding *encoding) 2983 { 2984 CIE_color white = white_point(encoding); 2985 2986 /* Original end points: */ 2987 me->encoding = encoding; 2988 2989 /* Chromaticities (in fixed point): */ 2990 me->wx = fix(chromaticity_x(white)); 2991 me->wy = fix(chromaticity_y(white)); 2992 2993 me->rx = fix(chromaticity_x(encoding->red)); 2994 me->ry = fix(chromaticity_y(encoding->red)); 2995 me->gx = fix(chromaticity_x(encoding->green)); 2996 me->gy = fix(chromaticity_y(encoding->green)); 2997 me->bx = fix(chromaticity_x(encoding->blue)); 2998 me->by = fix(chromaticity_y(encoding->blue)); 2999 3000 modification_init(&me->this); 3001 me->this.chunk = CHUNK_cHRM; 3002 me->this.modify_fn = chrm_modify; 3003 me->this.add = CHUNK_PLTE; 3004 me->this.next = pm->modifications; 3005 pm->modifications = &me->this; 3006 } 3007 3008 typedef struct srgb_modification 3009 { 3010 png_modification this; 3011 png_byte intent; 3012 } srgb_modification; 3013 3014 static int 3015 srgb_modify(png_modifier *pm, png_modification *me, int add) 3016 { 3017 UNUSED(add) 3018 /* As above, ignore add and just make a new chunk */ 3019 png_save_uint_32(pm->buffer, 1); 3020 png_save_uint_32(pm->buffer+4, CHUNK_sRGB); 3021 pm->buffer[8] = ((srgb_modification*)me)->intent; 3022 return 1; 3023 } 3024 3025 static void 3026 srgb_modification_init(srgb_modification *me, png_modifier *pm, png_byte intent) 3027 { 3028 modification_init(&me->this); 3029 me->this.chunk = CHUNK_sBIT; 3030 3031 if (intent <= 3) /* if valid, else *delete* sRGB chunks */ 3032 { 3033 me->this.modify_fn = srgb_modify; 3034 me->this.add = CHUNK_PLTE; 3035 me->intent = intent; 3036 } 3037 3038 else 3039 { 3040 me->this.modify_fn = 0; 3041 me->this.add = 0; 3042 me->intent = 0; 3043 } 3044 3045 me->this.next = pm->modifications; 3046 pm->modifications = &me->this; 3047 } 3048 3049 #ifdef PNG_READ_GAMMA_SUPPORTED 3050 typedef struct sbit_modification 3051 { 3052 png_modification this; 3053 png_byte sbit; 3054 } sbit_modification; 3055 3056 static int 3057 sbit_modify(png_modifier *pm, png_modification *me, int add) 3058 { 3059 png_byte sbit = ((sbit_modification*)me)->sbit; 3060 if (pm->bit_depth > sbit) 3061 { 3062 int cb = 0; 3063 switch (pm->colour_type) 3064 { 3065 case 0: 3066 cb = 1; 3067 break; 3068 3069 case 2: 3070 case 3: 3071 cb = 3; 3072 break; 3073 3074 case 4: 3075 cb = 2; 3076 break; 3077 3078 case 6: 3079 cb = 4; 3080 break; 3081 3082 default: 3083 png_error(pm->this.pread, 3084 "unexpected colour type in sBIT modification"); 3085 } 3086 3087 png_save_uint_32(pm->buffer, cb); 3088 png_save_uint_32(pm->buffer+4, CHUNK_sBIT); 3089 3090 while (cb > 0) 3091 (pm->buffer+8)[--cb] = sbit; 3092 3093 return 1; 3094 } 3095 else if (!add) 3096 { 3097 /* Remove the sBIT chunk */ 3098 pm->buffer_count = pm->buffer_position = 0; 3099 return 1; 3100 } 3101 else 3102 return 0; /* do nothing */ 3103 } 3104 3105 static void 3106 sbit_modification_init(sbit_modification *me, png_modifier *pm, png_byte sbit) 3107 { 3108 modification_init(&me->this); 3109 me->this.chunk = CHUNK_sBIT; 3110 me->this.modify_fn = sbit_modify; 3111 me->this.add = CHUNK_PLTE; 3112 me->sbit = sbit; 3113 me->this.next = pm->modifications; 3114 pm->modifications = &me->this; 3115 } 3116 #endif /* PNG_READ_GAMMA_SUPPORTED */ 3117 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 3118 3119 /***************************** STANDARD PNG FILES *****************************/ 3120 /* Standard files - write and save standard files. */ 3121 /* There are two basic forms of standard images. Those which attempt to have 3122 * all the possible pixel values (not possible for 16bpp images, but a range of 3123 * values are produced) and those which have a range of image sizes. The former 3124 * are used for testing transforms, in particular gamma correction and bit 3125 * reduction and increase. The latter are reserved for testing the behavior of 3126 * libpng with respect to 'odd' image sizes - particularly small images where 3127 * rows become 1 byte and interlace passes disappear. 3128 * 3129 * The first, most useful, set are the 'transform' images, the second set of 3130 * small images are the 'size' images. 3131 * 3132 * The transform files are constructed with rows which fit into a 1024 byte row 3133 * buffer. This makes allocation easier below. Further regardless of the file 3134 * format every row has 128 pixels (giving 1024 bytes for 64bpp formats). 3135 * 3136 * Files are stored with no gAMA or sBIT chunks, with a PLTE only when needed 3137 * and with an ID derived from the colour type, bit depth and interlace type 3138 * as above (FILEID). The width (128) and height (variable) are not stored in 3139 * the FILEID - instead the fields are set to 0, indicating a transform file. 3140 * 3141 * The size files ar constructed with rows a maximum of 128 bytes wide, allowing 3142 * a maximum width of 16 pixels (for the 64bpp case.) They also have a maximum 3143 * height of 16 rows. The width and height are stored in the FILEID and, being 3144 * non-zero, indicate a size file. 3145 * 3146 * Because the PNG filter code is typically the largest CPU consumer within 3147 * libpng itself there is a tendency to attempt to optimize it. This results in 3148 * special case code which needs to be validated. To cause this to happen the 3149 * 'size' images are made to use each possible filter, in so far as this is 3150 * possible for smaller images. 3151 * 3152 * For palette image (colour type 3) multiple transform images are stored with 3153 * the same bit depth to allow testing of more colour combinations - 3154 * particularly important for testing the gamma code because libpng uses a 3155 * different code path for palette images. For size images a single palette is 3156 * used. 3157 */ 3158 3159 /* Make a 'standard' palette. Because there are only 256 entries in a palette 3160 * (maximum) this actually makes a random palette in the hope that enough tests 3161 * will catch enough errors. (Note that the same palette isn't produced every 3162 * time for the same test - it depends on what previous tests have been run - 3163 * but a given set of arguments to pngvalid will always produce the same palette 3164 * at the same test! This is why pseudo-random number generators are useful for 3165 * testing.) 3166 * 3167 * The store must be open for write when this is called, otherwise an internal 3168 * error will occur. This routine contains its own magic number seed, so the 3169 * palettes generated don't change if there are intervening errors (changing the 3170 * calls to the store_mark seed.) 3171 */ 3172 static store_palette_entry * 3173 make_standard_palette(png_store* ps, int npalette, int do_tRNS) 3174 { 3175 static png_uint_32 palette_seed[2] = { 0x87654321, 9 }; 3176 3177 int i = 0; 3178 png_byte values[256][4]; 3179 3180 /* Always put in black and white plus the six primary and secondary colors. 3181 */ 3182 for (; i<8; ++i) 3183 { 3184 values[i][1] = (png_byte)((i&1) ? 255U : 0U); 3185 values[i][2] = (png_byte)((i&2) ? 255U : 0U); 3186 values[i][3] = (png_byte)((i&4) ? 255U : 0U); 3187 } 3188 3189 /* Then add 62 grays (one quarter of the remaining 256 slots). */ 3190 { 3191 int j = 0; 3192 png_byte random_bytes[4]; 3193 png_byte need[256]; 3194 3195 need[0] = 0; /*got black*/ 3196 memset(need+1, 1, (sizeof need)-2); /*need these*/ 3197 need[255] = 0; /*but not white*/ 3198 3199 while (i<70) 3200 { 3201 png_byte b; 3202 3203 if (j==0) 3204 { 3205 make_four_random_bytes(palette_seed, random_bytes); 3206 j = 4; 3207 } 3208 3209 b = random_bytes[--j]; 3210 if (need[b]) 3211 { 3212 values[i][1] = b; 3213 values[i][2] = b; 3214 values[i++][3] = b; 3215 } 3216 } 3217 } 3218 3219 /* Finally add 192 colors at random - don't worry about matches to things we 3220 * already have, chance is less than 1/65536. Don't worry about grays, 3221 * chance is the same, so we get a duplicate or extra gray less than 1 time 3222 * in 170. 3223 */ 3224 for (; i<256; ++i) 3225 make_four_random_bytes(palette_seed, values[i]); 3226 3227 /* Fill in the alpha values in the first byte. Just use all possible values 3228 * (0..255) in an apparently random order: 3229 */ 3230 { 3231 store_palette_entry *palette; 3232 png_byte selector[4]; 3233 3234 make_four_random_bytes(palette_seed, selector); 3235 3236 if (do_tRNS) 3237 for (i=0; i<256; ++i) 3238 values[i][0] = (png_byte)(i ^ selector[0]); 3239 3240 else 3241 for (i=0; i<256; ++i) 3242 values[i][0] = 255; /* no transparency/tRNS chunk */ 3243 3244 /* 'values' contains 256 ARGB values, but we only need 'npalette'. 3245 * 'npalette' will always be a power of 2: 2, 4, 16 or 256. In the low 3246 * bit depth cases select colors at random, else it is difficult to have 3247 * a set of low bit depth palette test with any chance of a reasonable 3248 * range of colors. Do this by randomly permuting values into the low 3249 * 'npalette' entries using an XOR mask generated here. This also 3250 * permutes the npalette == 256 case in a potentially useful way (there is 3251 * no relationship between palette index and the color value therein!) 3252 */ 3253 palette = store_write_palette(ps, npalette); 3254 3255 for (i=0; i<npalette; ++i) 3256 { 3257 palette[i].alpha = values[i ^ selector[1]][0]; 3258 palette[i].red = values[i ^ selector[1]][1]; 3259 palette[i].green = values[i ^ selector[1]][2]; 3260 palette[i].blue = values[i ^ selector[1]][3]; 3261 } 3262 3263 return palette; 3264 } 3265 } 3266 3267 /* Initialize a standard palette on a write stream. The 'do_tRNS' argument 3268 * indicates whether or not to also set the tRNS chunk. 3269 */ 3270 /* TODO: the png_structp here can probably be 'const' in the future */ 3271 static void 3272 init_standard_palette(png_store *ps, png_structp pp, png_infop pi, int npalette, 3273 int do_tRNS) 3274 { 3275 store_palette_entry *ppal = make_standard_palette(ps, npalette, do_tRNS); 3276 3277 { 3278 int i; 3279 png_color palette[256]; 3280 3281 /* Set all entries to detect overread errors. */ 3282 for (i=0; i<npalette; ++i) 3283 { 3284 palette[i].red = ppal[i].red; 3285 palette[i].green = ppal[i].green; 3286 palette[i].blue = ppal[i].blue; 3287 } 3288 3289 /* Just in case fill in the rest with detectable values: */ 3290 for (; i<256; ++i) 3291 palette[i].red = palette[i].green = palette[i].blue = 42; 3292 3293 png_set_PLTE(pp, pi, palette, npalette); 3294 } 3295 3296 if (do_tRNS) 3297 { 3298 int i, j; 3299 png_byte tRNS[256]; 3300 3301 /* Set all the entries, but skip trailing opaque entries */ 3302 for (i=j=0; i<npalette; ++i) 3303 if ((tRNS[i] = ppal[i].alpha) < 255) 3304 j = i+1; 3305 3306 /* Fill in the remainder with a detectable value: */ 3307 for (; i<256; ++i) 3308 tRNS[i] = 24; 3309 3310 # ifdef PNG_WRITE_tRNS_SUPPORTED 3311 if (j > 0) 3312 png_set_tRNS(pp, pi, tRNS, j, 0/*color*/); 3313 # endif 3314 } 3315 } 3316 3317 #ifdef PNG_WRITE_tRNS_SUPPORTED 3318 static void 3319 set_random_tRNS(png_structp pp, png_infop pi, const png_byte colour_type, 3320 const int bit_depth) 3321 { 3322 /* To make this useful the tRNS color needs to match at least one pixel. 3323 * Random values are fine for gray, including the 16-bit case where we know 3324 * that the test image contains all the gray values. For RGB we need more 3325 * method as only 65536 different RGB values are generated. 3326 */ 3327 png_color_16 tRNS; 3328 const png_uint_16 mask = (png_uint_16)((1U << bit_depth)-1); 3329 3330 R8(tRNS); /* makes unset fields random */ 3331 3332 if (colour_type & 2/*RGB*/) 3333 { 3334 if (bit_depth == 8) 3335 { 3336 R16(tRNS.red); 3337 R16(tRNS.green); 3338 tRNS.blue = tRNS.red ^ tRNS.green; 3339 tRNS.red &= mask; 3340 tRNS.green &= mask; 3341 tRNS.blue &= mask; 3342 } 3343 3344 else /* bit_depth == 16 */ 3345 { 3346 R16(tRNS.red); 3347 tRNS.green = (png_uint_16)(tRNS.red * 257); 3348 tRNS.blue = (png_uint_16)(tRNS.green * 17); 3349 } 3350 } 3351 3352 else 3353 { 3354 R16(tRNS.gray); 3355 tRNS.gray &= mask; 3356 } 3357 3358 png_set_tRNS(pp, pi, NULL, 0, &tRNS); 3359 } 3360 #endif 3361 3362 /* The number of passes is related to the interlace type. There was no libpng 3363 * API to determine this prior to 1.5, so we need an inquiry function: 3364 */ 3365 static int 3366 npasses_from_interlace_type(png_const_structp pp, int interlace_type) 3367 { 3368 switch (interlace_type) 3369 { 3370 default: 3371 png_error(pp, "invalid interlace type"); 3372 3373 case PNG_INTERLACE_NONE: 3374 return 1; 3375 3376 case PNG_INTERLACE_ADAM7: 3377 return PNG_INTERLACE_ADAM7_PASSES; 3378 } 3379 } 3380 3381 static unsigned int 3382 bit_size(png_const_structp pp, png_byte colour_type, png_byte bit_depth) 3383 { 3384 switch (colour_type) 3385 { 3386 default: png_error(pp, "invalid color type"); 3387 3388 case 0: return bit_depth; 3389 3390 case 2: return 3*bit_depth; 3391 3392 case 3: return bit_depth; 3393 3394 case 4: return 2*bit_depth; 3395 3396 case 6: return 4*bit_depth; 3397 } 3398 } 3399 3400 #define TRANSFORM_WIDTH 128U 3401 #define TRANSFORM_ROWMAX (TRANSFORM_WIDTH*8U) 3402 #define SIZE_ROWMAX (16*8U) /* 16 pixels, max 8 bytes each - 128 bytes */ 3403 #define STANDARD_ROWMAX TRANSFORM_ROWMAX /* The larger of the two */ 3404 #define SIZE_HEIGHTMAX 16 /* Maximum range of size images */ 3405 3406 static size_t 3407 transform_rowsize(png_const_structp pp, png_byte colour_type, 3408 png_byte bit_depth) 3409 { 3410 return (TRANSFORM_WIDTH * bit_size(pp, colour_type, bit_depth)) / 8; 3411 } 3412 3413 /* transform_width(pp, colour_type, bit_depth) current returns the same number 3414 * every time, so just use a macro: 3415 */ 3416 #define transform_width(pp, colour_type, bit_depth) TRANSFORM_WIDTH 3417 3418 static png_uint_32 3419 transform_height(png_const_structp pp, png_byte colour_type, png_byte bit_depth) 3420 { 3421 switch (bit_size(pp, colour_type, bit_depth)) 3422 { 3423 case 1: 3424 case 2: 3425 case 4: 3426 return 1; /* Total of 128 pixels */ 3427 3428 case 8: 3429 return 2; /* Total of 256 pixels/bytes */ 3430 3431 case 16: 3432 return 512; /* Total of 65536 pixels */ 3433 3434 case 24: 3435 case 32: 3436 return 512; /* 65536 pixels */ 3437 3438 case 48: 3439 case 64: 3440 return 2048;/* 4 x 65536 pixels. */ 3441 # define TRANSFORM_HEIGHTMAX 2048 3442 3443 default: 3444 return 0; /* Error, will be caught later */ 3445 } 3446 } 3447 3448 #ifdef PNG_READ_SUPPORTED 3449 /* The following can only be defined here, now we have the definitions 3450 * of the transform image sizes. 3451 */ 3452 static png_uint_32 3453 standard_width(png_const_structp pp, png_uint_32 id) 3454 { 3455 png_uint_32 width = WIDTH_FROM_ID(id); 3456 UNUSED(pp) 3457 3458 if (width == 0) 3459 width = transform_width(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); 3460 3461 return width; 3462 } 3463 3464 static png_uint_32 3465 standard_height(png_const_structp pp, png_uint_32 id) 3466 { 3467 png_uint_32 height = HEIGHT_FROM_ID(id); 3468 3469 if (height == 0) 3470 height = transform_height(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); 3471 3472 return height; 3473 } 3474 3475 static png_uint_32 3476 standard_rowsize(png_const_structp pp, png_uint_32 id) 3477 { 3478 png_uint_32 width = standard_width(pp, id); 3479 3480 /* This won't overflow: */ 3481 width *= bit_size(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); 3482 return (width + 7) / 8; 3483 } 3484 #endif /* PNG_READ_SUPPORTED */ 3485 3486 static void 3487 transform_row(png_const_structp pp, png_byte buffer[TRANSFORM_ROWMAX], 3488 png_byte colour_type, png_byte bit_depth, png_uint_32 y) 3489 { 3490 png_uint_32 v = y << 7; 3491 png_uint_32 i = 0; 3492 3493 switch (bit_size(pp, colour_type, bit_depth)) 3494 { 3495 case 1: 3496 while (i<128/8) buffer[i] = (png_byte)(v & 0xff), v += 17, ++i; 3497 return; 3498 3499 case 2: 3500 while (i<128/4) buffer[i] = (png_byte)(v & 0xff), v += 33, ++i; 3501 return; 3502 3503 case 4: 3504 while (i<128/2) buffer[i] = (png_byte)(v & 0xff), v += 65, ++i; 3505 return; 3506 3507 case 8: 3508 /* 256 bytes total, 128 bytes in each row set as follows: */ 3509 while (i<128) buffer[i] = (png_byte)(v & 0xff), ++v, ++i; 3510 return; 3511 3512 case 16: 3513 /* Generate all 65536 pixel values in order, which includes the 8 bit 3514 * GA case as well as the 16 bit G case. 3515 */ 3516 while (i<128) 3517 { 3518 buffer[2*i] = (png_byte)((v>>8) & 0xff); 3519 buffer[2*i+1] = (png_byte)(v & 0xff); 3520 ++v; 3521 ++i; 3522 } 3523 3524 return; 3525 3526 case 24: 3527 /* 65535 pixels, but rotate the values. */ 3528 while (i<128) 3529 { 3530 /* Three bytes per pixel, r, g, b, make b by r^g */ 3531 buffer[3*i+0] = (png_byte)((v >> 8) & 0xff); 3532 buffer[3*i+1] = (png_byte)(v & 0xff); 3533 buffer[3*i+2] = (png_byte)(((v >> 8) ^ v) & 0xff); 3534 ++v; 3535 ++i; 3536 } 3537 3538 return; 3539 3540 case 32: 3541 /* 65535 pixels, r, g, b, a; just replicate */ 3542 while (i<128) 3543 { 3544 buffer[4*i+0] = (png_byte)((v >> 8) & 0xff); 3545 buffer[4*i+1] = (png_byte)(v & 0xff); 3546 buffer[4*i+2] = (png_byte)((v >> 8) & 0xff); 3547 buffer[4*i+3] = (png_byte)(v & 0xff); 3548 ++v; 3549 ++i; 3550 } 3551 3552 return; 3553 3554 case 48: 3555 /* y is maximum 2047, giving 4x65536 pixels, make 'r' increase by 1 at 3556 * each pixel, g increase by 257 (0x101) and 'b' by 0x1111: 3557 */ 3558 while (i<128) 3559 { 3560 png_uint_32 t = v++; 3561 buffer[6*i+0] = (png_byte)((t >> 8) & 0xff); 3562 buffer[6*i+1] = (png_byte)(t & 0xff); 3563 t *= 257; 3564 buffer[6*i+2] = (png_byte)((t >> 8) & 0xff); 3565 buffer[6*i+3] = (png_byte)(t & 0xff); 3566 t *= 17; 3567 buffer[6*i+4] = (png_byte)((t >> 8) & 0xff); 3568 buffer[6*i+5] = (png_byte)(t & 0xff); 3569 ++i; 3570 } 3571 3572 return; 3573 3574 case 64: 3575 /* As above in the 32 bit case. */ 3576 while (i<128) 3577 { 3578 png_uint_32 t = v++; 3579 buffer[8*i+0] = (png_byte)((t >> 8) & 0xff); 3580 buffer[8*i+1] = (png_byte)(t & 0xff); 3581 buffer[8*i+4] = (png_byte)((t >> 8) & 0xff); 3582 buffer[8*i+5] = (png_byte)(t & 0xff); 3583 t *= 257; 3584 buffer[8*i+2] = (png_byte)((t >> 8) & 0xff); 3585 buffer[8*i+3] = (png_byte)(t & 0xff); 3586 buffer[8*i+6] = (png_byte)((t >> 8) & 0xff); 3587 buffer[8*i+7] = (png_byte)(t & 0xff); 3588 ++i; 3589 } 3590 return; 3591 3592 default: 3593 break; 3594 } 3595 3596 png_error(pp, "internal error"); 3597 } 3598 3599 /* This is just to do the right cast - could be changed to a function to check 3600 * 'bd' but there isn't much point. 3601 */ 3602 #define DEPTH(bd) ((png_byte)(1U << (bd))) 3603 3604 /* This is just a helper for compiling on minimal systems with no write 3605 * interlacing support. If there is no write interlacing we can't generate test 3606 * cases with interlace: 3607 */ 3608 #ifdef PNG_WRITE_INTERLACING_SUPPORTED 3609 # define INTERLACE_LAST PNG_INTERLACE_LAST 3610 # define check_interlace_type(type) ((void)(type)) 3611 # define set_write_interlace_handling(pp,type) png_set_interlace_handling(pp) 3612 # define do_own_interlace 0 3613 #elif PNG_LIBPNG_VER < 10700 3614 # define set_write_interlace_handling(pp,type) (1) 3615 static void 3616 check_interlace_type(int const interlace_type) 3617 { 3618 /* Prior to 1.7.0 libpng does not support the write of an interlaced image 3619 * unless PNG_WRITE_INTERLACING_SUPPORTED, even with do_interlace so the 3620 * code here does the pixel interlace itself, so: 3621 */ 3622 if (interlace_type != PNG_INTERLACE_NONE) 3623 { 3624 /* This is an internal error - --interlace tests should be skipped, not 3625 * attempted. 3626 */ 3627 fprintf(stderr, "pngvalid: no interlace support\n"); 3628 exit(99); 3629 } 3630 } 3631 # define INTERLACE_LAST (PNG_INTERLACE_NONE+1) 3632 # define do_own_interlace 0 3633 #else /* libpng 1.7+ */ 3634 # define set_write_interlace_handling(pp,type)\ 3635 npasses_from_interlace_type(pp,type) 3636 # define check_interlace_type(type) ((void)(type)) 3637 # define INTERLACE_LAST PNG_INTERLACE_LAST 3638 # define do_own_interlace 1 3639 #endif /* WRITE_INTERLACING tests */ 3640 3641 #define CAN_WRITE_INTERLACE\ 3642 PNG_LIBPNG_VER >= 10700 || defined PNG_WRITE_INTERLACING_SUPPORTED 3643 3644 /* Do the same thing for read interlacing; this controls whether read tests do 3645 * their own de-interlace or use libpng. 3646 */ 3647 #ifdef PNG_READ_INTERLACING_SUPPORTED 3648 # define do_read_interlace 0 3649 #else /* no libpng read interlace support */ 3650 # define do_read_interlace 1 3651 #endif 3652 /* The following two routines use the PNG interlace support macros from 3653 * png.h to interlace or deinterlace rows. 3654 */ 3655 static void 3656 interlace_row(png_bytep buffer, png_const_bytep imageRow, 3657 unsigned int pixel_size, png_uint_32 w, int pass, int littleendian) 3658 { 3659 png_uint_32 xin, xout, xstep; 3660 3661 /* Note that this can, trivially, be optimized to a memcpy on pass 7, the 3662 * code is presented this way to make it easier to understand. In practice 3663 * consult the code in the libpng source to see other ways of doing this. 3664 * 3665 * It is OK for buffer and imageRow to be identical, because 'xin' moves 3666 * faster than 'xout' and we copy up. 3667 */ 3668 xin = PNG_PASS_START_COL(pass); 3669 xstep = 1U<<PNG_PASS_COL_SHIFT(pass); 3670 3671 for (xout=0; xin<w; xin+=xstep) 3672 { 3673 pixel_copy(buffer, xout, imageRow, xin, pixel_size, littleendian); 3674 ++xout; 3675 } 3676 } 3677 3678 #ifdef PNG_READ_SUPPORTED 3679 static void 3680 deinterlace_row(png_bytep buffer, png_const_bytep row, 3681 unsigned int pixel_size, png_uint_32 w, int pass, int littleendian) 3682 { 3683 /* The inverse of the above, 'row' is part of row 'y' of the output image, 3684 * in 'buffer'. The image is 'w' wide and this is pass 'pass', distribute 3685 * the pixels of row into buffer and return the number written (to allow 3686 * this to be checked). 3687 */ 3688 png_uint_32 xin, xout, xstep; 3689 3690 xout = PNG_PASS_START_COL(pass); 3691 xstep = 1U<<PNG_PASS_COL_SHIFT(pass); 3692 3693 for (xin=0; xout<w; xout+=xstep) 3694 { 3695 pixel_copy(buffer, xout, row, xin, pixel_size, littleendian); 3696 ++xin; 3697 } 3698 } 3699 #endif /* PNG_READ_SUPPORTED */ 3700 3701 /* Make a standardized image given an image colour type, bit depth and 3702 * interlace type. The standard images have a very restricted range of 3703 * rows and heights and are used for testing transforms rather than image 3704 * layout details. See make_size_images below for a way to make images 3705 * that test odd sizes along with the libpng interlace handling. 3706 */ 3707 #ifdef PNG_WRITE_FILTER_SUPPORTED 3708 static void 3709 choose_random_filter(png_structp pp, int start) 3710 { 3711 /* Choose filters randomly except that on the very first row ensure that 3712 * there is at least one previous row filter. 3713 */ 3714 int filters = PNG_ALL_FILTERS & random_mod(256U); 3715 3716 /* There may be no filters; skip the setting. */ 3717 if (filters != 0) 3718 { 3719 if (start && filters < PNG_FILTER_UP) 3720 filters |= PNG_FILTER_UP; 3721 3722 png_set_filter(pp, 0/*method*/, filters); 3723 } 3724 } 3725 #else /* !WRITE_FILTER */ 3726 # define choose_random_filter(pp, start) ((void)0) 3727 #endif /* !WRITE_FILTER */ 3728 3729 static void 3730 make_transform_image(png_store* const ps, png_byte const colour_type, 3731 png_byte const bit_depth, unsigned int palette_number, 3732 int interlace_type, png_const_charp name) 3733 { 3734 context(ps, fault); 3735 3736 check_interlace_type(interlace_type); 3737 3738 Try 3739 { 3740 png_infop pi; 3741 png_structp pp = set_store_for_write(ps, &pi, name); 3742 png_uint_32 h, w; 3743 3744 /* In the event of a problem return control to the Catch statement below 3745 * to do the clean up - it is not possible to 'return' directly from a Try 3746 * block. 3747 */ 3748 if (pp == NULL) 3749 Throw ps; 3750 3751 w = transform_width(pp, colour_type, bit_depth); 3752 h = transform_height(pp, colour_type, bit_depth); 3753 3754 png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type, 3755 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 3756 3757 #ifdef PNG_TEXT_SUPPORTED 3758 # if defined(PNG_READ_zTXt_SUPPORTED) && defined(PNG_WRITE_zTXt_SUPPORTED) 3759 # define TEXT_COMPRESSION PNG_TEXT_COMPRESSION_zTXt 3760 # else 3761 # define TEXT_COMPRESSION PNG_TEXT_COMPRESSION_NONE 3762 # endif 3763 { 3764 static char key[] = "image name"; /* must be writeable */ 3765 size_t pos; 3766 png_text text; 3767 char copy[FILE_NAME_SIZE]; 3768 3769 /* Use a compressed text string to test the correct interaction of text 3770 * compression and IDAT compression. 3771 */ 3772 text.compression = TEXT_COMPRESSION; 3773 text.key = key; 3774 /* Yuck: the text must be writable! */ 3775 pos = safecat(copy, sizeof copy, 0, ps->wname); 3776 text.text = copy; 3777 text.text_length = pos; 3778 text.itxt_length = 0; 3779 text.lang = 0; 3780 text.lang_key = 0; 3781 3782 png_set_text(pp, pi, &text, 1); 3783 } 3784 #endif 3785 3786 if (colour_type == 3) /* palette */ 3787 init_standard_palette(ps, pp, pi, 1U << bit_depth, 1/*do tRNS*/); 3788 3789 # ifdef PNG_WRITE_tRNS_SUPPORTED 3790 else if (palette_number) 3791 set_random_tRNS(pp, pi, colour_type, bit_depth); 3792 # endif 3793 3794 png_write_info(pp, pi); 3795 3796 if (png_get_rowbytes(pp, pi) != 3797 transform_rowsize(pp, colour_type, bit_depth)) 3798 png_error(pp, "transform row size incorrect"); 3799 3800 else 3801 { 3802 /* Somewhat confusingly this must be called *after* png_write_info 3803 * because if it is called before, the information in *pp has not been 3804 * updated to reflect the interlaced image. 3805 */ 3806 int npasses = set_write_interlace_handling(pp, interlace_type); 3807 int pass; 3808 3809 if (npasses != npasses_from_interlace_type(pp, interlace_type)) 3810 png_error(pp, "write: png_set_interlace_handling failed"); 3811 3812 for (pass=0; pass<npasses; ++pass) 3813 { 3814 png_uint_32 y; 3815 3816 /* do_own_interlace is a pre-defined boolean (a #define) which is 3817 * set if we have to work out the interlaced rows here. 3818 */ 3819 for (y=0; y<h; ++y) 3820 { 3821 png_byte buffer[TRANSFORM_ROWMAX]; 3822 3823 transform_row(pp, buffer, colour_type, bit_depth, y); 3824 3825 # if do_own_interlace 3826 /* If do_own_interlace *and* the image is interlaced we need a 3827 * reduced interlace row; this may be reduced to empty. 3828 */ 3829 if (interlace_type == PNG_INTERLACE_ADAM7) 3830 { 3831 /* The row must not be written if it doesn't exist, notice 3832 * that there are two conditions here, either the row isn't 3833 * ever in the pass or the row would be but isn't wide 3834 * enough to contribute any pixels. In fact the wPass test 3835 * can be used to skip the whole y loop in this case. 3836 */ 3837 if (PNG_ROW_IN_INTERLACE_PASS(y, pass) && 3838 PNG_PASS_COLS(w, pass) > 0) 3839 interlace_row(buffer, buffer, 3840 bit_size(pp, colour_type, bit_depth), w, pass, 3841 0/*data always bigendian*/); 3842 else 3843 continue; 3844 } 3845 # endif /* do_own_interlace */ 3846 3847 choose_random_filter(pp, pass == 0 && y == 0); 3848 png_write_row(pp, buffer); 3849 } 3850 } 3851 } 3852 3853 #ifdef PNG_TEXT_SUPPORTED 3854 { 3855 static char key[] = "end marker"; 3856 static char comment[] = "end"; 3857 png_text text; 3858 3859 /* Use a compressed text string to test the correct interaction of text 3860 * compression and IDAT compression. 3861 */ 3862 text.compression = TEXT_COMPRESSION; 3863 text.key = key; 3864 text.text = comment; 3865 text.text_length = (sizeof comment)-1; 3866 text.itxt_length = 0; 3867 text.lang = 0; 3868 text.lang_key = 0; 3869 3870 png_set_text(pp, pi, &text, 1); 3871 } 3872 #endif 3873 3874 png_write_end(pp, pi); 3875 3876 /* And store this under the appropriate id, then clean up. */ 3877 store_storefile(ps, FILEID(colour_type, bit_depth, palette_number, 3878 interlace_type, 0, 0, 0)); 3879 3880 store_write_reset(ps); 3881 } 3882 3883 Catch(fault) 3884 { 3885 /* Use the png_store returned by the exception. This may help the compiler 3886 * because 'ps' is not used in this branch of the setjmp. Note that fault 3887 * and ps will always be the same value. 3888 */ 3889 store_write_reset(fault); 3890 } 3891 } 3892 3893 static void 3894 make_transform_images(png_modifier *pm) 3895 { 3896 png_byte colour_type = 0; 3897 png_byte bit_depth = 0; 3898 unsigned int palette_number = 0; 3899 3900 /* This is in case of errors. */ 3901 safecat(pm->this.test, sizeof pm->this.test, 0, "make standard images"); 3902 3903 /* Use next_format to enumerate all the combinations we test, including 3904 * generating multiple low bit depth palette images. Non-A images (palette 3905 * and direct) are created with and without tRNS chunks. 3906 */ 3907 while (next_format(&colour_type, &bit_depth, &palette_number, 1, 1)) 3908 { 3909 int interlace_type; 3910 3911 for (interlace_type = PNG_INTERLACE_NONE; 3912 interlace_type < INTERLACE_LAST; ++interlace_type) 3913 { 3914 char name[FILE_NAME_SIZE]; 3915 3916 standard_name(name, sizeof name, 0, colour_type, bit_depth, 3917 palette_number, interlace_type, 0, 0, do_own_interlace); 3918 make_transform_image(&pm->this, colour_type, bit_depth, palette_number, 3919 interlace_type, name); 3920 } 3921 } 3922 } 3923 3924 /* Build a single row for the 'size' test images; this fills in only the 3925 * first bit_width bits of the sample row. 3926 */ 3927 static void 3928 size_row(png_byte buffer[SIZE_ROWMAX], png_uint_32 bit_width, png_uint_32 y) 3929 { 3930 /* height is in the range 1 to 16, so: */ 3931 y = ((y & 1) << 7) + ((y & 2) << 6) + ((y & 4) << 5) + ((y & 8) << 4); 3932 /* the following ensures bits are set in small images: */ 3933 y ^= 0xA5; 3934 3935 while (bit_width >= 8) 3936 *buffer++ = (png_byte)y++, bit_width -= 8; 3937 3938 /* There may be up to 7 remaining bits, these go in the most significant 3939 * bits of the byte. 3940 */ 3941 if (bit_width > 0) 3942 { 3943 png_uint_32 mask = (1U<<(8-bit_width))-1; 3944 *buffer = (png_byte)((*buffer & mask) | (y & ~mask)); 3945 } 3946 } 3947 3948 static void 3949 make_size_image(png_store* const ps, png_byte const colour_type, 3950 png_byte const bit_depth, int const interlace_type, 3951 png_uint_32 const w, png_uint_32 const h, 3952 int const do_interlace) 3953 { 3954 context(ps, fault); 3955 3956 check_interlace_type(interlace_type); 3957 3958 Try 3959 { 3960 png_infop pi; 3961 png_structp pp; 3962 unsigned int pixel_size; 3963 3964 /* Make a name and get an appropriate id for the store: */ 3965 char name[FILE_NAME_SIZE]; 3966 const png_uint_32 id = FILEID(colour_type, bit_depth, 0/*palette*/, 3967 interlace_type, w, h, do_interlace); 3968 3969 standard_name_from_id(name, sizeof name, 0, id); 3970 pp = set_store_for_write(ps, &pi, name); 3971 3972 /* In the event of a problem return control to the Catch statement below 3973 * to do the clean up - it is not possible to 'return' directly from a Try 3974 * block. 3975 */ 3976 if (pp == NULL) 3977 Throw ps; 3978 3979 png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type, 3980 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 3981 3982 #ifdef PNG_TEXT_SUPPORTED 3983 { 3984 static char key[] = "image name"; /* must be writeable */ 3985 size_t pos; 3986 png_text text; 3987 char copy[FILE_NAME_SIZE]; 3988 3989 /* Use a compressed text string to test the correct interaction of text 3990 * compression and IDAT compression. 3991 */ 3992 text.compression = TEXT_COMPRESSION; 3993 text.key = key; 3994 /* Yuck: the text must be writable! */ 3995 pos = safecat(copy, sizeof copy, 0, ps->wname); 3996 text.text = copy; 3997 text.text_length = pos; 3998 text.itxt_length = 0; 3999 text.lang = 0; 4000 text.lang_key = 0; 4001 4002 png_set_text(pp, pi, &text, 1); 4003 } 4004 #endif 4005 4006 if (colour_type == 3) /* palette */ 4007 init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/); 4008 4009 png_write_info(pp, pi); 4010 4011 /* Calculate the bit size, divide by 8 to get the byte size - this won't 4012 * overflow because we know the w values are all small enough even for 4013 * a system where 'unsigned int' is only 16 bits. 4014 */ 4015 pixel_size = bit_size(pp, colour_type, bit_depth); 4016 if (png_get_rowbytes(pp, pi) != ((w * pixel_size) + 7) / 8) 4017 png_error(pp, "size row size incorrect"); 4018 4019 else 4020 { 4021 int npasses = npasses_from_interlace_type(pp, interlace_type); 4022 png_uint_32 y; 4023 int pass; 4024 png_byte image[16][SIZE_ROWMAX]; 4025 4026 /* To help consistent error detection make the parts of this buffer 4027 * that aren't set below all '1': 4028 */ 4029 memset(image, 0xff, sizeof image); 4030 4031 if (!do_interlace && 4032 npasses != set_write_interlace_handling(pp, interlace_type)) 4033 png_error(pp, "write: png_set_interlace_handling failed"); 4034 4035 /* Prepare the whole image first to avoid making it 7 times: */ 4036 for (y=0; y<h; ++y) 4037 size_row(image[y], w * pixel_size, y); 4038 4039 for (pass=0; pass<npasses; ++pass) 4040 { 4041 /* The following two are for checking the macros: */ 4042 const png_uint_32 wPass = PNG_PASS_COLS(w, pass); 4043 4044 /* If do_interlace is set we don't call png_write_row for every 4045 * row because some of them are empty. In fact, for a 1x1 image, 4046 * most of them are empty! 4047 */ 4048 for (y=0; y<h; ++y) 4049 { 4050 png_const_bytep row = image[y]; 4051 png_byte tempRow[SIZE_ROWMAX]; 4052 4053 /* If do_interlace *and* the image is interlaced we 4054 * need a reduced interlace row; this may be reduced 4055 * to empty. 4056 */ 4057 if (do_interlace && interlace_type == PNG_INTERLACE_ADAM7) 4058 { 4059 /* The row must not be written if it doesn't exist, notice 4060 * that there are two conditions here, either the row isn't 4061 * ever in the pass or the row would be but isn't wide 4062 * enough to contribute any pixels. In fact the wPass test 4063 * can be used to skip the whole y loop in this case. 4064 */ 4065 if (PNG_ROW_IN_INTERLACE_PASS(y, pass) && wPass > 0) 4066 { 4067 /* Set to all 1's for error detection (libpng tends to 4068 * set unset things to 0). 4069 */ 4070 memset(tempRow, 0xff, sizeof tempRow); 4071 interlace_row(tempRow, row, pixel_size, w, pass, 4072 0/*data always bigendian*/); 4073 row = tempRow; 4074 } 4075 else 4076 continue; 4077 } 4078 4079 # ifdef PNG_WRITE_FILTER_SUPPORTED 4080 /* Only get to here if the row has some pixels in it, set the 4081 * filters to 'all' for the very first row and thereafter to a 4082 * single filter. It isn't well documented, but png_set_filter 4083 * does accept a filter number (per the spec) as well as a bit 4084 * mask. 4085 * 4086 * The code now uses filters at random, except that on the first 4087 * row of an image it ensures that a previous row filter is in 4088 * the set so that libpng allocates the row buffer. 4089 */ 4090 { 4091 int filters = 8 << random_mod(PNG_FILTER_VALUE_LAST); 4092 4093 if (pass == 0 && y == 0 && 4094 (filters < PNG_FILTER_UP || w == 1U)) 4095 filters |= PNG_FILTER_UP; 4096 4097 png_set_filter(pp, 0/*method*/, filters); 4098 } 4099 # endif 4100 4101 png_write_row(pp, row); 4102 } 4103 } 4104 } 4105 4106 #ifdef PNG_TEXT_SUPPORTED 4107 { 4108 static char key[] = "end marker"; 4109 static char comment[] = "end"; 4110 png_text text; 4111 4112 /* Use a compressed text string to test the correct interaction of text 4113 * compression and IDAT compression. 4114 */ 4115 text.compression = TEXT_COMPRESSION; 4116 text.key = key; 4117 text.text = comment; 4118 text.text_length = (sizeof comment)-1; 4119 text.itxt_length = 0; 4120 text.lang = 0; 4121 text.lang_key = 0; 4122 4123 png_set_text(pp, pi, &text, 1); 4124 } 4125 #endif 4126 4127 png_write_end(pp, pi); 4128 4129 /* And store this under the appropriate id, then clean up. */ 4130 store_storefile(ps, id); 4131 4132 store_write_reset(ps); 4133 } 4134 4135 Catch(fault) 4136 { 4137 /* Use the png_store returned by the exception. This may help the compiler 4138 * because 'ps' is not used in this branch of the setjmp. Note that fault 4139 * and ps will always be the same value. 4140 */ 4141 store_write_reset(fault); 4142 } 4143 } 4144 4145 static void 4146 make_size(png_store* const ps, png_byte const colour_type, int bdlo, 4147 int const bdhi) 4148 { 4149 for (; bdlo <= bdhi; ++bdlo) 4150 { 4151 png_uint_32 width; 4152 4153 for (width = 1; width <= 16; ++width) 4154 { 4155 png_uint_32 height; 4156 4157 for (height = 1; height <= 16; ++height) 4158 { 4159 /* The four combinations of DIY interlace and interlace or not - 4160 * no interlace + DIY should be identical to no interlace with 4161 * libpng doing it. 4162 */ 4163 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE, 4164 width, height, 0); 4165 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE, 4166 width, height, 1); 4167 # ifdef PNG_WRITE_INTERLACING_SUPPORTED 4168 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7, 4169 width, height, 0); 4170 # endif 4171 # if CAN_WRITE_INTERLACE 4172 /* 1.7.0 removes the hack that prevented app write of an interlaced 4173 * image if WRITE_INTERLACE was not supported 4174 */ 4175 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7, 4176 width, height, 1); 4177 # endif 4178 } 4179 } 4180 } 4181 } 4182 4183 static void 4184 make_size_images(png_store *ps) 4185 { 4186 /* This is in case of errors. */ 4187 safecat(ps->test, sizeof ps->test, 0, "make size images"); 4188 4189 /* Arguments are colour_type, low bit depth, high bit depth 4190 */ 4191 make_size(ps, 0, 0, WRITE_BDHI); 4192 make_size(ps, 2, 3, WRITE_BDHI); 4193 make_size(ps, 3, 0, 3 /*palette: max 8 bits*/); 4194 make_size(ps, 4, 3, WRITE_BDHI); 4195 make_size(ps, 6, 3, WRITE_BDHI); 4196 } 4197 4198 #ifdef PNG_READ_SUPPORTED 4199 /* Return a row based on image id and 'y' for checking: */ 4200 static void 4201 standard_row(png_const_structp pp, png_byte std[STANDARD_ROWMAX], 4202 png_uint_32 id, png_uint_32 y) 4203 { 4204 if (WIDTH_FROM_ID(id) == 0) 4205 transform_row(pp, std, COL_FROM_ID(id), DEPTH_FROM_ID(id), y); 4206 else 4207 size_row(std, WIDTH_FROM_ID(id) * bit_size(pp, COL_FROM_ID(id), 4208 DEPTH_FROM_ID(id)), y); 4209 } 4210 #endif /* PNG_READ_SUPPORTED */ 4211 4212 /* Tests - individual test cases */ 4213 /* Like 'make_standard' but errors are deliberately introduced into the calls 4214 * to ensure that they get detected - it should not be possible to write an 4215 * invalid image with libpng! 4216 */ 4217 /* TODO: the 'set' functions can probably all be made to take a 4218 * png_const_structp rather than a modifiable one. 4219 */ 4220 #ifdef PNG_WARNINGS_SUPPORTED 4221 static void 4222 sBIT0_error_fn(png_structp pp, png_infop pi) 4223 { 4224 /* 0 is invalid... */ 4225 png_color_8 bad; 4226 bad.red = bad.green = bad.blue = bad.gray = bad.alpha = 0; 4227 png_set_sBIT(pp, pi, &bad); 4228 } 4229 4230 static void 4231 sBIT_error_fn(png_structp pp, png_infop pi) 4232 { 4233 png_byte bit_depth; 4234 png_color_8 bad; 4235 4236 if (png_get_color_type(pp, pi) == PNG_COLOR_TYPE_PALETTE) 4237 bit_depth = 8; 4238 4239 else 4240 bit_depth = png_get_bit_depth(pp, pi); 4241 4242 /* Now we know the bit depth we can easily generate an invalid sBIT entry */ 4243 bad.red = bad.green = bad.blue = bad.gray = bad.alpha = 4244 (png_byte)(bit_depth+1); 4245 png_set_sBIT(pp, pi, &bad); 4246 } 4247 4248 static const struct 4249 { 4250 void (*fn)(png_structp, png_infop); 4251 const char *msg; 4252 unsigned int warning :1; /* the error is a warning... */ 4253 } error_test[] = 4254 { 4255 /* no warnings makes these errors undetectable prior to 1.7.0 */ 4256 { sBIT0_error_fn, "sBIT(0): failed to detect error", 4257 PNG_LIBPNG_VER < 10700 }, 4258 4259 { sBIT_error_fn, "sBIT(too big): failed to detect error", 4260 PNG_LIBPNG_VER < 10700 }, 4261 }; 4262 4263 static void 4264 make_error(png_store* const ps, png_byte const colour_type, 4265 png_byte bit_depth, int interlace_type, int test, png_const_charp name) 4266 { 4267 context(ps, fault); 4268 4269 check_interlace_type(interlace_type); 4270 4271 Try 4272 { 4273 png_infop pi; 4274 const png_structp pp = set_store_for_write(ps, &pi, name); 4275 png_uint_32 w, h; 4276 gnu_volatile(pp) 4277 4278 if (pp == NULL) 4279 Throw ps; 4280 4281 w = transform_width(pp, colour_type, bit_depth); 4282 gnu_volatile(w) 4283 h = transform_height(pp, colour_type, bit_depth); 4284 gnu_volatile(h) 4285 png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type, 4286 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 4287 4288 if (colour_type == 3) /* palette */ 4289 init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/); 4290 4291 /* Time for a few errors; these are in various optional chunks, the 4292 * standard tests test the standard chunks pretty well. 4293 */ 4294 # define exception__prev exception_prev_1 4295 # define exception__env exception_env_1 4296 Try 4297 { 4298 gnu_volatile(exception__prev) 4299 4300 /* Expect this to throw: */ 4301 ps->expect_error = !error_test[test].warning; 4302 ps->expect_warning = error_test[test].warning; 4303 ps->saw_warning = 0; 4304 error_test[test].fn(pp, pi); 4305 4306 /* Normally the error is only detected here: */ 4307 png_write_info(pp, pi); 4308 4309 /* And handle the case where it was only a warning: */ 4310 if (ps->expect_warning && ps->saw_warning) 4311 Throw ps; 4312 4313 /* If we get here there is a problem, we have success - no error or 4314 * no warning - when we shouldn't have success. Log an error. 4315 */ 4316 store_log(ps, pp, error_test[test].msg, 1 /*error*/); 4317 } 4318 4319 Catch (fault) 4320 { /* expected exit */ 4321 } 4322 #undef exception__prev 4323 #undef exception__env 4324 4325 /* And clear these flags */ 4326 ps->expect_warning = 0; 4327 4328 if (ps->expect_error) 4329 ps->expect_error = 0; 4330 4331 else 4332 { 4333 /* Now write the whole image, just to make sure that the detected, or 4334 * undetected, errro has not created problems inside libpng. This 4335 * doesn't work if there was a png_error in png_write_info because that 4336 * can abort before PLTE was written. 4337 */ 4338 if (png_get_rowbytes(pp, pi) != 4339 transform_rowsize(pp, colour_type, bit_depth)) 4340 png_error(pp, "row size incorrect"); 4341 4342 else 4343 { 4344 int npasses = set_write_interlace_handling(pp, interlace_type); 4345 int pass; 4346 4347 if (npasses != npasses_from_interlace_type(pp, interlace_type)) 4348 png_error(pp, "write: png_set_interlace_handling failed"); 4349 4350 for (pass=0; pass<npasses; ++pass) 4351 { 4352 png_uint_32 y; 4353 4354 for (y=0; y<h; ++y) 4355 { 4356 png_byte buffer[TRANSFORM_ROWMAX]; 4357 4358 transform_row(pp, buffer, colour_type, bit_depth, y); 4359 4360 # if do_own_interlace 4361 /* If do_own_interlace *and* the image is interlaced we 4362 * need a reduced interlace row; this may be reduced to 4363 * empty. 4364 */ 4365 if (interlace_type == PNG_INTERLACE_ADAM7) 4366 { 4367 /* The row must not be written if it doesn't exist, 4368 * notice that there are two conditions here, either the 4369 * row isn't ever in the pass or the row would be but 4370 * isn't wide enough to contribute any pixels. In fact 4371 * the wPass test can be used to skip the whole y loop 4372 * in this case. 4373 */ 4374 if (PNG_ROW_IN_INTERLACE_PASS(y, pass) && 4375 PNG_PASS_COLS(w, pass) > 0) 4376 interlace_row(buffer, buffer, 4377 bit_size(pp, colour_type, bit_depth), w, pass, 4378 0/*data always bigendian*/); 4379 else 4380 continue; 4381 } 4382 # endif /* do_own_interlace */ 4383 4384 png_write_row(pp, buffer); 4385 } 4386 } 4387 } /* image writing */ 4388 4389 png_write_end(pp, pi); 4390 } 4391 4392 /* The following deletes the file that was just written. */ 4393 store_write_reset(ps); 4394 } 4395 4396 Catch(fault) 4397 { 4398 store_write_reset(fault); 4399 } 4400 } 4401 4402 static int 4403 make_errors(png_modifier* const pm, png_byte const colour_type, 4404 int bdlo, int const bdhi) 4405 { 4406 for (; bdlo <= bdhi; ++bdlo) 4407 { 4408 int interlace_type; 4409 4410 for (interlace_type = PNG_INTERLACE_NONE; 4411 interlace_type < INTERLACE_LAST; ++interlace_type) 4412 { 4413 unsigned int test; 4414 char name[FILE_NAME_SIZE]; 4415 4416 standard_name(name, sizeof name, 0, colour_type, 1<<bdlo, 0, 4417 interlace_type, 0, 0, do_own_interlace); 4418 4419 for (test=0; test<ARRAY_SIZE(error_test); ++test) 4420 { 4421 make_error(&pm->this, colour_type, DEPTH(bdlo), interlace_type, 4422 test, name); 4423 4424 if (fail(pm)) 4425 return 0; 4426 } 4427 } 4428 } 4429 4430 return 1; /* keep going */ 4431 } 4432 #endif /* PNG_WARNINGS_SUPPORTED */ 4433 4434 static void 4435 perform_error_test(png_modifier *pm) 4436 { 4437 #ifdef PNG_WARNINGS_SUPPORTED /* else there are no cases that work! */ 4438 /* Need to do this here because we just write in this test. */ 4439 safecat(pm->this.test, sizeof pm->this.test, 0, "error test"); 4440 4441 if (!make_errors(pm, 0, 0, WRITE_BDHI)) 4442 return; 4443 4444 if (!make_errors(pm, 2, 3, WRITE_BDHI)) 4445 return; 4446 4447 if (!make_errors(pm, 3, 0, 3)) 4448 return; 4449 4450 if (!make_errors(pm, 4, 3, WRITE_BDHI)) 4451 return; 4452 4453 if (!make_errors(pm, 6, 3, WRITE_BDHI)) 4454 return; 4455 #else 4456 UNUSED(pm) 4457 #endif 4458 } 4459 4460 /* This is just to validate the internal PNG formatting code - if this fails 4461 * then the warning messages the library outputs will probably be garbage. 4462 */ 4463 static void 4464 perform_formatting_test(png_store *ps) 4465 { 4466 #ifdef PNG_TIME_RFC1123_SUPPORTED 4467 /* The handle into the formatting code is the RFC1123 support; this test does 4468 * nothing if that is compiled out. 4469 */ 4470 context(ps, fault); 4471 4472 Try 4473 { 4474 png_const_charp correct = "29 Aug 2079 13:53:60 +0000"; 4475 png_const_charp result; 4476 # if PNG_LIBPNG_VER >= 10600 4477 char timestring[29]; 4478 # endif 4479 png_structp pp; 4480 png_time pt; 4481 4482 pp = set_store_for_write(ps, NULL, "libpng formatting test"); 4483 4484 if (pp == NULL) 4485 Throw ps; 4486 4487 4488 /* Arbitrary settings: */ 4489 pt.year = 2079; 4490 pt.month = 8; 4491 pt.day = 29; 4492 pt.hour = 13; 4493 pt.minute = 53; 4494 pt.second = 60; /* a leap second */ 4495 4496 # if PNG_LIBPNG_VER < 10600 4497 result = png_convert_to_rfc1123(pp, &pt); 4498 # else 4499 if (png_convert_to_rfc1123_buffer(timestring, &pt)) 4500 result = timestring; 4501 4502 else 4503 result = NULL; 4504 # endif 4505 4506 if (result == NULL) 4507 png_error(pp, "png_convert_to_rfc1123 failed"); 4508 4509 if (strcmp(result, correct) != 0) 4510 { 4511 size_t pos = 0; 4512 char msg[128]; 4513 4514 pos = safecat(msg, sizeof msg, pos, "png_convert_to_rfc1123("); 4515 pos = safecat(msg, sizeof msg, pos, correct); 4516 pos = safecat(msg, sizeof msg, pos, ") returned: '"); 4517 pos = safecat(msg, sizeof msg, pos, result); 4518 pos = safecat(msg, sizeof msg, pos, "'"); 4519 4520 png_error(pp, msg); 4521 } 4522 4523 store_write_reset(ps); 4524 } 4525 4526 Catch(fault) 4527 { 4528 store_write_reset(fault); 4529 } 4530 #else 4531 UNUSED(ps) 4532 #endif 4533 } 4534 4535 #ifdef PNG_READ_SUPPORTED 4536 /* Because we want to use the same code in both the progressive reader and the 4537 * sequential reader it is necessary to deal with the fact that the progressive 4538 * reader callbacks only have one parameter (png_get_progressive_ptr()), so this 4539 * must contain all the test parameters and all the local variables directly 4540 * accessible to the sequential reader implementation. 4541 * 4542 * The technique adopted is to reinvent part of what Dijkstra termed a 4543 * 'display'; an array of pointers to the stack frames of enclosing functions so 4544 * that a nested function definition can access the local (C auto) variables of 4545 * the functions that contain its definition. In fact C provides the first 4546 * pointer (the local variables - the stack frame pointer) and the last (the 4547 * global variables - the BCPL global vector typically implemented as global 4548 * addresses), this code requires one more pointer to make the display - the 4549 * local variables (and function call parameters) of the function that actually 4550 * invokes either the progressive or sequential reader. 4551 * 4552 * Perhaps confusingly this technique is confounded with classes - the 4553 * 'standard_display' defined here is sub-classed as the 'gamma_display' below. 4554 * A gamma_display is a standard_display, taking advantage of the ANSI-C 4555 * requirement that the pointer to the first member of a structure must be the 4556 * same as the pointer to the structure. This allows us to reuse standard_ 4557 * functions in the gamma test code; something that could not be done with 4558 * nested functions! 4559 */ 4560 typedef struct standard_display 4561 { 4562 png_store* ps; /* Test parameters (passed to the function) */ 4563 png_byte colour_type; 4564 png_byte bit_depth; 4565 png_byte red_sBIT; /* Input data sBIT values. */ 4566 png_byte green_sBIT; 4567 png_byte blue_sBIT; 4568 png_byte alpha_sBIT; 4569 png_byte interlace_type; 4570 png_byte filler; /* Output has a filler */ 4571 png_uint_32 id; /* Calculated file ID */ 4572 png_uint_32 w; /* Width of image */ 4573 png_uint_32 h; /* Height of image */ 4574 int npasses; /* Number of interlaced passes */ 4575 png_uint_32 pixel_size; /* Width of one pixel in bits */ 4576 png_uint_32 bit_width; /* Width of output row in bits */ 4577 size_t cbRow; /* Bytes in a row of the output image */ 4578 int do_interlace; /* Do interlacing internally */ 4579 int littleendian; /* App (row) data is little endian */ 4580 int is_transparent; /* Transparency information was present. */ 4581 int has_tRNS; /* color type GRAY or RGB with a tRNS chunk. */ 4582 int speed; /* Doing a speed test */ 4583 int use_update_info;/* Call update_info, not start_image */ 4584 struct 4585 { 4586 png_uint_16 red; 4587 png_uint_16 green; 4588 png_uint_16 blue; 4589 } transparent; /* The transparent color, if set. */ 4590 int npalette; /* Number of entries in the palette. */ 4591 store_palette 4592 palette; 4593 } standard_display; 4594 4595 static void 4596 standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id, 4597 int do_interlace, int use_update_info) 4598 { 4599 memset(dp, 0, sizeof *dp); 4600 4601 dp->ps = ps; 4602 dp->colour_type = COL_FROM_ID(id); 4603 dp->bit_depth = DEPTH_FROM_ID(id); 4604 if (dp->bit_depth < 1 || dp->bit_depth > 16) 4605 internal_error(ps, "internal: bad bit depth"); 4606 if (dp->colour_type == 3) 4607 dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = 8; 4608 else 4609 dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = 4610 dp->bit_depth; 4611 dp->interlace_type = INTERLACE_FROM_ID(id); 4612 check_interlace_type(dp->interlace_type); 4613 dp->id = id; 4614 /* All the rest are filled in after the read_info: */ 4615 dp->w = 0; 4616 dp->h = 0; 4617 dp->npasses = 0; 4618 dp->pixel_size = 0; 4619 dp->bit_width = 0; 4620 dp->cbRow = 0; 4621 dp->do_interlace = do_interlace; 4622 dp->littleendian = 0; 4623 dp->is_transparent = 0; 4624 dp->speed = ps->speed; 4625 dp->use_update_info = use_update_info; 4626 dp->npalette = 0; 4627 /* Preset the transparent color to black: */ 4628 memset(&dp->transparent, 0, sizeof dp->transparent); 4629 /* Preset the palette to full intensity/opaque througout: */ 4630 memset(dp->palette, 0xff, sizeof dp->palette); 4631 } 4632 4633 /* Initialize the palette fields - this must be done later because the palette 4634 * comes from the particular png_store_file that is selected. 4635 */ 4636 static void 4637 standard_palette_init(standard_display *dp) 4638 { 4639 store_palette_entry *palette = store_current_palette(dp->ps, &dp->npalette); 4640 4641 /* The remaining entries remain white/opaque. */ 4642 if (dp->npalette > 0) 4643 { 4644 int i = dp->npalette; 4645 memcpy(dp->palette, palette, i * sizeof *palette); 4646 4647 /* Check for a non-opaque palette entry: */ 4648 while (--i >= 0) 4649 if (palette[i].alpha < 255) 4650 break; 4651 4652 # ifdef __GNUC__ 4653 /* GCC can't handle the more obviously optimizable version. */ 4654 if (i >= 0) 4655 dp->is_transparent = 1; 4656 else 4657 dp->is_transparent = 0; 4658 # else 4659 dp->is_transparent = (i >= 0); 4660 # endif 4661 } 4662 } 4663 4664 /* Utility to read the palette from the PNG file and convert it into 4665 * store_palette format. This returns 1 if there is any transparency in the 4666 * palette (it does not check for a transparent colour in the non-palette case.) 4667 */ 4668 static int 4669 read_palette(store_palette palette, int *npalette, png_const_structp pp, 4670 png_infop pi) 4671 { 4672 png_colorp pal; 4673 png_bytep trans_alpha; 4674 int num; 4675 4676 pal = 0; 4677 *npalette = -1; 4678 4679 if (png_get_PLTE(pp, pi, &pal, npalette) & PNG_INFO_PLTE) 4680 { 4681 int i = *npalette; 4682 4683 if (i <= 0 || i > 256) 4684 png_error(pp, "validate: invalid PLTE count"); 4685 4686 while (--i >= 0) 4687 { 4688 palette[i].red = pal[i].red; 4689 palette[i].green = pal[i].green; 4690 palette[i].blue = pal[i].blue; 4691 } 4692 4693 /* Mark the remainder of the entries with a flag value (other than 4694 * white/opaque which is the flag value stored above.) 4695 */ 4696 memset(palette + *npalette, 126, (256-*npalette) * sizeof *palette); 4697 } 4698 4699 else /* !png_get_PLTE */ 4700 { 4701 if (*npalette != (-1)) 4702 png_error(pp, "validate: invalid PLTE result"); 4703 /* But there is no palette, so record this: */ 4704 *npalette = 0; 4705 memset(palette, 113, sizeof (store_palette)); 4706 } 4707 4708 trans_alpha = 0; 4709 num = 2; /* force error below */ 4710 if ((png_get_tRNS(pp, pi, &trans_alpha, &num, 0) & PNG_INFO_tRNS) != 0 && 4711 (trans_alpha != NULL || num != 1/*returns 1 for a transparent color*/) && 4712 /* Oops, if a palette tRNS gets expanded png_read_update_info (at least so 4713 * far as 1.5.4) does not remove the trans_alpha pointer, only num_trans, 4714 * so in the above call we get a success, we get a pointer (who knows what 4715 * to) and we get num_trans == 0: 4716 */ 4717 !(trans_alpha != NULL && num == 0)) /* TODO: fix this in libpng. */ 4718 { 4719 int i; 4720 4721 /* Any of these are crash-worthy - given the implementation of 4722 * png_get_tRNS up to 1.5 an app won't crash if it just checks the 4723 * result above and fails to check that the variables it passed have 4724 * actually been filled in! Note that if the app were to pass the 4725 * last, png_color_16p, variable too it couldn't rely on this. 4726 */ 4727 if (trans_alpha == NULL || num <= 0 || num > 256 || num > *npalette) 4728 png_error(pp, "validate: unexpected png_get_tRNS (palette) result"); 4729 4730 for (i=0; i<num; ++i) 4731 palette[i].alpha = trans_alpha[i]; 4732 4733 for (num=*npalette; i<num; ++i) 4734 palette[i].alpha = 255; 4735 4736 for (; i<256; ++i) 4737 palette[i].alpha = 33; /* flag value */ 4738 4739 return 1; /* transparency */ 4740 } 4741 4742 else 4743 { 4744 /* No palette transparency - just set the alpha channel to opaque. */ 4745 int i; 4746 4747 for (i=0, num=*npalette; i<num; ++i) 4748 palette[i].alpha = 255; 4749 4750 for (; i<256; ++i) 4751 palette[i].alpha = 55; /* flag value */ 4752 4753 return 0; /* no transparency */ 4754 } 4755 } 4756 4757 /* Utility to validate the palette if it should not have changed (the 4758 * non-transform case). 4759 */ 4760 static void 4761 standard_palette_validate(standard_display *dp, png_const_structp pp, 4762 png_infop pi) 4763 { 4764 int npalette; 4765 store_palette palette; 4766 4767 if (read_palette(palette, &npalette, pp, pi) != dp->is_transparent) 4768 png_error(pp, "validate: palette transparency changed"); 4769 4770 if (npalette != dp->npalette) 4771 { 4772 size_t pos = 0; 4773 char msg[64]; 4774 4775 pos = safecat(msg, sizeof msg, pos, "validate: palette size changed: "); 4776 pos = safecatn(msg, sizeof msg, pos, dp->npalette); 4777 pos = safecat(msg, sizeof msg, pos, " -> "); 4778 pos = safecatn(msg, sizeof msg, pos, npalette); 4779 png_error(pp, msg); 4780 } 4781 4782 { 4783 int i = npalette; /* npalette is aliased */ 4784 4785 while (--i >= 0) 4786 if (palette[i].red != dp->palette[i].red || 4787 palette[i].green != dp->palette[i].green || 4788 palette[i].blue != dp->palette[i].blue || 4789 palette[i].alpha != dp->palette[i].alpha) 4790 png_error(pp, "validate: PLTE or tRNS chunk changed"); 4791 } 4792 } 4793 4794 /* By passing a 'standard_display' the progressive callbacks can be used 4795 * directly by the sequential code, the functions suffixed "_imp" are the 4796 * implementations, the functions without the suffix are the callbacks. 4797 * 4798 * The code for the info callback is split into two because this callback calls 4799 * png_read_update_info or png_start_read_image and what gets called depends on 4800 * whether the info needs updating (we want to test both calls in pngvalid.) 4801 */ 4802 static void 4803 standard_info_part1(standard_display *dp, png_structp pp, png_infop pi) 4804 { 4805 if (png_get_bit_depth(pp, pi) != dp->bit_depth) 4806 png_error(pp, "validate: bit depth changed"); 4807 4808 if (png_get_color_type(pp, pi) != dp->colour_type) 4809 png_error(pp, "validate: color type changed"); 4810 4811 if (png_get_filter_type(pp, pi) != PNG_FILTER_TYPE_BASE) 4812 png_error(pp, "validate: filter type changed"); 4813 4814 if (png_get_interlace_type(pp, pi) != dp->interlace_type) 4815 png_error(pp, "validate: interlacing changed"); 4816 4817 if (png_get_compression_type(pp, pi) != PNG_COMPRESSION_TYPE_BASE) 4818 png_error(pp, "validate: compression type changed"); 4819 4820 dp->w = png_get_image_width(pp, pi); 4821 4822 if (dp->w != standard_width(pp, dp->id)) 4823 png_error(pp, "validate: image width changed"); 4824 4825 dp->h = png_get_image_height(pp, pi); 4826 4827 if (dp->h != standard_height(pp, dp->id)) 4828 png_error(pp, "validate: image height changed"); 4829 4830 /* Record (but don't check at present) the input sBIT according to the colour 4831 * type information. 4832 */ 4833 { 4834 png_color_8p sBIT = 0; 4835 4836 if (png_get_sBIT(pp, pi, &sBIT) & PNG_INFO_sBIT) 4837 { 4838 int sBIT_invalid = 0; 4839 4840 if (sBIT == 0) 4841 png_error(pp, "validate: unexpected png_get_sBIT result"); 4842 4843 if (dp->colour_type & PNG_COLOR_MASK_COLOR) 4844 { 4845 if (sBIT->red == 0 || sBIT->red > dp->bit_depth) 4846 sBIT_invalid = 1; 4847 else 4848 dp->red_sBIT = sBIT->red; 4849 4850 if (sBIT->green == 0 || sBIT->green > dp->bit_depth) 4851 sBIT_invalid = 1; 4852 else 4853 dp->green_sBIT = sBIT->green; 4854 4855 if (sBIT->blue == 0 || sBIT->blue > dp->bit_depth) 4856 sBIT_invalid = 1; 4857 else 4858 dp->blue_sBIT = sBIT->blue; 4859 } 4860 4861 else /* !COLOR */ 4862 { 4863 if (sBIT->gray == 0 || sBIT->gray > dp->bit_depth) 4864 sBIT_invalid = 1; 4865 else 4866 dp->blue_sBIT = dp->green_sBIT = dp->red_sBIT = sBIT->gray; 4867 } 4868 4869 /* All 8 bits in tRNS for a palette image are significant - see the 4870 * spec. 4871 */ 4872 if (dp->colour_type & PNG_COLOR_MASK_ALPHA) 4873 { 4874 if (sBIT->alpha == 0 || sBIT->alpha > dp->bit_depth) 4875 sBIT_invalid = 1; 4876 else 4877 dp->alpha_sBIT = sBIT->alpha; 4878 } 4879 4880 if (sBIT_invalid) 4881 png_error(pp, "validate: sBIT value out of range"); 4882 } 4883 } 4884 4885 /* Important: this is validating the value *before* any transforms have been 4886 * put in place. It doesn't matter for the standard tests, where there are 4887 * no transforms, but it does for other tests where rowbytes may change after 4888 * png_read_update_info. 4889 */ 4890 if (png_get_rowbytes(pp, pi) != standard_rowsize(pp, dp->id)) 4891 png_error(pp, "validate: row size changed"); 4892 4893 /* Validate the colour type 3 palette (this can be present on other color 4894 * types.) 4895 */ 4896 standard_palette_validate(dp, pp, pi); 4897 4898 /* In any case always check for a tranparent color (notice that the 4899 * colour type 3 case must not give a successful return on the get_tRNS call 4900 * with these arguments!) 4901 */ 4902 { 4903 png_color_16p trans_color = 0; 4904 4905 if (png_get_tRNS(pp, pi, 0, 0, &trans_color) & PNG_INFO_tRNS) 4906 { 4907 if (trans_color == 0) 4908 png_error(pp, "validate: unexpected png_get_tRNS (color) result"); 4909 4910 switch (dp->colour_type) 4911 { 4912 case 0: 4913 dp->transparent.red = dp->transparent.green = dp->transparent.blue = 4914 trans_color->gray; 4915 dp->has_tRNS = 1; 4916 break; 4917 4918 case 2: 4919 dp->transparent.red = trans_color->red; 4920 dp->transparent.green = trans_color->green; 4921 dp->transparent.blue = trans_color->blue; 4922 dp->has_tRNS = 1; 4923 break; 4924 4925 case 3: 4926 /* Not expected because it should result in the array case 4927 * above. 4928 */ 4929 png_error(pp, "validate: unexpected png_get_tRNS result"); 4930 break; 4931 4932 default: 4933 png_error(pp, "validate: invalid tRNS chunk with alpha image"); 4934 } 4935 } 4936 } 4937 4938 /* Read the number of passes - expected to match the value used when 4939 * creating the image (interlaced or not). This has the side effect of 4940 * turning on interlace handling (if do_interlace is not set.) 4941 */ 4942 dp->npasses = npasses_from_interlace_type(pp, dp->interlace_type); 4943 if (!dp->do_interlace) 4944 { 4945 # ifdef PNG_READ_INTERLACING_SUPPORTED 4946 if (dp->npasses != png_set_interlace_handling(pp)) 4947 png_error(pp, "validate: file changed interlace type"); 4948 # else /* !READ_INTERLACING */ 4949 /* This should never happen: the relevant tests (!do_interlace) should 4950 * not be run. 4951 */ 4952 if (dp->npasses > 1) 4953 png_error(pp, "validate: no libpng interlace support"); 4954 # endif /* !READ_INTERLACING */ 4955 } 4956 4957 /* Caller calls png_read_update_info or png_start_read_image now, then calls 4958 * part2. 4959 */ 4960 } 4961 4962 /* This must be called *after* the png_read_update_info call to get the correct 4963 * 'rowbytes' value, otherwise png_get_rowbytes will refer to the untransformed 4964 * image. 4965 */ 4966 static void 4967 standard_info_part2(standard_display *dp, png_const_structp pp, 4968 png_const_infop pi, int nImages) 4969 { 4970 /* Record cbRow now that it can be found. */ 4971 { 4972 png_byte ct = png_get_color_type(pp, pi); 4973 png_byte bd = png_get_bit_depth(pp, pi); 4974 4975 if (bd >= 8 && (ct == PNG_COLOR_TYPE_RGB || ct == PNG_COLOR_TYPE_GRAY) && 4976 dp->filler) 4977 ct |= 4; /* handle filler as faked alpha channel */ 4978 4979 dp->pixel_size = bit_size(pp, ct, bd); 4980 } 4981 dp->bit_width = png_get_image_width(pp, pi) * dp->pixel_size; 4982 dp->cbRow = png_get_rowbytes(pp, pi); 4983 4984 /* Validate the rowbytes here again. */ 4985 if (dp->cbRow != (dp->bit_width+7)/8) 4986 png_error(pp, "bad png_get_rowbytes calculation"); 4987 4988 /* Then ensure there is enough space for the output image(s). */ 4989 store_ensure_image(dp->ps, pp, nImages, dp->cbRow, dp->h); 4990 } 4991 4992 static void 4993 standard_info_imp(standard_display *dp, png_structp pp, png_infop pi, 4994 int nImages) 4995 { 4996 /* Note that the validation routine has the side effect of turning on 4997 * interlace handling in the subsequent code. 4998 */ 4999 standard_info_part1(dp, pp, pi); 5000 5001 /* And the info callback has to call this (or png_read_update_info - see 5002 * below in the png_modifier code for that variant. 5003 */ 5004 if (dp->use_update_info) 5005 { 5006 /* For debugging the effect of multiple calls: */ 5007 int i = dp->use_update_info; 5008 while (i-- > 0) 5009 png_read_update_info(pp, pi); 5010 } 5011 5012 else 5013 png_start_read_image(pp); 5014 5015 /* Validate the height, width and rowbytes plus ensure that sufficient buffer 5016 * exists for decoding the image. 5017 */ 5018 standard_info_part2(dp, pp, pi, nImages); 5019 } 5020 5021 static void PNGCBAPI 5022 standard_info(png_structp pp, png_infop pi) 5023 { 5024 standard_display *dp = voidcast(standard_display*, 5025 png_get_progressive_ptr(pp)); 5026 5027 /* Call with nImages==1 because the progressive reader can only produce one 5028 * image. 5029 */ 5030 standard_info_imp(dp, pp, pi, 1 /*only one image*/); 5031 } 5032 5033 static void PNGCBAPI 5034 progressive_row(png_structp ppIn, png_bytep new_row, png_uint_32 y, int pass) 5035 { 5036 png_const_structp pp = ppIn; 5037 const standard_display *dp = voidcast(standard_display*, 5038 png_get_progressive_ptr(pp)); 5039 5040 /* When handling interlacing some rows will be absent in each pass, the 5041 * callback still gets called, but with a NULL pointer. This is checked 5042 * in the 'else' clause below. We need our own 'cbRow', but we can't call 5043 * png_get_rowbytes because we got no info structure. 5044 */ 5045 if (new_row != NULL) 5046 { 5047 png_bytep row; 5048 5049 /* In the case where the reader doesn't do the interlace it gives 5050 * us the y in the sub-image: 5051 */ 5052 if (dp->do_interlace && dp->interlace_type == PNG_INTERLACE_ADAM7) 5053 { 5054 #ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED 5055 /* Use this opportunity to validate the png 'current' APIs: */ 5056 if (y != png_get_current_row_number(pp)) 5057 png_error(pp, "png_get_current_row_number is broken"); 5058 5059 if (pass != png_get_current_pass_number(pp)) 5060 png_error(pp, "png_get_current_pass_number is broken"); 5061 #endif /* USER_TRANSFORM_INFO */ 5062 5063 y = PNG_ROW_FROM_PASS_ROW(y, pass); 5064 } 5065 5066 /* Validate this just in case. */ 5067 if (y >= dp->h) 5068 png_error(pp, "invalid y to progressive row callback"); 5069 5070 row = store_image_row(dp->ps, pp, 0, y); 5071 5072 /* Combine the new row into the old: */ 5073 #ifdef PNG_READ_INTERLACING_SUPPORTED 5074 if (dp->do_interlace) 5075 #endif /* READ_INTERLACING */ 5076 { 5077 if (dp->interlace_type == PNG_INTERLACE_ADAM7) 5078 deinterlace_row(row, new_row, dp->pixel_size, dp->w, pass, 5079 dp->littleendian); 5080 else 5081 row_copy(row, new_row, dp->pixel_size * dp->w, dp->littleendian); 5082 } 5083 #ifdef PNG_READ_INTERLACING_SUPPORTED 5084 else 5085 png_progressive_combine_row(pp, row, new_row); 5086 #endif /* PNG_READ_INTERLACING_SUPPORTED */ 5087 } 5088 5089 else if (dp->interlace_type == PNG_INTERLACE_ADAM7 && 5090 PNG_ROW_IN_INTERLACE_PASS(y, pass) && 5091 PNG_PASS_COLS(dp->w, pass) > 0) 5092 png_error(pp, "missing row in progressive de-interlacing"); 5093 } 5094 5095 static void 5096 sequential_row(standard_display *dp, png_structp pp, png_infop pi, 5097 const int iImage, const int iDisplay) 5098 { 5099 const int npasses = dp->npasses; 5100 const int do_interlace = dp->do_interlace && 5101 dp->interlace_type == PNG_INTERLACE_ADAM7; 5102 const png_uint_32 height = standard_height(pp, dp->id); 5103 const png_uint_32 width = standard_width(pp, dp->id); 5104 const png_store* ps = dp->ps; 5105 int pass; 5106 5107 for (pass=0; pass<npasses; ++pass) 5108 { 5109 png_uint_32 y; 5110 png_uint_32 wPass = PNG_PASS_COLS(width, pass); 5111 5112 for (y=0; y<height; ++y) 5113 { 5114 if (do_interlace) 5115 { 5116 /* wPass may be zero or this row may not be in this pass. 5117 * png_read_row must not be called in either case. 5118 */ 5119 if (wPass > 0 && PNG_ROW_IN_INTERLACE_PASS(y, pass)) 5120 { 5121 /* Read the row into a pair of temporary buffers, then do the 5122 * merge here into the output rows. 5123 */ 5124 png_byte row[STANDARD_ROWMAX], display[STANDARD_ROWMAX]; 5125 5126 /* The following aids (to some extent) error detection - we can 5127 * see where png_read_row wrote. Use opposite values in row and 5128 * display to make this easier. Don't use 0xff (which is used in 5129 * the image write code to fill unused bits) or 0 (which is a 5130 * likely value to overwrite unused bits with). 5131 */ 5132 memset(row, 0xc5, sizeof row); 5133 memset(display, 0x5c, sizeof display); 5134 5135 png_read_row(pp, row, display); 5136 5137 if (iImage >= 0) 5138 deinterlace_row(store_image_row(ps, pp, iImage, y), row, 5139 dp->pixel_size, dp->w, pass, dp->littleendian); 5140 5141 if (iDisplay >= 0) 5142 deinterlace_row(store_image_row(ps, pp, iDisplay, y), display, 5143 dp->pixel_size, dp->w, pass, dp->littleendian); 5144 } 5145 } 5146 else 5147 png_read_row(pp, 5148 iImage >= 0 ? store_image_row(ps, pp, iImage, y) : NULL, 5149 iDisplay >= 0 ? store_image_row(ps, pp, iDisplay, y) : NULL); 5150 } 5151 } 5152 5153 /* And finish the read operation (only really necessary if the caller wants 5154 * to find additional data in png_info from chunks after the last IDAT.) 5155 */ 5156 png_read_end(pp, pi); 5157 } 5158 5159 #ifdef PNG_TEXT_SUPPORTED 5160 static void 5161 standard_check_text(png_const_structp pp, png_const_textp tp, 5162 png_const_charp keyword, png_const_charp text) 5163 { 5164 char msg[1024]; 5165 size_t pos = safecat(msg, sizeof msg, 0, "text: "); 5166 size_t ok; 5167 5168 pos = safecat(msg, sizeof msg, pos, keyword); 5169 pos = safecat(msg, sizeof msg, pos, ": "); 5170 ok = pos; 5171 5172 if (tp->compression != TEXT_COMPRESSION) 5173 { 5174 char buf[64]; 5175 5176 sprintf(buf, "compression [%d->%d], ", TEXT_COMPRESSION, 5177 tp->compression); 5178 pos = safecat(msg, sizeof msg, pos, buf); 5179 } 5180 5181 if (tp->key == NULL || strcmp(tp->key, keyword) != 0) 5182 { 5183 pos = safecat(msg, sizeof msg, pos, "keyword \""); 5184 if (tp->key != NULL) 5185 { 5186 pos = safecat(msg, sizeof msg, pos, tp->key); 5187 pos = safecat(msg, sizeof msg, pos, "\", "); 5188 } 5189 5190 else 5191 pos = safecat(msg, sizeof msg, pos, "null, "); 5192 } 5193 5194 if (tp->text == NULL) 5195 pos = safecat(msg, sizeof msg, pos, "text lost, "); 5196 5197 else 5198 { 5199 if (tp->text_length != strlen(text)) 5200 { 5201 char buf[64]; 5202 sprintf(buf, "text length changed[%lu->%lu], ", 5203 (unsigned long)strlen(text), (unsigned long)tp->text_length); 5204 pos = safecat(msg, sizeof msg, pos, buf); 5205 } 5206 5207 if (strcmp(tp->text, text) != 0) 5208 { 5209 pos = safecat(msg, sizeof msg, pos, "text becomes \""); 5210 pos = safecat(msg, sizeof msg, pos, tp->text); 5211 pos = safecat(msg, sizeof msg, pos, "\" (was \""); 5212 pos = safecat(msg, sizeof msg, pos, text); 5213 pos = safecat(msg, sizeof msg, pos, "\"), "); 5214 } 5215 } 5216 5217 if (tp->itxt_length != 0) 5218 pos = safecat(msg, sizeof msg, pos, "iTXt length set, "); 5219 5220 if (tp->lang != NULL) 5221 { 5222 pos = safecat(msg, sizeof msg, pos, "iTXt language \""); 5223 pos = safecat(msg, sizeof msg, pos, tp->lang); 5224 pos = safecat(msg, sizeof msg, pos, "\", "); 5225 } 5226 5227 if (tp->lang_key != NULL) 5228 { 5229 pos = safecat(msg, sizeof msg, pos, "iTXt keyword \""); 5230 pos = safecat(msg, sizeof msg, pos, tp->lang_key); 5231 pos = safecat(msg, sizeof msg, pos, "\", "); 5232 } 5233 5234 if (pos > ok) 5235 { 5236 msg[pos-2] = '\0'; /* Remove the ", " at the end */ 5237 png_error(pp, msg); 5238 } 5239 } 5240 5241 static void 5242 standard_text_validate(standard_display *dp, png_const_structp pp, 5243 png_infop pi, int check_end) 5244 { 5245 png_textp tp = NULL; 5246 png_uint_32 num_text = png_get_text(pp, pi, &tp, NULL); 5247 5248 if (num_text == 2 && tp != NULL) 5249 { 5250 standard_check_text(pp, tp, "image name", dp->ps->current->name); 5251 5252 /* This exists because prior to 1.5.18 the progressive reader left the 5253 * png_struct z_stream unreset at the end of the image, so subsequent 5254 * attempts to use it simply returns Z_STREAM_END. 5255 */ 5256 if (check_end) 5257 standard_check_text(pp, tp+1, "end marker", "end"); 5258 } 5259 5260 else 5261 { 5262 char msg[64]; 5263 5264 sprintf(msg, "expected two text items, got %lu", 5265 (unsigned long)num_text); 5266 png_error(pp, msg); 5267 } 5268 } 5269 #else 5270 # define standard_text_validate(dp,pp,pi,check_end) ((void)0) 5271 #endif 5272 5273 static void 5274 standard_row_validate(standard_display *dp, png_const_structp pp, 5275 int iImage, int iDisplay, png_uint_32 y) 5276 { 5277 int where; 5278 png_byte std[STANDARD_ROWMAX]; 5279 5280 /* The row must be pre-initialized to the magic number here for the size 5281 * tests to pass: 5282 */ 5283 memset(std, 178, sizeof std); 5284 standard_row(pp, std, dp->id, y); 5285 5286 /* At the end both the 'row' and 'display' arrays should end up identical. 5287 * In earlier passes 'row' will be partially filled in, with only the pixels 5288 * that have been read so far, but 'display' will have those pixels 5289 * replicated to fill the unread pixels while reading an interlaced image. 5290 */ 5291 if (iImage >= 0 && 5292 (where = pixel_cmp(std, store_image_row(dp->ps, pp, iImage, y), 5293 dp->bit_width)) != 0) 5294 { 5295 char msg[64]; 5296 sprintf(msg, "PNG image row[%lu][%d] changed from %.2x to %.2x", 5297 (unsigned long)y, where-1, std[where-1], 5298 store_image_row(dp->ps, pp, iImage, y)[where-1]); 5299 png_error(pp, msg); 5300 } 5301 5302 if (iDisplay >= 0 && 5303 (where = pixel_cmp(std, store_image_row(dp->ps, pp, iDisplay, y), 5304 dp->bit_width)) != 0) 5305 { 5306 char msg[64]; 5307 sprintf(msg, "display row[%lu][%d] changed from %.2x to %.2x", 5308 (unsigned long)y, where-1, std[where-1], 5309 store_image_row(dp->ps, pp, iDisplay, y)[where-1]); 5310 png_error(pp, msg); 5311 } 5312 } 5313 5314 static void 5315 standard_image_validate(standard_display *dp, png_const_structp pp, int iImage, 5316 int iDisplay) 5317 { 5318 png_uint_32 y; 5319 5320 if (iImage >= 0) 5321 store_image_check(dp->ps, pp, iImage); 5322 5323 if (iDisplay >= 0) 5324 store_image_check(dp->ps, pp, iDisplay); 5325 5326 for (y=0; y<dp->h; ++y) 5327 standard_row_validate(dp, pp, iImage, iDisplay, y); 5328 5329 /* This avoids false positives if the validation code is never called! */ 5330 dp->ps->validated = 1; 5331 } 5332 5333 static void PNGCBAPI 5334 standard_end(png_structp ppIn, png_infop pi) 5335 { 5336 png_const_structp pp = ppIn; 5337 standard_display *dp = voidcast(standard_display*, 5338 png_get_progressive_ptr(pp)); 5339 5340 UNUSED(pi) 5341 5342 /* Validate the image - progressive reading only produces one variant for 5343 * interlaced images. 5344 */ 5345 standard_text_validate(dp, pp, pi, 5346 PNG_LIBPNG_VER >= 10518/*check_end: see comments above*/); 5347 standard_image_validate(dp, pp, 0, -1); 5348 } 5349 5350 /* A single test run checking the standard image to ensure it is not damaged. */ 5351 static void 5352 standard_test(png_store* const psIn, png_uint_32 const id, 5353 int do_interlace, int use_update_info) 5354 { 5355 standard_display d; 5356 context(psIn, fault); 5357 5358 /* Set up the display (stack frame) variables from the arguments to the 5359 * function and initialize the locals that are filled in later. 5360 */ 5361 standard_display_init(&d, psIn, id, do_interlace, use_update_info); 5362 5363 /* Everything is protected by a Try/Catch. The functions called also 5364 * typically have local Try/Catch blocks. 5365 */ 5366 Try 5367 { 5368 png_structp pp; 5369 png_infop pi; 5370 5371 /* Get a png_struct for reading the image. This will throw an error if it 5372 * fails, so we don't need to check the result. 5373 */ 5374 pp = set_store_for_read(d.ps, &pi, d.id, 5375 d.do_interlace ? (d.ps->progressive ? 5376 "pngvalid progressive deinterlacer" : 5377 "pngvalid sequential deinterlacer") : (d.ps->progressive ? 5378 "progressive reader" : "sequential reader")); 5379 5380 /* Initialize the palette correctly from the png_store_file. */ 5381 standard_palette_init(&d); 5382 5383 /* Introduce the correct read function. */ 5384 if (d.ps->progressive) 5385 { 5386 png_set_progressive_read_fn(pp, &d, standard_info, progressive_row, 5387 standard_end); 5388 5389 /* Now feed data into the reader until we reach the end: */ 5390 store_progressive_read(d.ps, pp, pi); 5391 } 5392 else 5393 { 5394 /* Note that this takes the store, not the display. */ 5395 png_set_read_fn(pp, d.ps, store_read); 5396 5397 /* Check the header values: */ 5398 png_read_info(pp, pi); 5399 5400 /* The code tests both versions of the images that the sequential 5401 * reader can produce. 5402 */ 5403 standard_info_imp(&d, pp, pi, 2 /*images*/); 5404 5405 /* Need the total bytes in the image below; we can't get to this point 5406 * unless the PNG file values have been checked against the expected 5407 * values. 5408 */ 5409 { 5410 sequential_row(&d, pp, pi, 0, 1); 5411 5412 /* After the last pass loop over the rows again to check that the 5413 * image is correct. 5414 */ 5415 if (!d.speed) 5416 { 5417 standard_text_validate(&d, pp, pi, 1/*check_end*/); 5418 standard_image_validate(&d, pp, 0, 1); 5419 } 5420 else 5421 d.ps->validated = 1; 5422 } 5423 } 5424 5425 /* Check for validation. */ 5426 if (!d.ps->validated) 5427 png_error(pp, "image read failed silently"); 5428 5429 /* Successful completion. */ 5430 } 5431 5432 Catch(fault) 5433 d.ps = fault; /* make sure this hasn't been clobbered. */ 5434 5435 /* In either case clean up the store. */ 5436 store_read_reset(d.ps); 5437 } 5438 5439 static int 5440 test_standard(png_modifier* const pm, png_byte const colour_type, 5441 int bdlo, int const bdhi) 5442 { 5443 for (; bdlo <= bdhi; ++bdlo) 5444 { 5445 int interlace_type; 5446 5447 for (interlace_type = PNG_INTERLACE_NONE; 5448 interlace_type < INTERLACE_LAST; ++interlace_type) 5449 { 5450 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 5451 interlace_type, 0, 0, 0), do_read_interlace, pm->use_update_info); 5452 5453 if (fail(pm)) 5454 return 0; 5455 } 5456 } 5457 5458 return 1; /* keep going */ 5459 } 5460 5461 static void 5462 perform_standard_test(png_modifier *pm) 5463 { 5464 /* Test each colour type over the valid range of bit depths (expressed as 5465 * log2(bit_depth) in turn, stop as soon as any error is detected. 5466 */ 5467 if (!test_standard(pm, 0, 0, READ_BDHI)) 5468 return; 5469 5470 if (!test_standard(pm, 2, 3, READ_BDHI)) 5471 return; 5472 5473 if (!test_standard(pm, 3, 0, 3)) 5474 return; 5475 5476 if (!test_standard(pm, 4, 3, READ_BDHI)) 5477 return; 5478 5479 if (!test_standard(pm, 6, 3, READ_BDHI)) 5480 return; 5481 } 5482 5483 5484 /********************************** SIZE TESTS ********************************/ 5485 static int 5486 test_size(png_modifier* const pm, png_byte const colour_type, 5487 int bdlo, int const bdhi) 5488 { 5489 /* Run the tests on each combination. 5490 * 5491 * NOTE: on my 32 bit x86 each of the following blocks takes 5492 * a total of 3.5 seconds if done across every combo of bit depth 5493 * width and height. This is a waste of time in practice, hence the 5494 * hinc and winc stuff: 5495 */ 5496 static const png_byte hinc[] = {1, 3, 11, 1, 5}; 5497 static const png_byte winc[] = {1, 9, 5, 7, 1}; 5498 const int save_bdlo = bdlo; 5499 5500 for (; bdlo <= bdhi; ++bdlo) 5501 { 5502 png_uint_32 h, w; 5503 5504 for (h=1; h<=16; h+=hinc[bdlo]) for (w=1; w<=16; w+=winc[bdlo]) 5505 { 5506 /* First test all the 'size' images against the sequential 5507 * reader using libpng to deinterlace (where required.) This 5508 * validates the write side of libpng. There are four possibilities 5509 * to validate. 5510 */ 5511 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 5512 PNG_INTERLACE_NONE, w, h, 0), 0/*do_interlace*/, 5513 pm->use_update_info); 5514 5515 if (fail(pm)) 5516 return 0; 5517 5518 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 5519 PNG_INTERLACE_NONE, w, h, 1), 0/*do_interlace*/, 5520 pm->use_update_info); 5521 5522 if (fail(pm)) 5523 return 0; 5524 5525 /* Now validate the interlaced read side - do_interlace true, 5526 * in the progressive case this does actually make a difference 5527 * to the code used in the non-interlaced case too. 5528 */ 5529 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 5530 PNG_INTERLACE_NONE, w, h, 0), 1/*do_interlace*/, 5531 pm->use_update_info); 5532 5533 if (fail(pm)) 5534 return 0; 5535 5536 # if CAN_WRITE_INTERLACE 5537 /* Validate the pngvalid code itself: */ 5538 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 5539 PNG_INTERLACE_ADAM7, w, h, 1), 1/*do_interlace*/, 5540 pm->use_update_info); 5541 5542 if (fail(pm)) 5543 return 0; 5544 # endif 5545 } 5546 } 5547 5548 /* Now do the tests of libpng interlace handling, after we have made sure 5549 * that the pngvalid version works: 5550 */ 5551 for (bdlo = save_bdlo; bdlo <= bdhi; ++bdlo) 5552 { 5553 png_uint_32 h, w; 5554 5555 for (h=1; h<=16; h+=hinc[bdlo]) for (w=1; w<=16; w+=winc[bdlo]) 5556 { 5557 # ifdef PNG_READ_INTERLACING_SUPPORTED 5558 /* Test with pngvalid generated interlaced images first; we have 5559 * already verify these are ok (unless pngvalid has self-consistent 5560 * read/write errors, which is unlikely), so this detects errors in the 5561 * read side first: 5562 */ 5563 # if CAN_WRITE_INTERLACE 5564 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 5565 PNG_INTERLACE_ADAM7, w, h, 1), 0/*do_interlace*/, 5566 pm->use_update_info); 5567 5568 if (fail(pm)) 5569 return 0; 5570 # endif 5571 # endif /* READ_INTERLACING */ 5572 5573 # ifdef PNG_WRITE_INTERLACING_SUPPORTED 5574 /* Test the libpng write side against the pngvalid read side: */ 5575 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 5576 PNG_INTERLACE_ADAM7, w, h, 0), 1/*do_interlace*/, 5577 pm->use_update_info); 5578 5579 if (fail(pm)) 5580 return 0; 5581 # endif 5582 5583 # ifdef PNG_READ_INTERLACING_SUPPORTED 5584 # ifdef PNG_WRITE_INTERLACING_SUPPORTED 5585 /* Test both together: */ 5586 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 5587 PNG_INTERLACE_ADAM7, w, h, 0), 0/*do_interlace*/, 5588 pm->use_update_info); 5589 5590 if (fail(pm)) 5591 return 0; 5592 # endif 5593 # endif /* READ_INTERLACING */ 5594 } 5595 } 5596 5597 return 1; /* keep going */ 5598 } 5599 5600 static void 5601 perform_size_test(png_modifier *pm) 5602 { 5603 /* Test each colour type over the valid range of bit depths (expressed as 5604 * log2(bit_depth) in turn, stop as soon as any error is detected. 5605 */ 5606 if (!test_size(pm, 0, 0, READ_BDHI)) 5607 return; 5608 5609 if (!test_size(pm, 2, 3, READ_BDHI)) 5610 return; 5611 5612 /* For the moment don't do the palette test - it's a waste of time when 5613 * compared to the grayscale test. 5614 */ 5615 #if 0 5616 if (!test_size(pm, 3, 0, 3)) 5617 return; 5618 #endif 5619 5620 if (!test_size(pm, 4, 3, READ_BDHI)) 5621 return; 5622 5623 if (!test_size(pm, 6, 3, READ_BDHI)) 5624 return; 5625 } 5626 5627 5628 /******************************* TRANSFORM TESTS ******************************/ 5629 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 5630 /* A set of tests to validate libpng image transforms. The possibilities here 5631 * are legion because the transforms can be combined in a combinatorial 5632 * fashion. To deal with this some measure of restraint is required, otherwise 5633 * the tests would take forever. 5634 */ 5635 typedef struct image_pixel 5636 { 5637 /* A local (pngvalid) representation of a PNG pixel, in all its 5638 * various forms. 5639 */ 5640 unsigned int red, green, blue, alpha; /* For non-palette images. */ 5641 unsigned int palette_index; /* For a palette image. */ 5642 png_byte colour_type; /* As in the spec. */ 5643 png_byte bit_depth; /* Defines bit size in row */ 5644 png_byte sample_depth; /* Scale of samples */ 5645 unsigned int have_tRNS :1; /* tRNS chunk may need processing */ 5646 unsigned int swap_rgb :1; /* RGB swapped to BGR */ 5647 unsigned int alpha_first :1; /* Alpha at start, not end */ 5648 unsigned int alpha_inverted :1; /* Alpha channel inverted */ 5649 unsigned int mono_inverted :1; /* Gray channel inverted */ 5650 unsigned int swap16 :1; /* Byte swap 16-bit components */ 5651 unsigned int littleendian :1; /* High bits on right */ 5652 unsigned int sig_bits :1; /* Pixel shifted (sig bits only) */ 5653 5654 /* For checking the code calculates double precision floating point values 5655 * along with an error value, accumulated from the transforms. Because an 5656 * sBIT setting allows larger error bounds (indeed, by the spec, apparently 5657 * up to just less than +/-1 in the scaled value) the *lowest* sBIT for each 5658 * channel is stored. This sBIT value is folded in to the stored error value 5659 * at the end of the application of the transforms to the pixel. 5660 * 5661 * If sig_bits is set above the red, green, blue and alpha values have been 5662 * scaled so they only contain the significant bits of the component values. 5663 */ 5664 double redf, greenf, bluef, alphaf; 5665 double rede, greene, bluee, alphae; 5666 png_byte red_sBIT, green_sBIT, blue_sBIT, alpha_sBIT; 5667 } image_pixel; 5668 5669 /* Shared utility function, see below. */ 5670 static void 5671 image_pixel_setf(image_pixel *this, unsigned int rMax, unsigned int gMax, 5672 unsigned int bMax, unsigned int aMax) 5673 { 5674 this->redf = this->red / (double)rMax; 5675 this->greenf = this->green / (double)gMax; 5676 this->bluef = this->blue / (double)bMax; 5677 this->alphaf = this->alpha / (double)aMax; 5678 5679 if (this->red < rMax) 5680 this->rede = this->redf * DBL_EPSILON; 5681 else 5682 this->rede = 0; 5683 if (this->green < gMax) 5684 this->greene = this->greenf * DBL_EPSILON; 5685 else 5686 this->greene = 0; 5687 if (this->blue < bMax) 5688 this->bluee = this->bluef * DBL_EPSILON; 5689 else 5690 this->bluee = 0; 5691 if (this->alpha < aMax) 5692 this->alphae = this->alphaf * DBL_EPSILON; 5693 else 5694 this->alphae = 0; 5695 } 5696 5697 /* Initialize the structure for the next pixel - call this before doing any 5698 * transforms and call it for each pixel since all the fields may need to be 5699 * reset. 5700 */ 5701 static void 5702 image_pixel_init(image_pixel *this, png_const_bytep row, png_byte colour_type, 5703 png_byte bit_depth, png_uint_32 x, store_palette palette, 5704 const image_pixel *format /*from pngvalid transform of input*/) 5705 { 5706 const png_byte sample_depth = (png_byte)(colour_type == 5707 PNG_COLOR_TYPE_PALETTE ? 8 : bit_depth); 5708 const unsigned int max = (1U<<sample_depth)-1; 5709 const int swap16 = (format != 0 && format->swap16); 5710 const int littleendian = (format != 0 && format->littleendian); 5711 const int sig_bits = (format != 0 && format->sig_bits); 5712 5713 /* Initially just set everything to the same number and the alpha to opaque. 5714 * Note that this currently assumes a simple palette where entry x has colour 5715 * rgb(x,x,x)! 5716 */ 5717 this->palette_index = this->red = this->green = this->blue = 5718 sample(row, colour_type, bit_depth, x, 0, swap16, littleendian); 5719 this->alpha = max; 5720 this->red_sBIT = this->green_sBIT = this->blue_sBIT = this->alpha_sBIT = 5721 sample_depth; 5722 5723 /* Then override as appropriate: */ 5724 if (colour_type == 3) /* palette */ 5725 { 5726 /* This permits the caller to default to the sample value. */ 5727 if (palette != 0) 5728 { 5729 const unsigned int i = this->palette_index; 5730 5731 this->red = palette[i].red; 5732 this->green = palette[i].green; 5733 this->blue = palette[i].blue; 5734 this->alpha = palette[i].alpha; 5735 } 5736 } 5737 5738 else /* not palette */ 5739 { 5740 unsigned int i = 0; 5741 5742 if ((colour_type & 4) != 0 && format != 0 && format->alpha_first) 5743 { 5744 this->alpha = this->red; 5745 /* This handles the gray case for 'AG' pixels */ 5746 this->palette_index = this->red = this->green = this->blue = 5747 sample(row, colour_type, bit_depth, x, 1, swap16, littleendian); 5748 i = 1; 5749 } 5750 5751 if (colour_type & 2) 5752 { 5753 /* Green is second for both BGR and RGB: */ 5754 this->green = sample(row, colour_type, bit_depth, x, ++i, swap16, 5755 littleendian); 5756 5757 if (format != 0 && format->swap_rgb) /* BGR */ 5758 this->red = sample(row, colour_type, bit_depth, x, ++i, swap16, 5759 littleendian); 5760 else 5761 this->blue = sample(row, colour_type, bit_depth, x, ++i, swap16, 5762 littleendian); 5763 } 5764 5765 else /* grayscale */ if (format != 0 && format->mono_inverted) 5766 this->red = this->green = this->blue = this->red ^ max; 5767 5768 if ((colour_type & 4) != 0) /* alpha */ 5769 { 5770 if (format == 0 || !format->alpha_first) 5771 this->alpha = sample(row, colour_type, bit_depth, x, ++i, swap16, 5772 littleendian); 5773 5774 if (format != 0 && format->alpha_inverted) 5775 this->alpha ^= max; 5776 } 5777 } 5778 5779 /* Calculate the scaled values, these are simply the values divided by 5780 * 'max' and the error is initialized to the double precision epsilon value 5781 * from the header file. 5782 */ 5783 image_pixel_setf(this, 5784 sig_bits ? (1U << format->red_sBIT)-1 : max, 5785 sig_bits ? (1U << format->green_sBIT)-1 : max, 5786 sig_bits ? (1U << format->blue_sBIT)-1 : max, 5787 sig_bits ? (1U << format->alpha_sBIT)-1 : max); 5788 5789 /* Store the input information for use in the transforms - these will 5790 * modify the information. 5791 */ 5792 this->colour_type = colour_type; 5793 this->bit_depth = bit_depth; 5794 this->sample_depth = sample_depth; 5795 this->have_tRNS = 0; 5796 this->swap_rgb = 0; 5797 this->alpha_first = 0; 5798 this->alpha_inverted = 0; 5799 this->mono_inverted = 0; 5800 this->swap16 = 0; 5801 this->littleendian = 0; 5802 this->sig_bits = 0; 5803 } 5804 5805 #if defined PNG_READ_EXPAND_SUPPORTED || defined PNG_READ_GRAY_TO_RGB_SUPPORTED\ 5806 || defined PNG_READ_EXPAND_SUPPORTED || defined PNG_READ_EXPAND_16_SUPPORTED\ 5807 || defined PNG_READ_BACKGROUND_SUPPORTED 5808 /* Convert a palette image to an rgb image. This necessarily converts the tRNS 5809 * chunk at the same time, because the tRNS will be in palette form. The way 5810 * palette validation works means that the original palette is never updated, 5811 * instead the image_pixel value from the row contains the RGB of the 5812 * corresponding palette entry and *this* is updated. Consequently this routine 5813 * only needs to change the colour type information. 5814 */ 5815 static void 5816 image_pixel_convert_PLTE(image_pixel *this) 5817 { 5818 if (this->colour_type == PNG_COLOR_TYPE_PALETTE) 5819 { 5820 if (this->have_tRNS) 5821 { 5822 this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; 5823 this->have_tRNS = 0; 5824 } 5825 else 5826 this->colour_type = PNG_COLOR_TYPE_RGB; 5827 5828 /* The bit depth of the row changes at this point too (notice that this is 5829 * the row format, not the sample depth, which is separate.) 5830 */ 5831 this->bit_depth = 8; 5832 } 5833 } 5834 5835 /* Add an alpha channel; this will import the tRNS information because tRNS is 5836 * not valid in an alpha image. The bit depth will invariably be set to at 5837 * least 8 prior to 1.7.0. Palette images will be converted to alpha (using 5838 * the above API). With png_set_background the alpha channel is never expanded 5839 * but this routine is used by pngvalid to simplify code; 'for_background' 5840 * records this. 5841 */ 5842 static void 5843 image_pixel_add_alpha(image_pixel *this, const standard_display *display, 5844 int for_background) 5845 { 5846 if (this->colour_type == PNG_COLOR_TYPE_PALETTE) 5847 image_pixel_convert_PLTE(this); 5848 5849 if ((this->colour_type & PNG_COLOR_MASK_ALPHA) == 0) 5850 { 5851 if (this->colour_type == PNG_COLOR_TYPE_GRAY) 5852 { 5853 # if PNG_LIBPNG_VER < 10700 5854 if (!for_background && this->bit_depth < 8) 5855 this->bit_depth = this->sample_depth = 8; 5856 # endif 5857 5858 if (this->have_tRNS) 5859 { 5860 /* After 1.7 the expansion of bit depth only happens if there is a 5861 * tRNS chunk to expand at this point. 5862 */ 5863 # if PNG_LIBPNG_VER >= 10700 5864 if (!for_background && this->bit_depth < 8) 5865 this->bit_depth = this->sample_depth = 8; 5866 # endif 5867 5868 this->have_tRNS = 0; 5869 5870 /* Check the input, original, channel value here against the 5871 * original tRNS gray chunk valie. 5872 */ 5873 if (this->red == display->transparent.red) 5874 this->alphaf = 0; 5875 else 5876 this->alphaf = 1; 5877 } 5878 else 5879 this->alphaf = 1; 5880 5881 this->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; 5882 } 5883 5884 else if (this->colour_type == PNG_COLOR_TYPE_RGB) 5885 { 5886 if (this->have_tRNS) 5887 { 5888 this->have_tRNS = 0; 5889 5890 /* Again, check the exact input values, not the current transformed 5891 * value! 5892 */ 5893 if (this->red == display->transparent.red && 5894 this->green == display->transparent.green && 5895 this->blue == display->transparent.blue) 5896 this->alphaf = 0; 5897 else 5898 this->alphaf = 1; 5899 } 5900 else 5901 this->alphaf = 1; 5902 5903 this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; 5904 } 5905 5906 /* The error in the alpha is zero and the sBIT value comes from the 5907 * original sBIT data (actually it will always be the original bit depth). 5908 */ 5909 this->alphae = 0; 5910 this->alpha_sBIT = display->alpha_sBIT; 5911 } 5912 } 5913 #endif /* transforms that need image_pixel_add_alpha */ 5914 5915 struct transform_display; 5916 typedef struct image_transform 5917 { 5918 /* The name of this transform: a string. */ 5919 const char *name; 5920 5921 /* Each transform can be disabled from the command line: */ 5922 int enable; 5923 5924 /* The global list of transforms; read only. */ 5925 struct image_transform *const list; 5926 5927 /* The global count of the number of times this transform has been set on an 5928 * image. 5929 */ 5930 unsigned int global_use; 5931 5932 /* The local count of the number of times this transform has been set. */ 5933 unsigned int local_use; 5934 5935 /* The next transform in the list, each transform must call its own next 5936 * transform after it has processed the pixel successfully. 5937 */ 5938 const struct image_transform *next; 5939 5940 /* A single transform for the image, expressed as a series of function 5941 * callbacks and some space for values. 5942 * 5943 * First a callback to add any required modifications to the png_modifier; 5944 * this gets called just before the modifier is set up for read. 5945 */ 5946 void (*ini)(const struct image_transform *this, 5947 struct transform_display *that); 5948 5949 /* And a callback to set the transform on the current png_read_struct: 5950 */ 5951 void (*set)(const struct image_transform *this, 5952 struct transform_display *that, png_structp pp, png_infop pi); 5953 5954 /* Then a transform that takes an input pixel in one PNG format or another 5955 * and modifies it by a pngvalid implementation of the transform (thus 5956 * duplicating the libpng intent without, we hope, duplicating the bugs 5957 * in the libpng implementation!) The png_structp is solely to allow error 5958 * reporting via png_error and png_warning. 5959 */ 5960 void (*mod)(const struct image_transform *this, image_pixel *that, 5961 png_const_structp pp, const struct transform_display *display); 5962 5963 /* Add this transform to the list and return true if the transform is 5964 * meaningful for this colour type and bit depth - if false then the 5965 * transform should have no effect on the image so there's not a lot of 5966 * point running it. 5967 */ 5968 int (*add)(struct image_transform *this, 5969 const struct image_transform **that, png_byte colour_type, 5970 png_byte bit_depth); 5971 } image_transform; 5972 5973 typedef struct transform_display 5974 { 5975 standard_display this; 5976 5977 /* Parameters */ 5978 png_modifier* pm; 5979 const image_transform* transform_list; 5980 unsigned int max_gamma_8; 5981 5982 /* Local variables */ 5983 png_byte output_colour_type; 5984 png_byte output_bit_depth; 5985 png_byte unpacked; 5986 5987 /* Modifications (not necessarily used.) */ 5988 gama_modification gama_mod; 5989 chrm_modification chrm_mod; 5990 srgb_modification srgb_mod; 5991 } transform_display; 5992 5993 /* Set sRGB, cHRM and gAMA transforms as required by the current encoding. */ 5994 static void 5995 transform_set_encoding(transform_display *this) 5996 { 5997 /* Set up the png_modifier '_current' fields then use these to determine how 5998 * to add appropriate chunks. 5999 */ 6000 png_modifier *pm = this->pm; 6001 6002 modifier_set_encoding(pm); 6003 6004 if (modifier_color_encoding_is_set(pm)) 6005 { 6006 if (modifier_color_encoding_is_sRGB(pm)) 6007 srgb_modification_init(&this->srgb_mod, pm, PNG_sRGB_INTENT_ABSOLUTE); 6008 6009 else 6010 { 6011 /* Set gAMA and cHRM separately. */ 6012 gama_modification_init(&this->gama_mod, pm, pm->current_gamma); 6013 6014 if (pm->current_encoding != 0) 6015 chrm_modification_init(&this->chrm_mod, pm, pm->current_encoding); 6016 } 6017 } 6018 } 6019 6020 /* Three functions to end the list: */ 6021 static void 6022 image_transform_ini_end(const image_transform *this, 6023 transform_display *that) 6024 { 6025 UNUSED(this) 6026 UNUSED(that) 6027 } 6028 6029 static void 6030 image_transform_set_end(const image_transform *this, 6031 transform_display *that, png_structp pp, png_infop pi) 6032 { 6033 UNUSED(this) 6034 UNUSED(that) 6035 UNUSED(pp) 6036 UNUSED(pi) 6037 } 6038 6039 /* At the end of the list recalculate the output image pixel value from the 6040 * double precision values set up by the preceding 'mod' calls: 6041 */ 6042 static unsigned int 6043 sample_scale(double sample_value, unsigned int scale) 6044 { 6045 sample_value = floor(sample_value * scale + .5); 6046 6047 /* Return NaN as 0: */ 6048 if (!(sample_value > 0)) 6049 sample_value = 0; 6050 else if (sample_value > scale) 6051 sample_value = scale; 6052 6053 return (unsigned int)sample_value; 6054 } 6055 6056 static void 6057 image_transform_mod_end(const image_transform *this, image_pixel *that, 6058 png_const_structp pp, const transform_display *display) 6059 { 6060 const unsigned int scale = (1U<<that->sample_depth)-1; 6061 const int sig_bits = that->sig_bits; 6062 6063 UNUSED(this) 6064 UNUSED(pp) 6065 UNUSED(display) 6066 6067 /* At the end recalculate the digitized red green and blue values according 6068 * to the current sample_depth of the pixel. 6069 * 6070 * The sample value is simply scaled to the maximum, checking for over 6071 * and underflow (which can both happen for some image transforms, 6072 * including simple size scaling, though libpng doesn't do that at present. 6073 */ 6074 that->red = sample_scale(that->redf, scale); 6075 6076 /* This is a bit bogus; really the above calculation should use the red_sBIT 6077 * value, not sample_depth, but because libpng does png_set_shift by just 6078 * shifting the bits we get errors if we don't do it the same way. 6079 */ 6080 if (sig_bits && that->red_sBIT < that->sample_depth) 6081 that->red >>= that->sample_depth - that->red_sBIT; 6082 6083 /* The error value is increased, at the end, according to the lowest sBIT 6084 * value seen. Common sense tells us that the intermediate integer 6085 * representations are no more accurate than +/- 0.5 in the integral values, 6086 * the sBIT allows the implementation to be worse than this. In addition the 6087 * PNG specification actually permits any error within the range (-1..+1), 6088 * but that is ignored here. Instead the final digitized value is compared, 6089 * below to the digitized value of the error limits - this has the net effect 6090 * of allowing (almost) +/-1 in the output value. It's difficult to see how 6091 * any algorithm that digitizes intermediate results can be more accurate. 6092 */ 6093 that->rede += 1./(2*((1U<<that->red_sBIT)-1)); 6094 6095 if (that->colour_type & PNG_COLOR_MASK_COLOR) 6096 { 6097 that->green = sample_scale(that->greenf, scale); 6098 if (sig_bits && that->green_sBIT < that->sample_depth) 6099 that->green >>= that->sample_depth - that->green_sBIT; 6100 6101 that->blue = sample_scale(that->bluef, scale); 6102 if (sig_bits && that->blue_sBIT < that->sample_depth) 6103 that->blue >>= that->sample_depth - that->blue_sBIT; 6104 6105 that->greene += 1./(2*((1U<<that->green_sBIT)-1)); 6106 that->bluee += 1./(2*((1U<<that->blue_sBIT)-1)); 6107 } 6108 else 6109 { 6110 that->blue = that->green = that->red; 6111 that->bluef = that->greenf = that->redf; 6112 that->bluee = that->greene = that->rede; 6113 } 6114 6115 if ((that->colour_type & PNG_COLOR_MASK_ALPHA) || 6116 that->colour_type == PNG_COLOR_TYPE_PALETTE) 6117 { 6118 that->alpha = sample_scale(that->alphaf, scale); 6119 that->alphae += 1./(2*((1U<<that->alpha_sBIT)-1)); 6120 } 6121 else 6122 { 6123 that->alpha = scale; /* opaque */ 6124 that->alphaf = 1; /* Override this. */ 6125 that->alphae = 0; /* It's exact ;-) */ 6126 } 6127 6128 if (sig_bits && that->alpha_sBIT < that->sample_depth) 6129 that->alpha >>= that->sample_depth - that->alpha_sBIT; 6130 } 6131 6132 /* Static 'end' structure: */ 6133 static image_transform image_transform_end = 6134 { 6135 "(end)", /* name */ 6136 1, /* enable */ 6137 0, /* list */ 6138 0, /* global_use */ 6139 0, /* local_use */ 6140 0, /* next */ 6141 image_transform_ini_end, 6142 image_transform_set_end, 6143 image_transform_mod_end, 6144 0 /* never called, I want it to crash if it is! */ 6145 }; 6146 6147 /* Reader callbacks and implementations, where they differ from the standard 6148 * ones. 6149 */ 6150 static void 6151 transform_display_init(transform_display *dp, png_modifier *pm, png_uint_32 id, 6152 const image_transform *transform_list) 6153 { 6154 memset(dp, 0, sizeof *dp); 6155 6156 /* Standard fields */ 6157 standard_display_init(&dp->this, &pm->this, id, do_read_interlace, 6158 pm->use_update_info); 6159 6160 /* Parameter fields */ 6161 dp->pm = pm; 6162 dp->transform_list = transform_list; 6163 dp->max_gamma_8 = 16; 6164 6165 /* Local variable fields */ 6166 dp->output_colour_type = 255; /* invalid */ 6167 dp->output_bit_depth = 255; /* invalid */ 6168 dp->unpacked = 0; /* not unpacked */ 6169 } 6170 6171 static void 6172 transform_info_imp(transform_display *dp, png_structp pp, png_infop pi) 6173 { 6174 /* Reuse the standard stuff as appropriate. */ 6175 standard_info_part1(&dp->this, pp, pi); 6176 6177 /* Now set the list of transforms. */ 6178 dp->transform_list->set(dp->transform_list, dp, pp, pi); 6179 6180 /* Update the info structure for these transforms: */ 6181 { 6182 int i = dp->this.use_update_info; 6183 /* Always do one call, even if use_update_info is 0. */ 6184 do 6185 png_read_update_info(pp, pi); 6186 while (--i > 0); 6187 } 6188 6189 /* And get the output information into the standard_display */ 6190 standard_info_part2(&dp->this, pp, pi, 1/*images*/); 6191 6192 /* Plus the extra stuff we need for the transform tests: */ 6193 dp->output_colour_type = png_get_color_type(pp, pi); 6194 dp->output_bit_depth = png_get_bit_depth(pp, pi); 6195 6196 /* If png_set_filler is in action then fake the output color type to include 6197 * an alpha channel where appropriate. 6198 */ 6199 if (dp->output_bit_depth >= 8 && 6200 (dp->output_colour_type == PNG_COLOR_TYPE_RGB || 6201 dp->output_colour_type == PNG_COLOR_TYPE_GRAY) && dp->this.filler) 6202 dp->output_colour_type |= 4; 6203 6204 /* Validate the combination of colour type and bit depth that we are getting 6205 * out of libpng; the semantics of something not in the PNG spec are, at 6206 * best, unclear. 6207 */ 6208 switch (dp->output_colour_type) 6209 { 6210 case PNG_COLOR_TYPE_PALETTE: 6211 if (dp->output_bit_depth > 8) goto error; 6212 /*FALL THROUGH*/ 6213 case PNG_COLOR_TYPE_GRAY: 6214 if (dp->output_bit_depth == 1 || dp->output_bit_depth == 2 || 6215 dp->output_bit_depth == 4) 6216 break; 6217 /*FALL THROUGH*/ 6218 default: 6219 if (dp->output_bit_depth == 8 || dp->output_bit_depth == 16) 6220 break; 6221 /*FALL THROUGH*/ 6222 error: 6223 { 6224 char message[128]; 6225 size_t pos; 6226 6227 pos = safecat(message, sizeof message, 0, 6228 "invalid final bit depth: colour type("); 6229 pos = safecatn(message, sizeof message, pos, dp->output_colour_type); 6230 pos = safecat(message, sizeof message, pos, ") with bit depth: "); 6231 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); 6232 6233 png_error(pp, message); 6234 } 6235 } 6236 6237 /* Use a test pixel to check that the output agrees with what we expect - 6238 * this avoids running the whole test if the output is unexpected. This also 6239 * checks for internal errors. 6240 */ 6241 { 6242 image_pixel test_pixel; 6243 6244 memset(&test_pixel, 0, sizeof test_pixel); 6245 test_pixel.colour_type = dp->this.colour_type; /* input */ 6246 test_pixel.bit_depth = dp->this.bit_depth; 6247 if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE) 6248 test_pixel.sample_depth = 8; 6249 else 6250 test_pixel.sample_depth = test_pixel.bit_depth; 6251 /* Don't need sBIT here, but it must be set to non-zero to avoid 6252 * arithmetic overflows. 6253 */ 6254 test_pixel.have_tRNS = dp->this.is_transparent != 0; 6255 test_pixel.red_sBIT = test_pixel.green_sBIT = test_pixel.blue_sBIT = 6256 test_pixel.alpha_sBIT = test_pixel.sample_depth; 6257 6258 dp->transform_list->mod(dp->transform_list, &test_pixel, pp, dp); 6259 6260 if (test_pixel.colour_type != dp->output_colour_type) 6261 { 6262 char message[128]; 6263 size_t pos = safecat(message, sizeof message, 0, "colour type "); 6264 6265 pos = safecatn(message, sizeof message, pos, dp->output_colour_type); 6266 pos = safecat(message, sizeof message, pos, " expected "); 6267 pos = safecatn(message, sizeof message, pos, test_pixel.colour_type); 6268 6269 png_error(pp, message); 6270 } 6271 6272 if (test_pixel.bit_depth != dp->output_bit_depth) 6273 { 6274 char message[128]; 6275 size_t pos = safecat(message, sizeof message, 0, "bit depth "); 6276 6277 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); 6278 pos = safecat(message, sizeof message, pos, " expected "); 6279 pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth); 6280 6281 png_error(pp, message); 6282 } 6283 6284 /* If both bit depth and colour type are correct check the sample depth. 6285 */ 6286 if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE && 6287 test_pixel.sample_depth != 8) /* oops - internal error! */ 6288 png_error(pp, "pngvalid: internal: palette sample depth not 8"); 6289 else if (dp->unpacked && test_pixel.bit_depth != 8) 6290 png_error(pp, "pngvalid: internal: bad unpacked pixel depth"); 6291 else if (!dp->unpacked && test_pixel.colour_type != PNG_COLOR_TYPE_PALETTE 6292 && test_pixel.bit_depth != test_pixel.sample_depth) 6293 { 6294 char message[128]; 6295 size_t pos = safecat(message, sizeof message, 0, 6296 "internal: sample depth "); 6297 6298 /* Because unless something has set 'unpacked' or the image is palette 6299 * mapped we expect the transform to keep sample depth and bit depth 6300 * the same. 6301 */ 6302 pos = safecatn(message, sizeof message, pos, test_pixel.sample_depth); 6303 pos = safecat(message, sizeof message, pos, " expected "); 6304 pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth); 6305 6306 png_error(pp, message); 6307 } 6308 else if (test_pixel.bit_depth != dp->output_bit_depth) 6309 { 6310 /* This could be a libpng error too; libpng has not produced what we 6311 * expect for the output bit depth. 6312 */ 6313 char message[128]; 6314 size_t pos = safecat(message, sizeof message, 0, 6315 "internal: bit depth "); 6316 6317 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); 6318 pos = safecat(message, sizeof message, pos, " expected "); 6319 pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth); 6320 6321 png_error(pp, message); 6322 } 6323 } 6324 } 6325 6326 static void PNGCBAPI 6327 transform_info(png_structp pp, png_infop pi) 6328 { 6329 transform_info_imp(voidcast(transform_display*, png_get_progressive_ptr(pp)), 6330 pp, pi); 6331 } 6332 6333 static void 6334 transform_range_check(png_const_structp pp, unsigned int r, unsigned int g, 6335 unsigned int b, unsigned int a, unsigned int in_digitized, double in, 6336 unsigned int out, png_byte sample_depth, double err, double limit, 6337 const char *name, double digitization_error) 6338 { 6339 /* Compare the scaled, digitzed, values of our local calculation (in+-err) 6340 * with the digitized values libpng produced; 'sample_depth' is the actual 6341 * digitization depth of the libpng output colors (the bit depth except for 6342 * palette images where it is always 8.) The check on 'err' is to detect 6343 * internal errors in pngvalid itself. 6344 */ 6345 unsigned int max = (1U<<sample_depth)-1; 6346 double in_min = ceil((in-err)*max - digitization_error); 6347 double in_max = floor((in+err)*max + digitization_error); 6348 if (debugonly(err > limit ||) !(out >= in_min && out <= in_max)) 6349 { 6350 char message[256]; 6351 size_t pos; 6352 6353 pos = safecat(message, sizeof message, 0, name); 6354 pos = safecat(message, sizeof message, pos, " output value error: rgba("); 6355 pos = safecatn(message, sizeof message, pos, r); 6356 pos = safecat(message, sizeof message, pos, ","); 6357 pos = safecatn(message, sizeof message, pos, g); 6358 pos = safecat(message, sizeof message, pos, ","); 6359 pos = safecatn(message, sizeof message, pos, b); 6360 pos = safecat(message, sizeof message, pos, ","); 6361 pos = safecatn(message, sizeof message, pos, a); 6362 pos = safecat(message, sizeof message, pos, "): "); 6363 pos = safecatn(message, sizeof message, pos, out); 6364 pos = safecat(message, sizeof message, pos, " expected: "); 6365 pos = safecatn(message, sizeof message, pos, in_digitized); 6366 pos = safecat(message, sizeof message, pos, " ("); 6367 pos = safecatd(message, sizeof message, pos, (in-err)*max, 3); 6368 pos = safecat(message, sizeof message, pos, ".."); 6369 pos = safecatd(message, sizeof message, pos, (in+err)*max, 3); 6370 pos = safecat(message, sizeof message, pos, ")"); 6371 6372 png_error(pp, message); 6373 } 6374 6375 UNUSED(limit) 6376 } 6377 6378 static void 6379 transform_image_validate(transform_display *dp, png_const_structp pp, 6380 png_infop pi) 6381 { 6382 /* Constants for the loop below: */ 6383 const png_store* const ps = dp->this.ps; 6384 const png_byte in_ct = dp->this.colour_type; 6385 const png_byte in_bd = dp->this.bit_depth; 6386 const png_uint_32 w = dp->this.w; 6387 const png_uint_32 h = dp->this.h; 6388 const png_byte out_ct = dp->output_colour_type; 6389 const png_byte out_bd = dp->output_bit_depth; 6390 const png_byte sample_depth = (png_byte)(out_ct == 6391 PNG_COLOR_TYPE_PALETTE ? 8 : out_bd); 6392 const png_byte red_sBIT = dp->this.red_sBIT; 6393 const png_byte green_sBIT = dp->this.green_sBIT; 6394 const png_byte blue_sBIT = dp->this.blue_sBIT; 6395 const png_byte alpha_sBIT = dp->this.alpha_sBIT; 6396 const int have_tRNS = dp->this.is_transparent; 6397 double digitization_error; 6398 6399 store_palette out_palette; 6400 png_uint_32 y; 6401 6402 UNUSED(pi) 6403 6404 /* Check for row overwrite errors */ 6405 store_image_check(dp->this.ps, pp, 0); 6406 6407 /* Read the palette corresponding to the output if the output colour type 6408 * indicates a palette, othewise set out_palette to garbage. 6409 */ 6410 if (out_ct == PNG_COLOR_TYPE_PALETTE) 6411 { 6412 /* Validate that the palette count itself has not changed - this is not 6413 * expected. 6414 */ 6415 int npalette = (-1); 6416 6417 (void)read_palette(out_palette, &npalette, pp, pi); 6418 if (npalette != dp->this.npalette) 6419 png_error(pp, "unexpected change in palette size"); 6420 6421 digitization_error = .5; 6422 } 6423 else 6424 { 6425 png_byte in_sample_depth; 6426 6427 memset(out_palette, 0x5e, sizeof out_palette); 6428 6429 /* use-input-precision means assume that if the input has 8 bit (or less) 6430 * samples and the output has 16 bit samples the calculations will be done 6431 * with 8 bit precision, not 16. 6432 */ 6433 if (in_ct == PNG_COLOR_TYPE_PALETTE || in_bd < 16) 6434 in_sample_depth = 8; 6435 else 6436 in_sample_depth = in_bd; 6437 6438 if (sample_depth != 16 || in_sample_depth > 8 || 6439 !dp->pm->calculations_use_input_precision) 6440 digitization_error = .5; 6441 6442 /* Else calculations are at 8 bit precision, and the output actually 6443 * consists of scaled 8-bit values, so scale .5 in 8 bits to the 16 bits: 6444 */ 6445 else 6446 digitization_error = .5 * 257; 6447 } 6448 6449 for (y=0; y<h; ++y) 6450 { 6451 png_const_bytep const pRow = store_image_row(ps, pp, 0, y); 6452 png_uint_32 x; 6453 6454 /* The original, standard, row pre-transforms. */ 6455 png_byte std[STANDARD_ROWMAX]; 6456 6457 transform_row(pp, std, in_ct, in_bd, y); 6458 6459 /* Go through each original pixel transforming it and comparing with what 6460 * libpng did to the same pixel. 6461 */ 6462 for (x=0; x<w; ++x) 6463 { 6464 image_pixel in_pixel, out_pixel; 6465 unsigned int r, g, b, a; 6466 6467 /* Find out what we think the pixel should be: */ 6468 image_pixel_init(&in_pixel, std, in_ct, in_bd, x, dp->this.palette, 6469 NULL); 6470 6471 in_pixel.red_sBIT = red_sBIT; 6472 in_pixel.green_sBIT = green_sBIT; 6473 in_pixel.blue_sBIT = blue_sBIT; 6474 in_pixel.alpha_sBIT = alpha_sBIT; 6475 in_pixel.have_tRNS = have_tRNS != 0; 6476 6477 /* For error detection, below. */ 6478 r = in_pixel.red; 6479 g = in_pixel.green; 6480 b = in_pixel.blue; 6481 a = in_pixel.alpha; 6482 6483 /* This applies the transforms to the input data, including output 6484 * format operations which must be used when reading the output 6485 * pixel that libpng produces. 6486 */ 6487 dp->transform_list->mod(dp->transform_list, &in_pixel, pp, dp); 6488 6489 /* Read the output pixel and compare it to what we got, we don't 6490 * use the error field here, so no need to update sBIT. in_pixel 6491 * says whether we expect libpng to change the output format. 6492 */ 6493 image_pixel_init(&out_pixel, pRow, out_ct, out_bd, x, out_palette, 6494 &in_pixel); 6495 6496 /* We don't expect changes to the index here even if the bit depth is 6497 * changed. 6498 */ 6499 if (in_ct == PNG_COLOR_TYPE_PALETTE && 6500 out_ct == PNG_COLOR_TYPE_PALETTE) 6501 { 6502 if (in_pixel.palette_index != out_pixel.palette_index) 6503 png_error(pp, "unexpected transformed palette index"); 6504 } 6505 6506 /* Check the colours for palette images too - in fact the palette could 6507 * be separately verified itself in most cases. 6508 */ 6509 if (in_pixel.red != out_pixel.red) 6510 transform_range_check(pp, r, g, b, a, in_pixel.red, in_pixel.redf, 6511 out_pixel.red, sample_depth, in_pixel.rede, 6512 dp->pm->limit + 1./(2*((1U<<in_pixel.red_sBIT)-1)), "red/gray", 6513 digitization_error); 6514 6515 if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 && 6516 in_pixel.green != out_pixel.green) 6517 transform_range_check(pp, r, g, b, a, in_pixel.green, 6518 in_pixel.greenf, out_pixel.green, sample_depth, in_pixel.greene, 6519 dp->pm->limit + 1./(2*((1U<<in_pixel.green_sBIT)-1)), "green", 6520 digitization_error); 6521 6522 if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 && 6523 in_pixel.blue != out_pixel.blue) 6524 transform_range_check(pp, r, g, b, a, in_pixel.blue, in_pixel.bluef, 6525 out_pixel.blue, sample_depth, in_pixel.bluee, 6526 dp->pm->limit + 1./(2*((1U<<in_pixel.blue_sBIT)-1)), "blue", 6527 digitization_error); 6528 6529 if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0 && 6530 in_pixel.alpha != out_pixel.alpha) 6531 transform_range_check(pp, r, g, b, a, in_pixel.alpha, 6532 in_pixel.alphaf, out_pixel.alpha, sample_depth, in_pixel.alphae, 6533 dp->pm->limit + 1./(2*((1U<<in_pixel.alpha_sBIT)-1)), "alpha", 6534 digitization_error); 6535 } /* pixel (x) loop */ 6536 } /* row (y) loop */ 6537 6538 /* Record that something was actually checked to avoid a false positive. */ 6539 dp->this.ps->validated = 1; 6540 } 6541 6542 static void PNGCBAPI 6543 transform_end(png_structp ppIn, png_infop pi) 6544 { 6545 png_const_structp pp = ppIn; 6546 transform_display *dp = voidcast(transform_display*, 6547 png_get_progressive_ptr(pp)); 6548 6549 if (!dp->this.speed) 6550 transform_image_validate(dp, pp, pi); 6551 else 6552 dp->this.ps->validated = 1; 6553 } 6554 6555 /* A single test run. */ 6556 static void 6557 transform_test(png_modifier *pmIn, const png_uint_32 idIn, 6558 const image_transform* transform_listIn, const char * const name) 6559 { 6560 transform_display d; 6561 context(&pmIn->this, fault); 6562 6563 transform_display_init(&d, pmIn, idIn, transform_listIn); 6564 6565 Try 6566 { 6567 size_t pos = 0; 6568 png_structp pp; 6569 png_infop pi; 6570 char full_name[256]; 6571 6572 /* Make sure the encoding fields are correct and enter the required 6573 * modifications. 6574 */ 6575 transform_set_encoding(&d); 6576 6577 /* Add any modifications required by the transform list. */ 6578 d.transform_list->ini(d.transform_list, &d); 6579 6580 /* Add the color space information, if any, to the name. */ 6581 pos = safecat(full_name, sizeof full_name, pos, name); 6582 pos = safecat_current_encoding(full_name, sizeof full_name, pos, d.pm); 6583 6584 /* Get a png_struct for reading the image. */ 6585 pp = set_modifier_for_read(d.pm, &pi, d.this.id, full_name); 6586 standard_palette_init(&d.this); 6587 6588 # if 0 6589 /* Logging (debugging only) */ 6590 { 6591 char buffer[256]; 6592 6593 (void)store_message(&d.pm->this, pp, buffer, sizeof buffer, 0, 6594 "running test"); 6595 6596 fprintf(stderr, "%s\n", buffer); 6597 } 6598 # endif 6599 6600 /* Introduce the correct read function. */ 6601 if (d.pm->this.progressive) 6602 { 6603 /* Share the row function with the standard implementation. */ 6604 png_set_progressive_read_fn(pp, &d, transform_info, progressive_row, 6605 transform_end); 6606 6607 /* Now feed data into the reader until we reach the end: */ 6608 modifier_progressive_read(d.pm, pp, pi); 6609 } 6610 else 6611 { 6612 /* modifier_read expects a png_modifier* */ 6613 png_set_read_fn(pp, d.pm, modifier_read); 6614 6615 /* Check the header values: */ 6616 png_read_info(pp, pi); 6617 6618 /* Process the 'info' requirements. Only one image is generated */ 6619 transform_info_imp(&d, pp, pi); 6620 6621 sequential_row(&d.this, pp, pi, -1, 0); 6622 6623 if (!d.this.speed) 6624 transform_image_validate(&d, pp, pi); 6625 else 6626 d.this.ps->validated = 1; 6627 } 6628 6629 modifier_reset(d.pm); 6630 } 6631 6632 Catch(fault) 6633 { 6634 modifier_reset(voidcast(png_modifier*,(void*)fault)); 6635 } 6636 } 6637 6638 /* The transforms: */ 6639 #define ITSTRUCT(name) image_transform_##name 6640 #define ITDATA(name) image_transform_data_##name 6641 #define image_transform_ini image_transform_default_ini 6642 #define IT(name)\ 6643 static image_transform ITSTRUCT(name) =\ 6644 {\ 6645 #name,\ 6646 1, /*enable*/\ 6647 &PT, /*list*/\ 6648 0, /*global_use*/\ 6649 0, /*local_use*/\ 6650 0, /*next*/\ 6651 image_transform_ini,\ 6652 image_transform_png_set_##name##_set,\ 6653 image_transform_png_set_##name##_mod,\ 6654 image_transform_png_set_##name##_add\ 6655 } 6656 #define PT ITSTRUCT(end) /* stores the previous transform */ 6657 6658 /* To save code: */ 6659 extern void image_transform_default_ini(const image_transform *this, 6660 transform_display *that); /* silence GCC warnings */ 6661 6662 void /* private, but almost always needed */ 6663 image_transform_default_ini(const image_transform *this, 6664 transform_display *that) 6665 { 6666 this->next->ini(this->next, that); 6667 } 6668 6669 #ifdef PNG_READ_BACKGROUND_SUPPORTED 6670 static int 6671 image_transform_default_add(image_transform *this, 6672 const image_transform **that, png_byte colour_type, png_byte bit_depth) 6673 { 6674 UNUSED(colour_type) 6675 UNUSED(bit_depth) 6676 6677 this->next = *that; 6678 *that = this; 6679 6680 return 1; 6681 } 6682 #endif 6683 6684 #ifdef PNG_READ_EXPAND_SUPPORTED 6685 /* png_set_palette_to_rgb */ 6686 static void 6687 image_transform_png_set_palette_to_rgb_set(const image_transform *this, 6688 transform_display *that, png_structp pp, png_infop pi) 6689 { 6690 png_set_palette_to_rgb(pp); 6691 this->next->set(this->next, that, pp, pi); 6692 } 6693 6694 static void 6695 image_transform_png_set_palette_to_rgb_mod(const image_transform *this, 6696 image_pixel *that, png_const_structp pp, 6697 const transform_display *display) 6698 { 6699 if (that->colour_type == PNG_COLOR_TYPE_PALETTE) 6700 image_pixel_convert_PLTE(that); 6701 6702 this->next->mod(this->next, that, pp, display); 6703 } 6704 6705 static int 6706 image_transform_png_set_palette_to_rgb_add(image_transform *this, 6707 const image_transform **that, png_byte colour_type, png_byte bit_depth) 6708 { 6709 UNUSED(bit_depth) 6710 6711 this->next = *that; 6712 *that = this; 6713 6714 return colour_type == PNG_COLOR_TYPE_PALETTE; 6715 } 6716 6717 IT(palette_to_rgb); 6718 #undef PT 6719 #define PT ITSTRUCT(palette_to_rgb) 6720 #endif /* PNG_READ_EXPAND_SUPPORTED */ 6721 6722 #ifdef PNG_READ_EXPAND_SUPPORTED 6723 /* png_set_tRNS_to_alpha */ 6724 static void 6725 image_transform_png_set_tRNS_to_alpha_set(const image_transform *this, 6726 transform_display *that, png_structp pp, png_infop pi) 6727 { 6728 png_set_tRNS_to_alpha(pp); 6729 6730 /* If there was a tRNS chunk that would get expanded and add an alpha 6731 * channel is_transparent must be updated: 6732 */ 6733 if (that->this.has_tRNS) 6734 that->this.is_transparent = 1; 6735 6736 this->next->set(this->next, that, pp, pi); 6737 } 6738 6739 static void 6740 image_transform_png_set_tRNS_to_alpha_mod(const image_transform *this, 6741 image_pixel *that, png_const_structp pp, 6742 const transform_display *display) 6743 { 6744 #if PNG_LIBPNG_VER < 10700 6745 /* LIBPNG BUG: this always forces palette images to RGB. */ 6746 if (that->colour_type == PNG_COLOR_TYPE_PALETTE) 6747 image_pixel_convert_PLTE(that); 6748 #endif 6749 6750 /* This effectively does an 'expand' only if there is some transparency to 6751 * convert to an alpha channel. 6752 */ 6753 if (that->have_tRNS) 6754 # if PNG_LIBPNG_VER >= 10700 6755 if (that->colour_type != PNG_COLOR_TYPE_PALETTE && 6756 (that->colour_type & PNG_COLOR_MASK_ALPHA) == 0) 6757 # endif 6758 image_pixel_add_alpha(that, &display->this, 0/*!for background*/); 6759 6760 #if PNG_LIBPNG_VER < 10700 6761 /* LIBPNG BUG: otherwise libpng still expands to 8 bits! */ 6762 else 6763 { 6764 if (that->bit_depth < 8) 6765 that->bit_depth =8; 6766 if (that->sample_depth < 8) 6767 that->sample_depth = 8; 6768 } 6769 #endif 6770 6771 this->next->mod(this->next, that, pp, display); 6772 } 6773 6774 static int 6775 image_transform_png_set_tRNS_to_alpha_add(image_transform *this, 6776 const image_transform **that, png_byte colour_type, png_byte bit_depth) 6777 { 6778 UNUSED(bit_depth) 6779 6780 this->next = *that; 6781 *that = this; 6782 6783 /* We don't know yet whether there will be a tRNS chunk, but we know that 6784 * this transformation should do nothing if there already is an alpha 6785 * channel. In addition, after the bug fix in 1.7.0, there is no longer 6786 * any action on a palette image. 6787 */ 6788 return 6789 # if PNG_LIBPNG_VER >= 10700 6790 colour_type != PNG_COLOR_TYPE_PALETTE && 6791 # endif 6792 (colour_type & PNG_COLOR_MASK_ALPHA) == 0; 6793 } 6794 6795 IT(tRNS_to_alpha); 6796 #undef PT 6797 #define PT ITSTRUCT(tRNS_to_alpha) 6798 #endif /* PNG_READ_EXPAND_SUPPORTED */ 6799 6800 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 6801 /* png_set_gray_to_rgb */ 6802 static void 6803 image_transform_png_set_gray_to_rgb_set(const image_transform *this, 6804 transform_display *that, png_structp pp, png_infop pi) 6805 { 6806 png_set_gray_to_rgb(pp); 6807 /* NOTE: this doesn't result in tRNS expansion. */ 6808 this->next->set(this->next, that, pp, pi); 6809 } 6810 6811 static void 6812 image_transform_png_set_gray_to_rgb_mod(const image_transform *this, 6813 image_pixel *that, png_const_structp pp, 6814 const transform_display *display) 6815 { 6816 /* NOTE: we can actually pend the tRNS processing at this point because we 6817 * can correctly recognize the original pixel value even though we have 6818 * mapped the one gray channel to the three RGB ones, but in fact libpng 6819 * doesn't do this, so we don't either. 6820 */ 6821 if ((that->colour_type & PNG_COLOR_MASK_COLOR) == 0 && that->have_tRNS) 6822 image_pixel_add_alpha(that, &display->this, 0/*!for background*/); 6823 6824 /* Simply expand the bit depth and alter the colour type as required. */ 6825 if (that->colour_type == PNG_COLOR_TYPE_GRAY) 6826 { 6827 /* RGB images have a bit depth at least equal to '8' */ 6828 if (that->bit_depth < 8) 6829 that->sample_depth = that->bit_depth = 8; 6830 6831 /* And just changing the colour type works here because the green and blue 6832 * channels are being maintained in lock-step with the red/gray: 6833 */ 6834 that->colour_type = PNG_COLOR_TYPE_RGB; 6835 } 6836 6837 else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) 6838 that->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; 6839 6840 this->next->mod(this->next, that, pp, display); 6841 } 6842 6843 static int 6844 image_transform_png_set_gray_to_rgb_add(image_transform *this, 6845 const image_transform **that, png_byte colour_type, png_byte bit_depth) 6846 { 6847 UNUSED(bit_depth) 6848 6849 this->next = *that; 6850 *that = this; 6851 6852 return (colour_type & PNG_COLOR_MASK_COLOR) == 0; 6853 } 6854 6855 IT(gray_to_rgb); 6856 #undef PT 6857 #define PT ITSTRUCT(gray_to_rgb) 6858 #endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */ 6859 6860 #ifdef PNG_READ_EXPAND_SUPPORTED 6861 /* png_set_expand */ 6862 static void 6863 image_transform_png_set_expand_set(const image_transform *this, 6864 transform_display *that, png_structp pp, png_infop pi) 6865 { 6866 png_set_expand(pp); 6867 6868 if (that->this.has_tRNS) 6869 that->this.is_transparent = 1; 6870 6871 this->next->set(this->next, that, pp, pi); 6872 } 6873 6874 static void 6875 image_transform_png_set_expand_mod(const image_transform *this, 6876 image_pixel *that, png_const_structp pp, 6877 const transform_display *display) 6878 { 6879 /* The general expand case depends on what the colour type is: */ 6880 if (that->colour_type == PNG_COLOR_TYPE_PALETTE) 6881 image_pixel_convert_PLTE(that); 6882 else if (that->bit_depth < 8) /* grayscale */ 6883 that->sample_depth = that->bit_depth = 8; 6884 6885 if (that->have_tRNS) 6886 image_pixel_add_alpha(that, &display->this, 0/*!for background*/); 6887 6888 this->next->mod(this->next, that, pp, display); 6889 } 6890 6891 static int 6892 image_transform_png_set_expand_add(image_transform *this, 6893 const image_transform **that, png_byte colour_type, png_byte bit_depth) 6894 { 6895 UNUSED(bit_depth) 6896 6897 this->next = *that; 6898 *that = this; 6899 6900 /* 'expand' should do nothing for RGBA or GA input - no tRNS and the bit 6901 * depth is at least 8 already. 6902 */ 6903 return (colour_type & PNG_COLOR_MASK_ALPHA) == 0; 6904 } 6905 6906 IT(expand); 6907 #undef PT 6908 #define PT ITSTRUCT(expand) 6909 #endif /* PNG_READ_EXPAND_SUPPORTED */ 6910 6911 #ifdef PNG_READ_EXPAND_SUPPORTED 6912 /* png_set_expand_gray_1_2_4_to_8 6913 * Pre 1.7.0 LIBPNG BUG: this just does an 'expand' 6914 */ 6915 static void 6916 image_transform_png_set_expand_gray_1_2_4_to_8_set( 6917 const image_transform *this, transform_display *that, png_structp pp, 6918 png_infop pi) 6919 { 6920 png_set_expand_gray_1_2_4_to_8(pp); 6921 /* NOTE: don't expect this to expand tRNS */ 6922 this->next->set(this->next, that, pp, pi); 6923 } 6924 6925 static void 6926 image_transform_png_set_expand_gray_1_2_4_to_8_mod( 6927 const image_transform *this, image_pixel *that, png_const_structp pp, 6928 const transform_display *display) 6929 { 6930 #if PNG_LIBPNG_VER < 10700 6931 image_transform_png_set_expand_mod(this, that, pp, display); 6932 #else 6933 /* Only expand grayscale of bit depth less than 8: */ 6934 if (that->colour_type == PNG_COLOR_TYPE_GRAY && 6935 that->bit_depth < 8) 6936 that->sample_depth = that->bit_depth = 8; 6937 6938 this->next->mod(this->next, that, pp, display); 6939 #endif /* 1.7 or later */ 6940 } 6941 6942 static int 6943 image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform *this, 6944 const image_transform **that, png_byte colour_type, png_byte bit_depth) 6945 { 6946 #if PNG_LIBPNG_VER < 10700 6947 return image_transform_png_set_expand_add(this, that, colour_type, 6948 bit_depth); 6949 #else 6950 UNUSED(bit_depth) 6951 6952 this->next = *that; 6953 *that = this; 6954 6955 /* This should do nothing unless the color type is gray and the bit depth is 6956 * less than 8: 6957 */ 6958 return colour_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8; 6959 #endif /* 1.7 or later */ 6960 } 6961 6962 IT(expand_gray_1_2_4_to_8); 6963 #undef PT 6964 #define PT ITSTRUCT(expand_gray_1_2_4_to_8) 6965 #endif /* PNG_READ_EXPAND_SUPPORTED */ 6966 6967 #ifdef PNG_READ_EXPAND_16_SUPPORTED 6968 /* png_set_expand_16 */ 6969 static void 6970 image_transform_png_set_expand_16_set(const image_transform *this, 6971 transform_display *that, png_structp pp, png_infop pi) 6972 { 6973 png_set_expand_16(pp); 6974 6975 /* NOTE: prior to 1.7 libpng does SET_EXPAND as well, so tRNS is expanded. */ 6976 # if PNG_LIBPNG_VER < 10700 6977 if (that->this.has_tRNS) 6978 that->this.is_transparent = 1; 6979 # endif 6980 6981 this->next->set(this->next, that, pp, pi); 6982 } 6983 6984 static void 6985 image_transform_png_set_expand_16_mod(const image_transform *this, 6986 image_pixel *that, png_const_structp pp, 6987 const transform_display *display) 6988 { 6989 /* Expect expand_16 to expand everything to 16 bits as a result of also 6990 * causing 'expand' to happen. 6991 */ 6992 if (that->colour_type == PNG_COLOR_TYPE_PALETTE) 6993 image_pixel_convert_PLTE(that); 6994 6995 if (that->have_tRNS) 6996 image_pixel_add_alpha(that, &display->this, 0/*!for background*/); 6997 6998 if (that->bit_depth < 16) 6999 that->sample_depth = that->bit_depth = 16; 7000 7001 this->next->mod(this->next, that, pp, display); 7002 } 7003 7004 static int 7005 image_transform_png_set_expand_16_add(image_transform *this, 7006 const image_transform **that, png_byte colour_type, png_byte bit_depth) 7007 { 7008 UNUSED(colour_type) 7009 7010 this->next = *that; 7011 *that = this; 7012 7013 /* expand_16 does something unless the bit depth is already 16. */ 7014 return bit_depth < 16; 7015 } 7016 7017 IT(expand_16); 7018 #undef PT 7019 #define PT ITSTRUCT(expand_16) 7020 #endif /* PNG_READ_EXPAND_16_SUPPORTED */ 7021 7022 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED /* API added in 1.5.4 */ 7023 /* png_set_scale_16 */ 7024 static void 7025 image_transform_png_set_scale_16_set(const image_transform *this, 7026 transform_display *that, png_structp pp, png_infop pi) 7027 { 7028 png_set_scale_16(pp); 7029 # if PNG_LIBPNG_VER < 10700 7030 /* libpng will limit the gamma table size: */ 7031 that->max_gamma_8 = PNG_MAX_GAMMA_8; 7032 # endif 7033 this->next->set(this->next, that, pp, pi); 7034 } 7035 7036 static void 7037 image_transform_png_set_scale_16_mod(const image_transform *this, 7038 image_pixel *that, png_const_structp pp, 7039 const transform_display *display) 7040 { 7041 if (that->bit_depth == 16) 7042 { 7043 that->sample_depth = that->bit_depth = 8; 7044 if (that->red_sBIT > 8) that->red_sBIT = 8; 7045 if (that->green_sBIT > 8) that->green_sBIT = 8; 7046 if (that->blue_sBIT > 8) that->blue_sBIT = 8; 7047 if (that->alpha_sBIT > 8) that->alpha_sBIT = 8; 7048 } 7049 7050 this->next->mod(this->next, that, pp, display); 7051 } 7052 7053 static int 7054 image_transform_png_set_scale_16_add(image_transform *this, 7055 const image_transform **that, png_byte colour_type, png_byte bit_depth) 7056 { 7057 UNUSED(colour_type) 7058 7059 this->next = *that; 7060 *that = this; 7061 7062 return bit_depth > 8; 7063 } 7064 7065 IT(scale_16); 7066 #undef PT 7067 #define PT ITSTRUCT(scale_16) 7068 #endif /* PNG_READ_SCALE_16_TO_8_SUPPORTED (1.5.4 on) */ 7069 7070 #ifdef PNG_READ_16_TO_8_SUPPORTED /* the default before 1.5.4 */ 7071 /* png_set_strip_16 */ 7072 static void 7073 image_transform_png_set_strip_16_set(const image_transform *this, 7074 transform_display *that, png_structp pp, png_infop pi) 7075 { 7076 png_set_strip_16(pp); 7077 # if PNG_LIBPNG_VER < 10700 7078 /* libpng will limit the gamma table size: */ 7079 that->max_gamma_8 = PNG_MAX_GAMMA_8; 7080 # endif 7081 this->next->set(this->next, that, pp, pi); 7082 } 7083 7084 static void 7085 image_transform_png_set_strip_16_mod(const image_transform *this, 7086 image_pixel *that, png_const_structp pp, 7087 const transform_display *display) 7088 { 7089 if (that->bit_depth == 16) 7090 { 7091 that->sample_depth = that->bit_depth = 8; 7092 if (that->red_sBIT > 8) that->red_sBIT = 8; 7093 if (that->green_sBIT > 8) that->green_sBIT = 8; 7094 if (that->blue_sBIT > 8) that->blue_sBIT = 8; 7095 if (that->alpha_sBIT > 8) that->alpha_sBIT = 8; 7096 7097 /* Prior to 1.5.4 png_set_strip_16 would use an 'accurate' method if this 7098 * configuration option is set. From 1.5.4 the flag is never set and the 7099 * 'scale' API (above) must be used. 7100 */ 7101 # ifdef PNG_READ_ACCURATE_SCALE_SUPPORTED 7102 # if PNG_LIBPNG_VER >= 10504 7103 # error PNG_READ_ACCURATE_SCALE should not be set 7104 # endif 7105 7106 /* The strip 16 algorithm drops the low 8 bits rather than calculating 7107 * 1/257, so we need to adjust the permitted errors appropriately: 7108 * Notice that this is only relevant prior to the addition of the 7109 * png_set_scale_16 API in 1.5.4 (but 1.5.4+ always defines the above!) 7110 */ 7111 { 7112 const double d = (255-128.5)/65535; 7113 that->rede += d; 7114 that->greene += d; 7115 that->bluee += d; 7116 that->alphae += d; 7117 } 7118 # endif 7119 } 7120 7121 this->next->mod(this->next, that, pp, display); 7122 } 7123 7124 static int 7125 image_transform_png_set_strip_16_add(image_transform *this, 7126 const image_transform **that, png_byte colour_type, png_byte bit_depth) 7127 { 7128 UNUSED(colour_type) 7129 7130 this->next = *that; 7131 *that = this; 7132 7133 return bit_depth > 8; 7134 } 7135 7136 IT(strip_16); 7137 #undef PT 7138 #define PT ITSTRUCT(strip_16) 7139 #endif /* PNG_READ_16_TO_8_SUPPORTED */ 7140 7141 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 7142 /* png_set_strip_alpha */ 7143 static void 7144 image_transform_png_set_strip_alpha_set(const image_transform *this, 7145 transform_display *that, png_structp pp, png_infop pi) 7146 { 7147 png_set_strip_alpha(pp); 7148 this->next->set(this->next, that, pp, pi); 7149 } 7150 7151 static void 7152 image_transform_png_set_strip_alpha_mod(const image_transform *this, 7153 image_pixel *that, png_const_structp pp, 7154 const transform_display *display) 7155 { 7156 if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) 7157 that->colour_type = PNG_COLOR_TYPE_GRAY; 7158 else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) 7159 that->colour_type = PNG_COLOR_TYPE_RGB; 7160 7161 that->have_tRNS = 0; 7162 that->alphaf = 1; 7163 7164 this->next->mod(this->next, that, pp, display); 7165 } 7166 7167 static int 7168 image_transform_png_set_strip_alpha_add(image_transform *this, 7169 const image_transform **that, png_byte colour_type, png_byte bit_depth) 7170 { 7171 UNUSED(bit_depth) 7172 7173 this->next = *that; 7174 *that = this; 7175 7176 return (colour_type & PNG_COLOR_MASK_ALPHA) != 0; 7177 } 7178 7179 IT(strip_alpha); 7180 #undef PT 7181 #define PT ITSTRUCT(strip_alpha) 7182 #endif /* PNG_READ_STRIP_ALPHA_SUPPORTED */ 7183 7184 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 7185 /* png_set_rgb_to_gray(png_structp, int err_action, double red, double green) 7186 * png_set_rgb_to_gray_fixed(png_structp, int err_action, png_fixed_point red, 7187 * png_fixed_point green) 7188 * png_get_rgb_to_gray_status 7189 * 7190 * The 'default' test here uses values known to be used inside libpng prior to 7191 * 1.7.0: 7192 * 7193 * red: 6968 7194 * green: 23434 7195 * blue: 2366 7196 * 7197 * These values are being retained for compatibility, along with the somewhat 7198 * broken truncation calculation in the fast-and-inaccurate code path. Older 7199 * versions of libpng will fail the accuracy tests below because they use the 7200 * truncation algorithm everywhere. 7201 */ 7202 #define data ITDATA(rgb_to_gray) 7203 static struct 7204 { 7205 double gamma; /* File gamma to use in processing */ 7206 7207 /* The following are the parameters for png_set_rgb_to_gray: */ 7208 # ifdef PNG_FLOATING_POINT_SUPPORTED 7209 double red_to_set; 7210 double green_to_set; 7211 # else 7212 png_fixed_point red_to_set; 7213 png_fixed_point green_to_set; 7214 # endif 7215 7216 /* The actual coefficients: */ 7217 double red_coefficient; 7218 double green_coefficient; 7219 double blue_coefficient; 7220 7221 /* Set if the coeefficients have been overridden. */ 7222 int coefficients_overridden; 7223 } data; 7224 7225 #undef image_transform_ini 7226 #define image_transform_ini image_transform_png_set_rgb_to_gray_ini 7227 static void 7228 image_transform_png_set_rgb_to_gray_ini(const image_transform *this, 7229 transform_display *that) 7230 { 7231 png_modifier *pm = that->pm; 7232 const color_encoding *e = pm->current_encoding; 7233 7234 UNUSED(this) 7235 7236 /* Since we check the encoding this flag must be set: */ 7237 pm->test_uses_encoding = 1; 7238 7239 /* If 'e' is not NULL chromaticity information is present and either a cHRM 7240 * or an sRGB chunk will be inserted. 7241 */ 7242 if (e != 0) 7243 { 7244 /* Coefficients come from the encoding, but may need to be normalized to a 7245 * white point Y of 1.0 7246 */ 7247 const double whiteY = e->red.Y + e->green.Y + e->blue.Y; 7248 7249 data.red_coefficient = e->red.Y; 7250 data.green_coefficient = e->green.Y; 7251 data.blue_coefficient = e->blue.Y; 7252 7253 if (whiteY != 1) 7254 { 7255 data.red_coefficient /= whiteY; 7256 data.green_coefficient /= whiteY; 7257 data.blue_coefficient /= whiteY; 7258 } 7259 } 7260 7261 else 7262 { 7263 /* The default (built in) coeffcients, as above: */ 7264 # if PNG_LIBPNG_VER < 10700 7265 data.red_coefficient = 6968 / 32768.; 7266 data.green_coefficient = 23434 / 32768.; 7267 data.blue_coefficient = 2366 / 32768.; 7268 # else 7269 data.red_coefficient = .2126; 7270 data.green_coefficient = .7152; 7271 data.blue_coefficient = .0722; 7272 # endif 7273 } 7274 7275 data.gamma = pm->current_gamma; 7276 7277 /* If not set then the calculations assume linear encoding (implicitly): */ 7278 if (data.gamma == 0) 7279 data.gamma = 1; 7280 7281 /* The arguments to png_set_rgb_to_gray can override the coefficients implied 7282 * by the color space encoding. If doing exhaustive checks do the override 7283 * in each case, otherwise do it randomly. 7284 */ 7285 if (pm->test_exhaustive) 7286 { 7287 /* First time in coefficients_overridden is 0, the following sets it to 1, 7288 * so repeat if it is set. If a test fails this may mean we subsequently 7289 * skip a non-override test, ignore that. 7290 */ 7291 data.coefficients_overridden = !data.coefficients_overridden; 7292 pm->repeat = data.coefficients_overridden != 0; 7293 } 7294 7295 else 7296 data.coefficients_overridden = random_choice(); 7297 7298 if (data.coefficients_overridden) 7299 { 7300 /* These values override the color encoding defaults, simply use random 7301 * numbers. 7302 */ 7303 png_uint_32 ru; 7304 double total; 7305 7306 R32_1(ru); 7307 data.green_coefficient = total = (ru & 0xffff) / 65535.; 7308 ru >>= 16; 7309 data.red_coefficient = (1 - total) * (ru & 0xffff) / 65535.; 7310 total += data.red_coefficient; 7311 data.blue_coefficient = 1 - total; 7312 7313 # ifdef PNG_FLOATING_POINT_SUPPORTED 7314 data.red_to_set = data.red_coefficient; 7315 data.green_to_set = data.green_coefficient; 7316 # else 7317 data.red_to_set = fix(data.red_coefficient); 7318 data.green_to_set = fix(data.green_coefficient); 7319 # endif 7320 7321 /* The following just changes the error messages: */ 7322 pm->encoding_ignored = 1; 7323 } 7324 7325 else 7326 { 7327 data.red_to_set = -1; 7328 data.green_to_set = -1; 7329 } 7330 7331 /* Adjust the error limit in the png_modifier because of the larger errors 7332 * produced in the digitization during the gamma handling. 7333 */ 7334 if (data.gamma != 1) /* Use gamma tables */ 7335 { 7336 if (that->this.bit_depth == 16 || pm->assume_16_bit_calculations) 7337 { 7338 /* The computations have the form: 7339 * 7340 * r * rc + g * gc + b * bc 7341 * 7342 * Each component of which is +/-1/65535 from the gamma_to_1 table 7343 * lookup, resulting in a base error of +/-6. The gamma_from_1 7344 * conversion adds another +/-2 in the 16-bit case and 7345 * +/-(1<<(15-PNG_MAX_GAMMA_8)) in the 8-bit case. 7346 */ 7347 # if PNG_LIBPNG_VER < 10700 7348 if (that->this.bit_depth < 16) 7349 that->max_gamma_8 = PNG_MAX_GAMMA_8; 7350 # endif 7351 that->pm->limit += pow( 7352 (that->this.bit_depth == 16 || that->max_gamma_8 > 14 ? 7353 8. : 7354 6. + (1<<(15-that->max_gamma_8)) 7355 )/65535, data.gamma); 7356 } 7357 7358 else 7359 { 7360 /* Rounding to 8 bits in the linear space causes massive errors which 7361 * will trigger the error check in transform_range_check. Fix that 7362 * here by taking the gamma encoding into account. 7363 * 7364 * When DIGITIZE is set because a pre-1.7 version of libpng is being 7365 * tested allow a bigger slack. 7366 * 7367 * NOTE: this number only affects the internal limit check in pngvalid, 7368 * it has no effect on the limits applied to the libpng values. 7369 */ 7370 that->pm->limit += pow( 7371 # if DIGITIZE 7372 2.0 7373 # else 7374 1.0 7375 # endif 7376 /255, data.gamma); 7377 } 7378 } 7379 7380 else 7381 { 7382 /* With no gamma correction a large error comes from the truncation of the 7383 * calculation in the 8 bit case, allow for that here. 7384 */ 7385 if (that->this.bit_depth != 16 && !pm->assume_16_bit_calculations) 7386 that->pm->limit += 4E-3; 7387 } 7388 } 7389 7390 static void 7391 image_transform_png_set_rgb_to_gray_set(const image_transform *this, 7392 transform_display *that, png_structp pp, png_infop pi) 7393 { 7394 const int error_action = 1; /* no error, no defines in png.h */ 7395 7396 # ifdef PNG_FLOATING_POINT_SUPPORTED 7397 png_set_rgb_to_gray(pp, error_action, data.red_to_set, data.green_to_set); 7398 # else 7399 png_set_rgb_to_gray_fixed(pp, error_action, data.red_to_set, 7400 data.green_to_set); 7401 # endif 7402 7403 # ifdef PNG_READ_cHRM_SUPPORTED 7404 if (that->pm->current_encoding != 0) 7405 { 7406 /* We have an encoding so a cHRM chunk may have been set; if so then 7407 * check that the libpng APIs give the correct (X,Y,Z) values within 7408 * some margin of error for the round trip through the chromaticity 7409 * form. 7410 */ 7411 # ifdef PNG_FLOATING_POINT_SUPPORTED 7412 # define API_function png_get_cHRM_XYZ 7413 # define API_form "FP" 7414 # define API_type double 7415 # define API_cvt(x) (x) 7416 # else 7417 # define API_function png_get_cHRM_XYZ_fixed 7418 # define API_form "fixed" 7419 # define API_type png_fixed_point 7420 # define API_cvt(x) ((double)(x)/PNG_FP_1) 7421 # endif 7422 7423 API_type rX, gX, bX; 7424 API_type rY, gY, bY; 7425 API_type rZ, gZ, bZ; 7426 7427 if ((API_function(pp, pi, &rX, &rY, &rZ, &gX, &gY, &gZ, &bX, &bY, &bZ) 7428 & PNG_INFO_cHRM) != 0) 7429 { 7430 double maxe; 7431 const char *el; 7432 color_encoding e, o; 7433 7434 /* Expect libpng to return a normalized result, but the original 7435 * color space encoding may not be normalized. 7436 */ 7437 modifier_current_encoding(that->pm, &o); 7438 normalize_color_encoding(&o); 7439 7440 /* Sanity check the pngvalid code - the coefficients should match 7441 * the normalized Y values of the encoding unless they were 7442 * overridden. 7443 */ 7444 if (data.red_to_set == -1 && data.green_to_set == -1 && 7445 (fabs(o.red.Y - data.red_coefficient) > DBL_EPSILON || 7446 fabs(o.green.Y - data.green_coefficient) > DBL_EPSILON || 7447 fabs(o.blue.Y - data.blue_coefficient) > DBL_EPSILON)) 7448 png_error(pp, "internal pngvalid cHRM coefficient error"); 7449 7450 /* Generate a colour space encoding. */ 7451 e.gamma = o.gamma; /* not used */ 7452 e.red.X = API_cvt(rX); 7453 e.red.Y = API_cvt(rY); 7454 e.red.Z = API_cvt(rZ); 7455 e.green.X = API_cvt(gX); 7456 e.green.Y = API_cvt(gY); 7457 e.green.Z = API_cvt(gZ); 7458 e.blue.X = API_cvt(bX); 7459 e.blue.Y = API_cvt(bY); 7460 e.blue.Z = API_cvt(bZ); 7461 7462 /* This should match the original one from the png_modifier, within 7463 * the range permitted by the libpng fixed point representation. 7464 */ 7465 maxe = 0; 7466 el = "-"; /* Set to element name with error */ 7467 7468 # define CHECK(col,x)\ 7469 {\ 7470 double err = fabs(o.col.x - e.col.x);\ 7471 if (err > maxe)\ 7472 {\ 7473 maxe = err;\ 7474 el = #col "(" #x ")";\ 7475 }\ 7476 } 7477 7478 CHECK(red,X) 7479 CHECK(red,Y) 7480 CHECK(red,Z) 7481 CHECK(green,X) 7482 CHECK(green,Y) 7483 CHECK(green,Z) 7484 CHECK(blue,X) 7485 CHECK(blue,Y) 7486 CHECK(blue,Z) 7487 7488 /* Here in both fixed and floating cases to check the values read 7489 * from the cHRm chunk. PNG uses fixed point in the cHRM chunk, so 7490 * we can't expect better than +/-.5E-5 on the result, allow 1E-5. 7491 */ 7492 if (maxe >= 1E-5) 7493 { 7494 size_t pos = 0; 7495 char buffer[256]; 7496 7497 pos = safecat(buffer, sizeof buffer, pos, API_form); 7498 pos = safecat(buffer, sizeof buffer, pos, " cHRM "); 7499 pos = safecat(buffer, sizeof buffer, pos, el); 7500 pos = safecat(buffer, sizeof buffer, pos, " error: "); 7501 pos = safecatd(buffer, sizeof buffer, pos, maxe, 7); 7502 pos = safecat(buffer, sizeof buffer, pos, " "); 7503 /* Print the color space without the gamma value: */ 7504 pos = safecat_color_encoding(buffer, sizeof buffer, pos, &o, 0); 7505 pos = safecat(buffer, sizeof buffer, pos, " -> "); 7506 pos = safecat_color_encoding(buffer, sizeof buffer, pos, &e, 0); 7507 7508 png_error(pp, buffer); 7509 } 7510 } 7511 } 7512 # endif /* READ_cHRM */ 7513 7514 this->next->set(this->next, that, pp, pi); 7515 } 7516 7517 static void 7518 image_transform_png_set_rgb_to_gray_mod(const image_transform *this, 7519 image_pixel *that, png_const_structp pp, 7520 const transform_display *display) 7521 { 7522 if ((that->colour_type & PNG_COLOR_MASK_COLOR) != 0) 7523 { 7524 double gray, err; 7525 7526 # if PNG_LIBPNG_VER < 10700 7527 if (that->colour_type == PNG_COLOR_TYPE_PALETTE) 7528 image_pixel_convert_PLTE(that); 7529 # endif 7530 7531 /* Image now has RGB channels... */ 7532 # if DIGITIZE 7533 { 7534 png_modifier *pm = display->pm; 7535 const unsigned int sample_depth = that->sample_depth; 7536 const unsigned int calc_depth = (pm->assume_16_bit_calculations ? 16 : 7537 sample_depth); 7538 const unsigned int gamma_depth = 7539 (sample_depth == 16 ? 7540 display->max_gamma_8 : 7541 (pm->assume_16_bit_calculations ? 7542 display->max_gamma_8 : 7543 sample_depth)); 7544 int isgray; 7545 double r, g, b; 7546 double rlo, rhi, glo, ghi, blo, bhi, graylo, grayhi; 7547 7548 /* Do this using interval arithmetic, otherwise it is too difficult to 7549 * handle the errors correctly. 7550 * 7551 * To handle the gamma correction work out the upper and lower bounds 7552 * of the digitized value. Assume rounding here - normally the values 7553 * will be identical after this operation if there is only one 7554 * transform, feel free to delete the png_error checks on this below in 7555 * the future (this is just me trying to ensure it works!) 7556 * 7557 * Interval arithmetic is exact, but to implement it it must be 7558 * possible to control the floating point implementation rounding mode. 7559 * This cannot be done in ANSI-C, so instead I reduce the 'lo' values 7560 * by DBL_EPSILON and increase the 'hi' values by the same. 7561 */ 7562 # define DD(v,d,r) (digitize(v*(1-DBL_EPSILON), d, r) * (1-DBL_EPSILON)) 7563 # define DU(v,d,r) (digitize(v*(1+DBL_EPSILON), d, r) * (1+DBL_EPSILON)) 7564 7565 r = rlo = rhi = that->redf; 7566 rlo -= that->rede; 7567 rlo = DD(rlo, calc_depth, 1/*round*/); 7568 rhi += that->rede; 7569 rhi = DU(rhi, calc_depth, 1/*round*/); 7570 7571 g = glo = ghi = that->greenf; 7572 glo -= that->greene; 7573 glo = DD(glo, calc_depth, 1/*round*/); 7574 ghi += that->greene; 7575 ghi = DU(ghi, calc_depth, 1/*round*/); 7576 7577 b = blo = bhi = that->bluef; 7578 blo -= that->bluee; 7579 blo = DD(blo, calc_depth, 1/*round*/); 7580 bhi += that->bluee; 7581 bhi = DU(bhi, calc_depth, 1/*round*/); 7582 7583 isgray = r==g && g==b; 7584 7585 if (data.gamma != 1) 7586 { 7587 const double power = 1/data.gamma; 7588 const double abse = .5/(sample_depth == 16 ? 65535 : 255); 7589 7590 /* If a gamma calculation is done it is done using lookup tables of 7591 * precision gamma_depth, so the already digitized value above may 7592 * need to be further digitized here. 7593 */ 7594 if (gamma_depth != calc_depth) 7595 { 7596 rlo = DD(rlo, gamma_depth, 0/*truncate*/); 7597 rhi = DU(rhi, gamma_depth, 0/*truncate*/); 7598 glo = DD(glo, gamma_depth, 0/*truncate*/); 7599 ghi = DU(ghi, gamma_depth, 0/*truncate*/); 7600 blo = DD(blo, gamma_depth, 0/*truncate*/); 7601 bhi = DU(bhi, gamma_depth, 0/*truncate*/); 7602 } 7603 7604 /* 'abse' is the error in the gamma table calculation itself. */ 7605 r = pow(r, power); 7606 rlo = DD(pow(rlo, power)-abse, calc_depth, 1); 7607 rhi = DU(pow(rhi, power)+abse, calc_depth, 1); 7608 7609 g = pow(g, power); 7610 glo = DD(pow(glo, power)-abse, calc_depth, 1); 7611 ghi = DU(pow(ghi, power)+abse, calc_depth, 1); 7612 7613 b = pow(b, power); 7614 blo = DD(pow(blo, power)-abse, calc_depth, 1); 7615 bhi = DU(pow(bhi, power)+abse, calc_depth, 1); 7616 } 7617 7618 /* Now calculate the actual gray values. Although the error in the 7619 * coefficients depends on whether they were specified on the command 7620 * line (in which case truncation to 15 bits happened) or not (rounding 7621 * was used) the maxium error in an individual coefficient is always 7622 * 2/32768, because even in the rounding case the requirement that 7623 * coefficients add up to 32768 can cause a larger rounding error. 7624 * 7625 * The only time when rounding doesn't occur in 1.5.5 and later is when 7626 * the non-gamma code path is used for less than 16 bit data. 7627 */ 7628 gray = r * data.red_coefficient + g * data.green_coefficient + 7629 b * data.blue_coefficient; 7630 7631 { 7632 const int do_round = data.gamma != 1 || calc_depth == 16; 7633 const double ce = 2. / 32768; 7634 7635 graylo = DD(rlo * (data.red_coefficient-ce) + 7636 glo * (data.green_coefficient-ce) + 7637 blo * (data.blue_coefficient-ce), calc_depth, do_round); 7638 if (graylo > gray) /* always accept the right answer */ 7639 graylo = gray; 7640 7641 grayhi = DU(rhi * (data.red_coefficient+ce) + 7642 ghi * (data.green_coefficient+ce) + 7643 bhi * (data.blue_coefficient+ce), calc_depth, do_round); 7644 if (grayhi < gray) 7645 grayhi = gray; 7646 } 7647 7648 /* And invert the gamma. */ 7649 if (data.gamma != 1) 7650 { 7651 const double power = data.gamma; 7652 7653 /* And this happens yet again, shifting the values once more. */ 7654 if (gamma_depth != sample_depth) 7655 { 7656 rlo = DD(rlo, gamma_depth, 0/*truncate*/); 7657 rhi = DU(rhi, gamma_depth, 0/*truncate*/); 7658 glo = DD(glo, gamma_depth, 0/*truncate*/); 7659 ghi = DU(ghi, gamma_depth, 0/*truncate*/); 7660 blo = DD(blo, gamma_depth, 0/*truncate*/); 7661 bhi = DU(bhi, gamma_depth, 0/*truncate*/); 7662 } 7663 7664 gray = pow(gray, power); 7665 graylo = DD(pow(graylo, power), sample_depth, 1); 7666 grayhi = DU(pow(grayhi, power), sample_depth, 1); 7667 } 7668 7669 # undef DD 7670 # undef DU 7671 7672 /* Now the error can be calculated. 7673 * 7674 * If r==g==b because there is no overall gamma correction libpng 7675 * currently preserves the original value. 7676 */ 7677 if (isgray) 7678 err = (that->rede + that->greene + that->bluee)/3; 7679 7680 else 7681 { 7682 err = fabs(grayhi-gray); 7683 7684 if (fabs(gray - graylo) > err) 7685 err = fabs(graylo-gray); 7686 7687 #if !RELEASE_BUILD 7688 /* Check that this worked: */ 7689 if (err > pm->limit) 7690 { 7691 size_t pos = 0; 7692 char buffer[128]; 7693 7694 pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error "); 7695 pos = safecatd(buffer, sizeof buffer, pos, err, 6); 7696 pos = safecat(buffer, sizeof buffer, pos, " exceeds limit "); 7697 pos = safecatd(buffer, sizeof buffer, pos, pm->limit, 6); 7698 png_warning(pp, buffer); 7699 pm->limit = err; 7700 } 7701 #endif /* !RELEASE_BUILD */ 7702 } 7703 } 7704 # else /* !DIGITIZE */ 7705 { 7706 double r = that->redf; 7707 double re = that->rede; 7708 double g = that->greenf; 7709 double ge = that->greene; 7710 double b = that->bluef; 7711 double be = that->bluee; 7712 7713 # if PNG_LIBPNG_VER < 10700 7714 /* The true gray case involves no math in earlier versions (not 7715 * true, there was some if gamma correction was happening too.) 7716 */ 7717 if (r == g && r == b) 7718 { 7719 gray = r; 7720 err = re; 7721 if (err < ge) err = ge; 7722 if (err < be) err = be; 7723 } 7724 7725 else 7726 # endif /* before 1.7 */ 7727 if (data.gamma == 1) 7728 { 7729 /* There is no need to do the conversions to and from linear space, 7730 * so the calculation should be a lot more accurate. There is a 7731 * built in error in the coefficients because they only have 15 bits 7732 * and are adjusted to make sure they add up to 32768. This 7733 * involves a integer calculation with truncation of the form: 7734 * 7735 * ((int)(coefficient * 100000) * 32768)/100000 7736 * 7737 * This is done to the red and green coefficients (the ones 7738 * provided to the API) then blue is calculated from them so the 7739 * result adds up to 32768. In the worst case this can result in 7740 * a -1 error in red and green and a +2 error in blue. Consequently 7741 * the worst case in the calculation below is 2/32768 error. 7742 * 7743 * TODO: consider fixing this in libpng by rounding the calculation 7744 * limiting the error to 1/32768. 7745 * 7746 * Handling this by adding 2/32768 here avoids needing to increase 7747 * the global error limits to take this into account.) 7748 */ 7749 gray = r * data.red_coefficient + g * data.green_coefficient + 7750 b * data.blue_coefficient; 7751 err = re * data.red_coefficient + ge * data.green_coefficient + 7752 be * data.blue_coefficient + 2./32768 + gray * 5 * DBL_EPSILON; 7753 } 7754 7755 else 7756 { 7757 /* The calculation happens in linear space, and this produces much 7758 * wider errors in the encoded space. These are handled here by 7759 * factoring the errors in to the calculation. There are two table 7760 * lookups in the calculation and each introduces a quantization 7761 * error defined by the table size. 7762 */ 7763 png_modifier *pm = display->pm; 7764 double in_qe = (that->sample_depth > 8 ? .5/65535 : .5/255); 7765 double out_qe = (that->sample_depth > 8 ? .5/65535 : 7766 (pm->assume_16_bit_calculations ? .5/(1<<display->max_gamma_8) : 7767 .5/255)); 7768 double rhi, ghi, bhi, grayhi; 7769 double g1 = 1/data.gamma; 7770 7771 rhi = r + re + in_qe; if (rhi > 1) rhi = 1; 7772 r -= re + in_qe; if (r < 0) r = 0; 7773 ghi = g + ge + in_qe; if (ghi > 1) ghi = 1; 7774 g -= ge + in_qe; if (g < 0) g = 0; 7775 bhi = b + be + in_qe; if (bhi > 1) bhi = 1; 7776 b -= be + in_qe; if (b < 0) b = 0; 7777 7778 r = pow(r, g1)*(1-DBL_EPSILON); rhi = pow(rhi, g1)*(1+DBL_EPSILON); 7779 g = pow(g, g1)*(1-DBL_EPSILON); ghi = pow(ghi, g1)*(1+DBL_EPSILON); 7780 b = pow(b, g1)*(1-DBL_EPSILON); bhi = pow(bhi, g1)*(1+DBL_EPSILON); 7781 7782 /* Work out the lower and upper bounds for the gray value in the 7783 * encoded space, then work out an average and error. Remove the 7784 * previously added input quantization error at this point. 7785 */ 7786 gray = r * data.red_coefficient + g * data.green_coefficient + 7787 b * data.blue_coefficient - 2./32768 - out_qe; 7788 if (gray <= 0) 7789 gray = 0; 7790 else 7791 { 7792 gray *= (1 - 6 * DBL_EPSILON); 7793 gray = pow(gray, data.gamma) * (1-DBL_EPSILON); 7794 } 7795 7796 grayhi = rhi * data.red_coefficient + ghi * data.green_coefficient + 7797 bhi * data.blue_coefficient + 2./32768 + out_qe; 7798 grayhi *= (1 + 6 * DBL_EPSILON); 7799 if (grayhi >= 1) 7800 grayhi = 1; 7801 else 7802 grayhi = pow(grayhi, data.gamma) * (1+DBL_EPSILON); 7803 7804 err = (grayhi - gray) / 2; 7805 gray = (grayhi + gray) / 2; 7806 7807 if (err <= in_qe) 7808 err = gray * DBL_EPSILON; 7809 7810 else 7811 err -= in_qe; 7812 7813 #if !RELEASE_BUILD 7814 /* Validate that the error is within limits (this has caused 7815 * problems before, it's much easier to detect them here.) 7816 */ 7817 if (err > pm->limit) 7818 { 7819 size_t pos = 0; 7820 char buffer[128]; 7821 7822 pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error "); 7823 pos = safecatd(buffer, sizeof buffer, pos, err, 6); 7824 pos = safecat(buffer, sizeof buffer, pos, " exceeds limit "); 7825 pos = safecatd(buffer, sizeof buffer, pos, pm->limit, 6); 7826 png_warning(pp, buffer); 7827 pm->limit = err; 7828 } 7829 #endif /* !RELEASE_BUILD */ 7830 } 7831 } 7832 # endif /* !DIGITIZE */ 7833 7834 that->bluef = that->greenf = that->redf = gray; 7835 that->bluee = that->greene = that->rede = err; 7836 7837 /* The sBIT is the minium of the three colour channel sBITs. */ 7838 if (that->red_sBIT > that->green_sBIT) 7839 that->red_sBIT = that->green_sBIT; 7840 if (that->red_sBIT > that->blue_sBIT) 7841 that->red_sBIT = that->blue_sBIT; 7842 that->blue_sBIT = that->green_sBIT = that->red_sBIT; 7843 7844 /* And remove the colour bit in the type: */ 7845 if (that->colour_type == PNG_COLOR_TYPE_RGB) 7846 that->colour_type = PNG_COLOR_TYPE_GRAY; 7847 else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) 7848 that->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; 7849 } 7850 7851 this->next->mod(this->next, that, pp, display); 7852 } 7853 7854 static int 7855 image_transform_png_set_rgb_to_gray_add(image_transform *this, 7856 const image_transform **that, png_byte colour_type, png_byte bit_depth) 7857 { 7858 UNUSED(bit_depth) 7859 7860 this->next = *that; 7861 *that = this; 7862 7863 return (colour_type & PNG_COLOR_MASK_COLOR) != 0; 7864 } 7865 7866 #undef data 7867 IT(rgb_to_gray); 7868 #undef PT 7869 #define PT ITSTRUCT(rgb_to_gray) 7870 #undef image_transform_ini 7871 #define image_transform_ini image_transform_default_ini 7872 #endif /* PNG_READ_RGB_TO_GRAY_SUPPORTED */ 7873 7874 #ifdef PNG_READ_BACKGROUND_SUPPORTED 7875 /* png_set_background(png_structp, png_const_color_16p background_color, 7876 * int background_gamma_code, int need_expand, double background_gamma) 7877 * png_set_background_fixed(png_structp, png_const_color_16p background_color, 7878 * int background_gamma_code, int need_expand, 7879 * png_fixed_point background_gamma) 7880 * 7881 * This ignores the gamma (at present.) 7882 */ 7883 #define data ITDATA(background) 7884 static image_pixel data; 7885 7886 static void 7887 image_transform_png_set_background_set(const image_transform *this, 7888 transform_display *that, png_structp pp, png_infop pi) 7889 { 7890 png_byte colour_type, bit_depth; 7891 png_byte random_bytes[8]; /* 8 bytes - 64 bits - the biggest pixel */ 7892 int expand; 7893 png_color_16 back; 7894 7895 /* We need a background colour, because we don't know exactly what transforms 7896 * have been set we have to supply the colour in the original file format and 7897 * so we need to know what that is! The background colour is stored in the 7898 * transform_display. 7899 */ 7900 R8(random_bytes); 7901 7902 /* Read the random value, for colour type 3 the background colour is actually 7903 * expressed as a 24bit rgb, not an index. 7904 */ 7905 colour_type = that->this.colour_type; 7906 if (colour_type == 3) 7907 { 7908 colour_type = PNG_COLOR_TYPE_RGB; 7909 bit_depth = 8; 7910 expand = 0; /* passing in an RGB not a pixel index */ 7911 } 7912 7913 else 7914 { 7915 if (that->this.has_tRNS) 7916 that->this.is_transparent = 1; 7917 7918 bit_depth = that->this.bit_depth; 7919 expand = 1; 7920 } 7921 7922 image_pixel_init(&data, random_bytes, colour_type, 7923 bit_depth, 0/*x*/, 0/*unused: palette*/, NULL/*format*/); 7924 7925 /* Extract the background colour from this image_pixel, but make sure the 7926 * unused fields of 'back' are garbage. 7927 */ 7928 R8(back); 7929 7930 if (colour_type & PNG_COLOR_MASK_COLOR) 7931 { 7932 back.red = (png_uint_16)data.red; 7933 back.green = (png_uint_16)data.green; 7934 back.blue = (png_uint_16)data.blue; 7935 } 7936 7937 else 7938 back.gray = (png_uint_16)data.red; 7939 7940 # ifdef PNG_FLOATING_POINT_SUPPORTED 7941 png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, expand, 0); 7942 # else 7943 png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE, expand, 0); 7944 # endif 7945 7946 this->next->set(this->next, that, pp, pi); 7947 } 7948 7949 static void 7950 image_transform_png_set_background_mod(const image_transform *this, 7951 image_pixel *that, png_const_structp pp, 7952 const transform_display *display) 7953 { 7954 /* Check for tRNS first: */ 7955 if (that->have_tRNS && that->colour_type != PNG_COLOR_TYPE_PALETTE) 7956 image_pixel_add_alpha(that, &display->this, 1/*for background*/); 7957 7958 /* This is only necessary if the alpha value is less than 1. */ 7959 if (that->alphaf < 1) 7960 { 7961 /* Now we do the background calculation without any gamma correction. */ 7962 if (that->alphaf <= 0) 7963 { 7964 that->redf = data.redf; 7965 that->greenf = data.greenf; 7966 that->bluef = data.bluef; 7967 7968 that->rede = data.rede; 7969 that->greene = data.greene; 7970 that->bluee = data.bluee; 7971 7972 that->red_sBIT= data.red_sBIT; 7973 that->green_sBIT= data.green_sBIT; 7974 that->blue_sBIT= data.blue_sBIT; 7975 } 7976 7977 else /* 0 < alpha < 1 */ 7978 { 7979 double alf = 1 - that->alphaf; 7980 7981 that->redf = that->redf * that->alphaf + data.redf * alf; 7982 that->rede = that->rede * that->alphaf + data.rede * alf + 7983 DBL_EPSILON; 7984 that->greenf = that->greenf * that->alphaf + data.greenf * alf; 7985 that->greene = that->greene * that->alphaf + data.greene * alf + 7986 DBL_EPSILON; 7987 that->bluef = that->bluef * that->alphaf + data.bluef * alf; 7988 that->bluee = that->bluee * that->alphaf + data.bluee * alf + 7989 DBL_EPSILON; 7990 } 7991 7992 /* Remove the alpha type and set the alpha (not in that order.) */ 7993 that->alphaf = 1; 7994 that->alphae = 0; 7995 } 7996 7997 if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) 7998 that->colour_type = PNG_COLOR_TYPE_RGB; 7999 else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) 8000 that->colour_type = PNG_COLOR_TYPE_GRAY; 8001 /* PNG_COLOR_TYPE_PALETTE is not changed */ 8002 8003 this->next->mod(this->next, that, pp, display); 8004 } 8005 8006 #define image_transform_png_set_background_add image_transform_default_add 8007 8008 #undef data 8009 IT(background); 8010 #undef PT 8011 #define PT ITSTRUCT(background) 8012 #endif /* PNG_READ_BACKGROUND_SUPPORTED */ 8013 8014 /* png_set_quantize(png_structp, png_colorp palette, int num_palette, 8015 * int maximum_colors, png_const_uint_16p histogram, int full_quantize) 8016 * 8017 * Very difficult to validate this! 8018 */ 8019 /*NOTE: TBD NYI */ 8020 8021 /* The data layout transforms are handled by swapping our own channel data, 8022 * necessarily these need to happen at the end of the transform list because the 8023 * semantic of the channels changes after these are executed. Some of these, 8024 * like set_shift and set_packing, can't be done at present because they change 8025 * the layout of the data at the sub-sample level so sample() won't get the 8026 * right answer. 8027 */ 8028 /* png_set_invert_alpha */ 8029 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 8030 /* Invert the alpha channel 8031 * 8032 * png_set_invert_alpha(png_structrp png_ptr) 8033 */ 8034 static void 8035 image_transform_png_set_invert_alpha_set(const image_transform *this, 8036 transform_display *that, png_structp pp, png_infop pi) 8037 { 8038 png_set_invert_alpha(pp); 8039 this->next->set(this->next, that, pp, pi); 8040 } 8041 8042 static void 8043 image_transform_png_set_invert_alpha_mod(const image_transform *this, 8044 image_pixel *that, png_const_structp pp, 8045 const transform_display *display) 8046 { 8047 if (that->colour_type & 4) 8048 that->alpha_inverted = 1; 8049 8050 this->next->mod(this->next, that, pp, display); 8051 } 8052 8053 static int 8054 image_transform_png_set_invert_alpha_add(image_transform *this, 8055 const image_transform **that, png_byte colour_type, png_byte bit_depth) 8056 { 8057 UNUSED(bit_depth) 8058 8059 this->next = *that; 8060 *that = this; 8061 8062 /* Only has an effect on pixels with alpha: */ 8063 return (colour_type & 4) != 0; 8064 } 8065 8066 IT(invert_alpha); 8067 #undef PT 8068 #define PT ITSTRUCT(invert_alpha) 8069 8070 #endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */ 8071 8072 /* png_set_bgr */ 8073 #ifdef PNG_READ_BGR_SUPPORTED 8074 /* Swap R,G,B channels to order B,G,R. 8075 * 8076 * png_set_bgr(png_structrp png_ptr) 8077 * 8078 * This only has an effect on RGB and RGBA pixels. 8079 */ 8080 static void 8081 image_transform_png_set_bgr_set(const image_transform *this, 8082 transform_display *that, png_structp pp, png_infop pi) 8083 { 8084 png_set_bgr(pp); 8085 this->next->set(this->next, that, pp, pi); 8086 } 8087 8088 static void 8089 image_transform_png_set_bgr_mod(const image_transform *this, 8090 image_pixel *that, png_const_structp pp, 8091 const transform_display *display) 8092 { 8093 if (that->colour_type == PNG_COLOR_TYPE_RGB || 8094 that->colour_type == PNG_COLOR_TYPE_RGBA) 8095 that->swap_rgb = 1; 8096 8097 this->next->mod(this->next, that, pp, display); 8098 } 8099 8100 static int 8101 image_transform_png_set_bgr_add(image_transform *this, 8102 const image_transform **that, png_byte colour_type, png_byte bit_depth) 8103 { 8104 UNUSED(bit_depth) 8105 8106 this->next = *that; 8107 *that = this; 8108 8109 return colour_type == PNG_COLOR_TYPE_RGB || 8110 colour_type == PNG_COLOR_TYPE_RGBA; 8111 } 8112 8113 IT(bgr); 8114 #undef PT 8115 #define PT ITSTRUCT(bgr) 8116 8117 #endif /* PNG_READ_BGR_SUPPORTED */ 8118 8119 /* png_set_swap_alpha */ 8120 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 8121 /* Put the alpha channel first. 8122 * 8123 * png_set_swap_alpha(png_structrp png_ptr) 8124 * 8125 * This only has an effect on GA and RGBA pixels. 8126 */ 8127 static void 8128 image_transform_png_set_swap_alpha_set(const image_transform *this, 8129 transform_display *that, png_structp pp, png_infop pi) 8130 { 8131 png_set_swap_alpha(pp); 8132 this->next->set(this->next, that, pp, pi); 8133 } 8134 8135 static void 8136 image_transform_png_set_swap_alpha_mod(const image_transform *this, 8137 image_pixel *that, png_const_structp pp, 8138 const transform_display *display) 8139 { 8140 if (that->colour_type == PNG_COLOR_TYPE_GA || 8141 that->colour_type == PNG_COLOR_TYPE_RGBA) 8142 that->alpha_first = 1; 8143 8144 this->next->mod(this->next, that, pp, display); 8145 } 8146 8147 static int 8148 image_transform_png_set_swap_alpha_add(image_transform *this, 8149 const image_transform **that, png_byte colour_type, png_byte bit_depth) 8150 { 8151 UNUSED(bit_depth) 8152 8153 this->next = *that; 8154 *that = this; 8155 8156 return colour_type == PNG_COLOR_TYPE_GA || 8157 colour_type == PNG_COLOR_TYPE_RGBA; 8158 } 8159 8160 IT(swap_alpha); 8161 #undef PT 8162 #define PT ITSTRUCT(swap_alpha) 8163 8164 #endif /* PNG_READ_SWAP_ALPHA_SUPPORTED */ 8165 8166 /* png_set_swap */ 8167 #ifdef PNG_READ_SWAP_SUPPORTED 8168 /* Byte swap 16-bit components. 8169 * 8170 * png_set_swap(png_structrp png_ptr) 8171 */ 8172 static void 8173 image_transform_png_set_swap_set(const image_transform *this, 8174 transform_display *that, png_structp pp, png_infop pi) 8175 { 8176 png_set_swap(pp); 8177 this->next->set(this->next, that, pp, pi); 8178 } 8179 8180 static void 8181 image_transform_png_set_swap_mod(const image_transform *this, 8182 image_pixel *that, png_const_structp pp, 8183 const transform_display *display) 8184 { 8185 if (that->bit_depth == 16) 8186 that->swap16 = 1; 8187 8188 this->next->mod(this->next, that, pp, display); 8189 } 8190 8191 static int 8192 image_transform_png_set_swap_add(image_transform *this, 8193 const image_transform **that, png_byte colour_type, png_byte bit_depth) 8194 { 8195 UNUSED(colour_type) 8196 8197 this->next = *that; 8198 *that = this; 8199 8200 return bit_depth == 16; 8201 } 8202 8203 IT(swap); 8204 #undef PT 8205 #define PT ITSTRUCT(swap) 8206 8207 #endif /* PNG_READ_SWAP_SUPPORTED */ 8208 8209 #ifdef PNG_READ_FILLER_SUPPORTED 8210 /* Add a filler byte to 8-bit Gray or 24-bit RGB images. 8211 * 8212 * png_set_filler, (png_structp png_ptr, png_uint_32 filler, int flags)); 8213 * 8214 * Flags: 8215 * 8216 * PNG_FILLER_BEFORE 8217 * PNG_FILLER_AFTER 8218 */ 8219 #define data ITDATA(filler) 8220 static struct 8221 { 8222 png_uint_32 filler; 8223 int flags; 8224 } data; 8225 8226 static void 8227 image_transform_png_set_filler_set(const image_transform *this, 8228 transform_display *that, png_structp pp, png_infop pi) 8229 { 8230 /* Need a random choice for 'before' and 'after' as well as for the 8231 * filler. The 'filler' value has all 32 bits set, but only bit_depth 8232 * will be used. At this point we don't know bit_depth. 8233 */ 8234 R32(data.filler); 8235 data.flags = random_choice(); 8236 8237 png_set_filler(pp, data.filler, data.flags); 8238 8239 /* The standard display handling stuff also needs to know that 8240 * there is a filler, so set that here. 8241 */ 8242 that->this.filler = 1; 8243 8244 this->next->set(this->next, that, pp, pi); 8245 } 8246 8247 static void 8248 image_transform_png_set_filler_mod(const image_transform *this, 8249 image_pixel *that, png_const_structp pp, 8250 const transform_display *display) 8251 { 8252 if (that->bit_depth >= 8 && 8253 (that->colour_type == PNG_COLOR_TYPE_RGB || 8254 that->colour_type == PNG_COLOR_TYPE_GRAY)) 8255 { 8256 const unsigned int max = (1U << that->bit_depth)-1; 8257 that->alpha = data.filler & max; 8258 that->alphaf = ((double)that->alpha) / max; 8259 that->alphae = 0; 8260 8261 /* The filler has been stored in the alpha channel, we must record 8262 * that this has been done for the checking later on, the color 8263 * type is faked to have an alpha channel, but libpng won't report 8264 * this; the app has to know the extra channel is there and this 8265 * was recording in standard_display::filler above. 8266 */ 8267 that->colour_type |= 4; /* alpha added */ 8268 that->alpha_first = data.flags == PNG_FILLER_BEFORE; 8269 } 8270 8271 this->next->mod(this->next, that, pp, display); 8272 } 8273 8274 static int 8275 image_transform_png_set_filler_add(image_transform *this, 8276 const image_transform **that, png_byte colour_type, png_byte bit_depth) 8277 { 8278 this->next = *that; 8279 *that = this; 8280 8281 return bit_depth >= 8 && (colour_type == PNG_COLOR_TYPE_RGB || 8282 colour_type == PNG_COLOR_TYPE_GRAY); 8283 } 8284 8285 #undef data 8286 IT(filler); 8287 #undef PT 8288 #define PT ITSTRUCT(filler) 8289 8290 /* png_set_add_alpha, (png_structp png_ptr, png_uint_32 filler, int flags)); */ 8291 /* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ 8292 #define data ITDATA(add_alpha) 8293 static struct 8294 { 8295 png_uint_32 filler; 8296 int flags; 8297 } data; 8298 8299 static void 8300 image_transform_png_set_add_alpha_set(const image_transform *this, 8301 transform_display *that, png_structp pp, png_infop pi) 8302 { 8303 /* Need a random choice for 'before' and 'after' as well as for the 8304 * filler. The 'filler' value has all 32 bits set, but only bit_depth 8305 * will be used. At this point we don't know bit_depth. 8306 */ 8307 R32(data.filler); 8308 data.flags = random_choice(); 8309 8310 png_set_add_alpha(pp, data.filler, data.flags); 8311 this->next->set(this->next, that, pp, pi); 8312 } 8313 8314 static void 8315 image_transform_png_set_add_alpha_mod(const image_transform *this, 8316 image_pixel *that, png_const_structp pp, 8317 const transform_display *display) 8318 { 8319 if (that->bit_depth >= 8 && 8320 (that->colour_type == PNG_COLOR_TYPE_RGB || 8321 that->colour_type == PNG_COLOR_TYPE_GRAY)) 8322 { 8323 const unsigned int max = (1U << that->bit_depth)-1; 8324 that->alpha = data.filler & max; 8325 that->alphaf = ((double)that->alpha) / max; 8326 that->alphae = 0; 8327 8328 that->colour_type |= 4; /* alpha added */ 8329 that->alpha_first = data.flags == PNG_FILLER_BEFORE; 8330 } 8331 8332 this->next->mod(this->next, that, pp, display); 8333 } 8334 8335 static int 8336 image_transform_png_set_add_alpha_add(image_transform *this, 8337 const image_transform **that, png_byte colour_type, png_byte bit_depth) 8338 { 8339 this->next = *that; 8340 *that = this; 8341 8342 return bit_depth >= 8 && (colour_type == PNG_COLOR_TYPE_RGB || 8343 colour_type == PNG_COLOR_TYPE_GRAY); 8344 } 8345 8346 #undef data 8347 IT(add_alpha); 8348 #undef PT 8349 #define PT ITSTRUCT(add_alpha) 8350 8351 #endif /* PNG_READ_FILLER_SUPPORTED */ 8352 8353 /* png_set_packing */ 8354 #ifdef PNG_READ_PACK_SUPPORTED 8355 /* Use 1 byte per pixel in 1, 2, or 4-bit depth files. 8356 * 8357 * png_set_packing(png_structrp png_ptr) 8358 * 8359 * This should only affect grayscale and palette images with less than 8 bits 8360 * per pixel. 8361 */ 8362 static void 8363 image_transform_png_set_packing_set(const image_transform *this, 8364 transform_display *that, png_structp pp, png_infop pi) 8365 { 8366 png_set_packing(pp); 8367 that->unpacked = 1; 8368 this->next->set(this->next, that, pp, pi); 8369 } 8370 8371 static void 8372 image_transform_png_set_packing_mod(const image_transform *this, 8373 image_pixel *that, png_const_structp pp, 8374 const transform_display *display) 8375 { 8376 /* The general expand case depends on what the colour type is, 8377 * low bit-depth pixel values are unpacked into bytes without 8378 * scaling, so sample_depth is not changed. 8379 */ 8380 if (that->bit_depth < 8) /* grayscale or palette */ 8381 that->bit_depth = 8; 8382 8383 this->next->mod(this->next, that, pp, display); 8384 } 8385 8386 static int 8387 image_transform_png_set_packing_add(image_transform *this, 8388 const image_transform **that, png_byte colour_type, png_byte bit_depth) 8389 { 8390 UNUSED(colour_type) 8391 8392 this->next = *that; 8393 *that = this; 8394 8395 /* Nothing should happen unless the bit depth is less than 8: */ 8396 return bit_depth < 8; 8397 } 8398 8399 IT(packing); 8400 #undef PT 8401 #define PT ITSTRUCT(packing) 8402 8403 #endif /* PNG_READ_PACK_SUPPORTED */ 8404 8405 /* png_set_packswap */ 8406 #ifdef PNG_READ_PACKSWAP_SUPPORTED 8407 /* Swap pixels packed into bytes; reverses the order on screen so that 8408 * the high order bits correspond to the rightmost pixels. 8409 * 8410 * png_set_packswap(png_structrp png_ptr) 8411 */ 8412 static void 8413 image_transform_png_set_packswap_set(const image_transform *this, 8414 transform_display *that, png_structp pp, png_infop pi) 8415 { 8416 png_set_packswap(pp); 8417 that->this.littleendian = 1; 8418 this->next->set(this->next, that, pp, pi); 8419 } 8420 8421 static void 8422 image_transform_png_set_packswap_mod(const image_transform *this, 8423 image_pixel *that, png_const_structp pp, 8424 const transform_display *display) 8425 { 8426 if (that->bit_depth < 8) 8427 that->littleendian = 1; 8428 8429 this->next->mod(this->next, that, pp, display); 8430 } 8431 8432 static int 8433 image_transform_png_set_packswap_add(image_transform *this, 8434 const image_transform **that, png_byte colour_type, png_byte bit_depth) 8435 { 8436 UNUSED(colour_type) 8437 8438 this->next = *that; 8439 *that = this; 8440 8441 return bit_depth < 8; 8442 } 8443 8444 IT(packswap); 8445 #undef PT 8446 #define PT ITSTRUCT(packswap) 8447 8448 #endif /* PNG_READ_PACKSWAP_SUPPORTED */ 8449 8450 8451 /* png_set_invert_mono */ 8452 #ifdef PNG_READ_INVERT_MONO_SUPPORTED 8453 /* Invert the gray channel 8454 * 8455 * png_set_invert_mono(png_structrp png_ptr) 8456 */ 8457 static void 8458 image_transform_png_set_invert_mono_set(const image_transform *this, 8459 transform_display *that, png_structp pp, png_infop pi) 8460 { 8461 png_set_invert_mono(pp); 8462 this->next->set(this->next, that, pp, pi); 8463 } 8464 8465 static void 8466 image_transform_png_set_invert_mono_mod(const image_transform *this, 8467 image_pixel *that, png_const_structp pp, 8468 const transform_display *display) 8469 { 8470 if (that->colour_type & 4) 8471 that->mono_inverted = 1; 8472 8473 this->next->mod(this->next, that, pp, display); 8474 } 8475 8476 static int 8477 image_transform_png_set_invert_mono_add(image_transform *this, 8478 const image_transform **that, png_byte colour_type, png_byte bit_depth) 8479 { 8480 UNUSED(bit_depth) 8481 8482 this->next = *that; 8483 *that = this; 8484 8485 /* Only has an effect on pixels with no colour: */ 8486 return (colour_type & 2) == 0; 8487 } 8488 8489 IT(invert_mono); 8490 #undef PT 8491 #define PT ITSTRUCT(invert_mono) 8492 8493 #endif /* PNG_READ_INVERT_MONO_SUPPORTED */ 8494 8495 #ifdef PNG_READ_SHIFT_SUPPORTED 8496 /* png_set_shift(png_structp, png_const_color_8p true_bits) 8497 * 8498 * The output pixels will be shifted by the given true_bits 8499 * values. 8500 */ 8501 #define data ITDATA(shift) 8502 static png_color_8 data; 8503 8504 static void 8505 image_transform_png_set_shift_set(const image_transform *this, 8506 transform_display *that, png_structp pp, png_infop pi) 8507 { 8508 /* Get a random set of shifts. The shifts need to do something 8509 * to test the transform, so they are limited to the bit depth 8510 * of the input image. Notice that in the following the 'gray' 8511 * field is randomized independently. This acts as a check that 8512 * libpng does use the correct field. 8513 */ 8514 const unsigned int depth = that->this.bit_depth; 8515 8516 data.red = (png_byte)/*SAFE*/(random_mod(depth)+1); 8517 data.green = (png_byte)/*SAFE*/(random_mod(depth)+1); 8518 data.blue = (png_byte)/*SAFE*/(random_mod(depth)+1); 8519 data.gray = (png_byte)/*SAFE*/(random_mod(depth)+1); 8520 data.alpha = (png_byte)/*SAFE*/(random_mod(depth)+1); 8521 8522 png_set_shift(pp, &data); 8523 this->next->set(this->next, that, pp, pi); 8524 } 8525 8526 static void 8527 image_transform_png_set_shift_mod(const image_transform *this, 8528 image_pixel *that, png_const_structp pp, 8529 const transform_display *display) 8530 { 8531 /* Copy the correct values into the sBIT fields, libpng does not do 8532 * anything to palette data: 8533 */ 8534 if (that->colour_type != PNG_COLOR_TYPE_PALETTE) 8535 { 8536 that->sig_bits = 1; 8537 8538 /* The sBIT fields are reset to the values previously sent to 8539 * png_set_shift according to the colour type. 8540 * does. 8541 */ 8542 if (that->colour_type & 2) /* RGB channels */ 8543 { 8544 that->red_sBIT = data.red; 8545 that->green_sBIT = data.green; 8546 that->blue_sBIT = data.blue; 8547 } 8548 8549 else /* One grey channel */ 8550 that->red_sBIT = that->green_sBIT = that->blue_sBIT = data.gray; 8551 8552 that->alpha_sBIT = data.alpha; 8553 } 8554 8555 this->next->mod(this->next, that, pp, display); 8556 } 8557 8558 static int 8559 image_transform_png_set_shift_add(image_transform *this, 8560 const image_transform **that, png_byte colour_type, png_byte bit_depth) 8561 { 8562 UNUSED(bit_depth) 8563 8564 this->next = *that; 8565 *that = this; 8566 8567 return colour_type != PNG_COLOR_TYPE_PALETTE; 8568 } 8569 8570 IT(shift); 8571 #undef PT 8572 #define PT ITSTRUCT(shift) 8573 8574 #endif /* PNG_READ_SHIFT_SUPPORTED */ 8575 8576 #ifdef THIS_IS_THE_PROFORMA 8577 static void 8578 image_transform_png_set_@_set(const image_transform *this, 8579 transform_display *that, png_structp pp, png_infop pi) 8580 { 8581 png_set_@(pp); 8582 this->next->set(this->next, that, pp, pi); 8583 } 8584 8585 static void 8586 image_transform_png_set_@_mod(const image_transform *this, 8587 image_pixel *that, png_const_structp pp, 8588 const transform_display *display) 8589 { 8590 this->next->mod(this->next, that, pp, display); 8591 } 8592 8593 static int 8594 image_transform_png_set_@_add(image_transform *this, 8595 const image_transform **that, png_byte colour_type, png_byte bit_depth) 8596 { 8597 this->next = *that; 8598 *that = this; 8599 8600 return 1; 8601 } 8602 8603 IT(@); 8604 #endif 8605 8606 8607 /* This may just be 'end' if all the transforms are disabled! */ 8608 static image_transform *const image_transform_first = &PT; 8609 8610 static void 8611 transform_enable(const char *name) 8612 { 8613 /* Everything starts out enabled, so if we see an 'enable' disabled 8614 * everything else the first time round. 8615 */ 8616 static int all_disabled = 0; 8617 int found_it = 0; 8618 image_transform *list = image_transform_first; 8619 8620 while (list != &image_transform_end) 8621 { 8622 if (strcmp(list->name, name) == 0) 8623 { 8624 list->enable = 1; 8625 found_it = 1; 8626 } 8627 else if (!all_disabled) 8628 list->enable = 0; 8629 8630 list = list->list; 8631 } 8632 8633 all_disabled = 1; 8634 8635 if (!found_it) 8636 { 8637 fprintf(stderr, "pngvalid: --transform-enable=%s: unknown transform\n", 8638 name); 8639 exit(99); 8640 } 8641 } 8642 8643 static void 8644 transform_disable(const char *name) 8645 { 8646 image_transform *list = image_transform_first; 8647 8648 while (list != &image_transform_end) 8649 { 8650 if (strcmp(list->name, name) == 0) 8651 { 8652 list->enable = 0; 8653 return; 8654 } 8655 8656 list = list->list; 8657 } 8658 8659 fprintf(stderr, "pngvalid: --transform-disable=%s: unknown transform\n", 8660 name); 8661 exit(99); 8662 } 8663 8664 static void 8665 image_transform_reset_count(void) 8666 { 8667 image_transform *next = image_transform_first; 8668 int count = 0; 8669 8670 while (next != &image_transform_end) 8671 { 8672 next->local_use = 0; 8673 next->next = 0; 8674 next = next->list; 8675 ++count; 8676 } 8677 8678 /* This can only happen if we every have more than 32 transforms (excluding 8679 * the end) in the list. 8680 */ 8681 if (count > 32) abort(); 8682 } 8683 8684 static int 8685 image_transform_test_counter(png_uint_32 counter, unsigned int max) 8686 { 8687 /* Test the list to see if there is any point contining, given a current 8688 * counter and a 'max' value. 8689 */ 8690 image_transform *next = image_transform_first; 8691 8692 while (next != &image_transform_end) 8693 { 8694 /* For max 0 or 1 continue until the counter overflows: */ 8695 counter >>= 1; 8696 8697 /* Continue if any entry hasn't reacked the max. */ 8698 if (max > 1 && next->local_use < max) 8699 return 1; 8700 next = next->list; 8701 } 8702 8703 return max <= 1 && counter == 0; 8704 } 8705 8706 static png_uint_32 8707 image_transform_add(const image_transform **this, unsigned int max, 8708 png_uint_32 counter, char *name, size_t sizeof_name, size_t *pos, 8709 png_byte colour_type, png_byte bit_depth) 8710 { 8711 for (;;) /* until we manage to add something */ 8712 { 8713 png_uint_32 mask; 8714 image_transform *list; 8715 8716 /* Find the next counter value, if the counter is zero this is the start 8717 * of the list. This routine always returns the current counter (not the 8718 * next) so it returns 0 at the end and expects 0 at the beginning. 8719 */ 8720 if (counter == 0) /* first time */ 8721 { 8722 image_transform_reset_count(); 8723 if (max <= 1) 8724 counter = 1; 8725 else 8726 counter = random_32(); 8727 } 8728 else /* advance the counter */ 8729 { 8730 switch (max) 8731 { 8732 case 0: ++counter; break; 8733 case 1: counter <<= 1; break; 8734 default: counter = random_32(); break; 8735 } 8736 } 8737 8738 /* Now add all these items, if possible */ 8739 *this = &image_transform_end; 8740 list = image_transform_first; 8741 mask = 1; 8742 8743 /* Go through the whole list adding anything that the counter selects: */ 8744 while (list != &image_transform_end) 8745 { 8746 if ((counter & mask) != 0 && list->enable && 8747 (max == 0 || list->local_use < max)) 8748 { 8749 /* Candidate to add: */ 8750 if (list->add(list, this, colour_type, bit_depth) || max == 0) 8751 { 8752 /* Added, so add to the name too. */ 8753 *pos = safecat(name, sizeof_name, *pos, " +"); 8754 *pos = safecat(name, sizeof_name, *pos, list->name); 8755 } 8756 8757 else 8758 { 8759 /* Not useful and max>0, so remove it from *this: */ 8760 *this = list->next; 8761 list->next = 0; 8762 8763 /* And, since we know it isn't useful, stop it being added again 8764 * in this run: 8765 */ 8766 list->local_use = max; 8767 } 8768 } 8769 8770 mask <<= 1; 8771 list = list->list; 8772 } 8773 8774 /* Now if anything was added we have something to do. */ 8775 if (*this != &image_transform_end) 8776 return counter; 8777 8778 /* Nothing added, but was there anything in there to add? */ 8779 if (!image_transform_test_counter(counter, max)) 8780 return 0; 8781 } 8782 } 8783 8784 static void 8785 perform_transform_test(png_modifier *pm) 8786 { 8787 png_byte colour_type = 0; 8788 png_byte bit_depth = 0; 8789 unsigned int palette_number = 0; 8790 8791 while (next_format(&colour_type, &bit_depth, &palette_number, pm->test_lbg, 8792 pm->test_tRNS)) 8793 { 8794 png_uint_32 counter = 0; 8795 size_t base_pos; 8796 char name[64]; 8797 8798 base_pos = safecat(name, sizeof name, 0, "transform:"); 8799 8800 for (;;) 8801 { 8802 size_t pos = base_pos; 8803 const image_transform *list = 0; 8804 8805 /* 'max' is currently hardwired to '1'; this should be settable on the 8806 * command line. 8807 */ 8808 counter = image_transform_add(&list, 1/*max*/, counter, 8809 name, sizeof name, &pos, colour_type, bit_depth); 8810 8811 if (counter == 0) 8812 break; 8813 8814 /* The command line can change this to checking interlaced images. */ 8815 do 8816 { 8817 pm->repeat = 0; 8818 transform_test(pm, FILEID(colour_type, bit_depth, palette_number, 8819 pm->interlace_type, 0, 0, 0), list, name); 8820 8821 if (fail(pm)) 8822 return; 8823 } 8824 while (pm->repeat); 8825 } 8826 } 8827 } 8828 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 8829 8830 /********************************* GAMMA TESTS ********************************/ 8831 #ifdef PNG_READ_GAMMA_SUPPORTED 8832 /* Reader callbacks and implementations, where they differ from the standard 8833 * ones. 8834 */ 8835 typedef struct gamma_display 8836 { 8837 standard_display this; 8838 8839 /* Parameters */ 8840 png_modifier* pm; 8841 double file_gamma; 8842 double screen_gamma; 8843 double background_gamma; 8844 png_byte sbit; 8845 int threshold_test; 8846 int use_input_precision; 8847 int scale16; 8848 int expand16; 8849 int do_background; 8850 png_color_16 background_color; 8851 8852 /* Local variables */ 8853 double maxerrout; 8854 double maxerrpc; 8855 double maxerrabs; 8856 } gamma_display; 8857 8858 #define ALPHA_MODE_OFFSET 4 8859 8860 static void 8861 gamma_display_init(gamma_display *dp, png_modifier *pm, png_uint_32 id, 8862 double file_gamma, double screen_gamma, png_byte sbit, int threshold_test, 8863 int use_input_precision, int scale16, int expand16, 8864 int do_background, const png_color_16 *pointer_to_the_background_color, 8865 double background_gamma) 8866 { 8867 /* Standard fields */ 8868 standard_display_init(&dp->this, &pm->this, id, do_read_interlace, 8869 pm->use_update_info); 8870 8871 /* Parameter fields */ 8872 dp->pm = pm; 8873 dp->file_gamma = file_gamma; 8874 dp->screen_gamma = screen_gamma; 8875 dp->background_gamma = background_gamma; 8876 dp->sbit = sbit; 8877 dp->threshold_test = threshold_test; 8878 dp->use_input_precision = use_input_precision; 8879 dp->scale16 = scale16; 8880 dp->expand16 = expand16; 8881 dp->do_background = do_background; 8882 if (do_background && pointer_to_the_background_color != 0) 8883 dp->background_color = *pointer_to_the_background_color; 8884 else 8885 memset(&dp->background_color, 0, sizeof dp->background_color); 8886 8887 /* Local variable fields */ 8888 dp->maxerrout = dp->maxerrpc = dp->maxerrabs = 0; 8889 } 8890 8891 static void 8892 gamma_info_imp(gamma_display *dp, png_structp pp, png_infop pi) 8893 { 8894 /* Reuse the standard stuff as appropriate. */ 8895 standard_info_part1(&dp->this, pp, pi); 8896 8897 /* If requested strip 16 to 8 bits - this is handled automagically below 8898 * because the output bit depth is read from the library. Note that there 8899 * are interactions with sBIT but, internally, libpng makes sbit at most 8900 * PNG_MAX_GAMMA_8 prior to 1.7 when doing the following. 8901 */ 8902 if (dp->scale16) 8903 # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 8904 png_set_scale_16(pp); 8905 # else 8906 /* The following works both in 1.5.4 and earlier versions: */ 8907 # ifdef PNG_READ_16_TO_8_SUPPORTED 8908 png_set_strip_16(pp); 8909 # else 8910 png_error(pp, "scale16 (16 to 8 bit conversion) not supported"); 8911 # endif 8912 # endif 8913 8914 if (dp->expand16) 8915 # ifdef PNG_READ_EXPAND_16_SUPPORTED 8916 png_set_expand_16(pp); 8917 # else 8918 png_error(pp, "expand16 (8 to 16 bit conversion) not supported"); 8919 # endif 8920 8921 if (dp->do_background >= ALPHA_MODE_OFFSET) 8922 { 8923 # ifdef PNG_READ_ALPHA_MODE_SUPPORTED 8924 { 8925 /* This tests the alpha mode handling, if supported. */ 8926 int mode = dp->do_background - ALPHA_MODE_OFFSET; 8927 8928 /* The gamma value is the output gamma, and is in the standard, 8929 * non-inverted, represenation. It provides a default for the PNG file 8930 * gamma, but since the file has a gAMA chunk this does not matter. 8931 */ 8932 const double sg = dp->screen_gamma; 8933 # ifndef PNG_FLOATING_POINT_SUPPORTED 8934 const png_fixed_point g = fix(sg); 8935 # endif 8936 8937 # ifdef PNG_FLOATING_POINT_SUPPORTED 8938 png_set_alpha_mode(pp, mode, sg); 8939 # else 8940 png_set_alpha_mode_fixed(pp, mode, g); 8941 # endif 8942 8943 /* However, for the standard Porter-Duff algorithm the output defaults 8944 * to be linear, so if the test requires non-linear output it must be 8945 * corrected here. 8946 */ 8947 if (mode == PNG_ALPHA_STANDARD && sg != 1) 8948 { 8949 # ifdef PNG_FLOATING_POINT_SUPPORTED 8950 png_set_gamma(pp, sg, dp->file_gamma); 8951 # else 8952 png_fixed_point f = fix(dp->file_gamma); 8953 png_set_gamma_fixed(pp, g, f); 8954 # endif 8955 } 8956 } 8957 # else 8958 png_error(pp, "alpha mode handling not supported"); 8959 # endif 8960 } 8961 8962 else 8963 { 8964 /* Set up gamma processing. */ 8965 # ifdef PNG_FLOATING_POINT_SUPPORTED 8966 png_set_gamma(pp, dp->screen_gamma, dp->file_gamma); 8967 # else 8968 { 8969 png_fixed_point s = fix(dp->screen_gamma); 8970 png_fixed_point f = fix(dp->file_gamma); 8971 png_set_gamma_fixed(pp, s, f); 8972 } 8973 # endif 8974 8975 if (dp->do_background) 8976 { 8977 # ifdef PNG_READ_BACKGROUND_SUPPORTED 8978 /* NOTE: this assumes the caller provided the correct background gamma! 8979 */ 8980 const double bg = dp->background_gamma; 8981 # ifndef PNG_FLOATING_POINT_SUPPORTED 8982 const png_fixed_point g = fix(bg); 8983 # endif 8984 8985 # ifdef PNG_FLOATING_POINT_SUPPORTED 8986 png_set_background(pp, &dp->background_color, dp->do_background, 8987 0/*need_expand*/, bg); 8988 # else 8989 png_set_background_fixed(pp, &dp->background_color, 8990 dp->do_background, 0/*need_expand*/, g); 8991 # endif 8992 # else 8993 png_error(pp, "png_set_background not supported"); 8994 # endif 8995 } 8996 } 8997 8998 { 8999 int i = dp->this.use_update_info; 9000 /* Always do one call, even if use_update_info is 0. */ 9001 do 9002 png_read_update_info(pp, pi); 9003 while (--i > 0); 9004 } 9005 9006 /* Now we may get a different cbRow: */ 9007 standard_info_part2(&dp->this, pp, pi, 1 /*images*/); 9008 } 9009 9010 static void PNGCBAPI 9011 gamma_info(png_structp pp, png_infop pi) 9012 { 9013 gamma_info_imp(voidcast(gamma_display*, png_get_progressive_ptr(pp)), pp, 9014 pi); 9015 } 9016 9017 /* Validate a single component value - the routine gets the input and output 9018 * sample values as unscaled PNG component values along with a cache of all the 9019 * information required to validate the values. 9020 */ 9021 typedef struct validate_info 9022 { 9023 png_const_structp pp; 9024 gamma_display *dp; 9025 png_byte sbit; 9026 int use_input_precision; 9027 int do_background; 9028 int scale16; 9029 unsigned int sbit_max; 9030 unsigned int isbit_shift; 9031 unsigned int outmax; 9032 9033 double gamma_correction; /* Overall correction required. */ 9034 double file_inverse; /* Inverse of file gamma. */ 9035 double screen_gamma; 9036 double screen_inverse; /* Inverse of screen gamma. */ 9037 9038 double background_red; /* Linear background value, red or gray. */ 9039 double background_green; 9040 double background_blue; 9041 9042 double maxabs; 9043 double maxpc; 9044 double maxcalc; 9045 double maxout; 9046 double maxout_total; /* Total including quantization error */ 9047 double outlog; 9048 int outquant; 9049 } 9050 validate_info; 9051 9052 static void 9053 init_validate_info(validate_info *vi, gamma_display *dp, png_const_structp pp, 9054 int in_depth, int out_depth) 9055 { 9056 const unsigned int outmax = (1U<<out_depth)-1; 9057 9058 vi->pp = pp; 9059 vi->dp = dp; 9060 9061 if (dp->sbit > 0 && dp->sbit < in_depth) 9062 { 9063 vi->sbit = dp->sbit; 9064 vi->isbit_shift = in_depth - dp->sbit; 9065 } 9066 9067 else 9068 { 9069 vi->sbit = (png_byte)in_depth; 9070 vi->isbit_shift = 0; 9071 } 9072 9073 vi->sbit_max = (1U << vi->sbit)-1; 9074 9075 /* This mimics the libpng threshold test, '0' is used to prevent gamma 9076 * correction in the validation test. 9077 */ 9078 vi->screen_gamma = dp->screen_gamma; 9079 if (fabs(vi->screen_gamma-1) < PNG_GAMMA_THRESHOLD) 9080 vi->screen_gamma = vi->screen_inverse = 0; 9081 else 9082 vi->screen_inverse = 1/vi->screen_gamma; 9083 9084 vi->use_input_precision = dp->use_input_precision; 9085 vi->outmax = outmax; 9086 vi->maxabs = abserr(dp->pm, in_depth, out_depth); 9087 vi->maxpc = pcerr(dp->pm, in_depth, out_depth); 9088 vi->maxcalc = calcerr(dp->pm, in_depth, out_depth); 9089 vi->maxout = outerr(dp->pm, in_depth, out_depth); 9090 vi->outquant = output_quantization_factor(dp->pm, in_depth, out_depth); 9091 vi->maxout_total = vi->maxout + vi->outquant * .5; 9092 vi->outlog = outlog(dp->pm, in_depth, out_depth); 9093 9094 if ((dp->this.colour_type & PNG_COLOR_MASK_ALPHA) != 0 || 9095 (dp->this.colour_type == 3 && dp->this.is_transparent) || 9096 ((dp->this.colour_type == 0 || dp->this.colour_type == 2) && 9097 dp->this.has_tRNS)) 9098 { 9099 vi->do_background = dp->do_background; 9100 9101 if (vi->do_background != 0) 9102 { 9103 const double bg_inverse = 1/dp->background_gamma; 9104 double r, g, b; 9105 9106 /* Caller must at least put the gray value into the red channel */ 9107 r = dp->background_color.red; r /= outmax; 9108 g = dp->background_color.green; g /= outmax; 9109 b = dp->background_color.blue; b /= outmax; 9110 9111 # if 0 9112 /* libpng doesn't do this optimization, if we do pngvalid will fail. 9113 */ 9114 if (fabs(bg_inverse-1) >= PNG_GAMMA_THRESHOLD) 9115 # endif 9116 { 9117 r = pow(r, bg_inverse); 9118 g = pow(g, bg_inverse); 9119 b = pow(b, bg_inverse); 9120 } 9121 9122 vi->background_red = r; 9123 vi->background_green = g; 9124 vi->background_blue = b; 9125 } 9126 } 9127 else /* Do not expect any background processing */ 9128 vi->do_background = 0; 9129 9130 if (vi->do_background == 0) 9131 vi->background_red = vi->background_green = vi->background_blue = 0; 9132 9133 vi->gamma_correction = 1/(dp->file_gamma*dp->screen_gamma); 9134 if (fabs(vi->gamma_correction-1) < PNG_GAMMA_THRESHOLD) 9135 vi->gamma_correction = 0; 9136 9137 vi->file_inverse = 1/dp->file_gamma; 9138 if (fabs(vi->file_inverse-1) < PNG_GAMMA_THRESHOLD) 9139 vi->file_inverse = 0; 9140 9141 vi->scale16 = dp->scale16; 9142 } 9143 9144 /* This function handles composition of a single non-alpha component. The 9145 * argument is the input sample value, in the range 0..1, and the alpha value. 9146 * The result is the composed, linear, input sample. If alpha is less than zero 9147 * this is the alpha component and the function should not be called! 9148 */ 9149 static double 9150 gamma_component_compose(int do_background, double input_sample, double alpha, 9151 double background, int *compose) 9152 { 9153 switch (do_background) 9154 { 9155 #ifdef PNG_READ_BACKGROUND_SUPPORTED 9156 case PNG_BACKGROUND_GAMMA_SCREEN: 9157 case PNG_BACKGROUND_GAMMA_FILE: 9158 case PNG_BACKGROUND_GAMMA_UNIQUE: 9159 /* Standard PNG background processing. */ 9160 if (alpha < 1) 9161 { 9162 if (alpha > 0) 9163 { 9164 input_sample = input_sample * alpha + background * (1-alpha); 9165 if (compose != NULL) 9166 *compose = 1; 9167 } 9168 9169 else 9170 input_sample = background; 9171 } 9172 break; 9173 #endif 9174 9175 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 9176 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD: 9177 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN: 9178 /* The components are premultiplied in either case and the output is 9179 * gamma encoded (to get standard Porter-Duff we expect the output 9180 * gamma to be set to 1.0!) 9181 */ 9182 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED: 9183 /* The optimization is that the partial-alpha entries are linear 9184 * while the opaque pixels are gamma encoded, but this only affects the 9185 * output encoding. 9186 */ 9187 if (alpha < 1) 9188 { 9189 if (alpha > 0) 9190 { 9191 input_sample *= alpha; 9192 if (compose != NULL) 9193 *compose = 1; 9194 } 9195 9196 else 9197 input_sample = 0; 9198 } 9199 break; 9200 #endif 9201 9202 default: 9203 /* Standard cases where no compositing is done (so the component 9204 * value is already correct.) 9205 */ 9206 UNUSED(alpha) 9207 UNUSED(background) 9208 UNUSED(compose) 9209 break; 9210 } 9211 9212 return input_sample; 9213 } 9214 9215 /* This API returns the encoded *input* component, in the range 0..1 */ 9216 static double 9217 gamma_component_validate(const char *name, const validate_info *vi, 9218 const unsigned int id, const unsigned int od, 9219 const double alpha /* <0 for the alpha channel itself */, 9220 const double background /* component background value */) 9221 { 9222 const unsigned int isbit = id >> vi->isbit_shift; 9223 const unsigned int sbit_max = vi->sbit_max; 9224 const unsigned int outmax = vi->outmax; 9225 const int do_background = vi->do_background; 9226 9227 double i; 9228 9229 /* First check on the 'perfect' result obtained from the digitized input 9230 * value, id, and compare this against the actual digitized result, 'od'. 9231 * 'i' is the input result in the range 0..1: 9232 */ 9233 i = isbit; i /= sbit_max; 9234 9235 /* Check for the fast route: if we don't do any background composition or if 9236 * this is the alpha channel ('alpha' < 0) or if the pixel is opaque then 9237 * just use the gamma_correction field to correct to the final output gamma. 9238 */ 9239 if (alpha == 1 /* opaque pixel component */ || !do_background 9240 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 9241 || do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_PNG 9242 #endif 9243 || (alpha < 0 /* alpha channel */ 9244 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 9245 && do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN 9246 #endif 9247 )) 9248 { 9249 /* Then get the gamma corrected version of 'i' and compare to 'od', any 9250 * error less than .5 is insignificant - just quantization of the output 9251 * value to the nearest digital value (nevertheless the error is still 9252 * recorded - it's interesting ;-) 9253 */ 9254 double encoded_sample = i; 9255 double encoded_error; 9256 9257 /* alpha less than 0 indicates the alpha channel, which is always linear 9258 */ 9259 if (alpha >= 0 && vi->gamma_correction > 0) 9260 encoded_sample = pow(encoded_sample, vi->gamma_correction); 9261 encoded_sample *= outmax; 9262 9263 encoded_error = fabs(od-encoded_sample); 9264 9265 if (encoded_error > vi->dp->maxerrout) 9266 vi->dp->maxerrout = encoded_error; 9267 9268 if (encoded_error < vi->maxout_total && encoded_error < vi->outlog) 9269 return i; 9270 } 9271 9272 /* The slow route - attempt to do linear calculations. */ 9273 /* There may be an error, or background processing is required, so calculate 9274 * the actual sample values - unencoded light intensity values. Note that in 9275 * practice these are not completely unencoded because they include a 9276 * 'viewing correction' to decrease or (normally) increase the perceptual 9277 * contrast of the image. There's nothing we can do about this - we don't 9278 * know what it is - so assume the unencoded value is perceptually linear. 9279 */ 9280 { 9281 double input_sample = i; /* In range 0..1 */ 9282 double output, error, encoded_sample, encoded_error; 9283 double es_lo, es_hi; 9284 int compose = 0; /* Set to one if composition done */ 9285 int output_is_encoded; /* Set if encoded to screen gamma */ 9286 int log_max_error = 1; /* Check maximum error values */ 9287 png_const_charp pass = 0; /* Reason test passes (or 0 for fail) */ 9288 9289 /* Convert to linear light (with the above caveat.) The alpha channel is 9290 * already linear. 9291 */ 9292 if (alpha >= 0) 9293 { 9294 int tcompose; 9295 9296 if (vi->file_inverse > 0) 9297 input_sample = pow(input_sample, vi->file_inverse); 9298 9299 /* Handle the compose processing: */ 9300 tcompose = 0; 9301 input_sample = gamma_component_compose(do_background, input_sample, 9302 alpha, background, &tcompose); 9303 9304 if (tcompose) 9305 compose = 1; 9306 } 9307 9308 /* And similarly for the output value, but we need to check the background 9309 * handling to linearize it correctly. 9310 */ 9311 output = od; 9312 output /= outmax; 9313 9314 output_is_encoded = vi->screen_gamma > 0; 9315 9316 if (alpha < 0) /* The alpha channel */ 9317 { 9318 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 9319 if (do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN) 9320 #endif 9321 { 9322 /* In all other cases the output alpha channel is linear already, 9323 * don't log errors here, they are much larger in linear data. 9324 */ 9325 output_is_encoded = 0; 9326 log_max_error = 0; 9327 } 9328 } 9329 9330 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 9331 else /* A component */ 9332 { 9333 if (do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED && 9334 alpha < 1) /* the optimized case - linear output */ 9335 { 9336 if (alpha > 0) log_max_error = 0; 9337 output_is_encoded = 0; 9338 } 9339 } 9340 #endif 9341 9342 if (output_is_encoded) 9343 output = pow(output, vi->screen_gamma); 9344 9345 /* Calculate (or recalculate) the encoded_sample value and repeat the 9346 * check above (unnecessary if we took the fast route, but harmless.) 9347 */ 9348 encoded_sample = input_sample; 9349 if (output_is_encoded) 9350 encoded_sample = pow(encoded_sample, vi->screen_inverse); 9351 encoded_sample *= outmax; 9352 9353 encoded_error = fabs(od-encoded_sample); 9354 9355 /* Don't log errors in the alpha channel, or the 'optimized' case, 9356 * neither are significant to the overall perception. 9357 */ 9358 if (log_max_error && encoded_error > vi->dp->maxerrout) 9359 vi->dp->maxerrout = encoded_error; 9360 9361 if (encoded_error < vi->maxout_total) 9362 { 9363 if (encoded_error < vi->outlog) 9364 return i; 9365 9366 /* Test passed but error is bigger than the log limit, record why the 9367 * test passed: 9368 */ 9369 pass = "less than maxout:\n"; 9370 } 9371 9372 /* i: the original input value in the range 0..1 9373 * 9374 * pngvalid calculations: 9375 * input_sample: linear result; i linearized and composed, range 0..1 9376 * encoded_sample: encoded result; input_sample scaled to ouput bit depth 9377 * 9378 * libpng calculations: 9379 * output: linear result; od scaled to 0..1 and linearized 9380 * od: encoded result from libpng 9381 */ 9382 9383 /* Now we have the numbers for real errors, both absolute values as as a 9384 * percentage of the correct value (output): 9385 */ 9386 error = fabs(input_sample-output); 9387 9388 if (log_max_error && error > vi->dp->maxerrabs) 9389 vi->dp->maxerrabs = error; 9390 9391 /* The following is an attempt to ignore the tendency of quantization to 9392 * dominate the percentage errors for lower result values: 9393 */ 9394 if (log_max_error && input_sample > .5) 9395 { 9396 double percentage_error = error/input_sample; 9397 if (percentage_error > vi->dp->maxerrpc) 9398 vi->dp->maxerrpc = percentage_error; 9399 } 9400 9401 /* Now calculate the digitization limits for 'encoded_sample' using the 9402 * 'max' values. Note that maxout is in the encoded space but maxpc and 9403 * maxabs are in linear light space. 9404 * 9405 * First find the maximum error in linear light space, range 0..1: 9406 */ 9407 { 9408 double tmp = input_sample * vi->maxpc; 9409 if (tmp < vi->maxabs) tmp = vi->maxabs; 9410 /* If 'compose' is true the composition was done in linear space using 9411 * integer arithmetic. This introduces an extra error of +/- 0.5 (at 9412 * least) in the integer space used. 'maxcalc' records this, taking 9413 * into account the possibility that even for 16 bit output 8 bit space 9414 * may have been used. 9415 */ 9416 if (compose && tmp < vi->maxcalc) tmp = vi->maxcalc; 9417 9418 /* The 'maxout' value refers to the encoded result, to compare with 9419 * this encode input_sample adjusted by the maximum error (tmp) above. 9420 */ 9421 es_lo = encoded_sample - vi->maxout; 9422 9423 if (es_lo > 0 && input_sample-tmp > 0) 9424 { 9425 double low_value = input_sample-tmp; 9426 if (output_is_encoded) 9427 low_value = pow(low_value, vi->screen_inverse); 9428 low_value *= outmax; 9429 if (low_value < es_lo) es_lo = low_value; 9430 9431 /* Quantize this appropriately: */ 9432 es_lo = ceil(es_lo / vi->outquant - .5) * vi->outquant; 9433 } 9434 9435 else 9436 es_lo = 0; 9437 9438 es_hi = encoded_sample + vi->maxout; 9439 9440 if (es_hi < outmax && input_sample+tmp < 1) 9441 { 9442 double high_value = input_sample+tmp; 9443 if (output_is_encoded) 9444 high_value = pow(high_value, vi->screen_inverse); 9445 high_value *= outmax; 9446 if (high_value > es_hi) es_hi = high_value; 9447 9448 es_hi = floor(es_hi / vi->outquant + .5) * vi->outquant; 9449 } 9450 9451 else 9452 es_hi = outmax; 9453 } 9454 9455 /* The primary test is that the final encoded value returned by the 9456 * library should be between the two limits (inclusive) that were 9457 * calculated above. 9458 */ 9459 if (od >= es_lo && od <= es_hi) 9460 { 9461 /* The value passes, but we may need to log the information anyway. */ 9462 if (encoded_error < vi->outlog) 9463 return i; 9464 9465 if (pass == 0) 9466 pass = "within digitization limits:\n"; 9467 } 9468 9469 { 9470 /* There has been an error in processing, or we need to log this 9471 * value. 9472 */ 9473 double is_lo, is_hi; 9474 9475 /* pass is set at this point if either of the tests above would have 9476 * passed. Don't do these additional tests here - just log the 9477 * original [es_lo..es_hi] values. 9478 */ 9479 if (pass == 0 && vi->use_input_precision && vi->dp->sbit) 9480 { 9481 /* Ok, something is wrong - this actually happens in current libpng 9482 * 16-to-8 processing. Assume that the input value (id, adjusted 9483 * for sbit) can be anywhere between value-.5 and value+.5 - quite a 9484 * large range if sbit is low. 9485 * 9486 * NOTE: at present because the libpng gamma table stuff has been 9487 * changed to use a rounding algorithm to correct errors in 8-bit 9488 * calculations the precise sbit calculation (a shift) has been 9489 * lost. This can result in up to a +/-1 error in the presence of 9490 * an sbit less than the bit depth. 9491 */ 9492 # if PNG_LIBPNG_VER < 10700 9493 # define SBIT_ERROR .5 9494 # else 9495 # define SBIT_ERROR 1. 9496 # endif 9497 double tmp = (isbit - SBIT_ERROR)/sbit_max; 9498 9499 if (tmp <= 0) 9500 tmp = 0; 9501 9502 else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1) 9503 tmp = pow(tmp, vi->file_inverse); 9504 9505 tmp = gamma_component_compose(do_background, tmp, alpha, background, 9506 NULL); 9507 9508 if (output_is_encoded && tmp > 0 && tmp < 1) 9509 tmp = pow(tmp, vi->screen_inverse); 9510 9511 is_lo = ceil(outmax * tmp - vi->maxout_total); 9512 9513 if (is_lo < 0) 9514 is_lo = 0; 9515 9516 tmp = (isbit + SBIT_ERROR)/sbit_max; 9517 9518 if (tmp >= 1) 9519 tmp = 1; 9520 9521 else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1) 9522 tmp = pow(tmp, vi->file_inverse); 9523 9524 tmp = gamma_component_compose(do_background, tmp, alpha, background, 9525 NULL); 9526 9527 if (output_is_encoded && tmp > 0 && tmp < 1) 9528 tmp = pow(tmp, vi->screen_inverse); 9529 9530 is_hi = floor(outmax * tmp + vi->maxout_total); 9531 9532 if (is_hi > outmax) 9533 is_hi = outmax; 9534 9535 if (!(od < is_lo || od > is_hi)) 9536 { 9537 if (encoded_error < vi->outlog) 9538 return i; 9539 9540 pass = "within input precision limits:\n"; 9541 } 9542 9543 /* One last chance. If this is an alpha channel and the 16to8 9544 * option has been used and 'inaccurate' scaling is used then the 9545 * bit reduction is obtained by simply using the top 8 bits of the 9546 * value. 9547 * 9548 * This is only done for older libpng versions when the 'inaccurate' 9549 * (chop) method of scaling was used. 9550 */ 9551 # ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED 9552 # if PNG_LIBPNG_VER < 10504 9553 /* This may be required for other components in the future, 9554 * but at present the presence of gamma correction effectively 9555 * prevents the errors in the component scaling (I don't quite 9556 * understand why, but since it's better this way I care not 9557 * to ask, JB 20110419.) 9558 */ 9559 if (pass == 0 && alpha < 0 && vi->scale16 && vi->sbit > 8 && 9560 vi->sbit + vi->isbit_shift == 16) 9561 { 9562 tmp = ((id >> 8) - .5)/255; 9563 9564 if (tmp > 0) 9565 { 9566 is_lo = ceil(outmax * tmp - vi->maxout_total); 9567 if (is_lo < 0) is_lo = 0; 9568 } 9569 9570 else 9571 is_lo = 0; 9572 9573 tmp = ((id >> 8) + .5)/255; 9574 9575 if (tmp < 1) 9576 { 9577 is_hi = floor(outmax * tmp + vi->maxout_total); 9578 if (is_hi > outmax) is_hi = outmax; 9579 } 9580 9581 else 9582 is_hi = outmax; 9583 9584 if (!(od < is_lo || od > is_hi)) 9585 { 9586 if (encoded_error < vi->outlog) 9587 return i; 9588 9589 pass = "within 8 bit limits:\n"; 9590 } 9591 } 9592 # endif 9593 # endif 9594 } 9595 else /* !use_input_precision */ 9596 is_lo = es_lo, is_hi = es_hi; 9597 9598 /* Attempt to output a meaningful error/warning message: the message 9599 * output depends on the background/composite operation being performed 9600 * because this changes what parameters were actually used above. 9601 */ 9602 { 9603 size_t pos = 0; 9604 /* Need either 1/255 or 1/65535 precision here; 3 or 6 decimal 9605 * places. Just use outmax to work out which. 9606 */ 9607 int precision = (outmax >= 1000 ? 6 : 3); 9608 int use_input=1, use_background=0, do_compose=0; 9609 char msg[256]; 9610 9611 if (pass != 0) 9612 pos = safecat(msg, sizeof msg, pos, "\n\t"); 9613 9614 /* Set up the various flags, the output_is_encoded flag above 9615 * is also used below. do_compose is just a double check. 9616 */ 9617 switch (do_background) 9618 { 9619 # ifdef PNG_READ_BACKGROUND_SUPPORTED 9620 case PNG_BACKGROUND_GAMMA_SCREEN: 9621 case PNG_BACKGROUND_GAMMA_FILE: 9622 case PNG_BACKGROUND_GAMMA_UNIQUE: 9623 use_background = (alpha >= 0 && alpha < 1); 9624 /*FALL THROUGH*/ 9625 # endif 9626 # ifdef PNG_READ_ALPHA_MODE_SUPPORTED 9627 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD: 9628 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN: 9629 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED: 9630 # endif /* ALPHA_MODE_SUPPORTED */ 9631 do_compose = (alpha > 0 && alpha < 1); 9632 use_input = (alpha != 0); 9633 break; 9634 9635 default: 9636 break; 9637 } 9638 9639 /* Check the 'compose' flag */ 9640 if (compose != do_compose) 9641 png_error(vi->pp, "internal error (compose)"); 9642 9643 /* 'name' is the component name */ 9644 pos = safecat(msg, sizeof msg, pos, name); 9645 pos = safecat(msg, sizeof msg, pos, "("); 9646 pos = safecatn(msg, sizeof msg, pos, id); 9647 if (use_input || pass != 0/*logging*/) 9648 { 9649 if (isbit != id) 9650 { 9651 /* sBIT has reduced the precision of the input: */ 9652 pos = safecat(msg, sizeof msg, pos, ", sbit("); 9653 pos = safecatn(msg, sizeof msg, pos, vi->sbit); 9654 pos = safecat(msg, sizeof msg, pos, "): "); 9655 pos = safecatn(msg, sizeof msg, pos, isbit); 9656 } 9657 pos = safecat(msg, sizeof msg, pos, "/"); 9658 /* The output is either "id/max" or "id sbit(sbit): isbit/max" */ 9659 pos = safecatn(msg, sizeof msg, pos, vi->sbit_max); 9660 } 9661 pos = safecat(msg, sizeof msg, pos, ")"); 9662 9663 /* A component may have been multiplied (in linear space) by the 9664 * alpha value, 'compose' says whether this is relevant. 9665 */ 9666 if (compose || pass != 0) 9667 { 9668 /* If any form of composition is being done report our 9669 * calculated linear value here (the code above doesn't record 9670 * the input value before composition is performed, so what 9671 * gets reported is the value after composition.) 9672 */ 9673 if (use_input || pass != 0) 9674 { 9675 if (vi->file_inverse > 0) 9676 { 9677 pos = safecat(msg, sizeof msg, pos, "^"); 9678 pos = safecatd(msg, sizeof msg, pos, vi->file_inverse, 2); 9679 } 9680 9681 else 9682 pos = safecat(msg, sizeof msg, pos, "[linear]"); 9683 9684 pos = safecat(msg, sizeof msg, pos, "*(alpha)"); 9685 pos = safecatd(msg, sizeof msg, pos, alpha, precision); 9686 } 9687 9688 /* Now record the *linear* background value if it was used 9689 * (this function is not passed the original, non-linear, 9690 * value but it is contained in the test name.) 9691 */ 9692 if (use_background) 9693 { 9694 pos = safecat(msg, sizeof msg, pos, use_input ? "+" : " "); 9695 pos = safecat(msg, sizeof msg, pos, "(background)"); 9696 pos = safecatd(msg, sizeof msg, pos, background, precision); 9697 pos = safecat(msg, sizeof msg, pos, "*"); 9698 pos = safecatd(msg, sizeof msg, pos, 1-alpha, precision); 9699 } 9700 } 9701 9702 /* Report the calculated value (input_sample) and the linearized 9703 * libpng value (output) unless this is just a component gamma 9704 * correction. 9705 */ 9706 if (compose || alpha < 0 || pass != 0) 9707 { 9708 pos = safecat(msg, sizeof msg, pos, 9709 pass != 0 ? " =\n\t" : " = "); 9710 pos = safecatd(msg, sizeof msg, pos, input_sample, precision); 9711 pos = safecat(msg, sizeof msg, pos, " (libpng: "); 9712 pos = safecatd(msg, sizeof msg, pos, output, precision); 9713 pos = safecat(msg, sizeof msg, pos, ")"); 9714 9715 /* Finally report the output gamma encoding, if any. */ 9716 if (output_is_encoded) 9717 { 9718 pos = safecat(msg, sizeof msg, pos, " ^"); 9719 pos = safecatd(msg, sizeof msg, pos, vi->screen_inverse, 2); 9720 pos = safecat(msg, sizeof msg, pos, "(to screen) ="); 9721 } 9722 9723 else 9724 pos = safecat(msg, sizeof msg, pos, " [screen is linear] ="); 9725 } 9726 9727 if ((!compose && alpha >= 0) || pass != 0) 9728 { 9729 if (pass != 0) /* logging */ 9730 pos = safecat(msg, sizeof msg, pos, "\n\t[overall:"); 9731 9732 /* This is the non-composition case, the internal linear 9733 * values are irrelevant (though the log below will reveal 9734 * them.) Output a much shorter warning/error message and report 9735 * the overall gamma correction. 9736 */ 9737 if (vi->gamma_correction > 0) 9738 { 9739 pos = safecat(msg, sizeof msg, pos, " ^"); 9740 pos = safecatd(msg, sizeof msg, pos, vi->gamma_correction, 2); 9741 pos = safecat(msg, sizeof msg, pos, "(gamma correction) ="); 9742 } 9743 9744 else 9745 pos = safecat(msg, sizeof msg, pos, 9746 " [no gamma correction] ="); 9747 9748 if (pass != 0) 9749 pos = safecat(msg, sizeof msg, pos, "]"); 9750 } 9751 9752 /* This is our calculated encoded_sample which should (but does 9753 * not) match od: 9754 */ 9755 pos = safecat(msg, sizeof msg, pos, pass != 0 ? "\n\t" : " "); 9756 pos = safecatd(msg, sizeof msg, pos, is_lo, 1); 9757 pos = safecat(msg, sizeof msg, pos, " < "); 9758 pos = safecatd(msg, sizeof msg, pos, encoded_sample, 1); 9759 pos = safecat(msg, sizeof msg, pos, " (libpng: "); 9760 pos = safecatn(msg, sizeof msg, pos, od); 9761 pos = safecat(msg, sizeof msg, pos, ")"); 9762 pos = safecat(msg, sizeof msg, pos, "/"); 9763 pos = safecatn(msg, sizeof msg, pos, outmax); 9764 pos = safecat(msg, sizeof msg, pos, " < "); 9765 pos = safecatd(msg, sizeof msg, pos, is_hi, 1); 9766 9767 if (pass == 0) /* The error condition */ 9768 { 9769 # ifdef PNG_WARNINGS_SUPPORTED 9770 png_warning(vi->pp, msg); 9771 # else 9772 store_warning(vi->pp, msg); 9773 # endif 9774 } 9775 9776 else /* logging this value */ 9777 store_verbose(&vi->dp->pm->this, vi->pp, pass, msg); 9778 } 9779 } 9780 } 9781 9782 return i; 9783 } 9784 9785 static void 9786 gamma_image_validate(gamma_display *dp, png_const_structp pp, 9787 png_infop pi) 9788 { 9789 /* Get some constants derived from the input and output file formats: */ 9790 const png_store* const ps = dp->this.ps; 9791 const png_byte in_ct = dp->this.colour_type; 9792 const png_byte in_bd = dp->this.bit_depth; 9793 const png_uint_32 w = dp->this.w; 9794 const png_uint_32 h = dp->this.h; 9795 const size_t cbRow = dp->this.cbRow; 9796 const png_byte out_ct = png_get_color_type(pp, pi); 9797 const png_byte out_bd = png_get_bit_depth(pp, pi); 9798 9799 /* There are three sources of error, firstly the quantization in the 9800 * file encoding, determined by sbit and/or the file depth, secondly 9801 * the output (screen) gamma and thirdly the output file encoding. 9802 * 9803 * Since this API receives the screen and file gamma in double 9804 * precision it is possible to calculate an exact answer given an input 9805 * pixel value. Therefore we assume that the *input* value is exact - 9806 * sample/maxsample - calculate the corresponding gamma corrected 9807 * output to the limits of double precision arithmetic and compare with 9808 * what libpng returns. 9809 * 9810 * Since the library must quantize the output to 8 or 16 bits there is 9811 * a fundamental limit on the accuracy of the output of +/-.5 - this 9812 * quantization limit is included in addition to the other limits 9813 * specified by the paramaters to the API. (Effectively, add .5 9814 * everywhere.) 9815 * 9816 * The behavior of the 'sbit' paramter is defined by section 12.5 9817 * (sample depth scaling) of the PNG spec. That section forces the 9818 * decoder to assume that the PNG values have been scaled if sBIT is 9819 * present: 9820 * 9821 * png-sample = floor( input-sample * (max-out/max-in) + .5); 9822 * 9823 * This means that only a subset of the possible PNG values should 9824 * appear in the input. However, the spec allows the encoder to use a 9825 * variety of approximations to the above and doesn't require any 9826 * restriction of the values produced. 9827 * 9828 * Nevertheless the spec requires that the upper 'sBIT' bits of the 9829 * value stored in a PNG file be the original sample bits. 9830 * Consequently the code below simply scales the top sbit bits by 9831 * (1<<sbit)-1 to obtain an original sample value. 9832 * 9833 * Because there is limited precision in the input it is arguable that 9834 * an acceptable result is any valid result from input-.5 to input+.5. 9835 * The basic tests below do not do this, however if 'use_input_precision' 9836 * is set a subsequent test is performed above. 9837 */ 9838 const unsigned int samples_per_pixel = (out_ct & 2U) ? 3U : 1U; 9839 int processing; 9840 png_uint_32 y; 9841 const store_palette_entry *in_palette = dp->this.palette; 9842 const int in_is_transparent = dp->this.is_transparent; 9843 int process_tRNS; 9844 int out_npalette = -1; 9845 int out_is_transparent = 0; /* Just refers to the palette case */ 9846 store_palette out_palette; 9847 validate_info vi; 9848 9849 /* Check for row overwrite errors */ 9850 store_image_check(dp->this.ps, pp, 0); 9851 9852 /* Supply the input and output sample depths here - 8 for an indexed image, 9853 * otherwise the bit depth. 9854 */ 9855 init_validate_info(&vi, dp, pp, in_ct==3?8:in_bd, out_ct==3?8:out_bd); 9856 9857 processing = (vi.gamma_correction > 0 && !dp->threshold_test) 9858 || in_bd != out_bd || in_ct != out_ct || vi.do_background; 9859 process_tRNS = dp->this.has_tRNS && vi.do_background; 9860 9861 /* TODO: FIX THIS: MAJOR BUG! If the transformations all happen inside 9862 * the palette there is no way of finding out, because libpng fails to 9863 * update the palette on png_read_update_info. Indeed, libpng doesn't 9864 * even do the required work until much later, when it doesn't have any 9865 * info pointer. Oops. For the moment 'processing' is turned off if 9866 * out_ct is palette. 9867 */ 9868 if (in_ct == 3 && out_ct == 3) 9869 processing = 0; 9870 9871 if (processing && out_ct == 3) 9872 out_is_transparent = read_palette(out_palette, &out_npalette, pp, pi); 9873 9874 for (y=0; y<h; ++y) 9875 { 9876 png_const_bytep pRow = store_image_row(ps, pp, 0, y); 9877 png_byte std[STANDARD_ROWMAX]; 9878 9879 transform_row(pp, std, in_ct, in_bd, y); 9880 9881 if (processing) 9882 { 9883 unsigned int x; 9884 9885 for (x=0; x<w; ++x) 9886 { 9887 double alpha = 1; /* serves as a flag value */ 9888 9889 /* Record the palette index for index images. */ 9890 const unsigned int in_index = 9891 in_ct == 3 ? sample(std, 3, in_bd, x, 0, 0, 0) : 256; 9892 const unsigned int out_index = 9893 out_ct == 3 ? sample(std, 3, out_bd, x, 0, 0, 0) : 256; 9894 9895 /* Handle input alpha - png_set_background will cause the output 9896 * alpha to disappear so there is nothing to check. 9897 */ 9898 if ((in_ct & PNG_COLOR_MASK_ALPHA) != 0 || 9899 (in_ct == 3 && in_is_transparent)) 9900 { 9901 const unsigned int input_alpha = in_ct == 3 ? 9902 dp->this.palette[in_index].alpha : 9903 sample(std, in_ct, in_bd, x, samples_per_pixel, 0, 0); 9904 9905 unsigned int output_alpha = 65536 /* as a flag value */; 9906 9907 if (out_ct == 3) 9908 { 9909 if (out_is_transparent) 9910 output_alpha = out_palette[out_index].alpha; 9911 } 9912 9913 else if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0) 9914 output_alpha = sample(pRow, out_ct, out_bd, x, 9915 samples_per_pixel, 0, 0); 9916 9917 if (output_alpha != 65536) 9918 alpha = gamma_component_validate("alpha", &vi, input_alpha, 9919 output_alpha, -1/*alpha*/, 0/*background*/); 9920 9921 else /* no alpha in output */ 9922 { 9923 /* This is a copy of the calculation of 'i' above in order to 9924 * have the alpha value to use in the background calculation. 9925 */ 9926 alpha = input_alpha >> vi.isbit_shift; 9927 alpha /= vi.sbit_max; 9928 } 9929 } 9930 9931 else if (process_tRNS) 9932 { 9933 /* alpha needs to be set appropriately for this pixel, it is 9934 * currently 1 and needs to be 0 for an input pixel which matches 9935 * the values in tRNS. 9936 */ 9937 switch (in_ct) 9938 { 9939 case 0: /* gray */ 9940 if (sample(std, in_ct, in_bd, x, 0, 0, 0) == 9941 dp->this.transparent.red) 9942 alpha = 0; 9943 break; 9944 9945 case 2: /* RGB */ 9946 if (sample(std, in_ct, in_bd, x, 0, 0, 0) == 9947 dp->this.transparent.red && 9948 sample(std, in_ct, in_bd, x, 1, 0, 0) == 9949 dp->this.transparent.green && 9950 sample(std, in_ct, in_bd, x, 2, 0, 0) == 9951 dp->this.transparent.blue) 9952 alpha = 0; 9953 break; 9954 9955 default: 9956 break; 9957 } 9958 } 9959 9960 /* Handle grayscale or RGB components. */ 9961 if ((in_ct & PNG_COLOR_MASK_COLOR) == 0) /* grayscale */ 9962 (void)gamma_component_validate("gray", &vi, 9963 sample(std, in_ct, in_bd, x, 0, 0, 0), 9964 sample(pRow, out_ct, out_bd, x, 0, 0, 0), 9965 alpha/*component*/, vi.background_red); 9966 else /* RGB or palette */ 9967 { 9968 (void)gamma_component_validate("red", &vi, 9969 in_ct == 3 ? in_palette[in_index].red : 9970 sample(std, in_ct, in_bd, x, 0, 0, 0), 9971 out_ct == 3 ? out_palette[out_index].red : 9972 sample(pRow, out_ct, out_bd, x, 0, 0, 0), 9973 alpha/*component*/, vi.background_red); 9974 9975 (void)gamma_component_validate("green", &vi, 9976 in_ct == 3 ? in_palette[in_index].green : 9977 sample(std, in_ct, in_bd, x, 1, 0, 0), 9978 out_ct == 3 ? out_palette[out_index].green : 9979 sample(pRow, out_ct, out_bd, x, 1, 0, 0), 9980 alpha/*component*/, vi.background_green); 9981 9982 (void)gamma_component_validate("blue", &vi, 9983 in_ct == 3 ? in_palette[in_index].blue : 9984 sample(std, in_ct, in_bd, x, 2, 0, 0), 9985 out_ct == 3 ? out_palette[out_index].blue : 9986 sample(pRow, out_ct, out_bd, x, 2, 0, 0), 9987 alpha/*component*/, vi.background_blue); 9988 } 9989 } 9990 } 9991 9992 else if (memcmp(std, pRow, cbRow) != 0) 9993 { 9994 char msg[64]; 9995 9996 /* No transform is expected on the threshold tests. */ 9997 sprintf(msg, "gamma: below threshold row %lu changed", 9998 (unsigned long)y); 9999 10000 png_error(pp, msg); 10001 } 10002 } /* row (y) loop */ 10003 10004 dp->this.ps->validated = 1; 10005 } 10006 10007 static void PNGCBAPI 10008 gamma_end(png_structp ppIn, png_infop pi) 10009 { 10010 png_const_structp pp = ppIn; 10011 gamma_display *dp = voidcast(gamma_display*, png_get_progressive_ptr(pp)); 10012 10013 if (!dp->this.speed) 10014 gamma_image_validate(dp, pp, pi); 10015 else 10016 dp->this.ps->validated = 1; 10017 } 10018 10019 /* A single test run checking a gamma transformation. 10020 * 10021 * maxabs: maximum absolute error as a fraction 10022 * maxout: maximum output error in the output units 10023 * maxpc: maximum percentage error (as a percentage) 10024 */ 10025 static void 10026 gamma_test(png_modifier *pmIn, const png_byte colour_typeIn, 10027 const png_byte bit_depthIn, const int palette_numberIn, 10028 const int interlace_typeIn, 10029 const double file_gammaIn, const double screen_gammaIn, 10030 const png_byte sbitIn, const int threshold_testIn, 10031 const char *name, 10032 const int use_input_precisionIn, const int scale16In, 10033 const int expand16In, const int do_backgroundIn, 10034 const png_color_16 *bkgd_colorIn, double bkgd_gammaIn) 10035 { 10036 gamma_display d; 10037 context(&pmIn->this, fault); 10038 10039 gamma_display_init(&d, pmIn, FILEID(colour_typeIn, bit_depthIn, 10040 palette_numberIn, interlace_typeIn, 0, 0, 0), 10041 file_gammaIn, screen_gammaIn, sbitIn, 10042 threshold_testIn, use_input_precisionIn, scale16In, 10043 expand16In, do_backgroundIn, bkgd_colorIn, bkgd_gammaIn); 10044 10045 Try 10046 { 10047 png_structp pp; 10048 png_infop pi; 10049 gama_modification gama_mod; 10050 srgb_modification srgb_mod; 10051 sbit_modification sbit_mod; 10052 10053 /* For the moment don't use the png_modifier support here. */ 10054 d.pm->encoding_counter = 0; 10055 modifier_set_encoding(d.pm); /* Just resets everything */ 10056 d.pm->current_gamma = d.file_gamma; 10057 10058 /* Make an appropriate modifier to set the PNG file gamma to the 10059 * given gamma value and the sBIT chunk to the given precision. 10060 */ 10061 d.pm->modifications = NULL; 10062 gama_modification_init(&gama_mod, d.pm, d.file_gamma); 10063 srgb_modification_init(&srgb_mod, d.pm, 127 /*delete*/); 10064 if (d.sbit > 0) 10065 sbit_modification_init(&sbit_mod, d.pm, d.sbit); 10066 10067 modification_reset(d.pm->modifications); 10068 10069 /* Get a png_struct for reading the image. */ 10070 pp = set_modifier_for_read(d.pm, &pi, d.this.id, name); 10071 standard_palette_init(&d.this); 10072 10073 /* Introduce the correct read function. */ 10074 if (d.pm->this.progressive) 10075 { 10076 /* Share the row function with the standard implementation. */ 10077 png_set_progressive_read_fn(pp, &d, gamma_info, progressive_row, 10078 gamma_end); 10079 10080 /* Now feed data into the reader until we reach the end: */ 10081 modifier_progressive_read(d.pm, pp, pi); 10082 } 10083 else 10084 { 10085 /* modifier_read expects a png_modifier* */ 10086 png_set_read_fn(pp, d.pm, modifier_read); 10087 10088 /* Check the header values: */ 10089 png_read_info(pp, pi); 10090 10091 /* Process the 'info' requirements. Only one image is generated */ 10092 gamma_info_imp(&d, pp, pi); 10093 10094 sequential_row(&d.this, pp, pi, -1, 0); 10095 10096 if (!d.this.speed) 10097 gamma_image_validate(&d, pp, pi); 10098 else 10099 d.this.ps->validated = 1; 10100 } 10101 10102 modifier_reset(d.pm); 10103 10104 if (d.pm->log && !d.threshold_test && !d.this.speed) 10105 fprintf(stderr, "%d bit %s %s: max error %f (%.2g, %2g%%)\n", 10106 d.this.bit_depth, colour_types[d.this.colour_type], name, 10107 d.maxerrout, d.maxerrabs, 100*d.maxerrpc); 10108 10109 /* Log the summary values too. */ 10110 if (d.this.colour_type == 0 || d.this.colour_type == 4) 10111 { 10112 switch (d.this.bit_depth) 10113 { 10114 case 1: 10115 break; 10116 10117 case 2: 10118 if (d.maxerrout > d.pm->error_gray_2) 10119 d.pm->error_gray_2 = d.maxerrout; 10120 10121 break; 10122 10123 case 4: 10124 if (d.maxerrout > d.pm->error_gray_4) 10125 d.pm->error_gray_4 = d.maxerrout; 10126 10127 break; 10128 10129 case 8: 10130 if (d.maxerrout > d.pm->error_gray_8) 10131 d.pm->error_gray_8 = d.maxerrout; 10132 10133 break; 10134 10135 case 16: 10136 if (d.maxerrout > d.pm->error_gray_16) 10137 d.pm->error_gray_16 = d.maxerrout; 10138 10139 break; 10140 10141 default: 10142 png_error(pp, "bad bit depth (internal: 1)"); 10143 } 10144 } 10145 10146 else if (d.this.colour_type == 2 || d.this.colour_type == 6) 10147 { 10148 switch (d.this.bit_depth) 10149 { 10150 case 8: 10151 10152 if (d.maxerrout > d.pm->error_color_8) 10153 d.pm->error_color_8 = d.maxerrout; 10154 10155 break; 10156 10157 case 16: 10158 10159 if (d.maxerrout > d.pm->error_color_16) 10160 d.pm->error_color_16 = d.maxerrout; 10161 10162 break; 10163 10164 default: 10165 png_error(pp, "bad bit depth (internal: 2)"); 10166 } 10167 } 10168 10169 else if (d.this.colour_type == 3) 10170 { 10171 if (d.maxerrout > d.pm->error_indexed) 10172 d.pm->error_indexed = d.maxerrout; 10173 } 10174 } 10175 10176 Catch(fault) 10177 modifier_reset(voidcast(png_modifier*,(void*)fault)); 10178 } 10179 10180 static void gamma_threshold_test(png_modifier *pm, png_byte colour_type, 10181 png_byte bit_depth, int interlace_type, double file_gamma, 10182 double screen_gamma) 10183 { 10184 size_t pos = 0; 10185 char name[64]; 10186 pos = safecat(name, sizeof name, pos, "threshold "); 10187 pos = safecatd(name, sizeof name, pos, file_gamma, 3); 10188 pos = safecat(name, sizeof name, pos, "/"); 10189 pos = safecatd(name, sizeof name, pos, screen_gamma, 3); 10190 10191 (void)gamma_test(pm, colour_type, bit_depth, 0/*palette*/, interlace_type, 10192 file_gamma, screen_gamma, 0/*sBIT*/, 1/*threshold test*/, name, 10193 0 /*no input precision*/, 10194 0 /*no scale16*/, 0 /*no expand16*/, 0 /*no background*/, 0 /*hence*/, 10195 0 /*no background gamma*/); 10196 } 10197 10198 static void 10199 perform_gamma_threshold_tests(png_modifier *pm) 10200 { 10201 png_byte colour_type = 0; 10202 png_byte bit_depth = 0; 10203 unsigned int palette_number = 0; 10204 10205 /* Don't test more than one instance of each palette - it's pointless, in 10206 * fact this test is somewhat excessive since libpng doesn't make this 10207 * decision based on colour type or bit depth! 10208 * 10209 * CHANGED: now test two palettes and, as a side effect, images with and 10210 * without tRNS. 10211 */ 10212 while (next_format(&colour_type, &bit_depth, &palette_number, 10213 pm->test_lbg_gamma_threshold, pm->test_tRNS)) 10214 if (palette_number < 2) 10215 { 10216 double test_gamma = 1.0; 10217 while (test_gamma >= .4) 10218 { 10219 /* There's little point testing the interlacing vs non-interlacing, 10220 * but this can be set from the command line. 10221 */ 10222 gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type, 10223 test_gamma, 1/test_gamma); 10224 test_gamma *= .95; 10225 } 10226 10227 /* And a special test for sRGB */ 10228 gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type, 10229 .45455, 2.2); 10230 10231 if (fail(pm)) 10232 return; 10233 } 10234 } 10235 10236 static void gamma_transform_test(png_modifier *pm, 10237 const png_byte colour_type, const png_byte bit_depth, 10238 const int palette_number, 10239 const int interlace_type, const double file_gamma, 10240 const double screen_gamma, const png_byte sbit, 10241 const int use_input_precision, const int scale16) 10242 { 10243 size_t pos = 0; 10244 char name[64]; 10245 10246 if (sbit != bit_depth && sbit != 0) 10247 { 10248 pos = safecat(name, sizeof name, pos, "sbit("); 10249 pos = safecatn(name, sizeof name, pos, sbit); 10250 pos = safecat(name, sizeof name, pos, ") "); 10251 } 10252 10253 else 10254 pos = safecat(name, sizeof name, pos, "gamma "); 10255 10256 if (scale16) 10257 pos = safecat(name, sizeof name, pos, "16to8 "); 10258 10259 pos = safecatd(name, sizeof name, pos, file_gamma, 3); 10260 pos = safecat(name, sizeof name, pos, "->"); 10261 pos = safecatd(name, sizeof name, pos, screen_gamma, 3); 10262 10263 gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type, 10264 file_gamma, screen_gamma, sbit, 0, name, use_input_precision, 10265 scale16, pm->test_gamma_expand16, 0 , 0, 0); 10266 } 10267 10268 static void perform_gamma_transform_tests(png_modifier *pm) 10269 { 10270 png_byte colour_type = 0; 10271 png_byte bit_depth = 0; 10272 unsigned int palette_number = 0; 10273 10274 while (next_format(&colour_type, &bit_depth, &palette_number, 10275 pm->test_lbg_gamma_transform, pm->test_tRNS)) 10276 { 10277 unsigned int i, j; 10278 10279 for (i=0; i<pm->ngamma_tests; ++i) for (j=0; j<pm->ngamma_tests; ++j) 10280 if (i != j) 10281 { 10282 gamma_transform_test(pm, colour_type, bit_depth, palette_number, 10283 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], 0/*sBIT*/, 10284 pm->use_input_precision, 0 /*do not scale16*/); 10285 10286 if (fail(pm)) 10287 return; 10288 } 10289 } 10290 } 10291 10292 static void perform_gamma_sbit_tests(png_modifier *pm) 10293 { 10294 png_byte sbit; 10295 10296 /* The only interesting cases are colour and grayscale, alpha is ignored here 10297 * for overall speed. Only bit depths where sbit is less than the bit depth 10298 * are tested. 10299 */ 10300 for (sbit=pm->sbitlow; sbit<(1<<READ_BDHI); ++sbit) 10301 { 10302 png_byte colour_type = 0, bit_depth = 0; 10303 unsigned int npalette = 0; 10304 10305 while (next_format(&colour_type, &bit_depth, &npalette, 10306 pm->test_lbg_gamma_sbit, pm->test_tRNS)) 10307 if ((colour_type & PNG_COLOR_MASK_ALPHA) == 0 && 10308 ((colour_type == 3 && sbit < 8) || 10309 (colour_type != 3 && sbit < bit_depth))) 10310 { 10311 unsigned int i; 10312 10313 for (i=0; i<pm->ngamma_tests; ++i) 10314 { 10315 unsigned int j; 10316 10317 for (j=0; j<pm->ngamma_tests; ++j) if (i != j) 10318 { 10319 gamma_transform_test(pm, colour_type, bit_depth, npalette, 10320 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], 10321 sbit, pm->use_input_precision_sbit, 0 /*scale16*/); 10322 10323 if (fail(pm)) 10324 return; 10325 } 10326 } 10327 } 10328 } 10329 } 10330 10331 /* Note that this requires a 16 bit source image but produces 8 bit output, so 10332 * we only need the 16bit write support, but the 16 bit images are only 10333 * generated if DO_16BIT is defined. 10334 */ 10335 #ifdef DO_16BIT 10336 static void perform_gamma_scale16_tests(png_modifier *pm) 10337 { 10338 # ifndef PNG_MAX_GAMMA_8 10339 # define PNG_MAX_GAMMA_8 11 10340 # endif 10341 # if defined PNG_MAX_GAMMA_8 || PNG_LIBPNG_VER < 10700 10342 # define SBIT_16_TO_8 PNG_MAX_GAMMA_8 10343 # else 10344 # define SBIT_16_TO_8 16 10345 # endif 10346 /* Include the alpha cases here. Note that sbit matches the internal value 10347 * used by the library - otherwise we will get spurious errors from the 10348 * internal sbit style approximation. 10349 * 10350 * The threshold test is here because otherwise the 16 to 8 conversion will 10351 * proceed *without* gamma correction, and the tests above will fail (but not 10352 * by much) - this could be fixed, it only appears with the -g option. 10353 */ 10354 unsigned int i, j; 10355 for (i=0; i<pm->ngamma_tests; ++i) 10356 { 10357 for (j=0; j<pm->ngamma_tests; ++j) 10358 { 10359 if (i != j && 10360 fabs(pm->gammas[j]/pm->gammas[i]-1) >= PNG_GAMMA_THRESHOLD) 10361 { 10362 gamma_transform_test(pm, 0, 16, 0, pm->interlace_type, 10363 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, 10364 pm->use_input_precision_16to8, 1 /*scale16*/); 10365 10366 if (fail(pm)) 10367 return; 10368 10369 gamma_transform_test(pm, 2, 16, 0, pm->interlace_type, 10370 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, 10371 pm->use_input_precision_16to8, 1 /*scale16*/); 10372 10373 if (fail(pm)) 10374 return; 10375 10376 gamma_transform_test(pm, 4, 16, 0, pm->interlace_type, 10377 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, 10378 pm->use_input_precision_16to8, 1 /*scale16*/); 10379 10380 if (fail(pm)) 10381 return; 10382 10383 gamma_transform_test(pm, 6, 16, 0, pm->interlace_type, 10384 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, 10385 pm->use_input_precision_16to8, 1 /*scale16*/); 10386 10387 if (fail(pm)) 10388 return; 10389 } 10390 } 10391 } 10392 } 10393 #endif /* 16 to 8 bit conversion */ 10394 10395 #if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ 10396 defined(PNG_READ_ALPHA_MODE_SUPPORTED) 10397 static void gamma_composition_test(png_modifier *pm, 10398 const png_byte colour_type, const png_byte bit_depth, 10399 const int palette_number, 10400 const int interlace_type, const double file_gamma, 10401 const double screen_gamma, 10402 const int use_input_precision, const int do_background, 10403 const int expand_16) 10404 { 10405 size_t pos = 0; 10406 png_const_charp base; 10407 double bg; 10408 char name[128]; 10409 png_color_16 background; 10410 10411 /* Make up a name and get an appropriate background gamma value. */ 10412 switch (do_background) 10413 { 10414 default: 10415 base = ""; 10416 bg = 4; /* should not be used */ 10417 break; 10418 case PNG_BACKGROUND_GAMMA_SCREEN: 10419 base = " bckg(Screen):"; 10420 bg = 1/screen_gamma; 10421 break; 10422 case PNG_BACKGROUND_GAMMA_FILE: 10423 base = " bckg(File):"; 10424 bg = file_gamma; 10425 break; 10426 case PNG_BACKGROUND_GAMMA_UNIQUE: 10427 base = " bckg(Unique):"; 10428 /* This tests the handling of a unique value, the math is such that the 10429 * value tends to be <1, but is neither screen nor file (even if they 10430 * match!) 10431 */ 10432 bg = (file_gamma + screen_gamma) / 3; 10433 break; 10434 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 10435 case ALPHA_MODE_OFFSET + PNG_ALPHA_PNG: 10436 base = " alpha(PNG)"; 10437 bg = 4; /* should not be used */ 10438 break; 10439 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD: 10440 base = " alpha(Porter-Duff)"; 10441 bg = 4; /* should not be used */ 10442 break; 10443 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED: 10444 base = " alpha(Optimized)"; 10445 bg = 4; /* should not be used */ 10446 break; 10447 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN: 10448 base = " alpha(Broken)"; 10449 bg = 4; /* should not be used */ 10450 break; 10451 #endif 10452 } 10453 10454 /* Use random background values - the background is always presented in the 10455 * output space (8 or 16 bit components). 10456 */ 10457 if (expand_16 || bit_depth == 16) 10458 { 10459 png_uint_32 r = random_32(); 10460 10461 background.red = (png_uint_16)r; 10462 background.green = (png_uint_16)(r >> 16); 10463 r = random_32(); 10464 background.blue = (png_uint_16)r; 10465 background.gray = (png_uint_16)(r >> 16); 10466 10467 /* In earlier libpng versions, those where DIGITIZE is set, any background 10468 * gamma correction in the expand16 case was done using 8-bit gamma 10469 * correction tables, resulting in larger errors. To cope with those 10470 * cases use a 16-bit background value which will handle this gamma 10471 * correction. 10472 */ 10473 # if DIGITIZE 10474 if (expand_16 && (do_background == PNG_BACKGROUND_GAMMA_UNIQUE || 10475 do_background == PNG_BACKGROUND_GAMMA_FILE) && 10476 fabs(bg*screen_gamma-1) > PNG_GAMMA_THRESHOLD) 10477 { 10478 /* The background values will be looked up in an 8-bit table to do 10479 * the gamma correction, so only select values which are an exact 10480 * match for the 8-bit table entries: 10481 */ 10482 background.red = (png_uint_16)((background.red >> 8) * 257); 10483 background.green = (png_uint_16)((background.green >> 8) * 257); 10484 background.blue = (png_uint_16)((background.blue >> 8) * 257); 10485 background.gray = (png_uint_16)((background.gray >> 8) * 257); 10486 } 10487 # endif 10488 } 10489 10490 else /* 8 bit colors */ 10491 { 10492 png_uint_32 r = random_32(); 10493 10494 background.red = (png_byte)r; 10495 background.green = (png_byte)(r >> 8); 10496 background.blue = (png_byte)(r >> 16); 10497 background.gray = (png_byte)(r >> 24); 10498 } 10499 10500 background.index = 193; /* rgb(193,193,193) to detect errors */ 10501 10502 if (!(colour_type & PNG_COLOR_MASK_COLOR)) 10503 { 10504 /* Because, currently, png_set_background is always called with 10505 * 'need_expand' false in this case and because the gamma test itself 10506 * doesn't cause an expand to 8-bit for lower bit depths the colour must 10507 * be reduced to the correct range. 10508 */ 10509 if (bit_depth < 8) 10510 background.gray &= (png_uint_16)((1U << bit_depth)-1); 10511 10512 /* Grayscale input, we do not convert to RGB (TBD), so we must set the 10513 * background to gray - else libpng seems to fail. 10514 */ 10515 background.red = background.green = background.blue = background.gray; 10516 } 10517 10518 pos = safecat(name, sizeof name, pos, "gamma "); 10519 pos = safecatd(name, sizeof name, pos, file_gamma, 3); 10520 pos = safecat(name, sizeof name, pos, "->"); 10521 pos = safecatd(name, sizeof name, pos, screen_gamma, 3); 10522 10523 pos = safecat(name, sizeof name, pos, base); 10524 if (do_background < ALPHA_MODE_OFFSET) 10525 { 10526 /* Include the background color and gamma in the name: */ 10527 pos = safecat(name, sizeof name, pos, "("); 10528 /* This assumes no expand gray->rgb - the current code won't handle that! 10529 */ 10530 if (colour_type & PNG_COLOR_MASK_COLOR) 10531 { 10532 pos = safecatn(name, sizeof name, pos, background.red); 10533 pos = safecat(name, sizeof name, pos, ","); 10534 pos = safecatn(name, sizeof name, pos, background.green); 10535 pos = safecat(name, sizeof name, pos, ","); 10536 pos = safecatn(name, sizeof name, pos, background.blue); 10537 } 10538 else 10539 pos = safecatn(name, sizeof name, pos, background.gray); 10540 pos = safecat(name, sizeof name, pos, ")^"); 10541 pos = safecatd(name, sizeof name, pos, bg, 3); 10542 } 10543 10544 gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type, 10545 file_gamma, screen_gamma, 0/*sBIT*/, 0, name, use_input_precision, 10546 0/*strip 16*/, expand_16, do_background, &background, bg); 10547 } 10548 10549 10550 static void 10551 perform_gamma_composition_tests(png_modifier *pm, int do_background, 10552 int expand_16) 10553 { 10554 png_byte colour_type = 0; 10555 png_byte bit_depth = 0; 10556 unsigned int palette_number = 0; 10557 10558 /* Skip the non-alpha cases - there is no setting of a transparency colour at 10559 * present. 10560 * 10561 * TODO: incorrect; the palette case sets tRNS and, now RGB and gray do, 10562 * however the palette case fails miserably so is commented out below. 10563 */ 10564 while (next_format(&colour_type, &bit_depth, &palette_number, 10565 pm->test_lbg_gamma_composition, pm->test_tRNS)) 10566 if ((colour_type & PNG_COLOR_MASK_ALPHA) != 0 10567 #if 0 /* TODO: FIXME */ 10568 /*TODO: FIXME: this should work */ 10569 || colour_type == 3 10570 #endif 10571 || (colour_type != 3 && palette_number != 0)) 10572 { 10573 unsigned int i, j; 10574 10575 /* Don't skip the i==j case here - it's relevant. */ 10576 for (i=0; i<pm->ngamma_tests; ++i) for (j=0; j<pm->ngamma_tests; ++j) 10577 { 10578 gamma_composition_test(pm, colour_type, bit_depth, palette_number, 10579 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], 10580 pm->use_input_precision, do_background, expand_16); 10581 10582 if (fail(pm)) 10583 return; 10584 } 10585 } 10586 } 10587 #endif /* READ_BACKGROUND || READ_ALPHA_MODE */ 10588 10589 static void 10590 init_gamma_errors(png_modifier *pm) 10591 { 10592 /* Use -1 to catch tests that were not actually run */ 10593 pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = -1.; 10594 pm->error_color_8 = -1.; 10595 pm->error_indexed = -1.; 10596 pm->error_gray_16 = pm->error_color_16 = -1.; 10597 } 10598 10599 static void 10600 print_one(const char *leader, double err) 10601 { 10602 if (err != -1.) 10603 printf(" %s %.5f\n", leader, err); 10604 } 10605 10606 static void 10607 summarize_gamma_errors(png_modifier *pm, png_const_charp who, int low_bit_depth, 10608 int indexed) 10609 { 10610 fflush(stderr); 10611 10612 if (who) 10613 printf("\nGamma correction with %s:\n", who); 10614 10615 else 10616 printf("\nBasic gamma correction:\n"); 10617 10618 if (low_bit_depth) 10619 { 10620 print_one(" 2 bit gray: ", pm->error_gray_2); 10621 print_one(" 4 bit gray: ", pm->error_gray_4); 10622 print_one(" 8 bit gray: ", pm->error_gray_8); 10623 print_one(" 8 bit color:", pm->error_color_8); 10624 if (indexed) 10625 print_one(" indexed: ", pm->error_indexed); 10626 } 10627 10628 print_one("16 bit gray: ", pm->error_gray_16); 10629 print_one("16 bit color:", pm->error_color_16); 10630 10631 fflush(stdout); 10632 } 10633 10634 static void 10635 perform_gamma_test(png_modifier *pm, int summary) 10636 { 10637 /*TODO: remove this*/ 10638 /* Save certain values for the temporary overrides below. */ 10639 unsigned int calculations_use_input_precision = 10640 pm->calculations_use_input_precision; 10641 # ifdef PNG_READ_BACKGROUND_SUPPORTED 10642 double maxout8 = pm->maxout8; 10643 # endif 10644 10645 /* First some arbitrary no-transform tests: */ 10646 if (!pm->this.speed && pm->test_gamma_threshold) 10647 { 10648 perform_gamma_threshold_tests(pm); 10649 10650 if (fail(pm)) 10651 return; 10652 } 10653 10654 /* Now some real transforms. */ 10655 if (pm->test_gamma_transform) 10656 { 10657 if (summary) 10658 { 10659 fflush(stderr); 10660 printf("Gamma correction error summary\n\n"); 10661 printf("The printed value is the maximum error in the pixel values\n"); 10662 printf("calculated by the libpng gamma correction code. The error\n"); 10663 printf("is calculated as the difference between the output pixel\n"); 10664 printf("value (always an integer) and the ideal value from the\n"); 10665 printf("libpng specification (typically not an integer).\n\n"); 10666 10667 printf("Expect this value to be less than .5 for 8 bit formats,\n"); 10668 printf("less than 1 for formats with fewer than 8 bits and a small\n"); 10669 printf("number (typically less than 5) for the 16 bit formats.\n"); 10670 printf("For performance reasons the value for 16 bit formats\n"); 10671 printf("increases when the image file includes an sBIT chunk.\n"); 10672 fflush(stdout); 10673 } 10674 10675 init_gamma_errors(pm); 10676 /*TODO: remove this. Necessary because the current libpng 10677 * implementation works in 8 bits: 10678 */ 10679 if (pm->test_gamma_expand16) 10680 pm->calculations_use_input_precision = 1; 10681 perform_gamma_transform_tests(pm); 10682 if (!calculations_use_input_precision) 10683 pm->calculations_use_input_precision = 0; 10684 10685 if (summary) 10686 summarize_gamma_errors(pm, 0/*who*/, 1/*low bit depth*/, 1/*indexed*/); 10687 10688 if (fail(pm)) 10689 return; 10690 } 10691 10692 /* The sbit tests produce much larger errors: */ 10693 if (pm->test_gamma_sbit) 10694 { 10695 init_gamma_errors(pm); 10696 perform_gamma_sbit_tests(pm); 10697 10698 if (summary) 10699 summarize_gamma_errors(pm, "sBIT", pm->sbitlow < 8U, 1/*indexed*/); 10700 10701 if (fail(pm)) 10702 return; 10703 } 10704 10705 #ifdef DO_16BIT /* Should be READ_16BIT_SUPPORTED */ 10706 if (pm->test_gamma_scale16) 10707 { 10708 /* The 16 to 8 bit strip operations: */ 10709 init_gamma_errors(pm); 10710 perform_gamma_scale16_tests(pm); 10711 10712 if (summary) 10713 { 10714 fflush(stderr); 10715 printf("\nGamma correction with 16 to 8 bit reduction:\n"); 10716 printf(" 16 bit gray: %.5f\n", pm->error_gray_16); 10717 printf(" 16 bit color: %.5f\n", pm->error_color_16); 10718 fflush(stdout); 10719 } 10720 10721 if (fail(pm)) 10722 return; 10723 } 10724 #endif 10725 10726 #ifdef PNG_READ_BACKGROUND_SUPPORTED 10727 if (pm->test_gamma_background) 10728 { 10729 init_gamma_errors(pm); 10730 10731 /*TODO: remove this. Necessary because the current libpng 10732 * implementation works in 8 bits: 10733 */ 10734 if (pm->test_gamma_expand16) 10735 { 10736 pm->calculations_use_input_precision = 1; 10737 pm->maxout8 = .499; /* because the 16 bit background is smashed */ 10738 } 10739 perform_gamma_composition_tests(pm, PNG_BACKGROUND_GAMMA_UNIQUE, 10740 pm->test_gamma_expand16); 10741 if (!calculations_use_input_precision) 10742 pm->calculations_use_input_precision = 0; 10743 pm->maxout8 = maxout8; 10744 10745 if (summary) 10746 summarize_gamma_errors(pm, "background", 1, 0/*indexed*/); 10747 10748 if (fail(pm)) 10749 return; 10750 } 10751 #endif 10752 10753 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED 10754 if (pm->test_gamma_alpha_mode) 10755 { 10756 int do_background; 10757 10758 init_gamma_errors(pm); 10759 10760 /*TODO: remove this. Necessary because the current libpng 10761 * implementation works in 8 bits: 10762 */ 10763 if (pm->test_gamma_expand16) 10764 pm->calculations_use_input_precision = 1; 10765 for (do_background = ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD; 10766 do_background <= ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN && !fail(pm); 10767 ++do_background) 10768 perform_gamma_composition_tests(pm, do_background, 10769 pm->test_gamma_expand16); 10770 if (!calculations_use_input_precision) 10771 pm->calculations_use_input_precision = 0; 10772 10773 if (summary) 10774 summarize_gamma_errors(pm, "alpha mode", 1, 0/*indexed*/); 10775 10776 if (fail(pm)) 10777 return; 10778 } 10779 #endif 10780 } 10781 #endif /* PNG_READ_GAMMA_SUPPORTED */ 10782 #endif /* PNG_READ_SUPPORTED */ 10783 10784 /* INTERLACE MACRO VALIDATION */ 10785 /* This is copied verbatim from the specification, it is simply the pass 10786 * number in which each pixel in each 8x8 tile appears. The array must 10787 * be indexed adam7[y][x] and notice that the pass numbers are based at 10788 * 1, not 0 - the base libpng uses. 10789 */ 10790 static const 10791 png_byte adam7[8][8] = 10792 { 10793 { 1,6,4,6,2,6,4,6 }, 10794 { 7,7,7,7,7,7,7,7 }, 10795 { 5,6,5,6,5,6,5,6 }, 10796 { 7,7,7,7,7,7,7,7 }, 10797 { 3,6,4,6,3,6,4,6 }, 10798 { 7,7,7,7,7,7,7,7 }, 10799 { 5,6,5,6,5,6,5,6 }, 10800 { 7,7,7,7,7,7,7,7 } 10801 }; 10802 10803 /* This routine validates all the interlace support macros in png.h for 10804 * a variety of valid PNG widths and heights. It uses a number of similarly 10805 * named internal routines that feed off the above array. 10806 */ 10807 static png_uint_32 10808 png_pass_start_row(int pass) 10809 { 10810 int x, y; 10811 ++pass; 10812 for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) 10813 return y; 10814 return 0xf; 10815 } 10816 10817 static png_uint_32 10818 png_pass_start_col(int pass) 10819 { 10820 int x, y; 10821 ++pass; 10822 for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) 10823 return x; 10824 return 0xf; 10825 } 10826 10827 static int 10828 png_pass_row_shift(int pass) 10829 { 10830 int x, y, base=(-1), inc=8; 10831 ++pass; 10832 for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) 10833 { 10834 if (base == (-1)) 10835 base = y; 10836 else if (base == y) 10837 {} 10838 else if (inc == y-base) 10839 base=y; 10840 else if (inc == 8) 10841 inc = y-base, base=y; 10842 else if (inc != y-base) 10843 return 0xff; /* error - more than one 'inc' value! */ 10844 } 10845 10846 if (base == (-1)) return 0xfe; /* error - no row in pass! */ 10847 10848 /* The shift is always 1, 2 or 3 - no pass has all the rows! */ 10849 switch (inc) 10850 { 10851 case 2: return 1; 10852 case 4: return 2; 10853 case 8: return 3; 10854 default: break; 10855 } 10856 10857 /* error - unrecognized 'inc' */ 10858 return (inc << 8) + 0xfd; 10859 } 10860 10861 static int 10862 png_pass_col_shift(int pass) 10863 { 10864 int x, y, base=(-1), inc=8; 10865 ++pass; 10866 for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) 10867 { 10868 if (base == (-1)) 10869 base = x; 10870 else if (base == x) 10871 {} 10872 else if (inc == x-base) 10873 base=x; 10874 else if (inc == 8) 10875 inc = x-base, base=x; 10876 else if (inc != x-base) 10877 return 0xff; /* error - more than one 'inc' value! */ 10878 } 10879 10880 if (base == (-1)) return 0xfe; /* error - no row in pass! */ 10881 10882 /* The shift is always 1, 2 or 3 - no pass has all the rows! */ 10883 switch (inc) 10884 { 10885 case 1: return 0; /* pass 7 has all the columns */ 10886 case 2: return 1; 10887 case 4: return 2; 10888 case 8: return 3; 10889 default: break; 10890 } 10891 10892 /* error - unrecognized 'inc' */ 10893 return (inc << 8) + 0xfd; 10894 } 10895 10896 static png_uint_32 10897 png_row_from_pass_row(png_uint_32 yIn, int pass) 10898 { 10899 /* By examination of the array: */ 10900 switch (pass) 10901 { 10902 case 0: return yIn * 8; 10903 case 1: return yIn * 8; 10904 case 2: return yIn * 8 + 4; 10905 case 3: return yIn * 4; 10906 case 4: return yIn * 4 + 2; 10907 case 5: return yIn * 2; 10908 case 6: return yIn * 2 + 1; 10909 default: break; 10910 } 10911 10912 return 0xff; /* bad pass number */ 10913 } 10914 10915 static png_uint_32 10916 png_col_from_pass_col(png_uint_32 xIn, int pass) 10917 { 10918 /* By examination of the array: */ 10919 switch (pass) 10920 { 10921 case 0: return xIn * 8; 10922 case 1: return xIn * 8 + 4; 10923 case 2: return xIn * 4; 10924 case 3: return xIn * 4 + 2; 10925 case 4: return xIn * 2; 10926 case 5: return xIn * 2 + 1; 10927 case 6: return xIn; 10928 default: break; 10929 } 10930 10931 return 0xff; /* bad pass number */ 10932 } 10933 10934 static int 10935 png_row_in_interlace_pass(png_uint_32 y, int pass) 10936 { 10937 /* Is row 'y' in pass 'pass'? */ 10938 int x; 10939 y &= 7; 10940 ++pass; 10941 for (x=0; x<8; ++x) if (adam7[y][x] == pass) 10942 return 1; 10943 10944 return 0; 10945 } 10946 10947 static int 10948 png_col_in_interlace_pass(png_uint_32 x, int pass) 10949 { 10950 /* Is column 'x' in pass 'pass'? */ 10951 int y; 10952 x &= 7; 10953 ++pass; 10954 for (y=0; y<8; ++y) if (adam7[y][x] == pass) 10955 return 1; 10956 10957 return 0; 10958 } 10959 10960 static png_uint_32 10961 png_pass_rows(png_uint_32 height, int pass) 10962 { 10963 png_uint_32 tiles = height>>3; 10964 png_uint_32 rows = 0; 10965 unsigned int x, y; 10966 10967 height &= 7; 10968 ++pass; 10969 for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) 10970 { 10971 rows += tiles; 10972 if (y < height) ++rows; 10973 break; /* i.e. break the 'x', column, loop. */ 10974 } 10975 10976 return rows; 10977 } 10978 10979 static png_uint_32 10980 png_pass_cols(png_uint_32 width, int pass) 10981 { 10982 png_uint_32 tiles = width>>3; 10983 png_uint_32 cols = 0; 10984 unsigned int x, y; 10985 10986 width &= 7; 10987 ++pass; 10988 for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) 10989 { 10990 cols += tiles; 10991 if (x < width) ++cols; 10992 break; /* i.e. break the 'y', row, loop. */ 10993 } 10994 10995 return cols; 10996 } 10997 10998 static void 10999 perform_interlace_macro_validation(void) 11000 { 11001 /* The macros to validate, first those that depend only on pass: 11002 * 11003 * PNG_PASS_START_ROW(pass) 11004 * PNG_PASS_START_COL(pass) 11005 * PNG_PASS_ROW_SHIFT(pass) 11006 * PNG_PASS_COL_SHIFT(pass) 11007 */ 11008 int pass; 11009 11010 for (pass=0; pass<7; ++pass) 11011 { 11012 png_uint_32 m, f, v; 11013 11014 m = PNG_PASS_START_ROW(pass); 11015 f = png_pass_start_row(pass); 11016 if (m != f) 11017 { 11018 fprintf(stderr, "PNG_PASS_START_ROW(%d) = %u != %x\n", pass, m, f); 11019 exit(99); 11020 } 11021 11022 m = PNG_PASS_START_COL(pass); 11023 f = png_pass_start_col(pass); 11024 if (m != f) 11025 { 11026 fprintf(stderr, "PNG_PASS_START_COL(%d) = %u != %x\n", pass, m, f); 11027 exit(99); 11028 } 11029 11030 m = PNG_PASS_ROW_SHIFT(pass); 11031 f = png_pass_row_shift(pass); 11032 if (m != f) 11033 { 11034 fprintf(stderr, "PNG_PASS_ROW_SHIFT(%d) = %u != %x\n", pass, m, f); 11035 exit(99); 11036 } 11037 11038 m = PNG_PASS_COL_SHIFT(pass); 11039 f = png_pass_col_shift(pass); 11040 if (m != f) 11041 { 11042 fprintf(stderr, "PNG_PASS_COL_SHIFT(%d) = %u != %x\n", pass, m, f); 11043 exit(99); 11044 } 11045 11046 /* Macros that depend on the image or sub-image height too: 11047 * 11048 * PNG_PASS_ROWS(height, pass) 11049 * PNG_PASS_COLS(width, pass) 11050 * PNG_ROW_FROM_PASS_ROW(yIn, pass) 11051 * PNG_COL_FROM_PASS_COL(xIn, pass) 11052 * PNG_ROW_IN_INTERLACE_PASS(y, pass) 11053 * PNG_COL_IN_INTERLACE_PASS(x, pass) 11054 */ 11055 for (v=0;;) 11056 { 11057 /* First the base 0 stuff: */ 11058 m = PNG_ROW_FROM_PASS_ROW(v, pass); 11059 f = png_row_from_pass_row(v, pass); 11060 if (m != f) 11061 { 11062 fprintf(stderr, "PNG_ROW_FROM_PASS_ROW(%u, %d) = %u != %x\n", 11063 v, pass, m, f); 11064 exit(99); 11065 } 11066 11067 m = PNG_COL_FROM_PASS_COL(v, pass); 11068 f = png_col_from_pass_col(v, pass); 11069 if (m != f) 11070 { 11071 fprintf(stderr, "PNG_COL_FROM_PASS_COL(%u, %d) = %u != %x\n", 11072 v, pass, m, f); 11073 exit(99); 11074 } 11075 11076 m = PNG_ROW_IN_INTERLACE_PASS(v, pass); 11077 f = png_row_in_interlace_pass(v, pass); 11078 if (m != f) 11079 { 11080 fprintf(stderr, "PNG_ROW_IN_INTERLACE_PASS(%u, %d) = %u != %x\n", 11081 v, pass, m, f); 11082 exit(99); 11083 } 11084 11085 m = PNG_COL_IN_INTERLACE_PASS(v, pass); 11086 f = png_col_in_interlace_pass(v, pass); 11087 if (m != f) 11088 { 11089 fprintf(stderr, "PNG_COL_IN_INTERLACE_PASS(%u, %d) = %u != %x\n", 11090 v, pass, m, f); 11091 exit(99); 11092 } 11093 11094 /* Then the base 1 stuff: */ 11095 ++v; 11096 m = PNG_PASS_ROWS(v, pass); 11097 f = png_pass_rows(v, pass); 11098 if (m != f) 11099 { 11100 fprintf(stderr, "PNG_PASS_ROWS(%u, %d) = %u != %x\n", 11101 v, pass, m, f); 11102 exit(99); 11103 } 11104 11105 m = PNG_PASS_COLS(v, pass); 11106 f = png_pass_cols(v, pass); 11107 if (m != f) 11108 { 11109 fprintf(stderr, "PNG_PASS_COLS(%u, %d) = %u != %x\n", 11110 v, pass, m, f); 11111 exit(99); 11112 } 11113 11114 /* Move to the next v - the stepping algorithm starts skipping 11115 * values above 1024. 11116 */ 11117 if (v > 1024) 11118 { 11119 if (v == PNG_UINT_31_MAX) 11120 break; 11121 11122 v = (v << 1) ^ v; 11123 if (v >= PNG_UINT_31_MAX) 11124 v = PNG_UINT_31_MAX-1; 11125 } 11126 } 11127 } 11128 } 11129 11130 /* Test color encodings. These values are back-calculated from the published 11131 * chromaticities. The values are accurate to about 14 decimal places; 15 are 11132 * given. These values are much more accurate than the ones given in the spec, 11133 * which typically don't exceed 4 decimal places. This allows testing of the 11134 * libpng code to its theoretical accuracy of 4 decimal places. (If pngvalid 11135 * used the published errors the 'slack' permitted would have to be +/-.5E-4 or 11136 * more.) 11137 * 11138 * The png_modifier code assumes that encodings[0] is sRGB and treats it 11139 * specially: do not change the first entry in this list! 11140 */ 11141 static const color_encoding test_encodings[] = 11142 { 11143 /* sRGB: must be first in this list! */ 11144 /*gamma:*/ { 1/2.2, 11145 /*red: */ { 0.412390799265959, 0.212639005871510, 0.019330818715592 }, 11146 /*green:*/ { 0.357584339383878, 0.715168678767756, 0.119194779794626 }, 11147 /*blue: */ { 0.180480788401834, 0.072192315360734, 0.950532152249660} }, 11148 /* Kodak ProPhoto (wide gamut) */ 11149 /*gamma:*/ { 1/1.6 /*approximate: uses 1.8 power law compared to sRGB 2.4*/, 11150 /*red: */ { 0.797760489672303, 0.288071128229293, 0.000000000000000 }, 11151 /*green:*/ { 0.135185837175740, 0.711843217810102, 0.000000000000000 }, 11152 /*blue: */ { 0.031349349581525, 0.000085653960605, 0.825104602510460} }, 11153 /* Adobe RGB (1998) */ 11154 /*gamma:*/ { 1/(2+51./256), 11155 /*red: */ { 0.576669042910131, 0.297344975250536, 0.027031361386412 }, 11156 /*green:*/ { 0.185558237906546, 0.627363566255466, 0.070688852535827 }, 11157 /*blue: */ { 0.188228646234995, 0.075291458493998, 0.991337536837639} }, 11158 /* Adobe Wide Gamut RGB */ 11159 /*gamma:*/ { 1/(2+51./256), 11160 /*red: */ { 0.716500716779386, 0.258728243040113, 0.000000000000000 }, 11161 /*green:*/ { 0.101020574397477, 0.724682314948566, 0.051211818965388 }, 11162 /*blue: */ { 0.146774385252705, 0.016589442011321, 0.773892783545073} }, 11163 /* Fake encoding which selects just the green channel */ 11164 /*gamma:*/ { 1.45/2.2, /* the 'Mac' gamma */ 11165 /*red: */ { 0.716500716779386, 0.000000000000000, 0.000000000000000 }, 11166 /*green:*/ { 0.101020574397477, 1.000000000000000, 0.051211818965388 }, 11167 /*blue: */ { 0.146774385252705, 0.000000000000000, 0.773892783545073} }, 11168 }; 11169 11170 /* signal handler 11171 * 11172 * This attempts to trap signals and escape without crashing. It needs a 11173 * context pointer so that it can throw an exception (call longjmp) to recover 11174 * from the condition; this is handled by making the png_modifier used by 'main' 11175 * into a global variable. 11176 */ 11177 static png_modifier pm; 11178 11179 static void signal_handler(int signum) 11180 { 11181 11182 size_t pos = 0; 11183 char msg[64]; 11184 11185 pos = safecat(msg, sizeof msg, pos, "caught signal: "); 11186 11187 switch (signum) 11188 { 11189 case SIGABRT: 11190 pos = safecat(msg, sizeof msg, pos, "abort"); 11191 break; 11192 11193 case SIGFPE: 11194 pos = safecat(msg, sizeof msg, pos, "floating point exception"); 11195 break; 11196 11197 case SIGILL: 11198 pos = safecat(msg, sizeof msg, pos, "illegal instruction"); 11199 break; 11200 11201 case SIGINT: 11202 pos = safecat(msg, sizeof msg, pos, "interrupt"); 11203 break; 11204 11205 case SIGSEGV: 11206 pos = safecat(msg, sizeof msg, pos, "invalid memory access"); 11207 break; 11208 11209 case SIGTERM: 11210 pos = safecat(msg, sizeof msg, pos, "termination request"); 11211 break; 11212 11213 default: 11214 pos = safecat(msg, sizeof msg, pos, "unknown "); 11215 pos = safecatn(msg, sizeof msg, pos, signum); 11216 break; 11217 } 11218 11219 store_log(&pm.this, NULL/*png_structp*/, msg, 1/*error*/); 11220 11221 /* And finally throw an exception so we can keep going, unless this is 11222 * SIGTERM in which case stop now. 11223 */ 11224 if (signum != SIGTERM) 11225 { 11226 struct exception_context *the_exception_context = 11227 &pm.this.exception_context; 11228 11229 Throw &pm.this; 11230 } 11231 11232 else 11233 exit(1); 11234 } 11235 11236 /* main program */ 11237 int main(int argc, char **argv) 11238 { 11239 int summary = 1; /* Print the error summary at the end */ 11240 int memstats = 0; /* Print memory statistics at the end */ 11241 11242 /* Create the given output file on success: */ 11243 const char *touch = NULL; 11244 11245 /* This is an array of standard gamma values (believe it or not I've seen 11246 * every one of these mentioned somewhere.) 11247 * 11248 * In the following list the most useful values are first! 11249 */ 11250 static double 11251 gammas[]={2.2, 1.0, 2.2/1.45, 1.8, 1.5, 2.4, 2.5, 2.62, 2.9}; 11252 11253 /* This records the command and arguments: */ 11254 size_t cp = 0; 11255 char command[1024]; 11256 11257 anon_context(&pm.this); 11258 11259 gnu_volatile(summary) 11260 gnu_volatile(memstats) 11261 gnu_volatile(touch) 11262 11263 /* Add appropriate signal handlers, just the ANSI specified ones: */ 11264 signal(SIGABRT, signal_handler); 11265 signal(SIGFPE, signal_handler); 11266 signal(SIGILL, signal_handler); 11267 signal(SIGINT, signal_handler); 11268 signal(SIGSEGV, signal_handler); 11269 signal(SIGTERM, signal_handler); 11270 11271 #ifdef HAVE_FEENABLEEXCEPT 11272 /* Only required to enable FP exceptions on platforms where they start off 11273 * disabled; this is not necessary but if it is not done pngvalid will likely 11274 * end up ignoring FP conditions that other platforms fault. 11275 */ 11276 feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); 11277 #endif 11278 11279 modifier_init(&pm); 11280 11281 /* Preallocate the image buffer, because we know how big it needs to be, 11282 * note that, for testing purposes, it is deliberately mis-aligned by tag 11283 * bytes either side. All rows have an additional five bytes of padding for 11284 * overwrite checking. 11285 */ 11286 store_ensure_image(&pm.this, NULL, 2, TRANSFORM_ROWMAX, TRANSFORM_HEIGHTMAX); 11287 11288 /* Don't give argv[0], it's normally some horrible libtool string: */ 11289 cp = safecat(command, sizeof command, cp, "pngvalid"); 11290 11291 /* Default to error on warning: */ 11292 pm.this.treat_warnings_as_errors = 1; 11293 11294 /* Default assume_16_bit_calculations appropriately; this tells the checking 11295 * code that 16-bit arithmetic is used for 8-bit samples when it would make a 11296 * difference. 11297 */ 11298 pm.assume_16_bit_calculations = PNG_LIBPNG_VER >= 10700; 11299 11300 /* Currently 16 bit expansion happens at the end of the pipeline, so the 11301 * calculations are done in the input bit depth not the output. 11302 * 11303 * TODO: fix this 11304 */ 11305 pm.calculations_use_input_precision = 1U; 11306 11307 /* Store the test gammas */ 11308 pm.gammas = gammas; 11309 pm.ngammas = ARRAY_SIZE(gammas); 11310 pm.ngamma_tests = 0; /* default to off */ 11311 11312 /* Low bit depth gray images don't do well in the gamma tests, until 11313 * this is fixed turn them off for some gamma cases: 11314 */ 11315 # ifdef PNG_WRITE_tRNS_SUPPORTED 11316 pm.test_tRNS = 1; 11317 # endif 11318 pm.test_lbg = PNG_LIBPNG_VER >= 10600; 11319 pm.test_lbg_gamma_threshold = 1; 11320 pm.test_lbg_gamma_transform = PNG_LIBPNG_VER >= 10600; 11321 pm.test_lbg_gamma_sbit = 1; 11322 pm.test_lbg_gamma_composition = PNG_LIBPNG_VER >= 10700; 11323 11324 /* And the test encodings */ 11325 pm.encodings = test_encodings; 11326 pm.nencodings = ARRAY_SIZE(test_encodings); 11327 11328 # if PNG_LIBPNG_VER < 10700 11329 pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */ 11330 # else 11331 pm.sbitlow = 1U; 11332 # endif 11333 11334 /* The following allows results to pass if they correspond to anything in the 11335 * transformed range [input-.5,input+.5]; this is is required because of the 11336 * way libpng treates the 16_TO_8 flag when building the gamma tables in 11337 * releases up to 1.6.0. 11338 * 11339 * TODO: review this 11340 */ 11341 pm.use_input_precision_16to8 = 1U; 11342 pm.use_input_precision_sbit = 1U; /* because libpng now rounds sBIT */ 11343 11344 /* Some default values (set the behavior for 'make check' here). 11345 * These values simply control the maximum error permitted in the gamma 11346 * transformations. The practial limits for human perception are described 11347 * below (the setting for maxpc16), however for 8 bit encodings it isn't 11348 * possible to meet the accepted capabilities of human vision - i.e. 8 bit 11349 * images can never be good enough, regardless of encoding. 11350 */ 11351 pm.maxout8 = .1; /* Arithmetic error in *encoded* value */ 11352 pm.maxabs8 = .00005; /* 1/20000 */ 11353 pm.maxcalc8 = 1./255; /* +/-1 in 8 bits for compose errors */ 11354 pm.maxpc8 = .499; /* I.e., .499% fractional error */ 11355 pm.maxout16 = .499; /* Error in *encoded* value */ 11356 pm.maxabs16 = .00005;/* 1/20000 */ 11357 pm.maxcalc16 =1./65535;/* +/-1 in 16 bits for compose errors */ 11358 # if PNG_LIBPNG_VER < 10700 11359 pm.maxcalcG = 1./((1<<PNG_MAX_GAMMA_8)-1); 11360 # else 11361 pm.maxcalcG = 1./((1<<16)-1); 11362 # endif 11363 11364 /* NOTE: this is a reasonable perceptual limit. We assume that humans can 11365 * perceive light level differences of 1% over a 100:1 range, so we need to 11366 * maintain 1 in 10000 accuracy (in linear light space), which is what the 11367 * following guarantees. It also allows significantly higher errors at 11368 * higher 16 bit values, which is important for performance. The actual 11369 * maximum 16 bit error is about +/-1.9 in the fixed point implementation but 11370 * this is only allowed for values >38149 by the following: 11371 */ 11372 pm.maxpc16 = .005; /* I.e., 1/200% - 1/20000 */ 11373 11374 /* Now parse the command line options. */ 11375 while (--argc >= 1) 11376 { 11377 int catmore = 0; /* Set if the argument has an argument. */ 11378 11379 /* Record each argument for posterity: */ 11380 cp = safecat(command, sizeof command, cp, " "); 11381 cp = safecat(command, sizeof command, cp, *++argv); 11382 11383 if (strcmp(*argv, "-v") == 0) 11384 pm.this.verbose = 1; 11385 11386 else if (strcmp(*argv, "-l") == 0) 11387 pm.log = 1; 11388 11389 else if (strcmp(*argv, "-q") == 0) 11390 summary = pm.this.verbose = pm.log = 0; 11391 11392 else if (strcmp(*argv, "-w") == 0 || 11393 strcmp(*argv, "--strict") == 0) 11394 pm.this.treat_warnings_as_errors = 1; /* NOTE: this is the default! */ 11395 11396 else if (strcmp(*argv, "--nostrict") == 0) 11397 pm.this.treat_warnings_as_errors = 0; 11398 11399 else if (strcmp(*argv, "--speed") == 0) 11400 pm.this.speed = 1, pm.ngamma_tests = pm.ngammas, pm.test_standard = 0, 11401 summary = 0; 11402 11403 else if (strcmp(*argv, "--memory") == 0) 11404 memstats = 1; 11405 11406 else if (strcmp(*argv, "--size") == 0) 11407 pm.test_size = 1; 11408 11409 else if (strcmp(*argv, "--nosize") == 0) 11410 pm.test_size = 0; 11411 11412 else if (strcmp(*argv, "--standard") == 0) 11413 pm.test_standard = 1; 11414 11415 else if (strcmp(*argv, "--nostandard") == 0) 11416 pm.test_standard = 0; 11417 11418 else if (strcmp(*argv, "--transform") == 0) 11419 pm.test_transform = 1; 11420 11421 else if (strcmp(*argv, "--notransform") == 0) 11422 pm.test_transform = 0; 11423 11424 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 11425 else if (strncmp(*argv, "--transform-disable=", 11426 sizeof "--transform-disable") == 0) 11427 { 11428 pm.test_transform = 1; 11429 transform_disable(*argv + sizeof "--transform-disable"); 11430 } 11431 11432 else if (strncmp(*argv, "--transform-enable=", 11433 sizeof "--transform-enable") == 0) 11434 { 11435 pm.test_transform = 1; 11436 transform_enable(*argv + sizeof "--transform-enable"); 11437 } 11438 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 11439 11440 else if (strcmp(*argv, "--gamma") == 0) 11441 { 11442 /* Just do two gamma tests here (2.2 and linear) for speed: */ 11443 pm.ngamma_tests = 2U; 11444 pm.test_gamma_threshold = 1; 11445 pm.test_gamma_transform = 1; 11446 pm.test_gamma_sbit = 1; 11447 pm.test_gamma_scale16 = 1; 11448 pm.test_gamma_background = 1; /* composition */ 11449 pm.test_gamma_alpha_mode = 1; 11450 } 11451 11452 else if (strcmp(*argv, "--nogamma") == 0) 11453 pm.ngamma_tests = 0; 11454 11455 else if (strcmp(*argv, "--gamma-threshold") == 0) 11456 pm.ngamma_tests = 2U, pm.test_gamma_threshold = 1; 11457 11458 else if (strcmp(*argv, "--nogamma-threshold") == 0) 11459 pm.test_gamma_threshold = 0; 11460 11461 else if (strcmp(*argv, "--gamma-transform") == 0) 11462 pm.ngamma_tests = 2U, pm.test_gamma_transform = 1; 11463 11464 else if (strcmp(*argv, "--nogamma-transform") == 0) 11465 pm.test_gamma_transform = 0; 11466 11467 else if (strcmp(*argv, "--gamma-sbit") == 0) 11468 pm.ngamma_tests = 2U, pm.test_gamma_sbit = 1; 11469 11470 else if (strcmp(*argv, "--nogamma-sbit") == 0) 11471 pm.test_gamma_sbit = 0; 11472 11473 else if (strcmp(*argv, "--gamma-16-to-8") == 0) 11474 pm.ngamma_tests = 2U, pm.test_gamma_scale16 = 1; 11475 11476 else if (strcmp(*argv, "--nogamma-16-to-8") == 0) 11477 pm.test_gamma_scale16 = 0; 11478 11479 else if (strcmp(*argv, "--gamma-background") == 0) 11480 pm.ngamma_tests = 2U, pm.test_gamma_background = 1; 11481 11482 else if (strcmp(*argv, "--nogamma-background") == 0) 11483 pm.test_gamma_background = 0; 11484 11485 else if (strcmp(*argv, "--gamma-alpha-mode") == 0) 11486 pm.ngamma_tests = 2U, pm.test_gamma_alpha_mode = 1; 11487 11488 else if (strcmp(*argv, "--nogamma-alpha-mode") == 0) 11489 pm.test_gamma_alpha_mode = 0; 11490 11491 else if (strcmp(*argv, "--expand16") == 0) 11492 pm.test_gamma_expand16 = 1; 11493 11494 else if (strcmp(*argv, "--noexpand16") == 0) 11495 pm.test_gamma_expand16 = 0; 11496 11497 else if (strcmp(*argv, "--low-depth-gray") == 0) 11498 pm.test_lbg = pm.test_lbg_gamma_threshold = 11499 pm.test_lbg_gamma_transform = pm.test_lbg_gamma_sbit = 11500 pm.test_lbg_gamma_composition = 1; 11501 11502 else if (strcmp(*argv, "--nolow-depth-gray") == 0) 11503 pm.test_lbg = pm.test_lbg_gamma_threshold = 11504 pm.test_lbg_gamma_transform = pm.test_lbg_gamma_sbit = 11505 pm.test_lbg_gamma_composition = 0; 11506 11507 # ifdef PNG_WRITE_tRNS_SUPPORTED 11508 else if (strcmp(*argv, "--tRNS") == 0) 11509 pm.test_tRNS = 1; 11510 # endif 11511 11512 else if (strcmp(*argv, "--notRNS") == 0) 11513 pm.test_tRNS = 0; 11514 11515 else if (strcmp(*argv, "--more-gammas") == 0) 11516 pm.ngamma_tests = 3U; 11517 11518 else if (strcmp(*argv, "--all-gammas") == 0) 11519 pm.ngamma_tests = pm.ngammas; 11520 11521 else if (strcmp(*argv, "--progressive-read") == 0) 11522 pm.this.progressive = 1; 11523 11524 else if (strcmp(*argv, "--use-update-info") == 0) 11525 ++pm.use_update_info; /* Can call multiple times */ 11526 11527 else if (strcmp(*argv, "--interlace") == 0) 11528 { 11529 # if CAN_WRITE_INTERLACE 11530 pm.interlace_type = PNG_INTERLACE_ADAM7; 11531 # else /* !CAN_WRITE_INTERLACE */ 11532 fprintf(stderr, "pngvalid: no write interlace support\n"); 11533 return SKIP; 11534 # endif /* !CAN_WRITE_INTERLACE */ 11535 } 11536 11537 else if (strcmp(*argv, "--use-input-precision") == 0) 11538 pm.use_input_precision = 1U; 11539 11540 else if (strcmp(*argv, "--use-calculation-precision") == 0) 11541 pm.use_input_precision = 0; 11542 11543 else if (strcmp(*argv, "--calculations-use-input-precision") == 0) 11544 pm.calculations_use_input_precision = 1U; 11545 11546 else if (strcmp(*argv, "--assume-16-bit-calculations") == 0) 11547 pm.assume_16_bit_calculations = 1U; 11548 11549 else if (strcmp(*argv, "--calculations-follow-bit-depth") == 0) 11550 pm.calculations_use_input_precision = 11551 pm.assume_16_bit_calculations = 0; 11552 11553 else if (strcmp(*argv, "--exhaustive") == 0) 11554 pm.test_exhaustive = 1; 11555 11556 else if (argc > 1 && strcmp(*argv, "--sbitlow") == 0) 11557 --argc, pm.sbitlow = (png_byte)atoi(*++argv), catmore = 1; 11558 11559 else if (argc > 1 && strcmp(*argv, "--touch") == 0) 11560 --argc, touch = *++argv, catmore = 1; 11561 11562 else if (argc > 1 && strncmp(*argv, "--max", 5) == 0) 11563 { 11564 --argc; 11565 11566 if (strcmp(5+*argv, "abs8") == 0) 11567 pm.maxabs8 = atof(*++argv); 11568 11569 else if (strcmp(5+*argv, "abs16") == 0) 11570 pm.maxabs16 = atof(*++argv); 11571 11572 else if (strcmp(5+*argv, "calc8") == 0) 11573 pm.maxcalc8 = atof(*++argv); 11574 11575 else if (strcmp(5+*argv, "calc16") == 0) 11576 pm.maxcalc16 = atof(*++argv); 11577 11578 else if (strcmp(5+*argv, "out8") == 0) 11579 pm.maxout8 = atof(*++argv); 11580 11581 else if (strcmp(5+*argv, "out16") == 0) 11582 pm.maxout16 = atof(*++argv); 11583 11584 else if (strcmp(5+*argv, "pc8") == 0) 11585 pm.maxpc8 = atof(*++argv); 11586 11587 else if (strcmp(5+*argv, "pc16") == 0) 11588 pm.maxpc16 = atof(*++argv); 11589 11590 else 11591 { 11592 fprintf(stderr, "pngvalid: %s: unknown 'max' option\n", *argv); 11593 exit(99); 11594 } 11595 11596 catmore = 1; 11597 } 11598 11599 else if (strcmp(*argv, "--log8") == 0) 11600 --argc, pm.log8 = atof(*++argv), catmore = 1; 11601 11602 else if (strcmp(*argv, "--log16") == 0) 11603 --argc, pm.log16 = atof(*++argv), catmore = 1; 11604 11605 #ifdef PNG_SET_OPTION_SUPPORTED 11606 else if (strncmp(*argv, "--option=", 9) == 0) 11607 { 11608 /* Syntax of the argument is <option>:{on|off} */ 11609 const char *arg = 9+*argv; 11610 unsigned char option=0, setting=0; 11611 11612 #ifdef PNG_ARM_NEON 11613 if (strncmp(arg, "arm-neon:", 9) == 0) 11614 option = PNG_ARM_NEON, arg += 9; 11615 11616 else 11617 #endif 11618 #ifdef PNG_EXTENSIONS 11619 if (strncmp(arg, "extensions:", 11) == 0) 11620 option = PNG_EXTENSIONS, arg += 11; 11621 11622 else 11623 #endif 11624 #ifdef PNG_MAXIMUM_INFLATE_WINDOW 11625 if (strncmp(arg, "max-inflate-window:", 19) == 0) 11626 option = PNG_MAXIMUM_INFLATE_WINDOW, arg += 19; 11627 11628 else 11629 #endif 11630 { 11631 fprintf(stderr, "pngvalid: %s: %s: unknown option\n", *argv, arg); 11632 exit(99); 11633 } 11634 11635 if (strcmp(arg, "off") == 0) 11636 setting = PNG_OPTION_OFF; 11637 11638 else if (strcmp(arg, "on") == 0) 11639 setting = PNG_OPTION_ON; 11640 11641 else 11642 { 11643 fprintf(stderr, 11644 "pngvalid: %s: %s: unknown setting (use 'on' or 'off')\n", 11645 *argv, arg); 11646 exit(99); 11647 } 11648 11649 pm.this.options[pm.this.noptions].option = option; 11650 pm.this.options[pm.this.noptions++].setting = setting; 11651 } 11652 #endif /* PNG_SET_OPTION_SUPPORTED */ 11653 11654 else 11655 { 11656 fprintf(stderr, "pngvalid: %s: unknown argument\n", *argv); 11657 exit(99); 11658 } 11659 11660 if (catmore) /* consumed an extra *argv */ 11661 { 11662 cp = safecat(command, sizeof command, cp, " "); 11663 cp = safecat(command, sizeof command, cp, *argv); 11664 } 11665 } 11666 11667 /* If pngvalid is run with no arguments default to a reasonable set of the 11668 * tests. 11669 */ 11670 if (pm.test_standard == 0 && pm.test_size == 0 && pm.test_transform == 0 && 11671 pm.ngamma_tests == 0) 11672 { 11673 /* Make this do all the tests done in the test shell scripts with the same 11674 * parameters, where possible. The limitation is that all the progressive 11675 * read and interlace stuff has to be done in separate runs, so only the 11676 * basic 'standard' and 'size' tests are done. 11677 */ 11678 pm.test_standard = 1; 11679 pm.test_size = 1; 11680 pm.test_transform = 1; 11681 pm.ngamma_tests = 2U; 11682 } 11683 11684 if (pm.ngamma_tests > 0 && 11685 pm.test_gamma_threshold == 0 && pm.test_gamma_transform == 0 && 11686 pm.test_gamma_sbit == 0 && pm.test_gamma_scale16 == 0 && 11687 pm.test_gamma_background == 0 && pm.test_gamma_alpha_mode == 0) 11688 { 11689 pm.test_gamma_threshold = 1; 11690 pm.test_gamma_transform = 1; 11691 pm.test_gamma_sbit = 1; 11692 pm.test_gamma_scale16 = 1; 11693 pm.test_gamma_background = 1; 11694 pm.test_gamma_alpha_mode = 1; 11695 } 11696 11697 else if (pm.ngamma_tests == 0) 11698 { 11699 /* Nothing to test so turn everything off: */ 11700 pm.test_gamma_threshold = 0; 11701 pm.test_gamma_transform = 0; 11702 pm.test_gamma_sbit = 0; 11703 pm.test_gamma_scale16 = 0; 11704 pm.test_gamma_background = 0; 11705 pm.test_gamma_alpha_mode = 0; 11706 } 11707 11708 Try 11709 { 11710 /* Make useful base images */ 11711 make_transform_images(&pm); 11712 11713 /* Perform the standard and gamma tests. */ 11714 if (pm.test_standard) 11715 { 11716 perform_interlace_macro_validation(); 11717 perform_formatting_test(&pm.this); 11718 # ifdef PNG_READ_SUPPORTED 11719 perform_standard_test(&pm); 11720 # endif 11721 perform_error_test(&pm); 11722 } 11723 11724 /* Various oddly sized images: */ 11725 if (pm.test_size) 11726 { 11727 make_size_images(&pm.this); 11728 # ifdef PNG_READ_SUPPORTED 11729 perform_size_test(&pm); 11730 # endif 11731 } 11732 11733 #ifdef PNG_READ_TRANSFORMS_SUPPORTED 11734 /* Combinatorial transforms: */ 11735 if (pm.test_transform) 11736 perform_transform_test(&pm); 11737 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 11738 11739 #ifdef PNG_READ_GAMMA_SUPPORTED 11740 if (pm.ngamma_tests > 0) 11741 perform_gamma_test(&pm, summary); 11742 #endif 11743 } 11744 11745 Catch_anonymous 11746 { 11747 fprintf(stderr, "pngvalid: test aborted (probably failed in cleanup)\n"); 11748 if (!pm.this.verbose) 11749 { 11750 if (pm.this.error[0] != 0) 11751 fprintf(stderr, "pngvalid: first error: %s\n", pm.this.error); 11752 11753 fprintf(stderr, "pngvalid: run with -v to see what happened\n"); 11754 } 11755 exit(1); 11756 } 11757 11758 if (summary) 11759 { 11760 printf("%s: %s (%s point arithmetic)\n", 11761 (pm.this.nerrors || (pm.this.treat_warnings_as_errors && 11762 pm.this.nwarnings)) ? "FAIL" : "PASS", 11763 command, 11764 #if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || PNG_LIBPNG_VER < 10500 11765 "floating" 11766 #else 11767 "fixed" 11768 #endif 11769 ); 11770 } 11771 11772 if (memstats) 11773 { 11774 printf("Allocated memory statistics (in bytes):\n" 11775 "\tread %lu maximum single, %lu peak, %lu total\n" 11776 "\twrite %lu maximum single, %lu peak, %lu total\n", 11777 (unsigned long)pm.this.read_memory_pool.max_max, 11778 (unsigned long)pm.this.read_memory_pool.max_limit, 11779 (unsigned long)pm.this.read_memory_pool.max_total, 11780 (unsigned long)pm.this.write_memory_pool.max_max, 11781 (unsigned long)pm.this.write_memory_pool.max_limit, 11782 (unsigned long)pm.this.write_memory_pool.max_total); 11783 } 11784 11785 /* Do this here to provoke memory corruption errors in memory not directly 11786 * allocated by libpng - not a complete test, but better than nothing. 11787 */ 11788 store_delete(&pm.this); 11789 11790 /* Error exit if there are any errors, and maybe if there are any 11791 * warnings. 11792 */ 11793 if (pm.this.nerrors || (pm.this.treat_warnings_as_errors && 11794 pm.this.nwarnings)) 11795 { 11796 if (!pm.this.verbose) 11797 fprintf(stderr, "pngvalid: %s\n", pm.this.error); 11798 11799 fprintf(stderr, "pngvalid: %d errors, %d warnings\n", pm.this.nerrors, 11800 pm.this.nwarnings); 11801 11802 exit(1); 11803 } 11804 11805 /* Success case. */ 11806 if (touch != NULL) 11807 { 11808 FILE *fsuccess = fopen(touch, "wt"); 11809 11810 if (fsuccess != NULL) 11811 { 11812 int error = 0; 11813 fprintf(fsuccess, "PNG validation succeeded\n"); 11814 fflush(fsuccess); 11815 error = ferror(fsuccess); 11816 11817 if (fclose(fsuccess) || error) 11818 { 11819 fprintf(stderr, "%s: write failed\n", touch); 11820 exit(1); 11821 } 11822 } 11823 11824 else 11825 { 11826 fprintf(stderr, "%s: open failed\n", touch); 11827 exit(1); 11828 } 11829 } 11830 11831 /* This is required because some very minimal configurations do not use it: 11832 */ 11833 UNUSED(fail) 11834 return 0; 11835 } 11836 #else /* write or low level APIs not supported */ 11837 int main(void) 11838 { 11839 fprintf(stderr, 11840 "pngvalid: no low level write support in libpng, all tests skipped\n"); 11841 /* So the test is skipped: */ 11842 return SKIP; 11843 } 11844 #endif 11845