3 * Copyright (c) 2016,2022 John Cunningham Bowler
5 * This code is released under the libpng license.
6 * For conditions of distribution and use, see the disclaimer
9 * This is an example of copying a PNG without changes using the png_read_png
10 * and png_write_png interfaces. A considerable number of options are provided
11 * to manipulate the compression of the PNG data and other compressed chunks.
13 * For a more extensive example that uses the transforms see
14 * contrib/libtests/pngimage.c in the libpng distribution.
16 * This code is not intended for installation in a release system; the command
17 * line options are not documented and most of the behavior is intended for
18 * testing libpng performance, both speed and compression.
21 #include "pnglibconf.h" /* To find how libpng was configured. */
23 #ifdef PNG_PNGCP_TIMING_SUPPORTED
26 * This test is here to allow POSIX.1b extensions to be used if enabled in
27 * the compile; specifically the code requires_POSIX_C_SOURCE support of
28 * 199309L or later to enable clock_gettime use.
30 * IF this causes problems THEN compile with a strict ANSI C compiler and let
31 * this code turn on the POSIX features that it minimally requires.
33 * IF this does not work there is probably a bug in your ANSI C compiler or
34 * your POSIX implementation.
36 # define _POSIX_C_SOURCE 199309L
37 #else /* No timing support required */
38 # define _POSIX_SOURCE 1
41 #if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
47 /* Define the following to use this test against your installed libpng, rather
48 * than the one being built here:
50 #ifdef PNG_FREESTANDING_TESTS
53 # include "../../png.h"
56 #if PNG_LIBPNG_VER < 10700
57 /* READ_PNG and WRITE_PNG were not defined, so: */
58 # ifdef PNG_INFO_IMAGE_SUPPORTED
59 # ifdef PNG_SEQUENTIAL_READ_SUPPORTED
60 # define PNG_READ_PNG_SUPPORTED
61 # endif /* SEQUENTIAL_READ */
62 # ifdef PNG_WRITE_SUPPORTED
63 # define PNG_WRITE_PNG_SUPPORTED
65 # endif /* INFO_IMAGE */
66 #endif /* pre 1.7.0 */
68 #if (defined(PNG_READ_PNG_SUPPORTED)) && (defined(PNG_WRITE_PNG_SUPPORTED))
81 #ifndef PNG_SETJMP_SUPPORTED
82 # include <setjmp.h> /* because png.h did *not* include this */
86 # define voidcast(type, value) static_cast<type>(value)
88 # define voidcast(type, value) (value)
89 #endif /* __cplusplus */
92 /* Many versions of GCC erroneously report that local variables unmodified
93 * within the scope of a setjmp may be clobbered. This hacks round the
94 * problem (sometimes) without harming other compilers.
101 /* 'CLOCK_PROCESS_CPUTIME_ID' is one of the clock timers for clock_gettime. It
102 * need not be supported even when clock_gettime is available. It returns the
103 * 'CPU' time the process has consumed. 'CPU' time is assumed to include time
104 * when the CPU is actually blocked by a pending cache fill but not time
105 * waiting for page faults. The attempt is to get a measure of the actual time
106 * the implementation takes to read a PNG ignoring the potentially very large IO
109 #ifdef PNG_PNGCP_TIMING_SUPPORTED
110 # include <time.h> /* clock_gettime and associated definitions */
111 # ifndef CLOCK_PROCESS_CPUTIME_ID
112 /* Prevent inclusion of the spurious code: */
113 # undef PNG_PNGCP_TIMING_SUPPORTED
115 #endif /* PNGCP_TIMING */
117 /* So if the timing feature has been activated: */
119 /* This structure is used to control the test of a single file. */
122 VERBOSE, /* switches on all messages */
124 WARNINGS, /* switches on warnings */
127 ERRORS, /* just errors */
128 APP_FAIL, /* continuable error - no need to longjmp */
129 LIBPNG_ERROR, /* this and higher cause a longjmp */
130 LIBPNG_BUG, /* erroneous behavior in libpng */
131 APP_ERROR, /* such as out-of-memory in a callback */
132 QUIET, /* no normal messages */
133 USER_ERROR, /* such as file-not-found */
136 #define LEVEL_MASK 0xf /* where the level is in 'options' */
138 #define STRICT 0x010 /* Fail on warnings as well as errors */
139 #define LOG 0x020 /* Log pass/fail to stdout */
140 #define CONTINUE 0x040 /* Continue on APP_FAIL errors */
141 #define SIZES 0x080 /* Report input and output sizes */
142 #define SEARCH 0x100 /* Search IDAT compression options */
143 #define NOWRITE 0x200 /* Do not write an output file */
144 #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
145 # define IGNORE_INDEX 0x400 /* Ignore out of range palette indices (BAD!) */
146 # ifdef PNG_GET_PALETTE_MAX_SUPPORTED
147 # define FIX_INDEX 0x800 /* 'Fix' out of range palette indices (OK) */
148 # endif /* GET_PALETTE_MAX */
149 #endif /* CHECK_FOR_INVALID_INDEX */
150 #define OPTION 0x80000000 /* Used for handling options */
151 #define LIST 0x80000001 /* Used for handling options */
153 /* Result masks apply to the result bits in the 'results' field below; these
154 * bits are simple 1U<<error_level. A pass requires either nothing worse than
155 * warnings (--relaxes) or nothing worse than information (--strict)
157 #define RESULT_STRICT(r) (((r) & ~((1U<<WARNINGS)-1)) == 0)
158 #define RESULT_RELAXED(r) (((r) & ~((1U<<ERRORS)-1)) == 0)
160 /* OPTION DEFINITIONS */
161 static const char range_lo[] = "low";
162 static const char range_hi[] = "high";
163 static const char all[] = "all";
164 #define RANGE(lo,hi) { range_lo, lo }, { range_hi, hi }
165 typedef struct value_list
167 const char *name; /* the command line name of the value */
168 int value; /* the actual value to use */
171 static const value_list
172 #ifdef PNG_SW_COMPRESS_png_level
175 /* Overall compression control. The order controls the search order for
176 * 'all'. Since the search is for the smallest the order used is low memory
179 { "low-memory", PNG_COMPRESSION_LOW_MEMORY },
180 { "high-speed", PNG_COMPRESSION_HIGH_SPEED },
181 { "high-read-speed", PNG_COMPRESSION_HIGH_READ_SPEED },
182 { "low", PNG_COMPRESSION_LOW },
183 { "medium", PNG_COMPRESSION_MEDIUM },
184 { "old", PNG_COMPRESSION_COMPAT },
185 { "high", PNG_COMPRESSION_HIGH },
188 #endif /* SW_COMPRESS_png_level */
190 #if defined(PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED) ||\
191 defined(PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED)
194 /* This controls the order of search. */
195 { "huffman", Z_HUFFMAN_ONLY },
197 { "fixed", Z_FIXED }, /* the remainder do window searches */
198 { "filtered", Z_FILTERED },
199 { "default", Z_DEFAULT_STRATEGY },
202 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
203 vl_windowBits_text[] =
205 { "default", MAX_WBITS/*from zlib*/ },
207 RANGE(8, MAX_WBITS/*from zlib*/),
210 #endif /* text compression */
213 { "default", Z_DEFAULT_COMPRESSION /* this is -1 */ },
214 { "none", Z_NO_COMPRESSION },
215 { "speed", Z_BEST_SPEED },
216 { "best", Z_BEST_COMPRESSION },
217 { "0", Z_NO_COMPRESSION },
218 RANGE(1, 9), /* this deliberately excludes '0' */
223 { "max", MAX_MEM_LEVEL }, /* zlib maximum */
224 { "1", 1 }, /* zlib minimum */
225 { "default", 8 }, /* zlib default */
229 { "5", 5 }, /* for explicit testing */
230 RANGE(6, MAX_MEM_LEVEL/*zlib*/), /* exclude 5 and below: zlib bugs */
233 #endif /* WRITE_CUSTOMIZE_*COMPRESSION */
234 #ifdef PNG_WRITE_FILTER_SUPPORTED
237 { all, PNG_ALL_FILTERS },
238 { "off", PNG_NO_FILTERS },
239 { "none", PNG_FILTER_NONE },
240 { "sub", PNG_FILTER_SUB },
241 { "up", PNG_FILTER_UP },
242 { "avg", PNG_FILTER_AVG },
243 { "paeth", PNG_FILTER_PAETH }
245 #endif /* WRITE_FILTER */
246 #ifdef PNG_PNGCP_TIMING_SUPPORTED
247 # define PNGCP_TIME_READ 1
248 # define PNGCP_TIME_WRITE 2
251 { "both", PNGCP_TIME_READ+PNGCP_TIME_WRITE },
253 { "read", PNGCP_TIME_READ },
254 { "write", PNGCP_TIME_WRITE }
256 #endif /* PNGCP_TIMING */
257 vl_IDAT_size[] = /* for png_set_IDAT_size */
259 { "default", 0x7FFFFFFF },
263 #ifndef PNG_SW_IDAT_size
265 # define png_set_IDAT_size(p,v) png_set_compression_buffer_size(p, v)
266 #endif /* !SW_IDAT_size */
267 #define SL 8 /* stack limit in display, below */
268 vl_log_depth[] = { { "on", 1 }, { "off", 0 }, RANGE(0, SL) },
269 vl_on_off[] = { { "on", 1 }, { "off", 0 } };
271 #ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
273 vl_windowBits_IDAT[] =
275 { "default", MAX_WBITS },
277 RANGE(8, MAX_WBITS), /* modified by set_windowBits_hi */
280 #endif /* IDAT compression */
282 typedef struct option
284 const char *name; /* name of the option */
285 png_uint_32 opt; /* an option, or OPTION or LIST */
286 png_byte search; /* Search on --search */
287 png_byte value_count; /* length of the list of values: */
288 const value_list *values; /* values for OPTION or LIST */
291 static const option options[] =
293 /* struct display options, these are set when the command line is read */
294 # define S(n,v) { #n, v, 0, 2, vl_on_off },
296 S(warnings, WARNINGS)
301 S(continue, CONTINUE)
306 S(ignore-palette-index, IGNORE_INDEX)
307 # endif /* IGNORE_INDEX */
309 S(fix-palette-index, FIX_INDEX)
310 # endif /* FIX_INDEX */
313 /* OPTION settings, these and LIST settings are read on demand */
314 # define VLNAME(name) vl_ ## name
315 # define VLSIZE(name) voidcast(png_byte,\
316 (sizeof VLNAME(name))/(sizeof VLNAME(name)[0]))
317 # define VL(oname, name, type, search)\
318 { oname, type, search, VLSIZE(name), VLNAME(name) },
319 # define VLO(oname, name, search) VL(oname, name, OPTION, search)
321 # ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
322 # define VLCIDAT(name) VLO(#name, name, 1/*search*/)
323 # ifdef PNG_SW_COMPRESS_level
324 # define VLCiCCP(name) VLO("ICC-profile-" #name, name, 0/*search*/)
326 # define VLCiCCP(name)
329 # define VLCIDAT(name)
330 # define VLCiCCP(name)
331 # endif /* WRITE_CUSTOMIZE_COMPRESSION */
333 # ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
334 # define VLCzTXt(name) VLO("text-" #name, name, 0/*search*/)
336 # define VLCzTXt(name)
337 # endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
339 # define VLC(name) VLCIDAT(name) VLCiCCP(name) VLCzTXt(name)
341 # ifdef PNG_SW_COMPRESS_png_level
342 /* The libpng compression level isn't searched because it just sets the
343 * other things that are searched!
345 VLO("compression", compression, 0)
346 VLO("text-compression", compression, 0)
347 VLO("ICC-profile-compression", compression, 0)
348 # endif /* SW_COMPRESS_png_level */
350 VLO("windowBits", windowBits_IDAT, 1)
351 # ifdef PNG_SW_COMPRESS_windowBits
352 VLO("ICC-profile-windowBits", windowBits_text/*sic*/, 0)
354 VLO("text-windowBits", windowBits_text, 0)
357 VLO("IDAT-size", IDAT_size, 0)
358 VLO("log-depth", log_depth, 0)
363 # define VLL(name, search) VL(#name, name, LIST, search)
364 #ifdef PNG_WRITE_FILTER_SUPPORTED
366 #endif /* WRITE_FILTER */
367 #ifdef PNG_PNGCP_TIMING_SUPPORTED
369 #endif /* PNGCP_TIMING */
375 static const size_t option_count((sizeof options)/(sizeof options[0]));
376 #else /* !__cplusplus */
377 # define option_count ((sizeof options)/(sizeof options[0]))
378 #endif /* !__cplusplus */
385 case PNG_COLOR_TYPE_PALETTE: return "P";
386 case PNG_COLOR_TYPE_GRAY: return "G";
387 case PNG_COLOR_TYPE_GRAY_ALPHA: return "GA";
388 case PNG_COLOR_TYPE_RGB: return "RGB";
389 case PNG_COLOR_TYPE_RGB_ALPHA: return "RGBA";
390 default: return "INVALID";
396 jmp_buf error_return; /* Where to go to on error */
397 unsigned int errset; /* error_return is set */
399 const char *operation; /* What is happening */
400 const char *filename; /* The name of the original file */
401 const char *output_file; /* The name of the output file */
403 /* Used on both read and write: */
406 /* Used on a read, both the original read and when validating a written
409 png_alloc_size_t read_size;
412 # if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED
413 png_textp text_ptr; /* stash of text chunks */
416 # endif /* pre 1.7 */
418 # ifdef PNG_PNGCP_TIMING_SUPPORTED
419 struct timespec read_time;
420 struct timespec read_time_total;
421 struct timespec write_time;
422 struct timespec write_time_total;
423 # endif /* PNGCP_TIMING */
425 /* Used to write a new image (the original info_ptr is used) */
426 # define MAX_SIZE ((png_alloc_size_t)(-1))
427 png_alloc_size_t write_size;
428 png_alloc_size_t best_size;
429 png_structp write_pp;
431 /* Base file information */
432 png_alloc_size_t size;
437 int no_warnings; /* Do not output libpng warnings */
438 int min_windowBits; /* The windowBits range is 8..8 */
440 /* Options handling */
441 png_uint_32 results; /* A mask of errors seen */
442 png_uint_32 options; /* See display_log below */
443 png_byte entry[option_count]; /* The selected entry+1 of an option
444 * that appears on the command line, or
445 * 0 if it was not given. */
446 int value[option_count]; /* Corresponding value */
448 /* Compression exhaustive testing */
449 /* Temporary variables used only while testing a single collection of
452 unsigned int csp; /* next stack entry to use */
453 unsigned int nsp; /* highest active entry+1 found so far */
455 /* Values used while iterating through all the combinations of settings for a
458 unsigned int tsp; /* nsp from the last run; this is the
459 * index+1 of the highest active entry on
460 * this run; this entry will be advanced.
462 int opt_string_start; /* Position in buffer for the first
463 * searched option; non-zero if earlier
464 * options were set on the command line.
468 png_alloc_size_t best_size; /* Best so far for this option */
469 png_alloc_size_t lo_size;
470 png_alloc_size_t hi_size;
471 int lo, hi; /* For binary chop of a range */
472 int best_val; /* Best value found so far */
473 int opt_string_end; /* End of the option string in 'curr' */
474 png_byte opt; /* The option being tested */
475 png_byte entry; /* The next value entry to be tested */
476 png_byte end; /* This is the last entry */
477 } stack[SL]; /* Stack of entries being tested */
478 char curr[32*SL]; /* current options being tested */
479 char best[32*SL]; /* best options */
481 char namebuf[FILENAME_MAX]; /* output file name */
485 display_init(struct display *dp)
486 /* Call this only once right at the start to initialize the control
487 * structure, the (struct buffer) lists are maintained across calls - the
488 * memory is not freed.
491 memset(dp, 0, sizeof *dp);
492 dp->operation = "internal error";
493 dp->filename = "command line";
494 dp->output_file = "no output file";
495 dp->options = WARNINGS; /* default to !verbose, !quiet */
500 dp->min_windowBits = -1; /* this is an OPTIND, so -1 won't match anything */
501 # if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED
504 dp->text_stashed = 0;
505 # endif /* pre 1.7 */
509 display_clean_read(struct display *dp, int freeinfo)
511 if (dp->read_pp != NULL)
512 png_destroy_read_struct(&dp->read_pp, freeinfo ? &dp->ip : NULL, NULL);
523 display_clean_write(struct display *dp, int freeinfo)
532 if (dp->write_pp != NULL)
533 png_destroy_write_struct(&dp->write_pp, freeinfo ? &dp->ip : NULL);
537 display_clean(struct display *dp)
539 display_clean_read(dp, 1/*freeinfo*/);
540 display_clean_write(dp, 1/*freeinfo*/);
541 dp->output_file = NULL;
543 # if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED
544 /* This is actually created and used by the write code, but only
545 * once; it has to be retained for subsequent writes of the same file.
547 if (dp->text_stashed)
549 dp->text_stashed = 0;
554 # endif /* pre 1.7 */
556 /* leave the filename for error detection */
557 dp->results = 0; /* reset for next time */
561 display_destroy(struct display *dp)
563 /* Release any memory held in the display. */
567 static struct display *
568 get_dp(png_structp pp)
569 /* The display pointer is always stored in the png_struct error pointer */
571 struct display *dp = (struct display*)png_get_error_ptr(pp);
575 fprintf(stderr, "pngcp: internal error (no display)\n");
576 exit(99); /* prevents a crash */
584 # define VGATTR __attribute__((__format__ (__printf__,3,4)))
585 /* Required to quiet GNUC warnings when the compiler sees a stdarg function
586 * that calls one of the stdio v APIs.
592 display_log(struct display *dp, error_level level, const char *fmt, ...)
593 /* 'level' is as above, fmt is a stdio style format string. This routine
594 * does not return if level is above LIBPNG_WARNING
597 dp->results |= 1U << level;
599 if (level > (error_level)(dp->options & LEVEL_MASK))
606 case INFORMATION: lp = "information"; break;
607 case LIBPNG_WARNING: lp = "warning(libpng)"; break;
608 case APP_WARNING: lp = "warning(pngcp)"; break;
609 case APP_FAIL: lp = "error(continuable)"; break;
610 case LIBPNG_ERROR: lp = "error(libpng)"; break;
611 case LIBPNG_BUG: lp = "bug(libpng)"; break;
612 case APP_ERROR: lp = "error(pngcp)"; break;
613 case USER_ERROR: lp = "error(user)"; break;
615 case INTERNAL_ERROR: /* anything unexpected is an internal error: */
616 case VERBOSE: case WARNINGS: case ERRORS: case QUIET:
617 default: lp = "bug(pngcp)"; break;
620 fprintf(stderr, "%s: %s: %s",
621 dp->filename != NULL ? dp->filename : "<stdin>", lp, dp->operation);
623 fprintf(stderr, ": ");
626 vfprintf(stderr, fmt, ap);
631 /* else do not output any message */
633 /* Errors cause this routine to exit to the fail code */
634 if (level > APP_FAIL || (level > ERRORS && !(dp->options & CONTINUE)))
637 longjmp(dp->error_return, level);
644 #if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED
646 text_stash(struct display *dp)
648 /* libpng 1.6 and earlier fixed a bug whereby text chunks were written
649 * multiple times by png_write_png; the issue was that png_write_png passed
650 * the same png_info to both png_write_info and png_write_end. Rather than
651 * fixing it by recording the information in the png_struct, or by recording
652 * where to write the chunks, the fix made was to change the 'compression'
653 * field of the chunk to invalid values, rendering the png_info somewhat
656 * The only fix for this given that we use the png_info more than once is to
657 * make a copy of the text chunks and png_set_text it each time. This adds a
658 * text chunks, so they get replicated, but only the new set gets written
659 * each time. This uses memory like crazy but there is no way to delete the
660 * useless chunks from the png_info.
662 * To make this slightly more efficient only the top level structure is
663 * copied; since the old strings are actually preserved (in 1.6 and earlier)
664 * this happens to work.
666 png_textp chunks = NULL;
668 dp->num_text = png_get_text(dp->write_pp, dp->ip, &chunks, NULL);
670 if (dp->num_text > 0)
672 dp->text_ptr = voidcast(png_textp, malloc(dp->num_text * sizeof *chunks));
674 if (dp->text_ptr == NULL)
675 display_log(dp, APP_ERROR, "text chunks: stash malloc failed");
678 memcpy(dp->text_ptr, chunks, dp->num_text * sizeof *chunks);
681 dp->text_stashed = 1; /* regardless of whether there are chunks or not */
684 #define text_stash(dp) if (!dp->text_stashed) text_stash(dp)
687 text_restore(struct display *dp)
689 /* libpng makes a copy, so this is fine: */
690 if (dp->text_ptr != NULL)
691 png_set_text(dp->write_pp, dp->ip, dp->text_ptr, dp->num_text);
694 #define text_restore(dp) if (dp->text_stashed) text_restore(dp)
697 #define text_stash(dp) ((void)0)
698 #define text_restore(dp) ((void)0)
703 * The command handles options of the forms:
706 * Turn an option on (Option)
708 * Turn an option off (Option)
710 * Set an option to a value (Value)
711 * --option=val1,val2,val3
712 * Set an option to a bitmask constructed from the values (List)
715 option_index(struct display *dp, const char *opt, size_t len)
716 /* Return the index (in options[]) of the given option, outputs an error if
717 * it does not exist. Takes the name of the option and a length (number of
718 * characters in the name).
723 for (j=0; j<option_count; ++j)
724 if (strncmp(options[j].name, opt, len) == 0 && options[j].name[len] == 0)
727 /* If the setjmp buffer is set the code is asking for an option index; this
728 * is bad. Otherwise this is the command line option parsing.
730 display_log(dp, dp->errset ? INTERNAL_ERROR : USER_ERROR,
731 "%.*s: unknown option", (int)/*SAFE*/len, opt);
732 abort(); /* NOT REACHED */
735 /* This works for an option name (no quotes): */
736 #define OPTIND(dp, name) option_index(dp, #name, (sizeof #name)-1)
739 get_option(struct display *dp, const char *opt, int *value)
741 png_byte i = option_index(dp, opt, strlen(opt));
743 if (dp->entry[i]) /* option was set on command line */
745 *value = dp->value[i];
754 set_opt_string_(struct display *dp, unsigned int sp, png_byte opt,
755 const char *entry_name)
756 /* Add the appropriate option string to dp->curr. */
761 offset = dp->stack[sp-1].opt_string_end;
764 offset = dp->opt_string_start;
766 if (entry_name == range_lo)
767 add = sprintf(dp->curr+offset, " --%s=%d", options[opt].name,
771 add = sprintf(dp->curr+offset, " --%s=%s", options[opt].name, entry_name);
774 display_log(dp, INTERNAL_ERROR, "sprintf failed");
776 assert(offset+add < (int)/*SAFE*/sizeof dp->curr);
781 set_opt_string(struct display *dp, unsigned int sp)
782 /* Add the appropriate option string to dp->curr. */
784 dp->stack[sp].opt_string_end = set_opt_string_(dp, sp, dp->stack[sp].opt,
785 options[dp->stack[sp].opt].values[dp->stack[sp].entry].name);
789 record_opt(struct display *dp, png_byte opt, const char *entry_name)
790 /* Record this option in dp->curr; called for an option not being searched,
791 * the caller passes in the name of the value, or range_lo to use the
795 unsigned int sp = dp->csp; /* stack entry of next searched option */
799 /* At top of stack; add the opt string for this entry to the previous
800 * searched entry or the start of the dp->curr buffer if there is nothing
801 * on the stack yet (sp == 0).
803 int offset = set_opt_string_(dp, sp, opt, entry_name);
806 dp->stack[sp-1].opt_string_end = offset;
809 dp->opt_string_start = offset;
812 /* else do nothing: option already recorded */
816 opt_list_end(struct display *dp, png_byte opt, png_byte entry)
818 if (options[opt].values[entry].name == range_lo)
819 return entry+1U >= options[opt].value_count /* missing range_hi */ ||
820 options[opt].values[entry+1U].name != range_hi /* likewise */ ||
821 options[opt].values[entry+1U].value <= dp->value[opt] /* range end */;
824 return entry+1U >= options[opt].value_count /* missing 'all' */ ||
825 options[opt].values[entry+1U].name == all /* last entry */;
829 push_opt(struct display *dp, unsigned int sp, png_byte opt, int search)
830 /* Push a new option onto the stack, initializing the new stack entry
831 * appropriately; this does all the work of next_opt (setting end/nsp) for
832 * the first entry in the list.
836 const char *entry_name;
838 assert(sp == dp->tsp && sp < SL);
840 /* The starting entry is entry 0 unless there is a range in which case it is
841 * the entry corresponding to range_lo:
843 entry = options[opt].value_count;
848 entry_name = options[opt].values[--entry].name;
849 if (entry_name == range_lo)
855 dp->stack[sp].best_size =
856 dp->stack[sp].lo_size =
857 dp->stack[sp].hi_size = MAX_SIZE;
859 if (search && entry_name == range_lo) /* search this range */
861 dp->stack[sp].lo = options[opt].values[entry].value;
862 /* check for a mal-formed RANGE above: */
863 assert(entry+1 < options[opt].value_count &&
864 options[opt].values[entry+1].name == range_hi);
865 dp->stack[sp].hi = options[opt].values[entry+1].value;
870 /* next_opt will just iterate over the range. */
871 dp->stack[sp].lo = INT_MAX;
872 dp->stack[sp].hi = INT_MIN; /* Prevent range chop */
875 dp->stack[sp].opt = opt;
876 dp->stack[sp].entry = entry;
877 dp->stack[sp].best_val = dp->value[opt] = options[opt].values[entry].value;
879 set_opt_string(dp, sp);
881 /* This works for the search case too; if the range has only one entry 'end'
882 * will be marked here.
884 if (opt_list_end(dp, opt, entry))
886 dp->stack[sp].end = 1;
887 /* Skip the warning if pngcp did this itself. See the code in
890 if (opt != dp->min_windowBits)
891 display_log(dp, APP_WARNING, "%s: only testing one value",
897 dp->stack[sp].end = 0;
901 /* Do a lazy cache of the text chunks for libpng 1.6 and earlier; this is
902 * because they can only be written once(!) so if we are going to re-use the
903 * png_info we need a copy.
909 next_opt(struct display *dp, unsigned int sp)
910 /* Return the next value for this option. When called 'sp' is expected to be
911 * the topmost stack entry - only the topmost entry changes each time round -
912 * and there must be a valid entry to return. next_opt will set dp->nsp to
913 * sp+1 if more entries are available, otherwise it will not change it and
914 * set dp->stack[s].end to true.
919 const char *entry_name;
921 /* dp->stack[sp] must be the top stack entry and it must be active: */
922 assert(sp+1U == dp->tsp && !dp->stack[sp].end);
924 opt = dp->stack[sp].opt;
925 entry = dp->stack[sp].entry;
926 assert(entry+1U < options[opt].value_count);
927 entry_name = options[opt].values[entry].name;
928 assert(entry_name != NULL);
930 /* For ranges increment the value but don't change the entry, for all other
931 * cases move to the next entry and load its value:
933 if (entry_name == range_lo) /* a range */
935 /* A range can be iterated over or searched. The default iteration option
936 * is indicated by hi < lo on the stack, otherwise the range being search
937 * is [lo..hi] (inclusive).
939 if (dp->stack[sp].lo > dp->stack[sp].hi)
944 /* This is the best size found for this option value: */
945 png_alloc_size_t best_size = dp->stack[sp].best_size;
946 int lo = dp->stack[sp].lo;
947 int hi = dp->stack[sp].hi;
948 int val = dp->value[opt];
950 search = 1; /* end is determined here */
951 assert(best_size < MAX_SIZE);
955 /* Finding the best for the low end of the range: */
956 dp->stack[sp].lo_size = best_size;
959 if (hi == val+1) /* only 2 entries */
960 dp->stack[sp].end = 1;
967 dp->stack[sp].hi_size = best_size;
968 assert(val > lo+1); /* else 'end' set above */
970 if (val == lo+2) /* only three entries to test */
971 dp->stack[sp].end = 1;
978 png_alloc_size_t lo_size = dp->stack[sp].lo_size;
979 png_alloc_size_t hi_size = dp->stack[sp].hi_size;
981 /* lo and hi should have been tested. */
982 assert(lo_size < MAX_SIZE && hi_size < MAX_SIZE);
984 /* These cases arise with the 'probe' handling below when there is a
985 * dip or peak in the size curve.
987 if (val < lo) /* probing a new lo */
989 /* Swap lo and val: */
990 dp->stack[sp].lo = val;
991 dp->stack[sp].lo_size = best_size;
994 lo = dp->stack[sp].lo;
995 lo_size = dp->stack[sp].lo_size;
998 else if (val > hi) /* probing a new hi */
1000 /* Swap hi and val: */
1001 dp->stack[sp].hi = val;
1002 dp->stack[sp].hi_size = best_size;
1004 best_size = hi_size;
1005 hi = dp->stack[sp].hi;
1006 hi_size = dp->stack[sp].hi_size;
1009 /* The following should be true or something got messed up above. */
1010 assert(lo < val && val < hi);
1012 /* If there are only four entries (lo, val, hi plus one more) just
1013 * test the remaining entry.
1017 /* Because of the 'probe' code val can either be lo+1 or hi-1; we
1018 * need to test the other.
1020 val = lo + ((val == lo+1) ? 2 : 1);
1021 assert(lo < val && val < hi);
1022 dp->stack[sp].end = 1;
1027 /* There are at least 2 entries still untested between lo and hi,
1028 * i.e. hi >= lo+4. 'val' is the midpoint +/- 0.5
1030 * Separate out the four easy cases when lo..val..hi are
1031 * monotonically decreased or (more weird) increasing:
1035 if (lo_size <= best_size && best_size <= hi_size)
1037 /* Select the low range; testing this first favours the low
1038 * range over the high range when everything comes out equal.
1039 * Because of the probing 'val' may be lo+1. In that case end
1040 * the search and set 'val' to lo+2.
1045 dp->stack[sp].end = 1;
1050 dp->stack[sp].hi = hi = val;
1051 dp->stack[sp].hi_size = best_size;
1052 val = (lo + val) / 2;
1056 else if (lo_size >= best_size && best_size >= hi_size)
1058 /* Monotonically decreasing size; this is the expected case.
1059 * Select the high end of the range. As above, val may be
1065 dp->stack[sp].end = 1;
1070 dp->stack[sp].lo = lo = val;
1071 dp->stack[sp].lo_size = best_size;
1072 val = (val + hi) / 2;
1076 /* If both those tests failed 'best_size' is either greater than
1077 * or less than both lo_size and hi_size. There is a peak or dip
1078 * in the curve of sizes from lo to hi and val is on the peak or
1081 * Because the ranges being searched as so small (level is 1..9,
1082 * windowBits 8..15, memLevel 1..9) there will only be at most
1083 * three untested values between lo..val and val..hi, so solve
1084 * the problem by probing down from hi or up from lo, whichever
1087 * This is the place where 'val' is set to outside the range
1088 * lo..hi, described as 'probing', though maybe 'narrowing' would
1091 else if (lo_size <= hi_size) /* down from hi */
1093 dp->stack[sp].hi = val;
1094 dp->stack[sp].hi_size = best_size;
1098 else /* up from low */
1100 dp->stack[sp].lo = val;
1101 dp->stack[sp].lo_size = best_size;
1105 /* lo and hi are still the true range limits, check for the end
1110 dp->stack[sp].end = 1;
1114 assert(val != dp->stack[sp].best_val); /* should be a new value */
1115 dp->value[opt] = val;
1116 dp->stack[sp].best_size = MAX_SIZE;
1122 /* Increment 'entry' */
1123 dp->value[opt] = options[opt].values[++entry].value;
1124 dp->stack[sp].entry = entry;
1127 set_opt_string(dp, sp);
1129 if (!search && opt_list_end(dp, opt, entry)) /* end of list */
1130 dp->stack[sp].end = 1;
1132 else if (!dp->stack[sp].end) /* still active after all these tests */
1137 compare_option(const struct display *dp, unsigned int sp)
1139 int opt = dp->stack[sp].opt;
1141 /* If the best so far is numerically less than the current value the
1142 * current set of options is invariably worse.
1144 if (dp->stack[sp].best_val < dp->value[opt])
1147 /* Lists of options are searched out of numerical order (currently only
1148 * strategy), so only return +1 here when a range is being searched.
1150 else if (dp->stack[sp].best_val > dp->value[opt])
1152 if (dp->stack[sp].lo <= dp->stack[sp].hi /*searching*/)
1160 return 0; /* match; current value is the best one */
1164 advance_opt(struct display *dp, png_byte opt, int search)
1166 unsigned int sp = dp->csp++; /* my stack entry */
1168 assert(sp >= dp->nsp); /* nsp starts off zero */
1170 /* If the entry was active in the previous run dp->stack[sp] is already
1171 * set up and dp->tsp will be greater than sp, otherwise a new entry
1172 * needs to be created.
1174 * dp->nsp is handled this way:
1176 * 1) When an option is pushed onto the stack dp->nsp and dp->tsp are
1177 * both set (by push_opt) to the next stack entry *unless* there is
1178 * only one entry in the new list, in which case dp->stack[sp].end
1181 * 2) For the top stack entry next_opt is called. The entry must be
1182 * active (dp->stack[sp].end is not set) and either 'nsp' or 'end'
1183 * will be updated as appropriate.
1185 * 3) For lower stack entries nsp is set unless the stack entry is
1186 * already at the end. This means that when all the higher entries
1187 * are popped this entry will be too.
1191 push_opt(dp, sp, opt, search); /* This sets tsp to sp+1 */
1192 return 1; /* initialized */
1197 int ret = 0; /* unchanged */
1199 /* An option that is already on the stack; update best_size and best_val
1200 * if appropriate. On the first run there are no previous values and
1201 * dp->write_size will be MAX_SIZE, however on the first run dp->tsp
1204 assert(dp->write_size > 0U && dp->write_size < MAX_SIZE);
1206 if (dp->stack[sp].best_size > dp->write_size ||
1207 (dp->stack[sp].best_size == dp->write_size &&
1208 compare_option(dp, sp) > 0))
1210 dp->stack[sp].best_size = dp->write_size;
1211 dp->stack[sp].best_val = dp->value[opt];
1214 if (sp+1U >= dp->tsp)
1217 ret = 1; /* advanced */
1220 else if (!dp->stack[sp].end) /* Active, not at top of stack */
1223 return ret; /* advanced || unchanged */
1228 getallopts_(struct display *dp, png_byte opt, int *value, int record)
1229 /* Like getop but iterate over all the values if the option was set to "all".
1232 if (dp->entry[opt]) /* option was set on command line */
1234 /* Simple, single value, entries don't have a stack frame and have a fixed
1235 * value (it doesn't change once set on the command line). Otherwise the
1236 * value (entry) selected from the command line is 'all':
1238 const char *entry_name = options[opt].values[dp->entry[opt]-1].name;
1240 if (entry_name == all)
1241 (void)advance_opt(dp, opt, 0/*do not search; iterate*/);
1244 record_opt(dp, opt, entry_name);
1246 *value = dp->value[opt];
1251 return 0; /* not set */
1255 getallopts(struct display *dp, const char *opt_str, int *value)
1257 return getallopts_(dp, option_index(dp, opt_str, strlen(opt_str)), value, 0);
1261 getsearchopts(struct display *dp, const char *opt_str, int *value)
1262 /* As above except that if the option was not set try a search */
1265 png_byte opt = option_index(dp, opt_str, strlen(opt_str));
1266 int record = options[opt].search;
1267 const char *entry_name;
1269 /* If it was set on the command line honour the setting, including 'all'
1270 * which will override the built in search:
1272 if (getallopts_(dp, opt, value, record))
1275 else if (!record) /* not a search option */
1276 return 0; /* unset and not searched */
1278 /* Otherwise decide what to do here. */
1279 istrat = OPTIND(dp, strategy);
1280 entry_name = range_lo; /* record the value, not the name */
1282 if (opt == istrat) /* search all strategies */
1283 (void)advance_opt(dp, opt, 0/*iterate*/), record=0;
1285 else if (opt == OPTIND(dp, level))
1287 /* Both RLE and HUFFMAN don't benefit from level increases */
1288 if (dp->value[istrat] == Z_RLE || dp->value[istrat] == Z_HUFFMAN_ONLY)
1291 else /* fixed, filtered or default */
1292 (void)advance_opt(dp, opt, 1/*search*/), record=0;
1295 else if (opt == OPTIND(dp, windowBits))
1297 /* Changing windowBits for strategies that do not search the window is
1298 * pointless. Huffman-only does not search, RLE only searches backwards
1299 * one byte, so given that the maximum string length is 258, a windowBits
1300 * of 9 is always sufficient.
1302 if (dp->value[istrat] == Z_HUFFMAN_ONLY)
1305 else if (dp->value[istrat] == Z_RLE)
1308 else /* fixed, filtered or default */
1309 (void)advance_opt(dp, opt, 1/*search*/), record=0;
1312 else if (opt == OPTIND(dp, memLevel))
1315 (void)advance_opt(dp, opt, 0/*all*/), record=0;
1317 dp->value[opt] = MAX_MEM_LEVEL;
1321 else /* something else */
1322 assert(0=="reached");
1325 record_opt(dp, opt, entry_name);
1327 /* One of the above searched options: */
1328 *value = dp->value[opt];
1333 find_val(struct display *dp, png_byte opt, const char *str, size_t len)
1334 /* Like option_index but sets (index+i) of the entry in options[opt] that
1335 * matches str[0..len-1] into dp->entry[opt] as well as returning the actual
1339 int rlo = INT_MAX, rhi = INT_MIN;
1340 png_byte j, irange = 0;
1342 for (j=1U; j<=options[opt].value_count; ++j)
1344 if (strncmp(options[opt].values[j-1U].name, str, len) == 0 &&
1345 options[opt].values[j-1U].name[len] == 0)
1348 return options[opt].values[j-1U].value;
1350 else if (options[opt].values[j-1U].name == range_lo)
1351 rlo = options[opt].values[j-1U].value, irange = j;
1352 else if (options[opt].values[j-1U].name == range_hi)
1353 rhi = options[opt].values[j-1U].value;
1356 /* No match on the name, but there may be a range. */
1360 long l = strtol(str, &ep, 0);
1362 if (ep == str+len && l >= rlo && l <= rhi)
1364 dp->entry[opt] = irange; /* range_lo */
1365 return (int)/*SAFE*/l;
1369 display_log(dp, dp->errset ? INTERNAL_ERROR : USER_ERROR,
1370 "%s: unknown value setting '%.*s'", options[opt].name,
1371 (int)/*SAFE*/len, str);
1372 abort(); /* NOT REACHED */
1376 opt_check(struct display *dp, const char *arg)
1378 assert(dp->errset == 0);
1380 if (arg != NULL && arg[0] == '-' && arg[1] == '-')
1382 int i = 0, negate = (strncmp(arg+2, "no-", 3) == 0), val;
1386 arg += 5; /* --no- */
1391 /* Find the length (expect arg\0 or arg=) */
1392 while (arg[i] != 0 && arg[i] != '=') ++i;
1394 /* So arg[0..i-1] is the argument name, this does not return if this isn't
1395 * a valid option name.
1397 j = option_index(dp, arg, i);
1399 /* It matcheth an option; check the remainder. */
1400 if (arg[i] == 0) /* no specified value, use the default */
1402 val = options[j].values[negate].value;
1403 dp->entry[j] = (png_byte)/*SAFE*/(negate + 1U);
1408 const char *list = arg + (i+1);
1410 /* Expect a single value here unless this is a list, in which case
1411 * multiple values are combined.
1413 if (options[j].opt != LIST)
1415 /* find_val sets 'dp->entry[j]' to a non-zero value: */
1416 val = find_val(dp, j, list, strlen(list));
1420 if (options[j].opt < OPTION)
1425 display_log(dp, USER_ERROR,
1426 "%.*s: option=arg cannot be negated", i, arg);
1427 abort(); /* NOT REACHED */
1432 else /* multiple options separated by ',' characters */
1434 /* --no-option negates list values from the default, which should
1435 * therefore be 'all'. Notice that if the option list is empty in
1436 * this case nothing will be removed and therefore --no-option= is
1437 * the same as --option.
1440 val = options[j].values[0].value;
1445 while (*list != 0) /* allows option= which sets 0 */
1447 /* A value is terminated by the end of the list or a ','
1452 iv = 0; /* an index into 'list' */
1453 while (list[++iv] != 0 && list[iv] != ',') {}
1455 v = find_val(dp, j, list, iv);
1465 ++list; /* skip the ',' */
1470 /* 'val' is the new value, store it for use later and debugging: */
1473 if (options[j].opt < LEVEL_MASK)
1475 /* The handling for error levels is to set the level. */
1476 if (val) /* Set this level */
1477 dp->options = (dp->options & ~LEVEL_MASK) | options[j].opt;
1480 display_log(dp, USER_ERROR,
1481 "%.*s: messages cannot be turned off individually; set a message level",
1485 else if (options[j].opt < OPTION)
1488 dp->options |= options[j].opt;
1491 dp->options &= ~options[j].opt;
1494 return 1; /* this is an option */
1498 return 0; /* not an option */
1501 #ifdef PNG_PNGCP_TIMING_SUPPORTED
1503 set_timer(struct display *dp, struct timespec *timer)
1505 /* Do the timing using clock_gettime and the per-process timer. */
1506 if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, timer))
1508 display_log(dp, APP_ERROR,
1509 "CLOCK_PROCESS_CPUTIME_ID: %s: timing disabled\n", strerror(errno));
1510 dp->value[OPTIND(dp,time)] = 0; /* i.e. off */
1515 start_timer(struct display *dp, int what)
1517 if ((dp->value[OPTIND(dp,time)] & what) != 0)
1518 set_timer(dp, what == PNGCP_TIME_READ ? &dp->read_time : &dp->write_time);
1522 end_timer(struct display *dp, int what)
1524 if ((dp->value[OPTIND(dp,time)] & what) != 0)
1526 struct timespec t, tmp;
1530 if (what == PNGCP_TIME_READ)
1531 tmp = dp->read_time;
1534 tmp = dp->write_time;
1536 t.tv_sec -= tmp.tv_sec;
1537 t.tv_nsec -= tmp.tv_nsec;
1542 t.tv_nsec += 1000000000L;
1545 if (what == PNGCP_TIME_READ)
1546 dp->read_time = t, tmp = dp->read_time_total;
1549 dp->write_time = t, tmp = dp->write_time_total;
1551 tmp.tv_sec += t.tv_sec;
1552 tmp.tv_nsec += t.tv_nsec;
1554 if (tmp.tv_nsec >= 1000000000L)
1557 tmp.tv_nsec -= 1000000000L;
1560 if (what == PNGCP_TIME_READ)
1561 dp->read_time_total = tmp;
1564 dp->write_time_total = tmp;
1569 print_time(const char *what, struct timespec t)
1571 printf("%s %.2lu.%.9ld", what, (unsigned long)t.tv_sec, t.tv_nsec);
1573 #else /* !PNGCP_TIMING */
1574 #define start_timer(dp, what) ((void)0)
1575 #define end_timer(dp, what) ((void)0)
1576 #endif /* !PNGCP_TIMING */
1578 /* The following is used in main to verify that the final argument is a
1582 checkdir(const char *pathname)
1585 return stat(pathname, &buf) == 0 && S_ISDIR(buf.st_mode);
1588 /* Work out whether a path is valid (if not a display_log occurs), a directory
1589 * (1 is returned) or a file *or* non-existent (0 is returned).
1591 * Used for a write path.
1594 isdir(struct display *dp, const char *pathname)
1596 if (pathname == NULL)
1597 return 0; /* stdout */
1599 else if (pathname[0] == 0)
1600 return 1; /* empty string */
1605 int ret = stat(pathname, &buf);
1607 if (ret == 0) /* the entry exists */
1609 if (S_ISDIR(buf.st_mode))
1612 /* Else expect an object that exists and can be written: */
1613 if (access(pathname, W_OK) != 0)
1614 display_log(dp, USER_ERROR, "%s: cannot be written (%s)", pathname,
1617 return 0; /* file (exists, can be written) */
1622 /* Non-existence is fine, other errors are not: */
1623 if (errno != ENOENT)
1624 display_log(dp, USER_ERROR, "%s: invalid output name (%s)",
1625 pathname, strerror(errno));
1627 return 0; /* file (does not exist) */
1633 makename(struct display *dp, const char *dir, const char *infile)
1635 /* Make a name for an output file (and check it). */
1638 if (dir == NULL || infile == NULL)
1639 display_log(dp, INTERNAL_ERROR, "NULL name to makename");
1643 size_t dsize = strlen(dir);
1645 if (dsize <= (sizeof dp->namebuf)-2) /* Allow for name + '/' + '\0' */
1647 size_t isize = strlen(infile);
1648 size_t istart = isize-1;
1650 /* This should fail before here: */
1651 if (infile[istart] == '/')
1652 display_log(dp, INTERNAL_ERROR, "infile with trailing /");
1654 memcpy(dp->namebuf, dir, dsize);
1655 if (dsize > 0 && dp->namebuf[dsize-1] != '/')
1656 dp->namebuf[dsize++] = '/';
1658 /* Find the rightmost non-/ character: */
1659 while (istart > 0 && infile[istart-1] != '/')
1665 if (dsize+isize < (sizeof dp->namebuf)) /* dsize + infile + '\0' */
1667 memcpy(dp->namebuf+dsize, infile, isize+1);
1669 if (isdir(dp, dp->namebuf))
1670 display_log(dp, USER_ERROR, "%s: output file is a directory",
1676 dp->namebuf[dsize] = 0; /* allowed for: -2 at start */
1677 display_log(dp, USER_ERROR, "%s%s: output file name too long",
1678 dp->namebuf, infile);
1683 display_log(dp, USER_ERROR, "%s: output directory name too long", dir);
1687 /* error handler callbacks for libpng */
1688 static void PNGCBAPI
1689 display_warning(png_structp pp, png_const_charp warning)
1691 struct display *dp = get_dp(pp);
1693 /* This is used to prevent repeated warnings while searching */
1694 if (!dp->no_warnings)
1695 display_log(get_dp(pp), LIBPNG_WARNING, "%s", warning);
1698 static void PNGCBAPI
1699 display_error(png_structp pp, png_const_charp error)
1701 struct display *dp = get_dp(pp);
1703 display_log(dp, LIBPNG_ERROR, "%s", error);
1707 display_start_read(struct display *dp, const char *filename)
1709 if (filename != NULL)
1711 dp->filename = filename;
1712 dp->fp = fopen(filename, "rb");
1717 dp->filename = "<stdin>";
1727 display_log(dp, USER_ERROR, "file open failed (%s)", strerror(errno));
1730 static void PNGCBAPI
1731 read_function(png_structp pp, png_bytep data, size_t size)
1733 struct display *dp = get_dp(pp);
1735 if (size == 0U || fread(data, size, 1U, dp->fp) == 1U)
1736 dp->read_size += size;
1741 display_log(dp, LIBPNG_ERROR, "PNG file truncated");
1743 display_log(dp, LIBPNG_ERROR, "PNG file read failed (%s)",
1749 read_png(struct display *dp, const char *filename)
1751 /* This is an assumption of the code; it may happen if a previous write fails
1752 * and there is a bug in the cleanup handling below (look for setjmp).
1753 * Passing freeinfo==1 to display_clean_read below avoids a second error
1754 * on dp->ip != NULL below.
1756 if (dp->read_pp != NULL)
1758 display_log(dp, APP_FAIL, "unexpected png_read_struct");
1759 display_clean_read(dp, 1/*freeinfo*/); /* recovery */
1762 display_start_read(dp, filename);
1764 dp->read_pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, dp,
1765 display_error, display_warning);
1766 if (dp->read_pp == NULL)
1767 display_log(dp, LIBPNG_ERROR, "failed to create read struct");
1769 # ifdef PNG_BENIGN_ERRORS_SUPPORTED
1770 png_set_benign_errors(dp->read_pp, 1/*allowed*/);
1771 # endif /* BENIGN_ERRORS */
1774 if ((dp->options & FIX_INDEX) != 0)
1775 png_set_check_for_invalid_index(dp->read_pp, 1/*on, no warning*/);
1776 # ifdef IGNORE_INDEX
1778 # endif /* IGNORE_INDEX */
1779 # endif /* FIX_INDEX */
1780 # ifdef IGNORE_INDEX
1781 if ((dp->options & IGNORE_INDEX) != 0) /* DANGEROUS */
1782 png_set_check_for_invalid_index(dp->read_pp, -1/*off completely*/);
1783 # endif /* IGNORE_INDEX */
1787 /* UNEXPECTED: some problem in the display_clean function calls! */
1788 display_log(dp, APP_FAIL, "read_png: freeing old info struct");
1789 png_destroy_info_struct(dp->read_pp, &dp->ip);
1792 /* The png_read_png API requires us to make the info struct, but it does the
1793 * call to png_read_info.
1795 dp->ip = png_create_info_struct(dp->read_pp);
1797 png_error(dp->read_pp, "failed to create info struct");
1799 /* Set the IO handling */
1800 png_set_read_fn(dp->read_pp, dp, read_function);
1802 # ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1803 png_set_keep_unknown_chunks(dp->read_pp, PNG_HANDLE_CHUNK_ALWAYS, NULL,
1805 # endif /* HANDLE_AS_UNKNOWN */
1807 # ifdef PNG_SET_USER_LIMITS_SUPPORTED
1808 /* Remove the user limits, if any */
1809 png_set_user_limits(dp->read_pp, 0x7fffffff, 0x7fffffff);
1810 # endif /* SET_USER_LIMITS */
1812 /* Now read the PNG. */
1813 start_timer(dp, PNGCP_TIME_READ);
1814 png_read_png(dp->read_pp, dp->ip, 0U/*transforms*/, NULL/*params*/);
1815 end_timer(dp, PNGCP_TIME_READ);
1816 dp->w = png_get_image_width(dp->read_pp, dp->ip);
1817 dp->h = png_get_image_height(dp->read_pp, dp->ip);
1818 dp->ct = png_get_color_type(dp->read_pp, dp->ip);
1819 dp->bpp = png_get_bit_depth(dp->read_pp, dp->ip) *
1820 png_get_channels(dp->read_pp, dp->ip);
1822 /* png_get_rowbytes should never return 0 because the value is set by the
1823 * first call to png_set_IHDR, which should have happened by now, but just
1826 png_alloc_size_t rb = png_get_rowbytes(dp->read_pp, dp->ip);
1829 png_error(dp->read_pp, "invalid row byte count from libpng");
1831 /* The size calc can overflow. */
1832 if ((MAX_SIZE-dp->h)/rb < dp->h)
1833 png_error(dp->read_pp, "image too large");
1835 dp->size = rb * dp->h + dp->h/*filter byte*/;
1839 if (dp->ct == PNG_COLOR_TYPE_PALETTE && (dp->options & FIX_INDEX) != 0)
1841 int max = png_get_palette_max(dp->read_pp, dp->ip);
1842 png_colorp palette = NULL;
1845 if (png_get_PLTE(dp->read_pp, dp->ip, &palette, &num) != PNG_INFO_PLTE
1846 || max < 0 || num <= 0 || palette == NULL)
1847 display_log(dp, LIBPNG_ERROR, "invalid png_get_PLTE result");
1851 /* 'Fix' the palette. */
1853 png_color newpal[256];
1855 for (i=0; i<num; ++i)
1856 newpal[i] = palette[i];
1858 /* Fill in any remainder with a warning color: */
1861 newpal[i].red = 0xbe;
1862 newpal[i].green = 0xad;
1863 newpal[i].blue = 0xed;
1866 png_set_PLTE(dp->read_pp, dp->ip, newpal, i);
1869 #endif /* FIX_INDEX */
1871 /* NOTE: dp->ip is where all the information about the PNG that was just read
1872 * is stored. It can be used to write and write again a single PNG file,
1873 * however be aware that prior to libpng 1.7 text chunks could only be
1874 * written once; this is a bug which would require a significant code rewrite
1875 * to fix, it has been there in several versions of libpng (it was introduced
1876 * to fix another bug involving duplicate writes of the text chunks.)
1878 display_clean_read(dp, 0/*freeiinfo*/);
1879 dp->operation = "none";
1883 display_start_write(struct display *dp, const char *filename)
1885 assert(dp->fp == NULL);
1887 if ((dp->options & NOWRITE) != 0)
1888 dp->output_file = "<no write>";
1892 if (filename != NULL)
1894 dp->output_file = filename;
1895 dp->fp = fopen(filename, "wb");
1900 dp->output_file = "<stdout>";
1905 display_log(dp, USER_ERROR, "%s: file open failed (%s)",
1906 dp->output_file, strerror(errno));
1910 static void PNGCBAPI
1911 write_function(png_structp pp, png_bytep data, size_t size)
1913 struct display *dp = get_dp(pp);
1915 /* The write fail is classed as a USER_ERROR, so --quiet does not turn it
1916 * off, this seems more likely to be correct.
1918 if (dp->fp == NULL || fwrite(data, size, 1U, dp->fp) == 1U)
1920 dp->write_size += size;
1921 if (dp->write_size < size || dp->write_size == MAX_SIZE)
1922 png_error(pp, "IDAT size overflow");
1926 display_log(dp, USER_ERROR, "%s: PNG file write failed (%s)",
1927 dp->output_file, strerror(errno));
1930 /* Compression option, 'method' is never set: there is no choice.
1932 * IMPORTANT: the order of the entries in this macro determines the preference
1933 * order when two different combos of two of these options produce an IDAT of
1934 * the same size. The logic here is to put the things that affect the decoding
1935 * of the PNG image ahead of those that are relevant only to the encoding.
1937 #define SET_COMPRESSION\
1938 SET(strategy, strategy);\
1939 SET(windowBits, window_bits);\
1941 SET(memLevel, mem_level);
1943 #ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
1945 search_compression(struct display *dp)
1947 /* Like set_compression below but use a more restricted search than 'all' */
1950 # define SET(name, func) if (getsearchopts(dp, #name, &val))\
1951 png_set_compression_ ## func(dp->write_pp, val);
1957 set_compression(struct display *dp)
1961 # define SET(name, func) if (getallopts(dp, #name, &val))\
1962 png_set_compression_ ## func(dp->write_pp, val);
1967 #ifdef PNG_SW_COMPRESS_level /* 1.7.0+ */
1969 set_ICC_profile_compression(struct display *dp)
1973 # define SET(name, func) if (getallopts(dp, "ICC-profile-" #name, &val))\
1974 png_set_ICC_profile_compression_ ## func(dp->write_pp, val);
1979 # define set_ICC_profile_compression(dp) ((void)0)
1982 # define search_compression(dp) ((void)0)
1983 # define set_compression(dp) ((void)0)
1984 # define set_ICC_profile_compression(dp) ((void)0)
1985 #endif /* WRITE_CUSTOMIZE_COMPRESSION */
1987 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
1989 set_text_compression(struct display *dp)
1993 # define SET(name, func) if (getallopts(dp, "text-" #name, &val))\
1994 png_set_text_compression_ ## func(dp->write_pp, val);
1999 # define set_text_compression(dp) ((void)0)
2000 #endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
2003 write_png(struct display *dp, const char *destname)
2005 /* If this test fails png_write_png would fail *silently* below; this
2006 * is not helpful, so catch the problem now and give up:
2009 display_log(dp, INTERNAL_ERROR, "missing png_info");
2011 /* This is an assumption of the code; it may happen if a previous
2012 * write fails and there is a bug in the cleanup handling below.
2014 if (dp->write_pp != NULL)
2016 display_log(dp, APP_FAIL, "unexpected png_write_struct");
2017 display_clean_write(dp, 0/*!freeinfo*/);
2020 display_start_write(dp, destname);
2022 dp->write_pp = png_create_write_struct(PNG_LIBPNG_VER_STRING, dp,
2023 display_error, display_warning);
2025 if (dp->write_pp == NULL)
2026 display_log(dp, LIBPNG_ERROR, "failed to create write png_struct");
2028 # ifdef PNG_BENIGN_ERRORS_SUPPORTED
2029 png_set_benign_errors(dp->write_pp, 1/*allowed*/);
2030 # endif /* BENIGN_ERRORS */
2032 png_set_write_fn(dp->write_pp, dp, write_function, NULL/*flush*/);
2035 if ((dp->options & IGNORE_INDEX) != 0) /* DANGEROUS */
2036 png_set_check_for_invalid_index(dp->write_pp, -1/*off completely*/);
2037 #endif /* IGNORE_INDEX */
2039 /* Restore the text chunks when using libpng 1.6 or less; this is a macro
2040 * which expands to nothing in 1.7+ In earlier versions it tests
2041 * dp->text_stashed, which is only set (below) *after* the first write.
2045 # ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
2046 png_set_keep_unknown_chunks(dp->write_pp, PNG_HANDLE_CHUNK_ALWAYS, NULL,
2048 # endif /* HANDLE_AS_UNKNOWN */
2050 # ifdef PNG_SET_USER_LIMITS_SUPPORTED
2051 /* Remove the user limits, if any */
2052 png_set_user_limits(dp->write_pp, 0x7fffffff, 0x7fffffff);
2055 /* OPTION HANDLING */
2056 /* compression outputs, IDAT and zTXt/iTXt: */
2058 dp->nsp = dp->csp = 0;
2059 # ifdef PNG_SW_COMPRESS_png_level
2063 /* This sets everything, but then the following options just override
2064 * the specific settings for ICC profiles and text.
2066 if (getallopts(dp, "compression", &val))
2067 png_set_compression(dp->write_pp, val);
2069 if (getallopts(dp, "ICC-profile-compression", &val))
2070 png_set_ICC_profile_compression(dp->write_pp, val);
2072 if (getallopts(dp, "text-compression", &val))
2073 png_set_text_compression(dp->write_pp, val);
2075 # endif /* png_level support */
2076 if (dp->options & SEARCH)
2077 search_compression(dp);
2079 set_compression(dp);
2080 set_ICC_profile_compression(dp);
2081 set_text_compression(dp);
2086 /* The permitted range is 1..0x7FFFFFFF, so the cast is safe */
2087 if (get_option(dp, "IDAT-size", &val))
2088 png_set_IDAT_size(dp->write_pp, val);
2091 /* filter handling */
2092 # ifdef PNG_WRITE_FILTER_SUPPORTED
2096 if (get_option(dp, "filter", &val))
2097 png_set_filter(dp->write_pp, PNG_FILTER_TYPE_BASE, val);
2099 # endif /* WRITE_FILTER */
2101 /* This just uses the 'read' info_struct directly, it contains the image. */
2102 dp->write_size = 0U;
2103 start_timer(dp, PNGCP_TIME_WRITE);
2104 png_write_png(dp->write_pp, dp->ip, 0U/*transforms*/, NULL/*params*/);
2105 end_timer(dp, PNGCP_TIME_WRITE);
2107 /* Make sure the file was written ok: */
2113 display_log(dp, APP_ERROR, "%s: write failed (%s)",
2114 destname == NULL ? "stdout" : destname, strerror(errno));
2117 dp->operation = "none";
2121 set_windowBits_hi(struct display *dp)
2123 /* windowBits is in the range 8..15 but zlib maps '8' to '9' so it is only
2124 * worth using if the data size is 256 byte or less.
2126 int wb = MAX_WBITS; /* for large images */
2127 int i = VLSIZE(windowBits_IDAT);
2129 while (wb > 8 && dp->size <= 1U<<(wb-1)) --wb;
2131 while (--i >= 0) if (VLNAME(windowBits_IDAT)[i].name == range_hi) break;
2133 assert(i > 1); /* vl_windowBits_IDAT always has a RANGE() */
2134 VLNAME(windowBits_IDAT)[i].value = wb;
2136 assert(VLNAME(windowBits_IDAT)[--i].name == range_lo);
2137 VLNAME(windowBits_IDAT)[i].value = wb > 8 ? 9 : 8;
2139 /* If wb == 8 then any search has been restricted to just one windowBits
2140 * entry. Record that here to avoid producing a spurious app-level warning
2144 dp->min_windowBits = OPTIND(dp, windowBits);
2148 better_options(const struct display *dp)
2150 /* Are these options better than the best found so far? Normally the
2151 * options are tested in preference order, best first, however when doing a
2152 * search operation on a range the range values are tested out of order. In
2153 * that case preferable options will get tested later.
2155 * This function looks through the stack from the bottom up looking for an
2156 * option that does not match the current best value. When it finds one it
2157 * checks to see if it is more or less desirable and returns true or false
2160 * Notice that this means that the order options are pushed onto the stack
2161 * conveys a priority; lower/earlier options are more important than later
2166 for (sp=0; sp<dp->csp; ++sp)
2168 int c = compare_option(dp, sp);
2171 return 0; /* worse */
2174 return 1; /* better */
2177 assert(0 && "unreached");
2181 print_search_results(struct display *dp)
2183 assert(dp->filename != NULL);
2184 printf("%s [%ld x %ld %d bpp %s, %lu bytes] %lu -> %lu with '%s'\n",
2185 dp->filename, (unsigned long)dp->w, (unsigned long)dp->h, dp->bpp,
2186 cts(dp->ct), (unsigned long)dp->size, (unsigned long)dp->read_size,
2187 (unsigned long)dp->best_size, dp->best);
2192 log_search(struct display *dp, unsigned int log_depth)
2194 /* Log, and reset, the search so far: */
2195 if (dp->nsp/*next entry to change*/ <= log_depth)
2197 print_search_results(dp);
2198 /* Start again with this entry: */
2199 dp->best_size = MAX_SIZE;
2204 cp_one_file(struct display *dp, const char *filename, const char *destname)
2206 unsigned int log_depth;
2208 dp->filename = filename;
2209 dp->operation = "read";
2210 dp->no_warnings = 0;
2212 /* Read it then write it: */
2213 if (filename != NULL && access(filename, R_OK) != 0)
2214 display_log(dp, USER_ERROR, "%s: invalid file name (%s)",
2215 filename, strerror(errno));
2217 read_png(dp, filename);
2219 /* But 'destname' may be a directory. */
2220 dp->operation = "write";
2222 /* Limit the upper end of the windowBits range for this file */
2223 set_windowBits_hi(dp);
2225 /* For logging, depth to log: */
2229 if (get_option(dp, "log-depth", &val) && val >= 0)
2230 log_depth = (unsigned int)/*SAFE*/val;
2236 if (destname != NULL) /* else stdout */
2238 if (isdir(dp, destname))
2240 makename(dp, destname, filename);
2241 destname = dp->namebuf;
2244 else if (access(destname, W_OK) != 0 && errno != ENOENT)
2245 display_log(dp, USER_ERROR, "%s: invalid output name (%s)", destname,
2250 dp->curr[0] = 0; /* acts as a flag for the caller */
2251 dp->opt_string_start = 0;
2252 dp->best[0] = 0; /* safety */
2253 dp->best_size = MAX_SIZE;
2254 write_png(dp, destname);
2256 /* Initialize the 'best' fields: */
2257 strcpy(dp->best, dp->curr);
2258 dp->best_size = dp->write_size;
2260 if (dp->nsp > 0) /* iterating over lists */
2262 char *tmpname, tmpbuf[(sizeof dp->namebuf) + 4];
2263 assert(dp->curr[0] == ' ' && dp->tsp > 0);
2265 /* Cancel warnings on subsequent writes */
2266 log_search(dp, log_depth);
2267 dp->no_warnings = 1;
2269 /* Make a temporary name for the subsequent tests: */
2270 if (destname != NULL)
2272 strcpy(tmpbuf, destname);
2273 strcat(tmpbuf, ".tmp"); /* space for .tmp allocated above */
2278 tmpname = NULL; /* stdout */
2280 /* Loop to find the best option. */
2283 /* Clean before each write_png; this just removes *dp->write_pp which
2286 display_clean_write(dp, 0/*!freeinfo*/);
2287 write_png(dp, tmpname);
2289 /* And compare the sizes (the write function makes sure write_size
2290 * doesn't overflow.)
2292 assert(dp->csp > 0);
2294 if (dp->write_size < dp->best_size ||
2295 (dp->write_size == dp->best_size && better_options(dp)))
2297 if (destname != NULL && rename(tmpname, destname) != 0)
2298 display_log(dp, APP_ERROR, "rename %s %s failed (%s)", tmpname,
2299 destname, strerror(errno));
2301 strcpy(dp->best, dp->curr);
2302 dp->best_size = dp->write_size;
2305 else if (tmpname != NULL && unlink(tmpname) != 0)
2306 display_log(dp, APP_WARNING, "unlink %s failed (%s)", tmpname,
2309 log_search(dp, log_depth);
2311 while (dp->nsp > 0);
2313 /* Do this for the 'sizes' option so that it reports the correct size. */
2314 dp->write_size = dp->best_size;
2317 display_clean_write(dp, 1/*freeinfo*/);
2321 cppng(struct display *dp, const char *file, const char *gv dest)
2322 /* Exists solely to isolate the setjmp clobbers which some versions of GCC
2323 * erroneously generate.
2326 int ret = setjmp(dp->error_return);
2331 cp_one_file(dp, file, dest);
2340 if (ret < ERRORS) /* shouldn't longjmp on warnings */
2341 display_log(dp, INTERNAL_ERROR, "unexpected return code %d", ret);
2348 main(int argc, char **argv)
2350 /* For each file on the command line test it with a range of transforms */
2356 d.operation = "options";
2357 for (option_end = 1;
2358 option_end < argc && opt_check(&d, argv[option_end]);
2363 /* Do a quick check on the directory target case; when there are more than
2364 * two arguments the last one must be a directory.
2366 if (!(d.options & NOWRITE) && option_end+2 < argc && !checkdir(argv[argc-1]))
2369 "pngcp: %s: directory required with more than two arguments\n",
2378 /* Do this at least once; if there are no arguments stdin/stdout are used.
2380 d.operation = "files";
2383 const char *infile = NULL;
2384 const char *outfile = NULL;
2390 if (!(d.options & NOWRITE) && i < argc)
2391 outfile = argv[argc-1];
2394 ret = cppng(&d, infile, outfile);
2398 if (ret > QUIET) /* abort on user or internal error */
2401 /* An error: the output is meaningless */
2404 else if (d.best[0] != 0)
2406 /* This result may already have been output, in which case best_size
2409 if (d.best_size < MAX_SIZE)
2410 print_search_results(&d);
2413 else if (d.options & SIZES)
2415 printf("%s [%ld x %ld %d bpp %s, %lu bytes] %lu -> %lu [0x%lx]\n",
2416 infile, (unsigned long)d.w, (unsigned long)d.h, d.bpp,
2417 cts(d.ct), (unsigned long)d.size, (unsigned long)d.read_size,
2418 (unsigned long)d.write_size, (unsigned long)d.results);
2422 /* Here on any return, including failures, except user/internal issues
2425 int pass = (d.options & STRICT) ?
2426 RESULT_STRICT(d.results) : RESULT_RELAXED(d.results);
2431 if (d.options & LOG)
2435 printf("%s: pngcp", pass ? "PASS" : "FAIL");
2437 for (j=1; j<option_end; ++j)
2438 printf(" %s", argv[j]);
2441 printf(" %s", infile);
2443 # ifdef PNG_PNGCP_TIMING_SUPPORTED
2444 /* When logging output the files for each file, if enabled. */
2445 if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_READ) != 0)
2446 print_time(" read", d.read_time);
2448 if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_WRITE) != 0)
2449 print_time(" write", d.write_time);
2450 # endif /* PNGCP_TIMING */
2459 while (i+!(d.options & NOWRITE) < argc);
2460 /* I.e. for write cases after the first time through the loop require
2461 * there to be at least two arguments left and for the last one to be a
2462 * directory (this was checked above).
2465 /* Release allocated memory */
2466 display_destroy(&d);
2468 # ifdef PNG_PNGCP_TIMING_SUPPORTED
2472 if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_READ) != 0)
2473 print_time("read", d.read_time_total), output = 1;
2475 if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_WRITE) != 0)
2477 if (output) putchar(' ');
2478 print_time("write", d.write_time_total);
2482 if (output) putchar('\n');
2484 # endif /* PNGCP_TIMING */
2489 #else /* !READ_PNG || !WRITE_PNG */
2493 fprintf(stderr, "pngcp: no support for png_read/write_image\n");
2496 #endif /* !READ_PNG || !WRITE_PNG */