zopfli 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +1 -1
  3. data/.travis.yml +24 -0
  4. data/Gemfile +2 -0
  5. data/Rakefile +8 -10
  6. data/ext/extconf.rb +1 -0
  7. data/ext/zopfli.c +37 -17
  8. data/lib/zopfli/version.rb +1 -1
  9. data/smoke.sh +9 -0
  10. data/{test → spec}/fixtures/alice29.txt +0 -0
  11. data/spec/spec_helper.rb +2 -0
  12. data/spec/zopfli_spec.rb +68 -0
  13. data/vendor/zopfli/src/zopfli/blocksplitter.c +34 -44
  14. data/vendor/zopfli/src/zopfli/blocksplitter.h +2 -6
  15. data/vendor/zopfli/src/zopfli/cache.c +3 -1
  16. data/vendor/zopfli/src/zopfli/deflate.c +351 -287
  17. data/vendor/zopfli/src/zopfli/deflate.h +8 -2
  18. data/vendor/zopfli/src/zopfli/gzip_container.c +54 -47
  19. data/vendor/zopfli/src/zopfli/hash.c +18 -10
  20. data/vendor/zopfli/src/zopfli/hash.h +6 -3
  21. data/vendor/zopfli/src/zopfli/katajainen.c +73 -62
  22. data/vendor/zopfli/src/zopfli/lz77.c +190 -42
  23. data/vendor/zopfli/src/zopfli/lz77.h +32 -19
  24. data/vendor/zopfli/src/zopfli/squeeze.c +75 -61
  25. data/vendor/zopfli/src/zopfli/squeeze.h +1 -0
  26. data/vendor/zopfli/src/zopfli/symbols.h +239 -0
  27. data/vendor/zopfli/src/zopfli/util.c +0 -178
  28. data/vendor/zopfli/src/zopfli/util.h +6 -23
  29. data/vendor/zopfli/src/zopfli/zlib_container.c +1 -1
  30. data/vendor/zopfli/src/zopfli/zopfli.h +1 -4
  31. data/vendor/zopfli/src/zopfli/zopfli_bin.c +11 -8
  32. data/zopfli.gemspec +8 -27
  33. metadata +13 -20
  34. data/test/test_zopfli_deflate.rb +0 -45
  35. data/vendor/zopfli/CONTRIBUTING.md +0 -24
  36. data/vendor/zopfli/CONTRIBUTORS +0 -8
  37. data/vendor/zopfli/Makefile +0 -42
  38. data/vendor/zopfli/README +0 -32
  39. data/vendor/zopfli/README.zopflipng +0 -35
  40. data/vendor/zopfli/src/zopflipng/lodepng/lodepng.cpp +0 -6252
  41. data/vendor/zopfli/src/zopflipng/lodepng/lodepng.h +0 -1716
  42. data/vendor/zopfli/src/zopflipng/lodepng/lodepng_util.cpp +0 -656
  43. data/vendor/zopfli/src/zopflipng/lodepng/lodepng_util.h +0 -151
  44. data/vendor/zopfli/src/zopflipng/zopflipng_bin.cc +0 -408
  45. data/vendor/zopfli/src/zopflipng/zopflipng_lib.cc +0 -492
  46. data/vendor/zopfli/src/zopflipng/zopflipng_lib.h +0 -134
