1 /* pngcp.c 2 * 3 * Copyright (c) 2016 John Cunningham Bowler 4 * 5 * Last changed in libpng 1.6.24 [August 4, 2016] 6 * 7 * This code is released under the libpng license. 8 * For conditions of distribution and use, see the disclaimer 9 * and license in png.h 10 * 11 * This is an example of copying a PNG without changes using the png_read_png 12 * and png_write_png interfaces. A considerable number of options are provided 13 * to manipulate the compression of the PNG data and other compressed chunks. 14 * 15 * For a more extensive example that uses the transforms see 16 * contrib/libtests/pngimage.c in the libpng distribution. 17 */ 18 #include "pnglibconf.h" /* To find how libpng was configured. */ 19 20 #ifdef PNG_PNGCP_TIMING_SUPPORTED 21 /* WARNING: 22 * 23 * This test is here to allow POSIX.1b extensions to be used if enabled in 24 * the compile; specifically the code requires_POSIX_C_SOURCE support of 25 * 199309L or later to enable clock_gettime use. 26 * 27 * IF this causes problems THEN compile with a strict ANSI C compiler and let 28 * this code turn on the POSIX features that it minimally requires. 29 * 30 * IF this does not work there is probably a bug in your ANSI C compiler or 31 * your POSIX implementation. 32 */ 33 # define _POSIX_C_SOURCE 199309L 34 #else /* No timing support required */ 35 # define _POSIX_SOURCE 1 36 #endif 37 38 #if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) 39 # include <config.h> 40 #endif 41 42 #include <stdio.h> 43 44 /* Define the following to use this test against your installed libpng, rather 45 * than the one being built here: 46 */ 47 #ifdef PNG_FREESTANDING_TESTS 48 # include <png.h> 49 #else 50 # include "../../png.h" 51 #endif 52 53 #if PNG_LIBPNG_VER < 10700 54 /* READ_PNG and WRITE_PNG were not defined, so: */ 55 # ifdef PNG_INFO_IMAGE_SUPPORTED 56 # ifdef PNG_SEQUENTIAL_READ_SUPPORTED 57 # define PNG_READ_PNG_SUPPORTED 58 # endif /* SEQUENTIAL_READ */ 59 # ifdef PNG_WRITE_SUPPORTED 60 # define PNG_WRITE_PNG_SUPPORTED 61 # endif /* WRITE */ 62 # endif /* INFO_IMAGE */ 63 #endif /* pre 1.7.0 */ 64 65 #if (defined(PNG_READ_PNG_SUPPORTED)) && (defined(PNG_WRITE_PNG_SUPPORTED)) 66 #include <stdarg.h> 67 #include <stdlib.h> 68 #include <string.h> 69 #include <errno.h> 70 #include <limits.h> 71 #include <assert.h> 72 73 #include <unistd.h> 74 #include <sys/stat.h> 75 76 #include <zlib.h> 77 78 #ifndef PNG_SETJMP_SUPPORTED 79 # include <setjmp.h> /* because png.h did *not* include this */ 80 #endif 81 82 #ifdef __cplusplus 83 # define voidcast(type, value) static_cast<type>(value) 84 #else 85 # define voidcast(type, value) (value) 86 #endif /* __cplusplus */ 87 88 #ifdef __GNUC__ 89 /* Many versions of GCC erroneously report that local variables unmodified 90 * within the scope of a setjmp may be clobbered. This hacks round the 91 * problem (sometimes) without harming other compilers. 92 */ 93 # define gv volatile 94 #else 95 # define gv 96 #endif 97 98 /* 'CLOCK_PROCESS_CPUTIME_ID' is one of the clock timers for clock_gettime. It 99 * need not be supported even when clock_gettime is available. It returns the 100 * 'CPU' time the process has consumed. 'CPU' time is assumed to include time 101 * when the CPU is actually blocked by a pending cache fill but not time 102 * waiting for page faults. The attempt is to get a measure of the actual time 103 * the implementation takes to read a PNG ignoring the potentially very large IO 104 * overhead. 105 */ 106 #ifdef PNG_PNGCP_TIMING_SUPPORTED 107 # include <time.h> /* clock_gettime and associated definitions */ 108 # ifndef CLOCK_PROCESS_CPUTIME_ID 109 /* Prevent inclusion of the spurious code: */ 110 # undef PNG_PNGCP_TIMING_SUPPORTED 111 # endif 112 #endif /* PNGCP_TIMING */ 113 114 /* So if the timing feature has been activated: */ 115 116 /* This structure is used to control the test of a single file. */ 117 typedef enum 118 { 119 VERBOSE, /* switches on all messages */ 120 INFORMATION, 121 WARNINGS, /* switches on warnings */ 122 LIBPNG_WARNING, 123 APP_WARNING, 124 ERRORS, /* just errors */ 125 APP_FAIL, /* continuable error - no need to longjmp */ 126 LIBPNG_ERROR, /* this and higher cause a longjmp */ 127 LIBPNG_BUG, /* erroneous behavior in libpng */ 128 APP_ERROR, /* such as out-of-memory in a callback */ 129 QUIET, /* no normal messages */ 130 USER_ERROR, /* such as file-not-found */ 131 INTERNAL_ERROR 132 } error_level; 133 #define LEVEL_MASK 0xf /* where the level is in 'options' */ 134 135 #define STRICT 0x010 /* Fail on warnings as well as errors */ 136 #define LOG 0x020 /* Log pass/fail to stdout */ 137 #define CONTINUE 0x040 /* Continue on APP_FAIL errors */ 138 #define SIZES 0x080 /* Report input and output sizes */ 139 #define SEARCH 0x100 /* Search IDAT compression options */ 140 #define NOWRITE 0x200 /* Do not write an output file */ 141 #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED 142 # define IGNORE_INDEX 0x400 /* Ignore out of range palette indices (BAD!) */ 143 # ifdef PNG_GET_PALETTE_MAX_SUPPORTED 144 # define FIX_INDEX 0x800 /* 'Fix' out of range palette indices (OK) */ 145 # endif /* GET_PALETTE_MAX */ 146 #endif /* CHECK_FOR_INVALID_INDEX */ 147 #define OPTION 0x80000000 /* Used for handling options */ 148 #define LIST 0x80000001 /* Used for handling options */ 149 150 /* Result masks apply to the result bits in the 'results' field below; these 151 * bits are simple 1U<<error_level. A pass requires either nothing worse than 152 * warnings (--relaxes) or nothing worse than information (--strict) 153 */ 154 #define RESULT_STRICT(r) (((r) & ~((1U<<WARNINGS)-1)) == 0) 155 #define RESULT_RELAXED(r) (((r) & ~((1U<<ERRORS)-1)) == 0) 156 157 /* OPTION DEFINITIONS */ 158 static const char range_lo[] = "low"; 159 static const char range_hi[] = "high"; 160 static const char all[] = "all"; 161 #define RANGE(lo,hi) { range_lo, lo }, { range_hi, hi } 162 typedef struct value_list 163 { 164 const char *name; /* the command line name of the value */ 165 int value; /* the actual value to use */ 166 } value_list; 167 168 static const value_list 169 #ifdef PNG_SW_COMPRESS_png_level 170 vl_compression[] = 171 { 172 /* Overall compression control. The order controls the search order for 173 * 'all'. Since the search is for the smallest the order used is low memory 174 * then high speed. 175 */ 176 { "low-memory", PNG_COMPRESSION_LOW_MEMORY }, 177 { "high-speed", PNG_COMPRESSION_HIGH_SPEED }, 178 { "high-read-speed", PNG_COMPRESSION_HIGH_READ_SPEED }, 179 { "low", PNG_COMPRESSION_LOW }, 180 { "medium", PNG_COMPRESSION_MEDIUM }, 181 { "old", PNG_COMPRESSION_COMPAT }, 182 { "high", PNG_COMPRESSION_HIGH }, 183 { all, 0 } 184 }, 185 #endif /* SW_COMPRESS_png_level */ 186 187 #if defined(PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED) ||\ 188 defined(PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED) 189 vl_strategy[] = 190 { 191 /* This controls the order of search. */ 192 { "huffman", Z_HUFFMAN_ONLY }, 193 { "RLE", Z_RLE }, 194 { "fixed", Z_FIXED }, /* the remainder do window searchs */ 195 { "filtered", Z_FILTERED }, 196 { "default", Z_DEFAULT_STRATEGY }, 197 { all, 0 } 198 }, 199 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED 200 vl_windowBits_text[] = 201 { 202 { "default", MAX_WBITS/*from zlib*/ }, 203 { "minimum", 8 }, 204 RANGE(8, MAX_WBITS/*from zlib*/), 205 { all, 0 } 206 }, 207 #endif /* text compression */ 208 vl_level[] = 209 { 210 { "default", Z_DEFAULT_COMPRESSION /* this is -1 */ }, 211 { "none", Z_NO_COMPRESSION }, 212 { "speed", Z_BEST_SPEED }, 213 { "best", Z_BEST_COMPRESSION }, 214 { "0", Z_NO_COMPRESSION }, 215 RANGE(1, 9), /* this deliberately excludes '0' */ 216 { all, 0 } 217 }, 218 vl_memLevel[] = 219 { 220 { "max", MAX_MEM_LEVEL }, /* zlib maximum */ 221 { "1", 1 }, /* zlib minimum */ 222 { "default", 8 }, /* zlib default */ 223 { "2", 2 }, 224 { "3", 3 }, 225 { "4", 4 }, 226 { "5", 5 }, /* for explicit testing */ 227 RANGE(6, MAX_MEM_LEVEL/*zlib*/), /* exclude 5 and below: zlib bugs */ 228 { all, 0 } 229 }, 230 #endif /* WRITE_CUSTOMIZE_*COMPRESSION */ 231 #ifdef PNG_WRITE_FILTER_SUPPORTED 232 vl_filter[] = 233 { 234 { all, PNG_ALL_FILTERS }, 235 { "off", PNG_NO_FILTERS }, 236 { "none", PNG_FILTER_NONE }, 237 { "sub", PNG_FILTER_SUB }, 238 { "up", PNG_FILTER_UP }, 239 { "avg", PNG_FILTER_AVG }, 240 { "paeth", PNG_FILTER_PAETH } 241 }, 242 #endif /* WRITE_FILTER */ 243 #ifdef PNG_PNGCP_TIMING_SUPPORTED 244 # define PNGCP_TIME_READ 1 245 # define PNGCP_TIME_WRITE 2 246 vl_time[] = 247 { 248 { "both", PNGCP_TIME_READ+PNGCP_TIME_WRITE }, 249 { "off", 0 }, 250 { "read", PNGCP_TIME_READ }, 251 { "write", PNGCP_TIME_WRITE } 252 }, 253 #endif /* PNGCP_TIMING */ 254 vl_IDAT_size[] = /* for png_set_IDAT_size */ 255 { 256 { "default", 0x7FFFFFFF }, 257 { "minimal", 1 }, 258 RANGE(1, 0x7FFFFFFF) 259 }, 260 #ifndef PNG_SW_IDAT_size 261 /* Pre 1.7 API: */ 262 # define png_set_IDAT_size(p,v) png_set_compression_buffer_size(p, v) 263 #endif /* !SW_IDAT_size */ 264 #define SL 8 /* stack limit in display, below */ 265 vl_log_depth[] = { { "on", 1 }, { "off", 0 }, RANGE(0, SL) }, 266 vl_on_off[] = { { "on", 1 }, { "off", 0 } }; 267 268 #ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED 269 static value_list 270 vl_windowBits_IDAT[] = 271 { 272 { "default", MAX_WBITS }, 273 { "small", 9 }, 274 RANGE(8, MAX_WBITS), /* modified by set_windowBits_hi */ 275 { all, 0 } 276 }; 277 #endif /* IDAT compression */ 278 279 typedef struct option 280 { 281 const char *name; /* name of the option */ 282 png_uint_32 opt; /* an option, or OPTION or LIST */ 283 png_byte search; /* Search on --search */ 284 png_byte value_count; /* length of the list of values: */ 285 const value_list *values; /* values for OPTION or LIST */ 286 } option; 287 288 static const option options[] = 289 { 290 /* struct display options, these are set when the command line is read */ 291 # define S(n,v) { #n, v, 0, 2, vl_on_off }, 292 S(verbose, VERBOSE) 293 S(warnings, WARNINGS) 294 S(errors, ERRORS) 295 S(quiet, QUIET) 296 S(strict, STRICT) 297 S(log, LOG) 298 S(continue, CONTINUE) 299 S(sizes, SIZES) 300 S(search, SEARCH) 301 S(nowrite, NOWRITE) 302 # ifdef IGNORE_INDEX 303 S(ignore-palette-index, IGNORE_INDEX) 304 # endif /* IGNORE_INDEX */ 305 # ifdef FIX_INDEX 306 S(fix-palette-index, FIX_INDEX) 307 # endif /* FIX_INDEX */ 308 # undef S 309 310 /* OPTION settings, these and LIST settings are read on demand */ 311 # define VLNAME(name) vl_ ## name 312 # define VLSIZE(name) voidcast(png_byte,\ 313 (sizeof VLNAME(name))/(sizeof VLNAME(name)[0])) 314 # define VL(oname, name, type, search)\ 315 { oname, type, search, VLSIZE(name), VLNAME(name) }, 316 # define VLO(oname, name, search) VL(oname, name, OPTION, search) 317 318 # ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED 319 # define VLCIDAT(name) VLO(#name, name, 1/*search*/) 320 # ifdef PNG_SW_COMPRESS_level 321 # define VLCiCCP(name) VLO("ICC-profile-" #name, name, 0/*search*/) 322 # else 323 # define VLCiCCP(name) 324 # endif 325 # else 326 # define VLCIDAT(name) 327 # define VLCiCCP(name) 328 # endif /* WRITE_CUSTOMIZE_COMPRESSION */ 329 330 # ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED 331 # define VLCzTXt(name) VLO("text-" #name, name, 0/*search*/) 332 # else 333 # define VLCzTXt(name) 334 # endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ 335 336 # define VLC(name) VLCIDAT(name) VLCiCCP(name) VLCzTXt(name) 337 338 # ifdef PNG_SW_COMPRESS_png_level 339 /* The libpng compression level isn't searched beause it justs sets the 340 * other things that are searched! 341 */ 342 VLO("compression", compression, 0) 343 VLO("text-compression", compression, 0) 344 VLO("ICC-profile-compression", compression, 0) 345 # endif /* SW_COMPRESS_png_level */ 346 VLC(strategy) 347 VLO("windowBits", windowBits_IDAT, 1) 348 # ifdef PNG_SW_COMPRESS_windowBits 349 VLO("ICC-profile-windowBits", windowBits_text/*sic*/, 0) 350 # endif 351 VLO("text-windowBits", windowBits_text, 0) 352 VLC(level) 353 VLC(memLevel) 354 VLO("IDAT-size", IDAT_size, 0) 355 VLO("log-depth", log_depth, 0) 356 357 # undef VLO 358 359 /* LIST settings */ 360 # define VLL(name, search) VL(#name, name, LIST, search) 361 #ifdef PNG_WRITE_FILTER_SUPPORTED 362 VLL(filter, 0) 363 #endif /* WRITE_FILTER */ 364 #ifdef PNG_PNGCP_TIMING_SUPPORTED 365 VLL(time, 0) 366 #endif /* PNGCP_TIMING */ 367 # undef VLL 368 # undef VL 369 }; 370 371 #ifdef __cplusplus 372 static const size_t option_count((sizeof options)/(sizeof options[0])); 373 #else /* !__cplusplus */ 374 # define option_count ((sizeof options)/(sizeof options[0])) 375 #endif /* !__cplusplus */ 376 377 static const char * 378 cts(int ct) 379 { 380 switch (ct) 381 { 382 case PNG_COLOR_TYPE_PALETTE: return "P"; 383 case PNG_COLOR_TYPE_GRAY: return "G"; 384 case PNG_COLOR_TYPE_GRAY_ALPHA: return "GA"; 385 case PNG_COLOR_TYPE_RGB: return "RGB"; 386 case PNG_COLOR_TYPE_RGB_ALPHA: return "RGBA"; 387 default: return "INVALID"; 388 } 389 } 390 391 struct display 392 { 393 jmp_buf error_return; /* Where to go to on error */ 394 unsigned int errset; /* error_return is set */ 395 396 const char *operation; /* What is happening */ 397 const char *filename; /* The name of the original file */ 398 const char *output_file; /* The name of the output file */ 399 400 /* Used on both read and write: */ 401 FILE *fp; 402 403 /* Used on a read, both the original read and when validating a written 404 * image. 405 */ 406 png_alloc_size_t read_size; 407 png_structp read_pp; 408 png_infop ip; 409 # if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED 410 png_textp text_ptr; /* stash of text chunks */ 411 int num_text; 412 int text_stashed; 413 # endif /* pre 1.7 */ 414 415 # ifdef PNG_PNGCP_TIMING_SUPPORTED 416 struct timespec read_time; 417 struct timespec read_time_total; 418 struct timespec write_time; 419 struct timespec write_time_total; 420 # endif /* PNGCP_TIMING */ 421 422 /* Used to write a new image (the original info_ptr is used) */ 423 # define MAX_SIZE ((png_alloc_size_t)(-1)) 424 png_alloc_size_t write_size; 425 png_alloc_size_t best_size; 426 png_structp write_pp; 427 428 /* Base file information */ 429 png_alloc_size_t size; 430 png_uint_32 w; 431 png_uint_32 h; 432 int bpp; 433 png_byte ct; 434 int no_warnings; /* Do not output libpng warnings */ 435 int min_windowBits; /* The windowBits range is 8..8 */ 436 437 /* Options handling */ 438 png_uint_32 results; /* A mask of errors seen */ 439 png_uint_32 options; /* See display_log below */ 440 png_byte entry[option_count]; /* The selected entry+1 of an option 441 * that appears on the command line, or 442 * 0 if it was not given. */ 443 int value[option_count]; /* Corresponding value */ 444 445 /* Compression exhaustive testing */ 446 /* Temporary variables used only while testing a single collection of 447 * settings: 448 */ 449 unsigned int csp; /* next stack entry to use */ 450 unsigned int nsp; /* highest active entry+1 found so far */ 451 452 /* Values used while iterating through all the combinations of settings for a 453 * single file: 454 */ 455 unsigned int tsp; /* nsp from the last run; this is the 456 * index+1 of the highest active entry on 457 * this run; this entry will be advanced. 458 */ 459 int opt_string_start; /* Position in buffer for the first 460 * searched option; non-zero if earlier 461 * options were set on the command line. 462 */ 463 struct stack 464 { 465 png_alloc_size_t best_size; /* Best so far for this option */ 466 png_alloc_size_t lo_size; 467 png_alloc_size_t hi_size; 468 int lo, hi; /* For binary chop of a range */ 469 int best_val; /* Best value found so far */ 470 int opt_string_end; /* End of the option string in 'curr' */ 471 png_byte opt; /* The option being tested */ 472 png_byte entry; /* The next value entry to be tested */ 473 png_byte end; /* This is the last entry */ 474 } stack[SL]; /* Stack of entries being tested */ 475 char curr[32*SL]; /* current options being tested */ 476 char best[32*SL]; /* best options */ 477 478 char namebuf[FILENAME_MAX]; /* output file name */ 479 }; 480 481 static void 482 display_init(struct display *dp) 483 /* Call this only once right at the start to initialize the control 484 * structure, the (struct buffer) lists are maintained across calls - the 485 * memory is not freed. 486 */ 487 { 488 memset(dp, 0, sizeof *dp); 489 dp->operation = "internal error"; 490 dp->filename = "command line"; 491 dp->output_file = "no output file"; 492 dp->options = WARNINGS; /* default to !verbose, !quiet */ 493 dp->fp = NULL; 494 dp->read_pp = NULL; 495 dp->ip = NULL; 496 dp->write_pp = NULL; 497 dp->min_windowBits = -1; /* this is an OPTIND, so -1 won't match anything */ 498 # if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED 499 dp->text_ptr = NULL; 500 dp->num_text = 0; 501 dp->text_stashed = 0; 502 # endif /* pre 1.7 */ 503 } 504 505 static void 506 display_clean_read(struct display *dp) 507 { 508 if (dp->read_pp != NULL) 509 png_destroy_read_struct(&dp->read_pp, NULL, NULL); 510 511 if (dp->fp != NULL) 512 { 513 FILE *fp = dp->fp; 514 dp->fp = NULL; 515 (void)fclose(fp); 516 } 517 } 518 519 static void 520 display_clean_write(struct display *dp) 521 { 522 if (dp->fp != NULL) 523 { 524 FILE *fp = dp->fp; 525 dp->fp = NULL; 526 (void)fclose(fp); 527 } 528 529 if (dp->write_pp != NULL) 530 png_destroy_write_struct(&dp->write_pp, dp->tsp > 0 ? NULL : &dp->ip); 531 } 532 533 static void 534 display_clean(struct display *dp) 535 { 536 display_clean_read(dp); 537 display_clean_write(dp); 538 dp->output_file = NULL; 539 540 # if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED 541 /* This is actually created and used by the write code, but only 542 * once; it has to be retained for subsequent writes of the same file. 543 */ 544 if (dp->text_stashed) 545 { 546 dp->text_stashed = 0; 547 dp->num_text = 0; 548 free(dp->text_ptr); 549 dp->text_ptr = NULL; 550 } 551 # endif /* pre 1.7 */ 552 553 /* leave the filename for error detection */ 554 dp->results = 0; /* reset for next time */ 555 } 556 557 static void 558 display_destroy(struct display *dp) 559 { 560 /* Release any memory held in the display. */ 561 display_clean(dp); 562 } 563 564 static struct display * 565 get_dp(png_structp pp) 566 /* The display pointer is always stored in the png_struct error pointer */ 567 { 568 struct display *dp = (struct display*)png_get_error_ptr(pp); 569 570 if (dp == NULL) 571 { 572 fprintf(stderr, "pngcp: internal error (no display)\n"); 573 exit(99); /* prevents a crash */ 574 } 575 576 return dp; 577 } 578 579 /* error handling */ 580 #ifdef __GNUC__ 581 # define VGATTR __attribute__((__format__ (__printf__,3,4))) 582 /* Required to quiet GNUC warnings when the compiler sees a stdarg function 583 * that calls one of the stdio v APIs. 584 */ 585 #else 586 # define VGATTR 587 #endif 588 static void VGATTR 589 display_log(struct display *dp, error_level level, const char *fmt, ...) 590 /* 'level' is as above, fmt is a stdio style format string. This routine 591 * does not return if level is above LIBPNG_WARNING 592 */ 593 { 594 dp->results |= 1U << level; 595 596 if (level > (error_level)(dp->options & LEVEL_MASK)) 597 { 598 const char *lp; 599 va_list ap; 600 601 switch (level) 602 { 603 case INFORMATION: lp = "information"; break; 604 case LIBPNG_WARNING: lp = "warning(libpng)"; break; 605 case APP_WARNING: lp = "warning(pngcp)"; break; 606 case APP_FAIL: lp = "error(continuable)"; break; 607 case LIBPNG_ERROR: lp = "error(libpng)"; break; 608 case LIBPNG_BUG: lp = "bug(libpng)"; break; 609 case APP_ERROR: lp = "error(pngcp)"; break; 610 case USER_ERROR: lp = "error(user)"; break; 611 612 case INTERNAL_ERROR: /* anything unexpected is an internal error: */ 613 case VERBOSE: case WARNINGS: case ERRORS: case QUIET: 614 default: lp = "bug(pngcp)"; break; 615 } 616 617 fprintf(stderr, "%s: %s: %s", 618 dp->filename != NULL ? dp->filename : "<stdin>", lp, dp->operation); 619 620 fprintf(stderr, ": "); 621 622 va_start(ap, fmt); 623 vfprintf(stderr, fmt, ap); 624 va_end(ap); 625 626 fputc('\n', stderr); 627 } 628 /* else do not output any message */ 629 630 /* Errors cause this routine to exit to the fail code */ 631 if (level > APP_FAIL || (level > ERRORS && !(dp->options & CONTINUE))) 632 { 633 if (dp->errset) 634 longjmp(dp->error_return, level); 635 636 else 637 exit(99); 638 } 639 } 640 641 #if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED 642 static void 643 text_stash(struct display *dp) 644 { 645 /* libpng 1.6 and earlier fixed a bug whereby text chunks were written 646 * multiple times by png_write_png; the issue was that png_write_png passed 647 * the same png_info to both png_write_info and png_write_end. Rather than 648 * fixing it by recording the information in the png_struct, or by recording 649 * where to write the chunks, the fix made was to change the 'compression' 650 * field of the chunk to invalid values, rendering the png_info somewhat 651 * useless. 652 * 653 * The only fix for this given that we use the png_info more than once is to 654 * make a copy of the text chunks and png_set_text it each time. This adds a 655 * text chunks, so they get replicated, but only the new set gets written 656 * each time. This uses memory like crazy but there is no way to delete the 657 * useless chunks from the png_info. 658 * 659 * To make this slightly more efficient only the top level structure is 660 * copied; since the old strings are actually preserved (in 1.6 and earlier) 661 * this happens to work. 662 */ 663 png_textp chunks = NULL; 664 665 dp->num_text = png_get_text(dp->write_pp, dp->ip, &chunks, NULL); 666 667 if (dp->num_text > 0) 668 { 669 dp->text_ptr = voidcast(png_textp, malloc(dp->num_text * sizeof *chunks)); 670 671 if (dp->text_ptr == NULL) 672 display_log(dp, APP_ERROR, "text chunks: stash malloc failed"); 673 674 else 675 memcpy(dp->text_ptr, chunks, dp->num_text * sizeof *chunks); 676 } 677 678 dp->text_stashed = 1; /* regardless of whether there are chunks or not */ 679 } 680 681 #define text_stash(dp) if (!dp->text_stashed) text_stash(dp) 682 683 static void 684 text_restore(struct display *dp) 685 { 686 /* libpng makes a copy, so this is fine: */ 687 if (dp->text_ptr != NULL) 688 png_set_text(dp->write_pp, dp->ip, dp->text_ptr, dp->num_text); 689 } 690 691 #define text_restore(dp) if (dp->text_stashed) text_restore(dp) 692 693 #else 694 #define text_stash(dp) ((void)0) 695 #define text_restore(dp) ((void)0) 696 #endif /* pre 1.7 */ 697 698 /* OPTIONS: 699 * 700 * The command handles options of the forms: 701 * 702 * --option 703 * Turn an option on (Option) 704 * --no-option 705 * Turn an option off (Option) 706 * --option=value 707 * Set an option to a value (Value) 708 * --option=val1,val2,val3 709 * Set an option to a bitmask constructed from the values (List) 710 */ 711 static png_byte 712 option_index(struct display *dp, const char *opt, size_t len) 713 /* Return the index (in options[]) of the given option, outputs an error if 714 * it does not exist. Takes the name of the option and a length (number of 715 * characters in the name). 716 */ 717 { 718 png_byte j; 719 720 for (j=0; j<option_count; ++j) 721 if (strncmp(options[j].name, opt, len) == 0 && options[j].name[len] == 0) 722 return j; 723 724 /* If the setjmp buffer is set the code is asking for an option index; this 725 * is bad. Otherwise this is the command line option parsing. 726 */ 727 display_log(dp, dp->errset ? INTERNAL_ERROR : USER_ERROR, 728 "%.*s: unknown option", (int)/*SAFE*/len, opt); 729 abort(); /* NOT REACHED */ 730 } 731 732 /* This works for an option name (no quotes): */ 733 #define OPTIND(dp, name) option_index(dp, #name, (sizeof #name)-1) 734 735 static int 736 get_option(struct display *dp, const char *opt, int *value) 737 { 738 const png_byte i = option_index(dp, opt, strlen(opt)); 739 740 if (dp->entry[i]) /* option was set on command line */ 741 { 742 *value = dp->value[i]; 743 return 1; 744 } 745 746 else 747 return 0; 748 } 749 750 static int 751 set_opt_string_(struct display *dp, unsigned int sp, png_byte opt, 752 const char *entry_name) 753 /* Add the appropriate option string to dp->curr. */ 754 { 755 int offset, add; 756 757 if (sp > 0) 758 offset = dp->stack[sp-1].opt_string_end; 759 760 else 761 offset = dp->opt_string_start; 762 763 if (entry_name == range_lo) 764 add = sprintf(dp->curr+offset, " --%s=%d", options[opt].name, 765 dp->value[opt]); 766 767 else 768 add = sprintf(dp->curr+offset, " --%s=%s", options[opt].name, entry_name); 769 770 if (add < 0) 771 display_log(dp, INTERNAL_ERROR, "sprintf failed"); 772 773 assert(offset+add < (int)/*SAFE*/sizeof dp->curr); 774 return offset+add; 775 } 776 777 static void 778 set_opt_string(struct display *dp, unsigned int sp) 779 /* Add the appropriate option string to dp->curr. */ 780 { 781 dp->stack[sp].opt_string_end = set_opt_string_(dp, sp, dp->stack[sp].opt, 782 options[dp->stack[sp].opt].values[dp->stack[sp].entry].name); 783 } 784 785 static void 786 record_opt(struct display *dp, png_byte opt, const char *entry_name) 787 /* Record this option in dp->curr; called for an option not being searched, 788 * the caller passes in the name of the value, or range_lo to use the 789 * numerical value. 790 */ 791 { 792 const unsigned int sp = dp->csp; /* stack entry of next searched option */ 793 794 if (sp >= dp->tsp) 795 { 796 /* At top of stack; add the opt string for this entry to the previous 797 * searched entry or the start of the dp->curr buffer if there is nothing 798 * on the stack yet (sp == 0). 799 */ 800 const int offset = set_opt_string_(dp, sp, opt, entry_name); 801 802 if (sp > 0) 803 dp->stack[sp-1].opt_string_end = offset; 804 805 else 806 dp->opt_string_start = offset; 807 } 808 809 /* else do nothing: option already recorded */ 810 } 811 812 static int 813 opt_list_end(struct display *dp, png_byte opt, png_byte entry) 814 { 815 if (options[opt].values[entry].name == range_lo) 816 return entry+1U >= options[opt].value_count /* missing range_hi */ || 817 options[opt].values[entry+1U].name != range_hi /* likewise */ || 818 options[opt].values[entry+1U].value <= dp->value[opt] /* range end */; 819 820 else 821 return entry+1U >= options[opt].value_count /* missing 'all' */ || 822 options[opt].values[entry+1U].name == all /* last entry */; 823 } 824 825 static void 826 push_opt(struct display *dp, unsigned int sp, png_byte opt, int search) 827 /* Push a new option onto the stack, initializing the new stack entry 828 * appropriately; this does all the work of next_opt (setting end/nsp) for 829 * the first entry in the list. 830 */ 831 { 832 png_byte entry; 833 const char *entry_name; 834 835 assert(sp == dp->tsp && sp < SL); 836 837 /* The starting entry is entry 0 unless there is a range in which case it is 838 * the entry corresponding to range_lo: 839 */ 840 entry = options[opt].value_count; 841 assert(entry > 0U); 842 843 do 844 { 845 entry_name = options[opt].values[--entry].name; 846 if (entry_name == range_lo) 847 break; 848 } 849 while (entry > 0U); 850 851 dp->tsp = sp+1U; 852 dp->stack[sp].best_size = 853 dp->stack[sp].lo_size = 854 dp->stack[sp].hi_size = MAX_SIZE; 855 856 if (search && entry_name == range_lo) /* search this range */ 857 { 858 dp->stack[sp].lo = options[opt].values[entry].value; 859 /* check for a mal-formed RANGE above: */ 860 assert(entry+1 < options[opt].value_count && 861 options[opt].values[entry+1].name == range_hi); 862 dp->stack[sp].hi = options[opt].values[entry+1].value; 863 } 864 865 else 866 { 867 /* next_opt will just iterate over the range. */ 868 dp->stack[sp].lo = INT_MAX; 869 dp->stack[sp].hi = INT_MIN; /* Prevent range chop */ 870 } 871 872 dp->stack[sp].opt = opt; 873 dp->stack[sp].entry = entry; 874 dp->stack[sp].best_val = dp->value[opt] = options[opt].values[entry].value; 875 876 set_opt_string(dp, sp); 877 878 /* This works for the search case too; if the range has only one entry 'end' 879 * will be marked here. 880 */ 881 if (opt_list_end(dp, opt, entry)) 882 { 883 dp->stack[sp].end = 1; 884 /* Skip the warning if pngcp did this itself. See the code in 885 * set_windowBits_hi. 886 */ 887 if (opt != dp->min_windowBits) 888 display_log(dp, APP_WARNING, "%s: only testing one value", 889 options[opt].name); 890 } 891 892 else 893 { 894 dp->stack[sp].end = 0; 895 dp->nsp = dp->tsp; 896 } 897 898 /* Do a lazy cache of the text chunks for libpng 1.6 and earlier; this is 899 * because they can only be written once(!) so if we are going to re-use the 900 * png_info we need a copy. 901 */ 902 text_stash(dp); 903 } 904 905 static void 906 next_opt(struct display *dp, unsigned int sp) 907 /* Return the next value for this option. When called 'sp' is expected to be 908 * the topmost stack entry - only the topmost entry changes each time round - 909 * and there must be a valid entry to return. next_opt will set dp->nsp to 910 * sp+1 if more entries are available, otherwise it will not change it and 911 * set dp->stack[s].end to true. 912 */ 913 { 914 int search = 0; 915 png_byte entry, opt; 916 const char *entry_name; 917 918 /* dp->stack[sp] must be the top stack entry and it must be active: */ 919 assert(sp+1U == dp->tsp && !dp->stack[sp].end); 920 921 opt = dp->stack[sp].opt; 922 entry = dp->stack[sp].entry; 923 assert(entry+1U < options[opt].value_count); 924 entry_name = options[opt].values[entry].name; 925 assert(entry_name != NULL); 926 927 /* For ranges increment the value but don't change the entry, for all other 928 * cases move to the next entry and load its value: 929 */ 930 if (entry_name == range_lo) /* a range */ 931 { 932 /* A range can be iterated over or searched. The default iteration option 933 * is indicated by hi < lo on the stack, otherwise the range being search 934 * is [lo..hi] (inclusive). 935 */ 936 if (dp->stack[sp].lo > dp->stack[sp].hi) 937 dp->value[opt]++; 938 939 else 940 { 941 /* This is the best size found for this option value: */ 942 png_alloc_size_t best_size = dp->stack[sp].best_size; 943 int lo = dp->stack[sp].lo; 944 int hi = dp->stack[sp].hi; 945 int val = dp->value[opt]; 946 947 search = 1; /* end is determined here */ 948 assert(best_size < MAX_SIZE); 949 950 if (val == lo) 951 { 952 /* Finding the best for the low end of the range: */ 953 dp->stack[sp].lo_size = best_size; 954 assert(hi > val); 955 956 if (hi == val+1) /* only 2 entries */ 957 dp->stack[sp].end = 1; 958 959 val = hi; 960 } 961 962 else if (val == hi) 963 { 964 dp->stack[sp].hi_size = best_size; 965 assert(val > lo+1); /* else 'end' set above */ 966 967 if (val == lo+2) /* only three entries to test */ 968 dp->stack[sp].end = 1; 969 970 val = (lo + val)/2; 971 } 972 973 else 974 { 975 png_alloc_size_t lo_size = dp->stack[sp].lo_size; 976 png_alloc_size_t hi_size = dp->stack[sp].hi_size; 977 978 /* lo and hi should have been tested. */ 979 assert(lo_size < MAX_SIZE && hi_size < MAX_SIZE); 980 981 /* These cases arise with the 'probe' handling below when there is a 982 * dip or peak in the size curve. 983 */ 984 if (val < lo) /* probing a new lo */ 985 { 986 /* Swap lo and val: */ 987 dp->stack[sp].lo = val; 988 dp->stack[sp].lo_size = best_size; 989 val = lo; 990 best_size = lo_size; 991 lo = dp->stack[sp].lo; 992 lo_size = dp->stack[sp].lo_size; 993 } 994 995 else if (val > hi) /* probing a new hi */ 996 { 997 /* Swap hi and val: */ 998 dp->stack[sp].hi = val; 999 dp->stack[sp].hi_size = best_size; 1000 val = hi; 1001 best_size = hi_size; 1002 hi = dp->stack[sp].hi; 1003 hi_size = dp->stack[sp].hi_size; 1004 } 1005 1006 /* The following should be true or something got messed up above. */ 1007 assert(lo < val && val < hi); 1008 1009 /* If there are only four entries (lo, val, hi plus one more) just 1010 * test the remaining entry. 1011 */ 1012 if (hi == lo+3) 1013 { 1014 /* Because of the 'probe' code val can either be lo+1 or hi-1; we 1015 * need to test the other. 1016 */ 1017 val = lo + ((val == lo+1) ? 2 : 1); 1018 assert(lo < val && val < hi); 1019 dp->stack[sp].end = 1; 1020 } 1021 1022 else 1023 { 1024 /* There are at least 2 entries still untested between lo and hi, 1025 * i.e. hi >= lo+4. 'val' is the midpoint +/- 0.5 1026 * 1027 * Separate out the four easy cases when lo..val..hi are 1028 * monotonically decreased or (more weird) increasing: 1029 */ 1030 assert(hi > lo+3); 1031 1032 if (lo_size <= best_size && best_size <= hi_size) 1033 { 1034 /* Select the low range; testing this first favours the low 1035 * range over the high range when everything comes out equal. 1036 * Because of the probing 'val' may be lo+1. In that case end 1037 * the search and set 'val' to lo+2. 1038 */ 1039 if (val == lo+1) 1040 { 1041 ++val; 1042 dp->stack[sp].end = 1; 1043 } 1044 1045 else 1046 { 1047 dp->stack[sp].hi = hi = val; 1048 dp->stack[sp].hi_size = best_size; 1049 val = (lo + val) / 2; 1050 } 1051 } 1052 1053 else if (lo_size >= best_size && best_size >= hi_size) 1054 { 1055 /* Monotonically decreasing size; this is the expected case. 1056 * Select the high end of the range. As above, val may be 1057 * hi-1. 1058 */ 1059 if (val == hi-1) 1060 { 1061 --val; 1062 dp->stack[sp].end = 1; 1063 } 1064 1065 else 1066 { 1067 dp->stack[sp].lo = lo = val; 1068 dp->stack[sp].lo_size = best_size; 1069 val = (val + hi) / 2; 1070 } 1071 } 1072 1073 /* If both those tests failed 'best_size' is either greater than 1074 * or less than both lo_size and hi_size. There is a peak or dip 1075 * in the curve of sizes from lo to hi and val is on the peak or 1076 * dip. 1077 * 1078 * Because the ranges being searched as so small (level is 1..9, 1079 * windowBits 8..15, memLevel 1..9) there will only be at most 1080 * three untested values between lo..val and val..hi, so solve 1081 * the problem by probing down from hi or up from lo, whichever 1082 * is the higher. 1083 * 1084 * This is the place where 'val' is set to outside the range 1085 * lo..hi, described as 'probing', though maybe 'narrowing' would 1086 * be more accurate. 1087 */ 1088 else if (lo_size <= hi_size) /* down from hi */ 1089 { 1090 dp->stack[sp].hi = val; 1091 dp->stack[sp].hi_size = best_size; 1092 val = --hi; 1093 } 1094 1095 else /* up from low */ 1096 { 1097 dp->stack[sp].lo = val; 1098 dp->stack[sp].lo_size = best_size; 1099 val = ++lo; 1100 } 1101 1102 /* lo and hi are still the true range limits, check for the end 1103 * condition. 1104 */ 1105 assert(hi > lo+1); 1106 if (hi <= lo+2) 1107 dp->stack[sp].end = 1; 1108 } 1109 } 1110 1111 assert(val != dp->stack[sp].best_val); /* should be a new value */ 1112 dp->value[opt] = val; 1113 dp->stack[sp].best_size = MAX_SIZE; 1114 } 1115 } 1116 1117 else 1118 { 1119 /* Increment 'entry' */ 1120 dp->value[opt] = options[opt].values[++entry].value; 1121 dp->stack[sp].entry = entry; 1122 } 1123 1124 set_opt_string(dp, sp); 1125 1126 if (!search && opt_list_end(dp, opt, entry)) /* end of list */ 1127 dp->stack[sp].end = 1; 1128 1129 else if (!dp->stack[sp].end) /* still active after all these tests */ 1130 dp->nsp = dp->tsp; 1131 } 1132 1133 static int 1134 compare_option(const struct display *dp, unsigned int sp) 1135 { 1136 int opt = dp->stack[sp].opt; 1137 1138 /* If the best so far is numerically less than the current value the 1139 * current set of options is invariably worse. 1140 */ 1141 if (dp->stack[sp].best_val < dp->value[opt]) 1142 return -1; 1143 1144 /* Lists of options are searched out of numerical order (currently only 1145 * strategy), so only return +1 here when a range is being searched. 1146 */ 1147 else if (dp->stack[sp].best_val > dp->value[opt]) 1148 { 1149 if (dp->stack[sp].lo <= dp->stack[sp].hi /*searching*/) 1150 return 1; 1151 1152 else 1153 return -1; 1154 } 1155 1156 else 1157 return 0; /* match; current value is the best one */ 1158 } 1159 1160 static int 1161 advance_opt(struct display *dp, png_byte opt, int search) 1162 { 1163 unsigned int sp = dp->csp++; /* my stack entry */ 1164 1165 assert(sp >= dp->nsp); /* nsp starts off zero */ 1166 1167 /* If the entry was active in the previous run dp->stack[sp] is already 1168 * set up and dp->tsp will be greater than sp, otherwise a new entry 1169 * needs to be created. 1170 * 1171 * dp->nsp is handled this way: 1172 * 1173 * 1) When an option is pushed onto the stack dp->nsp and dp->tsp are 1174 * both set (by push_opt) to the next stack entry *unless* there is 1175 * only one entry in the new list, in which case dp->stack[sp].end 1176 * is set. 1177 * 1178 * 2) For the top stack entry next_opt is called. The entry must be 1179 * active (dp->stack[sp].end is not set) and either 'nsp' or 'end' 1180 * will be updated as appropriate. 1181 * 1182 * 3) For lower stack entries nsp is set unless the stack entry is 1183 * already at the end. This means that when all the higher entries 1184 * are popped this entry will be too. 1185 */ 1186 if (sp >= dp->tsp) 1187 { 1188 push_opt(dp, sp, opt, search); /* This sets tsp to sp+1 */ 1189 return 1; /* initialized */ 1190 } 1191 1192 else 1193 { 1194 int ret = 0; /* unchanged */ 1195 1196 /* An option that is already on the stack; update best_size and best_val 1197 * if appropriate. On the first run there are no previous values and 1198 * dp->write_size will be MAX_SIZE, however on the first run dp->tsp 1199 * starts off as 0. 1200 */ 1201 assert(dp->write_size > 0U && dp->write_size < MAX_SIZE); 1202 1203 if (dp->stack[sp].best_size > dp->write_size || 1204 (dp->stack[sp].best_size == dp->write_size && 1205 compare_option(dp, sp) > 0)) 1206 { 1207 dp->stack[sp].best_size = dp->write_size; 1208 dp->stack[sp].best_val = dp->value[opt]; 1209 } 1210 1211 if (sp+1U >= dp->tsp) 1212 { 1213 next_opt(dp, sp); 1214 ret = 1; /* advanced */ 1215 } 1216 1217 else if (!dp->stack[sp].end) /* Active, not at top of stack */ 1218 dp->nsp = sp+1U; 1219 1220 return ret; /* advanced || unchanged */ 1221 } 1222 } 1223 1224 static int 1225 getallopts_(struct display *dp, const png_byte opt, int *value, int record) 1226 /* Like getop but iterate over all the values if the option was set to "all". 1227 */ 1228 { 1229 if (dp->entry[opt]) /* option was set on command line */ 1230 { 1231 /* Simple, single value, entries don't have a stack frame and have a fixed 1232 * value (it doesn't change once set on the command line). Otherwise the 1233 * value (entry) selected from the command line is 'all': 1234 */ 1235 const char *entry_name = options[opt].values[dp->entry[opt]-1].name; 1236 1237 if (entry_name == all) 1238 (void)advance_opt(dp, opt, 0/*do not search; iterate*/); 1239 1240 else if (record) 1241 record_opt(dp, opt, entry_name); 1242 1243 *value = dp->value[opt]; 1244 return 1; /* set */ 1245 } 1246 1247 else 1248 return 0; /* not set */ 1249 } 1250 1251 static int 1252 getallopts(struct display *dp, const char *opt_str, int *value) 1253 { 1254 return getallopts_(dp, option_index(dp, opt_str, strlen(opt_str)), value, 0); 1255 } 1256 1257 static int 1258 getsearchopts(struct display *dp, const char *opt_str, int *value) 1259 /* As above except that if the option was not set try a search */ 1260 { 1261 png_byte istrat; 1262 const png_byte opt = option_index(dp, opt_str, strlen(opt_str)); 1263 int record = options[opt].search; 1264 const char *entry_name; 1265 1266 /* If it was set on the command line honour the setting, including 'all' 1267 * which will override the built in search: 1268 */ 1269 if (getallopts_(dp, opt, value, record)) 1270 return 1; 1271 1272 else if (!record) /* not a search option */ 1273 return 0; /* unset and not searched */ 1274 1275 /* Otherwise decide what to do here. */ 1276 istrat = OPTIND(dp, strategy); 1277 entry_name = range_lo; /* record the value, not the name */ 1278 1279 if (opt == istrat) /* search all strategies */ 1280 (void)advance_opt(dp, opt, 0/*iterate*/), record=0; 1281 1282 else if (opt == OPTIND(dp, level)) 1283 { 1284 /* Both RLE and HUFFMAN don't benefit from level increases */ 1285 if (dp->value[istrat] == Z_RLE || dp->value[istrat] == Z_HUFFMAN_ONLY) 1286 dp->value[opt] = 1; 1287 1288 else /* fixed, filtered or default */ 1289 (void)advance_opt(dp, opt, 1/*search*/), record=0; 1290 } 1291 1292 else if (opt == OPTIND(dp, windowBits)) 1293 { 1294 /* Changing windowBits for strategies that do not search the window is 1295 * pointless. Huffman-only does not search, RLE only searches backwards 1296 * one byte, so given that the maximum string length is 258, a windowBits 1297 * of 9 is always sufficient. 1298 */ 1299 if (dp->value[istrat] == Z_HUFFMAN_ONLY) 1300 dp->value[opt] = 8; 1301 1302 else if (dp->value[istrat] == Z_RLE) 1303 dp->value[opt] = 9; 1304 1305 else /* fixed, filtered or default */ 1306 (void)advance_opt(dp, opt, 1/*search*/), record=0; 1307 } 1308 1309 else if (opt == OPTIND(dp, memLevel)) 1310 { 1311 # if 0 1312 (void)advance_opt(dp, opt, 0/*all*/), record=0; 1313 # else 1314 dp->value[opt] = MAX_MEM_LEVEL; 1315 # endif 1316 } 1317 1318 else /* something else */ 1319 assert(0=="reached"); 1320 1321 if (record) 1322 record_opt(dp, opt, entry_name); 1323 1324 /* One of the above searched options: */ 1325 *value = dp->value[opt]; 1326 return 1; 1327 } 1328 1329 static int 1330 find_val(struct display *dp, png_byte opt, const char *str, size_t len) 1331 /* Like option_index but sets (index+i) of the entry in options[opt] that 1332 * matches str[0..len-1] into dp->entry[opt] as well as returning the actual 1333 * value. 1334 */ 1335 { 1336 int rlo = INT_MAX, rhi = INT_MIN; 1337 png_byte j, irange = 0; 1338 1339 for (j=1U; j<=options[opt].value_count; ++j) 1340 { 1341 if (strncmp(options[opt].values[j-1U].name, str, len) == 0 && 1342 options[opt].values[j-1U].name[len] == 0) 1343 { 1344 dp->entry[opt] = j; 1345 return options[opt].values[j-1U].value; 1346 } 1347 else if (options[opt].values[j-1U].name == range_lo) 1348 rlo = options[opt].values[j-1U].value, irange = j; 1349 else if (options[opt].values[j-1U].name == range_hi) 1350 rhi = options[opt].values[j-1U].value; 1351 } 1352 1353 /* No match on the name, but there may be a range. */ 1354 if (irange > 0) 1355 { 1356 char *ep = NULL; 1357 long l = strtol(str, &ep, 0); 1358 1359 if (ep == str+len && l >= rlo && l <= rhi) 1360 { 1361 dp->entry[opt] = irange; /* range_lo */ 1362 return (int)/*SAFE*/l; 1363 } 1364 } 1365 1366 display_log(dp, dp->errset ? INTERNAL_ERROR : USER_ERROR, 1367 "%s: unknown value setting '%.*s'", options[opt].name, 1368 (int)/*SAFE*/len, str); 1369 abort(); /* NOT REACHED */ 1370 } 1371 1372 static int 1373 opt_check(struct display *dp, const char *arg) 1374 { 1375 assert(dp->errset == 0); 1376 1377 if (arg != NULL && arg[0] == '-' && arg[1] == '-') 1378 { 1379 int i = 0, negate = (strncmp(arg+2, "no-", 3) == 0), val; 1380 png_byte j; 1381 1382 if (negate) 1383 arg += 5; /* --no- */ 1384 1385 else 1386 arg += 2; /* -- */ 1387 1388 /* Find the length (expect arg\0 or arg=) */ 1389 while (arg[i] != 0 && arg[i] != '=') ++i; 1390 1391 /* So arg[0..i-1] is the argument name, this does not return if this isn't 1392 * a valid option name. 1393 */ 1394 j = option_index(dp, arg, i); 1395 1396 /* It matcheth an option; check the remainder. */ 1397 if (arg[i] == 0) /* no specified value, use the default */ 1398 { 1399 val = options[j].values[negate].value; 1400 dp->entry[j] = (png_byte)/*SAFE*/(negate + 1U); 1401 } 1402 1403 else 1404 { 1405 const char *list = arg + (i+1); 1406 1407 /* Expect a single value here unless this is a list, in which case 1408 * multiple values are combined. 1409 */ 1410 if (options[j].opt != LIST) 1411 { 1412 /* find_val sets 'dp->entry[j]' to a non-zero value: */ 1413 val = find_val(dp, j, list, strlen(list)); 1414 1415 if (negate) 1416 { 1417 if (options[j].opt < OPTION) 1418 val = !val; 1419 1420 else 1421 { 1422 display_log(dp, USER_ERROR, 1423 "%.*s: option=arg cannot be negated", i, arg); 1424 abort(); /* NOT REACHED */ 1425 } 1426 } 1427 } 1428 1429 else /* multiple options separated by ',' characters */ 1430 { 1431 /* --no-option negates list values from the default, which should 1432 * therefore be 'all'. Notice that if the option list is empty in 1433 * this case nothing will be removed and therefore --no-option= is 1434 * the same as --option. 1435 */ 1436 if (negate) 1437 val = options[j].values[0].value; 1438 1439 else 1440 val = 0; 1441 1442 while (*list != 0) /* allows option= which sets 0 */ 1443 { 1444 /* A value is terminated by the end of the list or a ',' 1445 * character. 1446 */ 1447 int v, iv; 1448 1449 iv = 0; /* an index into 'list' */ 1450 while (list[++iv] != 0 && list[iv] != ',') {} 1451 1452 v = find_val(dp, j, list, iv); 1453 1454 if (negate) 1455 val &= ~v; 1456 1457 else 1458 val |= v; 1459 1460 list += iv; 1461 if (*list != 0) 1462 ++list; /* skip the ',' */ 1463 } 1464 } 1465 } 1466 1467 /* 'val' is the new value, store it for use later and debugging: */ 1468 dp->value[j] = val; 1469 1470 if (options[j].opt < LEVEL_MASK) 1471 { 1472 /* The handling for error levels is to set the level. */ 1473 if (val) /* Set this level */ 1474 dp->options = (dp->options & ~LEVEL_MASK) | options[j].opt; 1475 1476 else 1477 display_log(dp, USER_ERROR, 1478 "%.*s: messages cannot be turned off individually; set a message level", 1479 i, arg); 1480 } 1481 1482 else if (options[j].opt < OPTION) 1483 { 1484 if (val) 1485 dp->options |= options[j].opt; 1486 1487 else 1488 dp->options &= ~options[j].opt; 1489 } 1490 1491 return 1; /* this is an option */ 1492 } 1493 1494 else 1495 return 0; /* not an option */ 1496 } 1497 1498 #ifdef PNG_PNGCP_TIMING_SUPPORTED 1499 static void 1500 set_timer(struct display *dp, struct timespec *timer) 1501 { 1502 /* Do the timing using clock_gettime and the per-process timer. */ 1503 if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, timer)) 1504 { 1505 display_log(dp, APP_ERROR, 1506 "CLOCK_PROCESS_CPUTIME_ID: %s: timing disabled\n", strerror(errno)); 1507 dp->value[OPTIND(dp,time)] = 0; /* i.e. off */ 1508 } 1509 } 1510 1511 static void 1512 start_timer(struct display *dp, int what) 1513 { 1514 if ((dp->value[OPTIND(dp,time)] & what) != 0) 1515 set_timer(dp, what == PNGCP_TIME_READ ? &dp->read_time : &dp->write_time); 1516 } 1517 1518 static void 1519 end_timer(struct display *dp, int what) 1520 { 1521 if ((dp->value[OPTIND(dp,time)] & what) != 0) 1522 { 1523 struct timespec t, tmp; 1524 1525 set_timer(dp, &t); 1526 1527 if (what == PNGCP_TIME_READ) 1528 tmp = dp->read_time; 1529 1530 else 1531 tmp = dp->write_time; 1532 1533 t.tv_sec -= tmp.tv_sec; 1534 t.tv_nsec -= tmp.tv_nsec; 1535 1536 if (t.tv_nsec < 0) 1537 { 1538 --(t.tv_sec); 1539 t.tv_nsec += 1000000000L; 1540 } 1541 1542 if (what == PNGCP_TIME_READ) 1543 dp->read_time = t, tmp = dp->read_time_total; 1544 1545 else 1546 dp->write_time = t, tmp = dp->write_time_total; 1547 1548 tmp.tv_sec += t.tv_sec; 1549 tmp.tv_nsec += t.tv_nsec; 1550 1551 if (tmp.tv_nsec >= 1000000000L) 1552 { 1553 ++(tmp.tv_sec); 1554 tmp.tv_nsec -= 1000000000L; 1555 } 1556 1557 if (what == PNGCP_TIME_READ) 1558 dp->read_time_total = tmp; 1559 1560 else 1561 dp->write_time_total = tmp; 1562 } 1563 } 1564 1565 static void 1566 print_time(const char *what, struct timespec t) 1567 { 1568 printf("%s %.2lu.%.9ld", what, (unsigned long)t.tv_sec, t.tv_nsec); 1569 } 1570 #else /* !PNGCP_TIMING */ 1571 #define start_timer(dp, what) ((void)0) 1572 #define end_timer(dp, what) ((void)0) 1573 #endif /* !PNGCP_TIMING */ 1574 1575 /* The following is used in main to verify that the final argument is a 1576 * directory: 1577 */ 1578 static int 1579 checkdir(const char *pathname) 1580 { 1581 struct stat buf; 1582 return stat(pathname, &buf) == 0 && S_ISDIR(buf.st_mode); 1583 } 1584 1585 /* Work out whether a path is valid (if not a display_log occurs), a directory 1586 * (1 is returned) or a file *or* non-existent (0 is returned). 1587 * 1588 * Used for a write path. 1589 */ 1590 static int 1591 isdir(struct display *dp, const char *pathname) 1592 { 1593 if (pathname == NULL) 1594 return 0; /* stdout */ 1595 1596 else if (pathname[0] == 0) 1597 return 1; /* empty string */ 1598 1599 else 1600 { 1601 struct stat buf; 1602 int ret = stat(pathname, &buf); 1603 1604 if (ret == 0) /* the entry exists */ 1605 { 1606 if (S_ISDIR(buf.st_mode)) 1607 return 1; 1608 1609 /* Else expect an object that exists and can be written: */ 1610 if (access(pathname, W_OK) != 0) 1611 display_log(dp, USER_ERROR, "%s: cannot be written (%s)", pathname, 1612 strerror(errno)); 1613 1614 return 0; /* file (exists, can be written) */ 1615 } 1616 1617 else /* an error */ 1618 { 1619 /* Non-existence is fine, other errors are not: */ 1620 if (errno != ENOENT) 1621 display_log(dp, USER_ERROR, "%s: invalid output name (%s)", 1622 pathname, strerror(errno)); 1623 1624 return 0; /* file (does not exist) */ 1625 } 1626 } 1627 } 1628 1629 static void 1630 makename(struct display *dp, const char *dir, const char *infile) 1631 { 1632 /* Make a name for an output file (and check it). */ 1633 dp->namebuf[0] = 0; 1634 1635 if (dir == NULL || infile == NULL) 1636 display_log(dp, INTERNAL_ERROR, "NULL name to makename"); 1637 1638 else 1639 { 1640 size_t dsize = strlen(dir); 1641 1642 if (dsize <= (sizeof dp->namebuf)-2) /* Allow for name + '/' + '\0' */ 1643 { 1644 size_t isize = strlen(infile); 1645 size_t istart = isize-1; 1646 1647 /* This should fail before here: */ 1648 if (infile[istart] == '/') 1649 display_log(dp, INTERNAL_ERROR, "infile with trailing /"); 1650 1651 memcpy(dp->namebuf, dir, dsize); 1652 if (dsize > 0 && dp->namebuf[dsize-1] != '/') 1653 dp->namebuf[dsize++] = '/'; 1654 1655 /* Find the rightmost non-/ character: */ 1656 while (istart > 0 && infile[istart-1] != '/') 1657 --istart; 1658 1659 isize -= istart; 1660 infile += istart; 1661 1662 if (dsize+isize < (sizeof dp->namebuf)) /* dsize + infile + '\0' */ 1663 { 1664 memcpy(dp->namebuf+dsize, infile, isize+1); 1665 1666 if (isdir(dp, dp->namebuf)) 1667 display_log(dp, USER_ERROR, "%s: output file is a directory", 1668 dp->namebuf); 1669 } 1670 1671 else 1672 { 1673 dp->namebuf[dsize] = 0; /* allowed for: -2 at start */ 1674 display_log(dp, USER_ERROR, "%s%s: output file name too long", 1675 dp->namebuf, infile); 1676 } 1677 } 1678 1679 else 1680 display_log(dp, USER_ERROR, "%s: output directory name too long", dir); 1681 } 1682 } 1683 1684 /* error handler callbacks for libpng */ 1685 static void PNGCBAPI 1686 display_warning(png_structp pp, png_const_charp warning) 1687 { 1688 struct display *dp = get_dp(pp); 1689 1690 /* This is used to prevent repeated warnings while searching */ 1691 if (!dp->no_warnings) 1692 display_log(get_dp(pp), LIBPNG_WARNING, "%s", warning); 1693 } 1694 1695 static void PNGCBAPI 1696 display_error(png_structp pp, png_const_charp error) 1697 { 1698 struct display *dp = get_dp(pp); 1699 1700 display_log(dp, LIBPNG_ERROR, "%s", error); 1701 } 1702 1703 static void 1704 display_start_read(struct display *dp, const char *filename) 1705 { 1706 if (filename != NULL) 1707 { 1708 dp->filename = filename; 1709 dp->fp = fopen(filename, "rb"); 1710 } 1711 1712 else 1713 { 1714 dp->filename = "<stdin>"; 1715 dp->fp = stdin; 1716 } 1717 1718 dp->w = dp->h = 0U; 1719 dp->bpp = 0U; 1720 dp->size = 0U; 1721 dp->read_size = 0U; 1722 1723 if (dp->fp == NULL) 1724 display_log(dp, USER_ERROR, "file open failed (%s)", strerror(errno)); 1725 } 1726 1727 static void PNGCBAPI 1728 read_function(png_structp pp, png_bytep data, png_size_t size) 1729 { 1730 struct display *dp = get_dp(pp); 1731 1732 if (size == 0U || fread(data, size, 1U, dp->fp) == 1U) 1733 dp->read_size += size; 1734 1735 else 1736 { 1737 if (feof(dp->fp)) 1738 display_log(dp, LIBPNG_ERROR, "PNG file truncated"); 1739 else 1740 display_log(dp, LIBPNG_ERROR, "PNG file read failed (%s)", 1741 strerror(errno)); 1742 } 1743 } 1744 1745 static void 1746 read_png(struct display *dp, const char *filename) 1747 { 1748 display_clean_read(dp); /* safety */ 1749 display_start_read(dp, filename); 1750 1751 dp->read_pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, dp, 1752 display_error, display_warning); 1753 if (dp->read_pp == NULL) 1754 display_log(dp, LIBPNG_ERROR, "failed to create read struct"); 1755 1756 # ifdef PNG_BENIGN_ERRORS_SUPPORTED 1757 png_set_benign_errors(dp->read_pp, 1/*allowed*/); 1758 # endif /* BENIGN_ERRORS */ 1759 1760 # ifdef FIX_INDEX 1761 if ((dp->options & FIX_INDEX) != 0) 1762 png_set_check_for_invalid_index(dp->read_pp, 1/*on, no warning*/); 1763 # ifdef IGNORE_INDEX 1764 else 1765 # endif /* IGNORE_INDEX */ 1766 # endif /* FIX_INDEX */ 1767 # ifdef IGNORE_INDEX 1768 if ((dp->options & IGNORE_INDEX) != 0) /* DANGEROUS */ 1769 png_set_check_for_invalid_index(dp->read_pp, -1/*off completely*/); 1770 # endif /* IGNORE_INDEX */ 1771 1772 /* The png_read_png API requires us to make the info struct, but it does the 1773 * call to png_read_info. 1774 */ 1775 dp->ip = png_create_info_struct(dp->read_pp); 1776 if (dp->ip == NULL) 1777 png_error(dp->read_pp, "failed to create info struct"); 1778 1779 /* Set the IO handling */ 1780 png_set_read_fn(dp->read_pp, dp, read_function); 1781 1782 # ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 1783 png_set_keep_unknown_chunks(dp->read_pp, PNG_HANDLE_CHUNK_ALWAYS, NULL, 1784 0); 1785 # endif /* HANDLE_AS_UNKNOWN */ 1786 1787 # ifdef PNG_SET_USER_LIMITS_SUPPORTED 1788 /* Remove the user limits, if any */ 1789 png_set_user_limits(dp->read_pp, 0x7fffffff, 0x7fffffff); 1790 # endif /* SET_USER_LIMITS */ 1791 1792 /* Now read the PNG. */ 1793 start_timer(dp, PNGCP_TIME_READ); 1794 png_read_png(dp->read_pp, dp->ip, 0U/*transforms*/, NULL/*params*/); 1795 end_timer(dp, PNGCP_TIME_READ); 1796 dp->w = png_get_image_width(dp->read_pp, dp->ip); 1797 dp->h = png_get_image_height(dp->read_pp, dp->ip); 1798 dp->ct = png_get_color_type(dp->read_pp, dp->ip); 1799 dp->bpp = png_get_bit_depth(dp->read_pp, dp->ip) * 1800 png_get_channels(dp->read_pp, dp->ip); 1801 { 1802 /* png_get_rowbytes should never return 0 because the value is set by the 1803 * first call to png_set_IHDR, which should have happened by now, but just 1804 * in case: 1805 */ 1806 png_alloc_size_t rb = png_get_rowbytes(dp->read_pp, dp->ip); 1807 1808 if (rb == 0) 1809 png_error(dp->read_pp, "invalid row byte count from libpng"); 1810 1811 /* The size calc can overflow. */ 1812 if ((MAX_SIZE-dp->h)/rb < dp->h) 1813 png_error(dp->read_pp, "image too large"); 1814 1815 dp->size = rb * dp->h + dp->h/*filter byte*/; 1816 } 1817 1818 #ifdef FIX_INDEX 1819 if (dp->ct == PNG_COLOR_TYPE_PALETTE && (dp->options & FIX_INDEX) != 0) 1820 { 1821 int max = png_get_palette_max(dp->read_pp, dp->ip); 1822 png_colorp palette = NULL; 1823 int num = -1; 1824 1825 if (png_get_PLTE(dp->read_pp, dp->ip, &palette, &num) != PNG_INFO_PLTE 1826 || max < 0 || num <= 0 || palette == NULL) 1827 display_log(dp, LIBPNG_ERROR, "invalid png_get_PLTE result"); 1828 1829 if (max >= num) 1830 { 1831 /* 'Fix' the palette. */ 1832 int i; 1833 png_color newpal[256]; 1834 1835 for (i=0; i<num; ++i) 1836 newpal[i] = palette[i]; 1837 1838 /* Fill in any remainder with a warning color: */ 1839 for (; i<=max; ++i) 1840 { 1841 newpal[i].red = 0xbe; 1842 newpal[i].green = 0xad; 1843 newpal[i].blue = 0xed; 1844 } 1845 1846 png_set_PLTE(dp->read_pp, dp->ip, newpal, i); 1847 } 1848 } 1849 #endif /* FIX_INDEX */ 1850 1851 display_clean_read(dp); 1852 dp->operation = "none"; 1853 } 1854 1855 static void 1856 display_start_write(struct display *dp, const char *filename) 1857 { 1858 assert(dp->fp == NULL); 1859 1860 if ((dp->options & NOWRITE) != 0) 1861 dp->output_file = "<no write>"; 1862 1863 else 1864 { 1865 if (filename != NULL) 1866 { 1867 dp->output_file = filename; 1868 dp->fp = fopen(filename, "wb"); 1869 } 1870 1871 else 1872 { 1873 dp->output_file = "<stdout>"; 1874 dp->fp = stdout; 1875 } 1876 1877 if (dp->fp == NULL) 1878 display_log(dp, USER_ERROR, "%s: file open failed (%s)", 1879 dp->output_file, strerror(errno)); 1880 } 1881 } 1882 1883 static void PNGCBAPI 1884 write_function(png_structp pp, png_bytep data, png_size_t size) 1885 { 1886 struct display *dp = get_dp(pp); 1887 1888 /* The write fail is classed as a USER_ERROR, so --quiet does not turn it 1889 * off, this seems more likely to be correct. 1890 */ 1891 if (dp->fp == NULL || fwrite(data, size, 1U, dp->fp) == 1U) 1892 { 1893 dp->write_size += size; 1894 if (dp->write_size < size || dp->write_size == MAX_SIZE) 1895 png_error(pp, "IDAT size overflow"); 1896 } 1897 1898 else 1899 display_log(dp, USER_ERROR, "%s: PNG file write failed (%s)", 1900 dp->output_file, strerror(errno)); 1901 } 1902 1903 /* Compression option, 'method' is never set: there is no choice. 1904 * 1905 * IMPORTANT: the order of the entries in this macro determines the preference 1906 * order when two different combos of two of these options produce an IDAT of 1907 * the same size. The logic here is to put the things that affect the decoding 1908 * of the PNG image ahead of those that are relevant only to the encoding. 1909 */ 1910 #define SET_COMPRESSION\ 1911 SET(strategy, strategy);\ 1912 SET(windowBits, window_bits);\ 1913 SET(level, level);\ 1914 SET(memLevel, mem_level); 1915 1916 #ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED 1917 static void 1918 search_compression(struct display *dp) 1919 { 1920 /* Like set_compression below but use a more restricted search than 'all' */ 1921 int val; 1922 1923 # define SET(name, func) if (getsearchopts(dp, #name, &val))\ 1924 png_set_compression_ ## func(dp->write_pp, val); 1925 SET_COMPRESSION 1926 # undef SET 1927 } 1928 1929 static void 1930 set_compression(struct display *dp) 1931 { 1932 int val; 1933 1934 # define SET(name, func) if (getallopts(dp, #name, &val))\ 1935 png_set_compression_ ## func(dp->write_pp, val); 1936 SET_COMPRESSION 1937 # undef SET 1938 } 1939 1940 #ifdef PNG_SW_COMPRESS_level /* 1.7.0+ */ 1941 static void 1942 set_ICC_profile_compression(struct display *dp) 1943 { 1944 int val; 1945 1946 # define SET(name, func) if (getallopts(dp, "ICC-profile-" #name, &val))\ 1947 png_set_ICC_profile_compression_ ## func(dp->write_pp, val); 1948 SET_COMPRESSION 1949 # undef SET 1950 } 1951 #else 1952 # define set_ICC_profile_compression(dp) ((void)0) 1953 #endif 1954 #else 1955 # define search_compression(dp) ((void)0) 1956 # define set_compression(dp) ((void)0) 1957 # define set_ICC_profile_compression(dp) ((void)0) 1958 #endif /* WRITE_CUSTOMIZE_COMPRESSION */ 1959 1960 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED 1961 static void 1962 set_text_compression(struct display *dp) 1963 { 1964 int val; 1965 1966 # define SET(name, func) if (getallopts(dp, "text-" #name, &val))\ 1967 png_set_text_compression_ ## func(dp->write_pp, val); 1968 SET_COMPRESSION 1969 # undef SET 1970 } 1971 #else 1972 # define set_text_compression(dp) ((void)0) 1973 #endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ 1974 1975 static void 1976 write_png(struct display *dp, const char *destname) 1977 { 1978 display_clean_write(dp); /* safety */ 1979 display_start_write(dp, destname); 1980 1981 dp->write_pp = png_create_write_struct(PNG_LIBPNG_VER_STRING, dp, 1982 display_error, display_warning); 1983 1984 if (dp->write_pp == NULL) 1985 display_log(dp, LIBPNG_ERROR, "failed to create write png_struct"); 1986 1987 # ifdef PNG_BENIGN_ERRORS_SUPPORTED 1988 png_set_benign_errors(dp->write_pp, 1/*allowed*/); 1989 # endif /* BENIGN_ERRORS */ 1990 1991 png_set_write_fn(dp->write_pp, dp, write_function, NULL/*flush*/); 1992 1993 #ifdef IGNORE_INDEX 1994 if ((dp->options & IGNORE_INDEX) != 0) /* DANGEROUS */ 1995 png_set_check_for_invalid_index(dp->write_pp, -1/*off completely*/); 1996 #endif /* IGNORE_INDEX */ 1997 1998 /* Restore the text chunks when using libpng 1.6 or less; this is a macro 1999 * which expands to nothing in 1.7+ In earlier versions it tests 2000 * dp->text_stashed, which is only set (below) *after* the first write. 2001 */ 2002 text_restore(dp); 2003 2004 # ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 2005 png_set_keep_unknown_chunks(dp->write_pp, PNG_HANDLE_CHUNK_ALWAYS, NULL, 2006 0); 2007 # endif /* HANDLE_AS_UNKNOWN */ 2008 2009 # ifdef PNG_SET_USER_LIMITS_SUPPORTED 2010 /* Remove the user limits, if any */ 2011 png_set_user_limits(dp->write_pp, 0x7fffffff, 0x7fffffff); 2012 # endif 2013 2014 /* OPTION HANDLING */ 2015 /* compression outputs, IDAT and zTXt/iTXt: */ 2016 dp->tsp = dp->nsp; 2017 dp->nsp = dp->csp = 0; 2018 # ifdef PNG_SW_COMPRESS_png_level 2019 { 2020 int val; 2021 2022 /* This sets everything, but then the following options just override 2023 * the specific settings for ICC profiles and text. 2024 */ 2025 if (getallopts(dp, "compression", &val)) 2026 png_set_compression(dp->write_pp, val); 2027 2028 if (getallopts(dp, "ICC-profile-compression", &val)) 2029 png_set_ICC_profile_compression(dp->write_pp, val); 2030 2031 if (getallopts(dp, "text-compression", &val)) 2032 png_set_text_compression(dp->write_pp, val); 2033 } 2034 # endif /* png_level support */ 2035 if (dp->options & SEARCH) 2036 search_compression(dp); 2037 else 2038 set_compression(dp); 2039 set_ICC_profile_compression(dp); 2040 set_text_compression(dp); 2041 2042 { 2043 int val; 2044 2045 /* The permitted range is 1..0x7FFFFFFF, so the cast is safe */ 2046 if (get_option(dp, "IDAT-size", &val)) 2047 png_set_IDAT_size(dp->write_pp, val); 2048 } 2049 2050 /* filter handling */ 2051 # ifdef PNG_WRITE_FILTER_SUPPORTED 2052 { 2053 int val; 2054 2055 if (get_option(dp, "filter", &val)) 2056 png_set_filter(dp->write_pp, PNG_FILTER_TYPE_BASE, val); 2057 } 2058 # endif /* WRITE_FILTER */ 2059 2060 /* This just uses the 'read' info_struct directly, it contains the image. */ 2061 dp->write_size = 0U; 2062 start_timer(dp, PNGCP_TIME_WRITE); 2063 png_write_png(dp->write_pp, dp->ip, 0U/*transforms*/, NULL/*params*/); 2064 end_timer(dp, PNGCP_TIME_WRITE); 2065 2066 /* Make sure the file was written ok: */ 2067 if (dp->fp != NULL) 2068 { 2069 FILE *fp = dp->fp; 2070 dp->fp = NULL; 2071 if (fclose(fp)) 2072 display_log(dp, APP_ERROR, "%s: write failed (%s)", 2073 destname == NULL ? "stdout" : destname, strerror(errno)); 2074 } 2075 2076 /* Clean it on the way out - if control returns to the caller then the 2077 * written_file contains the required data. 2078 */ 2079 display_clean_write(dp); 2080 dp->operation = "none"; 2081 } 2082 2083 static void 2084 set_windowBits_hi(struct display *dp) 2085 { 2086 /* windowBits is in the range 8..15 but zlib maps '8' to '9' so it is only 2087 * worth using if the data size is 256 byte or less. 2088 */ 2089 int wb = MAX_WBITS; /* for large images */ 2090 int i = VLSIZE(windowBits_IDAT); 2091 2092 while (wb > 8 && dp->size <= 1U<<(wb-1)) --wb; 2093 2094 while (--i >= 0) if (VLNAME(windowBits_IDAT)[i].name == range_hi) break; 2095 2096 assert(i > 1); /* vl_windowBits_IDAT always has a RANGE() */ 2097 VLNAME(windowBits_IDAT)[i].value = wb; 2098 2099 assert(VLNAME(windowBits_IDAT)[--i].name == range_lo); 2100 VLNAME(windowBits_IDAT)[i].value = wb > 8 ? 9 : 8; 2101 2102 /* If wb == 8 then any search has been restricted to just one windowBits 2103 * entry. Record that here to avoid producing a spurious app-level warning 2104 * above. 2105 */ 2106 if (wb == 8) 2107 dp->min_windowBits = OPTIND(dp, windowBits); 2108 } 2109 2110 static int 2111 better_options(const struct display *dp) 2112 { 2113 /* Are these options better than the best found so far? Normally the 2114 * options are tested in preference order, best first, however when doing a 2115 * search operation on a range the range values are tested out of order. In 2116 * that case preferable options will get tested later. 2117 * 2118 * This function looks through the stack from the bottom up looking for an 2119 * option that does not match the current best value. When it finds one it 2120 * checks to see if it is more or less desireable and returns true or false 2121 * as appropriate. 2122 * 2123 * Notice that this means that the order options are pushed onto the stack 2124 * conveys a priority; lower/earlier options are more important than later 2125 * ones. 2126 */ 2127 unsigned int sp; 2128 2129 for (sp=0; sp<dp->csp; ++sp) 2130 { 2131 int c = compare_option(dp, sp); 2132 2133 if (c < 0) 2134 return 0; /* worse */ 2135 2136 else if (c > 0) 2137 return 1; /* better */ 2138 } 2139 2140 assert(0 && "unreached"); 2141 } 2142 2143 static void 2144 print_search_results(struct display *dp) 2145 { 2146 assert(dp->filename != NULL); 2147 printf("%s [%ld x %ld %d bpp %s, %lu bytes] %lu -> %lu with '%s'\n", 2148 dp->filename, (unsigned long)dp->w, (unsigned long)dp->h, dp->bpp, 2149 cts(dp->ct), (unsigned long)dp->size, (unsigned long)dp->read_size, 2150 (unsigned long)dp->best_size, dp->best); 2151 fflush(stdout); 2152 } 2153 2154 static void 2155 log_search(struct display *dp, unsigned int log_depth) 2156 { 2157 /* Log, and reset, the search so far: */ 2158 if (dp->nsp/*next entry to change*/ <= log_depth) 2159 { 2160 print_search_results(dp); 2161 /* Start again with this entry: */ 2162 dp->best_size = MAX_SIZE; 2163 } 2164 } 2165 2166 static void 2167 cp_one_file(struct display *dp, const char *filename, const char *destname) 2168 { 2169 unsigned int log_depth; 2170 2171 dp->filename = filename; 2172 dp->operation = "read"; 2173 dp->no_warnings = 0; 2174 2175 /* Read it then write it: */ 2176 if (filename != NULL && access(filename, R_OK) != 0) 2177 display_log(dp, USER_ERROR, "%s: invalid file name (%s)", 2178 filename, strerror(errno)); 2179 2180 read_png(dp, filename); 2181 2182 /* But 'destname' may be a directory. */ 2183 dp->operation = "write"; 2184 2185 /* Limit the upper end of the windowBits range for this file */ 2186 set_windowBits_hi(dp); 2187 2188 /* For logging, depth to log: */ 2189 { 2190 int val; 2191 2192 if (get_option(dp, "log-depth", &val) && val >= 0) 2193 log_depth = (unsigned int)/*SAFE*/val; 2194 2195 else 2196 log_depth = 0U; 2197 } 2198 2199 if (destname != NULL) /* else stdout */ 2200 { 2201 if (isdir(dp, destname)) 2202 { 2203 makename(dp, destname, filename); 2204 destname = dp->namebuf; 2205 } 2206 2207 else if (access(destname, W_OK) != 0 && errno != ENOENT) 2208 display_log(dp, USER_ERROR, "%s: invalid output name (%s)", destname, 2209 strerror(errno)); 2210 } 2211 2212 dp->nsp = 0; 2213 dp->curr[0] = 0; /* acts as a flag for the caller */ 2214 dp->opt_string_start = 0; 2215 dp->best[0] = 0; /* safety */ 2216 dp->best_size = MAX_SIZE; 2217 write_png(dp, destname); 2218 2219 /* Initialize the 'best' fields: */ 2220 strcpy(dp->best, dp->curr); 2221 dp->best_size = dp->write_size; 2222 2223 if (dp->nsp > 0) /* interating over lists */ 2224 { 2225 char *tmpname, tmpbuf[(sizeof dp->namebuf) + 4]; 2226 assert(dp->curr[0] == ' ' && dp->tsp > 0); 2227 2228 /* Cancel warnings on subsequent writes */ 2229 log_search(dp, log_depth); 2230 dp->no_warnings = 1; 2231 2232 /* Make a temporary name for the subsequent tests: */ 2233 if (destname != NULL) 2234 { 2235 strcpy(tmpbuf, destname); 2236 strcat(tmpbuf, ".tmp"); /* space for .tmp allocated above */ 2237 tmpname = tmpbuf; 2238 } 2239 2240 else 2241 tmpname = NULL; /* stdout */ 2242 2243 /* Loop to find the best option. */ 2244 do 2245 { 2246 write_png(dp, tmpname); 2247 2248 /* And compare the sizes (the write function makes sure write_size 2249 * doesn't overflow.) 2250 */ 2251 assert(dp->csp > 0); 2252 2253 if (dp->write_size < dp->best_size || 2254 (dp->write_size == dp->best_size && better_options(dp))) 2255 { 2256 if (destname != NULL && rename(tmpname, destname) != 0) 2257 display_log(dp, APP_ERROR, "rename %s %s failed (%s)", tmpname, 2258 destname, strerror(errno)); 2259 2260 strcpy(dp->best, dp->curr); 2261 dp->best_size = dp->write_size; 2262 } 2263 2264 else if (tmpname != NULL && unlink(tmpname) != 0) 2265 display_log(dp, APP_WARNING, "unlink %s failed (%s)", tmpname, 2266 strerror(errno)); 2267 2268 log_search(dp, log_depth); 2269 } 2270 while (dp->nsp > 0); 2271 2272 /* Do this for the 'sizes' option so that it reports the correct size. */ 2273 dp->write_size = dp->best_size; 2274 } 2275 } 2276 2277 static int 2278 cppng(struct display *dp, const char *file, const char *gv dest) 2279 /* Exists solely to isolate the setjmp clobbers which some versions of GCC 2280 * erroneously generate. 2281 */ 2282 { 2283 int ret = setjmp(dp->error_return); 2284 2285 if (ret == 0) 2286 { 2287 dp->errset = 1; 2288 cp_one_file(dp, file, dest); 2289 dp->errset = 0; 2290 return 0; 2291 } 2292 2293 else 2294 { 2295 dp->errset = 0; 2296 2297 if (ret < ERRORS) /* shouldn't longjmp on warnings */ 2298 display_log(dp, INTERNAL_ERROR, "unexpected return code %d", ret); 2299 2300 return ret; 2301 } 2302 } 2303 2304 int 2305 main(const int argc, const char * const * const argv) 2306 { 2307 /* For each file on the command line test it with a range of transforms */ 2308 int option_end; 2309 struct display d; 2310 2311 display_init(&d); 2312 2313 d.operation = "options"; 2314 for (option_end = 1; 2315 option_end < argc && opt_check(&d, argv[option_end]); 2316 ++option_end) 2317 { 2318 } 2319 2320 /* Do a quick check on the directory target case; when there are more than 2321 * two arguments the last one must be a directory. 2322 */ 2323 if (!(d.options & NOWRITE) && option_end+2 < argc && !checkdir(argv[argc-1])) 2324 { 2325 fprintf(stderr, 2326 "pngcp: %s: directory required with more than two arguments\n", 2327 argv[argc-1]); 2328 return 99; 2329 } 2330 2331 { 2332 int errors = 0; 2333 int i = option_end; 2334 2335 /* Do this at least once; if there are no arguments stdin/stdout are used. 2336 */ 2337 d.operation = "files"; 2338 do 2339 { 2340 const char *infile = NULL; 2341 const char *outfile = NULL; 2342 int ret; 2343 2344 if (i < argc) 2345 { 2346 infile = argv[i++]; 2347 if (!(d.options & NOWRITE) && i < argc) 2348 outfile = argv[argc-1]; 2349 } 2350 2351 ret = cppng(&d, infile, outfile); 2352 2353 if (ret) 2354 { 2355 if (ret > QUIET) /* abort on user or internal error */ 2356 return 99; 2357 2358 /* An error: the output is meaningless */ 2359 } 2360 2361 else if (d.best[0] != 0) 2362 { 2363 /* This result may already have been output, in which case best_size 2364 * has been reset. 2365 */ 2366 if (d.best_size < MAX_SIZE) 2367 print_search_results(&d); 2368 } 2369 2370 else if (d.options & SIZES) 2371 { 2372 printf("%s [%ld x %ld %d bpp %s, %lu bytes] %lu -> %lu [0x%lx]\n", 2373 infile, (unsigned long)d.w, (unsigned long)d.h, d.bpp, 2374 cts(d.ct), (unsigned long)d.size, (unsigned long)d.read_size, 2375 (unsigned long)d.write_size, (unsigned long)d.results); 2376 fflush(stdout); 2377 } 2378 2379 /* Here on any return, including failures, except user/internal issues 2380 */ 2381 { 2382 const int pass = (d.options & STRICT) ? 2383 RESULT_STRICT(d.results) : RESULT_RELAXED(d.results); 2384 2385 if (!pass) 2386 ++errors; 2387 2388 if (d.options & LOG) 2389 { 2390 int j; 2391 2392 printf("%s: pngcp", pass ? "PASS" : "FAIL"); 2393 2394 for (j=1; j<option_end; ++j) 2395 printf(" %s", argv[j]); 2396 2397 if (infile != NULL) 2398 printf(" %s", infile); 2399 2400 # ifdef PNG_PNGCP_TIMING_SUPPORTED 2401 /* When logging output the files for each file, if enabled. */ 2402 if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_READ) != 0) 2403 print_time(" read", d.read_time); 2404 2405 if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_WRITE) != 0) 2406 print_time(" write", d.write_time); 2407 # endif /* PNGCP_TIMING */ 2408 2409 printf("\n"); 2410 fflush(stdout); 2411 } 2412 } 2413 2414 display_clean(&d); 2415 } 2416 while (i+!(d.options & NOWRITE) < argc); 2417 /* I.e. for write cases after the first time through the loop require 2418 * there to be at least two arguments left and for the last one to be a 2419 * directory (this was checked above). 2420 */ 2421 2422 /* Release allocated memory */ 2423 display_destroy(&d); 2424 2425 # ifdef PNG_PNGCP_TIMING_SUPPORTED 2426 { 2427 int output = 0; 2428 2429 if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_READ) != 0) 2430 print_time("read", d.read_time_total), output = 1; 2431 2432 if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_WRITE) != 0) 2433 { 2434 if (output) putchar(' '); 2435 print_time("write", d.write_time_total); 2436 output = 1; 2437 } 2438 2439 if (output) putchar('\n'); 2440 } 2441 # endif /* PNGCP_TIMING */ 2442 2443 return errors != 0; 2444 } 2445 } 2446 #else /* !READ_PNG || !WRITE_PNG */ 2447 int 2448 main(void) 2449 { 2450 fprintf(stderr, "pngcp: no support for png_read/write_image\n"); 2451 return 77; 2452 } 2453 #endif /* !READ_PNG || !WRITE_PNG */ 2454