diff -Nru pngcrush-1.7.85/ChangeLog.html pngcrush-1.8.13/ChangeLog.html --- pngcrush-1.7.85/ChangeLog.html 2015-03-09 19:29:23.000000000 +0000 +++ pngcrush-1.8.13/ChangeLog.html 2017-08-29 21:15:16.000000000 +0000 @@ -3,6 +3,157 @@ Change log: +Version 1.8.13 (built with libpng-1.6.32 and zlib-1.2.11) + Add "exit(0)" after processing "-version" argument, to avoid + displaying the Usage information (bug report by Peter Hagan, + Issue #76). + Fix problem with MacOS prior to Sierra; it uses CLOCK_MONOTONIC + for some other purpose (bug report and help developing patch by + Github user "ilovezfs", Homebrew/homebrew-core PR#16391). + +Version 1.8.12 (built with libpng-1.6.31 and zlib-1.2.11) + Added POWERPC-VSX support. + Report whether using optimizations. + Added filter_method 6 (same as filter 5 with -speed). + Added "methods" 149-176 (that use filter_method 6). + Changed default verbosity from 1 (normal) to 0 (quiet). Use "-v" to get + the previous default behavior and "-v -v" to get the previous "verbose" + behavior. The "-s" (silent) and "-q" (quiet) options behave as before. + +Version 1.8.11 (built with libpng-1.6.28 and zlib-1.2.11) + Use png_set_option(PNG_IGNORE_ADLER32) to control ADLER32 handling. + Changed LD=gcc to LD=$(CC) in Makefile and Makefile-nolib (suggested + by Helmut G in Bug#850927 of some GIT project) + +Version 1.8.10 (built with libpng-1.6.26 and zlib-1.2.8.1) + Changed ADLER32 checksum handling to only use inflateValidate() + during IDAT chunk handling; it broke iCCP chunk handling. + +Version 1.8.9 (built with libpng-1.6.26 and zlib-1.2.8.1) + Added "-warn" option, to show only warnings. + Enabled method 149. For now it writes uncompressed IDAT but in + a future version of pngcrush it will just copy the IDAT data. + +Version 1.8.8 (built with libpng-1.6.26beta06 and zlib-1.2.8.1) + Fixed "nolib" build (bug report by Hanspeter Niederstrasser). + Make sure we use system-png.h, and not the local file. It is now + possible to build either the regular pngcrush or the "nolib" + pngcrush in the complete pngcrush source directory (use + "make clean" before rebuilding!) + Fixed timing when using "clock()". Sometimes an additional second + was added when the timer crossed a one-second boundary, since + version 1.8.5. + Upgrade libpng to version 1.6.26beta06 and zlib to 1.2.8.1. + Use zlib-1.2.8.1 new "inflateValidate()" function to avoid checking + ADLER32 checksums. Version 1.8.7 did not work when the "-fix" + option was used. + +Version 1.8.7 (built with libpng-1.6.25 and zlib-1.2.8) + Do not check the ADLER32 CRC while reading except during the final write + pass (requires libpng-1.6.26 or later and zlib-1.2.4 or later). + This saves some CPU time, around five to ten percent, in decoding. + Do not calculate the ADLER32 CRC while writing except during the final + write pass (writing raw deflate streams instead of zlib streams to + the IDAT chunks; these are invalid PNGs but since all we do is count + the bytes that does not matter). This saves some CPU time in encoding + but it is barely perceptible. Requires zlib 1.2.4 or later and modified + pngwutil.c. + +Version 1.8.6 (built with libpng-1.6.25 and zlib-1.2.8) + Enabled ARM_NEON support. + Fixed error in handling of timer wraparound when interval exceeds one + second. + Disable high resolution timers by default in Makefile. To enable them, + you must enable/disable relevant CPPFLAGS and LIBS in Makefile. + +Version 1.8.5 (built with libpng-1.6.24 and zlib-1.2.8) + Added "-benchmark n" option. It runs the main loop "n" times, and + records the minimum value for each timer. + After checking for CLOCK_ID, use clock() if none is found. + Avoid some timing when verbose<0 ("-s" or "--silent") + Added PNGCRUSH_CHECK_CRC (off by default) to use libpng default + CRC checking. Otherwise, CRC are only computed and checked during + the first read pass and while writing. + Accept "--option" (for now, by simply skipping the first "-"). + +Version 1.8.4 (built with libpng-1.6.24 and zlib-1.2.8) + Fixed handling of CLOCK_ID, removed some "//"-delimited comments. + Revised intel_init.c to always optimize 4bpp images, because the + poor optimization noted previously has been fixed. + +Version 1.8.3 (built with libpng-1.6.24 and zlib-1.2.8) + Fixed bug introduced in 1.8.2 that causes trial 10 to be skipped when + using the default heuristic method. + Fixed incorrect typecast in call to png_create_write_struct_2() (Bug + report by Richard K. Lloyd). + Added intel_init.c, filter_sse2_intrinsics.c, and Makefile-sse, + to enable INTEL SSE optimization. Revised intel_init.c to optionally + only optimize 4bpp images, because the optimization appears to slow + down reading of 3bpp images. + Added PNGCRUSH_TIMERS (nanosecond resolution using clock_gettime), to + measure defiltering time in png_read_filter_row(). For now, this only + works with a modified libpng, on platforms that provide "clock_gettime()". + To enable all timers, define PNGCRUSH_TIMERS=11. + Revised "-q" to show a short summary of results (final size and timing) + To do: Add ZLIB_AMALGAMATED configuration; currently produces different output + https://blog.forrestthewoods.com/ + improving-open-source-with-amalgamation-cf293592c5f4#.g9fb2tyhs + (added #ifndef NO_GZ / #endif to skip the gz* code in zlib_amalg.[ch]). + Added LIBPNG_UNIFIED configuration. + +Version 1.8.2 (built with libpng-1.6.23 and zlib-1.2.8) + Fixed filesize reduction report when "-ow" option is used (Bug report #68). + When a single method is specified, turn -reduce off by default and skip + trial 0. + +Version 1.8.1 (built with libpng-1.6.21 and zlib-1.2.8) + Added the LICENSE file to the tar and zip distributions. + Made "-force" force output even when the IDAT is larger, and added + "-noforce" option; "-noforce" is now the default behavior (Bug + report #68 at SourceForge by "wintakeall") + Use right filename in filesize reduction report (overwrite?inname:outname) + (bug report #69 by "wintakeall"). + Removed some superfluous spaces from the Copyright statement. + Added "-speed" option; it avoids using the AVG or PAETH filters which + are slower to decode. + +Version 1.8.0 (built with libpng-1.6.21 and zlib-1.2.8) + Made "-reduce" and "-force" the default behavior. Removed obsolete + options "-plte_len", "-cc", "-nocc", "-double_gamma", "-already_crushed", + and "-bit_depth". Removed "things_have_changed" code. + +Version 1.7.92 (built with libpng-1.6.20 and zlib-1.2.8) + Deleted png_read_update_info() statement that was mistakenly added to + version 1.7.89. It caused "bad adaptive filter value" errors. + +Version 1.7.91 (built with libpng-1.6.20 and zlib-1.2.8) + Suppress warning about "damaged LZ stream" when bailing out and building + with libpng-1.7.0beta. + Added a LICENSE file to the distribution. It points to the actual + license appearing in the NOTICES section near the top of pngcrush.c + Show if pngcrush is built with bundled or system libpng and zlib. + Fixed segfault while writing a -loco MNG (bug found with AFL, reported + by Brian Carpenter). Bug was introduced in pngcrush-1.7.35. + +Version 1.7.88 (built with libpng-1.6.19 and zlib-1.2.8) + Eliminated a potential overflow while adding iTXt chunk (over-length + text_lang or text_lang_key), reported by Coverity. + +Version 1.7.87 (built with libpng-1.6.18 and zlib-1.2.8) + Fixed a double-free bug (CVE-2015-7700). There was a "free" of the + sPLT chunk structure in pngcrush and then again in png.c (Bug report + by Brian Carpenter). + Added common-law trademark notice and export control information. + Rearranged some paragraphs in the comments at the beginning of pngcrush.c + Increased some buffer sizes in an attempt to prevent possible overflows. + +Version 1.7.86 (built with libpng-1.6.18 and zlib-1.2.8) + Increased maximum size of a text chunk input from 260 to 2048 + (STR_BUF_SIZE) bytes, to agree with the help screen (bug report by + Tamas Jursonovics). + Fixed bug that caused text chunks after IDAT to be written only when + the "-save" option is used. + Version 1.7.85 (built with libpng-1.6.16 and zlib-1.2.8) Improved reporting of invalid chunk names. Does not try to put non-printable characters in STDERR; displays hex numbers instead. @@ -129,17 +280,17 @@ Moved a closing bracket inside the PNGCRUSH_LOCO block. Moved the declaration of "new_mng" outside a PNGCRUSH_LOCO block. Put reference to "input_format" inside a PNGCRUSH_LOCO block. - Moved declarations of mng_out and mngname inside a PNGCRUSH_LOGO block. + Moved declarations of mng_out and mngname inside a PNGCRUSH_LOCO block. Version 1.7.58 (built with libpng-1.5.15 and zlib-1.2.7-1) Do not enable reduce_palette by default for "-reduce", "-new", or "-old". It still is failing for some files. Version 1.7.57 (built with libpng-1.5.15 and zlib-1.2.7-1) - Added "-new" option that turns on "-reduce" and "-force" which will be - the default settings for version 1.8.0 and beyond. - Added "-old" option that turns off "-reduce" and "-force" which are the - current default settings. + Added "-new" option that turns on "-reduce" which will be + the default setting for version 1.8.0 and beyond. + Added "-old" option that turns off "-reduce" which is the + current default setting. Updated copyright year for zlib-1.2.7-1. Reverted to libpng-1.5.15 to be able to read old PNG files with TOO FAR errors. This will of course only work with the embedded libpng. @@ -486,7 +637,7 @@ Version 1.6.18 (built with libpng-1.2.37 and zlib-1.2.3.2) Removed extra FCLOSE(fpin) and FCLOSE(fpout) in the first Catch{} block, - since they get removed anyway right after that (hanno boeck). + since they get removed anyway right after that (Hanno Boeck). Define PNG_NO_READ|WRITE_cHRM and PNG_NO_READ_|WRITEiCCP in pngcrush.h and reordered pngcrush.h diff -Nru pngcrush-1.7.85/debian/changelog pngcrush-1.8.13/debian/changelog --- pngcrush-1.7.85/debian/changelog 2016-04-23 00:18:38.000000000 +0000 +++ pngcrush-1.8.13/debian/changelog 2019-02-22 08:07:23.000000000 +0000 @@ -1,8 +1,26 @@ -pngcrush (1.7.85-1build1) yakkety; urgency=medium +pngcrush (1.8.13-0.1) unstable; urgency=medium - * No-change rebuild for libpng soname change. + * Non-maintainer upload. + * New upstream version + * Decide for latest upstream but found in upstream changelog: + Version 1.7.87 (built with libpng-1.6.18 and zlib-1.2.8) + Fixed a double-free bug (CVE-2015-7700). There was a "free" of the + sPLT chunk structure in pngcrush and then again in png.c (Bug report + by Brian Carpenter). + Closes: #874109 + * Standards-Version: 4.3.0 + * Remove custom compression settings in debian/source/options + * hardening=+all + + -- Andreas Tille Fri, 22 Feb 2019 09:07:23 +0100 + +pngcrush (1.7.85-2) UNRELEASED; urgency=medium + + * d/changelog: Remove trailing whitespaces + * d/control: Set Vcs-* to salsa.debian.org + * d/watch: Use https protocol - -- Matthias Klose Sat, 23 Apr 2016 00:18:38 +0000 + -- Ondřej Nový Mon, 01 Oct 2018 09:46:28 +0200 pngcrush (1.7.85-1) unstable; urgency=medium @@ -105,7 +123,7 @@ * New upstream release (1.6.13-nolib). - debian/patches/fix_itxt_param_handling: patch incorporated upstream so removed. - - incorporates newer libpng features. + - incorporates newer libpng features. - added "-time_stamp" command line directive to ensure that output file has new timestamp. (Closes: #510491) - see upstream changelog for further details. diff -Nru pngcrush-1.7.85/debian/control pngcrush-1.8.13/debian/control --- pngcrush-1.7.85/debian/control 2015-06-04 20:21:43.000000000 +0000 +++ pngcrush-1.8.13/debian/control 2019-02-22 08:07:23.000000000 +0000 @@ -4,9 +4,9 @@ Maintainer: Margarita Manterola Uploaders: Nelson A. de Oliveira , Sven Mueller Build-Depends: debhelper (>= 9), docbook-to-man, libpng-dev, zlib1g-dev -Vcs-Browser: http://anonscm.debian.org/cgit/collab-maint/pngcrush.git -Vcs-Git: git://anonscm.debian.org/collab-maint/pngcrush.git -Standards-Version: 3.9.6 +Vcs-Browser: https://salsa.debian.org/debian/pngcrush +Vcs-Git: https://salsa.debian.org/debian/pngcrush.git +Standards-Version: 4.3.0 Homepage: http://pmt.sourceforge.net/pngcrush/ Package: pngcrush diff -Nru pngcrush-1.7.85/debian/patches/local_Makefile_adjustments.diff pngcrush-1.8.13/debian/patches/local_Makefile_adjustments.diff --- pngcrush-1.7.85/debian/patches/local_Makefile_adjustments.diff 2015-06-04 20:21:43.000000000 +0000 +++ pngcrush-1.8.13/debian/patches/local_Makefile_adjustments.diff 2019-02-22 08:07:23.000000000 +0000 @@ -5,30 +5,31 @@ Forwarded: not-needed Last-Update: 2013-07-01 ---- a/Makefile 2013-07-01 10:48:08.476563260 -0400 -+++ b/Makefile 2013-07-01 11:00:21.480264692 -0400 -@@ -11,28 +11,29 @@ +--- a/Makefile ++++ b/Makefile +@@ -11,11 +11,11 @@ # macros -------------------------------------------------------------------- # uncomment these 2 lines only if you are using an external copy of libpng: --PNGINC = ${HOME}/include --PNGLIB = ${HOME}/lib -+#PNGINC = ${HOME}/include -+#PNGLIB = ${HOME}/lib +-PNGINC = /usr/local/include +-PNGLIB = /usr/local/lib ++#PNGINC = /usr/local/include ++#PNGLIB = /usr/local/lib # uncomment these 2 lines only if you are using an external copy of zlib: --ZINC = ${HOME}/include --ZLIB = ${HOME}/lib -+#ZINC = ${HOME}/include -+#ZLIB = ${HOME}/lib +-ZINC = /usr/local/include +-ZLIB = /usr/local/lib ++#ZINC = /usr/local/include ++#ZLIB = /usr/local/lib CC = gcc LD = gcc - RM = rm -f - #CFLAGS = -I. -O -Wall - #CFLAGS = -I. -O3 -fomit-frame-pointer -Wall --CFLAGS = -I${ZINC} -I. -g -O3 -fomit-frame-pointer -Wall -+#CFLAGS = -I${ZINC} -I. -g -O3 -fomit-frame-pointer -Wall -+CFLAGS += $(CPPFLAGS) -I. -g -O3 -fomit-frame-pointer -Wall +@@ -23,15 +23,17 @@ RM = rm -f + + CPPFLAGS = -I $(PNGINC) + +-CFLAGS = -g -O3 -fomit-frame-pointer -Wall ++#CFLAGS = -g -O3 -fomit-frame-pointer -Wall ++CFLAGS += $(CPPFLAGS) -g -O3 -fomit-frame-pointer -Wall # [note that -Wall is a gcc-specific compilation flag ("all warnings on")] -LDFLAGS = +#LDFLAGS = @@ -37,11 +38,9 @@ PNGCRUSH = pngcrush - # LIBS = -lm --LIBS = -L$(PNGLIB) -lpng -lz -lm --# LIBS = -lpng -lz -lm -+# LIBS = -L$(PNGLIB) -lpng -lz -lm +-LIBS = -L$(PNGLIB) -L$(ZLIB) -lpng -lz -lm ++#LIBS = -L$(PNGLIB) -L$(ZLIB) -lpng -lz -lm +LIBS = -lpng -lz -lm - #LIBS = ${ZLIB}/libz.a -lm - # uncomment these 4 lines only if you are NOT using an external copy of zlib: + OBJS = pngcrush$(O) + diff -Nru pngcrush-1.7.85/debian/patches/local_version_skew_warning_only_if_verbose.diff pngcrush-1.8.13/debian/patches/local_version_skew_warning_only_if_verbose.diff --- pngcrush-1.7.85/debian/patches/local_version_skew_warning_only_if_verbose.diff 2015-06-04 20:21:43.000000000 +0000 +++ pngcrush-1.8.13/debian/patches/local_version_skew_warning_only_if_verbose.diff 2019-02-22 08:07:23.000000000 +0000 @@ -7,13 +7,11 @@ Forwarded: not-needed Last-Update: 2013-07-01 -Index: pngcrush/pngcrush.c -=================================================================== ---- pngcrush.orig/pngcrush.c 2015-06-04 22:09:34.453079010 +0200 -+++ pngcrush/pngcrush.c 2015-06-04 22:09:34.453079010 +0200 -@@ -3025,14 +3025,6 @@ - - t_start = (TIME_T) clock(); +--- a/pngcrush.c ++++ b/pngcrush.c +@@ -3611,14 +3611,6 @@ int main(int argc, char *argv[]) + pngcrush_timer_start(PNGCRUSH_TIMER_MISC); + #endif - if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) - { @@ -26,10 +24,10 @@ row_buf = (png_bytep) NULL; P2(" row_buf = %p\n",row_buf); number_of_open_files = 0; -@@ -7903,6 +7895,14 @@ - PNGCRUSH_VERSION, progname, PNG_LIBPNG_VER_STRING, - png_get_header_version(NULL), ZLIB_VERSION,zlib_copyright); - +@@ -8759,6 +8751,14 @@ void print_version_info(void) + #else + fprintf(STDERR,"\n"); + #endif + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) + { + fprintf(STDERR, diff -Nru pngcrush-1.7.85/debian/rules pngcrush-1.8.13/debian/rules --- pngcrush-1.7.85/debian/rules 2015-06-04 20:21:43.000000000 +0000 +++ pngcrush-1.8.13/debian/rules 2019-02-22 08:07:23.000000000 +0000 @@ -1,5 +1,7 @@ #!/usr/bin/make -f +export DEB_BUILD_MAINT_OPTIONS=hardening=+all + %: dh $@ diff -Nru pngcrush-1.7.85/debian/source/options pngcrush-1.8.13/debian/source/options --- pngcrush-1.7.85/debian/source/options 2015-06-04 20:21:43.000000000 +0000 +++ pngcrush-1.8.13/debian/source/options 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -compression = "xz" diff -Nru pngcrush-1.7.85/debian/watch pngcrush-1.8.13/debian/watch --- pngcrush-1.7.85/debian/watch 2015-06-04 20:21:43.000000000 +0000 +++ pngcrush-1.8.13/debian/watch 2019-02-22 08:07:23.000000000 +0000 @@ -1,2 +1,2 @@ version=3 -http://sf.net/pmt/pngcrush-([\d\.]+)-nolib\.tar\.xz +https://sf.net/pmt/pngcrush-([\d\.]+)-nolib\.tar\.xz diff -Nru pngcrush-1.7.85/LICENSE pngcrush-1.8.13/LICENSE --- pngcrush-1.7.85/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ pngcrush-1.8.13/LICENSE 2016-03-31 17:45:29.000000000 +0000 @@ -0,0 +1,80 @@ + +This copy of the pngcrush notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file pngcrush.c +the latter shall prevail. + +NOTICES: + +If you have modified this source, you may insert additional notices +immediately after this sentence. + +COPYRIGHT: + +Copyright (C) 1998-2002, 2006-2016 Glenn Randers-Pehrson + (glennrp at users.sf.net) +Portions copyright (C) 2005 Greg Roelofs + +LICENSE: + +Permission is hereby irrevocably granted to everyone to use, copy, modify, +and distribute this source code, or portions hereof, or executable programs +compiled from it, for any purpose, without payment of any fee, subject to +the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not be + misrepresented as being the original source. + +3. This Copyright notice, disclaimers, and license may not be removed + or altered from any source or altered source distribution. + +DISCLAIMERS: + +The pngcrush computer program is supplied "AS IS". The Author disclaims all +warranties, expressed or implied, including, without limitation, the +warranties of merchantability and of fitness for any purpose. The +Author assumes no liability for direct, indirect, incidental, special, +exemplary, or consequential damages, which may result from the use of +the computer program, even if advised of the possibility of such damage. +There is no warranty against interference with your enjoyment of the +computer program or against infringement. There is no warranty that my +efforts or the computer program will fulfill any of your particular purposes +or needs. This computer program is provided with all faults, and the entire +risk of satisfactory quality, performance, accuracy, and effort is with +the user. + +EXPORT CONTROL + +I am not a lawyer, but I believe that the Export Control Classification +Number (ECCN) for pngcrush is EAR99, which means not subject to export +controls or International Traffic in Arms Regulations (ITAR) because it +and libpng and zlib which may be bundled with pngcrush are all open source, +publicly available software, that do not contain any encryption software. +See the EAR, paragraphs 734.3(b)(3) and 734.7(b). + +TRADEMARK: + +The name "pngcrush" has not been registered by the Copyright owner +as a trademark in any jurisdiction. However, because pngcrush has +been distributed and maintained world-wide, continually since 1998, +the Copyright owner claims "common-law trademark protection" in any +jurisdiction where common-law trademark is recognized. + +CEXCEPT COPYRIGHT, DISCLAIMER, and LICENSE: + +The cexcept.h header file which is bundled with this software +is conveyed under the license and disclaimer described in lines 10 +through 18 of cexcept.h. + +LIBPNG COPYRIGHT, DISCLAIMER, and LICENSE: + +If libpng is bundled with this software, it is conveyed under the +libpng license (see COPYRIGHT NOTICE, DISCLAIMER, and LICENSE, in png.h). + +ZLIB COPYRIGHT, DISCLAIMER, and LICENSE: + +If zlib is bundled with this software, it is conveyed under the +zlib license (see the copyright notice, disclaimer, and license +appearing in zlib.h). + diff -Nru pngcrush-1.7.85/Makefile pngcrush-1.8.13/Makefile --- pngcrush-1.7.85/Makefile 2011-01-21 23:04:44.000000000 +0000 +++ pngcrush-1.8.13/Makefile 2016-10-03 05:16:21.000000000 +0000 @@ -11,18 +11,19 @@ # macros -------------------------------------------------------------------- # uncomment these 2 lines only if you are using an external copy of libpng: -PNGINC = ${HOME}/include -PNGLIB = ${HOME}/lib +PNGINC = /usr/local/include +PNGLIB = /usr/local/lib # uncomment these 2 lines only if you are using an external copy of zlib: -ZINC = ${HOME}/include -ZLIB = ${HOME}/lib +ZINC = /usr/local/include +ZLIB = /usr/local/lib CC = gcc LD = gcc RM = rm -f -#CFLAGS = -I. -O -Wall -#CFLAGS = -I. -O3 -fomit-frame-pointer -Wall -CFLAGS = -I${ZINC} -I. -g -O3 -fomit-frame-pointer -Wall + +CPPFLAGS = -I $(PNGINC) + +CFLAGS = -g -O3 -fomit-frame-pointer -Wall # [note that -Wall is a gcc-specific compilation flag ("all warnings on")] LDFLAGS = O = .o @@ -30,42 +31,27 @@ PNGCRUSH = pngcrush -# LIBS = -lm -LIBS = -L$(PNGLIB) -lpng -lz -lm -# LIBS = -lpng -lz -lm -#LIBS = ${ZLIB}/libz.a -lm - -# uncomment these 4 lines only if you are NOT using an external copy of zlib: -# ZHDR = zlib.h -# ZOBJS = adler32$(O) compress$(O) crc32$(O) deflate$(O) \ -# infback$(O) inffast$(O) inflate$(O) inftrees$(O) \ -# trees$(O) uncompr$(O) zutil$(O) +LIBS = -L$(PNGLIB) -L$(ZLIB) -lpng -lz -lm OBJS = pngcrush$(O) -# png$(O) pngerror$(O) pngget$(O) pngmem$(O) \ -# pngpread$(O) pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) \ -# pngset$(O) pngtrans$(O) pngwio$(O) pngwrite$(O) \ -# pngwtran$(O) pngwutil$(O) $(ZOBJS) EXES = $(PNGCRUSH)$(E) - # implicit make rules ------------------------------------------------------- .c$(O): cexcept.h $(ZHDR) - $(CC) -c $(CFLAGS) $< -#.c$(O): png.h pngconf.h pngcrush.h cexcept.h pngpriv.h $(ZHDR) -# $(CC) -c $(CFLAGS) $< - + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< # dependencies -------------------------------------------------------------- + all: $(EXES) pngcrush$(O): pngcrush.c cexcept.h - $(CC) -c $(CFLAGS) $< -# pngcrush$(O): pngcrush.c png.h pngconf.h pngcrush.h cexcept.h $(ZHDR) -# $(CC) -c $(CFLAGS) $< + touch png.h + mv png.h png.h_embedded + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< + mv png.h_embedded png.h $(PNGCRUSH)$(E): $(OBJS) $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) @@ -73,7 +59,7 @@ # maintenance --------------------------------------------------------------- clean: - $(RM) $(EXES) $(OBJS) png.h + $(RM) $(EXES) $(OBJS) install: mkdir -p $(DESTDIR)/usr/bin/ diff -Nru pngcrush-1.7.85/pngcrush.c pngcrush-1.8.13/pngcrush.c --- pngcrush-1.7.85/pngcrush.c 2015-03-09 19:03:01.000000000 +0000 +++ pngcrush-1.8.13/pngcrush.c 2017-08-21 22:28:52.000000000 +0000 @@ -1,10 +1,15 @@ -/* - * pngcrush.c - recompresses png files - * Copyright (C) 1998-2002, 2006-2015 Glenn Randers-Pehrson + +/* pngcrush.c - recompresses png files + * Copyright (C) 1998-2002, 2006-2017 Glenn Randers-Pehrson * (glennrp at users.sf.net) - * Portions copyright (C) 2005 Greg Roelofs - * - * This software is released under a license derived from the libpng + * Portions Copyright (C) 2005 Greg Roelofs + */ + +#define PNGCRUSH_VERSION "1.8.13" + +#undef BLOCKY_DEINTERLACE + +/* This software is released under a license derived from the libpng * license (see LICENSE, below). * * The most recent version of pngcrush can be found at SourceForge in @@ -22,31 +27,117 @@ * * Uses libpng and zlib. This program was based upon libpng's pngtest.c. * + * NOTICES: + * + * If you have modified this source, you may insert additional notices + * immediately after this sentence. + * + * COPYRIGHT: + * + * Copyright (C) 1998-2002, 2006-2017 Glenn Randers-Pehrson + * (glennrp at users.sf.net) + * Portions Copyright (C) 2005 Greg Roelofs + * + * LICENSE: + * + * Permission is hereby irrevocably granted to everyone to use, copy, modify, + * and distribute this source code, or portions hereof, or executable programs + * compiled from it, for any purpose, without payment of any fee, subject to + * the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and must not be + * misrepresented as being the original source. + * + * 3. This Copyright notice, disclaimers, and license may not be removed + * or altered from any source or altered source distribution. + * + * DISCLAIMERS: + * + * The pngcrush computer program is supplied "AS IS". The Author disclaims all + * warranties, expressed or implied, including, without limitation, the + * warranties of merchantability and of fitness for any purpose. The + * Author assumes no liability for direct, indirect, incidental, special, + * exemplary, or consequential damages, which may result from the use of + * the computer program, even if advised of the possibility of such damage. + * There is no warranty against interference with your enjoyment of the + * computer program or against infringement. There is no warranty that my + * efforts or the computer program will fulfill any of your particular purposes + * or needs. This computer program is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is with + * the user. + * + * EXPORT CONTROL + * + * I am not a lawyer, but I believe that the Export Control Classification + * Number (ECCN) for pngcrush is EAR99, which means not subject to export + * controls or International Traffic in Arms Regulations (ITAR) because it + * and cexcept.c, libpng, and zlib, which may be bundled with pngcrush, are + * all open source, publicly available software, that do not contain any + * encryption software. See the EAR, paragraphs 734.3(b)(3) and 734.7(b). + * + * TRADEMARK: + * + * The name "pngcrush" has not been registered by the Copyright owner + * as a trademark in any jurisdiction. However, because pngcrush has + * been distributed and maintained world-wide, continually since 1998, + * the Copyright owner claims "common-law trademark protection" in any + * jurisdiction where common-law trademark is recognized. + * + * CEXCEPT COPYRIGHT, DISCLAIMER, and LICENSE: + * + * The cexcept.h header file which is bundled with this software + * is conveyed under the license and disclaimer described in lines 10 + * through 18 of cexcept.h. + * + * LIBPNG COPYRIGHT, DISCLAIMER, and LICENSE: + * + * If libpng is bundled with this software, it is conveyed under the + * libpng license (see COPYRIGHT NOTICE, DISCLAIMER, and LICENSE, in png.h). + * + * If intel_init.c and filter_sse2_intrinsics.c are bundled with this + * software, they are conveyed under the libpng license (see the + * copyright notices within those files and the COPYRIGHT NOTICE, DISCLAIMER, + * and LICENSE in png.h). + * + * ZLIB COPYRIGHT, DISCLAIMER, and LICENSE: + * + * If zlib is bundled with this software, it is conveyed under the + * zlib license (see the copyright notice, disclaimer, and license + * appearing in zlib.h). + * + * ACKNOWLEDGMENTS: + * * Thanks to Greg Roelofs for various bug fixes, suggestions, and * occasionally creating Linux executables. * * Thanks to Stephan Levavej for some helpful suggestions about gcc compiler * options and for a suggestion to increase the Z_MEM_LEVEL from default. * + * Thanks to others who have made bug reports and suggestions mentioned + * in the change log. + * * CAUTION: * * There is another version of pngcrush that has been distributed by * Apple since mid-2008 as a part of the Xcode SDK. Although it claims * to be pngcrush by Glenn Randers-Pehrson, it has additional options * "-iPhone", "-speed", "-revert-iphone-optimizations", and perhaps others. - * It is an "altered version" but is not "plainly marked as such" as - * required by the license. + * It is an "altered version". I've seen output from a 2006 version that + * says on its help screen, "and modified by Apple as indicated in the + * sources". * * It writes files that have the PNG 8-byte signature but are not valid PNG * files (instead they are "IOS-optimized PNG files"), due to at least * - * o the presence of the CgBI chunk ahead of the IHDR chunk, - * o nonstandard deflate compression in IDAT, iCCP, and perhaps zTXt chunks; - * I believe this only amounts to the omission of the zlib header from - * the IDAT and perhaps other compressed chunks. - * o Omission of the CRC bytes from the IDAT chunk and perhaps other chunks. - * o the use of premultiplied alpha in color_type 6 files, and - * o the sample order, which is ARGB instead of RGBA in color_type 6 files. + * 1. the presence of the CgBI chunk ahead of the IHDR chunk; + * 2. nonstandard deflate compression in IDAT, iCCP, and perhaps zTXt chunks + * (I believe this only amounts to the omission of the zlib header from + * the IDAT and perhaps other compressed chunks); + * 3. Omission of the CRC bytes from the IDAT chunk and perhaps other chunks; + * 4. the use of premultiplied alpha in color_type 6 files; and + * 5. the sample order, which is ARGB instead of RGBA in color_type 6 files. * * See http://iphonedevwiki.net/index.php/CgBI_file_format for more info. * @@ -64,7 +155,7 @@ * * It is said that the Xcode pngcrush does have a command to undo the * premultiplied alpha. It's not theoretically possible, however, to recover - * the original file without loss. The underlying color data must either be + * the original file without loss. The underlying color data will either be * reduced in precision, or, in the case of fully-transparent pixels, * completely lost. * @@ -74,83 +165,9 @@ * application . Anyone * who does have access to the revised pngcrush code cannot show it to me * anyhow because of their Non-Disclosure Agreement with Apple. - * - */ - -#define PNGCRUSH_VERSION "1.7.85" - -/* Experimental: define these if you wish, but, good luck. -#define PNGCRUSH_COUNT_COLORS -#define PNGCRUSH_MULTIPLE_ROWS -*/ -#define PNGCRUSH_LARGE - -#define PNGCRUSH_ROWBYTES(pixel_bits, width) \ - ((pixel_bits) >= 8 ? \ - ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ - (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) - -/* - * NOTICES - * - * If you have modified this source, you may insert additional notices - * immediately after this sentence. - * - * COPYRIGHT: - * - * Copyright (C) 1998-2002, 2006-2015 Glenn Randers-Pehrson - * (glennrp at users.sf.net) - * Portions copyright (C) 2005 Greg Roelofs - * - * DISCLAIMERS: - * - * The pngcrush computer program is supplied "AS IS". The Author disclaims all - * warranties, expressed or implied, including, without limitation, the - * warranties of merchantability and of fitness for any purpose. The - * Author assumes no liability for direct, indirect, incidental, special, - * exemplary, or consequential damages, which may result from the use of - * the computer program, even if advised of the possibility of such damage. - * There is no warranty against interference with your enjoyment of the - * computer program or against infringement. There is no warranty that my - * efforts or the computer program will fulfill any of your particular purposes - * or needs. This computer program is provided with all faults, and the entire - * risk of satisfactory quality, performance, accuracy, and effort is with - * the user. - * - * LICENSE: - * - * Permission is hereby irrevocably granted to everyone to use, copy, modify, - * and distribute this source code, or portions hereof, or executable programs - * compiled from it, for any purpose, without payment of any fee, subject to - * the following restrictions: - * - * 1. The origin of this source code must not be misrepresented. - * - * 2. Altered versions must be plainly marked as such and must not be - * misrepresented as being the original source. - * - * 3. This Copyright notice, disclaimer, and license may not be removed - * or altered from any source or altered source distribution. - * - * CEXCEPT COPYRIGHT, DISCLAIMER, and LICENSE: - * - * The cexcept.h header file which is bundled with this software - * is released under the license and disclaimer described in lines 10 - * through 18 of cexcept.h. - * - * LIBPNG COPYRIGHT, DISCLAIMER, and LICENSE: - * - * If libpng is bundled with this software, it is released under the - * libpng license (see COPYRIGHT NOTICE, DISCLAIMER, and LICENSE, in png.h) - * - * ZLIB COPYRIGHT, DISCLAIMER, and LICENSE: - * - * If zlib is bundled with this software, it is released under the - * zlib license (see the copyright notice, disclaimer, and license - * appearing in lines 4 through 24 of zlib.h) */ -/* To do: +/* To do (TODO, TO DO): * * (As noted below, some of the features that aren't yet implemented * in pngcrush are already available in ImageMagick; you can try a @@ -160,6 +177,10 @@ * makes a pass with libpng's "pngfix" app to optimize the zlib CMF * bytes.) * + * 0. Make pngcrush optionally operate as a filter, writing the crushed PNG + * to standard output, if an output file is not given, and reading + * the source file from standard input if no input file is given. + * * 1. Reset CINFO to reflect decoder's required window size (instead of * libz-1.1.3 encoder's required window size, which is 262 bytes larger). * See discussion about zlib in png-list archives for April 2001. @@ -219,7 +240,7 @@ * * pngcrush input.png temp.png * pngfix --optimize --out=output.png temp.png - * # TO DO: find out if this works with zopfli output + * # To do: find out if this works with zopfli output * * 2. Check for the possiblity of using the tRNS chunk instead of * the full alpha channel. If all of the transparent pixels are @@ -249,19 +270,19 @@ * a GIT repository at SourceForge (see https://code.google.com/p/zopfli/). * See also the "pngzop" directory under the pmt.sourceforge.net project. * Note paragraph 1.c above; zopfli always writes "7" in CINFO. See - * my "pmt/pngzop" project at SourceForge. + * my "pmt/pngzop" project at SourceForge and GitHub. * * 5. Optionally recognize any sRGB iCCP profile and replace it with the * sRGB chunk. Turn this option on if the "-reduce" option is on. Also, * if "-reduce" is on, delete any gAMA and cHRM chunks if the sRGB chunk * is being written. * - * 6. Turn "-reduce" and "-force" on by default, and provide an "-old" - * option to use the current default settings for these.. + * 6. Accept "--long-option". For starters, just accept -long_option + * and --long_option equally. * - * 7. Implement a "-copy" option that simply copies the IDAT data, - * possibly repackaged in a different IDAT chunk size (not quite the same - * as the existing "-already" option). + * 7. Implement a "copy_idat" option that simply copies the IDAT data, + * implemented as "-m 176". This will still repackage the IDAT chunks + * in a possibly different IDAT chunk size. * * 8. Implement palette-building (from ImageMagick-6.7.0 or later, minus * the "PNG8" part) -- actually ImageMagick puts the transparent colors @@ -305,12 +326,180 @@ * according to args table. Could start with static table of 16 or 32 slots, * then double size & copy if run out of room: still O(n) algorithm. * + * 16. With libpng17, png_write throws an "affirm()" with tc.format=256 + * when attempting to write a sub-8-bit grayscale image. + * + * 17. Figure out why we aren't calling png_read_update_info() and fix. + * + * 18. Fix ADLER32 checksum handling in conjunction with iCCP chunk + * reading. + * + * 19. Fix Coverity "TOCTOU" warning about our "stat()" usage. + * + * 20. Warn about removing copyright and license info appearing in + * PNG text chunks. + * + * 21. Implement the "eXIf" chunk if it is approved by the PNG + * Development Group. Optionally, remove preview and thumbnail + * images from the Exif profile contained in the eXIf chunk. + * */ #if 0 /* changelog */ Change log: +Version 1.8.13 (built with libpng-1.6.32 and zlib-1.2.11) + Add "exit(0)" after processing "-version" argument, to avoid + displaying the Usage information (bug report by Peter Hagan, + Issue #76). + Fix problem with MacOS prior to Sierra; it uses CLOCK_MONOTONIC + for some other purpose (bug report and help developing patch by + Github user "ilovezfs", Homebrew/homebrew-core PR#16391). + +Version 1.8.12 (built with libpng-1.6.31 and zlib-1.2.11) + Added POWERPC-VSX support. + Report whether using optimizations. + Added filter_method 6 (same as filter 5 with -speed). + Added "methods" 149-176 (that use filter_method 6). + Changed default verbosity from 1 (normal) to 0 (quiet). Use "-v" to get + the previous default behavior and "-v -v" to get the previous "verbose" + behavior. The "-s" (silent) and "-q" (quiet) options behave as before. + +Version 1.8.11 (built with libpng-1.6.28 and zlib-1.2.11) + Use png_set_option(PNG_IGNORE_ADLER32) to control ADLER32 handling. + Changed LD=gcc to LD=$(CC) in Makefile and Makefile-nolib (suggested + by Helmut G in Bug#850927 of some GIT project) + +Version 1.8.10 (built with libpng-1.6.26 and zlib-1.2.8.1) + Changed ADLER32 checksum handling to only use inflateValidate() + during IDAT chunk handling; it broke iCCP chunk handling. + +Version 1.8.9 (built with libpng-1.6.26 and zlib-1.2.8.1) + Added "-warn" option, to show only warnings. + Enabled method 149. For now it writes uncompressed IDAT but in + a future version of pngcrush it will just copy the IDAT data. + +Version 1.8.8 (built with libpng-1.6.26beta06 and zlib-1.2.8.1) + Fixed "nolib" build (bug report by Hanspeter Niederstrasser). + Make sure we use system-png.h, and not the local file. It is now + possible to build either the regular pngcrush or the "nolib" + pngcrush in the complete pngcrush source directory (use + "make clean" before rebuilding!) + Fixed timing when using "clock()". Sometimes an additional second + was added when the timer crossed a one-second boundary, since + version 1.8.5. + Upgrade libpng to version 1.6.26beta06 and zlib to 1.2.8.1. + Use zlib-1.2.8.1 new "inflateValidate()" function to avoid checking + ADLER32 checksums. Version 1.8.7 did not work when the "-fix" + option was used. + +Version 1.8.7 (built with libpng-1.6.25 and zlib-1.2.8) + Do not check the ADLER32 CRC while reading except during the final write + pass (requires libpng-1.6.26 or later and zlib-1.2.4 or later). + This saves some CPU time, around five to ten percent, in decoding. + Do not calculate the ADLER32 CRC while writing except during the final + write pass (writing raw deflate streams instead of zlib streams to + the IDAT chunks; these are invalid PNGs but since all we do is count + the bytes that does not matter). This saves some CPU time in encoding + but it is barely perceptible. Requires zlib 1.2.4 or later and modified + pngwutil.c. + +Version 1.8.6 (built with libpng-1.6.25 and zlib-1.2.8) + Enabled ARM_NEON support. + Fixed error in handling of timer wraparound when interval exceeds one + second. + Disable high resolution timers by default in Makefile. To enable them, + you must enable/disable relevant CPPFLAGS and LIBS in Makefile. + +Version 1.8.5 (built with libpng-1.6.24 and zlib-1.2.8) + Added "-benchmark n" option. It runs the main loop "n" times, and + records the minimum value for each timer. + After checking for CLOCK_ID, use clock() if none is found. + Avoid some timing when verbose<0 ("-s" or "--silent") + Added PNGCRUSH_CHECK_CRC (off by default) to use libpng default + CRC checking. Otherwise, CRC are only computed and checked during + the first read pass and while writing. + Accept "--option" (for now, by simply skipping the first "-"). + +Version 1.8.4 (built with libpng-1.6.24 and zlib-1.2.8) + Fixed handling of CLOCK_ID, removed some "//"-delimited comments. + Revised intel_init.c to always optimize 4bpp images, because the + poor optimization noted previously has been fixed. + +Version 1.8.3 (built with libpng-1.6.24 and zlib-1.2.8) + Fixed bug introduced in 1.8.2 that causes trial 10 to be skipped when + using the default heuristic method. + Fixed incorrect typecast in call to png_create_write_struct_2() (Bug + report by Richard K. Lloyd). + Added intel_init.c, filter_sse2_intrinsics.c, and Makefile-sse, + to enable INTEL SSE optimization. Revised intel_init.c to optionally + only optimize 4bpp images, because the optimization appears to slow + down reading of 3bpp images. + Added PNGCRUSH_TIMERS (nanosecond resolution using clock_gettime), to + measure defiltering time in png_read_filter_row(). For now, this only + works with a modified libpng, on platforms that provide "clock_gettime()". + To enable all timers, define PNGCRUSH_TIMERS=11. + Revised "-q" to show a short summary of results (final size and timing) + To do: Add ZLIB_AMALGAMATED configuration; currently produces different output + https://blog.forrestthewoods.com/ + improving-open-source-with-amalgamation-cf293592c5f4#.g9fb2tyhs + (added #ifndef NO_GZ / #endif to skip the gz* code in zlib_amalg.[ch]). + Added LIBPNG_UNIFIED configuration. + +Version 1.8.2 (built with libpng-1.6.23 and zlib-1.2.8) + Fixed filesize reduction report when "-ow" option is used (Bug report #68). + When a single method is specified, turn -reduce off by default and skip + trial 0. + +Version 1.8.1 (built with libpng-1.6.21 and zlib-1.2.8) + Added the LICENSE file to the tar and zip distributions. + Made "-force" force output even when the IDAT is larger, and added + "-noforce" option; "-noforce" is now the default behavior (Bug + report #68 at SourceForge by "wintakeall") + Use right filename in filesize reduction report (overwrite?inname:outname) + (bug report #69 by "wintakeall"). + Removed some superfluous spaces from the Copyright statement. + Added "-speed" option; it avoids using the AVG or PAETH filters which + are slower to decode. + +Version 1.8.0 (built with libpng-1.6.21 and zlib-1.2.8) + Made "-reduce" and "-force" the default behavior. Removed obsolete + options "-plte_len", "-cc", "-nocc", "-double_gamma", "-already_crushed", + and "-bit_depth". Removed "things_have_changed" code. + +Version 1.7.92 (built with libpng-1.6.20 and zlib-1.2.8) + Deleted png_read_update_info() statement that was mistakenly added to + version 1.7.89. It caused "bad adaptive filter value" errors. + +Version 1.7.91 (built with libpng-1.6.20 and zlib-1.2.8) + Suppress warning about "damaged LZ stream" when bailing out and building + with libpng-1.7.0beta. + Added a LICENSE file to the distribution. It points to the actual + license appearing in the NOTICES section near the top of pngcrush.c + Show if pngcrush is built with bundled or system libpng and zlib. + Fixed segfault while writing a -loco MNG (bug found with AFL, reported + by Brian Carpenter). Bug was introduced in pngcrush-1.7.35. + +Version 1.7.88 (built with libpng-1.6.19 and zlib-1.2.8) + Eliminated a potential overflow while adding iTXt chunk (over-length + text_lang or text_lang_key), reported by Coverity. + +Version 1.7.87 (built with libpng-1.6.18 and zlib-1.2.8) + Fixed a double-free bug (CVE-2015-7700). There was a "free" of the + sPLT chunk structure in pngcrush and then again in png.c (Bug report + by Brian Carpenter). + Added common-law trademark notice and export control information. + Rearranged some paragraphs in the comments at the beginning of pngcrush.c + Increased some buffer sizes in an attempt to prevent possible overflows. + +Version 1.7.86 (built with libpng-1.6.18 and zlib-1.2.8) + Increased maximum size of a text chunk input from 260 to 2048 + (STR_BUF_SIZE) bytes, to agree with the help screen (bug report by + Tamas Jursonovics). + Fixed bug that caused text chunks after IDAT to be written only when + the "-save" option is used. + Version 1.7.85 (built with libpng-1.6.16 and zlib-1.2.8) Improved reporting of invalid chunk names. Does not try to put non-printable characters in STDERR; displays hex numbers instead. @@ -437,17 +626,17 @@ Moved a closing bracket inside the PNGCRUSH_LOCO block. Moved the declaration of "new_mng" outside a PNGCRUSH_LOCO block. Put reference to "input_format" inside a PNGCRUSH_LOCO block. - Moved declarations of mng_out and mngname inside a PNGCRUSH_LOGO block. + Moved declarations of mng_out and mngname inside a PNGCRUSH_LOCO block. Version 1.7.58 (built with libpng-1.5.15 and zlib-1.2.7-1) Do not enable reduce_palette by default for "-reduce", "-new", or "-old". It still is failing for some files. Version 1.7.57 (built with libpng-1.5.15 and zlib-1.2.7-1) - Added "-new" option that turns on "-reduce" and "-force" which will be - the default settings for version 1.8.0 and beyond. - Added "-old" option that turns off "-reduce" and "-force" which are the - current default settings. + Added "-new" option that turns on "-reduce" which will be + the default setting for version 1.8.0 and beyond. + Added "-old" option that turns off "-reduce" which is the + current default setting. Updated copyright year for zlib-1.2.7-1. Reverted to libpng-1.5.15 to be able to read old PNG files with TOO FAR errors. This will of course only work with the embedded libpng. @@ -794,7 +983,7 @@ Version 1.6.18 (built with libpng-1.2.37 and zlib-1.2.3.2) Removed extra FCLOSE(fpin) and FCLOSE(fpout) in the first Catch{} block, - since they get removed anyway right after that (hanno boeck). + since they get removed anyway right after that (Hanno Boeck). Define PNG_NO_READ|WRITE_cHRM and PNG_NO_READ_|WRITEiCCP in pngcrush.h and reordered pngcrush.h @@ -1220,11 +1409,336 @@ #endif /* end of changelog */ +static int verbose = 0; +static int show_warnings = 0; /* =1 to show warnings even with verbose < 0 */ +static int copy_idat = 0; /* = 1 to simply copy the IDAT chunk data */ + +/* Experimental: define these if you wish, but, good luck. +#define PNGCRUSH_COUNT_COLORS +#define PNGCRUSH_MULTIPLE_ROWS +*/ + +#define PNGCRUSH_LARGE + +#define PNGCRUSH_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ + (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + /* Suppress libpng pedantic warnings */ #if 0 #define PNG_DEPSTRUCT /* Access to this struct member is deprecated */ #endif +#ifndef PNGCRUSH_TIMERS +# define PNGCRUSH_TIMERS 4 +#endif + +#if PNGCRUSH_TIMERS > 0 + +/* TIMER function + ===== ====================== + set in pngcrush.c: + 0 total time + 1 total decode + 2 total encode + 3 total other + set in pngread.c: + 4 decode deinterlace + 5 decode filter 0 (none) + 6 decode filter 1 (sub) + 7 decode filter 2 (up) + 8 decode filter 3 (avg) + 9 decode filter 4 (paeth) + set in pngwutil.c: + 10 encode filter setup +*/ +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 199309L /* for clock_gettime */ + +#include + +#ifdef CLOCKS_PER_SECOND +# if CLOCKS_PER_SECOND == '"1000"' +# undef CLOCKS_PER_SEC +# endif +#endif + +#ifndef CLOCKS_PER_SEC +# define CLOCKS_PER_SEC 1000 +#endif + +#ifdef __STDC__ +# define TIME_T clock_t +#else +# if CLOCKS_PER_SEC <= 100 +# define TIME_T long +# else +# define TIME_T float +# endif +#endif + +#ifdef __APPLE__ +# include +#endif + +/* As in GraphicsMagick */ +# if PNGCRUSH_USE_CLOCK_GETTIME == 0 +# define PNGCRUSH_USING_CLOCK "clock()" +# elif defined(CLOCK_HIGHRES) /* Solaris */ +# define PNGCRUSH_CLOCK_ID CLOCK_HIGHRES +# define PNGCRUSH_USING_CLOCK "clock_gettime(CLOCK_HIGHRES,&t)" +# define PNGCRUSH_USE_CLOCK_GETTIME 1 +# elif defined(CLOCK_MONOTONIC_RAW) /* Linux */ +# define PNGCRUSH_CLOCK_ID CLOCK_MONOTONIC_RAW +# define PNGCRUSH_USING_CLOCK "clock_gettime(CLOCK_MONOTONIC_RAW,&t)" +# define PNGCRUSH_USE_CLOCK_GETTIME 1 +# elif defined(CLOCK_MONOTONIC_PRECISE) /* FreeBSD */ +# define PNGCRUSH_CLOCK_ID CLOCK_MONOTONIC_PRECISE +# define PNGCRUSH_USING_CLOCK "clock_gettime(CLOCK_MONOTONIC_PRECISE,&t)" +# define PNGCRUSH_USE_CLOCK_GETTIME 1 +# elif defined(CLOCK_MONOTONIC) /* Linux, FreeBSD & macOS Sierra & up */ && \ + !(defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED < 101200) +# define PNGCRUSH_CLOCK_ID CLOCK_MONOTONIC +# define PNGCRUSH_USING_CLOCK "clock_gettime(CLOCK_MONOTONIC,&t)" +# define PNGCRUSH_USE_CLOCK_GETTIME 1 +# else +# define PNGCRUSH_USING_CLOCK "clock()" +# undef PNGCRUSH_USE_CLOCK_GETTIME +# define PNGCRUSH_USE_CLOCK_GETTIME 0 +# endif +#else /* PNGCRUSH_TIMERS */ +# define PNGCRUSH_USING_CLOCK "clock()" +# define PNGCRUSH_USE_CLOCK_GETTIME 0 +#endif + +#ifndef LIBPNG_UNIFIED +#include +#define PNGCRUSH_TIMER_UINT_API extern unsigned int PNGAPI +#define PNGCRUSH_TIMER_VOID_API extern void PNGAPI +#else +#define PNGCRUSH_TIMER_UINT_API unsigned int +#define PNGCRUSH_TIMER_VOID_API void +#endif + +#define PNGCRUSH_TIMER_DECODE 1 +#define PNGCRUSH_TIMER_ENCODE 2 +#define PNGCRUSH_TIMER_MISC 3 +#define PNGCRUSH_TIMER_TOTAL 0 + +static unsigned int pngcrush_timer_hits[PNGCRUSH_TIMERS]; +static unsigned int pngcrush_timer_secs[PNGCRUSH_TIMERS]; +static unsigned int pngcrush_timer_nsec[PNGCRUSH_TIMERS]; +static unsigned int pngcrush_clock_secs[PNGCRUSH_TIMERS]; +static unsigned int pngcrush_clock_nsec[PNGCRUSH_TIMERS]; + +PNGCRUSH_TIMER_UINT_API +pngcrush_timer_get_seconds(unsigned int n); +PNGCRUSH_TIMER_UINT_API +pngcrush_timer_get_hits(unsigned int n); +PNGCRUSH_TIMER_UINT_API +pngcrush_timer_get_nanoseconds(unsigned int n); +PNGCRUSH_TIMER_VOID_API +pngcrush_timer_reset(unsigned int n); +PNGCRUSH_TIMER_VOID_API +pngcrush_timer_start(unsigned int n); +PNGCRUSH_TIMER_VOID_API +pngcrush_timer_stop(unsigned int n); + +#if PNGCRUSH_TIMERS > 0 +PNGCRUSH_TIMER_UINT_API +pngcrush_timer_get_hits(unsigned int n) +{ + if (n < PNGCRUSH_TIMERS) + { + return pngcrush_timer_hits[n]; + } + return 0; +} +PNGCRUSH_TIMER_UINT_API +pngcrush_timer_get_seconds(unsigned int n) +{ + if (n < PNGCRUSH_TIMERS) + { + return pngcrush_timer_secs[n]; + } + return 0; +} +PNGCRUSH_TIMER_UINT_API +pngcrush_timer_get_nanoseconds(unsigned int n) +{ + if (n < PNGCRUSH_TIMERS) + { + return pngcrush_timer_nsec[n]; + } + return 0; +} +PNGCRUSH_TIMER_VOID_API +pngcrush_timer_reset(unsigned int n) +{ + if (n < PNGCRUSH_TIMERS) + { + pngcrush_timer_secs[n] = 0; + pngcrush_timer_nsec[n] = 0; + pngcrush_timer_hits[n] = 0; + } +} +PNGCRUSH_TIMER_VOID_API +pngcrush_timer_start(unsigned int n) +{ + if (verbose >= 0 && n < PNGCRUSH_TIMERS) + { +#if PNGCRUSH_USE_CLOCK_GETTIME + struct timespec t; + clock_gettime(PNGCRUSH_CLOCK_ID, &t); + pngcrush_clock_secs[n] = t.tv_sec; + pngcrush_clock_nsec[n] = t.tv_nsec; +#else + TIME_T t = clock(); + pngcrush_clock_secs[n] = t/CLOCKS_PER_SEC; + pngcrush_clock_nsec[n] = (t*1000000000/CLOCKS_PER_SEC) - + pngcrush_clock_secs[n]*1000000000; +#endif + } +} +PNGCRUSH_TIMER_VOID_API +pngcrush_timer_stop(unsigned int n) +{ + if (verbose >= 0 && n < PNGCRUSH_TIMERS) + { + unsigned long seconds; + unsigned long nseconds; + unsigned long delta_secs; + unsigned long delta_nsec; +#if PNGCRUSH_USE_CLOCK_GETTIME + struct timespec t; + clock_gettime(PNGCRUSH_CLOCK_ID, &t); + seconds = t.tv_sec; + nseconds = t.tv_nsec; +#else + TIME_T t = clock(); + seconds = t/CLOCKS_PER_SEC; + nseconds = (t*1000000000/CLOCKS_PER_SEC) - seconds*1000000000; +#endif + delta_secs = (unsigned int)seconds - pngcrush_clock_secs[n]; + if ((unsigned long)nseconds < pngcrush_clock_nsec[n]) + { + delta_nsec = 1000000000; + delta_secs--; + } + else + { + delta_nsec = 0; + } + + delta_nsec += (unsigned long)nseconds - pngcrush_clock_nsec[n]; + pngcrush_timer_secs[n] += delta_secs; + pngcrush_timer_nsec[n] += delta_nsec; + + if (pngcrush_timer_nsec[n] >= 1000000000) + { + pngcrush_timer_nsec[n] -= 1000000000; + pngcrush_timer_secs[n]++; + } + + pngcrush_clock_secs[n] = (unsigned long)seconds; + pngcrush_clock_nsec[n] = (unsigned long)nseconds; + pngcrush_timer_hits[n]++; + } +} + +static unsigned long pngcrush_timer_min_secs[PNGCRUSH_TIMERS]; +static unsigned long pngcrush_timer_min_nsec[PNGCRUSH_TIMERS]; +#endif /* PNGCRUSH_TIMERS */ + + +#ifdef ZLIB_AMALGAMATED +/* See + https://blog.forrestthewoods.com/ + improving-open-source-with-amalgamation-cf293592c5f4#.g9fb2tyhs + */ +#include "zlib_amalg.c" +#define ZLIB_H +#endif /* ZLIB_AMALGAMATED */ + +#ifdef ZLIB_UNIFIED /* Not working */ +#include "zutil.h" + +#include "adler32.c" +#undef DO1 +#undef DO8 + +#include "compress.c" +#include "crc32.c" +#include "deflate.c" +#include "infback.c" +#undef PULLBYTE + +#include "inffast.c" +#undef CHECK +#undef CODES +#undef DISTS +#undef DONE +#undef LENGTH +#undef LENS + +#include "inflate.c" +#undef CHECK +#undef CODES +#undef DISTS +#undef DONE +#undef LENGTH +#undef LENS +#undef PULLBYTE + +#include "inftrees.c" +#undef CHECK +#undef CODES +#undef DISTS +#undef DONE +#undef LENGTH +#undef LENS + +#include "trees.c" +#include "uncompr.c" +#include "zutil.c" +#endif /* ZLIB_UNIFIED */ + +#ifdef LIBPNG_UNIFIED +#include "pngcrush.h" +#include "png.c" +#include "pngerror.c" +#include "pngget.c" +#include "pngmem.c" +#include "pngpread.c" +#include "pngread.c" +#include "pngrio.c" +#include "pngrtran.c" +#include "pngrutil.c" +#include "pngset.c" +#include "pngtrans.c" +#include "pngwio.c" +#include "pngwrite.c" +#include "pngwtran.c" +#include "pngwutil.c" +#ifdef PNGCRUSH_USE_ARM_NEON +# include "arm_init.c" +# include "filter_neon_intrinsics.c" +#endif +#ifdef PNGCRUSH_USE_MIPS_NSA +# include "mips_init.c" +# include "filter_msa_intrinsics.c" +#endif +#ifdef PNGCRUSH_USE_INTEL_SSE +# include "intel_init.c" +# include "filter_sse2_intrinsics.c" +#endif +#ifdef PNGCRUSH_USE_POWERPC_VSX +# include "powerpc_init.c" +# include "filter_vsx_intrinsics.c" +#endif +#endif /* LIBPNG_UNIFIED */ + #include "png.h" #ifndef PNGCBAPI /* Needed when building with libpng-1.4.x and earlier */ @@ -1249,7 +1763,7 @@ #define pngcrush_save_uint_32 png_save_uint_32 #undef PNG_ABORT -#if (PNG_LIBPNG_VER < 10400) +#if (PNGCRUSH_LIBPNG_VER < 10400) /* This allows png_default_error() to return, when it is called after our * own exception handling, which only returns after "Too many IDAT's", * or anything else that we might want to handle as a warning instead of @@ -1257,13 +1771,13 @@ * png_benign_error() instead. */ # define PNG_ABORT() (void)0 -#elif (PNG_LIBPNG_VER < 10700) +#elif (PNGCRUSH_LIBPNG_VER < 10700) # define PNG_ABORT() abort() #else # define PNG_ABORT abort(); #endif -#if (PNG_LIBPNG_VER < 10500) +#if (PNGCRUSH_LIBPNG_VER < 10500) /* Two macros to return the first row and first column of the original, * full, image which appears in a given pass. 'pass' is in the range 0 * to 6 and the result is in the range 0 to 7. @@ -1295,9 +1809,10 @@ -1)-PNG_PASS_START_ROW(pass)))>>PNG_PASS_ROW_SHIFT(pass)) #define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) -#endif /* PNG_LIBPNG_VER < 10500 */ +#endif /* PNGCRUSH_LIBPNG_VER < 10500 */ #if PNGCRUSH_LIBPNG_VER >= 10500 +#if !defined(ZLIB_AMALGAMATED) && !defined(ZLIB_UNIFIED) /* "#include " is not provided by libpng15 */ #ifdef PNGCRUSH_H /* Use the bundled zlib */ @@ -1306,6 +1821,7 @@ /* Use the system zlib */ # include #endif +#endif /* ZLIB_AMALGAMATED || ZLIB_UNIFIED */ /* Not provided by libpng16 */ # include @@ -1336,6 +1852,7 @@ # endif #endif +#ifndef LIBPNG_UNIFIED #define PNG_IDAT const png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} #define PNG_IHDR const png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} #define PNG_acTL const png_byte png_acTL[5] = { 97, 99, 84, 76, '\0'} @@ -1344,6 +1861,7 @@ #define PNG_fdAT const png_byte png_fdAT[5] = {102, 100, 65, 84, '\0'} #define PNG_iCCP const png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} #define PNG_IEND const png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} +#endif /* GRR 20050220: added these, which apparently aren't defined anywhere else */ /* GRP 20110714: define PNG_UINT_32_NAME macro and used that instead */ @@ -1455,6 +1973,7 @@ # define PNG_UINT_zTXt PNG_UINT_32_NAME(122, 84, 88, 116) #endif +#ifndef LIBPNG_UNIFIED #define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 #define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 #define PNG_FLAG_CRC_CRITICAL_USE 0x0400 @@ -1472,6 +1991,7 @@ #define PNG_FILLER 0x8000L #define PNG_USER_TRANSFORM 0x100000L #define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ +#endif /* LIBPNG_UNIFIED */ /* * We don't need some of the extra libpng transformations @@ -1488,10 +2008,6 @@ # define STDERR stderr #endif -#ifndef PNGCRUSH_LIBPNG_VER -# define PNGCRUSH_LIBPNG_VER PNG_LIBPNG_VER -#endif - #ifdef PNG_MNG_FEATURES_SUPPORTED # define PNGCRUSH_LOCO #endif @@ -1568,6 +2084,7 @@ #define DIRECTORY_MODE 1 #define EXTENSION_MODE 2 #define DIREX_MODE 3 +#define OVERWRITE_MODE 4 #define FOPEN(file, how) fopen(file, how) #define FCLOSE(file) {fclose(file); file=NULL;--number_of_open_files;}; @@ -1578,9 +2095,9 @@ #define STRNGIFY_STAGE1(x) #x #define STRNGIFY(x) STRNGIFY_STAGE1(x) -#define STR_BUF_SIZE 260 +#define STR_BUF_SIZE 2048 #define MAX_IDAT_SIZE 524288L -#define MAX_METHODS 150 +#define MAX_METHODS 177 #define MAX_METHODSP1 (MAX_METHODS+1) #define DEFAULT_METHODS 10 #define FAKE_PAUSE_STRING "P" @@ -1595,26 +2112,6 @@ # include #endif -#ifdef CLOCKS_PER_SECOND -# if CLOCKS_PER_SECOND == '"1000"' -# undef CLOCKS_PER_SEC -# endif -#endif - -#ifndef CLOCKS_PER_SEC -# define CLOCKS_PER_SEC 1000 -#endif - -#ifdef __STDC__ -# define TIME_T clock_t -#else -# if CLOCKS_PER_SEC <= 100 -# define TIME_T long -# else -# define TIME_T float -# endif -#endif - struct options_help { int verbosity; /* if verbose >= this value, then print line */ @@ -1656,7 +2153,7 @@ static int premultiply = 0; static int printed_version_info = 0; static int interlace_method = 0; -#if (PNG_LIBPNG_VER < 10400) +#if (PNGCRUSH_LIBPNG_VER < 10400) png_size_t max_bytes; #else png_alloc_size_t max_bytes; @@ -1672,7 +2169,7 @@ * .ppng -> .ppng is not OK because colors are irretrievably lost. * .ppng -> no output (pngcrush -n) is OK. * - * TO DO: Implement this stuff! + * To do: Implement this stuff! */ static int found_CgBI = 0; @@ -1688,7 +2185,7 @@ static png_uint_32 max_rows_at_a_time = 1; static png_uint_32 rows_at_a_time; #endif -char pplt_string[1024]; +char pplt_string[STR_BUF_SIZE]; char *ip, *op, *dot; char in_string[STR_BUF_SIZE]; char prog_string[STR_BUF_SIZE]; @@ -1698,13 +2195,13 @@ int text_where[10]; /* 0: no text; 1: before PLTE; 2: after PLTE */ int text_compression[10]; /* -1: uncompressed tEXt; 0: compressed zTXt 1: uncompressed iTXt; 2: compressed iTXt */ -char text_text[10*2048]; /* It would be nice to png_malloc this, but we - * don't have a png_ptr yet when we need it. */ -char text_keyword[10*80]; +char text_text[11*STR_BUF_SIZE+1]; /* It would be nice to png_malloc this but we + don't have a png_ptr yet when we need it. */ +char text_keyword[11*80+1]; /* PNG_iTXt_SUPPORTED */ -char text_lang[800]; -char text_lang_key[800]; +char text_lang[881]; +char text_lang_key[881]; /* PNG_iCCP_SUPPORTED */ int iccp_length = 0; @@ -1723,6 +2220,7 @@ struct exception_context the_exception_context[1]; png_const_charp msg; +static png_uint_32 input_length; static png_uint_32 total_input_length = 0; static png_uint_32 total_output_length = 0; static int pngcrush_mode = DEFAULT_MODE; @@ -1739,16 +2237,19 @@ static png_uint_32 pngcrush_write_byte_count; static png_uint_32 pngcrush_best_byte_count=0xffffffff; -static int verbose = 1; static int salvage = 0; -static int bail = 0; /* if 0, bail out of trials early */ +static int bail = 0; /* if 0, bail out of trials early */ +static int check_crc = 0; /* if 0, skip CRC and ADLER32 checks */ + /* otherwise check both */ +static int force = 1; /* if 1, force output even if IDAT is larger */ +static unsigned int benchmark_iterations = 0; static int blacken = 0; /* if 0, or 2 after the first trial, do not blacken color samples */ /* Delete these in pngcrush-1.8.0 */ -#if 1 +#if 0 static int make_gray = 0; /* if 0, 2, or 3 after the first trial, do not change color_type to gray */ static int make_opaque = 0; /* if 0, 2, or 3 after the first trial, @@ -1759,7 +2260,8 @@ #endif /* Activate these in pngcrush-1.8.0 */ -#if 0 +#if 1 +static int noreduce = 1; /* if 0, "-reduce" was specified */ static int make_gray = 1; /* if 0, 2, or 3 after the first trial, do not change color_type to gray */ static int make_opaque = 1; /* if 0, 2, or 3 after the first trial, @@ -1769,16 +2271,6 @@ static int reduce_palette = 1; #endif -/* TO DO: do this another way. "things_have_changed" is an attempt - * to preserve the IDAT from the original file (by preserving the - * entire input file) when it is smaller than that achieved by any - * of the pngcrush trials. Better would be to handle the editing - * functions separately from the compression, i.e., just preserve - * the IDAT from the original file if it is smaller than any trial. - */ -static int things_have_changed = 0; -static int global_things_have_changed = 0; - static int compression_window; static int default_compression_window = 15; static int force_compression_window = 0; @@ -1795,11 +2287,12 @@ #else static int brute_force_strategies[NUM_STRATEGIES] = { 1, 1, 1 }; #endif +static int speed = 0; static int method = 10; static int pauses = 0; -static int nosave = 0; -static int overwrite = 0; /* overwrite the input file instead of creating - a new output file */ +static int nosave = 0; /* 0: save; 1: do not save */ +static int overwrite = 0; /* 1: overwrite the input file instead of + creating a new output file */ static int nofilecheck = 0; static int no_limits = 0; static int new_mng = 0; @@ -1827,6 +2320,7 @@ static int double_gamma = 0; static int names; +static int first_name; static int have_trns = 0; static png_uint_16 trns_index = 0; @@ -1876,7 +2370,14 @@ static png_uint_32 idat_length[MAX_METHODSP1]; static int filter_type, zlib_level; static png_bytep png_row_filters = NULL; -static float t_start, t_stop, t_decode, t_encode, t_misc; + +#if PNGCRUSH_TIMERS > 0 +unsigned int pc_timer; +static float t_filter[PNGCRUSH_TIMERS] = {0}; +static png_uint_32 filter_count[PNGCRUSH_TIMERS] = {0}; +png_uint_32 t_sec; +png_uint_32 t_nsec; +#endif static png_uint_32 max_idat_size = MAX_IDAT_SIZE; /* increases the IDAT size */ @@ -1931,30 +2432,6 @@ void pngcrush_write_png(png_structp write_pointer, png_bytep data, png_size_t length); -#ifdef PNGCRUSH_H -void png_reset_crc(png_structp png_ptr); -void png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length); -void png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length); -int png_crc_error(png_structp png_ptr); -int png_crc_finish(png_structp png_ptr, png_uint_32 skip); -#else -/* Use replacement functions for those in the system libpng */ -void pngcrush_reset_crc(png_structp png_ptr); -void pngcrush_calculate_crc(png_structp png_ptr, \ - png_bytep ptr, png_size_t length); -void pngcrush_crc_read(png_structp png_ptr, png_bytep buf,\ - png_size_t length); -int pngcrush_crc_error(png_structp png_ptr); -int pngcrush_crc_finish(png_structp png_ptr, png_uint_32 skip); -#define png_reset_crc(png_ptr) pngcrush_reset_crc(png_ptr) -#define png_calculate_crc(png_ptr, ptr, length) \ - pngcrush_calculate_crc(png_ptr, ptr, length) -#define png_crc_read(png_ptr, buf, length) \ - pngcrush_crc_read(png_ptr, buf, length) -#define png_crc_error(png_ptr) pngcrush_crc_error(png_ptr) -#define png_crc_finish(png_ptr, skip) pngcrush_crc_finish(png_ptr, skip) -#endif - #ifdef PNG_USER_MEM_SUPPORTED png_voidp pngcrush_debug_malloc(png_structp png_ptr, png_uint_32 size); void pngcrush_debug_free(png_structp png_ptr, png_voidp ptr); @@ -1978,7 +2455,17 @@ void print_version_info(void); void print_usage(int retval); -#ifndef PNGCRUSH_H +#ifdef PNGCRUSH_H +/* Use unexported functions in the embedded libpng */ +# define pngcrush_reset_crc(png_ptr) png_reset_crc(png_ptr) +# define pngcrush_calculate_crc(png_ptr, ptr, length) \ + png_calculate_crc(png_ptr, ptr, length) +# define pngcrush_crc_read(png_ptr, buf, length) \ + png_crc_read(png_ptr, buf, length) +# define pngcrush_crc_error(png_ptr) png_crc_error(png_ptr) +# define pngcrush_crc_finish(png_ptr, skip) png_crc_finish(png_ptr, skip) + +#else /* * ============================================================ * We aren't using the bundled libpng functions, so we must @@ -1986,10 +2473,9 @@ * ============================================================ */ - -# if (PNG_LIBPNG_VER >= 10209) -# ifndef PNG_READ_BIG_ENDIAN_SUPPORTED -#undef pngcrush_get_uint_32 +# if (PNGCRUSH_LIBPNG_VER >= 10209) +# ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +# undef pngcrush_get_uint_32 png_uint_32 pngcrush_get_uint_32(png_bytep buf); /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ png_uint_32 /* PRIVATE */ @@ -2000,11 +2486,11 @@ return (i); } -# else +# else /*! BIG_ENDIAN */ # define pngcrush_get_uint_32(buf) ( *((png_uint_32p) (buf))) -# endif +# endif /* BIG_ENDIAN */ -#undef pngcrush_get_uint_31 +# undef pngcrush_get_uint_31 png_uint_32 pngcrush_get_uint_31(png_structp png_ptr, png_bytep buf); png_uint_32 /* PRIVATE */ pngcrush_get_uint_31(png_structp png_ptr, png_bytep buf) @@ -2018,7 +2504,7 @@ return (i); } -#undef pngcrush_save_uint_32 +# undef pngcrush_save_uint_32 void pngcrush_save_uint_32(png_bytep buf, png_uint_32 i); void /* PRIVATE */ pngcrush_save_uint_32(png_bytep buf, png_uint_32 i) @@ -2028,7 +2514,7 @@ buf[2] = (png_byte)((i >> 8) & 0xff); buf[3] = (png_byte)(i & 0xff); } -# endif /* PNG_LIBPNG_VER < 10209 */ +# endif /* PNGCRUSH_LIBPNG_VER < 10209 */ /* * Reset the CRC variable to 32 bits of 1's. Care must be taken @@ -2106,7 +2592,7 @@ return (0); } -#endif /* !defined(PNGCRUSH_H) */ +#endif /* PNGCRUSH_H */ #ifdef PNG_STDIO_SUPPORTED /* @@ -2136,7 +2622,7 @@ io_ptr) != length) { png_error(png_ptr, "Read Error: invalid length returned"); -#if PNG_LIBPNG_VER >= 10700 +#if PNGCRUSH_LIBPNG_VER >= 10700 PNG_ABORT #else PNG_ABORT(); @@ -2185,8 +2671,19 @@ static void pngcrush_warning(png_structp png_ptr, png_const_charp warning_msg) { +#if (PNGCRUSH_LIBPNG_VER >= 10700) + /* don't warn about damaged LZ stream due to bailing */ + if (bail == 0 && !strcmp(warning_msg, "damaged LZ stream")) + return; +#endif + if (verbose >= 0) fprintf(stderr, "pngcrush: %s\n", warning_msg); + else + { + if (show_warnings) + fprintf(stderr, "%s: %s\n", inname, warning_msg); + } return; } @@ -2207,7 +2704,7 @@ return; } -#if PNG_LIBPNG_VER < 10400 +#if PNGCRUSH_LIBPNG_VER < 10400 /* Handle "Too many IDAT's found" error. In libpng-1.4.x this became * a benign error, "Too many IDATs found". This scheme will not work * in libpng-1.5.0 and later. @@ -2222,7 +2719,7 @@ return; } # endif /* PNGCRUSH_H */ -#endif /* PNG_LIBPNG_VER */ +#endif /* PNGCRUSH_LIBPNG_VER */ #endif /* 0 */ { @@ -2580,7 +3077,6 @@ || (!strncmp(name, "zTXt", 4) && (!strncmp(argv[i], "ztxt", 4) || allt)) ) { - global_things_have_changed = 1; /* (caller actually does the removal--by failing to create * copy) */ if (verbose > 0 && last_trial) @@ -2615,22 +3111,100 @@ (100.0 * total_output_length) / total_input_length), (unsigned long)(total_output_length - total_input_length)); } - t_stop = (TIME_T) clock(); - t_misc += (t_stop - t_start); - if (t_stop < t_start) { - t_misc += PNG_UINT_31_MAX; - if (t_stop < 0) - t_misc += PNG_UINT_31_MAX; - } - t_start = t_stop; - fprintf(STDERR, " CPU time decoding %.3f,", - t_decode / (float) CLOCKS_PER_SEC); - fprintf(STDERR, " encoding %.3f,", - t_encode / (float) CLOCKS_PER_SEC); - fprintf(STDERR, " other %.3f,", - t_misc / (float) CLOCKS_PER_SEC); - fprintf(STDERR, " total %.3f sec.\n\n", - (t_misc + t_decode + t_encode) / (float) CLOCKS_PER_SEC); + +#if PNGCRUSH_TIMERS > 0 + for (pc_timer=0;pc_timer < PNGCRUSH_TIMERS; pc_timer++) + { + filter_count[pc_timer]+=pngcrush_timer_get_hits(pc_timer); + t_sec=pngcrush_timer_get_seconds(pc_timer); + t_nsec=pngcrush_timer_get_nanoseconds(pc_timer); + t_filter[pc_timer] = (float)t_nsec/1000000000.; + if (t_sec) + t_filter[pc_timer] += (float)t_sec; + } + +# if PNGCRUSH_TIMERS >= 3 + if (benchmark_iterations > 0 && verbose >= 0) + { + fprintf(STDERR, " CPU time decode %.4f,", t_filter[1]); + fprintf(STDERR, " encode %.4f,", t_filter[2]); + fprintf(STDERR, " other %.4f,", t_filter[3]); + fprintf(STDERR, " total %.4f sec\n", t_filter[0]); + } +#endif + + if (verbose <= 0) + return; + +# if PNGCRUSH_TIMERS > 9 + { + float total_t_filter=0; + float total_filter_count=0; + for (pc_timer = 5; pc_timer < 10; pc_timer++) + { + total_t_filter+=t_filter[pc_timer]; + total_filter_count+=filter_count[pc_timer]; + } + if (total_filter_count > 0) + { + for (pc_timer = 5; pc_timer < 10; pc_timer++) + { + fprintf(STDERR, " filter[%u] defilter time = %15.9f, count = %lu\n", + pc_timer-5, t_filter[pc_timer], + (unsigned long)filter_count[pc_timer]); + } + fprintf(STDERR, " total defilter time = %15.9f, count = %lu\n", + total_t_filter, (unsigned long) total_filter_count); + } + } +# endif +# if PNGCRUSH_TIMERS > 4 + { + if (filter_count[4] > 0) + fprintf(STDERR, " deinterlace time = %15.9f, count = %lu\n", + t_filter[4], (unsigned long)filter_count[4]); + } +# endif +# if PNGCRUSH_USE_CLOCK_GETTIME != 0 +# if PNGCRUSH_TIMERS > 1 + { + fprintf(STDERR, " total decode time = %15.9f, count = %lu\n", + t_filter[1], (unsigned long)filter_count[1]); + } +# endif +# if PNGCRUSH_TIMERS > 10 + { + if (filter_count[10] > 0) + fprintf(STDERR, " filter setup time = %15.9f, count = %lu\n", + t_filter[10], (unsigned long)filter_count[10]); + } +# endif +# if PNGCRUSH_TIMERS > 2 + { + fprintf(STDERR, " total encode time = %15.9f, count = %lu\n", + t_filter[2], (unsigned long)filter_count[2]); + } +# endif +# if PNGCRUSH_TIMERS > 3 + { + fprintf(STDERR, " total misc time = %15.9f, count = %lu\n", + t_filter[3], (unsigned long)filter_count[3]); + } +# endif +# if PNGCRUSH_TIMERS > 0 + { + fprintf(STDERR, " total time = %15.9f, count = %lu\n", + t_filter[0], (unsigned long)filter_count[0]); + } +# endif +# endif +#else +# ifdef PNGCRUSH_TIMERS + fprintf(STDERR, " CPU time defilter = 0.000000\n"); + fprintf(STDERR, " (PNGCRUSH_TIMERS=%d)\n\n", (int)PNGCRUSH_TIMERS); +# endif +#endif + #ifdef PNG_USER_MEM_SUPPORTED if (current_allocation) { memory_infop pinfo = pinformation; @@ -2992,8 +3566,10 @@ int main(int argc, char *argv[]) { + unsigned int bench = 0; png_uint_32 y; - int bit_depth, color_type; + int bit_depth = 0; + int color_type = 0; int num_pass, pass; int num_methods; @@ -3006,13 +3582,14 @@ * : 1 means do not try this method. */ int try_method[MAX_METHODSP1]; + int methods_enabled = 0; + int last_method = MAX_METHODS; int fm[MAX_METHODSP1]; int lv[MAX_METHODSP1]; int zs[MAX_METHODSP1]; int lev, strat, filt; - #ifdef PNG_gAMA_SUPPORTED # ifdef PNG_FIXED_POINT_SUPPORTED png_fixed_point file_gamma = 0; @@ -3023,7 +3600,16 @@ char *cp; int i; - t_start = (TIME_T) clock(); +#if PNGCRUSH_TIMERS >= 0 + for (pc_timer=0;pc_timer< PNGCRUSH_TIMERS; pc_timer++) + { + pngcrush_timer_reset(pc_timer); + pngcrush_timer_min_secs[pc_timer]=0xffffffff; + pngcrush_timer_min_nsec[pc_timer]=0xffffffff; + } + pngcrush_timer_start(PNGCRUSH_TIMER_TOTAL); + pngcrush_timer_start(PNGCRUSH_TIMER_MISC); +#endif if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) { @@ -3050,32 +3636,30 @@ #else if (*cp == '\\' || *cp == '/') progname = ++cp; - if (*cp == '.') - *cp = '\0'; #endif } /* * Definition of methods ("canonical list" is methods 11 and up) */ - for (i = 0; i < MAX_METHODS; i++) + for (i = 0; i <= MAX_METHODS; i++) { try_method[i] = 1; /* 1 means do not try this method */ - fm[i] = 5; lv[i] = 9; zs[i] = 1; /* default: method 136 */ + fm[i] = 6; lv[i] = 9; zs[i] = 1; /* default: method 136 */ } - fm[0] = 0; lv[0] = 0; zs[0] = 0; /* method 0 == uncompressed */ - fm[1] = 0; lv[1] = 4; zs[1] = 0; /* method 1 == method 53 */ - fm[2] = 1; lv[2] = 4; zs[2] = 0; /* method 2 == method 54 */ - lv[3] = 4; /* method 3 == method 64 */ - fm[4] = 0; /* method 4 == method 119 */ - fm[5] = 1; zs[5] = 0; /* method 5 == method 114 */ - zs[6] = 0; /* method 6 == method 118 */ - fm[7] = 0; zs[7] = 0; /* method 7 == method 113 */ - fm[8] = 1; /* method 8 == method 120 */ - lv[9] = 2; zs[9] = 2; /* method 9 == method 16 */ - /* method 10 == method 124 */ + fm[0] = 0; lv[0] = 0; zs[0] = 0; /* method 0 == uncompressed */ + fm[1] = 0; lv[1] = 4; zs[1] = 0; /* method 1 == method 53 */ + fm[2] = 1; lv[2] = 4; zs[2] = 0; /* method 2 == method 54 */ + /* fm[3] = 6;*/ lv[3] = 4;/* zs[3] = 1;*/ /* method 3 == method 161 */ + fm[4] = 0;/* lv[4] = 9; zs[4] = 1;*/ /* method 4 == method 119 */ + fm[5] = 1;/* lv[5] = 9; zs[5] = 0;*/ /* method 5 == method 114 */ + /* fm[6] = 6; lv[6] = 9;*/ zs[6] = 0; /* method 6 == method 157 */ + fm[7] = 0;/* lv[7] = 9;*/ zs[7] = 0; /* method 7 == method 113 */ + fm[8] = 1;/* lv[8] = 9; zs[8] = 1;*/ /* method 8 == method 120 */ + /* fm[9] = 6;*/ lv[9] = 2; zs[9] = 2; /* method 9 == method xxx */ + /* fm[10]= 6; lv[10]= 9; zs[10]= 1;*/ /* method 10 == method 166 */ /* methods 11 through 16 * @@ -3108,7 +3692,7 @@ } #ifdef Z_RLE - /* methods 137 through 148 + /* methods 125 through 136 * * [strategy 3 (Z_RLE) is mostly independent of level; 1-3 and 4-9 are * same] @@ -3129,6 +3713,8 @@ } #endif /* Z_RLE */ + /* methods 137 through 148 (12*1*1 = 12), level 0 */ + for (strat = 0; strat <= 1; strat++) { for (filt = 0; filt <= 5; filt++) @@ -3140,8 +3726,29 @@ } } + /* + * methods 149 through 176 (9*3*1 + 1 = 28), speedy + */ + for (strat = 0; strat <= 3; strat++) + { + for (lev = 1; lev <= 9; lev++) + { + lv[method] = lev; + zs[method] = strat; + fm[method] = 6; + method++; + if (strat == 2) + break; /* HUFFMAN ONLY is independent of level */ + } + } + + num_methods = method; /* GRR */ + /* method 177 */ + fm[method] = 0; lv[method] = 0; zs[method] = 0; /* copy_idat */ + method++; + #define pngcrush_get_long strtol(argv[i],&endptr,10) #define pngcrush_check_long \ @@ -3164,23 +3771,25 @@ { errno=0; + if (!strncmp(argv[i], "--", 2)) + argv[i]++; + if (!strncmp(argv[i], "-", 1)) names++; /* GRR: start of giant else-if block */ - if (!strncmp(argv[i], "-already", 8)) /* obsolete, now disabled */ + + if (!strncmp(argv[i], "-bail", 5)) + bail=0; + + if (!strncmp(argv[i], "-bench", 6)) { names++; BUMP_I; -#if 0 /* disabled */ - crushed_idat_size = (png_uint_32) pngcrush_get_long; + benchmark_iterations = (unsigned int) pngcrush_get_long; pngcrush_check_long; -#endif } - else if (!strncmp(argv[i], "-bail", 5)) - bail=0; - else if (!strncmp(argv[i], "-bkgd", 5) || !strncmp(argv[i], "-bKGD", 5)) { @@ -3196,7 +3805,6 @@ bkgd_blue = (png_uint_16) pngcrush_get_long; pngcrush_check_long; bkgd_index = 0; - global_things_have_changed = 1; } else if (!strncmp(argv[i], "-blacken", 8)) @@ -3220,21 +3828,9 @@ brute_force_strategies[strat] = 0; } - else if (!strncmp(argv[i], "-bit_depth", 10)) - { - names++; - BUMP_I; - /* Reducing bit_depth does not work */ - { - fprintf(STDERR, - "pngcrush: the -bit_depth N option is longer functional.\n"); - exit(1); - } - } - - else if (!strncmp(argv[i], "-cc", 3)) + else if (!strncmp(argv[i], "-check", 6)) { - do_color_count = 1; + check_crc = 1; } else if (!strncmp(argv[i], "-c", 3) || !strncmp(argv[i], "-col", 4)) @@ -3245,15 +3841,6 @@ pngcrush_check_long; } -#ifdef PNG_gAMA_SUPPORTED - else if (!strncmp(argv[i], "-dou", 4)) - { - double_gamma++; - found_gAMA=1; - global_things_have_changed = 1; - } -#endif - else if (!strncmp(argv[i], "-d", 3) || !strncmp(argv[i], "-dir", 4)) { BUMP_I; @@ -3289,7 +3876,7 @@ else if (!strncmp(argv[i], "-force", 6)) { - global_things_have_changed = 1; + force = 1; } else if (!strncmp(argv[i], "-fix", 4)) @@ -3424,8 +4011,8 @@ { names++; BUMP_I; - if (!strncmp(argv[i], "dSIG", 4) - && (!strncmp(argv[i], "dsig", 4) )) + if (!strncmp(argv[i], "-dSIG", 5) + && (!strncmp(argv[i], "-dsig", 5) )) found_any_chunk=1; } @@ -3477,7 +4064,7 @@ BUMP_I; method = pngcrush_get_long; pngcrush_check_long; - if (method > 0 && method <= MAX_METHODS) + if (method >= 1 && method <= MAX_METHODS) { methods_specified = 1; brute_force = 0; @@ -3503,7 +4090,6 @@ else if (!strncmp(argv[i], "-new", 4)) { - global_things_have_changed = 1; /* -force */ make_opaque = 1; /* -reduce */ make_gray = 1; /* -reduce */ make_8_bit = 1; /* -reduce */ @@ -3513,15 +4099,20 @@ else if (!strncmp(argv[i], "-nobail", 7)) bail=1; - else if (!strncmp(argv[i], "-no_cc", 6)) + else if (!strncmp(argv[i], "-nocheck", 8)) { - do_color_count = 0; + check_crc = 0; } else if (!strncmp(argv[i], "-nofilecheck", 5)) { nofilecheck++; } + else if (!strncmp(argv[i], "-noforce", 6)) + { + force = 0; + } + else if (!strncmp(argv[i], "-nolimits", 5)) { @@ -3556,7 +4147,6 @@ else if (!strncmp(argv[i], "-old", 4)) { - global_things_have_changed = 0; /* no -force */ make_opaque = 0; /* no -reduce */ make_gray = 0; /* no -reduce */ make_8_bit = 0; /* no -reduce */ @@ -3568,26 +4158,18 @@ overwrite = 1; } - else if (!strncmp(argv[i], "-premultiply", 5)) - { - premultiply=2; - } - - else if (!strncmp(argv[i], "-plte_len", 9)) - { - names++; - BUMP_I; /* Ignore old plte_len argument */ - reduce_palette = 1; - } else if (!strncmp(argv[i], "-pplt", 3)) - { names++; do_pplt++; BUMP_I; strncpy(pplt_string, argv[i], STR_BUF_SIZE); pplt_string[STR_BUF_SIZE-1] = '\0'; - global_things_have_changed = 1; + } + + else if (!strncmp(argv[i], "-premultiply", 5)) + { + premultiply=2; } else if (!strncmp(argv[i], "-p", 3) || !strncmp(argv[i], "-pau", 4)) @@ -3597,6 +4179,7 @@ else if (!strncmp(argv[i], "-q", 3) || !strncmp(argv[i], "-qui", 4)) { + /* quiet, does not suppress warnings or timing */ verbose = 0; } @@ -3607,6 +4190,7 @@ else if (!strncmp(argv[i], "-reduce", 7)) { + noreduce = 0; make_opaque = 1; make_gray = 1; make_8_bit = 1; @@ -3647,7 +4231,6 @@ #endif pngcrush_check_long; } - global_things_have_changed = 1; } #endif /* PNG_gAMA_SUPPORTED */ @@ -3658,7 +4241,6 @@ BUMP_I; resolution = pngcrush_get_long; pngcrush_check_long; - global_things_have_changed = 1; } #endif @@ -3689,8 +4271,8 @@ remove_chunks = i; names++; BUMP_I; - if (!strncmp(argv[i], "dSIG", 4) - && (!strncmp(argv[i], "dsig", 4))) + if (!strncmp(argv[i], "-dSIG", 5) + && (!strncmp(argv[i], "-dsig", 5))) image_is_immutable=0; } @@ -3699,6 +4281,11 @@ all_chunks_are_safe++; } + else if (!strncmp(argv[i], "-speed", 6)) + { + speed = 1; + } + else if (!strncmp(argv[i], "-srgb", 5) || !strncmp(argv[i], "-sRGB", 5)) { @@ -3713,12 +4300,12 @@ BUMP_I; if (!strncmp(argv[i], "0", 1) || !strncmp(argv[i], "1", 1) || - !strncmp(argv[i], "2", 1) || !strncmp(argv[i], "3", 1)) + !strncmp(argv[i], "2", 1) || + !strncmp(argv[i], "3", 1)) { names++; specified_intent = (int) pngcrush_get_long; pngcrush_check_long; - global_things_have_changed = 1; } else i--; } @@ -3734,7 +4321,6 @@ names++; ster_mode = (int) pngcrush_get_long; pngcrush_check_long; - global_things_have_changed = 1; } else i--; @@ -3742,14 +4328,10 @@ else if (!strncmp(argv[i], "-s", 3) || !strncmp(argv[i], "-sil", 4)) { + /* silent, suppresses warnings, timing, and results */ verbose = -1; } - else if(!strncmp(argv[i], "-try10",6)) - { - try10 = 1; - } - else if (!strncmp(argv[i], "-text", 5) || !strncmp(argv[i], "-tEXt", 5) || #ifdef PNG_iTXt_SUPPORTED @@ -3764,8 +4346,8 @@ i += 2; BUMP_I; i -= 3; - global_things_have_changed = 1; - if (strlen(argv[i + 2]) < 80 && strlen(argv[i + 3]) < 2048 && + if (strlen(argv[i + 2]) < 80 && + strlen(argv[i + 3]) < STR_BUF_SIZE && text_inputs < 10) { #ifdef PNG_iTXt_SUPPORTED @@ -3811,18 +4393,16 @@ BUMP_I; i -= 3; names += 2; - strncpy(&text_lang[text_inputs * 80], argv[++i], - STR_BUF_SIZE); + strncpy(&text_lang[text_inputs * 80], argv[++i], 80); text_lang[text_inputs * 80 + 79] = '\0'; /* libpng-1.0.5j and later */ - strncpy(&text_lang_key[text_inputs * 80], argv[++i], - STR_BUF_SIZE); + strncpy(&text_lang_key[text_inputs * 80], argv[++i], 80); text_lang_key[text_inputs * 80 + 79] = '\0'; } #endif - strncpy(&text_text[text_inputs * 2048], argv[++i], + strncpy(&text_text[text_inputs * STR_BUF_SIZE], argv[++i], STR_BUF_SIZE); - text_text[text_inputs * 2048 + 2047] = '\0'; + text_text[(text_inputs + 1) * STR_BUF_SIZE - 1] = '\0'; text_inputs++; } else { if (text_inputs > 9) @@ -3891,6 +4471,11 @@ } #endif /* tRNS */ + else if(!strncmp(argv[i], "-try10",6)) + { + try10 = 1; + } + else if (!strncmp(argv[i], "-version", 8)) { fprintf(STDERR, " pngcrush "); @@ -3902,6 +4487,7 @@ fprintf(STDERR, "\n Check http://pmt.sf.net/\n"); fprintf(STDERR, " for the most recent version.\n"); verbose = 0; + exit(0); } else if (!strncmp(argv[i], "-v", 3) || !strncmp(argv[i], "-ver", 4)) @@ -3909,6 +4495,12 @@ verbose++; } + else if (!strncmp(argv[i], "-warn", 5)) + { + show_warnings++; + verbose = -1; + } + else if (!strncmp(argv[i], "-w", 3) || !strncmp(argv[i], "-win", 4)) { BUMP_I; @@ -3959,7 +4551,6 @@ } /* GRR: end of giant if-else block */ } /* end of loop over args ============================================ */ - if (verbose > 0 && printed_version_info == 0) print_version_info(); @@ -3998,8 +4589,7 @@ else if (overwrite) { - inname = argv[names]; - PNGCRUSH_UNUSED(outname) + inname = argv[names]; } else @@ -4015,15 +4605,39 @@ } } + first_name = names; + + if (benchmark_iterations) + bench=1; + else + bench=0; + + for (; bench <= benchmark_iterations; bench++) + { + if (benchmark_iterations > 0) + { + P1(" Pngcrush benchmark iteration %d\n",bench); + names = first_name; + } + +#if PNGCRUSH_TIMERS > 0 + for (pc_timer = 0; pc_timer < PNGCRUSH_TIMERS; pc_timer++) + { + pngcrush_timer_reset(pc_timer); + filter_count[pc_timer]=0; + } + pngcrush_timer_start(PNGCRUSH_TIMER_TOTAL); + pngcrush_timer_start(PNGCRUSH_TIMER_MISC); +#endif + for (ia = 0; ia < 256; ia++) trns_array[ia]=255; for (;;) /* loop on input files */ { + methods_enabled = 0; last_trial = 0; - things_have_changed = global_things_have_changed; - if (png_row_filters != NULL) { free(png_row_filters); @@ -4037,8 +4651,14 @@ if (inname == NULL) { - if (verbose > 0) +#if PNGCRUSH_TIMERS > 0 + pngcrush_timer_stop(PNGCRUSH_TIMER_MISC); + pngcrush_timer_stop(PNGCRUSH_TIMER_TOTAL); +#endif + if (verbose >= 0) + { show_result(); + } break; } @@ -4207,10 +4827,6 @@ } number_of_open_files++; -#if 0 /* disabled */ - already_crushed = 0; -#endif - #ifdef PNGCRUSH_LOCO if (new_mng) { @@ -4219,7 +4835,7 @@ if (verbose > 0) mng_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, (png_error_ptr) pngcrush_cexcept_error, - (png_error_ptr) pngcrush_warning, (png_error_ptr) NULL, + (png_error_ptr) pngcrush_warning, (png_voidp) NULL, (png_malloc_ptr) pngcrush_debug_malloc, (png_free_ptr) pngcrush_debug_free); else @@ -4260,13 +4876,26 @@ FCLOSE(fpin); - if (verbose > 0) + if (verbose >= 0 && bench < 2) { - - fprintf(STDERR, " Recompressing IDAT chunks in %s\n", inname); + if (nosave) + { + fprintf(STDERR, " %s:\n", inname); + } + else if (overwrite) + { + fprintf(STDERR, + " Recompressing IDAT chunks in %s\n", inname); + } + else + { + fprintf(STDERR, + " Recompressing IDAT chunks in %s to %s\n", + inname, outname); + } fprintf(STDERR, " Total length of data found in critical chunks " - " =%10lu\n", (unsigned long)idat_length[0]); + " =%10lu\n", (unsigned long)idat_length[0]); fflush(STDERR); } @@ -4278,30 +4907,15 @@ else idat_length[0] = 1; -#if 0 /* disabled */ - if (already_crushed) - { - fprintf(STDERR, " File %s has already been crushed.\n", inname); - } -#endif - if (image_is_immutable) { fprintf(STDERR, " Image %s has a dSIG chunk and is immutable.\n", inname); } -#if 0 /* disabled */ - if (!already_crushed && !image_is_immutable) -#else if (!image_is_immutable) -#endif { - if (do_color_count) - fprintf(STDERR, - " The -cc option is not supported.\n"); - if (force_output_color_type != 8 && force_output_color_type != 0 && force_output_color_type != 2 && @@ -4317,14 +4931,6 @@ output_bit_depth = force_output_bit_depth; - if (!methods_specified || try10 != 0) - { - for (i = 0; i <= DEFAULT_METHODS; i++) - try_method[i] = 0; - - try_method[6] = try10; - } - best_of_three = 1; pngcrush_best_byte_count=0xffffffff; @@ -4423,55 +5029,127 @@ /* Handle specified brute_force options */ if (brute_force_level || brute_force_filter || brute_force_strategy) { - for (method = 1; method < num_methods; method++) + for (method = 1; method < num_methods; method++) + { + int option; + + try_method[method]=1; + if (brute_force_level) { - int option; + for (option = 0; option < 10; option++) + if (option == lv[method]) + try_method[method]=brute_force_levels[option]; + } - try_method[method]=1; - if (brute_force_level) - { - for (option = 0; option < 10; option++) - if (option == lv[method]) - try_method[method]=brute_force_levels[option]; - } + if ((try_method[method] == 0) && brute_force_filter) + { + for (option = 0; option < 6; option++) + if (option == fm[method]) + try_method[method]=brute_force_filters[option]; + } - if ((try_method[method] == 0) && brute_force_filter) - { - for (option = 0; option < 6; option++) - if (option == fm[method]) - try_method[method]=brute_force_filters[option]; - } + if ((try_method[method] == 0) && brute_force_strategy) + { + for (option = 0; option < NUM_STRATEGIES; option++) + if (option == zs[method]) + try_method[method]=brute_force_strategies[option]; + } - if ((try_method[method] == 0) && brute_force_strategy) - { - for (option = 0; option < NUM_STRATEGIES; option++) - if (option == zs[method]) - try_method[method]=brute_force_strategies[option]; - } + if (method && method < 11) + try_method[method] = 1; + } - if (method && method < 11) - try_method[method] = 1; + if (speed) + { + /* Do not try AVG or PAETH */ + for (method = 1; method < num_methods; method++) + { + if (try_method[method] == 0 && (fm[method] == 3 || + fm[method] == 4 || fm[method] == 5)) + try_method[method] = 1; + } } } + if (methods_specified == 0 || try10 != 0) + { + for (i = 0; i <= DEFAULT_METHODS; i++) + try_method[i] = 0; + + try_method[6] = try10; + } + + for (i = 1; i <= MAX_METHODS; i++) + { + methods_enabled += (1 - try_method[i]); + } + P1("%d methods enabled\n",methods_enabled); +/* Skip trial 0 when a single method was specified and -reduce was not */ + if (methods_specified != 0 && noreduce != 0) + { + if (methods_enabled == 1) + { + try_method[0] = 1; + make_opaque = 0; + make_gray = 0; + make_8_bit = 0; + reduce_palette = 0; + } + } + + last_method = 0; + for (i = 1; i <= MAX_METHODS; i++) + { + if (try_method[i] == 0) + last_method = i; + } + + if (methods_enabled > 1) + last_method++; + + P1(" pngcrush: methods = %d\n",methods_enabled); + P1(" pngcrush: last_method = %d\n",last_method); + + if (methods_enabled == 1 && last_method == 176) + copy_idat = 1; + + best_of_three = 1; + +#ifndef __riscos + { + /* COVERITY complains about TOCTOU when inname is used later */ + struct stat stat_buf; + stat(inname, &stat_buf); + input_length = (unsigned long) stat_buf.st_size; + } +#else + input_length = (unsigned long) filesize(inname); +#endif + /* //////////////////////////////////////////////////////////////////// //////////////// //////////////////// //////////////// START OF MAIN LOOP OVER METHODS //////////////////// //////////////// //////////////////// //////////////////////////////////////////////////////////////////// */ - /* MAX_METHODS is 150 */ + /* MAX_METHODS is 177 */ P1("\n\nENTERING MAIN LOOP OVER %d METHODS\n", MAX_METHODS); - for (trial = 0; trial <= MAX_METHODS; trial++) + for (trial = 0; trial <= last_method; trial++) { - if (nosave || trial == MAX_METHODS) + if (nosave || trial == last_method) last_trial = 1; if (verbose > 1) - fprintf(STDERR, - "pngcrush: trial = %d\n",trial); + fprintf(STDERR, "pngcrush: trial = %d\n",trial); pngcrush_write_byte_count=0; +#ifdef PNGCRUSH_H +# if ZLIB_VERNUM > 0x1240 + if (last_trial == 0) + pngcrush_write_byte_count=6; /* zlib header that isn't written */ +# endif +#endif + found_IDAT = 0; if (trial != 0) @@ -4479,31 +5157,46 @@ /* this part of if-block is for final write-the-best-file iteration */ - if (trial == MAX_METHODS) + if (trial == last_method) { png_uint_32 best_length; - int j; - /* check lengths */ - best = 0; /* i.e., input file */ - best_length = (png_uint_32) 0xffffffff; - for (j = things_have_changed; j < MAX_METHODS; j++) + if (methods_enabled == 1) { - if (best == 0 && best_length == idat_length[j]) - { - /* If no change, report the first match */ - best = j; - } - if (best_length > idat_length[j]) - { - best_length = idat_length[j]; - best = j; - } + best = trial; + best_length = idat_length[trial]; + } + else + { + int j; + + /* check lengths */ + best = 0; /* i.e., input file */ + best_length = (png_uint_32) 0xffffffff; + for (j = 0; j <= last_method; j++) + { + if (best == 0 && best_length == idat_length[j]) + { + /* If no change, report the first match */ + best = j; + } + if ((force == 0 || j != 0) && + best_length > idat_length[j]) + { + best_length = idat_length[j]; + best = j; + } + if (j > 148 && j < 176 && best_length == idat_length[j]) + { + /* break ties in favor of method 6 */ + best = j; + } + } } if (image_is_immutable || (idat_length[best] == idat_length[0] && - things_have_changed == 0 && nosave == 0)) + force == 0 && nosave == 0)) { /* just copy input to output */ @@ -4528,8 +5221,7 @@ } number_of_open_files++; - P2("copying input to output... tc=%d ...", - things_have_changed); + P2("copying input to output..."); for (;;) { @@ -4564,7 +5256,7 @@ z_strategy = Z_DEFAULT_STRATEGY; } - else /* Trial < MAX_METHODS */ + else /* Trial < last_method */ { if (trial > 2 && trial < 5 && idat_length[trial - 1] < idat_length[best_of_three]) @@ -4682,7 +5374,8 @@ #ifdef PNG_USER_MEM_SUPPORTED if (verbose > 0) read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, - (png_voidp) NULL, (png_error_ptr) pngcrush_cexcept_error, + (png_voidp) NULL, + (png_error_ptr) pngcrush_cexcept_error, (png_error_ptr) pngcrush_warning, (png_voidp) NULL, (png_malloc_ptr) pngcrush_debug_malloc, @@ -4690,13 +5383,14 @@ else #endif /* PNG_USER_MEM_SUPPORTED */ read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, - (png_voidp) NULL, (png_error_ptr) pngcrush_cexcept_error, + (png_voidp) NULL, + (png_error_ptr) pngcrush_cexcept_error, (png_error_ptr) pngcrush_warning); if (read_ptr == NULL) Throw "pngcrush could not create read_ptr"; #ifdef PNG_BENIGN_ERRORS_SUPPORTED -# if PNG_LIBPNG_VER >= 10400 +# if PNGCRUSH_LIBPNG_VER >= 10400 /* Allow certain errors in the input file to be handled * as warnings. */ @@ -4707,11 +5401,11 @@ #ifdef PNG_SET_USER_LIMITS_SUPPORTED if (no_limits == 0) { -# if PNG_LIBPNG_VER >= 10400 +# if PNGCRUSH_LIBPNG_VER >= 10400 png_set_user_limits(read_ptr, 500000L, 500000L); png_set_chunk_cache_max(read_ptr, 500); # endif -# if PNG_LIBPNG_VER >= 10401 +# if PNGCRUSH_LIBPNG_VER >= 10401 png_set_chunk_malloc_max(read_ptr, 2000000L); # endif } @@ -4720,9 +5414,9 @@ #if defined(PNG_MAXIMUM_INFLATE_WINDOW) && defined(PNG_OPTION_ON) if (salvage) { + P1(" Setting MAXIMUM_INFLATE_WINDOW\n"); png_set_option(read_ptr, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON); - printf(" Setting MAXIMUM_INFLATE_WINDOW\n"); } #endif @@ -4763,8 +5457,9 @@ write_ptr = png_create_write_struct_2( PNG_LIBPNG_VER_STRING, (png_voidp) NULL, - (png_error_ptr) pngcrush_cexcept_error, - (png_error_ptr) NULL, (png_voidp) NULL, + (png_error_ptr) pngcrush_cexcept_error, + (png_error_ptr) pngcrush_warning, + (png_voidp) NULL, (png_malloc_ptr) pngcrush_debug_malloc, (png_free_ptr) pngcrush_debug_free); else @@ -4819,15 +5514,31 @@ pngcrush_pause(); #ifdef PNG_CRC_QUIET_USE - /* We don't need to check CRC's because they were already - checked in the pngcrush_measure_idat function */ - png_set_crc_action(read_ptr, PNG_CRC_QUIET_USE, - PNG_CRC_QUIET_USE); + if (check_crc == 0) + { + /* We don't need to check IDAT CRC's and ADLER32 because + * they were already checked in the pngcrush_measure_idat + * function + */ + png_set_option(read_ptr, PNG_IGNORE_ADLER32, + PNG_OPTION_ON); + png_set_crc_action(read_ptr, PNG_CRC_QUIET_USE, + PNG_CRC_QUIET_USE); + } +#endif +#ifndef PNGCRUSH_CHECK_ADLER32 +# ifdef PNG_IGNORE_ADLER32 if (last_trial == 0) - /* Only calculate CRC while writing the final output */ - png_set_crc_action(write_ptr, PNG_CRC_QUIET_USE, - PNG_CRC_QUIET_USE); + { + /* During trials other than the final output, avoid + * calculating CRC and ADLER32 checksums (just write + * a DEFLATE datastream) + */ + png_set_option(write_ptr, PNG_IGNORE_ADLER32, + PNG_OPTION_ON); + } +# endif #endif #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED @@ -4884,6 +5595,7 @@ png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_bytep) NULL, 0); + printf("while saving, all_chunks_are_safe=\n"); if (save_apng_chunks == 0) { png_set_keep_unknown_chunks(write_ptr, @@ -5008,8 +5720,8 @@ #endif /* PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED */ } /* last trial */ -/* TO DO: Remove this? We already did this in measure_idats */ - P1( "Reading signature bytes\n"); +/* To do: Remove this? We already did this in measure_idats */ + P1(" Reading signature bytes\n"); { #ifdef PNGCRUSH_LOCO png_byte mng_signature[8] = @@ -5066,7 +5778,7 @@ png_error(read_ptr, "Premultiplied alpha is not supported"); #endif - P1( "Reading info struct\n"); + P1( " Reading info struct\n"); png_read_info(read_ptr, read_info_ptr); if (trial != 0) @@ -5300,7 +6012,7 @@ if (trial > 0) { - /* TO DO: have we got the right plte_len now? */ + /* To do: have we got the right plte_len now? */ if (plte_len > 0 && output_color_type == 3 && force_output_bit_depth == 0) { @@ -5392,8 +6104,6 @@ } } else filter_method = 0; - if (input_format != output_format) - things_have_changed = 1; #endif png_set_IHDR(write_ptr, write_info_ptr, width, @@ -5401,10 +6111,6 @@ output_color_type, interlace_method, compression_method, filter_method); - if (output_color_type != input_color_type || - output_bit_depth != input_bit_depth) - things_have_changed = 1; - } /* IHDR */ } @@ -5516,7 +6222,6 @@ { if (last_trial) { - things_have_changed = 1; if (verbose > 0) fprintf(STDERR, " Inserting gAMA chunk with " #ifdef PNG_FIXED_POINT_SUPPORTED @@ -5572,7 +6277,6 @@ { if (last_trial) { - things_have_changed = 1; if (verbose > 0) fprintf(STDERR, " Inserting gAMA chunk with " #ifdef PNG_FIXED_POINT_SUPPORTED @@ -5618,7 +6322,6 @@ if (file_gamma >= 0.45000 && file_gamma <= 0.46000) # endif { - things_have_changed = 1; if (verbose > 0 && last_trial) fprintf(STDERR, " Inserting sRGB chunk with intent=%d\n", @@ -5888,8 +6591,6 @@ P0(" Adding a tRNS chunk\n"); png_set_tRNS(write_ptr, write_info_ptr, trns_array, num_trans, trans_values); - - things_have_changed = 1; } else { @@ -6046,8 +6747,6 @@ if (keep_chunk("sPLT", argv)) png_set_sPLT(write_ptr, write_info_ptr, entries, num_entries); - png_free_data(read_ptr, read_info_ptr, - PNG_FREE_SPLT, num_entries); } } #endif @@ -6149,7 +6848,8 @@ added_text[0].lang_key = &text_lang_key[ntext * 80]; #endif - added_text[0].text = &text_text[ntext * 2048]; + added_text[0].text = + &text_text[ntext * STR_BUF_SIZE]; added_text[0].compression = text_compression[ntext]; png_set_text(write_ptr, write_info_ptr, @@ -6336,7 +7036,10 @@ else if (filter_type == 4) png_set_filter(write_ptr, 0, PNG_FILTER_PAETH); else if (filter_type == 5) - png_set_filter(write_ptr, 0, PNG_ALL_FILTERS); + png_set_filter(write_ptr, 0, PNG_ALL_FILTERS); + else if (filter_type == 6) /* speedy */ + png_set_filter(write_ptr, 0, PNG_FILTER_NONE | + PNG_FILTER_SUB | PNG_FILTER_UP); else png_set_filter(write_ptr, 0, PNG_FILTER_NONE); @@ -6350,9 +7053,8 @@ if (outname[strlen(outname) - 3] == 'p') pngcrush_warning(read_ptr, " Writing a MNG file with a .png extension"); - pngcrush_default_write_data(write_ptr, - &mng_signature[0], - (png_size_t) 8); + pngcrush_write_png(write_ptr, &mng_signature[0], + (png_size_t) 8); png_set_sig_bytes(write_ptr, 8); /* Write a MHDR chunk */ @@ -6387,6 +7089,9 @@ } P1( "\nWriting info struct\n"); + if (copy_idat == 0) + { + #if 0 /* doesn't work; compression level has to be the same as in IDAT */ /* if zTXt other compressed chunk */ png_set_compression_level(write_ptr, 9); @@ -6422,6 +7127,10 @@ png_uint_32 rowbytes; png_uint_32 h = height; + /* FIX THIS, does not work with libpng-1.7.0 + * because info_ptr->bit_depth has not been + * updated yet. + */ rowbytes = png_get_rowbytes(read_ptr, read_info_ptr); #ifndef PNGCRUSH_H /* We must do this because we could not call @@ -6443,7 +7152,7 @@ */ png_uint_32 w = width; unsigned int pd = channels * output_bit_depth; -#if (PNG_LIBPNG_VER < 10400) +#if (PNGCRUSH_LIBPNG_VER < 10400) png_size_t cb_base; #else png_alloc_size_t cb_base; @@ -6523,8 +7232,18 @@ } png_set_compression_level(write_ptr, zlib_level); + } /* copy_idat */ + png_write_info(write_ptr, write_info_ptr); P1( "\nWrote info struct\n"); + + if (copy_idat == 1) + { + /* No recompress, just copy IDATs. */ + png_set_compression_buffer_size(write_ptr, + MAX_IDAT_SIZE); + } + #ifdef PNG_WRITE_PACK_SUPPORTED if (output_bit_depth < 8) { @@ -6614,7 +7333,7 @@ * If it's not enough we can drop the "average" filter and * we can reduce the zlib_window for writing. We can't * change the input zlib_window because the input file - * might have used the full 32K sliding window. (TO DO) + * might have used the full 32K sliding window. (To do) */ } @@ -6636,15 +7355,8 @@ if (nosave == 0) png_set_interlace_handling(write_ptr); - t_stop = (TIME_T) clock(); - t_misc += (t_stop - t_start); - if (t_stop < t_start) - { - t_misc += PNG_UINT_31_MAX; - if (t_stop < 0) - t_misc += PNG_UINT_31_MAX; - } - t_start = t_stop; +/* START_STOP */ + for (pass = 0; pass < num_pass; pass++) { #ifdef PNGCRUSH_MULTIPLE_ROWS @@ -6658,25 +7370,39 @@ for (y = 0; y < height; y++) #endif { +#if PNGCRUSH_TIMERS > 0 + if (verbose >= 0) + { + pngcrush_timer_stop(PNGCRUSH_TIMER_MISC); + pngcrush_timer_start(PNGCRUSH_TIMER_DECODE); + } +#endif #ifdef PNGCRUSH_MULTIPLE_ROWS if (y + num_rows > height) num_rows = height - y; +# ifdef BLOCKY_DEINTERLACE + png_read_rows(read_ptr, (png_bytepp) NULL, + row_pointers, num_rows); +# else /* SPARKLE */ png_read_rows(read_ptr, row_pointers, (png_bytepp) NULL, num_rows); +# endif #else +# ifdef BLOCKY_DEINTERLACE png_read_row(read_ptr, row_buf, (png_bytep) NULL); +# else /* SPARKLE */ + png_read_row(read_ptr, (png_bytep) NULL, row_buf); +# endif #endif if (nosave == 0) { - t_stop = (TIME_T) clock(); - t_decode += (t_stop - t_start); - if (t_stop < t_start) - { - t_decode += PNG_UINT_31_MAX; - if (t_stop < 0) - t_decode += PNG_UINT_31_MAX; - } - t_start = t_stop; +#if PNGCRUSH_TIMERS > 0 + if (verbose >= 0) + { + pngcrush_timer_stop(PNGCRUSH_TIMER_DECODE); + pngcrush_timer_start(PNGCRUSH_TIMER_ENCODE); + } +#endif #ifdef PNGCRUSH_MULTIPLE_ROWS /* To do: zero the padding bits */ png_write_rows(write_ptr, row_pointers, @@ -6685,24 +7411,28 @@ /* To do: zero the padding bits */ png_write_row(write_ptr, row_buf); #endif - t_stop = (TIME_T) clock(); - t_encode += (t_stop - t_start); - if (t_stop < t_start) - { - t_encode += PNG_UINT_31_MAX; - if (t_stop < 0) - t_encode += PNG_UINT_31_MAX; - } - t_start = t_stop; } +#if PNGCRUSH_TIMERS > 0 + if (verbose >= 0) + { + if (nosave == 0) + pngcrush_timer_stop(PNGCRUSH_TIMER_ENCODE); + else + pngcrush_timer_stop(PNGCRUSH_TIMER_DECODE); + pngcrush_timer_start(PNGCRUSH_TIMER_MISC); + } +#endif /* Bail if byte count exceeds best so far */ - if (bail == 0 && trial != MAX_METHODS && + if (bail == 0 && trial != last_method && pngcrush_write_byte_count > pngcrush_best_byte_count) + { + png_write_flush(write_ptr); break; + } } P2( "End interlace pass %d\n\n", pass); - if (bail == 0 && trial != MAX_METHODS && + if (bail == 0 && trial != last_method && pngcrush_write_byte_count > pngcrush_best_byte_count) break; @@ -6749,19 +7479,6 @@ } } - if (nosave) - { - t_stop = (TIME_T) clock(); - t_decode += (t_stop - t_start); - if (t_stop < t_start) - { - t_decode += PNG_UINT_31_MAX; - if (t_stop < 0) - t_decode += PNG_UINT_31_MAX; - } - t_start = t_stop; - } - #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) && \ defined(PNG_FLOATING_POINT_SUPPORTED) if ((color_type == 2 || color_type == 6 || color_type == 3) @@ -6792,11 +7509,11 @@ #endif /* PNG_FREE_UNKN */ /* { GRR: added for %-navigation (2) */ - if (!(bail == 0 && trial != MAX_METHODS && + if (!(bail == 0 && trial != last_method && pngcrush_write_byte_count > pngcrush_best_byte_count)) { - P1( "Reading and writing end_info data\n"); + P1(" Reading and writing end_info data\n"); png_read_end(read_ptr, end_info_ptr); /* Handle ancillary chunks */ @@ -6805,12 +7522,14 @@ #if (defined(PNG_READ_tEXt_SUPPORTED) && defined(PNG_WRITE_tEXt_SUPPORTED)) \ || (defined(PNG_READ_iTXt_SUPPORTED) && defined(PNG_WRITE_iTXt_SUPPORTED)) \ || (defined(PNG_READ_zTXt_SUPPORTED) && defined(PNG_WRITE_zTXt_SUPPORTED)) + + P1( "Check for iTXt/tEXt/zTXt chunks after IDAT\n"); { png_textp text_ptr; int num_text = 0; - if (png_get_text - (read_ptr, end_info_ptr, &text_ptr, &num_text) > 0 + if (png_get_text (read_ptr, + end_info_ptr, &text_ptr, &num_text) > 0 || text_inputs) { int ntext; @@ -6845,7 +7564,8 @@ fprintf(STDERR, "\n"); } } - if (nosave) + + if (last_trial) { if (num_text > 0) { @@ -6854,7 +7574,7 @@ int num_to_write = num_text; for (ntext = 0; ntext < num_text; ntext++) { - if (last_trial) + if (verbose > 1) P2("Text chunk after IDAT, " "compression=%d\n", text_ptr[ntext].compression); @@ -6896,8 +7616,11 @@ text_ptr, num_text); } } + + P1( "text_inputs=%d\n",text_inputs); for (ntext = 0; ntext < text_inputs; ntext++) { + P1( " ntext=%d\n",ntext); if (text_where[ntext] == 2) { png_textp added_text; @@ -6914,7 +7637,7 @@ &text_lang_key[ntext * 80]; #endif added_text[0].text = - &text_text[ntext * 2048]; + &text_text[ntext * STR_BUF_SIZE]; added_text[0].compression = text_compression[ntext]; png_set_text(write_ptr, write_end_info_ptr, @@ -7080,7 +7803,7 @@ &end_info_ptr); if (verbose > 1) fprintf(stderr, "returning after cleanup\n"); - trial = MAX_METHODS + 1; + trial = last_method + 1; } read_ptr = NULL; @@ -7103,7 +7826,7 @@ if (pngcrush_write_byte_count < pngcrush_best_byte_count) pngcrush_best_byte_count = pngcrush_write_byte_count; - if (verbose > 0 && trial != MAX_METHODS) + if (verbose > 0 && trial != last_method) { if (bail == 0 && pngcrush_write_byte_count > pngcrush_best_byte_count) @@ -7125,7 +7848,7 @@ } /* end of trial-loop */ - P1("\n\nFINISHED MAIN LOOP OVER %d METHODS\n\n\n", MAX_METHODS); + P1("\n\nFINISHED MAIN LOOP OVER %d METHODS\n\n\n", last_method); /* //////////////////////////////////////////////////////////////////// ////////////////// //////////////////// @@ -7165,13 +7888,12 @@ if (last_trial && nosave == 0) { - png_uint_32 input_length, output_length; + png_uint_32 output_length; #ifndef __riscos struct stat stat_buf; struct utimbuf utim; stat(inname, &stat_buf); - input_length = (unsigned long) stat_buf.st_size; utim.actime = stat_buf.st_atime; utim.modtime = stat_buf.st_mtime; stat(outname, &stat_buf); @@ -7182,19 +7904,16 @@ utime(outname, &utim); } #else - input_length = (unsigned long) filesize(inname); output_length = (unsigned long) filesize(outname); #endif - if (verbose > 0) + if (verbose >= 0 && bench < 2) { total_input_length += input_length + output_length; if (best == 0) { fprintf(STDERR, - " Best pngcrush method = 0 (settings undetermined)\n" - " for output to %s\n", - outname); + " Best pngcrush method = 0 (settings undetermined)\n"); } #if 0 /* disabled */ @@ -7205,11 +7924,13 @@ { fprintf(STDERR, " Best pngcrush method = %3d " - "(ws %d fm %d zl %d zs %d) =%10lu\n for output to %s\n", + "(ws %d fm %d zl %d zs %d) =%10lu\n", best, compression_window, fm[best], lv[best], zs[best], - (unsigned long)idat_length[best], outname); + (unsigned long)idat_length[best]); } + if (verbose > 0) + { if (idat_length[0] == idat_length[best]) fprintf(STDERR, " (no critical chunk change)\n"); else if (idat_length[0] > idat_length[best]) @@ -7231,18 +7952,25 @@ fprintf(STDERR, " Number of open files=%d\n", number_of_open_files); + } } } - if (pngcrush_mode == DEFAULT_MODE) + if (pngcrush_mode == DEFAULT_MODE || pngcrush_mode == OVERWRITE_MODE) { if (png_row_filters != NULL) { free(png_row_filters); png_row_filters = NULL; } - if (verbose > 0) +#if PNGCRUSH_TIMERS > 0 + pngcrush_timer_stop(PNGCRUSH_TIMER_MISC); + pngcrush_timer_stop(PNGCRUSH_TIMER_TOTAL); +#endif + if (verbose >= 0) + { show_result(); + } #ifdef PNG_iCCP_SUPPORTED if (iccp_length) { @@ -7251,12 +7979,123 @@ iccp_length = 0; } #endif - if (pngcrush_must_exit) - exit(0); - return 0; + break; } } /* end of loop on input files */ +#if PNGCRUSH_TIMERS > 0 + for (pc_timer = 0; pc_timer < PNGCRUSH_TIMERS; pc_timer++) + { + unsigned long ts,tn; + + ts=pngcrush_timer_get_seconds(pc_timer); + tn=pngcrush_timer_get_nanoseconds(pc_timer); + if (ts < pngcrush_timer_min_secs[pc_timer]) + { + pngcrush_timer_min_secs[pc_timer] = ts; + pngcrush_timer_min_nsec[pc_timer] = tn; + } + else + { + if (tn < pngcrush_timer_min_nsec[pc_timer]) + pngcrush_timer_min_nsec[pc_timer] = tn; + } + + pngcrush_timer_reset(pc_timer); + } +#endif + + } /* end of benchmark_iteration loop */ + if (verbose >= 0) + { +#if (PNGCRUSH_TIMERS > 0) + for (pc_timer=0;pc_timer < PNGCRUSH_TIMERS; pc_timer++) + { + filter_count[pc_timer]+=pngcrush_timer_get_hits(pc_timer); + t_sec=pngcrush_timer_min_secs[pc_timer]; + t_nsec=pngcrush_timer_min_nsec[pc_timer]; + t_filter[pc_timer] = (float)t_nsec/1000000000.; + if (t_sec) + t_filter[pc_timer] += (float)t_sec; + } + +# if PNGCRUSH_TIMERS >= 3 + fprintf(STDERR, "CPU time decode %.6f,", t_filter[1]); + fprintf(STDERR, " encode %.6f,", t_filter[2]); + fprintf(STDERR, " other %.6f,", t_filter[3]); + fprintf(STDERR, " total %.6f sec\n", t_filter[0]); +# endif + +# if PNGCRUSH_USE_CLOCK_GETTIME != 0 + if (benchmark_iterations > 0) + { +# if PNGCRUSH_TIMERS > 9 + { + float total_t_filter=0; + float total_filter_count=0; + for (pc_timer = 5; pc_timer < 10; pc_timer++) + { + total_t_filter+=t_filter[pc_timer]; + total_filter_count+=filter_count[pc_timer]; + } + if (total_filter_count > 0) + { + for (pc_timer = 5; pc_timer < 10; pc_timer++) + { + fprintf(STDERR, " filter[%u] defilter time = %15.9f, count = %lu\n", + pc_timer-5, t_filter[pc_timer], + (unsigned long)filter_count[pc_timer]); + } + fprintf(STDERR, " total defilter time = %15.9f, count = %lu\n", + total_t_filter, (unsigned long) total_filter_count); + } + } +# endif +# if PNGCRUSH_TIMERS > 4 + { + if (filter_count[4] > 0) + fprintf(STDERR, " deinterlace time = %15.9f, count = %lu\n", + t_filter[4], (unsigned long)filter_count[4]); + } +# endif +# if PNGCRUSH_TIMERS > 1 + { + fprintf(STDERR, " total decode time = %15.9f, count = %lu\n", + t_filter[1], (unsigned long)filter_count[1]); + } +# endif +# if PNGCRUSH_TIMERS > 10 + { + if (filter_count[10] > 0) + fprintf(STDERR, " filter setup time = %15.9f, count = %lu\n", + t_filter[10], (unsigned long)filter_count[10]); + } +# endif +# if PNGCRUSH_TIMERS > 2 + { + fprintf(STDERR, " total encode time = %15.9f, count = %lu\n", + t_filter[2], (unsigned long)filter_count[2]); + } +# endif +# if PNGCRUSH_TIMERS > 3 + { + fprintf(STDERR, " total misc time = %15.9f, count = %lu\n", + t_filter[3], (unsigned long)filter_count[3]); + } +# endif +# if PNGCRUSH_TIMERS > 0 + { + fprintf(STDERR, " total time = %15.9f, count = %lu\n", + t_filter[0], (unsigned long)filter_count[0]); + } +# endif + } +#endif +#endif + } + + if (pngcrush_must_exit) + exit(0); return 0; /* just in case */ } /* end of main() */ @@ -7352,7 +8191,7 @@ pngcrush_default_read_data(png_ptr, buff, 4); - /* TO DO: combine with checking for valid PNG chunk_name, below */ + /* To do: combine with checking for valid PNG chunk_name, below */ /* Check for valid chunk name [A-Za-z][A-Za-z][A-Z][A-Za-z] */ if (!(((buff[0] >= PNGCRUSH_a && buff[0] <= PNGCRUSH_z) || (buff[0] >= PNGCRUSH_A && buff[0] <= PNGCRUSH_Z)) && @@ -7377,8 +8216,8 @@ buff[0],buff[1],buff[2],buff[3]); } else - if (verbose > 0) - printf("Reading %c%c%c%c chunk.\n",buff[0],buff[1],buff[2], + if (verbose > 1) + printf(" Reading %c%c%c%c chunk.\n",buff[0],buff[1],buff[2], buff[3]); pngcrush_default_read_data(png_ptr, buff, length); @@ -7433,9 +8272,6 @@ if (salvage) { -#ifdef PNG_CRC_WARN_USE - png_set_crc_action(png_ptr, PNG_CRC_WARN_USE, PNG_CRC_WARN_USE); -#endif #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR /* The warning here about deprecated access to png_ptr->zstream * is unavoidable. This will not work with libpng-1.5.x and later. @@ -7471,8 +8307,8 @@ pngcrush_default_read_data(png_ptr, chunk_length, 4); length = pngcrush_get_uint_31(png_ptr,chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, chunk_name, 4); + pngcrush_reset_crc(png_ptr); + pngcrush_crc_read(png_ptr, chunk_name, 4); chunk_name[4]='\0'; /* Check for valid chunk name [A-Za-z][A-Za-z][A-Z][A-Za-z] */ @@ -7503,8 +8339,8 @@ chunk_name[0],chunk_name[1],chunk_name[2],chunk_name[3]); } else - if (verbose > 0) - printf("Reading %c%c%c%c chunk.\n", + if (verbose > 1) + printf(" Reading %c%c%c%c chunk.\n", chunk_name[0],chunk_name[1],chunk_name[2],chunk_name[3]); if (new_mng) @@ -7539,7 +8375,7 @@ bb=(png_byte*)png_malloc(mng_ptr, length+1); malloced_length=length+1; } - png_crc_read(png_ptr, bb, length); + pngcrush_crc_read(png_ptr, bb, length); bb[length]='\0'; png_write_chunk(mng_ptr, chunk_name, bb, (png_size_t) length); @@ -7636,8 +8472,8 @@ if (verbose > 1) { chunk_name[4] = '\0'; - fprintf(STDERR, "Reading %s chunk, length = %lu.\n", chunk_name, - (unsigned long)length); + fprintf(STDERR, " Reading %s chunk, length = %lu.\n", + chunk_name, (unsigned long)length); } if (pngcrush_get_uint_32(chunk_name) == PNG_UINT_CgBI) @@ -7665,7 +8501,7 @@ #endif { /* get the color type */ - png_crc_read(png_ptr, buff, 13); + pngcrush_crc_read(png_ptr, buff, 13); length -= 13; input_color_type = buff[9]; } @@ -7699,7 +8535,7 @@ /* Set found_color_bKGD if the components are different, * so we do not do reduction of color-type from color to gray */ - png_crc_read(png_ptr, buff, 6); + pngcrush_crc_read(png_ptr, buff, 6); length -= 6; if ((buff[0] != buff[2]) && (buff[0] != buff[4]) && (buff[1] != buff[3]) && (buff[0] != buff[5])) @@ -7743,7 +8579,7 @@ */ if (length == 2615) { - png_crc_read(png_ptr, buff, 22); + pngcrush_crc_read(png_ptr, buff, 22); length -= 22; buff[23] = 0; if (!strncmp((png_const_charp) buff, "Photoshop ICC profile", @@ -7780,7 +8616,7 @@ if (length <= 4) { int i; - png_crc_read(png_ptr, buff, length); + pngcrush_crc_read(png_ptr, buff, length); found_sBIT_max=0; for (i=length; i; i--) if (buff[i] > found_sBIT_max) @@ -7805,7 +8641,7 @@ found_tRNS=1; #endif /* PNG_tRNS_SUPPORTED */ - png_crc_finish(png_ptr, length); + pngcrush_crc_finish(png_ptr, length); #ifdef PNGCRUSH_LOCO # ifdef PNG_UINT_MEND @@ -7876,40 +8712,56 @@ case 0x1280: zlib_copyright="-2013"; break; + case 0x1290: + case 0x12a0: + case 0x12b0: + zlib_copyright="-2017"; + break; default: zlib_copyright=" (or later)"; break; } #endif +#ifdef PNGCRUSH_H +# define BUNDLED_LIB "bundled" +#else +# define BUNDLED_LIB "system" +#endif + fprintf(STDERR, "\n" - " | pngcrush %s\n" + " | pngcrush-%s\n" /* If you have modified this source, you may insert additional notices * immediately after this sentence: */ - " | Copyright (C) 1998-2002, 2006-2015 Glenn Randers-Pehrson\n" - " | Portions copyright (C) 2005 Greg Roelofs\n" + " | Copyright (C) 1998-2002, 2006-2017 Glenn Randers-Pehrson\n" + " | Portions Copyright (C) 2005 Greg Roelofs\n" " | This is a free, open-source program. Permission is irrevocably\n" " | granted to everyone to use this version of pngcrush without\n" " | payment of any fee.\n" " | Executable name is %s\n" - " | It was built with libpng version %s, and is\n" - " | running with %s" - " | Copyright (C) 1998-2004, 2006-2015 Glenn Randers-Pehrson,\n" + " | It was built with %s libpng-%s\n" + " | and is running with %s libpng-%s\n" + " | Copyright (C) 1998-2004, 2006-2017 Glenn Randers-Pehrson,\n" " | Copyright (C) 1996, 1997 Andreas Dilger,\n" " | Copyright (C) 1995, Guy Eric Schalnat, Group 42 Inc.,\n" - " | and zlib version %s, Copyright (C) 1995%s,\n" - " | Jean-loup Gailly and Mark Adler.\n", - PNGCRUSH_VERSION, progname, PNG_LIBPNG_VER_STRING, - png_get_header_version(NULL), ZLIB_VERSION,zlib_copyright); - + " | and %s zlib-%s, Copyright (C) 1995%s,\n" + " | Jean-loup Gailly and Mark Adler", + PNGCRUSH_VERSION, progname, + BUNDLED_LIB,PNG_LIBPNG_VER_STRING, + BUNDLED_LIB,png_get_header_ver(NULL), + BUNDLED_LIB,ZLIB_VERSION, + zlib_copyright); + +#if PNGCRUSH_TIMERS > 0 + fprintf(STDERR, + ",\n | and using \"%s\".\n",PNGCRUSH_USING_CLOCK); +#else + fprintf(STDERR,"\n"); +#endif #if defined(__GNUC__) fprintf(STDERR, " | It was compiled with gcc version %s", __VERSION__); -# if defined(PNG_USE_PNGGCCRD) - fprintf(STDERR, - " and gas version %s", GAS_VERSION); -# endif # if defined(__DJGPP__) fprintf(STDERR, "\n" @@ -7918,10 +8770,23 @@ " | Copyright (C) 1996, Matthias Grimrath.\n", __DJGPP__, __DJGPP_MINOR__); # else - fprintf(STDERR, ".\n"); + fprintf(STDERR, "\n"); # endif #endif +#if PNG_ARM_NEON_OPT > 0 + fprintf(STDERR," | using ARM_NEON optimizations.\n"); +#endif +#if PNG_MIPS_MSA_OPT > 0 + fprintf(STDERR," | using MIPS_MSA optimizations.\n"); +#endif +#if PNG_POWERPC_VSX_OPT > 0 + fprintf(STDERR," | using POWERPC_VSX optimizations.\n"); +#endif +#if PNG_INTEL_SSE_OPT > 0 + fprintf(STDERR," | using INTEL_SSE optimizations.\n"); +#endif + fprintf(STDERR, "\n"); } @@ -7933,8 +8798,8 @@ "", "If you have modified this source, you may insert additional notices", "immediately after this sentence.", - "Copyright (C) 1998-2002, 2006-2015 Glenn Randers-Pehrson", - "Portions copyright (C) 2005 Greg Roelofs", + "Copyright (C) 1998-2002, 2006-2017 Glenn Randers-Pehrson", + "Portions Copyright (C) 2005 Greg Roelofs", "", "DISCLAIMER: The pngcrush computer program is supplied \"AS IS\".", "The Author disclaims all warranties, expressed or implied, including,", @@ -7965,7 +8830,7 @@ }; static const char *pngcrush_usage[] = { - "\nusage: %s [options] infile.png outfile.png\n", + "\nusage: %s [options except for -e -d] infile.png outfile.png\n", " %s -e ext [other options] file.png ...\n", " %s -d dir/ [other options] file.png ...\n", " %s -ow [other options] file.png [tempfile.png]\n", @@ -7973,15 +8838,6 @@ }; struct options_help pngcrush_options[] = { -#if 0 - {0, " -already already_crushed_size [e.g., 8192]"}, - {2, ""}, /* blank */ - {2, " If file has an IDAT greater than this size, it"}, - {2, " will be considered to be already crushed and will"}, - {2, " not be processed, unless you are making other changes"}, - {2, " or the \"-force\" option is present."}, - {2, ""}, -#endif {0, " -bail (bail out of trial when size exceeds best size found"}, {2, ""}, @@ -7991,11 +8847,6 @@ {2, " option to prevent that."}, {2, ""}, - {0, " -bit_depth depth (deprecated)"}, - {2, ""}, - {2, " This option no longer does anything."}, - {2, ""}, - {0, " -blacken (zero samples underlying fully-transparent pixels)"}, {2, ""}, {2, " Changing the color samples to zero can improve the"}, @@ -8004,9 +8855,9 @@ {2, ""}, #ifdef Z_RLE - {0, " -brute (use brute-force: try 148 different methods)"}, + {0, " -brute (use brute-force: try 176 different methods)"}, #else - {0, " -brute (use brute-force: try 136 different methods)"}, + {0, " -brute (use brute-force: try 166 different methods)"}, #endif {2, ""}, {2, " Very time-consuming and generally not worthwhile."}, @@ -8029,6 +8880,11 @@ {2, " Default is to use same color type as the input file."}, {2, ""}, + {0, " -check (check CRC and ADLER32 checksums)"}, + {2, ""}, + {2, " Use \"-nocheck\" (default) to skip checking them"}, + {2, ""}, + {0, " -d directory_name/ (where output files will go)"}, {2, ""}, {2, " If a directory name is given, then the output"}, @@ -8043,16 +8899,10 @@ {0, FAKE_PAUSE_STRING}, - {0, " -double_gamma (used for fixing gamma in PhotoShop 5.0/5.02 files)"}, - {2, ""}, - {2, " It has been claimed that the PS5 bug is actually"}, - {2, " more complex than that, in some unspecified way."}, - {2, ""}, - {0, " -e extension (used for creating output filename)"}, {2, ""}, {2, " e.g., -ext .new means *.png => *.new"}, - {2, " and -e _C.png means *.png => *_C.png"}, + {2, " and -e _pc.png means *.png => *_pc.png"}, {2, ""}, {0, " -f user_filter [0-5] for specified method"}, @@ -8064,15 +8914,14 @@ {0, FAKE_PAUSE_STRING}, - {0, " -fix (salvage PNG with otherwise fatal conditions"}, - {2, " such as bad CRCs and adaptive filter bytes)"}, + {0, " -fix (salvage PNG with otherwise fatal conditions)"}, {2, ""}, - - {0, " -force (write a new output file even if larger than input)"}, + {2, " Fixes bad CRCs, bad adaptive filter bytes,"}, + {2, " or bad CMF bytes in the IDAT chunk that cause"}, + {2, " the \"Too far back\" error"}, {2, ""}, - {2, " Otherwise the input file will be copied to output"}, - {2, " if it is smaller than any generated file and no chunk"}, - {2, " additions, removals, or changes were requested."}, + + {0, " -force (write output even if IDAT is larger)"}, {2, ""}, #ifdef PNG_FIXED_POINT_SUPPORTED @@ -8151,7 +9000,7 @@ {2, ""}, {2, FAKE_PAUSE_STRING}, - {0, " -max maximum_IDAT_size [default "STRNGIFY(PNG_ZBUF_SIZE)"]"}, + {0, " -max maximum_IDAT_size [default "STRNGIFY(MAX_IDAT_SIZE)"]"}, {2, ""}, #ifdef PNGCRUSH_LOCO @@ -8164,7 +9013,7 @@ {2, " Useful in conjunction with -v option to get info."}, {2, ""}, - {0, " -new (Use new default settings (-force and -reduce))"}, + {0, " -new (Use new default settings (-reduce))"}, {2, ""}, {0, " -newtimestamp (Reset file modification time [default])"}, @@ -8176,6 +9025,11 @@ {2, " exact filesize achieved by each trial."}, {2, ""}, + {0, " -nocheck (do not check CRC and ADLER32 checksums)"}, + {2, ""}, + {2, " Use \"-check\" to check them"}, + {2, ""}, + {0, FAKE_PAUSE_STRING}, {0, " -nofilecheck (do not check for infile.png == outfile.png)"}, @@ -8185,6 +9039,9 @@ {2, " ensuring that the input file is not the output file."}, {2, ""}, + {0, " -noforce (default; do not write output when IDAT is larger)"}, + {2, ""}, + {0, " -nolimits (turns off limits on width, height, cache, malloc)"}, {2, ""}, {2, " Instead, the user limits are inherited from libpng."}, @@ -8196,7 +9053,7 @@ {0, "-noreduce_palette (turns off \"-reduce_palette\" operation)"}, {2, ""}, - {0, " -old (Use old default settings (no -force and no -reduce))"}, + {0, " -old (Use old default settings (no -reduce))"}, {2, ""}, {0, " -oldtimestamp (Do not reset file modification time)"}, @@ -8204,17 +9061,22 @@ {0, " -ow (Overwrite)"}, {2, ""}, - {2, " Overwrite the input file. The input file is "}, - {2, " removed and the output file (default \"pngout.png\")"}, + {2, " Overwrite the input file. The input file is removed"}, + {2, " and the temporary file (default \"pngout.png\")"}, {2, " is renamed to the input file after recompression"}, - {2, " and therefore they must reside on the same filesystem"}, + {2, " and therefore they must reside on the same"}, + {2, " filesystem."}, {2, ""}, - - {0, " -plte_len n (obsolete; any \"n\" enables palette reduction)"}, + {2, " CAUTION: If you are running multiple instances"}, + {2, " of pngcrush in parallel, you must specify a"}, + {2, " different temporary filename for each instance,"}, + {2, " to avoid collisions."}, {2, ""}, {0, " -q (quiet) suppresses console output except for warnings"}, {2, ""}, + {2, " and summary of results."}, + {2, ""}, {0, " -reduce (do lossless color-type or bit-depth reduction)"}, {2, ""}, @@ -8223,6 +9085,8 @@ {2, " bit depth from 16 to 8. Reduces all-gray RGB"}, {2, " or RGBA image to gray or gray-alpha. Reduces"}, {2, " all-opaque RGBA or GA image to RGB or grayscale."}, + {2, " Since pngcrush version 1.8.0, -reduce is on by"}, + {2, " default, and you can disable it with -noreduce."}, {2, ""}, {0, " -rem chunkname (or \"alla\" or \"allb\")"}, @@ -8270,6 +9134,9 @@ {0, " -s (silent) suppresses console output including warnings"}, {2, ""}, + {2, " benchmark timing, and summary of results."}, + {2, " (Use \"-warn\" to show only warnings"}, + {2, ""}, {0, " -save (keep all copy-unsafe PNG chunks)"}, {2, ""}, @@ -8286,6 +9153,15 @@ {0, FAKE_PAUSE_STRING}, + {0, " -speed Avoid the AVG and PAETH filters, for decoding speed"}, + {2, ""}, + {2, " Useful for compressing PNG files that are expected"}, + {2, " to be cached or otherwise to exist on the computer"}, + {2, " where they will be used rather than being downloaded,"}, + {2, " so filesize is therefore less important than CPU"}, + {2, " time expended in defiltering."}, + {2, ""}, + {0, " -srgb [0, 1, 2, or 3]"}, {2, ""}, {2, " Value of 'rendering intent' for sRGB chunk."}, @@ -8332,6 +9208,9 @@ {2, " http://pmt.sf.net"}, {2, ""}, + {0, " -warn (only show warnings)"}, + {2, ""}, + {0, " -w compression_window_size [32, 16, 8, 4, 2, 1, 512]"}, {2, ""}, {2, " Size of the sliding compression window, in kbytes"}, @@ -8438,4 +9317,5 @@ exit(retval); } + #endif /* PNGCRUSH_LIBPNG_VER < 10800 || defined(PNGCRUSH_H) */