@@ -1,151 +0,0 @@
1
- /*
2
- LodePNG Utils
3
-
4
- Copyright (c) 2005-2012 Lode Vandevenne
5
-
6
- This software is provided 'as-is', without any express or implied
7
- warranty. In no event will the authors be held liable for any damages
8
- arising from the use of this software.
9
-
10
- Permission is granted to anyone to use this software for any purpose,
11
- including commercial applications, and to alter it and redistribute it
12
- freely, subject to the following restrictions:
13
-
14
- 1. The origin of this software must not be misrepresented; you must not
15
- claim that you wrote the original software. If you use this software
16
- in a product, an acknowledgment in the product documentation would be
17
- appreciated but is not required.
18
-
19
- 2. Altered source versions must be plainly marked as such, and must not be
20
- misrepresented as being the original software.
21
-
22
- 3. This notice may not be removed or altered from any source
23
- distribution.
24
- */
25
-
26
- /*
27
- Extra C++ utilities for LodePNG, for convenience.
28
- */
29
-
30
- #include <string>
31
- #include <vector>
32
- #include "lodepng.h"
33
-
34
- #pragma once
35
-
36
- namespace lodepng
37
- {
38
-
39
- /*
40
- Returns info from the header of the PNG by value, purely for convenience.
41
- Does NOT check for errors. Returns bogus info if the PNG has an error.
42
- Does not require cleanup of allocated memory because no palette or text chunk
43
- info is in the LodePNGInfo object after checking only the header of the PNG.
44
- */
45
- LodePNGInfo getPNGHeaderInfo(const std::vector<unsigned char>& png);
46
-
47
- /*
48
- Get the names and sizes of all chunks in the PNG file.
49
- Returns 0 if ok, non-0 if error happened.
50
- */
51
- unsigned getChunkInfo(std::vector<std::string>& names, std::vector<size_t>& sizes,
52
- const std::vector<unsigned char>& png);
53
-
54
- /*
55
- Returns the names and full chunks (including the name and everything else that
56
- makes up the chunk) for all chunks except IHDR, PLTE, IDAT and IEND.
57
- It separates the chunks into 3 separate lists, representing the chunks between
58
- certain critical chunks: 0: IHDR-PLTE, 1: PLTE-IDAT, 2: IDAT-IEND
59
- Returns 0 if ok, non-0 if error happened.
60
- */
61
- unsigned getChunks(std::vector<std::string> names[3],
62
- std::vector<std::vector<unsigned char> > chunks[3],
63
- const std::vector<unsigned char>& png);
64
-
65
- /*
66
- Inserts chunks into the given png file. The chunks must be fully encoded,
67
- including length, type, content and CRC.
68
- The array index determines where it goes:
69
- 0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND.
70
- They're appended at the end of those locations within the PNG.
71
- Returns 0 if ok, non-0 if error happened.
72
- */
73
- unsigned insertChunks(std::vector<unsigned char>& png,
74
- const std::vector<std::vector<unsigned char> > chunks[3]);
75
-
76
- /*
77
- Get the filtertypes of each scanline in this PNG file.
78
- Returns 0 if ok, 1 if PNG decoding error happened.
79
-
80
- For a non-interlaced PNG, it returns one filtertype per scanline, in order.
81
-
82
- For interlaced PNGs, it returns a result as if it's not interlaced. It returns
83
- one filtertype per scanline, in order. The values match pass 6 and 7 of the
84
- Adam7 interlacing, alternating between the two, so that the values correspond
85
- the most to their scanlines.
86
- */
87
- unsigned getFilterTypes(std::vector<unsigned char>& filterTypes, const std::vector<unsigned char>& png);
88
-
89
- /*
90
- Get the filtertypes of each scanline in every interlace pass this PNG file.
91
- Returns 0 if ok, 1 if PNG decoding error happened.
92
-
93
- For a non-interlaced PNG, it returns one filtertype per scanline, in order, in
94
- a single std::vector in filterTypes.
95
-
96
- For an interlaced PNG, it returns 7 std::vectors in filterTypes, one for each
97
- Adam7 pass. The amount of values per pass can be calculated as follows, where
98
- w and h are the size of the image and all divisions are integer divisions:
99
- pass 1: (h + 7) / 8
100
- pass 2: w <= 4 ? 0 : (h + 7) / 8
101
- pass 3: h <= 4 ? 0 : (h + 7) / 8
102
- pass 4: w <= 2 ? 0 : (h + 3) / 4
103
- pass 5: h <= 2 ? 0 : (h + 3) / 4
104
- pass 6: w <= 1 ? 0 : (h + 1) / 2
105
- pass 7: h <= 1 ? 0 : (h + 1) / 2
106
- */
107
- unsigned getFilterTypesInterlaced(std::vector<std::vector<unsigned char> >& filterTypes,
108
- const std::vector<unsigned char>& png);
109
-
110
- /*
111
- Returns the value of the i-th pixel in an image with 1, 2, 4 or 8-bit color.
112
- E.g. if bits is 4 and i is 5, it returns the 5th nibble (4-bit group), which
113
- is the second half of the 3th byte, in big endian (PNG's endian order).
114
- */
115
- int getPaletteValue(const unsigned char* data, size_t i, int bits);
116
-
117
- /*
118
- The information for extractZlibInfo.
119
- */
120
- struct ZlibBlockInfo
121
- {
122
- int btype; //block type (0-2)
123
- size_t compressedbits; //size of compressed block in bits
124
- size_t uncompressedbytes; //size of uncompressed block in bytes
125
-
126
- // only filled in for block type 2
127
- size_t treebits; //encoded tree size in bits
128
- int hlit; //the HLIT value that was filled in for this tree
129
- int hdist; //the HDIST value that was filled in for this tree
130
- int hclen; //the HCLEN value that was filled in for this tree
131
- std::vector<int> clcl; //19 code length code lengths (compressed tree's tree)
132
- std::vector<int> treecodes; //N tree codes, with values 0-18. Values 17 or 18 are followed by the repetition value.
133
- std::vector<int> litlenlengths; //288 code lengths for lit/len symbols
134
- std::vector<int> distlengths; //32 code lengths for dist symbols
135
-
136
- // only filled in for block types 1 or 2
137
- std::vector<int> lz77_lcode; //LZ77 codes. 0-255: literals. 256: end symbol. 257-285: length code of length/dist pairs
138
- // the next vectors have the same size as lz77_lcode, but an element only has meaningful value if lz77_lcode contains a length code.
139
- std::vector<int> lz77_dcode;
140
- std::vector<int> lz77_lbits;
141
- std::vector<int> lz77_dbits;
142
- std::vector<int> lz77_lvalue;
143
- std::vector<int> lz77_dvalue;
144
- size_t numlit; //number of lit codes in this block
145
- size_t numlen; //number of len codes in this block
146
- };
147
-
148
- //Extracts all info needed from a PNG file to reconstruct the zlib compression exactly.
149
- void extractZlibInfo(std::vector<ZlibBlockInfo>& zlibinfo, const std::vector<unsigned char>& in);
150
-
151
- } // namespace lodepng
@@ -1,408 +0,0 @@
1
- // Copyright 2013 Google Inc. All Rights Reserved.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
14
- //
15
- // Author: lode.vandevenne@gmail.com (Lode Vandevenne)
16
- // Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala)
17
-
18
- // Command line tool to recompress and optimize PNG images, using zopflipng_lib.
19
-
20
- #include <stdlib.h>
21
- #include <stdio.h>
22
-
23
- #include "lodepng/lodepng.h"
24
- #include "zopflipng_lib.h"
25
-
26
- // Returns directory path (including last slash) in dir, filename without
27
- // extension in file, extension (including the dot) in ext
28
- void GetFileNameParts(const std::string& filename,
29
- std::string* dir, std::string* file, std::string* ext) {
30
- size_t npos = (size_t)(-1);
31
- size_t slashpos = filename.find_last_of("/\\");
32
- std::string nodir;
33
- if (slashpos == npos) {
34
- *dir = "";
35
- nodir = filename;
36
- } else {
37
- *dir = filename.substr(0, slashpos + 1);
38
- nodir = filename.substr(slashpos + 1);
39
- }
40
- size_t dotpos = nodir.find_last_of('.');
41
- if (dotpos == (size_t)(-1)) {
42
- *file = nodir;
43
- *ext = "";
44
- } else {
45
- *file = nodir.substr(0, dotpos);
46
- *ext = nodir.substr(dotpos);
47
- }
48
- }
49
-
50
- // Returns the size of the file
51
- size_t GetFileSize(const std::string& filename) {
52
- size_t size;
53
- FILE* file = fopen(filename.c_str(), "rb");
54
- if (!file) return 0;
55
- fseek(file , 0 , SEEK_END);
56
- size = static_cast<size_t>(ftell(file));
57
- fclose(file);
58
- return size;
59
- }
60
-
61
- void ShowHelp() {
62
- printf("ZopfliPNG, a Portable Network Graphics (PNG) image optimizer.\n"
63
- "\n"
64
- "Usage: zopflipng [options]... infile.png outfile.png\n"
65
- " zopflipng [options]... --prefix=[fileprefix] [files.png]...\n"
66
- "\n"
67
- "If the output file exists, it is considered a result from a"
68
- " previous run and not overwritten if its filesize is smaller.\n"
69
- "\n"
70
- "Options:\n"
71
- "-m: compress more: use more iterations (depending on file size) and"
72
- " use block split strategy 3\n"
73
- "--prefix=[fileprefix]: Adds a prefix to output filenames. May also"
74
- " contain a directory path. When using a prefix, multiple input files"
75
- " can be given and the output filenames are generated with the"
76
- " prefix\n"
77
- " If --prefix is specified without value, 'zopfli_' is used.\n"
78
- " If input file names contain the prefix, they are not processed but"
79
- " considered as output from previous runs. This is handy when using"
80
- " *.png wildcard expansion with multiple runs.\n"
81
- "-y: do not ask about overwriting files.\n"
82
- "--lossy_transparent: remove colors behind alpha channel 0. No visual"
83
- " difference, removes hidden information.\n"
84
- "--lossy_8bit: convert 16-bit per channel image to 8-bit per"
85
- " channel.\n"
86
- "-d: dry run: don't save any files, just see the console output"
87
- " (e.g. for benchmarking)\n"
88
- "--always_zopflify: always output the image encoded by Zopfli, even if"
89
- " it's bigger than the original, for benchmarking the algorithm. Not"
90
- " good for real optimization.\n"
91
- "-q: use quick, but not very good, compression"
92
- " (e.g. for only trying the PNG filter and color types)\n"
93
- "--iterations=[number]: number of iterations, more iterations makes it"
94
- " slower but provides slightly better compression. Default: 15 for"
95
- " small files, 5 for large files.\n"
96
- "--splitting=[0-3]: block split strategy:"
97
- " 0=none, 1=first, 2=last, 3=try both and take the best\n"
98
- "--filters=[types]: filter strategies to try:\n"
99
- " 0-4: give all scanlines PNG filter type 0-4\n"
100
- " m: minimum sum\n"
101
- " e: entropy\n"
102
- " p: predefined (keep from input, this likely overlaps another"
103
- " strategy)\n"
104
- " b: brute force (experimental)\n"
105
- " By default, if this argument is not given, one that is most likely"
106
- " the best for this image is chosen by trying faster compression with"
107
- " each type.\n"
108
- " If this argument is used, all given filter types"
109
- " are tried with slow compression and the best result retained. A good"
110
- " set of filters to try is --filters=0me.\n"
111
- "--keepchunks=nAME,nAME,...: keep metadata chunks with these names"
112
- " that would normally be removed, e.g. tEXt,zTXt,iTXt,gAMA, ... \n"
113
- " Due to adding extra data, this increases the result size. By default"
114
- " ZopfliPNG only keeps the following chunks because they are"
115
- " essential: IHDR, PLTE, tRNS, IDAT and IEND.\n"
116
- "\n"
117
- "Usage examples:\n"
118
- "Optimize a file and overwrite if smaller: zopflipng infile.png"
119
- " outfile.png\n"
120
- "Compress more: zopflipng -m infile.png outfile.png\n"
121
- "Optimize multiple files: zopflipng --prefix a.png b.png c.png\n"
122
- "Compress really good and trying all filter strategies: zopflipng"
123
- " --iterations=500 --splitting=3 --filters=01234mepb"
124
- " --lossy_8bit --lossy_transparent infile.png outfile.png\n");
125
- }
126
-
127
- void PrintSize(const char* label, size_t size) {
128
- printf("%s: %d (%dK)\n", label, (int) size, (int) size / 1024);
129
- }
130
-
131
- void PrintResultSize(const char* label, size_t oldsize, size_t newsize) {
132
- printf("%s: %d (%dK). Percentage of original: %.3f%%\n",
133
- label, (int) newsize, (int) newsize / 1024, newsize * 100.0 / oldsize);
134
- }
135
-
136
- int main(int argc, char *argv[]) {
137
- if (argc < 2) {
138
- ShowHelp();
139
- return 0;
140
- }
141
-
142
- ZopfliPNGOptions png_options;
143
-
144
- // cmd line options
145
- bool always_zopflify = false; // overwrite file even if we have bigger result
146
- bool yes = false; // do not ask to overwrite files
147
- bool dryrun = false; // never save anything
148
-
149
- std::string user_out_filename; // output filename if no prefix is used
150
- bool use_prefix = false;
151
- std::string prefix = "zopfli_"; // prefix for output filenames
152
-
153
- std::vector<std::string> files;
154
- for (int i = 1; i < argc; i++) {
155
- std::string arg = argv[i];
156
- if (arg[0] == '-' && arg.size() > 1 && arg[1] != '-') {
157
- for (size_t pos = 1; pos < arg.size(); pos++) {
158
- char c = arg[pos];
159
- if (c == 'y') {
160
- yes = true;
161
- } else if (c == 'd') {
162
- dryrun = true;
163
- } else if (c == 'm') {
164
- png_options.num_iterations *= 4;
165
- png_options.num_iterations_large *= 4;
166
- png_options.block_split_strategy = 3;
167
- } else if (c == 'q') {
168
- png_options.use_zopfli = false;
169
- } else if (c == 'h') {
170
- ShowHelp();
171
- return 0;
172
- } else {
173
- printf("Unknown flag: %c\n", c);
174
- return 0;
175
- }
176
- }
177
- } else if (arg[0] == '-' && arg.size() > 1 && arg[1] == '-') {
178
- size_t eq = arg.find('=');
179
- std::string name = arg.substr(0, eq);
180
- std::string value = eq >= arg.size() - 1 ? "" : arg.substr(eq + 1);
181
- int num = atoi(value.c_str());
182
- if (name == "--always_zopflify") {
183
- always_zopflify = true;
184
- } else if (name == "--verbose") {
185
- png_options.verbose = true;
186
- } else if (name == "--lossy_transparent") {
187
- png_options.lossy_transparent = true;
188
- } else if (name == "--lossy_8bit") {
189
- png_options.lossy_8bit = true;
190
- } else if (name == "--iterations") {
191
- if (num < 1) num = 1;
192
- png_options.num_iterations = num;
193
- png_options.num_iterations_large = num;
194
- } else if (name == "--splitting") {
195
- if (num < 0 || num > 3) num = 1;
196
- png_options.block_split_strategy = num;
197
- } else if (name == "--filters") {
198
- for (size_t j = 0; j < value.size(); j++) {
199
- ZopfliPNGFilterStrategy strategy = kStrategyZero;
200
- char f = value[j];
201
- switch (f) {
202
- case '0': strategy = kStrategyZero; break;
203
- case '1': strategy = kStrategyOne; break;
204
- case '2': strategy = kStrategyTwo; break;
205
- case '3': strategy = kStrategyThree; break;
206
- case '4': strategy = kStrategyFour; break;
207
- case 'm': strategy = kStrategyMinSum; break;
208
- case 'e': strategy = kStrategyEntropy; break;
209
- case 'p': strategy = kStrategyPredefined; break;
210
- case 'b': strategy = kStrategyBruteForce; break;
211
- default:
212
- printf("Unknown filter strategy: %c\n", f);
213
- return 1;
214
- }
215
- png_options.filter_strategies.push_back(strategy);
216
- // Enable auto filter strategy only if no user-specified filter is
217
- // given.
218
- png_options.auto_filter_strategy = false;
219
- }
220
- } else if (name == "--keepchunks") {
221
- bool correct = true;
222
- if ((value.size() + 1) % 5 != 0) correct = false;
223
- for (size_t i = 0; i + 4 <= value.size() && correct; i += 5) {
224
- png_options.keepchunks.push_back(value.substr(i, 4));
225
- if (i > 4 && value[i - 1] != ',') correct = false;
226
- }
227
- if (!correct) {
228
- printf("Error: keepchunks format must be like for example:\n"
229
- " --keepchunks=gAMA,cHRM,sRGB,iCCP\n");
230
- return 0;
231
- }
232
- } else if (name == "--prefix") {
233
- use_prefix = true;
234
- if (!value.empty()) prefix = value;
235
- } else if (name == "--help") {
236
- ShowHelp();
237
- return 0;
238
- } else {
239
- printf("Unknown flag: %s\n", name.c_str());
240
- return 0;
241
- }
242
- } else {
243
- files.push_back(argv[i]);
244
- }
245
- }
246
-
247
- if (!use_prefix) {
248
- if (files.size() == 2) {
249
- // The second filename is the output instead of an input if no prefix is
250
- // given.
251
- user_out_filename = files[1];
252
- files.resize(1);
253
- } else {
254
- printf("Please provide one input and output filename\n\n");
255
- ShowHelp();
256
- return 0;
257
- }
258
- }
259
-
260
- size_t total_in_size = 0;
261
- // Total output size, taking input size if the input file was smaller
262
- size_t total_out_size = 0;
263
- // Total output size that zopfli produced, even if input was smaller, for
264
- // benchmark information
265
- size_t total_out_size_zopfli = 0;
266
- size_t total_errors = 0;
267
- size_t total_files = 0;
268
- size_t total_files_smaller = 0;
269
- size_t total_files_saved = 0;
270
- size_t total_files_equal = 0;
271
-
272
- for (size_t i = 0; i < files.size(); i++) {
273
- if (use_prefix && files.size() > 1) {
274
- std::string dir, file, ext;
275
- GetFileNameParts(files[i], &dir, &file, &ext);
276
- // avoid doing filenames which were already output by this so that you
277
- // don't get zopfli_zopfli_zopfli_... files after multiple runs.
278
- if (file.find(prefix) == 0) continue;
279
- }
280
-
281
- total_files++;
282
-
283
- printf("Optimizing %s\n", files[i].c_str());
284
- std::vector<unsigned char> image;
285
- unsigned w, h;
286
- std::vector<unsigned char> origpng;
287
- unsigned error;
288
- lodepng::State inputstate;
289
- std::vector<unsigned char> resultpng;
290
-
291
- lodepng::load_file(origpng, files[i]);
292
- error = ZopfliPNGOptimize(origpng, png_options, true, &resultpng);
293
-
294
- if (error) {
295
- printf("Decoding error %u: %s\n", error, lodepng_error_text(error));
296
- }
297
-
298
- // Verify result, check that the result causes no decoding errors
299
- if (!error) {
300
- error = lodepng::decode(image, w, h, inputstate, resultpng);
301
- if (error) printf("Error: verification of result failed.\n");
302
- }
303
-
304
- if (error) {
305
- printf("There was an error\n");
306
- total_errors++;
307
- } else {
308
- size_t origsize = GetFileSize(files[i]);
309
- size_t resultsize = resultpng.size();
310
-
311
- if (resultsize < origsize) {
312
- printf("Result is smaller\n");
313
- } else if (resultsize == origsize) {
314
- printf("Result has exact same size\n");
315
- } else {
316
- printf(always_zopflify
317
- ? "Original was smaller\n"
318
- : "Preserving original PNG since it was smaller\n");
319
- }
320
- PrintSize("Input size", origsize);
321
- PrintResultSize("Result size", origsize, resultsize);
322
-
323
- std::string out_filename = user_out_filename;
324
- if (use_prefix) {
325
- std::string dir, file, ext;
326
- GetFileNameParts(files[i], &dir, &file, &ext);
327
- out_filename = dir + prefix + file + ext;
328
- }
329
- bool different_output_name = out_filename != files[i];
330
-
331
- total_in_size += origsize;
332
- total_out_size_zopfli += resultpng.size();
333
- if (resultpng.size() < origsize) total_files_smaller++;
334
- else if (resultpng.size() == origsize) total_files_equal++;
335
-
336
- if (!always_zopflify && resultpng.size() > origsize) {
337
- // Set output file to input since input was smaller.
338
- resultpng = origpng;
339
- }
340
-
341
- size_t origoutfilesize = GetFileSize(out_filename);
342
- bool already_exists = true;
343
- if (origoutfilesize == 0) already_exists = false;
344
-
345
- // When using a prefix, and the output file already exist, assume it's
346
- // from a previous run. If that file is smaller, it may represent a
347
- // previous run with different parameters that gave a smaller PNG image.
348
- // In that case, do not overwrite it. This behaviour can be removed by
349
- // adding the always_zopflify flag.
350
- bool keep_earlier_output_file = already_exists &&
351
- resultpng.size() >= origoutfilesize && !always_zopflify && use_prefix;
352
-
353
- if (keep_earlier_output_file) {
354
- // An output file from a previous run is kept, add that files' size
355
- // to the output size statistics.
356
- total_out_size += origoutfilesize;
357
- if (different_output_name) {
358
- printf(resultpng.size() == origoutfilesize
359
- ? "File not written because a previous run was as good.\n"
360
- : "File not written because a previous run was better.\n");
361
- }
362
- } else {
363
- bool confirmed = true;
364
- if (!yes && !dryrun && already_exists) {
365
- printf("File %s exists, overwrite? (y/N) ", out_filename.c_str());
366
- char answer = 0;
367
- // Read the first character, the others and enter with getchar.
368
- while (int input = getchar()) {
369
- if (input == '\n' || input == EOF) break;
370
- else if (!answer) answer = input;
371
- }
372
- confirmed = answer == 'y' || answer == 'Y';
373
- }
374
- if (confirmed) {
375
- if (!dryrun) {
376
- lodepng::save_file(resultpng, out_filename);
377
- total_files_saved++;
378
- }
379
- total_out_size += resultpng.size();
380
- } else {
381
- // An output file from a previous run is kept, add that files' size
382
- // to the output size statistics.
383
- total_out_size += origoutfilesize;
384
- }
385
- }
386
- }
387
- printf("\n");
388
- }
389
-
390
- if (total_files > 1) {
391
- printf("Summary for all files:\n");
392
- printf("Files tried: %d\n", (int) total_files);
393
- printf("Files smaller: %d\n", (int) total_files_smaller);
394
- if (total_files_equal) {
395
- printf("Files equal: %d\n", (int) total_files_equal);
396
- }
397
- printf("Files saved: %d\n", (int) total_files_saved);
398
- if (total_errors) printf("Errors: %d\n", (int) total_errors);
399
- PrintSize("Total input size", total_in_size);
400
- PrintResultSize("Total output size", total_in_size, total_out_size);
401
- PrintResultSize("Benchmark result size",
402
- total_in_size, total_out_size_zopfli);
403
- }
404
-
405
- if (dryrun) printf("No files were written because dry run was specified\n");
406
-
407
- return total_errors;
408
- }