Gentoo Archives: gentoo-commits

From: "Samuli Suominen (drac)" <drac@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in media-gfx/pngcrush/files: pngcrush-1.6.7-modified_debian_patchset_1.patch
Date: Wed, 30 Jul 2008 20:07:59
Message-Id: E1KOHxV-0005pZ-4F@stork.gentoo.org
1 drac 08/07/30 20:07:41
2
3 Added: pngcrush-1.6.7-modified_debian_patchset_1.patch
4 Log:
5 version bump
6 (Portage version: 2.2_rc3/cvs/Linux 2.6.26-rc3 x86_64)
7
8 Revision Changes Path
9 1.1 media-gfx/pngcrush/files/pngcrush-1.6.7-modified_debian_patchset_1.patch
10
11 file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/media-gfx/pngcrush/files/pngcrush-1.6.7-modified_debian_patchset_1.patch?rev=1.1&view=markup
12 plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/media-gfx/pngcrush/files/pngcrush-1.6.7-modified_debian_patchset_1.patch?rev=1.1&content-type=text/plain
13
14 Index: pngcrush-1.6.7-modified_debian_patchset_1.patch
15 ===================================================================
16 diff -ruN pngcrush-1.6.7-nolib.orig/Makefile pngcrush-1.6.7-nolib/Makefile
17 --- pngcrush-1.6.7-nolib.orig/Makefile 1970-01-01 02:00:00.000000000 +0200
18 +++ pngcrush-1.6.7-nolib/Makefile 2008-07-30 23:01:16.000000000 +0300
19 @@ -0,0 +1,69 @@
20 +# Sample makefile for pngcrush using gcc and GNU make.
21 +# Glenn Randers-Pehrson
22 +# Last modified: 19 February 2005
23 +# Kapil Hari Paranjape
24 +# Last modified: 12 June 2008
25 +#
26 +# Invoke this makefile from a shell prompt in the usual way; for example:
27 +#
28 +# make -f Makefile
29 +#
30 +# This makefile builds a dynamically linked executable.
31 +
32 +# macros --------------------------------------------------------------------
33 +
34 +GAS_VERSION := $(shell as --version | sed -n -e's/GNU assembler (.*) //p')
35 +
36 +PNGINC = /usr/include
37 +
38 +CC ?= gcc
39 +RM = rm -f
40 +
41 +CFLAGS += -I. -Wall
42 +
43 +O = .o
44 +E =
45 +
46 +# additional defines
47 +DEFINES = -DPNG_USE_PNGGCCRD -DPNG_iCCP_SUPPORTED \
48 + -DPNG_iTXt_SUPPORTED -DPNG_USE_GLOBAL_ARRAYS \
49 + -DGAS_VERSION="\"${GAS_VERSION}\"" \
50 +
51 +PNGCRUSH = pngcrush
52 +
53 +LIBS = -lpng -lz
54 +
55 +OBJS = pngcrush$(O)
56 +
57 +EXES = $(PNGCRUSH)$(E)
58 +
59 +
60 +# implicit make rules -------------------------------------------------------
61 +
62 +.c$(O): png.h cexcept.h $(ZHDR)
63 + $(CC) -c $(CFLAGS) $(DEFINES) $<
64 +
65 +
66 +# dependencies --------------------------------------------------------------
67 +
68 +all: $(EXES)
69 +
70 +png.h:
71 + ln -s $(PNGINC)/png.h png.h
72 +
73 +pngcrush$(O): pngcrush.c cexcept.h
74 + $(CC) -c $(CFLAGS) $(DEFINES) $<
75 +
76 +$(PNGCRUSH)$(E): $(OBJS)
77 + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
78 +
79 +# maintenance ---------------------------------------------------------------
80 +
81 +clean:
82 + $(RM) $(EXES) $(OBJS) png.h
83 +
84 +install:
85 + mkdir -p $(DESTDIR)/usr/bin/
86 + cp $(PNGCRUSH)$(E) $(DESTDIR)/usr/bin/
87 + chmod 0755 $(DESTDIR)/usr/bin/$(PNGCRUSH)$(E)
88 +
89 diff -ruN pngcrush-1.6.7-nolib.orig/pngcrush.c pngcrush-1.6.7-nolib/pngcrush.c
90 --- pngcrush-1.6.7-nolib.orig/pngcrush.c 2008-06-13 04:50:52.000000000 +0300
91 +++ pngcrush-1.6.7-nolib/pngcrush.c 2008-07-30 22:54:19.000000000 +0300
92 @@ -303,6 +303,11 @@
93 ((png_uint_32) 116 ))
94 #endif
95
96 +PNG_EXPORT_VAR (const png_byte FARDATA) png_IHDR[5];
97 +PNG_EXPORT_VAR (const png_byte FARDATA) png_IDAT[5];
98 +PNG_EXPORT_VAR (const png_byte FARDATA) png_IEND[5];
99 +PNG_EXPORT_VAR (const png_byte FARDATA) png_iCCP[5];
100 +
101 #define PNG_FLAG_CRC_CRITICAL_USE 0x0400
102 #define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800
103 #define PNG_FLAG_CRC_ANCILLARY_USE 0x0100
104 @@ -1569,13 +1574,6 @@
105 do_color_count = do_color_count; /* silence compiler warning */
106 #endif
107
108 - if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) {
109 - fprintf(STDERR,
110 - "Warning: versions are different between png.h and png.c\n");
111 - fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING);
112 - fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver);
113 - }
114 -
115 t_start = (TIME_T) clock();
116
117 strncpy(prog_string, argv[0], STR_BUF_SIZE);
118 @@ -2035,7 +2033,7 @@
119 if (!strncmp(argv[i], "-zi", 3)) {
120 text_compression[text_inputs] =
121 PNG_ITXT_COMPRESSION_zTXt;
122 - names += 2;
123 + /* names += 2; */
124 } else
125 #endif
126 if (!strncmp(argv[i], "-z", 2))
127 @@ -2048,7 +2046,7 @@
128 else {
129 text_compression[text_inputs] =
130 PNG_ITXT_COMPRESSION_NONE;
131 - names += 2;
132 + /* names += 2; */
133 }
134 #endif
135 names += 3;
136 @@ -2062,6 +2060,10 @@
137 text_lang[text_inputs * 80] = '\0';
138 text_lang_key[text_inputs * 80] = '\0';
139 } else {
140 + i += 2;
141 + BUMP_I;
142 + i -= 3;
143 + names += 2;
144 strcpy(&text_lang[text_inputs * 80], argv[++i]);
145 /* libpng-1.0.5j and later */
146 strcpy(&text_lang_key[text_inputs * 80], argv[++i]);
147 @@ -4698,7 +4700,7 @@
148
149 for (;;) {
150 #ifndef PNG_UINT_IDAT
151 -#ifdef PNG_USE_LOCAL_ARRAYS
152 +#if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNGCRUSH_USE_LOCAL_ARRAYS)
153 PNG_IDAT;
154 PNG_IEND;
155 PNG_IHDR;
156 @@ -5452,6 +5454,12 @@
157 PNGCRUSH_VERSION, progname, PNG_LIBPNG_VER_STRING,
158 png_get_header_version(NULL), ZLIB_VERSION);
159
160 + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) {
161 + fprintf(STDERR, "|| Warning: versions are different between png.h and png.c\n");
162 + fprintf(STDERR, "|| png.h version: %s\n", PNG_LIBPNG_VER_STRING);
163 + fprintf(STDERR, "|| png.c version: %s\n\n", png_libpng_ver);
164 + }
165 +
166 #if defined(__GNUC__)
167 fprintf(STDERR,
168 " | It was compiled with gcc version %s", __VERSION__);
169 diff -ruN pngcrush-1.6.7-nolib.orig/pngcrush.c.orig pngcrush-1.6.7-nolib/pngcrush.c.orig
170 --- pngcrush-1.6.7-nolib.orig/pngcrush.c.orig 1970-01-01 02:00:00.000000000 +0200
171 +++ pngcrush-1.6.7-nolib/pngcrush.c.orig 2008-07-30 22:54:14.000000000 +0300
172 @@ -0,0 +1,5915 @@
173 +/* pngcrush.c - recompresses png files
174 + * Copyright (C) 1998-2002,2006-2008 Glenn Randers-Pehrson (glennrp@××××××××.net)
175 + * Copyright (C) 2005 Greg Roelofs
176 + *
177 + * The most recent version of pngcrush can be found at SourceForge in
178 + * http://pmt.sf.net/pngcrush/
179 + *
180 + * This program reads in a PNG image, and writes it out again, with the
181 + * optimum filter_method and zlib_level. It uses brute force (trying
182 + * filter_method none, and libpng adaptive filtering, with compression
183 + * levels 3 and 9). It does the most time-consuming method last in case
184 + * it turns out to be the best.
185 + *
186 + * Optionally, it can remove unwanted chunks or add gAMA, sRGB, bKGD,
187 + * tEXt/zTXt, and tRNS chunks. It will remove some chunks such as gAMA,
188 + * cHRM, pHYs, and oFFs when their data fields contain all zero, which is a
189 + * mistake.
190 + *
191 + * Uses libpng and zlib. This program was based upon libpng's pngtest.c.
192 + *
193 + * Thanks to Greg Roelofs for various bug fixes, suggestions, and
194 + * occasionally creating Linux executables.
195 + *
196 + * Thanks to Stephan Levavej for some helpful suggestions about gcc compiler
197 + * options and for a suggestion to increase the Z_MEM_LEVEL from default.
198 + *
199 + */
200 +
201 +#define PNGCRUSH_VERSION "1.6.6"
202 +
203 +/*
204 +#define PNGCRUSH_COUNT_COLORS
205 +*/
206 +
207 +/*
208 + * COPYRIGHT NOTICE, DISCLAIMER, AND LICENSE:
209 + *
210 + * If you have modified this source, you may insert additional notices
211 + * immediately after this sentence.
212 + *
213 + * Copyright (C) 1998-2002,2006-2008 Glenn Randers-Pehrson (glennrp@××××××××.net)
214 + * Copyright (C) 2005 Greg Roelofs
215 + *
216 + * The pngcrush computer program is supplied "AS IS". The Author disclaims all
217 + * warranties, expressed or implied, including, without limitation, the
218 + * warranties of merchantability and of fitness for any purpose. The
219 + * Author assumes no liability for direct, indirect, incidental, special,
220 + * exemplary, or consequential damages, which may result from the use of
221 + * the computer program, even if advised of the possibility of such damage.
222 + * There is no warranty against interference with your enjoyment of the
223 + * computer program or against infringement. There is no warranty that my
224 + * efforts or the computer program will fulfill any of your particular purposes
225 + * or needs. This computer program is provided with all faults, and the entire
226 + * risk of satisfactory quality, performance, accuracy, and effort is with
227 + * the user.
228 + *
229 + * Permission is hereby irrevocably granted to everyone to use, copy, modify,
230 + * and distribute this source code, or portions hereof, or executable programs
231 + * compiled from it, for any purpose, without payment of any fee, subject to
232 + * the following restrictions:
233 + *
234 + * 1. The origin of this source code must not be misrepresented.
235 + *
236 + * 2. Altered versions must be plainly marked as such and must not be
237 + * misrepresented as being the original source.
238 + *
239 + * 3. This Copyright notice, disclaimer, and license may not be removed
240 + * or altered from any source or altered source distribution.
241 + */
242 +
243 +/* To do:
244 + *
245 + * Reset CINFO to reflect decoder's required window size (instead of
246 + * libz-1.1.3 encoder's required window size, which is 262 bytes larger).
247 + * See discussion about zlib in png-list archives for April 2001.
248 + *
249 + * Add a "pcRu" ancillary chunk that keeps track of the best method,
250 + * methods already tried, and whether "loco crushing" was effective.
251 + *
252 + * Try both transformed and untransformed colors when "-loco" is used.
253 + *
254 + * Check for unused alpha channel and ok-to-reduce-depth.
255 + * Take care that sBIT and bKGD data aren't lost when reducing images
256 + * from truecolor to grayscale.
257 + *
258 + * Rearrange palette to put most-used color first and transparent color
259 + * second (see ImageMagick 5.1.1 and later).
260 + *
261 + * Finish pplt (partial palette) feature.
262 + *
263 + * add "-time" directive
264 + *
265 + * Allow in-place file replacement or as a filter, as in
266 + * "pngcrush -overwrite file.png"
267 + * "pngcreator | pngcrush > output.png"
268 + *
269 + * Use an alternate write function for the trial passes, that
270 + * simply counts bytes rather than actually writing to a file, to save wear
271 + * and tear on disk drives.
272 + *
273 + * Remove text-handling and color-handling features and put
274 + * those in a separate program or programs, to avoid unnecessary
275 + * recompressing.
276 + *
277 + * Move the Photoshop-fixing stuff into a separate program.
278 + *
279 + * GRR: More generally (superset of previous 3 items): split into separate
280 + * "edit" and "crush" programs (or functions). Former is fully libpng-
281 + * aware, much like current pngcrush; latter makes little or no use of
282 + * libpng (maybe IDAT-compression parts only?), instead handling virtually
283 + * all chunks as opaque binary blocks that are copied to output file _once_,
284 + * with IDATs alone replaced (either by best in-memory result or by original
285 + * _data_ resplit into bigger IDATs, if pngcrush can't match/beat). "edit"
286 + * version should be similar to current code but more efficient: make
287 + * _one_ pass through args list, creating table of PNG_UINTs for removal;
288 + * then make initial pass through PNG image, creating (in-order) table of
289 + * all chunks (and byte offsets?) and marking each as "keep" or "remove"
290 + * according to args table. Can start with static table of ~20-30 slots,
291 + * then double size & copy if run out of room: still O(n) algorithm.
292 + */
293 +
294 +#include "png.h"
295 +
296 +/* internal libpng macros */
297 +
298 +
299 +#ifdef PNG_LIBPNG_VER
300 +#define PNGCRUSH_LIBPNG_VER PNG_LIBPNG_VER
301 +#else
302 +/* This must agree with PNG_LIBPNG_VER; you have to define it manually
303 + here if you are using libpng-1.0.6h or earlier */
304 +#define PNGCRUSH_LIBPNG_VER 10007
305 +#endif
306 +
307 +/* Changed in version 0.99 */
308 +#if PNGCRUSH_LIBPNG_VER < 99
309 +#undef PNG_CONST
310 +#ifndef PNG_NO_CONST
311 +# define PNG_CONST const
312 +#else
313 +# define PNG_CONST
314 +#endif
315 +#endif
316 +
317 +#define PNG_IDAT const png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'}
318 +#define PNG_IHDR const png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'}
319 +#define PNG_dSIG const png_byte png_dSIG[5] = {100, 83, 73, 71, '\0'}
320 +#define PNG_iCCP const png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'}
321 +#define PNG_IEND const png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'}
322 +
323 +/* GRR 20050220: added these, which apparently aren't defined anywhere else */
324 +#ifndef PNG_UINT_IHDR
325 +# define PNG_UINT_IHDR (((png_uint_32) 73<<24) | \
326 + ((png_uint_32) 72<<16) | \
327 + ((png_uint_32) 68<< 8) | \
328 + ((png_uint_32) 82 ))
329 +#endif
330 +
331 +#ifndef PNG_UINT_IDAT
332 +# define PNG_UINT_IDAT (((png_uint_32) 73<<24) | \
333 + ((png_uint_32) 68<<16) | \
334 + ((png_uint_32) 65<< 8) | \
335 + ((png_uint_32) 84 ))
336 +#endif
337 +
338 +#ifndef PNG_UINT_IEND
339 +# define PNG_UINT_IEND (((png_uint_32) 73<<24) | \
340 + ((png_uint_32) 69<<16) | \
341 + ((png_uint_32) 78<< 8) | \
342 + ((png_uint_32) 68 ))
343 +#endif
344 +
345 +#ifndef PNG_UINT_PLTE
346 +# define PNG_UINT_PLTE (((png_uint_32) 80<<24) | \
347 + ((png_uint_32) 76<<16) | \
348 + ((png_uint_32) 84<< 8) | \
349 + ((png_uint_32) 69 ))
350 +#endif
351 +
352 +#ifndef PNG_UINT_bKGD
353 +# define PNG_UINT_bKGD (((png_uint_32) 98<<24) | \
354 + ((png_uint_32) 75<<16) | \
355 + ((png_uint_32) 71<< 8) | \
356 + ((png_uint_32) 68 ))
357 +#endif
358 +
359 +#ifndef PNG_UINT_cHRM
360 +# define PNG_UINT_cHRM (((png_uint_32) 99<<24) | \
361 + ((png_uint_32) 72<<16) | \
362 + ((png_uint_32) 82<< 8) | \
363 + ((png_uint_32) 77 ))
364 +#endif
365 +
366 +#ifndef PNG_UINT_dSIG
367 +# define PNG_UINT_dSIG (((png_uint_32) 100<<24) | \
368 + ((png_uint_32) 83<<16) | \
369 + ((png_uint_32) 73<< 8) | \
370 + ((png_uint_32) 71 ))
371 +#endif
372 +
373 +#ifndef PNG_UINT_gAMA
374 +# define PNG_UINT_gAMA (((png_uint_32) 103<<24) | \
375 + ((png_uint_32) 65<<16) | \
376 + ((png_uint_32) 77<< 8) | \
377 + ((png_uint_32) 65 ))
378 +#endif
379 +
380 +#ifndef PNG_UINT_hIST
381 +# define PNG_UINT_hIST (((png_uint_32) 104<<24) | \
382 + ((png_uint_32) 73<<16) | \
383 + ((png_uint_32) 83<< 8) | \
384 + ((png_uint_32) 84 ))
385 +#endif
386 +
387 +#ifndef PNG_UINT_iCCP
388 +# define PNG_UINT_iCCP (((png_uint_32) 105<<24) | \
389 + ((png_uint_32) 67<<16) | \
390 + ((png_uint_32) 67<< 8) | \
391 + ((png_uint_32) 80 ))
392 +#endif
393 +
394 +#ifndef PNG_UINT_iTXt
395 +# define PNG_UINT_iTXt (((png_uint_32) 105<<24) | \
396 + ((png_uint_32) 84<<16) | \
397 + ((png_uint_32) 88<< 8) | \
398 + ((png_uint_32) 116 ))
399 +#endif
400 +
401 +#ifndef PNG_UINT_oFFs
402 +# define PNG_UINT_oFFs (((png_uint_32) 111<<24) | \
403 + ((png_uint_32) 70<<16) | \
404 + ((png_uint_32) 70<< 8) | \
405 + ((png_uint_32) 115 ))
406 +#endif
407 +
408 +#ifndef PNG_UINT_pCAL
409 +# define PNG_UINT_pCAL (((png_uint_32) 112<<24) | \
410 + ((png_uint_32) 67<<16) | \
411 + ((png_uint_32) 65<< 8) | \
412 + ((png_uint_32) 76 ))
413 +#endif
414 +
415 +#ifndef PNG_UINT_pHYs
416 +# define PNG_UINT_pHYs (((png_uint_32) 112<<24) | \
417 + ((png_uint_32) 72<<16) | \
418 + ((png_uint_32) 89<< 8) | \
419 + ((png_uint_32) 115 ))
420 +#endif
421 +
422 +#ifndef PNG_UINT_sBIT
423 +# define PNG_UINT_sBIT (((png_uint_32) 115<<24) | \
424 + ((png_uint_32) 66<<16) | \
425 + ((png_uint_32) 73<< 8) | \
426 + ((png_uint_32) 84 ))
427 +#endif
428 +
429 +#ifndef PNG_UINT_sCAL
430 +# define PNG_UINT_sCAL (((png_uint_32) 115<<24) | \
431 + ((png_uint_32) 67<<16) | \
432 + ((png_uint_32) 65<< 8) | \
433 + ((png_uint_32) 76 ))
434 +#endif
435 +
436 +#ifndef PNG_UINT_sPLT
437 +# define PNG_UINT_sPLT (((png_uint_32) 115<<24) | \
438 + ((png_uint_32) 80<<16) | \
439 + ((png_uint_32) 76<< 8) | \
440 + ((png_uint_32) 84 ))
441 +#endif
442 +
443 +#ifndef PNG_UINT_sRGB
444 +# define PNG_UINT_sRGB (((png_uint_32) 115<<24) | \
445 + ((png_uint_32) 82<<16) | \
446 + ((png_uint_32) 71<< 8) | \
447 + ((png_uint_32) 66 ))
448 +#endif
449 +
450 +#ifndef PNG_UINT_tEXt
451 +# define PNG_UINT_tEXt (((png_uint_32) 116<<24) | \
452 + ((png_uint_32) 69<<16) | \
453 + ((png_uint_32) 88<< 8) | \
454 + ((png_uint_32) 116 ))
455 +#endif
456 +
457 +#ifndef PNG_UINT_tIME
458 +# define PNG_UINT_tIME (((png_uint_32) 116<<24) | \
459 + ((png_uint_32) 73<<16) | \
460 + ((png_uint_32) 77<< 8) | \
461 + ((png_uint_32) 69 ))
462 +#endif
463 +
464 +#ifndef PNG_UINT_tRNS
465 +# define PNG_UINT_tRNS (((png_uint_32) 116<<24) | \
466 + ((png_uint_32) 82<<16) | \
467 + ((png_uint_32) 78<< 8) | \
468 + ((png_uint_32) 83 ))
469 +#endif
470 +
471 +#ifndef PNG_UINT_zTXt
472 +# define PNG_UINT_zTXt (((png_uint_32) 122<<24) | \
473 + ((png_uint_32) 84<<16) | \
474 + ((png_uint_32) 88<< 8) | \
475 + ((png_uint_32) 116 ))
476 +#endif
477 +
478 +PNG_EXPORT_VAR (const png_byte FARDATA) png_IHDR[5];
479 +PNG_EXPORT_VAR (const png_byte FARDATA) png_IDAT[5];
480 +PNG_EXPORT_VAR (const png_byte FARDATA) png_IEND[5];
481 +PNG_EXPORT_VAR (const png_byte FARDATA) png_iCCP[5];
482 +
483 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400
484 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800
485 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100
486 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200
487 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400
488 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800
489 +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \
490 + PNG_FLAG_CRC_ANCILLARY_NOWARN)
491 +#define PNG_PACK 0x0004
492 +#define PNG_DITHER 0x0040
493 +#define PNG_BACKGROUND 0x0080
494 +#define PNG_16_TO_8 0x0400
495 +#define PNG_RGBA 0x0800
496 +#define PNG_EXPAND 0x1000
497 +#define PNG_GAMMA 0x2000
498 +#define PNG_GRAY_TO_RGB 0x4000
499 +#define PNG_FILLER 0x8000L
500 +#define PNG_USER_TRANSFORM 0x100000L
501 +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */
502 +
503 +/* we don't need some of the extra libpng transformations
504 + * so they are ifdef'ed out in pngcrush.h, which is included by
505 + * libpng's pngconf.h which is included by png.h */
506 +
507 +/* defined so I can write to a file on gui/windowing platforms */
508 +/* #define STDERR stderr */
509 +#define STDERR stdout /* for DOS */
510 +
511 +#ifndef PNGCRUSH_LIBPNG_VER
512 +# define PNGCRUSH_LIBPNG_VER PNG_LIBPNG_VER
513 +#endif
514 +
515 +#ifdef PNG_MNG_FEATURES_SUPPORTED
516 +# define PNGCRUSH_LOCO
517 +#endif
518 +
519 +#ifndef PNG_UINT_31_MAX
520 +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL)
521 +#endif
522 +
523 +/* These macros were renamed in libpng-1.2.6 */
524 +#ifndef PNG_HANDLE_CHUNK_ALWAYS
525 +#define PNG_HANDLE_CHUNK_ALWAYS HANDLE_CHUNK_ALWAYS
526 +#define PNG_HANDLE_CHUNK_NEVER HANDLE_CHUNK_NEVER
527 +#define PNG_HANDLE_CHUNK_IF_SAFE HANDLE_CHUNK_IF_SAFE
528 +#endif
529 +
530 +#if defined(__DJGPP__)
531 +# if ((__DJGPP__ == 2) && (__DJGPP_MINOR__ == 0))
532 +# include <libc/dosio.h> /* for _USE_LFN, djgpp 2.0 only */
533 +# endif
534 +# define SLASH "\\"
535 +# define DOT "."
536 +#else
537 +# ifdef __riscos
538 +# define SLASH "."
539 +# define DOT "/"
540 +# else
541 +# define SLASH "/"
542 +# define DOT "."
543 +# endif
544 +#endif
545 +
546 +#ifndef GAS_VERSION
547 +# define GAS_VERSION "2.9.5(?)" /* used only in help/usage screen */
548 +#endif
549 +
550 +#if !defined(__TURBOC__) && !defined(_MSC_VER) && !defined(_MBCS) && \
551 + !defined(__riscos)
552 +# include <unistd.h>
553 +#endif
554 +
555 +#ifndef __riscos
556 +# include <sys/types.h>
557 +# include <sys/stat.h>
558 +# include <utime.h>
559 +#endif
560 +
561 +#include <stdio.h>
562 +#include <stdlib.h>
563 +#include <time.h>
564 +#include <assert.h>
565 +
566 +#if defined(_MBCS) || defined(WIN32) || defined(__WIN32__)
567 +# include <direct.h>
568 +#endif
569 +
570 +#define DEFAULT_MODE 0
571 +#define DIRECTORY_MODE 1
572 +#define EXTENSION_MODE 2
573 +#define DIREX_MODE 3
574 +#define FOPEN(file, how) fopen(file, how)
575 +#define FCLOSE(file) {fclose(file); file=NULL;--number_of_open_files;};
576 +
577 +#define P0 if(first_trial && verbose > 0)printf
578 +#define P1 if(verbose > 1)printf
579 +#define P2 if(verbose > 2)printf
580 +
581 +#define STRNGIFY_STAGE1(x) #x
582 +#define STRNGIFY(x) STRNGIFY_STAGE1(x)
583 +
584 +#define STR_BUF_SIZE 256
585 +#define MAX_IDAT_SIZE 524288L
586 +#define MAX_METHODS 200
587 +#define MAX_METHODSP1 (MAX_METHODS+1)
588 +#define DEFAULT_METHODS 10
589 +#define FAKE_PAUSE_STRING "P"
590 +
591 +#ifdef Z_RLE
592 +# define NUM_STRATEGIES 4
593 +#else
594 +# define NUM_STRATEGIES 3
595 +#endif
596 +
597 +#ifdef __TURBOC__
598 +# include <mem.h>
599 +#endif
600 +
601 +#ifndef CLOCKS_PER_SEC
602 +#define CLOCKS_PER_SEC 1000
603 +#endif
604 +
605 +#if CLOCKS_PER_SEC <= 100
606 +# define TIME_T long
607 +#else
608 +# define TIME_T float
609 +#endif
610 +
611 +struct options_help {
612 + int verbosity; /* if verbose >= this value, then print line */
613 + const char *textline; /* static string with newline chopped off */
614 +};
615 +
616 +/* input and output filenames */
617 +static PNG_CONST char *progname;
618 +static PNG_CONST char *inname = "pngtest" DOT "png";
619 +static PNG_CONST char *outname = "pngout" DOT "png";
620 +static PNG_CONST char *mngname = "mngout" DOT "mng";
621 +static PNG_CONST char *directory_name = "pngcrush" DOT "bak";
622 +static PNG_CONST char *extension = "_C" DOT "png";
623 +
624 +static png_uint_32 width, height;
625 +static png_uint_32 measured_idat_length;
626 +static int found_gAMA = 0;
627 +static int found_cHRM = 0;
628 +static int found_any_chunk = 0;
629 +static int image_is_immutable = 0;
630 +static int pngcrush_must_exit = 0;
631 +static int all_chunks_are_safe = 0;
632 +static int number_of_open_files;
633 +static int do_pplt = 0;
634 +#ifdef PNGCRUSH_MULTIPLE_ROWS
635 +static png_uint_32 max_rows_at_a_time = 1;
636 +static png_uint_32 rows_at_a_time;
637 +#endif
638 +char pplt_string[1024];
639 +char *ip, *op, *dot;
640 +char in_string[STR_BUF_SIZE];
641 +char prog_string[STR_BUF_SIZE];
642 +char out_string[STR_BUF_SIZE];
643 +char in_extension[STR_BUF_SIZE];
644 +static int text_inputs = 0;
645 +int text_where[10]; /* 0: no text; 1: before PLTE; 2: after PLTE */
646 +int text_compression[10]; /* -1: uncompressed tEXt; 0: compressed zTXt
647 + 1: uncompressed iTXt; 2: compressed iTXt */
648 +char text_text[20480]; /* It would be nice to png_malloc this, but we
649 + * don't have a png_ptr yet when we need it. */
650 +char text_keyword[800];
651 +
652 +/* PNG_iTXt_SUPPORTED */
653 +char text_lang[800];
654 +char text_lang_key[800];
655 +
656 +/* PNG_iCCP_SUPPORTED */
657 +int iccp_length = 0;
658 +char *iccp_text;
659 +char *iccp_file;
660 +char iccp_name[80];
661 +
662 +int best;
663 +
664 +char buffer[256];
665 +
666 +/* Set up the "cexcept" Try/Throw/Catch exception handler. */
667 +#include "cexcept.h"
668 +define_exception_type(const char *);
669 +extern struct exception_context the_exception_context[1];
670 +struct exception_context the_exception_context[1];
671 +png_const_charp msg;
672 +
673 +static png_uint_32 total_input_length = 0;
674 +static png_uint_32 total_output_length = 0;
675 +static int pngcrush_mode = DEFAULT_MODE;
676 +static int resolution = 0;
677 +static int remove_chunks = 0;
678 +static int output_color_type;
679 +static int output_bit_depth;
680 +static int force_output_color_type = 8;
681 +static int force_output_bit_depth = 0;
682 +static int input_color_type;
683 +static int input_bit_depth;
684 +static int trial;
685 +static int first_trial = 0;
686 +static int verbose = 1;
687 +static int fix = 0;
688 +static int things_have_changed = 0;
689 +static int global_things_have_changed = 0;
690 +static int default_compression_window = 15;
691 +static int force_compression_window = 0;
692 +static int compression_mem_level = 9;
693 +static int final_method = 0;
694 +static int brute_force = 0;
695 +static int brute_force_level = 0;
696 +static int brute_force_filter = 0;
697 +static int brute_force_strategy = 0;
698 +static int brute_force_levels[10] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
699 +static int brute_force_filters[6] = { 1, 1, 1, 1, 1, 1 };
700 +#ifdef Z_RLE
701 +static int brute_force_strategies[NUM_STRATEGIES] = { 1, 1, 1, 1 };
702 +#else
703 +static int brute_force_strategies[NUM_STRATEGIES] = { 1, 1, 1 };
704 +#endif
705 +static int method = 10;
706 +static int pauses = 0;
707 +static int nosave = 0;
708 +static int nofilecheck = 0;
709 +#ifdef PNGCRUSH_LOCO
710 +static int new_mng = 0;
711 +#endif
712 +static png_bytep row_buf;
713 +#ifdef PNGCRUSH_MULTIPLE_ROWS
714 +static png_bytepp row_pointers;
715 +#endif
716 +static int z_strategy;
717 +static int best_of_three;
718 +static int methods_specified = 0;
719 +static int intent = -1;
720 +static int plte_len = -1;
721 +#ifdef PNG_FIXED_POINT_SUPPORTED
722 +static int specified_gamma = 0;
723 +static int image_specified_gamma = 0;
724 +static int force_specified_gamma = 0;
725 +#else
726 +static double specified_gamma = 0.0;
727 +static double image_specified_gamma = 0;
728 +static double force_specified_gamma = 0.0;
729 +#endif
730 +static int double_gamma = 0;
731 +
732 +static int names;
733 +
734 +static int have_trns = 0;
735 +static png_uint_16 trns_index = 0;
736 +static png_uint_16 trns_red = 0;
737 +static png_uint_16 trns_green = 0;
738 +static png_uint_16 trns_blue = 0;
739 +static png_uint_16 trns_gray = 0;
740 +
741 +static png_byte trns_array[256];
742 +static png_byte trans_in[256];
743 +static png_uint_16 num_trans_in;
744 +
745 +static int have_bkgd = 0;
746 +static png_uint_16 bkgd_red = 0;
747 +static png_uint_16 bkgd_green = 0;
748 +static png_uint_16 bkgd_blue = 0;
749 +
750 +static png_colorp palette;
751 +static int num_palette;
752 +
753 +#ifdef REORDER_PALETTE
754 +static png_byte palette_reorder[256];
755 +#endif
756 +
757 +static png_structp read_ptr, write_ptr, mng_ptr;
758 +static png_infop read_info_ptr, write_info_ptr;
759 +static png_infop end_info_ptr;
760 +static png_infop write_end_info_ptr;
761 +static FILE *fpin, *fpout, *mng_out;
762 +png_uint_32 measure_idats(FILE * fpin);
763 +#ifdef PNGCRUSH_LOCO
764 +static int do_loco = 0;
765 +static int input_format = 0; /* 0: PNG 1: MNG */
766 +static int output_format = 0;
767 +#endif
768 +static int do_color_count;
769 +static int reduction_ok = 0;
770 +#ifdef PNGCRUSH_COUNT_COLORS
771 +int count_colors(FILE * fpin);
772 +static int num_rgba, reduce_to_gray, it_is_opaque;
773 +#endif
774 +png_uint_32 png_measure_idat(png_structp png_ptr);
775 +
776 +static png_uint_32 idat_length[MAX_METHODSP1];
777 +static int filter_type, zlib_level;
778 +static png_bytep png_row_filters = NULL;
779 +static float t_start, t_stop, t_decode, t_encode, t_misc;
780 +
781 +static png_uint_32 max_idat_size = MAX_IDAT_SIZE; /* increases the IDAT size */
782 +static png_uint_32 crushed_idat_size = 0x3ffffffL;
783 +static int already_crushed = 0;
784 +int ia;
785 +
786 +
787 +/* prototypes */
788 +static void png_cexcept_error(png_structp png_ptr, png_const_charp msg);
789 +
790 +void PNGAPI png_default_read_data(png_structp png_ptr, png_bytep data,
791 + png_size_t length);
792 +
793 +void png_read_transform_info(png_structp png_ptr, png_infop info_ptr);
794 +
795 +void PNGAPI png_default_write_data(png_structp png_ptr, png_bytep data,
796 + png_size_t length);
797 +
798 +void png_reset_crc(png_structp png_ptr);
799 +void png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length);
800 +void png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length);
801 +int png_crc_error(png_structp png_ptr);
802 +int png_crc_finish(png_structp png_ptr, png_uint_32 skip);
803 +
804 +png_uint_32 png_get_uint_31(png_structp png_ptr, png_bytep buf);
805 +png_uint_32 png_get_uint_32(png_bytep buf);
806 +void png_save_uint_32(png_bytep buf, png_uint_32 i);
807 +
808 +#ifdef PNG_USER_MEM_SUPPORTED
809 +png_voidp png_debug_malloc(png_structp png_ptr, png_uint_32 size);
810 +void png_debug_free(png_structp png_ptr, png_voidp ptr);
811 +#endif
812 +
813 +void png_crush_pause(void);
814 +
815 +#ifdef __riscos
816 +static int fileexists(const char *name)
817 +static int filesize(const char *name)
818 +static int mkdir(const char *name, int ignored)
819 +static void setfiletype(const char *name)
820 +#endif
821 +
822 +int keep_unknown_chunk(png_const_charp name, char *argv[]);
823 +int keep_chunk(png_const_charp name, char *argv[]);
824 +void show_result(void);
825 +png_uint_32 measure_idats(FILE * fpin);
826 +png_uint_32 png_measure_idat(png_structp png_ptr);
827 +
828 +#ifdef PNGCRUSH_COUNT_COLORS
829 +int count_colors(FILE * fpin);
830 +#endif
831 +void print_version_info(void);
832 +void print_usage(int retval);
833 +
834 +
835 +#if (!defined(PNGCRUSH_H))
836 +/* ============================================================
837 + * We aren't using the bundled libpng functions, so we must
838 + * reproduce the libpng routines that aren't exported by libpng
839 + * ============================================================
840 + */
841 +
842 +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
843 +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
844 +png_uint_32 /* PRIVATE */
845 +png_get_uint_32(png_bytep buf)
846 +{
847 + png_uint_32 i = ((png_uint_32)(*buf) << 24) +
848 + ((png_uint_32)(*(buf + 1)) << 16) +
849 + ((png_uint_32)(*(buf + 2)) << 8) +
850 + (png_uint_32)(*(buf + 3));
851 +
852 + return (i);
853 +}
854 +#else
855 +# define png_get_uint_32(buf) ( *((png_uint_32p) (buf)))
856 +#endif
857 +png_uint_32 /* PRIVATE */
858 +png_get_uint_31(png_structp png_ptr, png_bytep buf)
859 +{
860 + png_uint_32 i = png_get_uint_32(buf);
861 + if (i > PNG_UINT_31_MAX)
862 + png_error(png_ptr, "PNG unsigned integer out of range.\n");
863 + return (i);
864 +}
865 +void /* PRIVATE */
866 +png_save_uint_32(png_bytep buf, png_uint_32 i)
867 +{
868 + buf[0] = (png_byte)((i >> 24) & 0xff);
869 + buf[1] = (png_byte)((i >> 16) & 0xff);
870 + buf[2] = (png_byte)((i >> 8) & 0xff);
871 + buf[3] = (png_byte)(i & 0xff);
872 +}
873 +
874 +/* Reset the CRC variable to 32 bits of 1's. Care must be taken
875 + * in case CRC is > 32 bits to leave the top bits 0.
876 + */
877 +void /* PRIVATE */
878 +png_reset_crc(png_structp png_ptr)
879 +{
880 + png_ptr->crc = crc32(0, Z_NULL, 0);
881 +}
882 +/* Calculate the CRC over a section of data. We can only pass as
883 + * much data to this routine as the largest single buffer size. We
884 + * also check that this data will actually be used before going to the
885 + * trouble of calculating it.
886 + */
887 +void /* PRIVATE */
888 +png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length)
889 +{
890 + int need_crc = 1;
891 +
892 + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
893 + {
894 + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
895 + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
896 + need_crc = 0;
897 + }
898 + else /* critical */
899 + {
900 + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
901 + need_crc = 0;
902 + }
903 +
904 + if (need_crc)
905 + png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length);
906 +}
907 +
908 +/* Read data, and (optionally) run it through the CRC. */
909 +void /* PRIVATE */
910 +png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
911 +{
912 + png_default_read_data(png_ptr, buf, length);
913 + png_calculate_crc(png_ptr, buf, length);
914 +}
915 +
916 +/* Compare the CRC stored in the PNG file with that calculated by libpng from
917 + the data it has read thus far. */
918 +int /* PRIVATE */
919 +png_crc_error(png_structp png_ptr)
920 +{
921 + png_byte crc_bytes[4];
922 + png_uint_32 crc;
923 + int need_crc = 1;
924 +
925 + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
926 + {
927 + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
928 + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
929 + need_crc = 0;
930 + }
931 + else /* critical */
932 + {
933 + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
934 + need_crc = 0;
935 + }
936 +
937 + png_default_read_data(png_ptr, crc_bytes, 4);
938 +
939 + if (need_crc)
940 + {
941 + crc = png_get_uint_32(crc_bytes);
942 + return ((int)(crc != png_ptr->crc));
943 + }
944 + else
945 + return (0);
946 +}
947 +
948 +/* Optionally skip data and then check the CRC. Depending on whether we
949 + are reading a ancillary or critical chunk, and how the program has set
950 + things up, we may calculate the CRC on the data and print a message.
951 + Returns '1' if there was a CRC error, '0' otherwise. */
952 +int /* PRIVATE */
953 +png_crc_finish(png_structp png_ptr, png_uint_32 skip)
954 +{
955 + png_size_t i;
956 + png_size_t istop = png_ptr->zbuf_size;
957 +
958 + for (i = (png_size_t)skip; i > istop; i -= istop)
959 + {
960 + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
961 + }
962 + if (i)
963 + {
964 + png_crc_read(png_ptr, png_ptr->zbuf, i);
965 + }
966 +
967 + if (png_crc_error(png_ptr))
968 + {
969 + if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
970 + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
971 + (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
972 + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
973 + {
974 + png_chunk_warning(png_ptr, "CRC error");
975 + }
976 + else
977 + {
978 + png_chunk_error(png_ptr, "CRC error");
979 + }
980 + return (1);
981 + }
982 +
983 + return (0);
984 +}
985 +
986 +/* Modify the info structure to reflect the transformations. The
987 + * info should be updated so a PNG file could be written with it,
988 + * assuming the transformations result in valid PNG data.
989 + */
990 +void /* PRIVATE */
991 +png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
992 +{
993 + png_debug(1, "in png_read_transform_info\n");
994 +#if defined(PNG_READ_EXPAND_SUPPORTED)
995 + if (png_ptr->transformations & PNG_EXPAND)
996 + {
997 + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
998 + {
999 + if (png_ptr->num_trans)
1000 + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1001 + else
1002 + info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1003 + info_ptr->bit_depth = 8;
1004 + info_ptr->num_trans = 0;
1005 + }
1006 + else
1007 + {
1008 + if (png_ptr->num_trans)
1009 + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1010 + if (info_ptr->bit_depth < 8)
1011 + info_ptr->bit_depth = 8;
1012 + info_ptr->num_trans = 0;
1013 + }
1014 + }
1015 +#endif
1016 +
1017 +#if defined(PNG_READ_BACKGROUND_SUPPORTED)
1018 + if (png_ptr->transformations & PNG_BACKGROUND)
1019 + {
1020 + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1021 + info_ptr->num_trans = 0;
1022 + info_ptr->background = png_ptr->background;
1023 + }
1024 +#endif
1025 +
1026 +#if defined(PNG_READ_GAMMA_SUPPORTED)
1027 + if (png_ptr->transformations & PNG_GAMMA)
1028 + {
1029 +#ifdef PNG_FLOATING_POINT_SUPPORTED
1030 + info_ptr->gamma = png_ptr->gamma;
1031 +#endif
1032 +#ifdef PNG_FIXED_POINT_SUPPORTED
1033 + info_ptr->int_gamma = png_ptr->int_gamma;
1034 +#endif
1035 + }
1036 +#endif
1037 +
1038 +#if defined(PNG_READ_16_TO_8_SUPPORTED)
1039 + if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
1040 + info_ptr->bit_depth = 8;
1041 +#endif
1042 +
1043 +#if defined(PNG_READ_DITHER_SUPPORTED)
1044 + if (png_ptr->transformations & PNG_DITHER)
1045 + {
1046 + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1047 + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1048 + png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1049 + {
1050 + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1051 + }
1052 + }
1053 +#endif
1054 +
1055 +#if defined(PNG_READ_PACK_SUPPORTED)
1056 + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
1057 + info_ptr->bit_depth = 8;
1058 +#endif
1059 +
1060 +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1061 + if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1062 + info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1063 +#endif
1064 +
1065 +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1066 + if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1067 + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1068 +#endif
1069 +
1070 + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1071 + info_ptr->channels = 1;
1072 + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1073 + info_ptr->channels = 3;
1074 + else
1075 + info_ptr->channels = 1;
1076 +
1077 +#ifndef PNG_FLAG_ADD_ALPHA
1078 +#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */
1079 +#endif
1080 +#ifndef PNG_FLAG_STRIP_ALPHA
1081 +#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */
1082 +#endif
1083 +#ifndef PNG_ADD_ALPHA
1084 +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */
1085 +#endif
1086 +
1087 +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1088 + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1089 + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1090 +#endif
1091 +
1092 + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1093 + info_ptr->channels++;
1094 +
1095 +#if defined(PNG_READ_FILLER_SUPPORTED)
1096 + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
1097 + if ((png_ptr->transformations & PNG_FILLER) &&
1098 + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1099 + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1100 + {
1101 + info_ptr->channels++;
1102 + /* if adding a true alpha channel not just filler */
1103 +#if !defined(PNG_1_0_X)
1104 + if (png_ptr->transformations & PNG_ADD_ALPHA)
1105 + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1106 +#endif
1107 + }
1108 +#endif
1109 +
1110 +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1111 +defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1112 + if(png_ptr->transformations & PNG_USER_TRANSFORM)
1113 + {
1114 + if(info_ptr->bit_depth < png_ptr->user_transform_depth)
1115 + info_ptr->bit_depth = png_ptr->user_transform_depth;
1116 + if(info_ptr->channels < png_ptr->user_transform_channels)
1117 + info_ptr->channels = png_ptr->user_transform_channels;
1118 + }
1119 +#endif
1120 +
1121 + info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1122 + info_ptr->bit_depth);
1123 +
1124 +#ifndef PNG_ROWBYTES
1125 +/* Added to libpng-1.2.6 JB */
1126 +#define PNG_ROWBYTES(pixel_bits, width) \
1127 + ((pixel_bits) >= 8 ? \
1128 + ((width) * (((png_uint_32)(pixel_bits)) >> 3)) : \
1129 + (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) )
1130 +#endif
1131 + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width);
1132 +
1133 +#if !defined(PNG_READ_EXPAND_SUPPORTED)
1134 + if(png_ptr)
1135 + return;
1136 +#endif
1137 +}
1138 +
1139 +#if !defined(PNG_NO_STDIO)
1140 +/* This is the function that does the actual reading of data. If you are
1141 + not reading from a standard C stream, you should create a replacement
1142 + read_data function and use it at run time with png_set_read_fn(), rather
1143 + than changing the library. */
1144 +#ifndef USE_FAR_KEYWORD
1145 +void PNGAPI
1146 +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
1147 +{
1148 + png_size_t check;
1149 +
1150 + /* fread() returns 0 on error, so it is OK to store this in a png_size_t
1151 + * instead of an int, which is what fread() actually returns.
1152 + */
1153 +#if defined(_WIN32_WCE)
1154 + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
1155 + check = 0;
1156 +#else
1157 + check = (png_size_t)fread(data, (png_size_t)1, length,
1158 + (png_FILE_p)png_ptr->io_ptr);
1159 +#endif
1160 +
1161 + if (check != length)
1162 + png_error(png_ptr, "Read Error");
1163 +}
1164 +#else
1165 +/* this is the model-independent version. Since the standard I/O library
1166 + can't handle far buffers in the medium and small models, we have to copy
1167 + the data.
1168 +*/
1169 +
1170 +#define NEAR_BUF_SIZE 1024
1171 +#define MIN(a,b) (a <= b ? a : b)
1172 +
1173 +static void /* PRIVATE */
1174 +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
1175 +{
1176 + int check;
1177 + png_byte *n_data;
1178 + png_FILE_p io_ptr;
1179 +
1180 + /* Check if data really is near. If so, use usual code. */
1181 + n_data = (png_byte *)CVT_PTR_NOCHECK(data);
1182 + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
1183 + if ((png_bytep)n_data == data)
1184 + {
1185 +#if defined(_WIN32_WCE)
1186 + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
1187 + check = 0;
1188 +#else
1189 + check = fread(n_data, 1, length, io_ptr);
1190 +#endif
1191 + }
1192 + else
1193 + {
1194 + png_byte buf[NEAR_BUF_SIZE];
1195 + png_size_t read, remaining, err;
1196 + check = 0;
1197 + remaining = length;
1198 + do
1199 + {
1200 + read = MIN(NEAR_BUF_SIZE, remaining);
1201 +#if defined(_WIN32_WCE)
1202 + if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) )
1203 + err = 0;
1204 +#else
1205 + err = fread(buf, (png_size_t)1, read, io_ptr);
1206 +#endif
1207 + png_memcpy(data, buf, read); /* copy far buffer to near buffer */
1208 + if(err != read)
1209 + break;
1210 + else
1211 + check += err;
1212 + data += read;
1213 + remaining -= read;
1214 + }
1215 + while (remaining != 0);
1216 + }
1217 + if ((png_uint_32)check != (png_uint_32)length)
1218 + png_error(png_ptr, "read Error");
1219 +}
1220 +#endif
1221 +#endif
1222 +#if !defined(PNG_NO_STDIO)
1223 +/* This is the function that does the actual writing of data. If you are
1224 + not writing to a standard C stream, you should create a replacement
1225 + write_data function and use it at run time with png_set_write_fn(), rather
1226 + than changing the library. */
1227 +#ifndef USE_FAR_KEYWORD
1228 +void PNGAPI
1229 +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
1230 +{
1231 + png_uint_32 check;
1232 +
1233 +#if defined(_WIN32_WCE)
1234 + if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
1235 + check = 0;
1236 +#else
1237 + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
1238 +#endif
1239 + if (check != length)
1240 + png_error(png_ptr, "Write Error");
1241 +}
1242 +#else
1243 +/* this is the model-independent version. Since the standard I/O library
1244 + can't handle far buffers in the medium and small models, we have to copy
1245 + the data.
1246 +*/
1247 +
1248 +#define NEAR_BUF_SIZE 1024
1249 +#define MIN(a,b) (a <= b ? a : b)
1250 +
1251 +void PNGAPI
1252 +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
1253 +{
1254 + png_uint_32 check;
1255 + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
1256 + png_FILE_p io_ptr;
1257 +
1258 + /* Check if data really is near. If so, use usual code. */
1259 + near_data = (png_byte *)CVT_PTR_NOCHECK(data);
1260 + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
1261 + if ((png_bytep)near_data == data)
1262 + {
1263 +#if defined(_WIN32_WCE)
1264 + if ( !WriteFile(io_ptr, near_data, length, &check, NULL) )
1265 + check = 0;
1266 +#else
1267 + check = fwrite(near_data, 1, length, io_ptr);
1268 +#endif
1269 + }
1270 + else
1271 + {
1272 + png_byte buf[NEAR_BUF_SIZE];
1273 + png_size_t written, remaining, err;
1274 + check = 0;
1275 + remaining = length;
1276 + do
1277 + {
1278 + written = MIN(NEAR_BUF_SIZE, remaining);
1279 + png_memcpy(buf, data, written); /* copy far buffer to near buffer */
1280 +#if defined(_WIN32_WCE)
1281 + if ( !WriteFile(io_ptr, buf, written, &err, NULL) )
1282 + err = 0;
1283 +#else
1284 + err = fwrite(buf, 1, written, io_ptr);
1285 +#endif
1286 + if (err != written)
1287 + break;
1288 + else
1289 + check += err;
1290 + data += written;
1291 + remaining -= written;
1292 + }
1293 + while (remaining != 0);
1294 + }
1295 + if (check != length)
1296 + png_error(png_ptr, "Write Error");
1297 +}
1298 +
1299 +#endif
1300 +#endif
1301 +
1302 +#endif /* !defined(PNGCRUSH_H) */
1303 +
1304 +
1305 +
1306 +/* cexcept interface */
1307 +
1308 +static void png_cexcept_error(png_structp png_ptr, png_const_charp msg)
1309 +{
1310 + if (png_ptr);
1311 +#if (defined(PNGCRUSH_H))
1312 + if (!strcmp(msg, "Too many IDAT's found")) {
1313 +#ifndef PNG_NO_CONSOLE_IO
1314 + fprintf(stderr, "\nIn %s, correcting ", inname);
1315 +#else
1316 + png_warning(png_ptr, msg);
1317 +#endif
1318 + } else
1319 +#endif /* defined(PNGCRUSH_H) */
1320 + {
1321 + Throw msg;
1322 + }
1323 +}
1324 +
1325 +
1326 +
1327 +
1328 +/* START of code to validate memory allocation and deallocation */
1329 +#ifdef PNG_USER_MEM_SUPPORTED
1330 +
1331 +/* Allocate memory. For reasonable files, size should never exceed
1332 + 64K. However, zlib may allocate more then 64K if you don't tell
1333 + it not to. See zconf.h and png.h for more information. zlib does
1334 + need to allocate exactly 64K, so whatever you call here must
1335 + have the ability to do that.
1336 +
1337 + This piece of code can be compiled to validate max 64K allocations
1338 + by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. */
1339 +typedef struct memory_information {
1340 + png_uint_32 size;
1341 + png_voidp pointer;
1342 + struct memory_information FAR *next;
1343 +} memory_information;
1344 +typedef memory_information FAR *memory_infop;
1345 +
1346 +static memory_infop pinformation = NULL;
1347 +static int current_allocation = 0;
1348 +static int maximum_allocation = 0;
1349 +
1350 +
1351 +
1352 +
1353 +png_voidp png_debug_malloc(png_structp png_ptr, png_uint_32 size)
1354 +{
1355 +
1356 + /* png_malloc has already tested for NULL; png_create_struct calls
1357 + png_debug_malloc directly (with png_ptr == NULL prior to libpng-1.2.0
1358 + which is OK since we are not using a user mem_ptr) */
1359 +
1360 + if (size == 0)
1361 + return (png_voidp) (NULL);
1362 +
1363 + /* This calls the library allocator twice, once to get the requested
1364 + buffer and once to get a new free list entry. */
1365 + {
1366 + memory_infop pinfo = png_malloc_default(png_ptr, sizeof *pinfo);
1367 + pinfo->size = size;
1368 + current_allocation += size;
1369 + if (current_allocation > maximum_allocation)
1370 + maximum_allocation = current_allocation;
1371 + pinfo->pointer = png_malloc_default(png_ptr, size);
1372 + pinfo->next = pinformation;
1373 + pinformation = pinfo;
1374 + /* Make sure the caller isn't assuming zeroed memory. */
1375 + png_memset(pinfo->pointer, 0xdd, pinfo->size);
1376 + if (verbose > 2)
1377 + fprintf(STDERR, "Pointer %lux allocated %lu bytes\n",
1378 + (unsigned long) pinfo->pointer, (unsigned long)size);
1379 + return (png_voidp) (pinfo->pointer);
1380 + }
1381 +}
1382 +
1383 +
1384 +
1385 +
1386 +/* Free a pointer. It is removed from the list at the same time. */
1387 +void png_debug_free(png_structp png_ptr, png_voidp ptr)
1388 +{
1389 + if (png_ptr == NULL)
1390 + fprintf(STDERR, "NULL pointer to png_debug_free.\n");
1391 + if (ptr == 0) {
1392 +#if 0 /* This happens all the time. */
1393 + fprintf(STDERR, "WARNING: freeing NULL pointer\n");
1394 +#endif
1395 + return;
1396 + }
1397 +
1398 + /* Unlink the element from the list. */
1399 + {
1400 + memory_infop FAR *ppinfo = &pinformation;
1401 + for (;;) {
1402 + memory_infop pinfo = *ppinfo;
1403 + if (pinfo->pointer == ptr) {
1404 + *ppinfo = pinfo->next;
1405 + current_allocation -= pinfo->size;
1406 + if (current_allocation < 0)
1407 + fprintf(STDERR, "Duplicate free of memory\n");
1408 + /* We must free the list element too, but first kill
1409 + the memory that is to be freed. */
1410 + memset(ptr, 0x55, pinfo->size);
1411 + if (verbose > 2)
1412 + fprintf(STDERR, "Pointer %lux freed %lu bytes\n",
1413 + (unsigned long) ptr, (unsigned long)pinfo->size);
1414 + png_free_default(png_ptr, pinfo);
1415 + break;
1416 + }
1417 + if (pinfo->next == NULL) {
1418 + fprintf(STDERR, "Pointer %lux not found\n",
1419 + (unsigned long) ptr);
1420 + break;
1421 + }
1422 + ppinfo = &pinfo->next;
1423 + }
1424 + }
1425 +
1426 + /* Finally free the data. */
1427 + png_free_default(png_ptr, ptr);
1428 +}
1429 +
1430 +#endif /* PNG_USER_MEM_SUPPORTED */
1431 +/* END of code to test memory allocation/deallocation */
1432 +
1433 +
1434 +
1435 +
1436 +void png_crush_pause(void)
1437 +{
1438 + if (pauses > 0) {
1439 + char keystroke;
1440 + fprintf(STDERR, "Press [ENTER] key to continue.\n");
1441 + keystroke = (char) getc(stdin);
1442 + keystroke = keystroke; /* stifle compiler warning */
1443 + }
1444 +}
1445 +
1446 +
1447 +
1448 +
1449 +#ifndef __riscos
1450 +# define setfiletype(x)
1451 +
1452 +#else /* defined(__riscos) */
1453 +# include <kernel.h>
1454 +
1455 +/* The riscos/acorn support was contributed by Darren Salt. */
1456 +static int fileexists(const char *name)
1457 +{
1458 +# ifdef __acorn
1459 + int ret;
1460 + return _swix(8, 3 | 1 << 31, 17, name, &ret) ? 0 : ret;
1461 +# else
1462 + _kernel_swi_regs r;
1463 + r.r[0] = 17;
1464 + r.r[1] = (int) name;
1465 + return _kernel_swi(8, &r, &r) ? 0 : r.r[0];
1466 +# endif
1467 +}
1468 +
1469 +
1470 +static int filesize(const char *name)
1471 +{
1472 +# ifdef __acorn
1473 + int ret;
1474 + return _swix(8, 3 | 1 << 27, 17, name, &ret) ? 0 : ret;
1475 +# else
1476 + _kernel_swi_regs r;
1477 + r.r[0] = 17;
1478 + r.r[1] = (int) name;
1479 + return _kernel_swi(8, &r, &r) ? 0 : r.r[4];
1480 +# endif
1481 +}
1482 +
1483 +
1484 +static int mkdir(const char *name, int ignored)
1485 +{
1486 +# ifdef __acorn
1487 + _swi(8, 0x13, 8, name, 0);
1488 + return 0;
1489 +# else
1490 + _kernel_swi_regs r;
1491 + r.r[0] = 8;
1492 + r.r[1] = (int) name;
1493 + r.r[4] = r.r[3] = r.r[2] = 0;
1494 + return (int) _kernel_swi(8 | 1 << 31, &r, &r);
1495 +# endif
1496 +}
1497 +
1498 +
1499 +static void setfiletype(const char *name)
1500 +{
1501 +# ifdef __acorn
1502 + _swi(8, 7, 18, name, 0xB60);
1503 +# else
1504 + _kernel_swi_regs r;
1505 + r.r[0] = 18;
1506 + r.r[1] = (int) name;
1507 + r.r[2] = 0xB60;
1508 + _kernel_swi(8 | 1 << 31, &r, &r);
1509 +# endif
1510 +}
1511 +
1512 +#endif /* ?defined(__riscos) */
1513 +
1514 +
1515 +
1516 +
1517 +/* GRR: basically boolean; first arg is chunk name-string (e.g., "tIME" or
1518 + * "alla"); second is always full argv[] command line
1519 + * - remove_chunks is argv index of *last* -rem arg on command line
1520 + * (would be more efficient to build table at time of cmdline processing!)
1521 + * (i.e., build removal_list with names or unique IDs or whatever--skip
1522 + * excessive string-processing on every single one)
1523 + * - reprocesses command line _every_ time called, looking for -rem opts...
1524 + * - just like keep_chunk() except that latter sets things_have_changed
1525 + * variable and debug stmts say "Removed chunk" (but caller actually does
1526 + * so, by choosing not to copy chunk to new file)
1527 + * - for any given chunk name, "name" must either match exact command-line
1528 + * arg (e.g., -rem fOOb), OR it must match one of the official PNG chunk
1529 + * names explicitly listed below AND command-line arg either used all-
1530 + * lowercase form or one of "all[ab]" options
1531 + */
1532 +int keep_unknown_chunk(png_const_charp name, char *argv[])
1533 +{
1534 + int i;
1535 + if (remove_chunks == 0)
1536 + return 1; /* no -rem options, so always keeping */
1537 + for (i = 1; i <= remove_chunks; i++) {
1538 + if (!strncmp(argv[i], "-rem", 4)) {
1539 + int allb = 0;
1540 + i++;
1541 + if (!strncmp(argv[i], "all", 3)) {
1542 + allb++; /* all but gamma, but not doing gamma here */
1543 + }
1544 + if (!strncmp(argv[i], name, 4) /* exact chunk-name match in args */
1545 + /* ...or exact match for one of known set, plus args included
1546 + * either "alla", "allb", or all-lowercase form of "name" */
1547 + || (!strncmp(name, "cHRM", 4)
1548 + && (!strncmp(argv[i], "chrm", 4) || allb))
1549 + || (!strncmp(name, "dSIG", 4)
1550 + && (!strncmp(argv[i], "dsig", 4) || allb))
1551 + || (!strncmp(name, "gIFg", 4)
1552 + && (!strncmp(argv[i], "gifg", 4) || allb))
1553 + || (!strncmp(name, "gIFt", 4)
1554 + && (!strncmp(argv[i], "gift", 4) || allb))
1555 + || (!strncmp(name, "gIFx", 4)
1556 + && (!strncmp(argv[i], "gifx", 4) || allb))
1557 + || (!strncmp(name, "hIST", 4)
1558 + && (!strncmp(argv[i], "hist", 4) || allb))
1559 + || (!strncmp(name, "iCCP", 4)
1560 + && (!strncmp(argv[i], "iccp", 4) || allb))
1561 + || (!strncmp(name, "pCAL", 4)
1562 + && (!strncmp(argv[i], "pcal", 4) || allb))
1563 + || (!strncmp(name, "sCAL", 4)
1564 + && (!strncmp(argv[i], "scal", 4) || allb))
1565 + || (!strncmp(name, "sPLT", 4)
1566 + && (!strncmp(argv[i], "splt", 4) || allb))
1567 + || (!strncmp(name, "tIME", 4)
1568 + && (!strncmp(argv[i], "time", 4) || allb)))
1569 + {
1570 + return 0;
1571 + }
1572 + }
1573 + }
1574 + return 1;
1575 +}
1576 +
1577 +
1578 +
1579 +
1580 +int keep_chunk(png_const_charp name, char *argv[])
1581 +{
1582 + int i;
1583 + if (verbose > 2 && first_trial)
1584 + fprintf(STDERR, " Read the %s chunk.\n", name);
1585 + if (remove_chunks == 0)
1586 + return 1;
1587 + if (verbose > 1 && first_trial)
1588 + fprintf(STDERR, " Check for removal of the %s chunk.\n", name);
1589 + for (i = 1; i <= remove_chunks; i++) {
1590 + if (!strncmp(argv[i], "-rem", 4)) {
1591 + int alla = 0;
1592 + int allb = 0;
1593 + int allt = 0;
1594 + i++;
1595 + if (!strncmp(argv[i], "all", 3)) {
1596 + allt++; /* all forms of text chunk are ancillary */
1597 + allb++; /* all ancillaries but gamma... */
1598 + if (!strncmp(argv[i], "alla", 4))
1599 + alla++; /* ...no, all ancillaries, period */
1600 + } else if (!strncmp(argv[i], "text", 4))
1601 + allt++; /* all forms of text chunk */
1602 + if (!strncmp(argv[i], name, 4) /* exact chunk-name match in args
1603 + * ...or exact match for one of known set, plus args included
1604 + * either "alla", "allb", or all-lowercase form of "name": */
1605 + || (!strncmp(name, "PLTE", 4)
1606 + && (!strncmp(argv[i], "plte", 4) ))
1607 + || (!strncmp(name, "bKGD", 4)
1608 + && (!strncmp(argv[i], "bkgd", 4) || allb))
1609 + || (!strncmp(name, "cHRM", 4)
1610 + && (!strncmp(argv[i], "chrm", 4) || allb))
1611 + || (!strncmp(name, "dSIG", 4)
1612 + && (!strncmp(argv[i], "dsig", 4) || allb))
1613 + || (!strncmp(name, "gAMA", 4)
1614 + && (!strncmp(argv[i], "gama", 4) || alla))
1615 + || (!strncmp(name, "gIFg", 4)
1616 + && (!strncmp(argv[i], "gifg", 4) || allb))
1617 + || (!strncmp(name, "gIFt", 4)
1618 + && (!strncmp(argv[i], "gift", 4) || allb))
1619 + || (!strncmp(name, "gIFx", 4)
1620 + && (!strncmp(argv[i], "gifx", 4) || allb))
1621 + || (!strncmp(name, "hIST", 4)
1622 + && (!strncmp(argv[i], "hist", 4) || allb))
1623 + || (!strncmp(name, "iCCP", 4)
1624 + && (!strncmp(argv[i], "iccp", 4) || allb))
1625 + || (!strncmp(name, "iTXt", 4)
1626 + && (!strncmp(argv[i], "itxt", 4) || allt))
1627 + || (!strncmp(name, "oFFs", 4)
1628 + && (!strncmp(argv[i], "offs", 4) || allb))
1629 + || (!strncmp(name, "pHYs", 4)
1630 + && (!strncmp(argv[i], "phys", 4) || allb))
1631 + || (!strncmp(name, "pCAL", 4)
1632 + && (!strncmp(argv[i], "pcal", 4) || allb))
1633 + || (!strncmp(name, "sBIT", 4)
1634 + && (!strncmp(argv[i], "sbit", 4) || allb))
1635 + || (!strncmp(name, "sCAL", 4)
1636 + && (!strncmp(argv[i], "scal", 4) || allb))
1637 + || (!strncmp(name, "sRGB", 4)
1638 + && (!strncmp(argv[i], "srgb", 4) || allb))
1639 + || (!strncmp(name, "sPLT", 4)
1640 + && (!strncmp(argv[i], "splt", 4) || allb))
1641 + || (!strncmp(name, "tEXt", 4)
1642 + && ( allt))
1643 + || (!strncmp(name, "tIME", 4)
1644 + && (!strncmp(argv[i], "time", 4) || allb))
1645 + || (!strncmp(name, "tRNS", 4)
1646 + && (!strncmp(argv[i], "trns", 4) ))
1647 + || (!strncmp(name, "zTXt", 4)
1648 + && (!strncmp(argv[i], "ztxt", 4) || allt)) )
1649 + {
1650 + things_have_changed = 1;
1651 + /* (caller actually does the removal--by failing to create
1652 + * copy) */
1653 + if (verbose > 0 && first_trial)
1654 + fprintf(STDERR, " Removed the %s chunk.\n", name);
1655 + return 0;
1656 + }
1657 + }
1658 + }
1659 + if (verbose > 1 && first_trial)
1660 + fprintf(STDERR, " Preserving the %s chunk.\n", name);
1661 + return 1;
1662 +}
1663 +
1664 +
1665 +
1666 +
1667 +void show_result(void)
1668 +{
1669 + if (total_output_length) {
1670 + if (total_input_length == total_output_length)
1671 + fprintf(STDERR, " Overall result: no change\n");
1672 + else if (total_input_length > total_output_length)
1673 + fprintf(STDERR,
1674 + " Overall result: %4.2f%% reduction, %lu bytes\n",
1675 + (100.0 -
1676 + (100.0 * total_output_length) / total_input_length),
1677 + (unsigned long)(total_input_length-total_output_length));
1678 + else
1679 + fprintf(STDERR,
1680 + " Overall result: %4.2f%% increase, %lu bytes\n",
1681 + -(100.0 -
1682 + (100.0 * total_output_length) / total_input_length),
1683 + (unsigned long)(total_output_length - total_input_length));
1684 + }
1685 + t_stop = (TIME_T) clock();
1686 + t_misc += (t_stop - t_start);
1687 + if (t_stop < t_start) {
1688 + t_misc += PNG_UINT_31_MAX;
1689 + if (t_stop < 0)
1690 + t_misc += PNG_UINT_31_MAX;
1691 + }
1692 + t_start = t_stop;
1693 + fprintf(STDERR, " CPU time used = %.3f seconds",
1694 + (t_misc + t_decode + t_encode) / (float) CLOCKS_PER_SEC);
1695 + fprintf(STDERR, " (decoding %.3f,\n",
1696 + t_decode / (float) CLOCKS_PER_SEC);
1697 + fprintf(STDERR, " encoding %.3f,",
1698 + t_encode / (float) CLOCKS_PER_SEC);
1699 + fprintf(STDERR, " other %.3f seconds)\n\n",
1700 + t_misc / (float) CLOCKS_PER_SEC);
1701 +#ifdef PNG_USER_MEM_SUPPORTED
1702 + if (current_allocation) {
1703 + memory_infop pinfo = pinformation;
1704 + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
1705 + current_allocation);
1706 + while (pinfo != NULL) {
1707 + fprintf(STDERR, " %8lu bytes at %lux\n", (unsigned long)pinfo->size,
1708 + (unsigned long) pinfo->pointer);
1709 + free(pinfo->pointer);
1710 + pinfo = pinfo->next;
1711 + }
1712 + }
1713 +#endif
1714 +}
1715 +
1716 +
1717 +
1718 +
1719 +int main(int argc, char *argv[])
1720 +{
1721 + png_uint_32 y;
1722 + int bit_depth, color_type;
1723 + int num_pass, pass;
1724 + int num_methods;
1725 + int try_method[MAX_METHODSP1];
1726 + int fm[MAX_METHODSP1];
1727 + int lv[MAX_METHODSP1];
1728 + int zs[MAX_METHODSP1];
1729 + int lev, strat, filt;
1730 +#ifdef PNG_gAMA_SUPPORTED
1731 +#ifdef PNG_FIXED_POINT_SUPPORTED
1732 + png_fixed_point file_gamma = 0;
1733 +#else
1734 + double file_gamma = 0.;
1735 +#endif
1736 +#endif
1737 + char *cp;
1738 + int i;
1739 + row_buf = (png_bytep) NULL;
1740 + number_of_open_files = 0;
1741 +#ifdef PNGCRUSH_COUNT_COLORS
1742 + reduce_to_gray = 0;
1743 + it_is_opaque = 0;
1744 +#else
1745 + do_color_count = 0;
1746 + do_color_count = do_color_count; /* silence compiler warning */
1747 +#endif
1748 +
1749 + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) {
1750 + fprintf(STDERR,
1751 + "Warning: versions are different between png.h and png.c\n");
1752 + fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING);
1753 + fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver);
1754 + }
1755 +
1756 + t_start = (TIME_T) clock();
1757 +
1758 + strncpy(prog_string, argv[0], STR_BUF_SIZE);
1759 + prog_string[STR_BUF_SIZE-1] = '\0';
1760 + progname = prog_string;
1761 + for (i = 0, cp = prog_string; *cp != '\0'; i++, cp++) {
1762 +#ifdef __riscos
1763 + if (*cp == '.' || *cp == ':')
1764 + progname = ++cp;
1765 +#else
1766 + if (*cp == '\\' || *cp == '/')
1767 + progname = ++cp;
1768 + if (*cp == '.')
1769 + *cp = '\0';
1770 +#endif
1771 + }
1772 +
1773 + /*
1774 + * Definition of methods ("canonical list" is methods 11 and up)
1775 + */
1776 + for (i = 0; i < MAX_METHODS; i++) {
1777 + try_method[i] = 1;
1778 + fm[i] = 5; lv[i] = 9; zs[i] = 1; /* default: method 124 */
1779 + }
1780 +
1781 + fm[1] = 0; lv[1] = 4; zs[1] = 0; /* method 1 == method 53 */
1782 + fm[2] = 1; lv[2] = 4; zs[2] = 0; /* method 2 == method 54 */
1783 + lv[3] = 4; /* method 3 == method 64 */
1784 + fm[4] = 0; /* method 4 == method 119 */
1785 + fm[5] = 1; zs[5] = 0; /* method 5 == method 114 */
1786 + zs[6] = 0; /* method 6 == method 118 */
1787 + fm[7] = 0; zs[7] = 0; /* method 7 == method 113 */
1788 + fm[8] = 1; /* method 8 == method 120 */
1789 + lv[9] = 2; zs[9] = 2; /* method 9 == method 16 */
1790 + /* method 10 == method 124 */
1791 +
1792 + /* methods 11 through 16 */
1793 + /* [strategy 2 (Z_HUFFMAN_ONLY) is independent of zlib compression level] */
1794 + method = 11;
1795 + for (filt = 0; filt <= 5; filt++) {
1796 + fm[method] = filt;
1797 + lv[method] = 2;
1798 + zs[method] = 2;
1799 + method++;
1800 + }
1801 +
1802 + /* methods 17 through 124 (9*2*6 = 108) */
1803 + for (lev = 1; lev <= 9; lev++) {
1804 + for (strat = 0; strat <= 1; strat++) {
1805 + for (filt = 0; filt <= 5; filt++) {
1806 + fm[method] = filt;
1807 + lv[method] = lev;
1808 + zs[method] = strat;
1809 + method++;
1810 + }
1811 + }
1812 + }
1813 +
1814 +#ifdef Z_RLE
1815 + /* methods 125 through 136 */
1816 + /* [strategy 3 (Z_RLE) is mostly independent of level; 1-3 and 4-9 are
1817 + * same] */
1818 + for (filt = 0; filt <= 5; filt++) {
1819 + fm[method] = filt;
1820 + lv[method] = 1;
1821 + zs[method] = 3;
1822 + method++;
1823 + }
1824 + for (filt = 0; filt <= 5; filt++) {
1825 + fm[method] = filt;
1826 + lv[method] = 4;
1827 + zs[method] = 3;
1828 + method++;
1829 + }
1830 +#endif /* Z_RLE */
1831 +
1832 + num_methods = method; /* GRR */
1833 +
1834 +
1835 +#define BUMP_I i++;if(i >= argc) {printf("insufficient parameters\n");exit(1);}
1836 + names = 1;
1837 +
1838 + /* ===================================================================== */
1839 + /* FIXME: move args-processing block into separate function (470 lines) */
1840 + for (i = 1; i < argc; i++) {
1841 + if (!strncmp(argv[i], "-", 1))
1842 + names++;
1843 +
1844 +
1845 + /* GRR: start of giant else-if block */
1846 + if (!strncmp(argv[i], "-fast", 5)) {
1847 + /* try two fast filters */
1848 + methods_specified = 1;
1849 + try_method[16] = 0;
1850 + try_method[53] = 0;
1851 + } else if (!strncmp(argv[i], "-huffman", 8)) {
1852 + /* try all filters with huffman */
1853 + methods_specified = 1;
1854 + for (method = 11; method <= 16; method++) {
1855 + try_method[method] = 0;
1856 + }
1857 +#ifdef Z_RLE
1858 + } else if (!strncmp(argv[i], "-rle", 4)) {
1859 + /* try all filters with RLE */
1860 + methods_specified = 1;
1861 + for (method = 125; method <= 136; method++) {
1862 + try_method[method] = 0;
1863 + }
1864 +#endif
1865 + }
1866 +
1867 + else if (!strncmp(argv[i], "-already", 8)) {
1868 + names++;
1869 + BUMP_I;
1870 + crushed_idat_size = (png_uint_32) atoi(argv[i]);
1871 + }
1872 +
1873 + else if (!strncmp(argv[i], "-bkgd", 5) ||
1874 + !strncmp(argv[i], "-bKGD", 5))
1875 + {
1876 + names += 3;
1877 + have_bkgd = 1;
1878 + bkgd_red = (png_uint_16) atoi(argv[++i]);
1879 + bkgd_green = (png_uint_16) atoi(argv[++i]);
1880 + bkgd_blue = (png_uint_16) atoi(argv[++i]);
1881 + }
1882 +
1883 + else if (!strncmp(argv[i], "-brute", 6))
1884 + /* brute force: try everything */
1885 + {
1886 + int lev, strat, filt;
1887 + methods_specified = 1;
1888 + brute_force++;
1889 + for (method = 11; method < num_methods; method++)
1890 + try_method[method] = 0;
1891 + if (brute_force_filter == 0)
1892 + for (filt = 0; filt < 6; filt++)
1893 + brute_force_filters[filt] = 0;
1894 + if (brute_force_level == 0)
1895 + for (lev = 0; lev < 10; lev++)
1896 + brute_force_levels[lev] = 0;
1897 + if (brute_force_strategy == 0)
1898 + for (strat = 0; strat < NUM_STRATEGIES; strat++)
1899 + brute_force_strategies[strat] = 0;
1900 + } else if (!strncmp(argv[i], "-bit_depth", 10)) {
1901 + names++;
1902 + BUMP_I;
1903 + force_output_bit_depth = atoi(argv[i]);
1904 + } else if (!strncmp(argv[i], "-cc", 3)) {
1905 + do_color_count = 1;
1906 + } else if (!strncmp(argv[i], "-no_cc", 6)) {
1907 + do_color_count = 0;
1908 + } else if (!strncmp(argv[i], "-c", 2)) {
1909 + names++;
1910 + BUMP_I;
1911 + force_output_color_type = atoi(argv[i]);
1912 + }
1913 +#ifdef PNG_gAMA_SUPPORTED
1914 + else if (!strncmp(argv[i], "-dou", 4)) {
1915 + double_gamma++;
1916 + found_gAMA=1;
1917 + global_things_have_changed = 1;
1918 + }
1919 +#endif
1920 + else if (!strncmp(argv[i], "-d", 2)) {
1921 + BUMP_I;
1922 + if (pngcrush_mode == EXTENSION_MODE)
1923 + pngcrush_mode = DIREX_MODE;
1924 + else
1925 + pngcrush_mode = DIRECTORY_MODE;
1926 + directory_name = argv[names++];
1927 + } else if (!strncmp(argv[i], "-exit", 5)) {
1928 + pngcrush_must_exit = 1;
1929 + } else if (!strncmp(argv[i], "-e", 2)) {
1930 + BUMP_I;
1931 + if (pngcrush_mode == DIRECTORY_MODE)
1932 + pngcrush_mode = DIREX_MODE;
1933 + else
1934 + pngcrush_mode = EXTENSION_MODE;
1935 + extension = argv[names++];
1936 + } else if (!strncmp(argv[i], "-force", 6)) {
1937 + global_things_have_changed = 1;
1938 + } else if (!strncmp(argv[i], "-fix", 4)) {
1939 + fix++;
1940 + } else if (!strncmp(argv[i], "-f", 2)) {
1941 + int specified_filter = atoi(argv[++i]);
1942 + int lev, strat, filt;
1943 + if (specified_filter > 5 || specified_filter < 0)
1944 + specified_filter = 5;
1945 + names++;
1946 + if (brute_force == 0)
1947 + fm[method] = specified_filter;
1948 + else {
1949 + for (filt = 0; filt < 6; filt++)
1950 + brute_force_filters[filt] = 1;
1951 + brute_force_filters[specified_filter] = 0;
1952 + method = 11;
1953 + for (filt = 0; filt < 6; filt++) {
1954 + try_method[method] = brute_force_filters[filt] |
1955 + brute_force_strategies[2];
1956 + method++;
1957 + }
1958 + for (lev = 1; lev < 10; lev++) {
1959 + for (strat = 0; strat < 2; strat++) {
1960 + for (filt = 0; filt < 6; filt++) {
1961 + try_method[method] = brute_force_levels[lev] |
1962 + brute_force_filters[filt] |
1963 + brute_force_strategies[strat];
1964 + method++;
1965 + }
1966 + }
1967 + }
1968 + brute_force_filter++;
1969 + }
1970 + } else if (!strncmp(argv[i], "-loco", 5)) {
1971 +#ifdef PNGCRUSH_LOCO
1972 + do_loco = 1;
1973 +#else
1974 + printf
1975 + ("Cannot do -loco because libpng was compiled without MNG features");
1976 +#endif
1977 + } else if (!strncmp(argv[i], "-l", 2)) {
1978 + int lev, strat, filt;
1979 + int specified_level = atoi(argv[++i]);
1980 + if (specified_level > 9 || specified_level < 0)
1981 + specified_level = 9;
1982 + names++;
1983 + if (brute_force == 0)
1984 + lv[method] = specified_level;
1985 + else {
1986 + if (brute_force_level == 0)
1987 + for (lev = 0; lev < 10; lev++)
1988 + brute_force_levels[lev] = 1;
1989 + brute_force_levels[specified_level] = 0;
1990 + method = 11;
1991 + for (filt = 0; filt < 6; filt++) {
1992 + lv[method] = specified_level;
1993 + method++;
1994 + }
1995 + for (lev = 1; lev < 10; lev++) {
1996 + for (strat = 0; strat < 2; strat++) {
1997 + for (filt = 0; filt < 6; filt++) {
1998 + try_method[method] = brute_force_levels[lev] |
1999 + brute_force_filters[filt] |
2000 + brute_force_strategies[strat];
2001 + method++;
2002 + }
2003 + }
2004 + }
2005 + brute_force_level++;
2006 + }
2007 + }
2008 +#ifdef PNG_gAMA_SUPPORTED
2009 + else if (!strncmp(argv[i], "-g", 2)) {
2010 + names++;
2011 + BUMP_I;
2012 + found_gAMA=1;
2013 + if (intent < 0) {
2014 +#ifdef PNG_FIXED_POINT_SUPPORTED
2015 + int c;
2016 + char number[16];
2017 + char *n = number;
2018 + int nzeroes = -1;
2019 + int length = strlen(argv[i]);
2020 + for (c = 0; c < length; c++) {
2021 + if (*(argv[i] + c) == '.') {
2022 + nzeroes = 5;
2023 + } else if (nzeroes) {
2024 + *n++ = *(argv[i] + c);
2025 + nzeroes--;
2026 + }
2027 + }
2028 + for (c = 0; c < nzeroes; c++)
2029 + *n++ = '0';
2030 + *n = '\0';
2031 + specified_gamma = atoi(number);
2032 +#else
2033 + specified_gamma = atof(argv[i]);
2034 +#endif
2035 + }
2036 + }
2037 +#endif /* PNG_gAMA_SUPPORTED */
2038 + else if (!strncmp(argv[i], "-h", 2)) {
2039 + ++verbose;
2040 + print_version_info();
2041 + print_usage(0); /* this exits */
2042 + }
2043 +#ifdef PNG_iCCP_SUPPORTED
2044 + else if (!strncmp(argv[i], "-iccp", 5)) {
2045 + FILE *iccp_fn;
2046 + if (iccp_length)
2047 + free(iccp_text);
2048 + iccp_length = atoi(argv[++i]);
2049 + names += 3;
2050 + strcpy(iccp_name, argv[++i]);
2051 + iccp_file = argv[++i];
2052 + if ((iccp_fn = FOPEN(iccp_file, "rb")) == NULL) {
2053 + fprintf(STDERR, "Could not find file: %s\n", iccp_file);
2054 + iccp_length = 0;
2055 + } else {
2056 + int ic;
2057 + iccp_text = malloc(iccp_length);
2058 + for (ic = 0; ic < iccp_length; ic++) {
2059 + png_size_t num_in;
2060 + num_in = fread(buffer, 1, 1, iccp_fn);
2061 + if (!num_in)
2062 + break;
2063 + iccp_text[ic] = buffer[0];
2064 + }
2065 + }
2066 + }
2067 +#endif
2068 + else if (!strncmp(argv[i], "-keep", 5)) {
2069 + names++;
2070 + BUMP_I;
2071 + if (!strncmp(argv[i], "dSIG", 4)
2072 + && (!strncmp(argv[i], "dsig", 4) ))
2073 + found_any_chunk=1;
2074 + }
2075 +
2076 + else if (!strncmp(argv[i], "-max", 4)) {
2077 + names++;
2078 + BUMP_I;
2079 + max_idat_size = (png_uint_32) atoi(argv[i]);
2080 + if (max_idat_size == 0 || max_idat_size > PNG_UINT_31_MAX)
2081 + max_idat_size = PNG_ZBUF_SIZE;
2082 +#ifdef PNGCRUSH_LOCO
2083 + } else if (!strncmp(argv[i], "-mng", 4)) {
2084 + names++;
2085 + BUMP_I;
2086 + mngname = argv[i];
2087 + new_mng++;
2088 +#endif
2089 + } else if (!strncmp(argv[i], "-m", 2)) {
2090 + names++;
2091 + BUMP_I;
2092 + method = atoi(argv[i]);
2093 + methods_specified = 1;
2094 + brute_force = 0;
2095 + try_method[method] = 0;
2096 + } else if (!strncmp(argv[i], "-nofilecheck", 5)) {
2097 + nofilecheck++;
2098 + } else if (!strncmp(argv[i], "-nosave", 2)) {
2099 + /* no save; I just use this for testing decode speed */
2100 + nosave++;
2101 + pngcrush_mode = EXTENSION_MODE;
2102 + } else if (!strncmp(argv[i], "-plte_len", 9)) {
2103 + names++;
2104 + BUMP_I;
2105 + plte_len = atoi(argv[i]);
2106 + } else if (!strncmp(argv[i], "-pplt", 3)) {
2107 + names++;
2108 + do_pplt++;
2109 + BUMP_I;
2110 + strcpy(pplt_string, argv[i]);
2111 + global_things_have_changed = 1;
2112 + } else if (!strncmp(argv[i], "-p", 2)) {
2113 + pauses++;
2114 + } else if (!strncmp(argv[i], "-q", 2)) {
2115 + verbose = 0;
2116 + } else if (!strncmp(argv[i], "-reduce", 7)) {
2117 + reduction_ok++;
2118 + do_color_count = 1;
2119 + }
2120 +#ifdef PNG_gAMA_SUPPORTED
2121 + else if (!strncmp(argv[i], "-rep", 4)) {
2122 + names++;
2123 + BUMP_I;
2124 + found_gAMA=1;
2125 + {
2126 +#ifdef PNG_FIXED_POINT_SUPPORTED
2127 + int c;
2128 + char number[16];
2129 + char *n = number;
2130 + int nzeroes = -1;
2131 + int length = strlen(argv[i]);
2132 + for (c = 0; c < length; c++) {
2133 + if (*(argv[i] + c) == '.') {
2134 + nzeroes = 5;
2135 + } else if (nzeroes) {
2136 + *n++ = *(argv[i] + c);
2137 + nzeroes--;
2138 + }
2139 + }
2140 + for (c = 0; c < nzeroes; c++)
2141 + *n++ = '0';
2142 + *n = '\0';
2143 + force_specified_gamma = atoi(number);
2144 +#else
2145 + force_specified_gamma = atof(argv[i]);
2146 +#endif
2147 + }
2148 + global_things_have_changed = 1;
2149 + }
2150 +#endif
2151 +#ifdef PNG_pHYs_SUPPORTED
2152 + else if (!strncmp(argv[i], "-res", 4)) {
2153 + names++;
2154 + BUMP_I;
2155 + resolution = atoi(argv[i]);
2156 + global_things_have_changed = 1;
2157 + }
2158 +#endif
2159 +#ifdef PNGCRUSH_MULTIPLE_ROWS
2160 + else if (!strncmp(argv[i], "-rows", 5)) {
2161 + names++;
2162 + BUMP_I;
2163 + max_rows_at_a_time = atoi(argv[i]);
2164 + }
2165 +#endif
2166 + else if (!strncmp(argv[i], "-r", 2)) {
2167 + remove_chunks = i;
2168 + names++;
2169 + BUMP_I;
2170 + if (!strncmp(argv[i], "dSIG", 4)
2171 + && (!strncmp(argv[i], "dsig", 4)))
2172 + image_is_immutable=0;
2173 + } else if (!strncmp(argv[i], "-save", 5)) {
2174 + all_chunks_are_safe++;
2175 + } else if (!strncmp(argv[i], "-srgb", 5) ||
2176 + !strncmp(argv[i], "-sRGB", 5)) {
2177 +#ifdef PNG_gAMA_SUPPORTED
2178 +#ifdef PNG_FIXED_POINT_SUPPORTED
2179 + specified_gamma = 45455L;
2180 +#else
2181 + specified_gamma = 0.45455;
2182 +#endif
2183 +#endif
2184 + intent = 0;
2185 + BUMP_I;
2186 + if (!strncmp(argv[i], "0", 1) ||
2187 + !strncmp(argv[i], "1", 1) ||
2188 + !strncmp(argv[i], "2", 1) || !strncmp(argv[i], "3", 1)) {
2189 + names++;
2190 + intent = (int) atoi(argv[i]);
2191 + } else
2192 + i--;
2193 + } else if (!strncmp(argv[i], "-s", 2)) {
2194 + verbose = 0;
2195 + } else if (!strncmp(argv[i], "-text", 5)
2196 + || !strncmp(argv[i], "-tEXt", 5) ||
2197 +#ifdef PNG_iTXt_SUPPORTED
2198 + !strncmp(argv[i], "-itxt", 5)
2199 + || !strncmp(argv[i], "-iTXt", 5)
2200 + || !strncmp(argv[i], "-zitxt", 6)
2201 + || !strncmp(argv[i], "-ziTXt", 6) ||
2202 +#endif
2203 + !strncmp(argv[i], "-ztxt", 5)
2204 + || !strncmp(argv[i], "-zTXt", 5))
2205 + {
2206 + i += 2;
2207 + BUMP_I;
2208 + i -= 3;
2209 + if (strlen(argv[i + 2]) < 180 && strlen(argv[i + 3]) < 2048 &&
2210 + text_inputs < 10) {
2211 +#ifdef PNG_iTXt_SUPPORTED
2212 + if (!strncmp(argv[i], "-zi", 3)) {
2213 + text_compression[text_inputs] =
2214 + PNG_ITXT_COMPRESSION_zTXt;
2215 + /* names += 2; */
2216 + } else
2217 +#endif
2218 + if (!strncmp(argv[i], "-z", 2))
2219 + text_compression[text_inputs] =
2220 + PNG_TEXT_COMPRESSION_zTXt;
2221 + else if (!strncmp(argv[i], "-t", 2))
2222 + text_compression[text_inputs] =
2223 + PNG_TEXT_COMPRESSION_NONE;
2224 +#ifdef PNG_iTXt_SUPPORTED
2225 + else {
2226 + text_compression[text_inputs] =
2227 + PNG_ITXT_COMPRESSION_NONE;
2228 + /* names += 2; */
2229 + }
2230 +#endif
2231 + names += 3;
2232 + if (!strncmp(argv[++i], "b", 1))
2233 + text_where[text_inputs] = 1;
2234 + if (!strncmp(argv[i], "a", 1))
2235 + text_where[text_inputs] = 2;
2236 + strcpy(&text_keyword[text_inputs * 80], argv[++i]);
2237 +#ifdef PNG_iTXt_SUPPORTED
2238 + if (text_compression[text_inputs] <= 0) {
2239 + text_lang[text_inputs * 80] = '\0';
2240 + text_lang_key[text_inputs * 80] = '\0';
2241 + } else {
2242 + i += 2;
2243 + BUMP_I;
2244 + i -= 3;
2245 + names += 2;
2246 + strcpy(&text_lang[text_inputs * 80], argv[++i]);
2247 + /* libpng-1.0.5j and later */
2248 + strcpy(&text_lang_key[text_inputs * 80], argv[++i]);
2249 + }
2250 +#endif
2251 + strcpy(&text_text[text_inputs * 2048], argv[++i]);
2252 + text_inputs++;
2253 + } else {
2254 + if (text_inputs > 9)
2255 + fprintf(STDERR,
2256 + "too many text/zTXt inputs; only 10 allowed\n");
2257 + else
2258 + fprintf(STDERR,
2259 + "keyword exceeds 79 characters or text exceeds 2047 characters\n");
2260 + i += 3;
2261 + names += 3;
2262 +#ifdef PNG_iTXt_SUPPORTED
2263 + if (!strncmp(argv[i], "-i", 2)
2264 + || !strncmp(argv[i], "-zi", 3)) {
2265 + i++;
2266 + BUMP_I;
2267 + names += 2;
2268 + }
2269 +#endif
2270 + }
2271 + }
2272 +#ifdef PNG_tRNS_SUPPORTED
2273 + else if (!strncmp(argv[i], "-trns_a", 7) ||
2274 + !strncmp(argv[i], "-tRNS_a", 7)) {
2275 + num_trans_in = (png_uint_16) atoi(argv[++i]);
2276 + trns_index=num_trans_in-1;
2277 + have_trns = 1;
2278 + for (ia = 0; ia < num_trans_in; ia++)
2279 + trans_in[ia] = (png_byte) atoi(argv[++i]);
2280 + names += 1 + num_trans_in;
2281 + } else if (!strncmp(argv[i], "-trns", 5) ||
2282 + !strncmp(argv[i], "-tRNS", 5)) {
2283 + names += 5;
2284 + have_trns = 1;
2285 + trns_index = (png_uint_16) atoi(argv[++i]);
2286 + trns_red = (png_uint_16) atoi(argv[++i]);
2287 + trns_green = (png_uint_16) atoi(argv[++i]);
2288 + trns_blue = (png_uint_16) atoi(argv[++i]);
2289 + trns_gray = (png_uint_16) atoi(argv[++i]);
2290 + }
2291 +#endif
2292 + else if (!strncmp(argv[i], "-version", 8)) {
2293 + fprintf(STDERR, " pngcrush ");
2294 + fprintf(STDERR, PNGCRUSH_VERSION);
2295 + fprintf(STDERR, ", uses libpng ");
2296 + fprintf(STDERR, PNG_LIBPNG_VER_STRING);
2297 + fprintf(STDERR, " and zlib ");
2298 + fprintf(STDERR, ZLIB_VERSION);
2299 + fprintf(STDERR, "\n Check http://pmt.sf.net/\n");
2300 + fprintf(STDERR, " for the most recent version.\n");
2301 + verbose = 0;
2302 + } else if (!strncmp(argv[i], "-v", 2)) {
2303 + verbose++;
2304 + } else if (!strncmp(argv[i], "-w", 2)) {
2305 + default_compression_window = atoi(argv[++i]);
2306 + force_compression_window++;
2307 + names++;
2308 + } else if (!strncmp(argv[i], "-zm", 3)) {
2309 + compression_mem_level = atoi(argv[++i]);
2310 + names++;
2311 + } else if (!strncmp(argv[i], "-z", 2)) {
2312 + int lev, strat, filt;
2313 + int specified_strategy = atoi(argv[++i]);
2314 + if (specified_strategy > 2 || specified_strategy < 0)
2315 + specified_strategy = 0;
2316 + names++;
2317 + if (brute_force == 0)
2318 + zs[method] = specified_strategy;
2319 + else {
2320 + if (brute_force_strategy == 0)
2321 + for (strat = 0; strat < 2; strat++)
2322 + brute_force_strategies[strat] = 1;
2323 + brute_force_strategies[specified_strategy] = 0;
2324 + method = 11;
2325 + for (filt = 0; filt < 6; filt++) {
2326 + if (specified_strategy != 2)
2327 + try_method[method] = 1;
2328 + method++;
2329 + }
2330 + for (lev = 1; lev < 10; lev++) {
2331 + for (strat = 0; strat < 2; strat++) {
2332 + for (filt = 0; filt < 6; filt++) {
2333 + try_method[method] = brute_force_levels[lev] |
2334 + brute_force_filters[filt] |
2335 + brute_force_strategies[strat];
2336 + method++;
2337 + }
2338 + }
2339 + }
2340 + }
2341 + brute_force_strategy++;
2342 + } /* GRR: end of giant if-else block */
2343 + } /* end of loop over args ============================================ */
2344 +
2345 +
2346 + if (verbose > 0)
2347 + print_version_info();
2348 +
2349 + if (default_compression_window == 32)
2350 + default_compression_window = 15;
2351 + else if (default_compression_window == 16)
2352 + default_compression_window = 14;
2353 + else if (default_compression_window == 8)
2354 + default_compression_window = 13;
2355 + else if (default_compression_window == 4)
2356 + default_compression_window = 12;
2357 + else if (default_compression_window == 2)
2358 + default_compression_window = 11;
2359 + else if (default_compression_window == 1)
2360 + default_compression_window = 10;
2361 + else if (default_compression_window == 512)
2362 + default_compression_window = 9;
2363 + /* Use of compression window size 256 is not recommended. */
2364 + else if (default_compression_window == 256)
2365 + default_compression_window = 8;
2366 + else if (default_compression_window != 15) {
2367 + fprintf(STDERR, "Invalid window size (%d); using window size=4\n",
2368 + default_compression_window);
2369 + default_compression_window = 12;
2370 + }
2371 +
2372 + if (pngcrush_mode == DEFAULT_MODE) {
2373 + if (argc - names == 2) {
2374 + inname = argv[names];
2375 + outname = argv[names + 1];
2376 + } else {
2377 + if ((argc - names == 1 || nosave)) {
2378 + inname = argv[names];
2379 + }
2380 + if (verbose && !nosave) {
2381 + print_usage(1); /* this exits */
2382 + }
2383 + }
2384 + }
2385 +
2386 + for (ia = 0; ia < 256; ia++)
2387 + trns_array[ia]=255;
2388 +
2389 + for (;;) /* loop on input files */
2390 + {
2391 + first_trial = 1;
2392 +
2393 + things_have_changed = global_things_have_changed;
2394 +
2395 + if (png_row_filters != NULL) {
2396 + free(png_row_filters);
2397 + png_row_filters = NULL;
2398 + }
2399 +
2400 + image_specified_gamma = 0;
2401 +
2402 + inname = argv[names++];
2403 +
2404 + if (inname == NULL) {
2405 + if (verbose > 0)
2406 + show_result();
2407 + break;
2408 + }
2409 +
2410 + if (pngcrush_mode == DIRECTORY_MODE || pngcrush_mode == DIREX_MODE) {
2411 + int inlen, outlen;
2412 +#ifndef __riscos
2413 + struct stat stat_buf;
2414 + if (stat(directory_name, &stat_buf))
2415 +#else
2416 + if (fileexists(directory_name) & 2)
2417 +#endif
2418 + {
2419 +#if defined(_MBCS) || defined(WIN32) || defined(__WIN32__)
2420 + if (_mkdir(directory_name))
2421 +#else
2422 + if (mkdir(directory_name, 0755))
2423 +#endif
2424 + {
2425 + fprintf(STDERR, "could not create directory %s\n",
2426 + directory_name);
2427 + exit(1);
2428 + }
2429 + nofilecheck = 1;
2430 + }
2431 + outlen = strlen(directory_name);
2432 + if (outlen >= STR_BUF_SIZE-1) {
2433 + fprintf(STDERR, "directory %s is too long for buffer\n",
2434 + directory_name);
2435 + exit(1);
2436 + }
2437 + strcpy(out_string, directory_name);
2438 + /*strcpy(out_string+outlen, SLASH); */
2439 + out_string[outlen++] = SLASH[0]; /* (assuming SLASH is 1 byte) */
2440 + out_string[outlen] = '\0';
2441 +
2442 + inlen = strlen(inname);
2443 + if (inlen >= STR_BUF_SIZE) {
2444 + fprintf(STDERR, "filename %s is too long for buffer\n", inname);
2445 + exit(1);
2446 + }
2447 + strcpy(in_string, inname);
2448 + in_string[inlen] = '\0';
2449 +#ifdef __riscos
2450 + op = strrchr(in_string, '.');
2451 + if (!op)
2452 + op = in_string;
2453 + else
2454 + op++;
2455 +#else
2456 + op = in_string;
2457 + ip = in_string + inlen - 1; /* start at last char in string */
2458 + while (ip > in_string) {
2459 + if (*ip == '\\' || *ip == '/') {
2460 + op = ip + 1;
2461 + break;
2462 + }
2463 + --ip;
2464 + }
2465 +#endif
2466 +
2467 + if (outlen + (inlen - (op - in_string)) >= STR_BUF_SIZE) {
2468 + fprintf(STDERR, "full path is too long for buffer\n");
2469 + exit(1);
2470 + }
2471 + strcpy(out_string+outlen, op);
2472 + /*outlen += inlen - (op - in_string); */
2473 + outname = out_string;
2474 + }
2475 +
2476 + /* FIXME: need same input-validation fixes (as above) here, too
2477 + * FIXME: what was the point of setting in_string and out_string in
2478 + * DIREX_MODE above if going to do all over again here? */
2479 + if (pngcrush_mode == EXTENSION_MODE || pngcrush_mode == DIREX_MODE) {
2480 + ip = in_string;
2481 + in_string[0] = '\0';
2482 + if (pngcrush_mode == EXTENSION_MODE)
2483 + strcat(in_string, inname);
2484 + else
2485 + strcat(in_string, outname);
2486 + ip = in_string;
2487 + op = dot = out_string;
2488 + while (*ip != '\0') {
2489 + *op++ = *ip++;
2490 +#ifdef __riscos
2491 + if (*ip == '/')
2492 + dot = op;
2493 +#else
2494 + if (*ip == '.')
2495 + dot = op;
2496 +#endif
2497 + }
2498 + *op = '\0';
2499 +
2500 + if (dot != out_string)
2501 + *dot = '\0';
2502 +
2503 + in_extension[0] = '\0';
2504 + if (dot != out_string) {
2505 + strcat(in_extension, ++dot);
2506 + }
2507 +
2508 + strcat(out_string, extension);
2509 + outname = out_string;
2510 + }
2511 +
2512 +
2513 + if (nosave < 2) {
2514 + P1( "Opening file %s for length measurement\n",
2515 + inname);
2516 +
2517 + if ((fpin = FOPEN(inname, "rb")) == NULL) {
2518 + fprintf(STDERR, "Could not find file: %s\n", inname);
2519 + continue;
2520 + }
2521 + number_of_open_files++;
2522 +
2523 + already_crushed = 0;
2524 +
2525 +#ifdef PNGCRUSH_LOCO
2526 + if (new_mng) {
2527 +
2528 +#ifdef PNG_USER_MEM_SUPPORTED
2529 + mng_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING,
2530 + (png_voidp) NULL, (png_error_ptr) png_cexcept_error,
2531 + (png_error_ptr) NULL, (png_voidp) NULL,
2532 + (png_malloc_ptr) png_debug_malloc,
2533 + (png_free_ptr) png_debug_free);
2534 +#else
2535 + mng_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
2536 + (png_voidp) NULL, (png_error_ptr) png_cexcept_error,
2537 + (png_error_ptr) NULL);
2538 +#endif
2539 + if (mng_ptr == NULL)
2540 + fprintf(STDERR, "pngcrush could not create mng_ptr");
2541 +
2542 + if ((mng_out = FOPEN(mngname, "wb")) == NULL) {
2543 + fprintf(STDERR, "Could not open output file %s\n",
2544 + mngname);
2545 + FCLOSE(fpin);
2546 + exit(1);
2547 + }
2548 + number_of_open_files++;
2549 + png_init_io(mng_ptr, mng_out);
2550 + png_set_write_fn(mng_ptr, (png_voidp) mng_out,
2551 + (png_rw_ptr) NULL,
2552 + NULL);
2553 +#endif
2554 +
2555 + }
2556 +
2557 + idat_length[0] = measure_idats(fpin);
2558 +
2559 +#ifdef PNGCRUSH_LOCO
2560 + if (new_mng) {
2561 + png_destroy_write_struct(&mng_ptr, NULL);
2562 + FCLOSE(mng_out);
2563 + }
2564 +#endif
2565 +
2566 + FCLOSE(fpin);
2567 +
2568 +
2569 + if (verbose > 0) {
2570 + fprintf(STDERR, " Recompressing %s\n", inname);
2571 + fprintf(STDERR,
2572 + " Total length of data found in IDAT chunks = %8lu\n",
2573 + (unsigned long)idat_length[0]);
2574 + fflush(STDERR);
2575 + }
2576 +
2577 + if (idat_length[0] == 0)
2578 + continue;
2579 +
2580 + } else
2581 + idat_length[0] = 1;
2582 +
2583 + if (already_crushed) {
2584 + fprintf(STDERR, " File %s has already been crushed.\n", inname);
2585 + }
2586 + if (image_is_immutable) {
2587 + fprintf(STDERR,
2588 + " Image %s has a dSIG chunk and is immutable.\n", inname);
2589 + }
2590 + if (!already_crushed && !image_is_immutable) {
2591 +#ifdef PNGCRUSH_COUNT_COLORS
2592 + reduce_to_gray = 0;
2593 + it_is_opaque = 0;
2594 + output_color_type = input_color_type;
2595 + if (do_color_count) {
2596 + if (force_output_color_type == 8 && (input_color_type == 2 ||
2597 + (input_color_type == 3) ||
2598 + input_color_type == 4
2599 + || input_color_type == 6))
2600 + /* check for unused alpha channel or single transparent color */
2601 + {
2602 + int alpha_status;
2603 + P1( "Opening file %s for alpha check\n", inname);
2604 +
2605 + if ((fpin = FOPEN(inname, "rb")) == NULL) {
2606 + fprintf(STDERR, "Could not find file: %s\n", inname);
2607 + continue;
2608 + }
2609 + number_of_open_files++;
2610 +
2611 + alpha_status = count_colors(fpin);
2612 + if (num_rgba < 257) {
2613 + P1("Finished counting colors. num_rgba=%d\n",
2614 + num_rgba);
2615 + } else {
2616 + P1("Finished counting colors. num_rgba is more than 256\n");
2617 + }
2618 + alpha_status = alpha_status; /* silence compiler warning. */
2619 +
2620 + FCLOSE(fpin);
2621 +
2622 + if (it_is_opaque) {
2623 + if (output_color_type == 4)
2624 + output_color_type = 0;
2625 + else if (output_color_type == 6)
2626 + output_color_type = 2;
2627 + }
2628 + if (reduce_to_gray) {
2629 + if (output_color_type == 2)
2630 + output_color_type = 0;
2631 + else if (output_color_type == 6)
2632 + output_color_type = 4;
2633 + }
2634 + }
2635 +#if 0 /* TO DO */
2636 + if (output_color_type == 0)
2637 + /* see if bit depth can be reduced */
2638 + {
2639 + }
2640 +
2641 + if (input_color_type == 2)
2642 + /* check for 256 or fewer colors */
2643 + {
2644 + /* TO DO */
2645 + }
2646 +
2647 + if (input_color_type == 3)
2648 + /* check for unused palette entries */
2649 + {
2650 + /* TO DO */
2651 + }
2652 +#endif
2653 + if (force_output_color_type == 8
2654 + && input_color_type != output_color_type) {
2655 + P1("setting output color type to %d\n", output_color_type);
2656 + force_output_color_type = output_color_type;
2657 + }
2658 + }
2659 +#else
2660 + if (do_color_count)
2661 + printf(" color counting (-cc option) is disabled.\n");
2662 +#endif /* PNGCRUSH_COUNT_COLORS */
2663 +
2664 + if (force_output_bit_depth != 0 &&
2665 + force_output_bit_depth != 1 &&
2666 + force_output_bit_depth != 2 &&
2667 + force_output_bit_depth != 4 &&
2668 + force_output_bit_depth != 8 &&
2669 + force_output_bit_depth != 16)
2670 + {
2671 + fprintf(STDERR, "\n Ignoring invalid bit_depth: %d\n",
2672 + force_output_bit_depth);
2673 + force_output_bit_depth=0;
2674 + }
2675 + if (force_output_color_type != 8 &&
2676 + force_output_color_type != 0 &&
2677 + force_output_color_type != 2 &&
2678 + force_output_color_type != 3 &&
2679 + force_output_color_type != 4 &&
2680 + force_output_color_type != 6)
2681 + {
2682 + fprintf(STDERR, "\n Ignoring invalid color_type: %d\n",
2683 + force_output_color_type);
2684 + force_output_color_type=8;
2685 + }
2686 + output_color_type = force_output_color_type;
2687 + output_bit_depth = force_output_bit_depth;
2688 +
2689 + if (!methods_specified || try_method[0] == 0) {
2690 + for (i = 1; i <= DEFAULT_METHODS; i++)
2691 + try_method[i] = 0;
2692 + try_method[6] = try_method[0];
2693 + }
2694 +
2695 + best_of_three = 1;
2696 +
2697 + /* ////////////////////////////////////////////////////////////////////
2698 + //////////////// ////////////////////
2699 + //////////////// START OF MAIN LOOP OVER METHODS ////////////////////
2700 + //////////////// ////////////////////
2701 + //////////////////////////////////////////////////////////////////// */
2702 +
2703 + /* MAX_METHODS is 200 */
2704 + P1("\n\nENTERING MAIN LOOP OVER %d METHODS\n", MAX_METHODS);
2705 + for (trial = 1; trial <= MAX_METHODS; trial++) {
2706 + idat_length[trial] = (png_uint_32) 0xffffffff;
2707 +
2708 + /* this part of if-block is for final write-the-best-file
2709 + iteration */
2710 + if (trial == MAX_METHODS) {
2711 + png_uint_32 best_length;
2712 + int j;
2713 +
2714 + /* check lengths */
2715 + best = 0; /* i.e., input file */
2716 + best_length = (png_uint_32) 0xffffffff;
2717 + for (j = things_have_changed; j < MAX_METHODS; j++) {
2718 + if (best_length > idat_length[j]) {
2719 + best_length = idat_length[j];
2720 + best = j;
2721 + }
2722 + }
2723 +
2724 + if (image_is_immutable
2725 + || (idat_length[best] == idat_length[0]
2726 + && things_have_changed == 0
2727 + && idat_length[best] != idat_length[final_method]
2728 + && nosave == 0))
2729 + {
2730 + /* just copy input to output */
2731 +
2732 + P2("prepare to copy input to output\n");
2733 + png_crush_pause();
2734 +
2735 + if ((fpin = FOPEN(inname, "rb")) == NULL) {
2736 + fprintf(STDERR, "Could not find input file %s\n",
2737 + inname);
2738 + continue;
2739 + }
2740 +
2741 + number_of_open_files++;
2742 + if ((fpout = FOPEN(outname, "wb")) == NULL) {
2743 + fprintf(STDERR, "Could not open output file %s\n",
2744 + outname);
2745 + FCLOSE(fpin);
2746 + exit(1);
2747 + }
2748 +
2749 + number_of_open_files++;
2750 + P2("copying input to output... tc=%d ...",
2751 + things_have_changed);
2752 +
2753 + for (;;) {
2754 + png_size_t num_in;
2755 +
2756 + num_in = fread(buffer, 1, 1, fpin);
2757 + if (!num_in)
2758 + break;
2759 + fwrite(buffer, 1, 1, fpout);
2760 + }
2761 + P2("copy complete.\n");
2762 + png_crush_pause();
2763 + FCLOSE(fpin);
2764 + FCLOSE(fpout);
2765 + setfiletype(outname);
2766 + break;
2767 + }
2768 +
2769 + if (idat_length[best] == idat_length[final_method]) {
2770 + break;
2771 + } else {
2772 + filter_type = fm[best];
2773 + zlib_level = lv[best];
2774 + if (zs[best] == 1)
2775 + z_strategy = Z_FILTERED;
2776 + else if (zs[best] == 2)
2777 + z_strategy = Z_HUFFMAN_ONLY;
2778 +#ifdef Z_RLE
2779 + else if (zs[best] == 3)
2780 + z_strategy = Z_RLE;
2781 +#endif
2782 + else /* if (zs[best] == 0) */
2783 + z_strategy = Z_DEFAULT_STRATEGY;
2784 + }
2785 + } else {
2786 + if (trial > 2 && trial < 5 && idat_length[trial - 1]
2787 + < idat_length[best_of_three])
2788 + best_of_three = trial - 1;
2789 + if (try_method[trial]) {
2790 + P2("skipping \"late\" trial %d\n", trial);
2791 + continue;
2792 + }
2793 + if (!methods_specified && try_method[0]) {
2794 + if ((trial == 4 || trial == 7) && best_of_three != 1) {
2795 + P2("skipping \"early\" trial %d\n", trial);
2796 + continue;
2797 + }
2798 + if ((trial == 5 || trial == 8) && best_of_three != 2) {
2799 + P2("skipping \"early\" trial %d\n", trial);
2800 + continue;
2801 + }
2802 + if ((trial == 6 || trial == 9 || trial == 10)
2803 + && best_of_three != 3) {
2804 + P2("skipping \"early\" trial %d\n", trial);
2805 + continue;
2806 + }
2807 + }
2808 + filter_type = fm[trial];
2809 + zlib_level = lv[trial];
2810 + if (zs[trial] == 1)
2811 + z_strategy = Z_FILTERED;
2812 + else if (zs[trial] == 2)
2813 + z_strategy = Z_HUFFMAN_ONLY;
2814 +#ifdef Z_RLE
2815 + else if (zs[trial] == 3)
2816 + z_strategy = Z_RLE;
2817 +#endif
2818 + else /* if (zs[trial] == 0) */
2819 + z_strategy = Z_DEFAULT_STRATEGY;
2820 + final_method = trial;
2821 + if (!nosave) {
2822 + P2("\n\n------------------------------------------------\n"
2823 + "Begin trial %d, filter %d, strategy %d, level %d\n",
2824 + trial, filter_type, z_strategy, zlib_level);
2825 + }
2826 + }
2827 +
2828 + P2("prepare to open files.\n");
2829 + png_crush_pause();
2830 +
2831 + if ((fpin = FOPEN(inname, "rb")) == NULL) {
2832 + fprintf(STDERR, "Could not find input file %s\n", inname);
2833 + continue;
2834 + }
2835 + number_of_open_files++;
2836 + if (nosave == 0) {
2837 +#ifndef __riscos
2838 + /* Can't sensibly check this on RISC OS without opening a file
2839 + for update or output
2840 + */
2841 + struct stat stat_in, stat_out;
2842 + if (first_trial && !nofilecheck
2843 + && (stat(inname, &stat_in) == 0)
2844 + && (stat(outname, &stat_out) == 0) &&
2845 +#if defined(_MSC_VER) || defined(__MINGW32__) /* maybe others? */
2846 + /* MSVC++6.0 will erroneously return 0 for both files, so
2847 + we simply check the size instead. It is possible that
2848 + we will erroneously reject the attempt when inputsize
2849 + and outputsize are equal, for different files
2850 + */
2851 + (stat_in.st_size == stat_out.st_size) &&
2852 +#else
2853 + (stat_in.st_ino == stat_out.st_ino) &&
2854 +#endif
2855 + (stat_in.st_dev == stat_out.st_dev)) {
2856 + fprintf(STDERR,
2857 + "\n Cannot overwrite input file %s\n",
2858 + outname);
2859 + P1(" st_ino=%d, st_size=%d\n\n",
2860 + (int) stat_in.st_ino, (int) stat_in.st_size);
2861 + FCLOSE(fpin);
2862 + exit(1);
2863 + }
2864 +#endif
2865 + if ((fpout = FOPEN(outname, "wb")) == NULL) {
2866 + fprintf(STDERR, "Could not open output file %s\n",
2867 + outname);
2868 + FCLOSE(fpin);
2869 + exit(1);
2870 + }
2871 +
2872 + number_of_open_files++;
2873 + }
2874 +
2875 + P2("files are opened.\n");
2876 + png_crush_pause();
2877 +
2878 +/* OK to ignore any warning about the address of exception__prev in "Try" */
2879 + Try {
2880 + png_uint_32 row_length;
2881 + P1( "Allocating read and write structures\n");
2882 +#ifdef PNG_USER_MEM_SUPPORTED
2883 + read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
2884 + (png_voidp) NULL, (png_error_ptr) png_cexcept_error,
2885 + (png_error_ptr) NULL, (png_voidp) NULL,
2886 + (png_malloc_ptr) png_debug_malloc,
2887 + (png_free_ptr) png_debug_free);
2888 +#else
2889 + read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
2890 + (png_voidp) NULL, (png_error_ptr) png_cexcept_error,
2891 + (png_error_ptr) NULL);
2892 +#endif
2893 + if (read_ptr == NULL)
2894 + Throw "pngcrush could not create read_ptr";
2895 +
2896 + if (nosave == 0) {
2897 +#ifdef PNG_USER_MEM_SUPPORTED
2898 + write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING,
2899 + (png_voidp) NULL, (png_error_ptr) png_cexcept_error,
2900 + (png_error_ptr) NULL, (png_voidp) NULL,
2901 + (png_malloc_ptr) png_debug_malloc,
2902 + (png_free_ptr) png_debug_free);
2903 +#else
2904 + write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
2905 + (png_voidp) NULL, (png_error_ptr) png_cexcept_error,
2906 + (png_error_ptr) NULL);
2907 +#endif
2908 + if (write_ptr == NULL)
2909 + Throw "pngcrush could not create write_ptr";
2910 +
2911 + }
2912 + P1("Allocating read_info, write_info, end_info structures\n");
2913 + read_info_ptr = png_create_info_struct(read_ptr);
2914 + if (read_info_ptr == NULL)
2915 + Throw "pngcrush could not create read_info_ptr";
2916 + end_info_ptr = png_create_info_struct(read_ptr);
2917 + if (end_info_ptr == NULL)
2918 + Throw "pngcrush could not create end_info_ptr";
2919 + if (nosave == 0) {
2920 + write_info_ptr = png_create_info_struct(write_ptr);
2921 + if (write_info_ptr == NULL)
2922 + Throw "pngcrush could not create write_info_ptr";
2923 + write_end_info_ptr = png_create_info_struct(write_ptr);
2924 + if (write_end_info_ptr == NULL)
2925 + Throw
2926 + "pngcrush could not create write_end_info_ptr";
2927 + }
2928 +
2929 + P2("structures created.\n");
2930 + png_crush_pause();
2931 +
2932 + P1( "Initializing input and output streams\n");
2933 +#if !defined(PNG_NO_STDIO)
2934 + png_init_io(read_ptr, fpin);
2935 + if (nosave == 0)
2936 + png_init_io(write_ptr, fpout);
2937 +#else
2938 + png_set_read_fn(read_ptr, (png_voidp) fpin,
2939 + (png_rw_ptr) NULL);
2940 + if (nosave == 0)
2941 + png_set_write_fn(write_ptr, (png_voidp) fpout,
2942 + (png_rw_ptr) NULL,
2943 +#if defined(PNG_WRITE_FLUSH_SUPPORTED)
2944 + png_default_flush);
2945 +#else
2946 + NULL);
2947 +#endif
2948 +#endif
2949 +
2950 + P2("io has been initialized.\n");
2951 + png_crush_pause();
2952 +
2953 + /* We don't need to check CRC's because they were already
2954 + checked in the png_measure_idat function */
2955 +
2956 +#ifdef PNG_CRC_QUIET_USE
2957 + png_set_crc_action(read_ptr, PNG_CRC_QUIET_USE,
2958 + PNG_CRC_QUIET_USE);
2959 +#endif
2960 +
2961 +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2962 + png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS,
2963 + (png_bytep) NULL, 0);
2964 +#endif
2965 +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
2966 + if (nosave == 0) {
2967 + if (found_any_chunk == 1)
2968 + png_set_keep_unknown_chunks(write_ptr,
2969 + PNG_HANDLE_CHUNK_ALWAYS,
2970 + (png_bytep) "dSIG", 1);
2971 + if (all_chunks_are_safe)
2972 + png_set_keep_unknown_chunks(write_ptr,
2973 + PNG_HANDLE_CHUNK_ALWAYS,
2974 + (png_bytep) NULL, 0);
2975 + else {
2976 +#if !defined(PNG_cHRM_SUPPORTED) || !defined(PNG_hIST_SUPPORTED) || \
2977 + !defined(PNG_iCCP_SUPPORTED) || !defined(PNG_sCAL_SUPPORTED) || \
2978 + !defined(PNG_pCAL_SUPPORTED) || !defined(PNG_sPLT_SUPPORTED) || \
2979 + !defined(PNG_tIME_SUPPORTED)
2980 + png_byte chunk_name[5];
2981 + chunk_name[4] = '\0';
2982 +#endif
2983 +
2984 + if (keep_unknown_chunk("alla", argv) &&
2985 + keep_unknown_chunk("allb", argv))
2986 + png_set_keep_unknown_chunks(write_ptr,
2987 + PNG_HANDLE_CHUNK_IF_SAFE,
2988 + (png_bytep) NULL,
2989 + 0);
2990 + else
2991 + png_set_keep_unknown_chunks(write_ptr,
2992 + PNG_HANDLE_CHUNK_NEVER,
2993 + (png_bytep) NULL,
2994 + 0);
2995 +
2996 +#if !defined(PNG_cHRM_SUPPORTED)
2997 + if (keep_unknown_chunk("cHRM", argv)) {
2998 + png_save_uint_32(chunk_name, PNG_UINT_cHRM);
2999 + png_set_keep_unknown_chunks(write_ptr,
3000 + PNG_HANDLE_CHUNK_ALWAYS,
3001 + chunk_name, 1);
3002 + }
3003 +#endif
3004 +#if !defined(PNG_hIST_SUPPORTED)
3005 + if (keep_unknown_chunk("hIST", argv)) {
3006 + png_save_uint_32(chunk_name, PNG_UINT_hIST);
3007 + png_set_keep_unknown_chunks(write_ptr,
3008 + PNG_HANDLE_CHUNK_ALWAYS,
3009 + chunk_name, 1);
3010 + }
3011 +#endif
3012 +#if !defined(PNG_iCCP_SUPPORTED)
3013 + if (keep_unknown_chunk("iCCP", argv)) {
3014 + png_save_uint_32(chunk_name, PNG_UINT_iCCP);
3015 + png_set_keep_unknown_chunks(write_ptr,
3016 + PNG_HANDLE_CHUNK_ALWAYS,
3017 + chunk_name, 1);
3018 + }
3019 +#endif
3020 +#if !defined(PNG_sCAL_SUPPORTED)
3021 + if (keep_unknown_chunk("sCAL", argv)) {
3022 + png_save_uint_32(chunk_name, PNG_UINT_sCAL);
3023 + png_set_keep_unknown_chunks(write_ptr,
3024 + PNG_HANDLE_CHUNK_ALWAYS,
3025 + chunk_name, 1);
3026 + }
3027 +#endif
3028 +#if !defined(PNG_pCAL_SUPPORTED)
3029 + if (keep_unknown_chunk("pCAL", argv)) {
3030 + png_save_uint_32(chunk_name, PNG_UINT_pCAL);
3031 + png_set_keep_unknown_chunks(write_ptr,
3032 + PNG_HANDLE_CHUNK_ALWAYS,
3033 + chunk_name, 1);
3034 + }
3035 +#endif
3036 +#if !defined(PNG_sPLT_SUPPORTED)
3037 + if (keep_unknown_chunk("sPLT", argv)) {
3038 + png_save_uint_32(chunk_name, PNG_UINT_sPLT);
3039 + png_set_keep_unknown_chunks(write_ptr,
3040 + PNG_HANDLE_CHUNK_ALWAYS,
3041 + chunk_name, 1);
3042 + }
3043 +#endif
3044 +#if !defined(PNG_tIME_SUPPORTED)
3045 + if (keep_unknown_chunk("tIME", argv)) {
3046 + png_save_uint_32(chunk_name, PNG_UINT_tIME);
3047 + png_set_keep_unknown_chunks(write_ptr,
3048 + PNG_HANDLE_CHUNK_ALWAYS,
3049 + chunk_name, 1);
3050 + }
3051 +#endif
3052 + }
3053 + }
3054 +#endif /* PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED */
3055 +
3056 + P1( "Reading info struct\n");
3057 + {
3058 +#if defined(PNGCRUSH_LOCO)
3059 + png_byte mng_signature[8] =
3060 + { 138, 77, 78, 71, 13, 10, 26, 10 };
3061 +#endif
3062 + png_byte png_signature[8] =
3063 + { 137, 80, 78, 71, 13, 10, 26, 10 };
3064 +
3065 + png_default_read_data(read_ptr, png_signature, 8);
3066 + png_set_sig_bytes(read_ptr, 8);
3067 +
3068 +#if defined(PNGCRUSH_LOCO)
3069 + if (!(int)
3070 + (png_memcmp(mng_signature, png_signature, 8))) {
3071 + png_byte buffer[40];
3072 + unsigned long length;
3073 + /* Skip the MHDR */
3074 + png_permit_mng_features(read_ptr,
3075 + PNG_FLAG_MNG_FILTER_64);
3076 + png_default_read_data(read_ptr, buffer, 4);
3077 + length=buffer[3]+(buffer[2]<<8)+(buffer[1]<<16)+(buffer[0]<<24);
3078 + png_default_read_data(read_ptr, buffer, 4);
3079 + printf("Skipping %c%c%c%c chunk.\n",buffer[0],buffer[1],
3080 + buffer[2],buffer[3]);
3081 + png_default_read_data(read_ptr, buffer, length);
3082 + png_default_read_data(read_ptr, buffer, 4);
3083 + input_format = 1;
3084 + } else
3085 +#endif
3086 + if (png_sig_cmp(png_signature, 0, 8)) {
3087 + if (png_sig_cmp(png_signature, 0, 4))
3088 + png_error(read_ptr, "Not a PNG file!");
3089 + else
3090 + png_error(read_ptr,
3091 + "PNG file corrupted by ASCII conversion");
3092 + }
3093 + }
3094 +
3095 + png_read_info(read_ptr, read_info_ptr);
3096 +
3097 + /* { GRR added for quick %-navigation (1) */
3098 +
3099 + /* Start of chunk-copying/removal code, in order:
3100 + * - IHDR
3101 + * - bKGD
3102 + * - cHRM
3103 + * - gAMA
3104 + * - sRGB
3105 + * - iCCP
3106 + * - oFFs
3107 + * - pCAL
3108 + * - pHYs
3109 + * - hIST
3110 + * - tRNS
3111 + * - PLTE
3112 + * - sBIT
3113 + * - sCAL
3114 + * - sPLT
3115 + * - tEXt/zTXt/iTXt
3116 + * - tIME
3117 + * - unknown chunks
3118 + */
3119 + {
3120 + int interlace_method, compression_method,
3121 + filter_method;
3122 +
3123 + P1( "Transferring info struct\n");
3124 +
3125 + if (png_get_IHDR
3126 + (read_ptr, read_info_ptr, &width, &height,
3127 + &bit_depth, &color_type, &interlace_method,
3128 + &compression_method, &filter_method)) {
3129 + int need_expand = 0;
3130 + input_color_type = color_type;
3131 + input_bit_depth = bit_depth;
3132 +
3133 + if (output_color_type > 7) {
3134 + output_color_type = input_color_type;
3135 + }
3136 +
3137 + if (verbose > 1 && first_trial) {
3138 + fprintf(STDERR, " IHDR chunk data:\n");
3139 + fprintf(STDERR,
3140 + " Width=%lu, height=%lu\n",
3141 + (unsigned long)width,
3142 + (unsigned long)height);
3143 + fprintf(STDERR, " Bit depth =%d\n",
3144 + bit_depth);
3145 + fprintf(STDERR, " Color type=%d\n",
3146 + color_type);
3147 + if (output_color_type != color_type)
3148 + fprintf(STDERR,
3149 + " Output color type=%d\n",
3150 + output_color_type);
3151 + fprintf(STDERR, " Interlace =%d\n",
3152 + interlace_method);
3153 + }
3154 +
3155 +#ifndef PNG_WRITE_PACK_SUPPORTED
3156 + if (output_bit_depth == 0)
3157 +#else
3158 + if (force_output_bit_depth == 0)
3159 +#endif
3160 + {
3161 + output_bit_depth = input_bit_depth;
3162 + }
3163 + if ((output_color_type != 3
3164 + || output_bit_depth > 8)
3165 + && output_bit_depth >= 8
3166 + && output_bit_depth != input_bit_depth)
3167 + need_expand = 1;
3168 +
3169 +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
3170 + if ((color_type == 2 || color_type == 6
3171 + || color_type == 3) &&
3172 + (output_color_type == 0 || output_color_type == 4))
3173 + {
3174 + if (verbose > 0 && first_trial) {
3175 +#ifdef PNGCRUSH_COUNT_COLORS
3176 + if (reduce_to_gray)
3177 + fprintf(STDERR, " Reducing all-gray "
3178 + "truecolor image to grayscale.\n");
3179 + else
3180 +#endif
3181 + fprintf(STDERR, " Reducing truecolor "
3182 + "image to grayscale.\n");
3183 + }
3184 +#ifdef PNG_FIXED_POINT_SUPPORTED
3185 + png_set_rgb_to_gray_fixed(read_ptr, 1, -1, -1);
3186 +#else
3187 + png_set_rgb_to_gray(read_ptr, 1, 0., 0.);
3188 +#endif
3189 + if (output_bit_depth < 8)
3190 + output_bit_depth = 8;
3191 + if (color_type == 3)
3192 + need_expand = 1;
3193 + }
3194 +#endif
3195 +
3196 + if (color_type != 3 && output_color_type == 3) {
3197 + printf(" Cannot change to indexed color "
3198 + "(color_type 3)\n");
3199 + output_color_type = input_color_type;
3200 + }
3201 +
3202 + if ((color_type == 0 || color_type == 4) &&
3203 + (output_color_type == 2
3204 + || output_color_type == 6)) {
3205 + png_set_gray_to_rgb(read_ptr);
3206 + }
3207 +
3208 + if ((color_type == 4 || color_type == 6) &&
3209 + (output_color_type != 4
3210 + && output_color_type != 6)) {
3211 + if (verbose > 0 && first_trial) {
3212 +#ifdef PNGCRUSH_COUNT_COLORS
3213 + if (it_is_opaque)
3214 + fprintf(STDERR,
3215 + " Stripping opaque alpha channel.\n");
3216 + else
3217 +#endif
3218 + fprintf(STDERR,
3219 + " Stripping existing alpha channel.\n");
3220 + }
3221 +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
3222 + png_set_strip_alpha(read_ptr);
3223 +#endif
3224 + }
3225 +
3226 + if ((output_color_type == 4
3227 + || output_color_type == 6) && (color_type != 4
3228 + && color_type
3229 + != 6)) {
3230 + if (verbose > 0 && first_trial)
3231 + fprintf(STDERR,
3232 + " Adding an opaque alpha channel.\n");
3233 +#ifdef PNG_READ_FILLER_SUPPORTED
3234 + png_set_filler(read_ptr, (png_uint_32) 65535L,
3235 + PNG_FILLER_AFTER);
3236 +#endif
3237 + need_expand = 1;
3238 + }
3239 +
3240 + if (output_color_type && output_color_type != 3 &&
3241 + output_bit_depth < 8)
3242 + output_bit_depth = 8;
3243 +
3244 + if ((output_color_type == 2
3245 + || output_color_type == 6)
3246 + && color_type == 3) {
3247 + if (verbose > 0 && first_trial)
3248 + fprintf(STDERR,
3249 + " Expanding indexed color file.\n");
3250 + need_expand = 1;
3251 + }
3252 +#ifdef PNG_READ_EXPAND_SUPPORTED
3253 + if (need_expand == 1)
3254 + png_set_expand(read_ptr);
3255 +#endif
3256 +
3257 +#ifdef PNG_READ_PACK_SUPPORTED
3258 + if (input_bit_depth < 8) {
3259 + png_set_packing(read_ptr);
3260 + }
3261 + if (output_color_type == 0 && output_bit_depth < 8) {
3262 + png_color_8 true_bits;
3263 + true_bits.gray = (png_byte) (output_bit_depth);
3264 + png_set_shift(read_ptr, &true_bits);
3265 + }
3266 +#endif
3267 +
3268 + if (verbose > 1)
3269 + fprintf(STDERR, " Setting IHDR\n");
3270 +
3271 +#if defined(PNGCRUSH_LOCO)
3272 + output_format = 0;
3273 + if (do_loco) {
3274 + if (output_color_type == 2
3275 + || output_color_type == 6) {
3276 + output_format = 1;
3277 + filter_method = 64;
3278 + png_permit_mng_features(write_ptr,
3279 + PNG_FLAG_MNG_FILTER_64);
3280 + }
3281 + } else
3282 + filter_method = 0;
3283 + if (input_format != output_format)
3284 + things_have_changed = 1;
3285 +#endif
3286 +
3287 + png_set_IHDR(write_ptr, write_info_ptr, width,
3288 + height, output_bit_depth,
3289 + output_color_type, interlace_method,
3290 + compression_method, filter_method);
3291 +
3292 + if (output_color_type != input_color_type)
3293 + things_have_changed = 1;
3294 +
3295 + }
3296 + }
3297 +
3298 +#if defined(PNG_READ_bKGD_SUPPORTED) && defined(PNG_WRITE_bKGD_SUPPORTED)
3299 + {
3300 + png_color_16p background;
3301 +
3302 + if (!have_bkgd
3303 + && png_get_bKGD(read_ptr, read_info_ptr,
3304 + &background)) {
3305 + if (keep_chunk("bKGD", argv)) {
3306 + if ((input_color_type == 2
3307 + || input_color_type == 6)
3308 + && (output_color_type == 0
3309 + || output_color_type == 4))
3310 + background->gray = background->green;
3311 + png_set_bKGD(write_ptr, write_info_ptr,
3312 + background);
3313 + }
3314 + }
3315 + if (have_bkgd) {
3316 + /* If we are reducing an RGB image to grayscale, but
3317 + the background color isn't gray, the green channel
3318 + is written. That's not spec-compliant. We should
3319 + really check for a non-gray bKGD and refuse to do
3320 + the reduction if one is present. */
3321 + png_color_16 backgd;
3322 + png_color_16p background = &backgd;
3323 + background->red = bkgd_red;
3324 + background->green = bkgd_green;
3325 + background->blue = bkgd_blue;
3326 + background->gray = background->green;
3327 + png_set_bKGD(write_ptr, write_info_ptr,
3328 + background);
3329 + }
3330 + }
3331 +#endif /* defined(PNG_READ_bKGD_SUPPORTED)&&defined(PNG_WRITE_bKGD_SUPPORTED) */
3332 +
3333 +#if defined(PNG_READ_cHRM_SUPPORTED) && defined(PNG_WRITE_cHRM_SUPPORTED)
3334 +#ifdef PNG_FIXED_POINT_SUPPORTED
3335 + {
3336 + png_fixed_point white_x, white_y, red_x, red_y,
3337 + green_x, green_y, blue_x, blue_y;
3338 +
3339 + if (found_cHRM && png_get_cHRM_fixed
3340 + (read_ptr, read_info_ptr, &white_x, &white_y,
3341 + &red_x, &red_y, &green_x, &green_y, &blue_x,
3342 + &blue_y)) {
3343 + if (keep_chunk("cHRM", argv)) {
3344 + if (white_x == 0 && white_y == 0 && red_x == 0
3345 + && red_y == 0 && green_x == 0
3346 + && green_y == 0 && blue_x == 0
3347 + && blue_y == 0)
3348 + png_warning(write_ptr,
3349 + "Deleting all-zero cHRM chunk");
3350 + else
3351 + png_set_cHRM_fixed(write_ptr,
3352 + write_info_ptr, white_x,
3353 + white_y, red_x, red_y,
3354 + green_x, green_y,
3355 + blue_x, blue_y);
3356 + }
3357 + }
3358 + }
3359 +#else
3360 + {
3361 + double white_x, white_y, red_x, red_y, green_x,
3362 + green_y, blue_x, blue_y;
3363 +
3364 + if (png_get_cHRM
3365 + (read_ptr, read_info_ptr, &white_x, &white_y,
3366 + &red_x, &red_y, &green_x, &green_y, &blue_x,
3367 + &blue_y)) {
3368 + if (keep_chunk("cHRM", argv)) {
3369 + if (white_x == 0 && white_y == 0 && red_x == 0
3370 + && red_y == 0 && green_x == 0
3371 + && green_y == 0 && blue_x == 0
3372 + && blue_y == 0)
3373 + png_warning(write_ptr,
3374 + "Deleting all-zero cHRM chunk");
3375 + else
3376 + png_set_cHRM(write_ptr, write_info_ptr,
3377 + white_x, white_y, red_x,
3378 + red_y, green_x, green_y,
3379 + blue_x, blue_y);
3380 + }
3381 + }
3382 + }
3383 +#endif /* ?PNG_FIXED_POINT_SUPPORTED */
3384 +#endif /* defined(PNG_READ_cHRM_SUPPORTED)&&defined(PNG_WRITE_cHRM_SUPPORTED) */
3385 +
3386 +#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_WRITE_gAMA_SUPPORTED)
3387 + {
3388 + if (force_specified_gamma) {
3389 + if (first_trial) {
3390 + things_have_changed = 1;
3391 + if (verbose > 0)
3392 + fprintf(STDERR, " Inserting gAMA chunk with "
3393 +#ifdef PNG_FIXED_POINT_SUPPORTED
3394 + "gamma=(%d/100000)\n",
3395 +#else
3396 + "gamma=%f\n",
3397 +#endif
3398 + force_specified_gamma);
3399 + }
3400 +#ifdef PNG_FIXED_POINT_SUPPORTED
3401 + png_set_gAMA_fixed(write_ptr, write_info_ptr,
3402 + (png_fixed_point)
3403 + force_specified_gamma);
3404 + file_gamma =
3405 + (png_fixed_point) force_specified_gamma;
3406 +#else
3407 + png_set_gAMA(write_ptr, write_info_ptr,
3408 + force_specified_gamma);
3409 + file_gamma = force_specified_gamma;
3410 +#endif
3411 + }
3412 +#ifdef PNG_FIXED_POINT_SUPPORTED
3413 + else if (found_gAMA && png_get_gAMA_fixed
3414 + (read_ptr, read_info_ptr, &file_gamma))
3415 +#else
3416 + else if (found_gAMA && png_get_gAMA
3417 + (read_ptr, read_info_ptr, &file_gamma))
3418 +#endif
3419 + {
3420 + if (keep_chunk("gAMA", argv)) {
3421 + if (image_specified_gamma)
3422 + file_gamma = image_specified_gamma;
3423 + if (verbose > 1 && first_trial)
3424 +#ifdef PNG_FIXED_POINT_SUPPORTED
3425 + fprintf(STDERR, " gamma=(%d/100000)\n",
3426 + (int) file_gamma);
3427 + if (double_gamma)
3428 + file_gamma += file_gamma;
3429 + png_set_gAMA_fixed(write_ptr, write_info_ptr,
3430 + file_gamma);
3431 +#else
3432 + fprintf(STDERR, " gamma=%f\n",
3433 + file_gamma);
3434 + if (double_gamma)
3435 + file_gamma += file_gamma;
3436 + png_set_gAMA(write_ptr, write_info_ptr,
3437 + file_gamma);
3438 +#endif
3439 + }
3440 + } else if (specified_gamma) {
3441 + if (first_trial) {
3442 + things_have_changed = 1;
3443 + if (verbose > 0)
3444 + fprintf(STDERR, " Inserting gAMA chunk with "
3445 +#ifdef PNG_FIXED_POINT_SUPPORTED
3446 + "gamma=(%d/100000)\n",
3447 +#else
3448 + "gamma=%f\n",
3449 +#endif
3450 + specified_gamma);
3451 + }
3452 +#ifdef PNG_FIXED_POINT_SUPPORTED
3453 + png_set_gAMA_fixed(write_ptr, write_info_ptr,
3454 + specified_gamma);
3455 + file_gamma = (png_fixed_point) specified_gamma;
3456 +#else
3457 + png_set_gAMA(write_ptr, write_info_ptr,
3458 + specified_gamma);
3459 + file_gamma = specified_gamma;
3460 +#endif
3461 + }
3462 + }
3463 +#endif /* defined(PNG_READ_gAMA_SUPPORTED)&&defined(PNG_WRITE_gAMA_SUPPORTED) */
3464 +
3465 +#if defined(PNG_READ_sRGB_SUPPORTED) && defined(PNG_WRITE_sRGB_SUPPORTED)
3466 + {
3467 + int file_intent;
3468 +
3469 + if (png_get_sRGB
3470 + (read_ptr, read_info_ptr, &file_intent)) {
3471 + if (keep_chunk("sRGB", argv)) {
3472 + png_set_sRGB(write_ptr, write_info_ptr,
3473 + file_intent);
3474 + intent = file_intent;
3475 + }
3476 + } else if (intent >= 0) {
3477 +#ifdef PNG_gAMA_SUPPORTED
3478 +#ifdef PNG_FIXED_POINT_SUPPORTED
3479 + if (file_gamma >= 45000L && file_gamma <= 46000L)
3480 +#else
3481 + if (file_gamma >= 0.45000 && file_gamma <= 0.46000)
3482 +#endif
3483 + {
3484 + things_have_changed = 1;
3485 + if (first_trial)
3486 + fprintf(STDERR,
3487 + " Inserting sRGB chunk with intent=%d\n",
3488 + intent);
3489 + png_set_sRGB(write_ptr, write_info_ptr,
3490 + intent);
3491 + } else if (file_gamma != 0) {
3492 + if (first_trial) {
3493 + fprintf(STDERR, " Ignoring sRGB request; "
3494 +#ifdef PNG_FIXED_POINT_SUPPORTED
3495 + "gamma=(%lu/100000)"
3496 +#else
3497 + "gamma=%f"
3498 +#endif
3499 + " is not approx. 0.455\n",
3500 + (unsigned long)file_gamma);
3501 + }
3502 + }
3503 +#endif /* PNG_gAMA_SUPPORTED */
3504 + }
3505 + }
3506 +#endif /* defined(PNG_READ_sRGB_SUPPORTED)&&defined(PNG_WRITE_sRGB_SUPPORTED) */
3507 +
3508 +#if defined(PNG_READ_iCCP_SUPPORTED) && defined(PNG_WRITE_iCCP_SUPPORTED)
3509 + if (intent < 0) { /* ignore iCCP if sRGB is being written */
3510 + png_charp name;
3511 + png_charp profile;
3512 + png_uint_32 proflen;
3513 + int compression_method;
3514 +
3515 + if (png_get_iCCP
3516 + (read_ptr, read_info_ptr, &name,
3517 + &compression_method, &profile, &proflen)) {
3518 + P1("Got iCCP chunk, proflen=%lu\n",
3519 + (unsigned long)proflen);
3520 + if (iccp_length)
3521 + P0("Will not replace existing iCCP chunk.\n");
3522 + if (keep_chunk("iCCP", argv))
3523 + png_set_iCCP(write_ptr, write_info_ptr, name,
3524 + compression_method, profile,
3525 + proflen);
3526 +
3527 + }
3528 +#ifdef PNG_iCCP_SUPPORTED
3529 + else if (iccp_length) {
3530 + png_set_iCCP(write_ptr, write_info_ptr, iccp_name,
3531 + 0, iccp_text, iccp_length);
3532 + P1("Wrote iCCP chunk, proflen=%d\n", iccp_length);
3533 + }
3534 +#endif
3535 +
3536 + }
3537 +#endif /* defined(PNG_READ_iCCP_SUPPORTED)&&defined(PNG_WRITE_iCCP_SUPPORTED) */
3538 +
3539 +#if defined(PNG_READ_oFFs_SUPPORTED) && defined(PNG_WRITE_oFFs_SUPPORTED)
3540 + {
3541 + png_int_32 offset_x, offset_y;
3542 + int unit_type;
3543 +
3544 + if (png_get_oFFs
3545 + (read_ptr, read_info_ptr, &offset_x, &offset_y,
3546 + &unit_type)) {
3547 + if (offset_x == 0 && offset_y == 0) {
3548 + if (verbose > 0 && first_trial)
3549 + fprintf(STDERR,
3550 + " Deleting useless oFFs 0 0 chunk\n");
3551 + } else {
3552 + if (keep_chunk("oFFs", argv))
3553 + png_set_oFFs(write_ptr, write_info_ptr,
3554 + offset_x, offset_y,
3555 + unit_type);
3556 + }
3557 + }
3558 + }
3559 +#endif
3560 +
3561 +#if defined(PNG_READ_pCAL_SUPPORTED) && defined(PNG_WRITE_pCAL_SUPPORTED)
3562 + {
3563 + png_charp purpose, units;
3564 + png_charpp params;
3565 + png_int_32 X0, X1;
3566 + int type, nparams;
3567 +
3568 + if (png_get_pCAL
3569 + (read_ptr, read_info_ptr, &purpose, &X0, &X1,
3570 + &type, &nparams, &units, &params)) {
3571 + if (keep_chunk("pCAL", argv))
3572 + png_set_pCAL(write_ptr, write_info_ptr,
3573 + purpose, X0, X1, type, nparams,
3574 + units, params);
3575 + }
3576 + }
3577 +#endif
3578 +
3579 +#if defined(PNG_READ_pHYs_SUPPORTED) && defined(PNG_WRITE_pHYs_SUPPORTED)
3580 + {
3581 + png_uint_32 res_x, res_y;
3582 + int unit_type;
3583 +
3584 + if (resolution == 0) {
3585 + if (png_get_pHYs
3586 + (read_ptr, read_info_ptr, &res_x, &res_y,
3587 + &unit_type)) {
3588 + if (res_x == 0 && res_y == 0) {
3589 + if (verbose > 0 && first_trial)
3590 + fprintf(STDERR,
3591 + " Deleting useless pHYs 0 0 chunk\n");
3592 + } else {
3593 + if (keep_chunk("pHYs", argv))
3594 + png_set_pHYs(write_ptr, write_info_ptr,
3595 + res_x, res_y, unit_type);
3596 + }
3597 + }
3598 + } else {
3599 + unit_type = 1;
3600 + res_x = res_y =
3601 + (png_uint_32) ((resolution / .0254 + 0.5));
3602 + png_set_pHYs(write_ptr, write_info_ptr, res_x,
3603 + res_y, unit_type);
3604 + if (verbose > 0 && first_trial)
3605 + fprintf(STDERR, " Added pHYs %lu %lu 1 chunk\n",
3606 + (unsigned long)res_x,
3607 + (unsigned long)res_y);
3608 + }
3609 + }
3610 +#endif
3611 +
3612 +#if defined(PNG_READ_hIST_SUPPORTED) && defined(PNG_WRITE_hIST_SUPPORTED)
3613 + {
3614 + png_uint_16p hist;
3615 +
3616 + if (png_get_hIST(read_ptr, read_info_ptr, &hist)) {
3617 + if (keep_chunk("hIST", argv))
3618 + png_set_hIST(write_ptr, write_info_ptr, hist);
3619 + }
3620 + }
3621 +#endif
3622 +
3623 +#if defined(PNG_READ_tRNS_SUPPORTED) && defined(PNG_WRITE_tRNS_SUPPORTED)
3624 + {
3625 + png_bytep trans;
3626 + int num_trans;
3627 + png_color_16p trans_values;
3628 +
3629 + if (png_get_tRNS
3630 + (read_ptr, read_info_ptr, &trans, &num_trans,
3631 + &trans_values)) {
3632 + if (verbose > 1)
3633 + fprintf(STDERR,
3634 + " Found tRNS chunk in input file.\n");
3635 + if (have_trns == 1) {
3636 + P0(" Will not overwrite existing tRNS chunk.\n");
3637 + }
3638 + if (keep_chunk("tRNS", argv)) {
3639 + int last_nonmax = -1;
3640 + trns_red = trans_values->red;
3641 + trns_green = trans_values->green;
3642 + trns_blue = trans_values->blue;
3643 + trns_gray = trans_values->gray;
3644 + if (output_color_type == 3) {
3645 + for (ia = 0; ia < num_trans; ia++)
3646 + trns_array[ia] = trans[ia];
3647 + for (; ia < 256; ia++)
3648 + trns_array[ia] = 255;
3649 + for (ia = 0; ia < 256; ia++) {
3650 + if (trns_array[ia] != 255)
3651 + last_nonmax = ia;
3652 + }
3653 + if (first_trial && verbose > 0) {
3654 + if (last_nonmax < 0)
3655 + fprintf(STDERR, " Deleting "
3656 + "all-opaque tRNS chunk.\n");
3657 + else if (last_nonmax + 1 < num_trans)
3658 + fprintf(STDERR,
3659 + " Truncating trailing opaque "
3660 + "entries from tRNS chunk.\n");
3661 + }
3662 + num_trans = last_nonmax + 1;
3663 + }
3664 + if (verbose > 1)
3665 + fprintf(STDERR,
3666 + " png_set_tRNS, num_trans=%d\n",
3667 + num_trans);
3668 + if (output_color_type != 3 || num_trans)
3669 + png_set_tRNS(write_ptr, write_info_ptr,
3670 + trans, num_trans,
3671 + trans_values);
3672 + }
3673 + } else if (have_trns == 1) { /* will not overwrite existing trns data */
3674 + png_color_16 trans_data;
3675 + png_byte index_data = (png_byte) trns_index;
3676 + num_trans = index_data + 1;
3677 + if (verbose > 1)
3678 + fprintf(STDERR, "Have_tRNS, num_trans=%d\n",
3679 + num_trans);
3680 + if (output_color_type == 3) {
3681 + trans_values = NULL;
3682 + for (ia = 0; ia < num_trans; ia++)
3683 + trns_array[ia] = trans_in[ia];
3684 + for (; ia < 256; ia++)
3685 + trns_array[ia] = 255;
3686 + } else {
3687 + for (ia = 0; ia < 256; ia++)
3688 + trns_array[ia] = 255;
3689 + trns_array[index_data] = 0;
3690 +
3691 + trans_data.index = index_data;
3692 + trans_data.red = trns_red;
3693 + trans_data.green = trns_green;
3694 + trans_data.blue = trns_blue;
3695 + trans_data.gray = trns_gray;
3696 + trans_values = &trans_data;
3697 + }
3698 +
3699 + P0(" Adding a tRNS chunk\n");
3700 + png_set_tRNS(write_ptr, write_info_ptr, trns_array,
3701 + num_trans, trans_values);
3702 +
3703 + things_have_changed = 1;
3704 + } else {
3705 + for (ia = 0; ia < 256; ia++)
3706 + trns_array[ia] = 255;
3707 + }
3708 + if (verbose > 1 && first_trial) {
3709 + int last = -1;
3710 + for (i = 0; ia < num_palette; ia++)
3711 + if (trns_array[ia] != 255)
3712 + last = ia;
3713 + if (last >= 0) {
3714 + fprintf(STDERR, " Transparency:\n");
3715 + if (output_color_type == 3)
3716 + for (i = 0; ia < num_palette; ia++)
3717 + fprintf(STDERR, " %4d %4d\n", ia,
3718 + trns_array[ia]);
3719 + else if (output_color_type == 0)
3720 + fprintf(STDERR, " %d\n", trns_gray);
3721 + else if (output_color_type == 2)
3722 + fprintf(STDERR, " %d %d %d\n",
3723 + trns_red, trns_green, trns_blue);
3724 + }
3725 + }
3726 + }
3727 +#endif /* defined(PNG_READ_tRNS_SUPPORTED)&&defined(PNG_WRITE_tRNS_SUPPORTED) */
3728 +
3729 + if (png_get_PLTE
3730 + (read_ptr, read_info_ptr, &palette, &num_palette))
3731 + {
3732 + if (plte_len > 0)
3733 + num_palette = plte_len;
3734 + if (do_pplt) {
3735 + printf("PPLT: %s\n", pplt_string);
3736 + printf("Sorry, PPLT is not implemented yet.\n");
3737 + }
3738 + if (output_color_type == 3)
3739 + png_set_PLTE(write_ptr, write_info_ptr, palette,
3740 + num_palette);
3741 + else if (keep_chunk("PLTE", argv))
3742 + png_set_PLTE(write_ptr, write_info_ptr, palette,
3743 + num_palette);
3744 + if (verbose > 1 && first_trial) {
3745 + int i;
3746 + png_colorp p = palette;
3747 + fprintf(STDERR, " Palette:\n");
3748 + fprintf(STDERR,
3749 + " I R G B ( color ) A\n");
3750 + for (i = 0; i < num_palette; i++) {
3751 + fprintf(STDERR,
3752 + " %4d %4d %4d %4d (#%2.2x%2.2x%2.2x) %4d\n",
3753 + i, p->red, p->green, p->blue, p->red,
3754 + p->green, p->blue, trns_array[i]);
3755 + p++;
3756 + }
3757 + }
3758 + }
3759 +
3760 +
3761 +#if defined(PNG_READ_sBIT_SUPPORTED) && defined(PNG_WRITE_sBIT_SUPPORTED)
3762 + {
3763 + png_color_8p sig_bit;
3764 +
3765 + /* If we are reducing a truecolor PNG to grayscale, and the
3766 + * RGB sBIT values aren't identical, we'll lose sBIT info.
3767 + */
3768 + if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) {
3769 + if (keep_chunk("sBIT", argv)) {
3770 + if ((input_color_type == 0
3771 + || input_color_type == 4)
3772 + && (output_color_type == 2
3773 + || output_color_type == 6
3774 + || output_color_type == 3))
3775 + sig_bit->red = sig_bit->green =
3776 + sig_bit->blue = sig_bit->gray;
3777 + if ((input_color_type == 2
3778 + || input_color_type == 6
3779 + || output_color_type == 3)
3780 + && (output_color_type == 0
3781 + || output_color_type == 4))
3782 + sig_bit->gray = sig_bit->green;
3783 +
3784 + if ((input_color_type == 0
3785 + || input_color_type == 2)
3786 + && (output_color_type == 4
3787 + || output_color_type == 6))
3788 + sig_bit->alpha = 1;
3789 +
3790 + png_set_sBIT(write_ptr, write_info_ptr,
3791 + sig_bit);
3792 + }
3793 + }
3794 + }
3795 +#endif /* defined(PNG_READ_sBIT_SUPPORTED)&&defined(PNG_WRITE_sBIT_SUPPORTED) */
3796 +
3797 +#if defined(PNG_sCAL_SUPPORTED)
3798 +#ifdef PNG_FLOATING_POINT_SUPPORTED
3799 + {
3800 + int unit;
3801 + double scal_width, scal_height;
3802 +
3803 + if (png_get_sCAL
3804 + (read_ptr, read_info_ptr, &unit, &scal_width,
3805 + &scal_height)) {
3806 + png_set_sCAL(write_ptr, write_info_ptr, unit,
3807 + scal_width, scal_height);
3808 + }
3809 + }
3810 +#else
3811 +#ifdef PNG_FIXED_POINT_SUPPORTED
3812 + {
3813 + int unit;
3814 + png_charp scal_width, scal_height;
3815 +
3816 + if (png_get_sCAL_s
3817 + (read_ptr, read_info_ptr, &unit, &scal_width,
3818 + &scal_height)) {
3819 + if (keep_chunk("sCAL", argv))
3820 + png_set_sCAL_s(write_ptr, write_info_ptr, unit,
3821 + scal_width, scal_height);
3822 + }
3823 + }
3824 +#endif
3825 +#endif /* PNG_FLOATING_POINT_SUPPORTED */
3826 +#endif /* ?PNG_sCAL_SUPPORTED */
3827 +
3828 +#if defined(PNG_sPLT_SUPPORTED)
3829 + {
3830 + png_sPLT_tp entries;
3831 + int num_entries;
3832 +
3833 + num_entries =
3834 + (int) png_get_sPLT(read_ptr, read_info_ptr,
3835 + &entries);
3836 + if (num_entries) {
3837 + if (keep_chunk("sPLT", argv))
3838 + png_set_sPLT(write_ptr, write_info_ptr,
3839 + entries, num_entries);
3840 + png_free_data(read_ptr, read_info_ptr,
3841 + PNG_FREE_SPLT, num_entries);
3842 + }
3843 + }
3844 +#endif
3845 +
3846 +#if defined(PNG_TEXT_SUPPORTED)
3847 + {
3848 + png_textp text_ptr;
3849 + int num_text = 0;
3850 +
3851 + if (png_get_text
3852 + (read_ptr, read_info_ptr, &text_ptr, &num_text) > 0
3853 + || text_inputs) {
3854 + int ntext;
3855 + P1( "Handling %d tEXt/zTXt chunks\n",
3856 + num_text);
3857 +
3858 + if (verbose > 1 && first_trial && num_text > 0) {
3859 + for (ntext = 0; ntext < num_text; ntext++) {
3860 + fprintf(STDERR, "%d %s", ntext,
3861 + text_ptr[ntext].key);
3862 + if (text_ptr[ntext].text_length)
3863 + fprintf(STDERR, ": %s\n",
3864 + text_ptr[ntext].text);
3865 +#ifdef PNG_iTXt_SUPPORTED
3866 + else if (text_ptr[ntext].itxt_length) {
3867 + fprintf(STDERR, " (%s: %s): \n",
3868 + text_ptr[ntext].lang,
3869 + text_ptr[ntext].lang_key);
3870 + fprintf(STDERR, "%s\n",
3871 + text_ptr[ntext].text);
3872 + }
3873 +#endif
3874 + else
3875 + fprintf(STDERR, "\n");
3876 + }
3877 + }
3878 +
3879 + if (num_text > 0) {
3880 + if (keep_chunk("text", argv)) {
3881 + int num_to_write = num_text;
3882 + for (ntext = 0; ntext < num_text; ntext++) {
3883 + if (first_trial)
3884 + P2("Text chunk before IDAT, "
3885 + "compression=%d\n",
3886 + text_ptr[ntext].compression);
3887 + if (text_ptr[ntext].compression ==
3888 + PNG_TEXT_COMPRESSION_NONE) {
3889 + if (!keep_chunk("tEXt", argv)) {
3890 + text_ptr[ntext].key[0] = '\0';
3891 + num_to_write--;
3892 + }
3893 + }
3894 + if (text_ptr[ntext].compression ==
3895 + PNG_TEXT_COMPRESSION_zTXt) {
3896 + if (!keep_chunk("zTXt", argv)) {
3897 + text_ptr[ntext].key[0] = '\0';
3898 + num_to_write--;
3899 + }
3900 + }
3901 +#ifdef PNG_iTXt_SUPPORTED
3902 + if (text_ptr[ntext].compression ==
3903 + PNG_ITXT_COMPRESSION_NONE
3904 + || text_ptr[ntext].compression ==
3905 + PNG_ITXT_COMPRESSION_zTXt) {
3906 + if (!keep_chunk("iTXt", argv)) {
3907 + text_ptr[ntext].key[0] = '\0';
3908 + num_to_write--;
3909 + }
3910 + }
3911 +#endif
3912 + }
3913 + if (num_to_write > 0)
3914 + png_set_text(write_ptr, write_info_ptr,
3915 + text_ptr, num_text);
3916 + }
3917 + }
3918 + for (ntext = 0; ntext < text_inputs; ntext++) {
3919 + if (text_where[ntext] == 1) {
3920 + png_textp added_text;
3921 + added_text = (png_textp) png_malloc(write_ptr,
3922 + (png_uint_32) sizeof(png_text));
3923 + added_text[0].key = &text_keyword[ntext * 80];
3924 +#ifdef PNG_iTXt_SUPPORTED
3925 + added_text[0].lang = &text_lang[ntext * 80];
3926 + added_text[0].lang_key =
3927 + &text_lang_key[ntext * 80];
3928 +#endif
3929 + added_text[0].text = &text_text[ntext * 2048];
3930 + added_text[0].compression =
3931 + text_compression[ntext];
3932 + png_set_text(write_ptr, write_info_ptr,
3933 + added_text, 1);
3934 + if (added_text[0].compression < 0)
3935 + printf(" Added a tEXt chunk.\n");
3936 + else if (added_text[0].compression == 0)
3937 + printf(" Added a zTXt chunk.\n");
3938 +#ifdef PNG_iTXt_SUPPORTED
3939 + else
3940 + printf(" Added a%scompressed iTXt chunk"
3941 + ".\n", (added_text[0].compression == 1)?
3942 + "n un" : " ");
3943 +#endif
3944 +#if 0
3945 + printf(" key=%s.\n",(added_text[0].key));
3946 +#endif
3947 + png_free(write_ptr, added_text);
3948 + added_text = (png_textp) NULL;
3949 + }
3950 + }
3951 + }
3952 + }
3953 +#endif /* defined(PNG_TEXT_SUPPORTED) */
3954 +
3955 +#if defined(PNG_READ_tIME_SUPPORTED) && defined(PNG_WRITE_tIME_SUPPORTED)
3956 + {
3957 + png_timep mod_time;
3958 +
3959 + if (png_get_tIME(read_ptr, read_info_ptr, &mod_time)) {
3960 + if (keep_chunk("tIME", argv))
3961 + png_set_tIME(write_ptr, write_info_ptr, mod_time);
3962 + }
3963 + }
3964 +#endif
3965 +
3966 +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
3967 + /* This section handles pCAL and tIME (at least, in default
3968 + * build), gIFx/gIFg/gIFt, private Fireworks chunks, etc. */
3969 + {
3970 + png_unknown_chunkp unknowns; /* allocated by libpng */
3971 + int num_unknowns;
3972 +
3973 + num_unknowns = (int)png_get_unknown_chunks(read_ptr,
3974 + read_info_ptr, &unknowns);
3975 + P1("Found %d unknown chunks\n", num_unknowns);
3976 +
3977 + if (nosave == 0 && num_unknowns) {
3978 + png_unknown_chunkp unknowns_keep; /* allocated by us */
3979 + int num_unknowns_keep;
3980 + int i;
3981 +
3982 + unknowns_keep = png_malloc(write_ptr,
3983 + (png_uint_32) num_unknowns*sizeof(png_unknown_chunk));
3984 + P1("malloc for %d unknown chunks\n", num_unknowns);
3985 + num_unknowns_keep = 0;
3986 +
3987 + /* make an array of only those chunks we want to keep */
3988 + for (i = 0; i < num_unknowns; i++) {
3989 + P1("Handling unknown chunk %d %s\n", i,
3990 + (char *)unknowns[i].name);
3991 + /* not EBCDIC-safe, but neither is keep_chunks(): */
3992 + P2(" unknown[%d] = %s (%lu bytes, location %d)\n",
3993 + i, unknowns[i].name,
3994 + (unsigned long)unknowns[i].size,
3995 + unknowns[i].location);
3996 + if (keep_chunk((char *)unknowns[i].name, argv)) {
3997 + memcpy(&unknowns_keep[num_unknowns_keep],
3998 + &unknowns[i], sizeof(png_unknown_chunk));
3999 + ++num_unknowns_keep;
4000 + }
4001 + }
4002 +
4003 + P1("Keeping %d unknown chunks\n", num_unknowns_keep);
4004 + png_set_unknown_chunks(write_ptr, write_info_ptr,
4005 + unknowns_keep, num_unknowns_keep);
4006 +
4007 + /* relevant location bits:
4008 + * (1) !PNG_HAVE_PLTE && !PNG_HAVE_IDAT (before PLTE)
4009 + * (2) PNG_HAVE_PLTE && !PNG_HAVE_IDAT (between)
4010 + * (3) PNG_AFTER_IDAT (after IDAT)
4011 + * PNG_HAVE_PLTE = 0x02
4012 + * PNG_HAVE_IDAT = 0x04
4013 + * PNG_AFTER_IDAT = 0x08
4014 + */
4015 + for (i = 0; i < num_unknowns_keep; i++) {
4016 + png_set_unknown_chunk_location(write_ptr,
4017 + write_info_ptr, i,
4018 + (int)unknowns_keep[i].location);
4019 + }
4020 +
4021 + /* png_set_unknown_chunks() makes own copy, so nuke
4022 + * ours */
4023 + png_free(write_ptr, unknowns_keep);
4024 + }
4025 + }
4026 + P0("unknown chunk handling done.\n");
4027 +#endif /* PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED */
4028 +
4029 + /* } GRR added for quick %-navigation (1) */
4030 +
4031 + png_read_transform_info(read_ptr, read_info_ptr);
4032 +
4033 +
4034 + /* this is the default case (nosave == 1 -> perf-testing
4035 + only) */
4036 + if (nosave == 0) {
4037 +
4038 + if (filter_type == 0)
4039 + png_set_filter(write_ptr, 0, PNG_FILTER_NONE);
4040 + else if (filter_type == 1)
4041 + png_set_filter(write_ptr, 0, PNG_FILTER_SUB);
4042 + else if (filter_type == 2)
4043 + png_set_filter(write_ptr, 0, PNG_FILTER_UP);
4044 + else if (filter_type == 3)
4045 + png_set_filter(write_ptr, 0, PNG_FILTER_AVG);
4046 + else if (filter_type == 4)
4047 + png_set_filter(write_ptr, 0, PNG_FILTER_PAETH);
4048 + else if (filter_type == 5)
4049 + png_set_filter(write_ptr, 0, PNG_ALL_FILTERS);
4050 + else
4051 + png_set_filter(write_ptr, 0, PNG_FILTER_NONE);
4052 +
4053 +
4054 +/* GRR 20050220: not clear why unknowns treated differently from other chunks */
4055 +/* (i.e., inside nosave==0 block)... Moved up 50 lines now. */
4056 +#if 0 /* #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED */
4057 + {
4058 + png_unknown_chunkp unknowns;
4059 + int num_unknowns = (int) png_get_unknown_chunks(
4060 + read_ptr, read_info_ptr, &unknowns);
4061 +
4062 + P1("Keeping %d unknown chunks\n", num_unknowns);
4063 + if (num_unknowns) {
4064 + int i;
4065 +
4066 + png_set_unknown_chunks(write_ptr, write_info_ptr,
4067 + unknowns, num_unknowns);
4068 + for (i = 0; i < num_unknowns; i++) {
4069 + P2(" unknown[%d] = %s\n", i, unknowns[i].name);
4070 + png_set_unknown_chunk_location(write_ptr,
4071 + write_info_ptr, i, (int)unknowns[i].location);
4072 + }
4073 + }
4074 + }
4075 +#endif /* 0, was PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED */
4076 +
4077 +#ifdef PNGCRUSH_LOCO
4078 + if (do_loco) {
4079 + png_byte buffer[30];
4080 + const png_byte png_MHDR[5] = { 77, 72, 68, 82, '\0' };
4081 + png_byte mng_signature[8] =
4082 + { 138, 77, 78, 71, 13, 10, 26, 10 };
4083 + /* write the MNG 8-byte signature */
4084 + if (outname[strlen(outname) - 3] == 'p')
4085 + png_warning(read_ptr,
4086 + " Writing a MNG file with a .png extension");
4087 + png_default_write_data(write_ptr, &mng_signature[0],
4088 + (png_size_t) 8);
4089 + png_set_sig_bytes(write_ptr, 8);
4090 +
4091 + /* Write a MHDR chunk */
4092 +
4093 + buffer[0] = (png_byte) ((width >> 24) & 0xff);
4094 + buffer[1] = (png_byte) ((width >> 16) & 0xff);
4095 + buffer[2] = (png_byte) ((width >> 8) & 0xff);
4096 + buffer[3] = (png_byte) ((width) & 0xff);
4097 + buffer[4] = (png_byte) ((height >> 24) & 0xff);
4098 + buffer[5] = (png_byte) ((height >> 16) & 0xff);
4099 + buffer[6] = (png_byte) ((height >> 8) & 0xff);
4100 + buffer[7] = (png_byte) ((height) & 0xff);
4101 + for (i = 8; i < 27; i++)
4102 + buffer[i] = 0x00;
4103 + buffer[15] = 2; /* layer count */
4104 + buffer[19] = 1; /* frame count */
4105 + if (output_color_type == 6)
4106 + buffer[27] = 0x09; /* profile: MNG-VLC with trans. */
4107 + else
4108 + buffer[27] = 0x01; /* profile: MNG-VLC */
4109 + png_write_chunk(write_ptr, (png_bytep) png_MHDR,
4110 + buffer, (png_size_t) 28);
4111 + }
4112 +#endif /* PNGCRUSH_LOCO */
4113 +
4114 + png_crush_pause();
4115 + P1( "\nWriting info struct\n");
4116 +
4117 +#if 0 /* doesn't work; compression level has to be the same as in IDAT */
4118 + /* if zTXt other compressed chunk */
4119 + png_set_compression_level(write_ptr, 9);
4120 + png_set_compression_window_bits(write_ptr, 15);
4121 +#endif
4122 +
4123 + png_crush_pause();
4124 + {
4125 + int compression_window;
4126 + png_uint_32 zbuf_size;
4127 + png_uint_32 required_window;
4128 + int channels = 0;
4129 + png_set_compression_strategy(write_ptr,
4130 + z_strategy);
4131 + png_set_compression_mem_level(write_ptr,
4132 + compression_mem_level);
4133 +
4134 + if (output_color_type == 0)
4135 + channels = 1;
4136 + if (output_color_type == 2)
4137 + channels = 3;
4138 + if (output_color_type == 3)
4139 + channels = 1;
4140 + if (output_color_type == 4)
4141 + channels = 2;
4142 + if (output_color_type == 6)
4143 + channels = 4;
4144 +
4145 + required_window =
4146 + (png_uint_32) (height *
4147 + ((width * channels * bit_depth +
4148 + 15) >> 3) + 262);
4149 +
4150 + zbuf_size =
4151 + png_get_compression_buffer_size(write_ptr);
4152 +
4153 + /* reinitialize zbuf - compression buffer */
4154 + if (zbuf_size != max_idat_size) {
4155 + png_uint_32 max_possible_size =
4156 + required_window;
4157 + if (max_possible_size > max_idat_size)
4158 + max_possible_size = max_idat_size;
4159 + P2("reinitializing write zbuf to %lu.\n",
4160 + (unsigned long)max_possible_size);
4161 + png_set_compression_buffer_size(write_ptr,
4162 + max_possible_size);
4163 + }
4164 +
4165 +#ifdef WBITS_8_OK
4166 + if (required_window <= 256)
4167 + compression_window = 8;
4168 + else if (required_window <= 512)
4169 + compression_window = 9;
4170 +#else
4171 + if (required_window <= 512)
4172 + compression_window = 9;
4173 +#endif
4174 + else if (required_window <= 1024)
4175 + compression_window = 10;
4176 + else if (required_window <= 2048)
4177 + compression_window = 11;
4178 + else if (required_window <= 4096)
4179 + compression_window = 12;
4180 + else if (required_window <= 8192)
4181 + compression_window = 13;
4182 + else if (required_window <= 16384)
4183 + compression_window = 14;
4184 + else
4185 + compression_window = 15;
4186 + if (compression_window > default_compression_window
4187 + || force_compression_window)
4188 + compression_window =
4189 + default_compression_window;
4190 +
4191 + if (verbose > 1 && first_trial
4192 + && (compression_window != 15
4193 + || force_compression_window))
4194 + fprintf(STDERR,
4195 + " Compression window for output= %d\n",
4196 + 1 << compression_window);
4197 +
4198 + png_set_compression_window_bits(write_ptr,
4199 + compression_window);
4200 + }
4201 +
4202 + png_set_compression_level(write_ptr, zlib_level);
4203 + png_write_info(write_ptr, write_info_ptr);
4204 + P1( "\nWrote info struct\n");
4205 +#ifdef PNG_WRITE_PACK_SUPPORTED
4206 + if (output_bit_depth < 8) {
4207 + if (output_color_type == 0) {
4208 + png_color_8 true_bits;
4209 + true_bits.gray = (png_byte) (output_bit_depth);
4210 + png_set_shift(write_ptr, &true_bits);
4211 + }
4212 + png_set_packing(write_ptr);
4213 + }
4214 +#endif
4215 +
4216 + }
4217 + /* no save */
4218 +#define LARGE_PNGCRUSH
4219 +
4220 +#ifdef PNGCRUSH_MULTIPLE_ROWS
4221 + rows_at_a_time = max_rows_at_a_time;
4222 + if (rows_at_a_time == 0 || rows_at_a_time < height)
4223 + rows_at_a_time = height;
4224 +#endif
4225 +
4226 +#ifndef LARGE_PNGCRUSH
4227 + {
4228 + png_uint_32 rowbytes_s;
4229 + png_uint_32 rowbytes;
4230 +
4231 + rowbytes = png_get_rowbytes(read_ptr, read_info_ptr);
4232 +
4233 + rowbytes_s = (png_size_t) rowbytes;
4234 + if (rowbytes == (png_uint_32) rowbytes_s)
4235 +#ifdef PNGCRUSH_MULTIPLE_ROWS
4236 + row_buf =
4237 + png_malloc(read_ptr,
4238 + rows_at_a_time * rowbytes + 16);
4239 +#else
4240 + row_buf = png_malloc(read_ptr, rowbytes + 16);
4241 +#endif
4242 + else
4243 + row_buf = NULL;
4244 + }
4245 +#else
4246 + {
4247 + png_uint_32 read_row_length, write_row_length;
4248 + read_row_length =
4249 + (png_uint_32) (png_get_rowbytes
4250 + (read_ptr, read_info_ptr));
4251 + write_row_length =
4252 + (png_uint_32) (png_get_rowbytes
4253 + (write_ptr, write_info_ptr));
4254 + row_length =
4255 + read_row_length >
4256 + write_row_length ? read_row_length :
4257 + write_row_length;
4258 +#ifdef PNGCRUSH_MULTIPLE_ROWS
4259 + row_buf =
4260 + (png_bytep) png_malloc(read_ptr,
4261 + rows_at_a_time *
4262 + row_length + 16);
4263 +#else
4264 + row_buf =
4265 + (png_bytep) png_malloc(read_ptr, row_length + 16);
4266 +#endif
4267 + }
4268 +#endif
4269 +
4270 + if (row_buf == NULL)
4271 + png_error(read_ptr,
4272 + "Insufficient memory to allocate row buffer");
4273 +
4274 + {
4275 + /* check for sufficient memory: we need 2*zlib_window and,
4276 + if filter_type == 5, 4*rowbytes in separate allocations.
4277 + If it's not enough we can drop the "average" filter and
4278 + we can reduce the zlib_window for writing. We can't
4279 + change the input zlib_window because the input file
4280 + might have used the full 32K sliding window.
4281 + */
4282 + }
4283 +
4284 +#ifdef PNGCRUSH_MULTIPLE_ROWS
4285 + row_pointers = (png_bytepp) png_malloc(read_ptr,
4286 + rows_at_a_time *
4287 + sizeof(png_bytepp));
4288 + for (i = 0; i < rows_at_a_time; i++)
4289 + row_pointers[i] = row_buf + i * row_length;
4290 +#endif
4291 +
4292 + P2("allocated rowbuf.\n");
4293 + png_crush_pause();
4294 +
4295 + num_pass = png_set_interlace_handling(read_ptr);
4296 + if (nosave == 0)
4297 + png_set_interlace_handling(write_ptr);
4298 +
4299 + t_stop = (TIME_T) clock();
4300 + t_misc += (t_stop - t_start);
4301 + if (t_stop < t_start) {
4302 + t_misc += PNG_UINT_31_MAX;
4303 + if (t_stop < 0)
4304 + t_misc += PNG_UINT_31_MAX;
4305 + }
4306 + t_start = t_stop;
4307 + for (pass = 0; pass < num_pass; pass++) {
4308 +#ifdef PNGCRUSH_MULTIPLE_ROWS
4309 + png_uint_32 num_rows;
4310 +#endif
4311 + P1( "\nBegin interlace pass %d\n", pass);
4312 +#ifdef PNGCRUSH_MULTIPLE_ROWS
4313 + num_rows = rows_at_a_time;
4314 + for (y = 0; y < height; y += rows_at_a_time)
4315 +#else
4316 + for (y = 0; y < height; y++)
4317 +#endif
4318 + {
4319 +#ifdef PNGCRUSH_MULTIPLE_ROWS
4320 + if (y + num_rows > height)
4321 + num_rows = height - y;
4322 + png_read_rows(read_ptr, row_pointers,
4323 + (png_bytepp) NULL, num_rows);
4324 +#else
4325 + png_read_row(read_ptr, row_buf, (png_bytep) NULL);
4326 +#endif
4327 + if (nosave == 0) {
4328 + t_stop = (TIME_T) clock();
4329 + t_decode += (t_stop - t_start);
4330 + if (t_stop < t_start) {
4331 + t_decode += PNG_UINT_31_MAX;
4332 + if (t_stop < 0)
4333 + t_decode += PNG_UINT_31_MAX;
4334 + }
4335 + t_start = t_stop;
4336 +#ifdef PNGCRUSH_MULTIPLE_ROWS
4337 + png_write_rows(write_ptr, row_pointers,
4338 + num_rows);
4339 +#else
4340 + png_write_row(write_ptr, row_buf);
4341 +#endif
4342 + t_stop = (TIME_T) clock();
4343 + t_encode += (t_stop - t_start);
4344 + if (t_stop < t_start) {
4345 + t_encode += PNG_UINT_31_MAX;
4346 + if (t_stop < 0)
4347 + t_encode += PNG_UINT_31_MAX;
4348 + }
4349 + t_start = t_stop;
4350 + }
4351 + }
4352 + P2( "End interlace pass %d\n\n", pass);
4353 + }
4354 + if (nosave) {
4355 + t_stop = (TIME_T) clock();
4356 + t_decode += (t_stop - t_start);
4357 + if (t_stop < t_start) {
4358 + t_decode += PNG_UINT_31_MAX;
4359 + if (t_stop < 0)
4360 + t_decode += PNG_UINT_31_MAX;
4361 + }
4362 + t_start = t_stop;
4363 + }
4364 +
4365 +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) && \
4366 + defined(PNG_FLOATING_POINT_SUPPORTED)
4367 + if ((color_type == 2 || color_type == 6 || color_type == 3)
4368 + && (output_color_type == 0 || output_color_type == 4))
4369 + {
4370 + png_byte rgb_error =
4371 + png_get_rgb_to_gray_status(read_ptr);
4372 + if ((first_trial) && rgb_error)
4373 + printf(
4374 + " **** Converted non-gray image to gray. **** \n");
4375 + }
4376 +#endif
4377 +
4378 +#ifdef PNG_FREE_UNKN
4379 +# if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
4380 + png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1);
4381 +# endif
4382 +# if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
4383 + png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1);
4384 +# endif
4385 +#else
4386 +# if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
4387 + png_free_unknown_chunks(read_ptr, read_info_ptr, -1);
4388 +# endif
4389 +# if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
4390 + png_free_unknown_chunks(write_ptr, write_info_ptr, -1);
4391 +# endif
4392 +#endif
4393 +
4394 + P1( "Reading and writing end_info data\n");
4395 + png_read_end(read_ptr, end_info_ptr);
4396 +
4397 + /* { GRR: added for %-navigation (2) */
4398 +
4399 +#if (defined(PNG_READ_tEXt_SUPPORTED) && defined(PNG_WRITE_tEXt_SUPPORTED)) \
4400 + || (defined(PNG_READ_zTXt_SUPPORTED) && defined(PNG_WRITE_zTXt_SUPPORTED))
4401 + {
4402 + png_textp text_ptr;
4403 + int num_text = 0;
4404 +
4405 + if (png_get_text
4406 + (read_ptr, end_info_ptr, &text_ptr, &num_text) > 0
4407 + || text_inputs) {
4408 + int ntext;
4409 + P1( "Handling %d tEXt/zTXt chunks\n",
4410 + num_text);
4411 +
4412 + if (verbose > 1 && first_trial && num_text > 0) {
4413 + for (ntext = 0; ntext < num_text; ntext++) {
4414 + fprintf(STDERR, "%d %s", ntext,
4415 + text_ptr[ntext].key);
4416 + if (text_ptr[ntext].text_length)
4417 + fprintf(STDERR, ": %s\n",
4418 + text_ptr[ntext].text);
4419 +#ifdef PNG_iTXt_SUPPORTED
4420 + else if (text_ptr[ntext].itxt_length) {
4421 + fprintf(STDERR, " (%s: %s): \n",
4422 + text_ptr[ntext].lang,
4423 + text_ptr[ntext].lang_key);
4424 + fprintf(STDERR, "%s\n",
4425 + text_ptr[ntext].text);
4426 + }
4427 +#endif
4428 + else
4429 + fprintf(STDERR, "\n");
4430 + }
4431 + }
4432 +
4433 + if (num_text > 0) {
4434 + if (keep_chunk("text", argv)) {
4435 + int num_to_write = num_text;
4436 + for (ntext = 0; ntext < num_text; ntext++) {
4437 + if (first_trial)
4438 + P2("Text chunk after IDAT, "
4439 + "compression=%d\n",
4440 + text_ptr[ntext].compression);
4441 + if (text_ptr[ntext].compression ==
4442 + PNG_TEXT_COMPRESSION_NONE) {
4443 + if (!keep_chunk("tEXt", argv)) {
4444 + text_ptr[ntext].key[0] = '\0';
4445 + num_to_write--;
4446 + }
4447 + }
4448 + if (text_ptr[ntext].compression ==
4449 + PNG_TEXT_COMPRESSION_zTXt) {
4450 + if (!keep_chunk("zTXt", argv)) {
4451 + text_ptr[ntext].key[0] = '\0';
4452 + num_to_write--;
4453 + }
4454 + }
4455 +#ifdef PNG_iTXt_SUPPORTED
4456 + if (text_ptr[ntext].compression ==
4457 + PNG_ITXT_COMPRESSION_NONE
4458 + || text_ptr[ntext].compression ==
4459 + PNG_ITXT_COMPRESSION_zTXt) {
4460 + if (!keep_chunk("iTXt", argv)) {
4461 + text_ptr[ntext].key[0] = '\0';
4462 + num_to_write--;
4463 + }
4464 + }
4465 +#endif
4466 + }
4467 + if (num_to_write > 0)
4468 + png_set_text(write_ptr,
4469 + write_end_info_ptr,
4470 + text_ptr, num_text);
4471 + }
4472 + }
4473 + for (ntext = 0; ntext < text_inputs; ntext++) {
4474 + if (text_where[ntext] == 2) {
4475 + png_textp added_text;
4476 + added_text = (png_textp)
4477 + png_malloc(write_ptr,
4478 + (png_uint_32)
4479 + sizeof(png_text));
4480 + added_text[0].key =
4481 + &text_keyword[ntext * 80];
4482 +#ifdef PNG_iTXt_SUPPORTED
4483 + added_text[0].lang =
4484 + &text_lang[ntext * 80];
4485 + added_text[0].lang_key =
4486 + &text_lang_key[ntext * 80];
4487 +#endif
4488 + added_text[0].text =
4489 + &text_text[ntext * 2048];
4490 + added_text[0].compression =
4491 + text_compression[ntext];
4492 + png_set_text(write_ptr, write_end_info_ptr,
4493 + added_text, 1);
4494 + if (added_text[0].compression < 0)
4495 + printf(" Added a tEXt chunk.\n");
4496 + else if (added_text[0].compression == 0)
4497 + printf(" Added a zTXt chunk.\n");
4498 +#ifdef PNG_iTXt_SUPPORTED
4499 + else if (added_text[0].compression == 1)
4500 + printf(" Added an uncompressed iTXt "
4501 + "chunk.\n");
4502 + else
4503 + printf(" Added a compressed iTXt "
4504 + "chunk.\n");
4505 +#endif
4506 + png_free(write_ptr, added_text);
4507 + added_text = (png_textp) NULL;
4508 + }
4509 + }
4510 + }
4511 + }
4512 +#endif /* (PNG_READ_tEXt_SUPPORTED and PNG_WRITE_tEXt_SUPPORTED) or */
4513 + /* (PNG_READ_zTXt_SUPPORTED and PNG_WRITE_zTXt_SUPPORTED) */
4514 +#if defined(PNG_READ_tIME_SUPPORTED) && defined(PNG_WRITE_tIME_SUPPORTED)
4515 + {
4516 + png_timep mod_time;
4517 +
4518 + if (png_get_tIME(read_ptr, end_info_ptr, &mod_time)) {
4519 + if (keep_chunk("tIME", argv))
4520 + png_set_tIME(write_ptr, write_end_info_ptr,
4521 + mod_time);
4522 + }
4523 + }
4524 +#endif
4525 +
4526 +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
4527 + /* GRR FIXME? this block may need same fix as above */
4528 + {
4529 + png_unknown_chunkp unknowns;
4530 + int num_unknowns =
4531 + (int) png_get_unknown_chunks(read_ptr,
4532 + end_info_ptr,
4533 + &unknowns);
4534 + if (num_unknowns && nosave == 0) {
4535 + int i;
4536 + printf("setting %d unknown chunks after IDAT\n",
4537 + num_unknowns);
4538 + png_set_unknown_chunks(write_ptr,
4539 + write_end_info_ptr,
4540 + unknowns, num_unknowns);
4541 + for (i = 0; i < num_unknowns; i++)
4542 + png_set_unknown_chunk_location(write_ptr,
4543 + write_end_info_ptr,
4544 + i,
4545 + (int)
4546 + unknowns[i].
4547 + location);
4548 + }
4549 + }
4550 +#endif
4551 + /* } GRR: added for %-navigation (2) */
4552 +
4553 + if (nosave == 0) {
4554 +#if 0 /* doesn't work; compression level has to be the same as in IDAT */
4555 + /* if zTXt other compressed chunk */
4556 + png_set_compression_level(write_ptr, 9);
4557 + png_set_compression_window_bits(write_ptr, 15);
4558 + png_set_compression_buffer_size(write_ptr,
4559 + PNG_ZBUF_SIZE);
4560 + png_set_compression_strategy(write_ptr, 0);
4561 +#endif
4562 + png_write_end(write_ptr, write_end_info_ptr);
4563 + }
4564 +
4565 + P1( "Destroying data structs\n");
4566 + if (row_buf != (png_bytep) NULL) {
4567 + png_free(read_ptr, row_buf);
4568 + row_buf = (png_bytep) NULL;
4569 + }
4570 +#ifdef PNGCRUSH_MULTIPLE_ROWS
4571 + if (row_pointers != (png_bytepp) NULL) {
4572 + png_free(read_ptr, row_pointers);
4573 + row_pointers = (png_bytepp) NULL;
4574 + }
4575 +#endif
4576 + png_destroy_read_struct(&read_ptr, &read_info_ptr,
4577 + &end_info_ptr);
4578 + if (nosave == 0) {
4579 +#ifdef PNGCRUSH_LOCO
4580 + if (do_loco) {
4581 + const png_byte png_MEND[5] =
4582 + { 77, 69, 78, 68, '\0' };
4583 + /* write the MNG MEND chunk */
4584 + png_write_chunk(write_ptr, (png_bytep) png_MEND,
4585 + NULL, (png_size_t) 0);
4586 + }
4587 +#endif
4588 + png_destroy_info_struct(write_ptr,
4589 + &write_end_info_ptr);
4590 + png_destroy_write_struct(&write_ptr, &write_info_ptr);
4591 + }
4592 + }
4593 + Catch(msg) {
4594 + if (nosave == 0)
4595 + fprintf(stderr, "While converting %s to %s:\n", inname,
4596 + outname);
4597 + else
4598 + fprintf(stderr, "While reading %s:\n", inname);
4599 + fprintf(stderr,
4600 + " pngcrush caught libpng error:\n %s\n\n", msg);
4601 + if (row_buf) {
4602 + png_free(read_ptr, row_buf);
4603 + row_buf = (png_bytep) NULL;
4604 + }
4605 +#ifdef PNGCRUSH_MULTIPLE_ROWS
4606 + if (row_pointers != (png_bytepp) NULL) {
4607 + png_free(read_ptr, row_pointers);
4608 + row_pointers = (png_bytepp) NULL;
4609 + }
4610 +#endif
4611 + if (nosave == 0) {
4612 + png_destroy_info_struct(write_ptr,
4613 + &write_end_info_ptr);
4614 + png_destroy_write_struct(&write_ptr, &write_info_ptr);
4615 + FCLOSE(fpout);
4616 + setfiletype(outname);
4617 + }
4618 + png_destroy_read_struct(&read_ptr, &read_info_ptr,
4619 + &end_info_ptr);
4620 + FCLOSE(fpin);
4621 + if (verbose > 1)
4622 + fprintf(stderr, "returning after cleanup\n");
4623 + trial = MAX_METHODS + 1;
4624 + }
4625 +
4626 + read_ptr = NULL;
4627 + write_ptr = NULL;
4628 + FCLOSE(fpin);
4629 + if (nosave == 0) {
4630 + FCLOSE(fpout);
4631 + setfiletype(outname);
4632 + }
4633 +
4634 + if (nosave)
4635 + break;
4636 +
4637 + first_trial = 0;
4638 +
4639 + if (nosave == 0) {
4640 + P1( "Opening file for length measurement\n");
4641 + if ((fpin = FOPEN(outname, "rb")) == NULL) {
4642 + fprintf(STDERR, "Could not find output file %s\n", outname);
4643 + if (png_row_filters != NULL) {
4644 + free(png_row_filters);
4645 + png_row_filters = NULL;
4646 + }
4647 + exit(1);
4648 + }
4649 + number_of_open_files++;
4650 +
4651 + idat_length[trial] = measure_idats(fpin);
4652 +
4653 + FCLOSE(fpin);
4654 + }
4655 +
4656 + if (verbose > 0 && trial != MAX_METHODS) {
4657 + fprintf(STDERR,
4658 + " IDAT length with method %3d (fm %d zl %d zs %d) = %8lu\n",
4659 + trial, filter_type, zlib_level, z_strategy,
4660 + (unsigned long)idat_length[trial]);
4661 + fflush(STDERR);
4662 + }
4663 +
4664 + } /* end of trial-loop */
4665 +
4666 + P1("\n\nFINISHED MAIN LOOP OVER %d METHODS\n\n\n", MAX_METHODS);
4667 +
4668 + /* ////////////////////////////////////////////////////////////////////
4669 + ////////////////// ////////////////////
4670 + ////////////////// END OF MAIN LOOP OVER METHODS ////////////////////
4671 + ////////////////// ////////////////////
4672 + //////////////////////////////////////////////////////////////////// */
4673 + }
4674 +
4675 + if (fpin) {
4676 + FCLOSE(fpin);
4677 + }
4678 + if (nosave == 0 && fpout) {
4679 + FCLOSE(fpout);
4680 + setfiletype(outname);
4681 + }
4682 +
4683 + if (verbose > 0 && nosave == 0) {
4684 + png_uint_32 input_length, output_length;
4685 +#ifndef __riscos
4686 + struct stat stat_buf;
4687 + struct utimbuf utim;
4688 +
4689 + stat(inname, &stat_buf);
4690 + input_length = (unsigned long) stat_buf.st_size;
4691 + utim.actime = stat_buf.st_atime;
4692 + utim.modtime = stat_buf.st_mtime;
4693 + stat(outname, &stat_buf);
4694 + output_length = (unsigned long) stat_buf.st_size;
4695 + utime(outname, &utim); /* set timestamp (no big deal if fails) */
4696 +#else
4697 + input_length = (unsigned long) filesize(inname);
4698 + output_length = (unsigned long) filesize(outname);
4699 +#endif
4700 + total_input_length += input_length + output_length;
4701 +
4702 + if (!already_crushed && !image_is_immutable) {
4703 + fprintf(STDERR, " Best pngcrush method = %d (fm %d zl %d zs %d) "
4704 + "for %s\n", best, fm[best], lv[best], zs[best], outname);
4705 + }
4706 + if (idat_length[0] == idat_length[best])
4707 + fprintf(STDERR, " (no IDAT change)\n");
4708 + else if (idat_length[0] > idat_length[best])
4709 + fprintf(STDERR, " (%4.2f%% IDAT reduction)\n",
4710 + (100.0 - (100.0 * idat_length[best]) / idat_length[0]));
4711 + else
4712 + fprintf(STDERR, " (%4.2f%% IDAT increase)\n",
4713 + -(100.0 - (100.0 * idat_length[best]) / idat_length[0]));
4714 + if (input_length == output_length)
4715 + fprintf(STDERR, " (no filesize change)\n\n");
4716 + else if (input_length > output_length)
4717 + fprintf(STDERR, " (%4.2f%% filesize reduction)\n\n",
4718 + (100.0 - (100.0 * output_length) / input_length));
4719 + else
4720 + fprintf(STDERR, " (%4.2f%% filesize increase)\n\n",
4721 + -(100.0 - (100.0 * output_length) / input_length));
4722 +
4723 + if (verbose > 2)
4724 + fprintf(STDERR, " Number of open files=%d\n",
4725 + number_of_open_files);
4726 +
4727 + }
4728 +
4729 + if (pngcrush_mode == DEFAULT_MODE) {
4730 + if (png_row_filters != NULL) {
4731 + free(png_row_filters);
4732 + png_row_filters = NULL;
4733 + }
4734 + if (verbose > 0)
4735 + show_result();
4736 +#ifdef PNG_iCCP_SUPPORTED
4737 + if (iccp_length)
4738 + free(iccp_text);
4739 +#endif
4740 + if (pngcrush_must_exit)
4741 + exit(0);
4742 + return 0;
4743 + }
4744 + } /* end of loop on input files */
4745 +
4746 + return 0; /* just in case */
4747 +
4748 +} /* end of main() */
4749 +
4750 +
4751 +
4752 +
4753 +png_uint_32 measure_idats(FILE * fpin)
4754 +{
4755 + /* Copyright (C) 1999-2002,2006 Glenn Randers-Pehrson (glennrp@××××××××.net)
4756 + See notice in pngcrush.c for conditions of use and distribution */
4757 + P2("\nmeasure_idats:\n");
4758 + P1( "Allocating read structure\n");
4759 +/* OK to ignore any warning about the address of exception__prev in "Try" */
4760 + Try {
4761 + read_ptr =
4762 + png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL,
4763 + (png_error_ptr) png_cexcept_error,
4764 + (png_error_ptr) NULL);
4765 + P1( "Allocating read_info, end_info structures\n");
4766 + read_info_ptr = png_create_info_struct(read_ptr);
4767 + end_info_ptr = png_create_info_struct(read_ptr);
4768 +
4769 +#if !defined(PNG_NO_STDIO)
4770 + png_init_io(read_ptr, fpin);
4771 +#else
4772 + png_set_read_fn(read_ptr, (png_voidp) fpin, (png_rw_ptr) NULL);
4773 +#endif
4774 +
4775 + png_set_sig_bytes(read_ptr, 0);
4776 + measured_idat_length = png_measure_idat(read_ptr);
4777 + P2("measure_idats: IDAT length=%lu\n",
4778 + (unsigned long)measured_idat_length);
4779 + P1( "Destroying data structs\n");
4780 + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
4781 + }
4782 + Catch(msg) {
4783 + fprintf(STDERR, "\nWhile measuring IDATs in %s ", inname);
4784 + fprintf(STDERR, "pngcrush caught libpng error:\n %s\n\n", msg);
4785 + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
4786 + P1( "Destroyed data structs\n");
4787 + measured_idat_length = 0;
4788 + }
4789 + return measured_idat_length;
4790 +}
4791 +
4792 +
4793 +
4794 +
4795 +
4796 +png_uint_32 png_measure_idat(png_structp png_ptr)
4797 +{
4798 + /* Copyright (C) 1999-2002,2006 Glenn Randers-Pehrson (glennrp@××××××××.net)
4799 + See notice in pngcrush.c for conditions of use and distribution */
4800 + png_uint_32 sum_idat_length = 0;
4801 + png_byte *bb = NULL;
4802 + png_uint_32 malloced_length=0;
4803 +
4804 + {
4805 + png_byte png_signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
4806 +#if defined(PNGCRUSH_LOCO)
4807 + png_byte mng_signature[8] = { 138, 77, 78, 71, 13, 10, 26, 10 };
4808 +#endif
4809 +
4810 + png_default_read_data(png_ptr, png_signature, 8);
4811 + png_set_sig_bytes(png_ptr, 8);
4812 +
4813 +#if defined(PNGCRUSH_LOCO)
4814 + if (!(int) (png_memcmp(mng_signature, png_signature, 8))) {
4815 + const png_byte png_MHDR[5] = { 77, 72, 68, 82, '\0' };
4816 +
4817 + int b;
4818 + png_byte buffer[40];
4819 + unsigned long length;
4820 + /* read the MHDR */
4821 + png_default_read_data(read_ptr, buffer, 4);
4822 + length=buffer[3]+(buffer[2]<<8)+(buffer[1]<<16)+(buffer[0]<<24);
4823 + png_default_read_data(read_ptr, buffer, 4);
4824 + printf("Reading %c%c%c%c chunk.\n",buffer[0],buffer[1],
4825 + buffer[2],buffer[3]);
4826 + for (b=0; b<40; b++)
4827 + buffer[b]='\0';
4828 + png_default_read_data(read_ptr, buffer, length);
4829 + if (verbose) {
4830 + printf(" width=%lu\n",(unsigned long)(buffer[3]+(buffer[2]<<8)
4831 + +(buffer[1]<<16)+(buffer[0]<<24)));
4832 + printf(" height=%lu\n",(unsigned long)(buffer[7]+(buffer[6]<<8)
4833 + +(buffer[5]<<16)+(buffer[4]<<24)));
4834 + printf(" ticksps=%lu\n",(unsigned long)(buffer[11]+
4835 + (buffer[10]<<8)+(buffer[9]<<16)+(buffer[8]<<24)));
4836 + printf(" nomlayc=%lu\n",(unsigned long)(buffer[15]+
4837 + (buffer[14]<<8)+(buffer[13]<<16)+(buffer[12]<<24)));
4838 + printf(" nomfram=%lu\n",(unsigned long)(buffer[19]+
4839 + (buffer[18]<<8)+(buffer[17]<<16)+(buffer[16]<<24)));
4840 + printf(" nomplay=%lu\n",(unsigned long)(buffer[23]+
4841 + (buffer[22]<<8)+(buffer[21]<<16)+(buffer[20]<<24)));
4842 + printf(" profile=%lu\n",(unsigned long)(buffer[27]+
4843 + (buffer[26]<<8)+(buffer[25]<<16)+(buffer[24]<<24)));
4844 + }
4845 +
4846 + if (new_mng) {
4847 + /* write the MNG 8-byte signature */
4848 + png_default_write_data(mng_ptr, &mng_signature[0],
4849 + (png_size_t) 8);
4850 +
4851 + /* Write a MHDR chunk */
4852 + png_write_chunk(mng_ptr, (png_bytep) png_MHDR,
4853 + buffer, (png_size_t) 28);
4854 + }
4855 +
4856 + png_default_read_data(read_ptr, buffer, 4);
4857 + input_format = 1;
4858 +
4859 + } else
4860 +#endif
4861 + if (png_sig_cmp(png_signature, 0, 8)) {
4862 + if (png_sig_cmp(png_signature, 0, 4))
4863 + png_error(png_ptr, "Not a PNG file..");
4864 + else
4865 + png_error(png_ptr,
4866 + "PNG file corrupted by ASCII conversion");
4867 + }
4868 + }
4869 +
4870 + if (fix)
4871 + {
4872 +#ifdef PNG_CRC_WARN_USE
4873 + png_set_crc_action(png_ptr, PNG_CRC_WARN_USE, PNG_CRC_WARN_USE);
4874 +#endif
4875 +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
4876 + inflateUndermine(&png_ptr->zstream, 1);
4877 +#endif
4878 + }
4879 +
4880 + for (;;) {
4881 +#ifndef PNG_UINT_IDAT
4882 +#if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNGCRUSH_USE_LOCAL_ARRAYS)
4883 + PNG_IDAT;
4884 + PNG_IEND;
4885 + PNG_IHDR;
4886 +#ifdef PNG_iCCP_SUPPORTED
4887 + PNG_iCCP;
4888 +#else
4889 + const png_byte png_iCCP[5] = { 105, 67, 67, 80, '\0' };
4890 +#endif
4891 +#endif
4892 +#endif
4893 + png_byte chunk_name[5];
4894 + png_byte chunk_length[4];
4895 + png_byte buffer[32];
4896 + png_uint_32 length;
4897 +
4898 + png_default_read_data(png_ptr, chunk_length, 4);
4899 + length = png_get_uint_31(png_ptr,chunk_length);
4900 +
4901 + png_reset_crc(png_ptr);
4902 + png_crc_read(png_ptr, chunk_name, 4);
4903 +
4904 + if (new_mng) {
4905 + const png_byte png_DHDR[5] = { 68, 72, 68, 82, '\0' };
4906 + const png_byte png_DEFI[5] = { 68, 69, 70, 73, '\0' };
4907 + const png_byte png_FRAM[5] = { 70, 82, 65, 77, '\0' };
4908 + const png_byte png_nEED[5] = { 110, 69, 69, 68, '\0' };
4909 + if (!png_memcmp(chunk_name, png_nEED, 4))
4910 + {
4911 + /* Skip the nEED chunk */
4912 + printf (" skipping MNG %c%c%c%c chunk, %lu bytes\n",chunk_name[0],
4913 + chunk_name[1],chunk_name[2],chunk_name[3],(unsigned long)length);
4914 + }
4915 + else {
4916 + /* copy the chunk. */
4917 + printf (" reading MNG %c%c%c%c chunk, %lu bytes\n",chunk_name[0],
4918 + chunk_name[1],chunk_name[2],chunk_name[3],(unsigned long)length);
4919 + if (length > malloced_length) {
4920 + png_free(mng_ptr,bb);
4921 + printf (" png_malloc %lu bytes.\n",(unsigned long)length);
4922 + bb=png_malloc(mng_ptr, length);
4923 + malloced_length=length;
4924 + }
4925 + png_crc_read(png_ptr, bb, length);
4926 + png_write_chunk(mng_ptr, chunk_name,
4927 + bb, (png_size_t) length);
4928 +
4929 + if (!png_memcmp(chunk_name, png_DHDR, 4)) {
4930 + if (verbose > 1) {
4931 + printf(" objid=%lu\n",(unsigned long)(bb[1]+(bb[0]<<8)));
4932 + printf(" itype=%lu\n",(unsigned long)(bb[2]));
4933 + printf(" dtype=%lu\n",(unsigned long)(bb[3]));
4934 + printf(" width=%lu\n",(unsigned long)(bb[7]+(bb[6]<<8)
4935 + +(bb[5]<<16)+(bb[4]<<24)));
4936 + printf(" height=%lu\n",(unsigned long)(bb[11]+(bb[10]<<8)
4937 + +(bb[9]<<16)+(bb[8]<<24)));
4938 + printf(" xloc=%lu\n",(unsigned long)(bb[15]+(bb[14]<<8)
4939 + +(bb[13]<<16)+(bb[12]<<24)));
4940 + printf(" yloc=%lu\n",(unsigned long)(bb[19]+(bb[18]<<8)
4941 + +(bb[17]<<16)+(bb[16]<<24)));
4942 + }
4943 + }
4944 +
4945 + if (!png_memcmp(chunk_name, png_DEFI, 4)) {
4946 + if (verbose > 1) {
4947 + printf(" objid=%lu\n",(unsigned long)(bb[1]+(bb[0]<<8)));
4948 + printf(" do_not_show=%lu\n",(unsigned long)(bb[2]));
4949 + printf(" concrete=%lu\n",(unsigned long)(bb[3]));
4950 + if (length > 4) {
4951 + printf(" xloc=%lu\n",(unsigned long)(bb[15]+(bb[14]<<8)
4952 + +(bb[13]<<16)+(bb[12]<<24)));
4953 + printf(" yloc=%lu\n",(unsigned long)(bb[19]+(bb[18]<<8)
4954 + +(bb[17]<<16)+(bb[16]<<24)));
4955 + if (length > 12) {
4956 + printf(" l_cb=%lu\n",(unsigned long)(bb[20]+(bb[19]<<8)
4957 + +(bb[18]<<16)+(bb[17]<<24)));
4958 + printf(" r_cb=%lu\n",(unsigned long)(bb[24]+(bb[23]<<8)
4959 + +(bb[22]<<16)+(bb[21]<<24)));
4960 + }
4961 + }
4962 + }
4963 + }
4964 + if (!png_memcmp(chunk_name, png_FRAM, 4)) {
4965 + if (verbose > 1) {
4966 + printf(" mode=%lu\n",(unsigned long)bb[0]);
4967 + if (length > 1) {
4968 + int ib;
4969 + printf(" name = ");
4970 + for (ib=0; bb[ib]; ib++)
4971 + {
4972 + printf ("%c", bb[ib]);
4973 + }
4974 + printf ("\n");
4975 + }
4976 + }
4977 + }
4978 + length=0;
4979 + }
4980 + }
4981 +
4982 + else {
4983 +
4984 +#ifdef PNG_UINT_IDAT
4985 + if (png_get_uint_32(chunk_name) == PNG_UINT_IDAT)
4986 +#else
4987 + if (!png_memcmp(chunk_name, png_IDAT, 4))
4988 +#endif
4989 + {
4990 + sum_idat_length += length;
4991 + if (length > crushed_idat_size)
4992 + already_crushed++;
4993 + }
4994 +
4995 + if (verbose > 1) {
4996 + chunk_name[4] = '\0';
4997 + printf("Reading %s chunk, length = %lu.\n", chunk_name,
4998 + (unsigned long)length);
4999 + }
5000 +#ifdef PNG_UINT_IHDR
5001 + if (png_get_uint_32(chunk_name) == PNG_UINT_IHDR)
5002 +#else
5003 + if (!png_memcmp(chunk_name, png_IHDR, 4))
5004 +#endif
5005 + {
5006 + /* get the color type */
5007 + png_crc_read(png_ptr, buffer, 13);
5008 + length -= 13;
5009 + input_color_type = buffer[9];
5010 + }
5011 + else
5012 + {
5013 + if (png_get_uint_32(chunk_name) == PNG_UINT_dSIG)
5014 + {
5015 + if (found_any_chunk == 0 && !all_chunks_are_safe)
5016 + {
5017 + image_is_immutable=1;
5018 + }
5019 + }
5020 + else
5021 + found_any_chunk=1;
5022 + }
5023 +
5024 +#ifdef PNG_gAMA_SUPPORTED
5025 + if (png_get_uint_32(chunk_name) == PNG_UINT_gAMA)
5026 + found_gAMA=1;
5027 +#endif
5028 +
5029 +#ifdef PNG_cHRM_SUPPORTED
5030 + if (png_get_uint_32(chunk_name) == PNG_UINT_cHRM)
5031 + found_cHRM=1;
5032 +#endif
5033 +
5034 +#ifdef PNG_iCCP_SUPPORTED
5035 + /* check for bad Photoshop iCCP chunk */
5036 +#ifdef PNG_UINT_iCCP
5037 + if (png_get_uint_32(chunk_name) == PNG_UINT_iCCP)
5038 +#else
5039 + if (!png_memcmp(chunk_name, png_iCCP, 4))
5040 +#endif
5041 + {
5042 + /* Check for bad Photoshop iCCP chunk. Libpng will reject the
5043 + * bad chunk because the Adler-32 bytes are missing, but we check
5044 + * here to see if it's really the sRGB profile, and if so, set the
5045 + * "intent" flag and gamma so pngcrush will write an sRGB chunk
5046 + * and a gamma chunk.
5047 + */
5048 + if (length == 2615) {
5049 + png_crc_read(png_ptr, buffer, 22);
5050 + length -= 22;
5051 + buffer[23] = 0;
5052 + if (!strncmp((png_const_charp) buffer, "Photoshop ICC profile",
5053 + 21))
5054 + {
5055 + printf(" Replacing bad Photoshop ICCP chunk with an "
5056 + "sRGB chunk\n");
5057 +#ifdef PNG_gAMA_SUPPORTED
5058 +#ifdef PNG_FIXED_POINT_SUPPORTED
5059 + image_specified_gamma = 45455L;
5060 +#else
5061 + image_specified_gamma = 0.45455;
5062 +#endif
5063 +#endif
5064 + intent = 0;
5065 + }
5066 + }
5067 + }
5068 +#endif
5069 +
5070 +
5071 + }
5072 + png_crc_finish(png_ptr, length);
5073 +
5074 +#ifdef PNGCRUSH_LOCO
5075 +#ifdef PNG_UINT_MEND
5076 + if (png_get_uint_32(chunk_name) == PNG_UINT_MEND)
5077 + return sum_idat_length;
5078 +#else
5079 + {
5080 + const png_byte png_MEND[5] =
5081 + { 77, 69, 78, 68, '\0' };
5082 + if (!png_memcmp(chunk_name, png_MEND, 4))
5083 + {
5084 + if (new_mng)
5085 + png_free(mng_ptr,bb);
5086 + return (0);
5087 + return sum_idat_length;
5088 + }
5089 + }
5090 +#endif
5091 +#endif
5092 +
5093 +
5094 +if (input_format == 0)
5095 + {
5096 +#ifdef PNG_UINT_IEND
5097 + if (png_get_uint_32(chunk_name) == PNG_UINT_IEND)
5098 +#else
5099 + if (!png_memcmp(chunk_name, png_IEND, 4))
5100 +#endif
5101 + return sum_idat_length;
5102 + }
5103 + }
5104 +}
5105 +
5106 +
5107 +
5108 +
5109 +
5110 +#ifdef PNGCRUSH_COUNT_COLORS
5111 +#define USE_HASHCODE
5112 +int count_colors(FILE * fpin)
5113 +{
5114 + /* Copyright (C) 2000-2002,2006 Glenn Randers-Pehrson (glennrp@××××××××.net)
5115 + See notice in pngcrush.c for conditions of use and distribution */
5116 + int bit_depth, color_type, interlace_method, filter_method,
5117 + compression_method;
5118 + png_uint_32 rowbytes;
5119 + volatile png_uint_32 channels;
5120 +
5121 + int i;
5122 + int pass, num_pass;
5123 + int ret;
5124 + volatile int result, hashmiss, hashinserts;
5125 +
5126 + png_uint_32 rgba_frequency[257];
5127 +
5128 + png_uint_32 rgba_hi[257]; /* Actually contains ARGB not RGBA */
5129 +#if 0
5130 + png_uint_32 rgba_lo[257]; /* Low bytes of ARGB in 16-bit PNGs */
5131 +#endif
5132 +
5133 + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
5134 +
5135 + /* start of interlace block */
5136 + int png_pass_start[] = { 0, 4, 0, 2, 0, 1, 0 };
5137 +
5138 + /* offset to next interlace block */
5139 + int png_pass_inc[] = { 8, 8, 4, 4, 2, 2, 1 };
5140 +
5141 + /* start of interlace block in the y direction */
5142 + int png_pass_ystart[] = { 0, 0, 4, 0, 2, 0, 1 };
5143 +
5144 + /* offset to next interlace block in the y direction */
5145 + int png_pass_yinc[] = { 8, 8, 8, 4, 4, 2, 2 };
5146 +
5147 + result = 0;
5148 + reduce_to_gray = 1;
5149 + it_is_opaque = 1;
5150 + hashmiss = 0;
5151 + hashinserts = 0;
5152 + row_buf = (png_bytep) NULL;
5153 +
5154 + num_rgba = 0;
5155 + for (i = 0; i < 257; i++) {
5156 + rgba_frequency[i] = 0;
5157 + }
5158 +
5159 + P2("Checking alphas:\n");
5160 + P1( "Allocating read structure\n");
5161 + Try {
5162 + read_ptr =
5163 + png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL,
5164 + (png_error_ptr) png_cexcept_error,
5165 + (png_error_ptr) NULL);
5166 + if (read_ptr) {
5167 + P1( "Allocating read_info structure\n");
5168 + read_info_ptr = png_create_info_struct(read_ptr);
5169 + if (read_info_ptr == NULL)
5170 + png_destroy_read_struct(&read_ptr, (png_infopp) NULL,
5171 + (png_infopp) NULL);
5172 + } else
5173 + read_info_ptr = NULL;
5174 + if (read_info_ptr) {
5175 +
5176 +#ifdef USE_HASHCODE
5177 + int hash[16385];
5178 +#endif
5179 +
5180 +#ifdef USE_HASHCODE
5181 + for (i = 0; i < 16385; i++)
5182 + hash[i] = -1;
5183 +#endif
5184 + end_info_ptr = NULL;
5185 +
5186 +#if !defined(PNG_NO_STDIO)
5187 + png_init_io(read_ptr, fpin);
5188 +#else
5189 + png_set_read_fn(read_ptr, (png_voidp) fpin, (png_rw_ptr) NULL);
5190 +#endif
5191 +
5192 + {
5193 +#if defined(PNGCRUSH_LOCO)
5194 + png_byte mng_signature[8] =
5195 + { 138, 77, 78, 71, 13, 10, 26, 10 };
5196 +#endif
5197 + png_byte png_signature[8] =
5198 + { 137, 80, 78, 71, 13, 10, 26, 10 };
5199 +
5200 + png_default_read_data(read_ptr, png_signature, 8);
5201 + png_set_sig_bytes(read_ptr, 8);
5202 +
5203 +#if defined(PNGCRUSH_LOCO)
5204 + if (!(int) (png_memcmp(mng_signature, png_signature, 8))) {
5205 + png_byte buffer[40];
5206 + unsigned long length;
5207 + /* skip the MHDR */
5208 + png_default_read_data(read_ptr, buffer, 4);
5209 + length=buffer[3]+(buffer[2]<<8)+(buffer[1]<<16)+(buffer[0]<<24);
5210 + png_default_read_data(read_ptr, buffer, 4);
5211 + printf("Skipping %c%c%c%c chunk.\n",buffer[0],buffer[1],
5212 + buffer[2],buffer[3]);
5213 + png_default_read_data(read_ptr, buffer, length);
5214 + png_default_read_data(read_ptr, buffer, 4);
5215 + png_permit_mng_features(read_ptr,
5216 + PNG_FLAG_MNG_FILTER_64);
5217 + input_format = 1;
5218 + } else
5219 +#endif
5220 + if (png_sig_cmp(png_signature, 0, 8)) {
5221 + if (png_sig_cmp(png_signature, 0, 4))
5222 + png_error(read_ptr, "Not a PNG file.");
5223 + else
5224 + png_error(read_ptr,
5225 + "PNG file corrupted by ASCII conversion");
5226 + }
5227 + }
5228 + png_read_info(read_ptr, read_info_ptr);
5229 +
5230 +#ifdef PNG_CRC_QUIET_USE
5231 + png_set_crc_action(read_ptr, PNG_CRC_QUIET_USE,
5232 + PNG_CRC_QUIET_USE);
5233 +#endif
5234 +
5235 + png_get_IHDR(read_ptr, read_info_ptr, &width, &height,
5236 + &bit_depth, &color_type, &interlace_method,
5237 + &compression_method, &filter_method);
5238 +
5239 + if (color_type == 2)
5240 + channels = 3;
5241 + else if (color_type == 4)
5242 + channels = 2;
5243 + else if (color_type == 6)
5244 + channels = 4;
5245 + else
5246 + channels = 1;
5247 +
5248 + if (color_type == 0 || color_type == 3 || color_type == 4)
5249 + reduce_to_gray = 1;
5250 +
5251 + if (bit_depth == 8) {
5252 + if (interlace_method)
5253 + num_pass = 7;
5254 + else
5255 + num_pass = 1;
5256 +
5257 + rowbytes = png_get_rowbytes(read_ptr, read_info_ptr);
5258 +
5259 + row_buf = png_malloc(read_ptr, rowbytes + 16);
5260 +
5261 + for (pass = 0; pass < num_pass; pass++) {
5262 + png_byte *rp;
5263 + png_uint_32 pass_height, pass_width, y;
5264 + P2( "\nBegin count_colors() interlace pass %d\n", pass);
5265 +
5266 + if (interlace_method) {
5267 + pass_height = (height - png_pass_ystart[pass]
5268 + + png_pass_yinc[pass] -
5269 + 1) / png_pass_yinc[pass];
5270 + pass_width = (width - png_pass_start[pass]
5271 + + png_pass_inc[pass] -
5272 + 1) / png_pass_inc[pass];
5273 + } else {
5274 + pass_height = height;
5275 + pass_width = width;
5276 + }
5277 +
5278 + for (y = 0; y < pass_height; y++) {
5279 + png_uint_32 x;
5280 + png_read_row(read_ptr, row_buf, (png_bytep) NULL);
5281 + if (result < 2 || it_is_opaque || reduce_to_gray) {
5282 + if (color_type == 2) {
5283 + for (rp = row_buf, x = 0; x < pass_width;
5284 + x++, rp += channels) {
5285 +#ifdef USE_HASHCODE
5286 + int hashcode;
5287 +#endif
5288 + png_uint_32 rgba_high =
5289 + (255 << 24) | (*(rp) << 16) |
5290 + (*(rp + 1) << 8) | *(rp + 2);
5291 + assert(num_rgba < 258);
5292 + rgba_hi[num_rgba] = rgba_high;
5293 +
5294 + if (reduce_to_gray &&
5295 + ((*(rp)) != (*(rp + 1))
5296 + || (*(rp)) != (*(rp + 2))))
5297 + reduce_to_gray = 0;
5298 +
5299 + if (result > 1 || !it_is_opaque)
5300 + continue;
5301 +
5302 +
5303 +#ifdef USE_HASHCODE
5304 + /*
5305 + * R G B mask
5306 + * 11,111 0,0000, 0000 0x3e00
5307 + * 00,000 1,1111, 0000 0x01f0
5308 + * 00,000 0,0000, 1111 0x000f
5309 + *
5310 + */
5311 +
5312 + hashcode =
5313 + (int) (((rgba_high >> 10) & 0x3e00)
5314 + | ((rgba_high >> 7) &
5315 + 0x01f0) | ((rgba_high >>
5316 + 4) &
5317 + 0x000f));
5318 + assert(hashcode < 16385);
5319 + if (hash[hashcode] < 0) {
5320 + hash[hashcode] = i = num_rgba;
5321 + if (i > 256)
5322 + result = 2;
5323 + else
5324 + num_rgba++;
5325 + } else {
5326 + int start = hash[hashcode];
5327 + for (i = start; i <= num_rgba; i++)
5328 + if (rgba_high == rgba_hi[i])
5329 + break;
5330 + hashmiss += (i - start);
5331 + if (i == num_rgba) {
5332 + int j;
5333 + if (i > 256)
5334 + result = 2;
5335 + else {
5336 + for (j = num_rgba;
5337 + j > start + 1; j--) {
5338 + rgba_hi[j] =
5339 + rgba_hi[j - 1];
5340 + rgba_frequency[j] =
5341 + rgba_frequency[j -
5342 + 1];
5343 + }
5344 + assert(start + 1 < 258);
5345 + rgba_hi[start + 1] =
5346 + rgba_high;
5347 + rgba_frequency[start + 1] =
5348 + 0;
5349 + for (j = 0; j < 16384; j++)
5350 + if (hash[j] > start)
5351 + hash[j]++;
5352 + i = start + 1;
5353 + hashinserts++;
5354 + num_rgba++;
5355 + }
5356 + }
5357 + }
5358 +#else
5359 + for (i = 0; i <= num_rgba; i++)
5360 + if (rgba_high == rgba_hi[i])
5361 + break;
5362 + hashmiss += i;
5363 + if (i > 256)
5364 + result = 2;
5365 + else if (i == num_rgba)
5366 + num_rgba++;
5367 +#endif
5368 + assert(i < 258);
5369 + ++rgba_frequency[i];
5370 + }
5371 + } else if (color_type == 6) {
5372 + for (rp = row_buf, x = 0; x < pass_width;
5373 + x++, rp += channels) {
5374 +#ifdef USE_HASHCODE
5375 + int hashcode;
5376 +#endif
5377 + png_uint_32 rgba_high =
5378 + (*(rp + 3) << 24) | (*(rp) << 16) |
5379 + (*(rp + 1) << 8) | *(rp + 2);
5380 + assert(rp - row_buf + 3 < rowbytes);
5381 + rgba_hi[num_rgba] = rgba_high;
5382 + if (reduce_to_gray &&
5383 + ((*(rp)) != (*(rp + 1))
5384 + || (*(rp)) != (*(rp + 2))))
5385 + reduce_to_gray = 0;
5386 + if (it_is_opaque && (*(rp + 3)) != 255)
5387 + it_is_opaque = 0;
5388 + if (result > 1)
5389 + continue;
5390 +#ifdef USE_HASHCODE
5391 + /*
5392 + * A R G B mask
5393 + * 11,1 000,0 000,0 000 0x3800
5394 + * 00,0 111,1 000,0 000 0x0780
5395 + * 00,0 000,0 111,1 000 0x0078
5396 + * 00,0 000,0 000,0 111 0x0007
5397 + *
5398 + */
5399 +
5400 + hashcode =
5401 + (int) (((rgba_high >> 18) & 0x3800)
5402 + | ((rgba_high >> 12) &
5403 + 0x0780) | ((rgba_high >>
5404 + 8) & 0x0078)
5405 + | ((rgba_high >> 4) &
5406 + 0x0007));
5407 + assert(hashcode < 16385);
5408 + if (hash[hashcode] < 0) {
5409 + hash[hashcode] = i = num_rgba;
5410 + if (i > 256)
5411 + result = 2;
5412 + else
5413 + num_rgba++;
5414 + } else {
5415 + int start = hash[hashcode];
5416 + for (i = start; i <= num_rgba; i++)
5417 + if (rgba_high == rgba_hi[i])
5418 + break;
5419 + hashmiss += (i - start);
5420 + if (i == num_rgba) {
5421 + if (i > 256)
5422 + result = 2;
5423 + else {
5424 + int j;
5425 + for (j = num_rgba;
5426 + j > start + 1; j--) {
5427 + rgba_hi[j] =
5428 + rgba_hi[j - 1];
5429 + rgba_frequency[j] =
5430 + rgba_frequency[j -
5431 + 1];
5432 + }
5433 + rgba_hi[start + 1] =
5434 + rgba_high;
5435 + rgba_frequency[start + 1] =
5436 + 0;
5437 + for (j = 0; j < 16384; j++)
5438 + if (hash[j] > start)
5439 + hash[j]++;
5440 + i = start + 1;
5441 + hashinserts++;
5442 + num_rgba++;
5443 + }
5444 + }
5445 + }
5446 +#else
5447 + for (i = 0; i <= num_rgba; i++)
5448 + if (rgba_high == rgba_hi[i])
5449 + break;
5450 + hashmiss += i;
5451 + if (i > 256)
5452 + result = 2;
5453 + else if (i == num_rgba)
5454 + num_rgba++;
5455 +#endif
5456 + ++rgba_frequency[i];
5457 + }
5458 + } else if (color_type == 4) {
5459 + for (rp = row_buf, x = 0; x < pass_width;
5460 + x++, rp += channels) {
5461 +#ifdef USE_HASHCODE
5462 + int hashcode;
5463 +#endif
5464 + png_uint_32 rgba_high =
5465 + (*(rp + 1) << 24) | (*(rp) << 16) |
5466 + (*(rp) << 8) | (*rp);
5467 + assert(rp - row_buf + 1 < rowbytes);
5468 + rgba_hi[num_rgba] = rgba_high;
5469 + if (it_is_opaque && (*(rp + 1)) != 255)
5470 + it_is_opaque = 0;
5471 +#ifdef USE_HASHCODE
5472 + /*
5473 + * A G mask
5474 + * 11,1111, 0000,0000 0x3f00
5475 + * 00,0000, 1111,1111 0x00ff
5476 + *
5477 + */
5478 +
5479 + hashcode =
5480 + (int) (((rgba_high >> 18) & 0x3f00)
5481 + | ((rgba_high >> 4) &
5482 + 0x00ff));
5483 + if (hash[hashcode] < 0) {
5484 + hash[hashcode] = i = num_rgba;
5485 + if (i > 256)
5486 + result = 2;
5487 + else
5488 + num_rgba++;
5489 + } else {
5490 + int start = hash[hashcode];
5491 + for (i = start; i <= num_rgba; i++)
5492 + if (rgba_high == rgba_hi[i])
5493 + break;
5494 + hashmiss += (i - start);
5495 + if (i == num_rgba) {
5496 + if (i > 256)
5497 + result = 2;
5498 + else {
5499 + int j;
5500 + for (j = num_rgba;
5501 + j > start + 1; j--) {
5502 + rgba_hi[j] =
5503 + rgba_hi[j - 1];
5504 + rgba_frequency[j] =
5505 + rgba_frequency[j -
5506 + 1];
5507 + }
5508 + rgba_hi[start + 1] =
5509 + rgba_high;
5510 + rgba_frequency[start + 1] =
5511 + 0;
5512 + for (j = 0; j < 16384; j++)
5513 + if (hash[j] > start)
5514 + hash[j]++;
5515 + i = start + 1;
5516 + hashinserts++;
5517 + num_rgba++;
5518 + }
5519 + }
5520 + }
5521 +#else
5522 + for (i = 0; i <= num_rgba; i++)
5523 + if (rgba_high == rgba_hi[i])
5524 + break;
5525 + hashmiss += i;
5526 + if (i > 256)
5527 + result = 2;
5528 + else if (i == num_rgba)
5529 + num_rgba++;
5530 +#endif
5531 + ++rgba_frequency[i];
5532 + }
5533 + } else { /* other color type */
5534 +
5535 + result = 2;
5536 + }
5537 + }
5538 + }
5539 + P2( "End count_colors() interlace pass %d\n\n", pass);
5540 + }
5541 +
5542 + } else /* (bit_depth != 8) */ {
5543 +
5544 + /* TO DO: 16-bit support */
5545 + reduce_to_gray = 0;
5546 + it_is_opaque = 0;
5547 + result = 0;
5548 + }
5549 +
5550 + png_free(read_ptr, row_buf);
5551 + row_buf = (png_bytep) NULL;
5552 + P1( "Destroying data structs\n");
5553 + png_destroy_read_struct(&read_ptr, &read_info_ptr,
5554 + (png_infopp) NULL);
5555 + } else
5556 + result = 2;
5557 + }
5558 + Catch(msg) {
5559 + fprintf(STDERR, "\nWhile checking alphas in %s ", inname);
5560 + fprintf(STDERR, "pngcrush caught libpng error:\n %s\n\n", msg);
5561 + png_free(read_ptr, row_buf);
5562 + row_buf = (png_bytep) NULL;
5563 + png_destroy_read_struct(&read_ptr, &read_info_ptr,
5564 + (png_infopp) NULL);
5565 + P1( "Destroyed data structs\n");
5566 + result = 2;
5567 + }
5568 + if (verbose > 1) {
5569 + int total = 0;
5570 + if (num_rgba && num_rgba < 257) {
5571 + for (i = 0; i < num_rgba; i++) {
5572 + printf("RGBA=(%3.3d,%3.3d,%3.3d,%3.3d), frequency=%d\n",
5573 + (int) (rgba_hi[i] >> 16) & 0xff,
5574 + (int) (rgba_hi[i] >> 8) & 0xff,
5575 + (int) (rgba_hi[i]) & 0xff,
5576 + (int) (rgba_hi[i] >> 24) & 0xff,
5577 + (int) rgba_frequency[i]);
5578 + total += rgba_frequency[i];
5579 + }
5580 + P2("num_rgba=%d, total pixels=%d\n", num_rgba, total);
5581 + P2("hashcode misses=%d, inserts=%d\n", hashmiss, hashinserts);
5582 + }
5583 + if (color_type == 0 || color_type == 2)
5584 + it_is_opaque = 0;
5585 + if (reduction_ok) {
5586 + if (reduce_to_gray)
5587 + P1("The truecolor image is all gray and will be reduced.\n");
5588 + if (it_is_opaque)
5589 + P1("The image is opaque and the alpha channel will be "
5590 + "removed.\n");
5591 + } else {
5592 + if (reduce_to_gray)
5593 + P1("The truecolor image is all gray and could be reduced.\n");
5594 + if (it_is_opaque)
5595 + P1("The image is opaque and the alpha channel could be "
5596 + "removed.\n");
5597 + if (reduce_to_gray || it_is_opaque)
5598 + P1("Rerun pngcrush with the \"-reduce\" option to do so.\n");
5599 + reduce_to_gray = 0;
5600 + it_is_opaque = 0;
5601 + }
5602 + P2("Finished checking alphas, result=%d\n", result);
5603 + }
5604 + ret = result;
5605 + return (ret);
5606 +}
5607 +#endif /* PNGCRUSH_COUNT_COLORS */
5608 +
5609 +
5610 +
5611 +
5612 +
5613 +void print_version_info(void)
5614 +{
5615 + fprintf(STDERR,
5616 + "\n"
5617 + " | pngcrush %s\n"
5618 + /* If you have modified this source, you may insert additional notices
5619 + * immediately after this sentence: */
5620 + " | Copyright (C) 1998-2002,2006-2008 Glenn Randers-Pehrson\n"
5621 + " | Copyright (C) 2005 Greg Roelofs\n"
5622 + " | This is a free, open-source program. Permission is irrevocably\n"
5623 + " | granted to everyone to use this version of pngcrush without\n"
5624 + " | payment of any fee.\n"
5625 + " | Executable name is %s\n"
5626 + " | It was built with libpng version %s, and is\n"
5627 + " | running with %s"
5628 + " | Copyright (C) 1998-2004,2006-2008 Glenn Randers-Pehrson,\n"
5629 + " | Copyright (C) 1996, 1997 Andreas Dilger,\n"
5630 + " | Copyright (C) 1995, Guy Eric Schalnat, Group 42 Inc.,\n"
5631 + " | and zlib version %s, Copyright (C) 1998-2002 (or later),\n"
5632 + " | Jean-loup Gailly and Mark Adler.\n",
5633 + PNGCRUSH_VERSION, progname, PNG_LIBPNG_VER_STRING,
5634 + png_get_header_version(NULL), ZLIB_VERSION);
5635 +
5636 +#if defined(__GNUC__)
5637 + fprintf(STDERR,
5638 + " | It was compiled with gcc version %s", __VERSION__);
5639 +# if defined(PNG_USE_PNGGCCRD)
5640 + fprintf(STDERR,
5641 + " and gas version %s", GAS_VERSION);
5642 +# endif
5643 +# if defined(__DJGPP__)
5644 + fprintf(STDERR,
5645 + "\n"
5646 + " | under DJGPP %d.%d, Copyright (C) 1995, D. J. Delorie\n"
5647 + " | and loaded with PMODE/DJ, by Thomas Pytel and Matthias Grimrath\n"
5648 + " | Copyright (C) 1996, Matthias Grimrath.\n",
5649 + __DJGPP__, __DJGPP_MINOR__);
5650 +# else
5651 + fprintf(STDERR, ".\n");
5652 +# endif
5653 +#endif
5654 +
5655 + fprintf(STDERR, "\n");
5656 +}
5657 +
5658 +
5659 +
5660 +
5661 +
5662 +static const char *pngcrush_legal[] = {
5663 + "",
5664 + /* If you have modified this source, you may insert additional notices
5665 + * immediately after this sentence: */
5666 + "Copyright (C) 1998-2002,2006-2008 Glenn Randers-Pehrson (glennrp@××××××××.net)",
5667 + "Copyright (C) 2005 Greg Roelofs",
5668 + "",
5669 + "DISCLAIMER: The pngcrush computer program is supplied \"AS IS\".",
5670 + "The Author disclaims all warranties, expressed or implied, including,",
5671 + "without limitation, the warranties of merchantability and of fitness",
5672 + "for any purpose. The Author assumes no liability for direct, indirect,",
5673 + "incidental, special, exemplary, or consequential damages, which may",
5674 + "result from the use of the computer program, even if advised of the",
5675 + "possibility of such damage. There is no warranty against interference",
5676 + "with your enjoyment of the computer program or against infringement.",
5677 + "There is no warranty that my efforts or the computer program will",
5678 + "fulfill any of your particular purposes or needs. This computer",
5679 + "program is provided with all faults, and the entire risk of satisfactory",
5680 + "quality, performance, accuracy, and effort is with the user.",
5681 + "",
5682 + "LICENSE: Permission is hereby irrevocably granted to everyone to use,",
5683 + "copy, modify, and distribute this computer program, or portions hereof,",
5684 + "purpose, without payment of any fee, subject to the following",
5685 + "restrictions:",
5686 + "",
5687 + "1. The origin of this binary or source code must not be misrepresented.",
5688 + "",
5689 + "2. Altered versions must be plainly marked as such and must not be",
5690 + "misrepresented as being the original binary or source.",
5691 + "",
5692 + "3. The Copyright notice, disclaimer, and license may not be removed",
5693 + "or altered from any source, binary, or altered source distribution.",
5694 + ""
5695 +};
5696 +
5697 +static const char *pngcrush_usage[] = {
5698 + "\nusage: %s [options] infile.png outfile.png\n",
5699 + " %s -e ext [other options] files.png ...\n",
5700 + " %s -d dir [other options] files.png ...\n"
5701 +};
5702 +
5703 +struct options_help pngcrush_options[] = {
5704 + {0, " -already already_crushed_size [e.g., 8192]"},
5705 + {2, ""}, /* blank */
5706 + {2, " If file has an IDAT greater than this size, it"},
5707 + {2, " will be considered to be already crushed and will"},
5708 + {2, " not be processed, unless you are making other changes"},
5709 + {2, " or the \"-force\" option is present."},
5710 + {2, ""},
5711 +
5712 + {0, " -bit_depth depth (bit_depth to use in output file)"},
5713 + {2, ""},
5714 + {2, " Default output depth is same as input depth."},
5715 + {2, ""},
5716 +
5717 +#ifdef Z_RLE
5718 + {0, " -brute (use brute-force: try 126 different methods [11-136])"},
5719 +#else
5720 + {0, " -brute (use brute-force: try 114 different methods [11-124])"},
5721 +#endif
5722 + {2, ""},
5723 + {2, " Very time-consuming and generally not worthwhile."},
5724 + {2, " You can restrict this option to certain filter types,"},
5725 + {2, " compression levels, or strategies by following it"},
5726 + {2, " with \"-f filter\", \"-l level\", or \"-z strategy\"."},
5727 + {2, ""},
5728 +
5729 + {0, " -c color_type of output file [0, 2, 4, or 6]"},
5730 + {2, ""},
5731 + {2, " Color type for the output file. Future versions"},
5732 + {2, " will also allow color_type 3, if there are 256 or"},
5733 + {2, " fewer colors present in the input file. Color types"},
5734 + {2, " 4 and 6 are padded with an opaque alpha channel if"},
5735 + {2, " the input file does not have alpha information."},
5736 + {2, " You can use 0 or 4 to convert color to grayscale."},
5737 + {2, " Use 0 or 2 to delete an unwanted alpha channel."},
5738 + {2, " Default is to use same color type as the input file."},
5739 + {2, ""},
5740 +
5741 +#ifdef PNGCRUSH_COUNT_COLORS
5742 + {0, " -cc (do color counting)"},
5743 + {2, ""},
5744 +#endif
5745 +
5746 + {0, " -d directory_name (where output files will go)"},
5747 + {2, ""},
5748 + {2, " If a directory name is given, then the output"},
5749 + {2, " files are placed in it, with the same filenames as"},
5750 + {2, " those of the original files. For example,"},
5751 + {2, " you would type 'pngcrush -directory CRUSHED *.png'"},
5752 + {2, " to get *.png => CRUSHED/*.png"},
5753 + {2, ""},
5754 +
5755 + {0, FAKE_PAUSE_STRING},
5756 +
5757 + {0, " -double_gamma (used for fixing gamma in PhotoShop 5.0/5.02 files)"},
5758 + {2, ""},
5759 + {2, " It has been claimed that the PS5 bug is actually"},
5760 + {2, " more complex than that, in some unspecified way."},
5761 + {2, ""},
5762 +
5763 + {0, " -e extension (used for creating output filename)"},
5764 + {2, ""},
5765 + {2, " e.g., -ext .new means *.png => *.new"},
5766 + {2, " and -e _C.png means *.png => *_C.png"},
5767 + {2, ""},
5768 +
5769 + {0, " -f user_filter [0-5]"},
5770 + {2, ""},
5771 + {2, " filter to use with the method specified in the"},
5772 + {2, " preceding '-m method' or '-brute_force' argument."},
5773 + {2, " 0: none; 1-4: use specified filter; 5: adaptive."},
5774 + {2, ""},
5775 +
5776 + {0, " -fix (fix otherwise fatal conditions such as bad CRCs)"},
5777 + {2, ""},
5778 +
5779 + {0, " -force (write a new output file even if larger than input)"},
5780 + {2, ""},
5781 + {2, " Otherwise the input file will be copied to output"},
5782 + {2, " if it is smaller than any generated file and no chunk"},
5783 + {2, " additions, removals, or changes were requested."},
5784 + {2, ""},
5785 +
5786 +#ifdef PNG_FIXED_POINT_SUPPORTED
5787 + {0, " -g gamma (float or fixed*100000, e.g., 0.45455 or 45455)"},
5788 +#else
5789 + {0, " -g gamma (float, e.g., 0.45455)"},
5790 +#endif
5791 + {2, ""},
5792 + {2, " Value to insert in gAMA chunk, only if the input"},
5793 + {2, " file has no gAMA chunk. To replace an existing"},
5794 + {2, " gAMA chunk, use the '-replace_gamma' option."},
5795 + {2, ""},
5796 +
5797 + {0, FAKE_PAUSE_STRING},
5798 +
5799 + {0, " -huffman (use only zlib strategy 2, Huffman-only)"},
5800 + {2, ""},
5801 + {2, " Fast, but almost never very effective except for"},
5802 + {2, " certain rare image types."},
5803 + {2, ""},
5804 +
5805 +#ifdef PNG_iCCP_SUPPORTED
5806 + {0, " -iccp length \"Profile Name\" iccp_file"},
5807 + {2, ""},
5808 + {2, " file with ICC profile to insert in an iCCP chunk."},
5809 + {2, ""},
5810 +#endif
5811 +
5812 +#ifdef PNG_iTXt_SUPPORTED
5813 + {0, " -itxt b[efore_IDAT]|a[fter_IDAT] \"keyword\""},
5814 + {2, " \"language_code\" \"translated_keyword\" \"text\""},
5815 + {2, ""},
5816 + {2, " Uncompressed iTXt chunk to insert (see -text)."},
5817 + {2, ""},
5818 +#endif
5819 +
5820 + {0, " -keep chunk_name"},
5821 + {2, ""},
5822 + {2, " keep named chunk even when pngcrush makes"},
5823 + {2, " changes to the PNG datastream that cause it"},
5824 + {2, " to become invalid. Currently only dSIG is"},
5825 + {2, " recognized as a chunk to be kept."},
5826 + {2, ""},
5827 +
5828 +
5829 + {0, " -l zlib_compression_level [0-9]"},
5830 + {2, ""},
5831 + {2, " zlib compression level to use with method specified"},
5832 + {2, " with the preceding '-m method' or '-brute_force'"},
5833 + {2, " argument."},
5834 + {2, ""},
5835 +
5836 +#ifdef PNGCRUSH_LOCO
5837 + {0, " -loco (\"loco crush\" truecolor PNGs)"},
5838 + {2, ""},
5839 + {2, " Make the file more compressible by performing a"},
5840 + {2, " lossless, reversible, color transformation."},
5841 + {2, " The resulting file is a MNG, not a PNG, and should"},
5842 + {2, " be given the \".mng\" file extension. The"},
5843 + {2, " \"loco\" option has no effect on grayscale or"},
5844 + {2, " indexed-color PNG files."},
5845 + {2, ""},
5846 +#endif
5847 +
5848 + {0, " -m method [0 through " STRNGIFY(MAX_METHODS) "]"},
5849 + {2, ""},
5850 + {2, " pngcrush method to try (0 means try all of 1-10)."},
5851 + {2, " Can be repeated as in '-m 1 -m 4 -m 7'."},
5852 + {2, " This can be useful if pngcrush runs out of memory"},
5853 + {2, " when it tries methods 2, 3, 5, 6, 8, 9, or 10 which"},
5854 + {2, " use filtering and are memory-intensive. Methods"},
5855 + {2, " 1, 4, and 7 use no filtering; methods 11 and up use"},
5856 + {2, " specified filter, compression level, and strategy."},
5857 + {2, ""},
5858 + {2, FAKE_PAUSE_STRING},
5859 +
5860 + {0, " -max maximum_IDAT_size [default "STRNGIFY(PNG_ZBUF_SIZE)"]"},
5861 + {2, ""},
5862 +
5863 +#ifdef PNGCRUSH_LOCO
5864 + {0, " -mng (write a new MNG, do not crush embedded PNGs)"},
5865 + {2, ""},
5866 +#endif
5867 +
5868 +
5869 +#ifdef PNGCRUSH_COUNT_COLORS
5870 + {0, " -no_cc (no color counting)"},
5871 + {2, ""},
5872 +#endif
5873 +
5874 + {0, " -nofilecheck (do not check for infile.png == outfile.png)"},
5875 + {2, ""},
5876 + {2, " To avoid false hits from MSVC-compiled code. Note"},
5877 + {2, " that if you use this option, you are responsible for"},
5878 + {2, " ensuring that the input file is not the output file."},
5879 + {2, ""},
5880 +
5881 + {0, " -n (no save; does not do compression or write output PNG)"},
5882 + {2, ""},
5883 + {2, " Useful in conjunction with -v option to get info."},
5884 + {2, ""},
5885 +
5886 +
5887 + {0, " -plte_len n (truncate PLTE)"},
5888 + {2, ""},
5889 + {2, " Truncates the PLTE. Be sure not to truncate it to"},
5890 + {2, " less than the greatest index present in IDAT."},
5891 + {2, ""},
5892 +
5893 + {0, " -q (quiet)"},
5894 + {2, ""},
5895 +
5896 + {0, " -reduce (do lossless color-type or bit-depth reduction)"},
5897 + {2, ""},
5898 + {2, " (if possible)"},
5899 + {2, ""},
5900 +
5901 + {0, " -rem chunkname (or \"alla\" or \"allb\")"},
5902 + {2, ""},
5903 + {2, " Name of an ancillary chunk or optional PLTE to be"},
5904 + {2, " removed. Be careful with this. Please don't use "},
5905 + {2, " this feature to remove transparency, gamma, copyright,"},
5906 + {2, " or other valuable information. To remove several"},
5907 + {2, " different chunks, repeat: -rem tEXt -rem pHYs."},
5908 + {2, " Known chunks (those in the PNG 1.1 spec or extensions"},
5909 + {2, " document) can be named with all lower-case letters,"},
5910 + {2, " so \"-rem bkgd\" is equivalent to \"-rem bKGD\". But"},
5911 + {2, " note: \"-rem text\" removes all forms of text chunks;"},
5912 + {2, " Exact case is required to remove unknown chunks."},
5913 + {2, " To do surgery with a chain-saw, \"-rem alla\" removes"},
5914 + {2, " all known ancillary chunks except for tRNS, and"},
5915 + {2, " \"-rem allb\" removes all but tRNS and gAMA."},
5916 + {2, ""},
5917 +
5918 + {0, FAKE_PAUSE_STRING},
5919 +
5920 +#ifdef PNG_FIXED_POINT_SUPPORTED
5921 + {0, "-replace_gamma gamma (float or fixed*100000) even if gAMA is present."},
5922 +#else
5923 + {0, "-replace_gamma gamma (float, e.g. 0.45455) even if gAMA is present."},
5924 +#endif
5925 + {2, ""},
5926 +
5927 + {0, " -res dpi"},
5928 + {2, ""},
5929 + {2, " Write a pHYs chunk with the given resolution."},
5930 + {2, ""},
5931 +
5932 +#ifdef Z_RLE
5933 + {0, " -rle (use only zlib strategy 3, RLE-only)"},
5934 + {2, ""},
5935 + {2, " A relatively fast subset of the \"-brute\" methods,"},
5936 + {2, " generally more effective than \"-huffman\" on PNG images"},
5937 + {2, " (and quite effective on black-and-white images),"},
5938 + {2, " but not necessarily worth the bother otherwise."},
5939 + {2, ""},
5940 +#endif
5941 +
5942 + {0, " -save (keep all copy-unsafe chunks)"},
5943 + {2, ""},
5944 + {2, " Save otherwise unknown ancillary chunks that would"},
5945 + {2, " be considered copy-unsafe. This option makes"},
5946 + {2, " chunks 'known' to pngcrush, so they can be copied."},
5947 + {2, " It also causes the dSIG chunk to be saved, even when"},
5948 + {2, " it becomes invalid due to datastream changes."},
5949 + {2, ""},
5950 +
5951 + {0, FAKE_PAUSE_STRING},
5952 +
5953 + {0, " -srgb [0, 1, 2, or 3]"},
5954 + {2, ""},
5955 + {2, " Value of 'rendering intent' for sRGB chunk."},
5956 + {2, ""},
5957 +
5958 + {0, " -text b[efore_IDAT]|a[fter_IDAT] \"keyword\" \"text\""},
5959 + {2, ""},
5960 + {2, " tEXt chunk to insert. keyword < 80 chars,"},
5961 + {2, " text < 2048 chars. For now, you can add no more than"},
5962 + {2, " ten tEXt, iTXt, or zTXt chunks per pngcrush run."},
5963 + {2, ""},
5964 +
5965 +#ifdef PNG_tRNS_SUPPORTED
5966 + {0, " -trns_array n trns[0] trns[1] .. trns[n-1]"},
5967 + {2, ""},
5968 + {2, " Insert a tRNS chunk, if no tRNS chunk found in file."},
5969 + {2, " Values are for the tRNS array in indexed-color PNG."},
5970 + {2, ""},
5971 +
5972 + {0, " -trns index red green blue gray"},
5973 + {2, ""},
5974 + {2, " Insert a tRNS chunk, if no tRNS chunk found in file."},
5975 + {2, " You must give all five parameters regardless of the"},
5976 + {2, " color type, scaled to the output bit depth."},
5977 + {2, ""},
5978 +#endif
5979 +
5980 + {0, " -v (display more detailed information)"},
5981 + {2, ""},
5982 + {2, " Repeat the option (use \"-v -v\") for even more."},
5983 + {2, ""},
5984 +
5985 + {0, " -version (display the pngcrush version)"},
5986 + {2, ""},
5987 + {2, " Look for the most recent version of pngcrush at"},
5988 + {2, " http://pmt.sf.net"},
5989 + {2, ""},
5990 +
5991 + {0, " -w compression_window_size [32, 16, 8, 4, 2, 1, 512]"},
5992 + {2, ""},
5993 + {2, " Size of the sliding compression window, in kbytes"},
5994 + {2, " (or bytes, in case of 512). It's best to"},
5995 + {2, " use the default (32) unless you run out of memory."},
5996 + {2, " The program will use a smaller window anyway when"},
5997 + {2, " the uncompressed file is smaller than 16k."},
5998 + {2, ""},
5999 +
6000 +#ifdef Z_RLE
6001 + {0, " -z zlib_strategy [0, 1, 2, or 3]"},
6002 +#else
6003 + {0, " -z zlib_strategy [0, 1, or 2]"},
6004 +#endif
6005 + {2, ""},
6006 + {2, " zlib compression strategy to use with the preceding"},
6007 + {2, " '-m method' argument."},
6008 + {2, ""},
6009 +
6010 + {0, " -zmem zlib_compression_mem_level [1-9, default 9]"},
6011 + {2, ""},
6012 +
6013 +#ifdef PNG_iTXt_SUPPORTED
6014 + {0, " -zitxt b[efore_IDAT]|a[fter_IDAT] \"keyword\""},
6015 + {2, " \"language_code\" \"translated_keyword\" \"text\""},
6016 + {2, ""},
6017 + {2, " Compressed iTXt chunk to insert (see -text)."},
6018 + {2, ""},
6019 +#endif
6020 +
6021 + {0, " -ztxt b[efore_IDAT]|a[fter_IDAT] \"keyword\" \"text\""},
6022 + {2, ""},
6023 + {2, " zTXt chunk to insert (see -text)."},
6024 + {2, ""},
6025 + {2, FAKE_PAUSE_STRING},
6026 +
6027 + {0, " -h (help and legal notices)"},
6028 + {2, ""},
6029 + {2, " Display this information."},
6030 + {2, ""},
6031 +
6032 + {0, " -p (pause)"}
6033 +};
6034 +
6035 +
6036 +
6037 +
6038 +
6039 +void print_usage(int retval)
6040 +{
6041 + int j, jmax;
6042 +
6043 + if (verbose) {
6044 + jmax = sizeof(pngcrush_legal) / sizeof(char *);
6045 + for (j = 0; j < jmax; ++j)
6046 + fprintf(STDERR, "%s\n", pngcrush_legal[j]);
6047 +
6048 + jmax = sizeof(pngcrush_usage) / sizeof(char *);
6049 + for (j = 0; j < jmax; ++j)
6050 + fprintf(STDERR, pngcrush_usage[j], progname); /* special case */
6051 + }
6052 +
6053 + /* this block is also handled specially due to the "else" clause... */
6054 + if (verbose > 1) {
6055 + png_crush_pause();
6056 + fprintf(STDERR,
6057 + "\n"
6058 + "options (Note: any option can be spelled out for clarity, e.g.,\n"
6059 + " \"pngcrush -dir New -method 7 -remove bkgd *.png\"\n"
6060 + " is the same as \"pngcrush -d New -m 7 -rem bkgd *.png\"):"
6061 + "\n\n");
6062 + } else
6063 + fprintf(STDERR, "options:\n");
6064 +
6065 + /* this is the main part of the help screen; it is more complex than the
6066 + * other blocks due to the mix of verbose and non-verbose lines */
6067 + jmax = sizeof(pngcrush_options) / sizeof(struct options_help);
6068 + for (j = 0; j < jmax; ++j) {
6069 + if (verbose >= pngcrush_options[j].verbosity) {
6070 + if (pngcrush_options[j].textline[0] == FAKE_PAUSE_STRING[0])
6071 + png_crush_pause();
6072 + else
6073 + fprintf(STDERR, "%s\n", pngcrush_options[j].textline);
6074 + }
6075 + }
6076 +
6077 + /* due to progname, the verbose part of the -p option is handled explicitly
6078 + * (fortunately, it's the very last option anyway) */
6079 + if (verbose > 1) {
6080 + fprintf(STDERR, "\n"
6081 + " Wait for [enter] key before continuing display.\n"
6082 + " e.g., type '%s -pause -help', if the help\n"
6083 + " screen scrolls out of sight.\n\n", progname);
6084 + }
6085 +
6086 + exit(retval);
6087 +}