zopfli 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/main.yml +35 -0
- data/.github/workflows/publish.yml +34 -0
- data/.gitmodules +1 -1
- data/Gemfile +4 -0
- data/README.md +6 -1
- data/Rakefile +14 -10
- data/ext/extconf.rb +36 -32
- data/ext/zopfli.c +52 -20
- data/lib/zopfli/version.rb +1 -1
- data/smoke.sh +9 -0
- data/test/test_helper.rb +7 -0
- data/test/zopfli_test.rb +63 -0
- data/vendor/zopfli/src/zopfli/blocksplitter.c +41 -53
- data/vendor/zopfli/src/zopfli/blocksplitter.h +2 -6
- data/vendor/zopfli/src/zopfli/cache.c +6 -0
- data/vendor/zopfli/src/zopfli/deflate.c +613 -381
- data/vendor/zopfli/src/zopfli/deflate.h +8 -2
- data/vendor/zopfli/src/zopfli/gzip_container.c +54 -47
- data/vendor/zopfli/src/zopfli/hash.c +18 -10
- data/vendor/zopfli/src/zopfli/hash.h +10 -7
- data/vendor/zopfli/src/zopfli/katajainen.c +73 -62
- data/vendor/zopfli/src/zopfli/katajainen.h +1 -1
- data/vendor/zopfli/src/zopfli/lz77.c +190 -42
- data/vendor/zopfli/src/zopfli/lz77.h +39 -23
- data/vendor/zopfli/src/zopfli/squeeze.c +75 -61
- data/vendor/zopfli/src/zopfli/squeeze.h +1 -0
- data/vendor/zopfli/src/zopfli/symbols.h +239 -0
- data/vendor/zopfli/src/zopfli/util.c +0 -178
- data/vendor/zopfli/src/zopfli/util.h +6 -23
- data/vendor/zopfli/src/zopfli/zlib_container.c +1 -1
- data/vendor/zopfli/src/zopfli/zopfli.h +1 -4
- data/vendor/zopfli/src/zopfli/zopfli_bin.c +31 -15
- data/zopfli.gemspec +12 -32
- metadata +20 -68
- data/test/fixtures/alice29.txt +0 -3609
- data/test/test_zopfli_deflate.rb +0 -47
- data/vendor/zopfli/CONTRIBUTORS +0 -7
- data/vendor/zopfli/README +0 -32
- data/vendor/zopfli/README.zopflipng +0 -35
- data/vendor/zopfli/makefile +0 -37
- data/vendor/zopfli/src/zopflipng/lodepng/lodepng.cpp +0 -6253
- data/vendor/zopfli/src/zopflipng/lodepng/lodepng.h +0 -1705
- data/vendor/zopfli/src/zopflipng/lodepng/lodepng_util.cpp +0 -656
- data/vendor/zopfli/src/zopflipng/lodepng/lodepng_util.h +0 -151
- data/vendor/zopfli/src/zopflipng/zopflipng_bin.cc +0 -407
- data/vendor/zopfli/src/zopflipng/zopflipng_lib.cc +0 -376
- data/vendor/zopfli/src/zopflipng/zopflipng_lib.h +0 -79
@@ -30,21 +30,17 @@ ones that enhance it.
|
|
30
30
|
|
31
31
|
#include <stdlib.h>
|
32
32
|
|
33
|
+
#include "lz77.h"
|
33
34
|
#include "zopfli.h"
|
34
35
|
|
35
36
|
|
36
37
|
/*
|
37
38
|
Does blocksplitting on LZ77 data.
|
38
39
|
The output splitpoints are indices in the LZ77 data.
|
39
|
-
litlens: lz77 lit/lengths
|
40
|
-
dists: lz77 distances
|
41
|
-
llsize: size of litlens and dists
|
42
40
|
maxblocks: set a limit to the amount of blocks. Set to 0 to mean no limit.
|
43
41
|
*/
|
44
42
|
void ZopfliBlockSplitLZ77(const ZopfliOptions* options,
|
45
|
-
const
|
46
|
-
const unsigned short* dists,
|
47
|
-
size_t llsize, size_t maxblocks,
|
43
|
+
const ZopfliLZ77Store* lz77, size_t maxblocks,
|
48
44
|
size_t** splitpoints, size_t* npoints);
|
49
45
|
|
50
46
|
/*
|
@@ -31,6 +31,12 @@ void ZopfliInitCache(size_t blocksize, ZopfliLongestMatchCache* lmc) {
|
|
31
31
|
lmc->dist = (unsigned short*)malloc(sizeof(unsigned short) * blocksize);
|
32
32
|
/* Rather large amount of memory. */
|
33
33
|
lmc->sublen = (unsigned char*)malloc(ZOPFLI_CACHE_LENGTH * 3 * blocksize);
|
34
|
+
if(lmc->sublen == NULL) {
|
35
|
+
fprintf(stderr,
|
36
|
+
"Error: Out of memory. Tried allocating %lu bytes of memory.\n",
|
37
|
+
ZOPFLI_CACHE_LENGTH * 3 * blocksize);
|
38
|
+
exit (EXIT_FAILURE);
|
39
|
+
}
|
34
40
|
|
35
41
|
/* length > 0 and dist 0 is invalid combination, which indicates on purpose
|
36
42
|
that this cache value is not filled in yet. */
|
@@ -24,15 +24,22 @@ Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala)
|
|
24
24
|
#include <stdlib.h>
|
25
25
|
|
26
26
|
#include "blocksplitter.h"
|
27
|
-
#include "lz77.h"
|
28
27
|
#include "squeeze.h"
|
28
|
+
#include "symbols.h"
|
29
29
|
#include "tree.h"
|
30
30
|
|
31
|
+
/*
|
32
|
+
bp = bitpointer, always in range [0, 7].
|
33
|
+
The outsize is number of necessary bytes to encode the bits.
|
34
|
+
Given the value of bp and the amount of bytes, the amount of bits represented
|
35
|
+
is not simply bytesize * 8 + bp because even representing one bit requires a
|
36
|
+
whole byte. It is: (bp == 0) ? (bytesize * 8) : ((bytesize - 1) * 8 + bp)
|
37
|
+
*/
|
31
38
|
static void AddBit(int bit,
|
32
39
|
unsigned char* bp, unsigned char** out, size_t* outsize) {
|
33
|
-
if (
|
34
|
-
(*out)[*outsize - 1] |= bit <<
|
35
|
-
(*bp)
|
40
|
+
if (*bp == 0) ZOPFLI_APPEND_DATA(0, out, outsize);
|
41
|
+
(*out)[*outsize - 1] |= bit << *bp;
|
42
|
+
*bp = (*bp + 1) & 7;
|
36
43
|
}
|
37
44
|
|
38
45
|
static void AddBits(unsigned symbol, unsigned length,
|
@@ -41,9 +48,9 @@ static void AddBits(unsigned symbol, unsigned length,
|
|
41
48
|
unsigned i;
|
42
49
|
for (i = 0; i < length; i++) {
|
43
50
|
unsigned bit = (symbol >> i) & 1;
|
44
|
-
if (
|
45
|
-
(*out)[*outsize - 1] |= bit <<
|
46
|
-
(*bp)
|
51
|
+
if (*bp == 0) ZOPFLI_APPEND_DATA(0, out, outsize);
|
52
|
+
(*out)[*outsize - 1] |= bit << *bp;
|
53
|
+
*bp = (*bp + 1) & 7;
|
47
54
|
}
|
48
55
|
}
|
49
56
|
|
@@ -58,9 +65,9 @@ static void AddHuffmanBits(unsigned symbol, unsigned length,
|
|
58
65
|
unsigned i;
|
59
66
|
for (i = 0; i < length; i++) {
|
60
67
|
unsigned bit = (symbol >> (length - i - 1)) & 1;
|
61
|
-
if (
|
62
|
-
(*out)[*outsize - 1] |= bit <<
|
63
|
-
(*bp)
|
68
|
+
if (*bp == 0) ZOPFLI_APPEND_DATA(0, out, outsize);
|
69
|
+
(*out)[*outsize - 1] |= bit << *bp;
|
70
|
+
*bp = (*bp + 1) & 7;
|
64
71
|
}
|
65
72
|
}
|
66
73
|
|
@@ -91,141 +98,195 @@ static void PatchDistanceCodesForBuggyDecoders(unsigned* d_lengths) {
|
|
91
98
|
}
|
92
99
|
}
|
93
100
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
101
|
+
/*
|
102
|
+
Encodes the Huffman tree and returns how many bits its encoding takes. If out
|
103
|
+
is a null pointer, only returns the size and runs faster.
|
104
|
+
*/
|
105
|
+
static size_t EncodeTree(const unsigned* ll_lengths,
|
106
|
+
const unsigned* d_lengths,
|
107
|
+
int use_16, int use_17, int use_18,
|
108
|
+
unsigned char* bp,
|
109
|
+
unsigned char** out, size_t* outsize) {
|
110
|
+
unsigned lld_total; /* Total amount of literal, length, distance codes. */
|
111
|
+
/* Runlength encoded version of lengths of litlen and dist trees. */
|
112
|
+
unsigned* rle = 0;
|
103
113
|
unsigned* rle_bits = 0; /* Extra bits for rle values 16, 17 and 18. */
|
104
114
|
size_t rle_size = 0; /* Size of rle array. */
|
105
115
|
size_t rle_bits_size = 0; /* Should have same value as rle_size. */
|
106
|
-
unsigned hlit = 29;
|
116
|
+
unsigned hlit = 29; /* 286 - 257 */
|
107
117
|
unsigned hdist = 29; /* 32 - 1, but gzip does not like hdist > 29.*/
|
108
118
|
unsigned hclen;
|
119
|
+
unsigned hlit2;
|
109
120
|
size_t i, j;
|
110
121
|
size_t clcounts[19];
|
111
122
|
unsigned clcl[19]; /* Code length code lengths. */
|
112
123
|
unsigned clsymbols[19];
|
113
124
|
/* The order in which code length code lengths are encoded as per deflate. */
|
114
|
-
unsigned order[19] = {
|
125
|
+
static const unsigned order[19] = {
|
115
126
|
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
116
127
|
};
|
128
|
+
int size_only = !out;
|
129
|
+
size_t result_size = 0;
|
130
|
+
|
131
|
+
for(i = 0; i < 19; i++) clcounts[i] = 0;
|
117
132
|
|
118
133
|
/* Trim zeros. */
|
119
134
|
while (hlit > 0 && ll_lengths[257 + hlit - 1] == 0) hlit--;
|
120
135
|
while (hdist > 0 && d_lengths[1 + hdist - 1] == 0) hdist--;
|
136
|
+
hlit2 = hlit + 257;
|
121
137
|
|
122
|
-
lld_total =
|
123
|
-
lld_lengths = (unsigned*)malloc(sizeof(*lld_lengths) * lld_total);
|
124
|
-
if (!lld_lengths) exit(-1); /* Allocation failed. */
|
138
|
+
lld_total = hlit2 + hdist + 1;
|
125
139
|
|
126
140
|
for (i = 0; i < lld_total; i++) {
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
count++;
|
141
|
+
/* This is an encoding of a huffman tree, so now the length is a symbol */
|
142
|
+
unsigned char symbol = i < hlit2 ? ll_lengths[i] : d_lengths[i - hlit2];
|
143
|
+
unsigned count = 1;
|
144
|
+
if(use_16 || (symbol == 0 && (use_17 || use_18))) {
|
145
|
+
for (j = i + 1; j < lld_total && symbol ==
|
146
|
+
(j < hlit2 ? ll_lengths[j] : d_lengths[j - hlit2]); j++) {
|
147
|
+
count++;
|
148
|
+
}
|
136
149
|
}
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
150
|
+
i += count - 1;
|
151
|
+
|
152
|
+
/* Repetitions of zeroes */
|
153
|
+
if (symbol == 0 && count >= 3) {
|
154
|
+
if (use_18) {
|
155
|
+
while (count >= 11) {
|
156
|
+
unsigned count2 = count > 138 ? 138 : count;
|
157
|
+
if (!size_only) {
|
158
|
+
ZOPFLI_APPEND_DATA(18, &rle, &rle_size);
|
159
|
+
ZOPFLI_APPEND_DATA(count2 - 11, &rle_bits, &rle_bits_size);
|
160
|
+
}
|
161
|
+
clcounts[18]++;
|
162
|
+
count -= count2;
|
146
163
|
}
|
147
|
-
}
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
164
|
+
}
|
165
|
+
if (use_17) {
|
166
|
+
while (count >= 3) {
|
167
|
+
unsigned count2 = count > 10 ? 10 : count;
|
168
|
+
if (!size_only) {
|
169
|
+
ZOPFLI_APPEND_DATA(17, &rle, &rle_size);
|
170
|
+
ZOPFLI_APPEND_DATA(count2 - 3, &rle_bits, &rle_bits_size);
|
171
|
+
}
|
172
|
+
clcounts[17]++;
|
173
|
+
count -= count2;
|
155
174
|
}
|
156
|
-
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
/* Repetitions of any symbol */
|
179
|
+
if (use_16 && count >= 4) {
|
180
|
+
count--; /* Since the first one is hardcoded. */
|
181
|
+
clcounts[symbol]++;
|
182
|
+
if (!size_only) {
|
183
|
+
ZOPFLI_APPEND_DATA(symbol, &rle, &rle_size);
|
184
|
+
ZOPFLI_APPEND_DATA(0, &rle_bits, &rle_bits_size);
|
185
|
+
}
|
186
|
+
while (count >= 3) {
|
187
|
+
unsigned count2 = count > 6 ? 6 : count;
|
188
|
+
if (!size_only) {
|
157
189
|
ZOPFLI_APPEND_DATA(16, &rle, &rle_size);
|
158
|
-
ZOPFLI_APPEND_DATA(
|
159
|
-
repeat = 0;
|
160
|
-
}
|
161
|
-
while (repeat != 0) {
|
162
|
-
ZOPFLI_APPEND_DATA(lld_lengths[i], &rle, &rle_size);
|
163
|
-
ZOPFLI_APPEND_DATA(0, &rle_bits, &rle_bits_size);
|
164
|
-
repeat--;
|
190
|
+
ZOPFLI_APPEND_DATA(count2 - 3, &rle_bits, &rle_bits_size);
|
165
191
|
}
|
192
|
+
clcounts[16]++;
|
193
|
+
count -= count2;
|
166
194
|
}
|
167
|
-
|
168
|
-
i += count - 1;
|
169
|
-
} else {
|
170
|
-
ZOPFLI_APPEND_DATA(lld_lengths[i], &rle, &rle_size);
|
171
|
-
ZOPFLI_APPEND_DATA(0, &rle_bits, &rle_bits_size);
|
172
195
|
}
|
173
|
-
assert(rle[rle_size - 1] <= 18);
|
174
|
-
}
|
175
196
|
|
176
|
-
|
177
|
-
clcounts[
|
178
|
-
|
179
|
-
|
180
|
-
|
197
|
+
/* No or insufficient repetition */
|
198
|
+
clcounts[symbol] += count;
|
199
|
+
while (count > 0) {
|
200
|
+
if (!size_only) {
|
201
|
+
ZOPFLI_APPEND_DATA(symbol, &rle, &rle_size);
|
202
|
+
ZOPFLI_APPEND_DATA(0, &rle_bits, &rle_bits_size);
|
203
|
+
}
|
204
|
+
count--;
|
205
|
+
}
|
181
206
|
}
|
182
207
|
|
183
208
|
ZopfliCalculateBitLengths(clcounts, 19, 7, clcl);
|
184
|
-
ZopfliLengthsToSymbols(clcl, 19, 7, clsymbols);
|
209
|
+
if (!size_only) ZopfliLengthsToSymbols(clcl, 19, 7, clsymbols);
|
185
210
|
|
186
211
|
hclen = 15;
|
187
212
|
/* Trim zeros. */
|
188
213
|
while (hclen > 0 && clcounts[order[hclen + 4 - 1]] == 0) hclen--;
|
189
214
|
|
190
|
-
|
191
|
-
|
192
|
-
|
215
|
+
if (!size_only) {
|
216
|
+
AddBits(hlit, 5, bp, out, outsize);
|
217
|
+
AddBits(hdist, 5, bp, out, outsize);
|
218
|
+
AddBits(hclen, 4, bp, out, outsize);
|
219
|
+
|
220
|
+
for (i = 0; i < hclen + 4; i++) {
|
221
|
+
AddBits(clcl[order[i]], 3, bp, out, outsize);
|
222
|
+
}
|
193
223
|
|
194
|
-
|
195
|
-
|
224
|
+
for (i = 0; i < rle_size; i++) {
|
225
|
+
unsigned symbol = clsymbols[rle[i]];
|
226
|
+
AddHuffmanBits(symbol, clcl[rle[i]], bp, out, outsize);
|
227
|
+
/* Extra bits. */
|
228
|
+
if (rle[i] == 16) AddBits(rle_bits[i], 2, bp, out, outsize);
|
229
|
+
else if (rle[i] == 17) AddBits(rle_bits[i], 3, bp, out, outsize);
|
230
|
+
else if (rle[i] == 18) AddBits(rle_bits[i], 7, bp, out, outsize);
|
231
|
+
}
|
196
232
|
}
|
197
233
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
if (rle[i] == 16) AddBits(rle_bits[i], 2, bp, out, outsize);
|
203
|
-
else if (rle[i] == 17) AddBits(rle_bits[i], 3, bp, out, outsize);
|
204
|
-
else if (rle[i] == 18) AddBits(rle_bits[i], 7, bp, out, outsize);
|
234
|
+
result_size += 14; /* hlit, hdist, hclen bits */
|
235
|
+
result_size += (hclen + 4) * 3; /* clcl bits */
|
236
|
+
for(i = 0; i < 19; i++) {
|
237
|
+
result_size += clcl[i] * clcounts[i];
|
205
238
|
}
|
239
|
+
/* Extra bits. */
|
240
|
+
result_size += clcounts[16] * 2;
|
241
|
+
result_size += clcounts[17] * 3;
|
242
|
+
result_size += clcounts[18] * 7;
|
206
243
|
|
207
|
-
|
244
|
+
/* Note: in case of "size_only" these are null pointers so no effect. */
|
208
245
|
free(rle);
|
209
246
|
free(rle_bits);
|
247
|
+
|
248
|
+
return result_size;
|
249
|
+
}
|
250
|
+
|
251
|
+
static void AddDynamicTree(const unsigned* ll_lengths,
|
252
|
+
const unsigned* d_lengths,
|
253
|
+
unsigned char* bp,
|
254
|
+
unsigned char** out, size_t* outsize) {
|
255
|
+
int i;
|
256
|
+
int best = 0;
|
257
|
+
size_t bestsize = 0;
|
258
|
+
|
259
|
+
for(i = 0; i < 8; i++) {
|
260
|
+
size_t size = EncodeTree(ll_lengths, d_lengths,
|
261
|
+
i & 1, i & 2, i & 4,
|
262
|
+
0, 0, 0);
|
263
|
+
if (bestsize == 0 || size < bestsize) {
|
264
|
+
bestsize = size;
|
265
|
+
best = i;
|
266
|
+
}
|
267
|
+
}
|
268
|
+
|
269
|
+
EncodeTree(ll_lengths, d_lengths,
|
270
|
+
best & 1, best & 2, best & 4,
|
271
|
+
bp, out, outsize);
|
210
272
|
}
|
211
273
|
|
212
274
|
/*
|
213
275
|
Gives the exact size of the tree, in bits, as it will be encoded in DEFLATE.
|
214
276
|
*/
|
215
277
|
static size_t CalculateTreeSize(const unsigned* ll_lengths,
|
216
|
-
const unsigned* d_lengths
|
217
|
-
|
218
|
-
|
219
|
-
size_t dummysize = 0;
|
220
|
-
unsigned char bp = 0;
|
221
|
-
|
222
|
-
(void)ll_counts;
|
223
|
-
(void)d_counts;
|
278
|
+
const unsigned* d_lengths) {
|
279
|
+
size_t result = 0;
|
280
|
+
int i;
|
224
281
|
|
225
|
-
|
226
|
-
|
282
|
+
for(i = 0; i < 8; i++) {
|
283
|
+
size_t size = EncodeTree(ll_lengths, d_lengths,
|
284
|
+
i & 1, i & 2, i & 4,
|
285
|
+
0, 0, 0);
|
286
|
+
if (result == 0 || size < result) result = size;
|
287
|
+
}
|
227
288
|
|
228
|
-
return
|
289
|
+
return result;
|
229
290
|
}
|
230
291
|
|
231
292
|
/*
|
@@ -233,8 +294,7 @@ Adds all lit/len and dist codes from the lists as huffman symbols. Does not add
|
|
233
294
|
end code 256. expected_data_size is the uncompressed block size, used for
|
234
295
|
assert, but you can set it to 0 to not do the assertion.
|
235
296
|
*/
|
236
|
-
static void AddLZ77Data(const
|
237
|
-
const unsigned short* dists,
|
297
|
+
static void AddLZ77Data(const ZopfliLZ77Store* lz77,
|
238
298
|
size_t lstart, size_t lend,
|
239
299
|
size_t expected_data_size,
|
240
300
|
const unsigned* ll_symbols, const unsigned* ll_lengths,
|
@@ -245,8 +305,8 @@ static void AddLZ77Data(const unsigned short* litlens,
|
|
245
305
|
size_t i;
|
246
306
|
|
247
307
|
for (i = lstart; i < lend; i++) {
|
248
|
-
unsigned dist = dists[i];
|
249
|
-
unsigned litlen = litlens[i];
|
308
|
+
unsigned dist = lz77->dists[i];
|
309
|
+
unsigned litlen = lz77->litlens[i];
|
250
310
|
if (dist == 0) {
|
251
311
|
assert(litlen < 256);
|
252
312
|
assert(ll_lengths[litlen] > 0);
|
@@ -282,58 +342,326 @@ static void GetFixedTree(unsigned* ll_lengths, unsigned* d_lengths) {
|
|
282
342
|
}
|
283
343
|
|
284
344
|
/*
|
285
|
-
|
345
|
+
Same as CalculateBlockSymbolSize, but for block size smaller than histogram
|
346
|
+
size.
|
286
347
|
*/
|
287
|
-
static size_t
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
size_t lstart, size_t lend) {
|
348
|
+
static size_t CalculateBlockSymbolSizeSmall(const unsigned* ll_lengths,
|
349
|
+
const unsigned* d_lengths,
|
350
|
+
const ZopfliLZ77Store* lz77,
|
351
|
+
size_t lstart, size_t lend) {
|
292
352
|
size_t result = 0;
|
293
353
|
size_t i;
|
294
354
|
for (i = lstart; i < lend; i++) {
|
295
|
-
|
296
|
-
|
355
|
+
assert(i < lz77->size);
|
356
|
+
assert(lz77->litlens[i] < 259);
|
357
|
+
if (lz77->dists[i] == 0) {
|
358
|
+
result += ll_lengths[lz77->litlens[i]];
|
297
359
|
} else {
|
298
|
-
|
299
|
-
|
300
|
-
result +=
|
301
|
-
result +=
|
360
|
+
int ll_symbol = ZopfliGetLengthSymbol(lz77->litlens[i]);
|
361
|
+
int d_symbol = ZopfliGetDistSymbol(lz77->dists[i]);
|
362
|
+
result += ll_lengths[ll_symbol];
|
363
|
+
result += d_lengths[d_symbol];
|
364
|
+
result += ZopfliGetLengthSymbolExtraBits(ll_symbol);
|
365
|
+
result += ZopfliGetDistSymbolExtraBits(d_symbol);
|
302
366
|
}
|
303
367
|
}
|
304
368
|
result += ll_lengths[256]; /*end symbol*/
|
305
369
|
return result;
|
306
370
|
}
|
307
371
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
372
|
+
/*
|
373
|
+
Same as CalculateBlockSymbolSize, but with the histogram provided by the caller.
|
374
|
+
*/
|
375
|
+
static size_t CalculateBlockSymbolSizeGivenCounts(const size_t* ll_counts,
|
376
|
+
const size_t* d_counts,
|
377
|
+
const unsigned* ll_lengths,
|
378
|
+
const unsigned* d_lengths,
|
379
|
+
const ZopfliLZ77Store* lz77,
|
380
|
+
size_t lstart, size_t lend) {
|
381
|
+
size_t result = 0;
|
382
|
+
size_t i;
|
383
|
+
if (lstart + ZOPFLI_NUM_LL * 3 > lend) {
|
384
|
+
return CalculateBlockSymbolSizeSmall(
|
385
|
+
ll_lengths, d_lengths, lz77, lstart, lend);
|
386
|
+
} else {
|
387
|
+
for (i = 0; i < 256; i++) {
|
388
|
+
result += ll_lengths[i] * ll_counts[i];
|
389
|
+
}
|
390
|
+
for (i = 257; i < 286; i++) {
|
391
|
+
result += ll_lengths[i] * ll_counts[i];
|
392
|
+
result += ZopfliGetLengthSymbolExtraBits(i) * ll_counts[i];
|
393
|
+
}
|
394
|
+
for (i = 0; i < 30; i++) {
|
395
|
+
result += d_lengths[i] * d_counts[i];
|
396
|
+
result += ZopfliGetDistSymbolExtraBits(i) * d_counts[i];
|
397
|
+
}
|
398
|
+
result += ll_lengths[256]; /*end symbol*/
|
399
|
+
return result;
|
400
|
+
}
|
401
|
+
}
|
313
402
|
|
314
|
-
|
315
|
-
|
403
|
+
/*
|
404
|
+
Calculates size of the part after the header and tree of an LZ77 block, in bits.
|
405
|
+
*/
|
406
|
+
static size_t CalculateBlockSymbolSize(const unsigned* ll_lengths,
|
407
|
+
const unsigned* d_lengths,
|
408
|
+
const ZopfliLZ77Store* lz77,
|
409
|
+
size_t lstart, size_t lend) {
|
410
|
+
if (lstart + ZOPFLI_NUM_LL * 3 > lend) {
|
411
|
+
return CalculateBlockSymbolSizeSmall(
|
412
|
+
ll_lengths, d_lengths, lz77, lstart, lend);
|
413
|
+
} else {
|
414
|
+
size_t ll_counts[ZOPFLI_NUM_LL];
|
415
|
+
size_t d_counts[ZOPFLI_NUM_D];
|
416
|
+
ZopfliLZ77GetHistogram(lz77, lstart, lend, ll_counts, d_counts);
|
417
|
+
return CalculateBlockSymbolSizeGivenCounts(
|
418
|
+
ll_counts, d_counts, ll_lengths, d_lengths, lz77, lstart, lend);
|
419
|
+
}
|
420
|
+
}
|
316
421
|
|
317
|
-
|
422
|
+
static size_t AbsDiff(size_t x, size_t y) {
|
423
|
+
if (x > y)
|
424
|
+
return x - y;
|
425
|
+
else
|
426
|
+
return y - x;
|
427
|
+
}
|
318
428
|
|
319
|
-
|
429
|
+
/*
|
430
|
+
Changes the population counts in a way that the consequent Huffman tree
|
431
|
+
compression, especially its rle-part, will be more likely to compress this data
|
432
|
+
more efficiently. length contains the size of the histogram.
|
433
|
+
*/
|
434
|
+
void OptimizeHuffmanForRle(int length, size_t* counts) {
|
435
|
+
int i, k, stride;
|
436
|
+
size_t symbol, sum, limit;
|
437
|
+
int* good_for_rle;
|
438
|
+
|
439
|
+
/* 1) We don't want to touch the trailing zeros. We may break the
|
440
|
+
rules of the format by adding more data in the distance codes. */
|
441
|
+
for (; length >= 0; --length) {
|
442
|
+
if (length == 0) {
|
443
|
+
return;
|
444
|
+
}
|
445
|
+
if (counts[length - 1] != 0) {
|
446
|
+
/* Now counts[0..length - 1] does not have trailing zeros. */
|
447
|
+
break;
|
448
|
+
}
|
449
|
+
}
|
450
|
+
/* 2) Let's mark all population counts that already can be encoded
|
451
|
+
with an rle code.*/
|
452
|
+
good_for_rle = (int*)malloc((unsigned)length * sizeof(int));
|
453
|
+
for (i = 0; i < length; ++i) good_for_rle[i] = 0;
|
454
|
+
|
455
|
+
/* Let's not spoil any of the existing good rle codes.
|
456
|
+
Mark any seq of 0's that is longer than 5 as a good_for_rle.
|
457
|
+
Mark any seq of non-0's that is longer than 7 as a good_for_rle.*/
|
458
|
+
symbol = counts[0];
|
459
|
+
stride = 0;
|
460
|
+
for (i = 0; i < length + 1; ++i) {
|
461
|
+
if (i == length || counts[i] != symbol) {
|
462
|
+
if ((symbol == 0 && stride >= 5) || (symbol != 0 && stride >= 7)) {
|
463
|
+
for (k = 0; k < stride; ++k) {
|
464
|
+
good_for_rle[i - k - 1] = 1;
|
465
|
+
}
|
466
|
+
}
|
467
|
+
stride = 1;
|
468
|
+
if (i != length) {
|
469
|
+
symbol = counts[i];
|
470
|
+
}
|
471
|
+
} else {
|
472
|
+
++stride;
|
473
|
+
}
|
474
|
+
}
|
320
475
|
|
321
|
-
|
476
|
+
/* 3) Let's replace those population counts that lead to more rle codes. */
|
477
|
+
stride = 0;
|
478
|
+
limit = counts[0];
|
479
|
+
sum = 0;
|
480
|
+
for (i = 0; i < length + 1; ++i) {
|
481
|
+
if (i == length || good_for_rle[i]
|
482
|
+
/* Heuristic for selecting the stride ranges to collapse. */
|
483
|
+
|| AbsDiff(counts[i], limit) >= 4) {
|
484
|
+
if (stride >= 4 || (stride >= 3 && sum == 0)) {
|
485
|
+
/* The stride must end, collapse what we have, if we have enough (4). */
|
486
|
+
int count = (sum + stride / 2) / stride;
|
487
|
+
if (count < 1) count = 1;
|
488
|
+
if (sum == 0) {
|
489
|
+
/* Don't make an all zeros stride to be upgraded to ones. */
|
490
|
+
count = 0;
|
491
|
+
}
|
492
|
+
for (k = 0; k < stride; ++k) {
|
493
|
+
/* We don't want to change value at counts[i],
|
494
|
+
that is already belonging to the next stride. Thus - 1. */
|
495
|
+
counts[i - k - 1] = count;
|
496
|
+
}
|
497
|
+
}
|
498
|
+
stride = 0;
|
499
|
+
sum = 0;
|
500
|
+
if (i < length - 3) {
|
501
|
+
/* All interesting strides have a count of at least 4,
|
502
|
+
at least when non-zeros. */
|
503
|
+
limit = (counts[i] + counts[i + 1] +
|
504
|
+
counts[i + 2] + counts[i + 3] + 2) / 4;
|
505
|
+
} else if (i < length) {
|
506
|
+
limit = counts[i];
|
507
|
+
} else {
|
508
|
+
limit = 0;
|
509
|
+
}
|
510
|
+
}
|
511
|
+
++stride;
|
512
|
+
if (i != length) {
|
513
|
+
sum += counts[i];
|
514
|
+
}
|
515
|
+
}
|
516
|
+
|
517
|
+
free(good_for_rle);
|
518
|
+
}
|
519
|
+
|
520
|
+
/*
|
521
|
+
Tries out OptimizeHuffmanForRle for this block, if the result is smaller,
|
522
|
+
uses it, otherwise keeps the original. Returns size of encoded tree and data in
|
523
|
+
bits, not including the 3-bit block header.
|
524
|
+
*/
|
525
|
+
static double TryOptimizeHuffmanForRle(
|
526
|
+
const ZopfliLZ77Store* lz77, size_t lstart, size_t lend,
|
527
|
+
const size_t* ll_counts, const size_t* d_counts,
|
528
|
+
unsigned* ll_lengths, unsigned* d_lengths) {
|
529
|
+
size_t ll_counts2[ZOPFLI_NUM_LL];
|
530
|
+
size_t d_counts2[ZOPFLI_NUM_D];
|
531
|
+
unsigned ll_lengths2[ZOPFLI_NUM_LL];
|
532
|
+
unsigned d_lengths2[ZOPFLI_NUM_D];
|
533
|
+
double treesize;
|
534
|
+
double datasize;
|
535
|
+
double treesize2;
|
536
|
+
double datasize2;
|
537
|
+
|
538
|
+
treesize = CalculateTreeSize(ll_lengths, d_lengths);
|
539
|
+
datasize = CalculateBlockSymbolSizeGivenCounts(ll_counts, d_counts,
|
540
|
+
ll_lengths, d_lengths, lz77, lstart, lend);
|
541
|
+
|
542
|
+
memcpy(ll_counts2, ll_counts, sizeof(ll_counts2));
|
543
|
+
memcpy(d_counts2, d_counts, sizeof(d_counts2));
|
544
|
+
OptimizeHuffmanForRle(ZOPFLI_NUM_LL, ll_counts2);
|
545
|
+
OptimizeHuffmanForRle(ZOPFLI_NUM_D, d_counts2);
|
546
|
+
ZopfliCalculateBitLengths(ll_counts2, ZOPFLI_NUM_LL, 15, ll_lengths2);
|
547
|
+
ZopfliCalculateBitLengths(d_counts2, ZOPFLI_NUM_D, 15, d_lengths2);
|
548
|
+
PatchDistanceCodesForBuggyDecoders(d_lengths2);
|
549
|
+
|
550
|
+
treesize2 = CalculateTreeSize(ll_lengths2, d_lengths2);
|
551
|
+
datasize2 = CalculateBlockSymbolSizeGivenCounts(ll_counts, d_counts,
|
552
|
+
ll_lengths2, d_lengths2, lz77, lstart, lend);
|
553
|
+
|
554
|
+
if (treesize2 + datasize2 < treesize + datasize) {
|
555
|
+
memcpy(ll_lengths, ll_lengths2, sizeof(ll_lengths2));
|
556
|
+
memcpy(d_lengths, d_lengths2, sizeof(d_lengths2));
|
557
|
+
return treesize2 + datasize2;
|
558
|
+
}
|
559
|
+
return treesize + datasize;
|
560
|
+
}
|
561
|
+
|
562
|
+
/*
|
563
|
+
Calculates the bit lengths for the symbols for dynamic blocks. Chooses bit
|
564
|
+
lengths that give the smallest size of tree encoding + encoding of all the
|
565
|
+
symbols to have smallest output size. This are not necessarily the ideal Huffman
|
566
|
+
bit lengths. Returns size of encoded tree and data in bits, not including the
|
567
|
+
3-bit block header.
|
568
|
+
*/
|
569
|
+
static double GetDynamicLengths(const ZopfliLZ77Store* lz77,
|
570
|
+
size_t lstart, size_t lend,
|
571
|
+
unsigned* ll_lengths, unsigned* d_lengths) {
|
572
|
+
size_t ll_counts[ZOPFLI_NUM_LL];
|
573
|
+
size_t d_counts[ZOPFLI_NUM_D];
|
574
|
+
|
575
|
+
ZopfliLZ77GetHistogram(lz77, lstart, lend, ll_counts, d_counts);
|
576
|
+
ll_counts[256] = 1; /* End symbol. */
|
577
|
+
ZopfliCalculateBitLengths(ll_counts, ZOPFLI_NUM_LL, 15, ll_lengths);
|
578
|
+
ZopfliCalculateBitLengths(d_counts, ZOPFLI_NUM_D, 15, d_lengths);
|
579
|
+
PatchDistanceCodesForBuggyDecoders(d_lengths);
|
580
|
+
return TryOptimizeHuffmanForRle(
|
581
|
+
lz77, lstart, lend, ll_counts, d_counts, ll_lengths, d_lengths);
|
582
|
+
}
|
583
|
+
|
584
|
+
double ZopfliCalculateBlockSize(const ZopfliLZ77Store* lz77,
|
585
|
+
size_t lstart, size_t lend, int btype) {
|
586
|
+
unsigned ll_lengths[ZOPFLI_NUM_LL];
|
587
|
+
unsigned d_lengths[ZOPFLI_NUM_D];
|
588
|
+
|
589
|
+
double result = 3; /* bfinal and btype bits */
|
590
|
+
|
591
|
+
if (btype == 0) {
|
592
|
+
size_t length = ZopfliLZ77GetByteRange(lz77, lstart, lend);
|
593
|
+
size_t rem = length % 65535;
|
594
|
+
size_t blocks = length / 65535 + (rem ? 1 : 0);
|
595
|
+
/* An uncompressed block must actually be split into multiple blocks if it's
|
596
|
+
larger than 65535 bytes long. Eeach block header is 5 bytes: 3 bits,
|
597
|
+
padding, LEN and NLEN (potential less padding for first one ignored). */
|
598
|
+
return blocks * 5 * 8 + length * 8;
|
599
|
+
} if (btype == 1) {
|
322
600
|
GetFixedTree(ll_lengths, d_lengths);
|
601
|
+
result += CalculateBlockSymbolSize(
|
602
|
+
ll_lengths, d_lengths, lz77, lstart, lend);
|
323
603
|
} else {
|
324
|
-
|
325
|
-
ZopfliCalculateBitLengths(ll_counts, 288, 15, ll_lengths);
|
326
|
-
ZopfliCalculateBitLengths(d_counts, 32, 15, d_lengths);
|
327
|
-
PatchDistanceCodesForBuggyDecoders(d_lengths);
|
328
|
-
result += CalculateTreeSize(ll_lengths, d_lengths, ll_counts, d_counts);
|
604
|
+
result += GetDynamicLengths(lz77, lstart, lend, ll_lengths, d_lengths);
|
329
605
|
}
|
330
606
|
|
331
|
-
result += CalculateBlockSymbolSize(
|
332
|
-
ll_lengths, d_lengths, litlens, dists, lstart, lend);
|
333
|
-
|
334
607
|
return result;
|
335
608
|
}
|
336
609
|
|
610
|
+
double ZopfliCalculateBlockSizeAutoType(const ZopfliLZ77Store* lz77,
|
611
|
+
size_t lstart, size_t lend) {
|
612
|
+
double uncompressedcost = ZopfliCalculateBlockSize(lz77, lstart, lend, 0);
|
613
|
+
/* Don't do the expensive fixed cost calculation for larger blocks that are
|
614
|
+
unlikely to use it. */
|
615
|
+
double fixedcost = (lz77->size > 1000) ?
|
616
|
+
uncompressedcost : ZopfliCalculateBlockSize(lz77, lstart, lend, 1);
|
617
|
+
double dyncost = ZopfliCalculateBlockSize(lz77, lstart, lend, 2);
|
618
|
+
return (uncompressedcost < fixedcost && uncompressedcost < dyncost)
|
619
|
+
? uncompressedcost
|
620
|
+
: (fixedcost < dyncost ? fixedcost : dyncost);
|
621
|
+
}
|
622
|
+
|
623
|
+
/* Since an uncompressed block can be max 65535 in size, it actually adds
|
624
|
+
multible blocks if needed. */
|
625
|
+
static void AddNonCompressedBlock(const ZopfliOptions* options, int final,
|
626
|
+
const unsigned char* in, size_t instart,
|
627
|
+
size_t inend,
|
628
|
+
unsigned char* bp,
|
629
|
+
unsigned char** out, size_t* outsize) {
|
630
|
+
size_t pos = instart;
|
631
|
+
(void)options;
|
632
|
+
for (;;) {
|
633
|
+
size_t i;
|
634
|
+
unsigned short blocksize = 65535;
|
635
|
+
unsigned short nlen;
|
636
|
+
int currentfinal;
|
637
|
+
|
638
|
+
if (pos + blocksize > inend) blocksize = inend - pos;
|
639
|
+
currentfinal = pos + blocksize >= inend;
|
640
|
+
|
641
|
+
nlen = ~blocksize;
|
642
|
+
|
643
|
+
AddBit(final && currentfinal, bp, out, outsize);
|
644
|
+
/* BTYPE 00 */
|
645
|
+
AddBit(0, bp, out, outsize);
|
646
|
+
AddBit(0, bp, out, outsize);
|
647
|
+
|
648
|
+
/* Any bits of input up to the next byte boundary are ignored. */
|
649
|
+
*bp = 0;
|
650
|
+
|
651
|
+
ZOPFLI_APPEND_DATA(blocksize % 256, out, outsize);
|
652
|
+
ZOPFLI_APPEND_DATA((blocksize / 256) % 256, out, outsize);
|
653
|
+
ZOPFLI_APPEND_DATA(nlen % 256, out, outsize);
|
654
|
+
ZOPFLI_APPEND_DATA((nlen / 256) % 256, out, outsize);
|
655
|
+
|
656
|
+
for (i = 0; i < blocksize; i++) {
|
657
|
+
ZOPFLI_APPEND_DATA(in[pos + i], out, outsize);
|
658
|
+
}
|
659
|
+
|
660
|
+
if (currentfinal) break;
|
661
|
+
pos += blocksize;
|
662
|
+
}
|
663
|
+
}
|
664
|
+
|
337
665
|
/*
|
338
666
|
Adds a deflate block with the given LZ77 data to the output.
|
339
667
|
options: global program options
|
@@ -352,22 +680,27 @@ out: dynamic output array to append to
|
|
352
680
|
outsize: dynamic output array size
|
353
681
|
*/
|
354
682
|
static void AddLZ77Block(const ZopfliOptions* options, int btype, int final,
|
355
|
-
const
|
356
|
-
const unsigned short* dists,
|
683
|
+
const ZopfliLZ77Store* lz77,
|
357
684
|
size_t lstart, size_t lend,
|
358
685
|
size_t expected_data_size,
|
359
686
|
unsigned char* bp,
|
360
687
|
unsigned char** out, size_t* outsize) {
|
361
|
-
|
362
|
-
|
363
|
-
unsigned
|
364
|
-
unsigned
|
365
|
-
unsigned ll_symbols[288];
|
366
|
-
unsigned d_symbols[32];
|
688
|
+
unsigned ll_lengths[ZOPFLI_NUM_LL];
|
689
|
+
unsigned d_lengths[ZOPFLI_NUM_D];
|
690
|
+
unsigned ll_symbols[ZOPFLI_NUM_LL];
|
691
|
+
unsigned d_symbols[ZOPFLI_NUM_D];
|
367
692
|
size_t detect_block_size = *outsize;
|
368
693
|
size_t compressed_size;
|
369
694
|
size_t uncompressed_size = 0;
|
370
695
|
size_t i;
|
696
|
+
if (btype == 0) {
|
697
|
+
size_t length = ZopfliLZ77GetByteRange(lz77, lstart, lend);
|
698
|
+
size_t pos = lstart == lend ? 0 : lz77->pos[lstart];
|
699
|
+
size_t end = pos + length;
|
700
|
+
AddNonCompressedBlock(options, final,
|
701
|
+
lz77->data, pos, end, bp, out, outsize);
|
702
|
+
return;
|
703
|
+
}
|
371
704
|
|
372
705
|
AddBit(final, bp, out, outsize);
|
373
706
|
AddBit(btype & 1, bp, out, outsize);
|
@@ -380,34 +713,28 @@ static void AddLZ77Block(const ZopfliOptions* options, int btype, int final,
|
|
380
713
|
/* Dynamic block. */
|
381
714
|
unsigned detect_tree_size;
|
382
715
|
assert(btype == 2);
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
PatchDistanceCodesForBuggyDecoders(d_lengths);
|
716
|
+
|
717
|
+
GetDynamicLengths(lz77, lstart, lend, ll_lengths, d_lengths);
|
718
|
+
|
387
719
|
detect_tree_size = *outsize;
|
388
720
|
AddDynamicTree(ll_lengths, d_lengths, bp, out, outsize);
|
389
721
|
if (options->verbose) {
|
390
722
|
fprintf(stderr, "treesize: %d\n", (int)(*outsize - detect_tree_size));
|
391
723
|
}
|
392
|
-
|
393
|
-
/* Assert that for every present symbol, the code length is non-zero. */
|
394
|
-
/* TODO(lode): remove this in release version. */
|
395
|
-
for (i = 0; i < 288; i++) assert(ll_counts[i] == 0 || ll_lengths[i] > 0);
|
396
|
-
for (i = 0; i < 32; i++) assert(d_counts[i] == 0 || d_lengths[i] > 0);
|
397
724
|
}
|
398
725
|
|
399
|
-
ZopfliLengthsToSymbols(ll_lengths,
|
400
|
-
ZopfliLengthsToSymbols(d_lengths,
|
726
|
+
ZopfliLengthsToSymbols(ll_lengths, ZOPFLI_NUM_LL, 15, ll_symbols);
|
727
|
+
ZopfliLengthsToSymbols(d_lengths, ZOPFLI_NUM_D, 15, d_symbols);
|
401
728
|
|
402
729
|
detect_block_size = *outsize;
|
403
|
-
AddLZ77Data(
|
730
|
+
AddLZ77Data(lz77, lstart, lend, expected_data_size,
|
404
731
|
ll_symbols, ll_lengths, d_symbols, d_lengths,
|
405
732
|
bp, out, outsize);
|
406
733
|
/* End symbol. */
|
407
734
|
AddHuffmanBits(ll_symbols[256], ll_lengths[256], bp, out, outsize);
|
408
735
|
|
409
736
|
for (i = lstart; i < lend; i++) {
|
410
|
-
uncompressed_size += dists[i] == 0 ? 1 : litlens[i];
|
737
|
+
uncompressed_size += lz77->dists[i] == 0 ? 1 : lz77->litlens[i];
|
411
738
|
}
|
412
739
|
compressed_size = *outsize - detect_block_size;
|
413
740
|
if (options->verbose) {
|
@@ -417,283 +744,188 @@ static void AddLZ77Block(const ZopfliOptions* options, int btype, int final,
|
|
417
744
|
}
|
418
745
|
}
|
419
746
|
|
420
|
-
static void
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
/* For small block, encoding with fixed tree can be smaller. For large block,
|
443
|
-
don't bother doing this expensive test, dynamic tree will be better.*/
|
444
|
-
if (store.size < 1000) {
|
445
|
-
double dyncost, fixedcost;
|
446
|
-
ZopfliLZ77Store fixedstore;
|
447
|
-
ZopfliInitLZ77Store(&fixedstore);
|
448
|
-
ZopfliLZ77OptimalFixed(&s, in, instart, inend, &fixedstore);
|
449
|
-
dyncost = ZopfliCalculateBlockSize(store.litlens, store.dists,
|
450
|
-
0, store.size, 2);
|
451
|
-
fixedcost = ZopfliCalculateBlockSize(fixedstore.litlens, fixedstore.dists,
|
452
|
-
0, fixedstore.size, 1);
|
453
|
-
if (fixedcost < dyncost) {
|
454
|
-
btype = 1;
|
455
|
-
ZopfliCleanLZ77Store(&store);
|
456
|
-
store = fixedstore;
|
457
|
-
} else {
|
458
|
-
ZopfliCleanLZ77Store(&fixedstore);
|
459
|
-
}
|
747
|
+
static void AddLZ77BlockAutoType(const ZopfliOptions* options, int final,
|
748
|
+
const ZopfliLZ77Store* lz77,
|
749
|
+
size_t lstart, size_t lend,
|
750
|
+
size_t expected_data_size,
|
751
|
+
unsigned char* bp,
|
752
|
+
unsigned char** out, size_t* outsize) {
|
753
|
+
double uncompressedcost = ZopfliCalculateBlockSize(lz77, lstart, lend, 0);
|
754
|
+
double fixedcost = ZopfliCalculateBlockSize(lz77, lstart, lend, 1);
|
755
|
+
double dyncost = ZopfliCalculateBlockSize(lz77, lstart, lend, 2);
|
756
|
+
|
757
|
+
/* Whether to perform the expensive calculation of creating an optimal block
|
758
|
+
with fixed huffman tree to check if smaller. Only do this for small blocks or
|
759
|
+
blocks which already are pretty good with fixed huffman tree. */
|
760
|
+
int expensivefixed = (lz77->size < 1000) || fixedcost <= dyncost * 1.1;
|
761
|
+
|
762
|
+
ZopfliLZ77Store fixedstore;
|
763
|
+
if (lstart == lend) {
|
764
|
+
/* Smallest empty block is represented by fixed block */
|
765
|
+
AddBits(final, 1, bp, out, outsize);
|
766
|
+
AddBits(1, 2, bp, out, outsize); /* btype 01 */
|
767
|
+
AddBits(0, 7, bp, out, outsize); /* end symbol has code 0000000 */
|
768
|
+
return;
|
460
769
|
}
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
static void DeflateFixedBlock(const ZopfliOptions* options, int final,
|
474
|
-
const unsigned char* in,
|
475
|
-
size_t instart, size_t inend,
|
476
|
-
unsigned char* bp,
|
477
|
-
unsigned char** out, size_t* outsize) {
|
478
|
-
ZopfliBlockState s;
|
479
|
-
size_t blocksize = inend - instart;
|
480
|
-
ZopfliLZ77Store store;
|
481
|
-
|
482
|
-
ZopfliInitLZ77Store(&store);
|
483
|
-
|
484
|
-
s.options = options;
|
485
|
-
s.blockstart = instart;
|
486
|
-
s.blockend = inend;
|
487
|
-
#ifdef ZOPFLI_LONGEST_MATCH_CACHE
|
488
|
-
s.lmc = (ZopfliLongestMatchCache*)malloc(sizeof(ZopfliLongestMatchCache));
|
489
|
-
ZopfliInitCache(blocksize, s.lmc);
|
490
|
-
#endif
|
491
|
-
|
492
|
-
ZopfliLZ77OptimalFixed(&s, in, instart, inend, &store);
|
493
|
-
|
494
|
-
AddLZ77Block(s.options, 1, final, store.litlens, store.dists, 0, store.size,
|
495
|
-
blocksize, bp, out, outsize);
|
496
|
-
|
497
|
-
#ifdef ZOPFLI_LONGEST_MATCH_CACHE
|
498
|
-
ZopfliCleanCache(s.lmc);
|
499
|
-
free(s.lmc);
|
500
|
-
#endif
|
501
|
-
ZopfliCleanLZ77Store(&store);
|
502
|
-
}
|
503
|
-
|
504
|
-
static void DeflateNonCompressedBlock(const ZopfliOptions* options, int final,
|
505
|
-
const unsigned char* in, size_t instart,
|
506
|
-
size_t inend,
|
507
|
-
unsigned char* bp,
|
508
|
-
unsigned char** out, size_t* outsize) {
|
509
|
-
size_t i;
|
510
|
-
size_t blocksize = inend - instart;
|
511
|
-
unsigned short nlen = ~blocksize;
|
512
|
-
|
513
|
-
(void)options;
|
514
|
-
assert(blocksize < 65536); /* Non compressed blocks are max this size. */
|
515
|
-
|
516
|
-
AddBit(final, bp, out, outsize);
|
517
|
-
/* BTYPE 00 */
|
518
|
-
AddBit(0, bp, out, outsize);
|
519
|
-
AddBit(0, bp, out, outsize);
|
520
|
-
|
521
|
-
/* Any bits of input up to the next byte boundary are ignored. */
|
522
|
-
*bp = 0;
|
523
|
-
|
524
|
-
ZOPFLI_APPEND_DATA(blocksize % 256, out, outsize);
|
525
|
-
ZOPFLI_APPEND_DATA((blocksize / 256) % 256, out, outsize);
|
526
|
-
ZOPFLI_APPEND_DATA(nlen % 256, out, outsize);
|
527
|
-
ZOPFLI_APPEND_DATA((nlen / 256) % 256, out, outsize);
|
528
|
-
|
529
|
-
for (i = instart; i < inend; i++) {
|
530
|
-
ZOPFLI_APPEND_DATA(in[i], out, outsize);
|
770
|
+
ZopfliInitLZ77Store(lz77->data, &fixedstore);
|
771
|
+
if (expensivefixed) {
|
772
|
+
/* Recalculate the LZ77 with ZopfliLZ77OptimalFixed */
|
773
|
+
size_t instart = lz77->pos[lstart];
|
774
|
+
size_t inend = instart + ZopfliLZ77GetByteRange(lz77, lstart, lend);
|
775
|
+
|
776
|
+
ZopfliBlockState s;
|
777
|
+
ZopfliInitBlockState(options, instart, inend, 1, &s);
|
778
|
+
ZopfliLZ77OptimalFixed(&s, lz77->data, instart, inend, &fixedstore);
|
779
|
+
fixedcost = ZopfliCalculateBlockSize(&fixedstore, 0, fixedstore.size, 1);
|
780
|
+
ZopfliCleanBlockState(&s);
|
531
781
|
}
|
532
|
-
}
|
533
782
|
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
783
|
+
if (uncompressedcost < fixedcost && uncompressedcost < dyncost) {
|
784
|
+
AddLZ77Block(options, 0, final, lz77, lstart, lend,
|
785
|
+
expected_data_size, bp, out, outsize);
|
786
|
+
} else if (fixedcost < dyncost) {
|
787
|
+
if (expensivefixed) {
|
788
|
+
AddLZ77Block(options, 1, final, &fixedstore, 0, fixedstore.size,
|
789
|
+
expected_data_size, bp, out, outsize);
|
790
|
+
} else {
|
791
|
+
AddLZ77Block(options, 1, final, lz77, lstart, lend,
|
792
|
+
expected_data_size, bp, out, outsize);
|
793
|
+
}
|
544
794
|
} else {
|
545
|
-
|
546
|
-
|
795
|
+
AddLZ77Block(options, 2, final, lz77, lstart, lend,
|
796
|
+
expected_data_size, bp, out, outsize);
|
547
797
|
}
|
798
|
+
|
799
|
+
ZopfliCleanLZ77Store(&fixedstore);
|
548
800
|
}
|
549
801
|
|
550
802
|
/*
|
551
|
-
|
552
|
-
|
553
|
-
|
803
|
+
Deflate a part, to allow ZopfliDeflate() to use multiple master blocks if
|
804
|
+
needed.
|
805
|
+
It is possible to call this function multiple times in a row, shifting
|
806
|
+
instart and inend to next bytes of the data. If instart is larger than 0, then
|
807
|
+
previous bytes are used as the initial dictionary for LZ77.
|
808
|
+
This function will usually output multiple deflate blocks. If final is 1, then
|
809
|
+
the final bit will be set on the last block.
|
554
810
|
*/
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
unsigned char* bp,
|
560
|
-
unsigned char** out, size_t* outsize) {
|
811
|
+
void ZopfliDeflatePart(const ZopfliOptions* options, int btype, int final,
|
812
|
+
const unsigned char* in, size_t instart, size_t inend,
|
813
|
+
unsigned char* bp, unsigned char** out,
|
814
|
+
size_t* outsize) {
|
561
815
|
size_t i;
|
562
|
-
|
816
|
+
/* byte coordinates rather than lz77 index */
|
817
|
+
size_t* splitpoints_uncompressed = 0;
|
563
818
|
size_t npoints = 0;
|
819
|
+
size_t* splitpoints = 0;
|
820
|
+
double totalcost = 0;
|
821
|
+
ZopfliLZ77Store lz77;
|
822
|
+
|
823
|
+
/* If btype=2 is specified, it tries all block types. If a lesser btype is
|
824
|
+
given, then however it forces that one. Neither of the lesser types needs
|
825
|
+
block splitting as they have no dynamic huffman trees. */
|
564
826
|
if (btype == 0) {
|
565
|
-
|
827
|
+
AddNonCompressedBlock(options, final, in, instart, inend, bp, out, outsize);
|
828
|
+
return;
|
566
829
|
} else if (btype == 1) {
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
options->blocksplittingmax, &splitpoints, &npoints);
|
572
|
-
}
|
830
|
+
ZopfliLZ77Store store;
|
831
|
+
ZopfliBlockState s;
|
832
|
+
ZopfliInitLZ77Store(in, &store);
|
833
|
+
ZopfliInitBlockState(options, instart, inend, 1, &s);
|
573
834
|
|
574
|
-
|
575
|
-
|
576
|
-
size_t end = i == npoints ? inend : splitpoints[i];
|
577
|
-
DeflateBlock(options, btype, i == npoints && final, in, start, end,
|
835
|
+
ZopfliLZ77OptimalFixed(&s, in, instart, inend, &store);
|
836
|
+
AddLZ77Block(options, btype, final, &store, 0, store.size, 0,
|
578
837
|
bp, out, outsize);
|
579
|
-
}
|
580
838
|
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
Does squeeze strategy where first the best possible lz77 is done, and then based
|
586
|
-
on that data, block splitting is done.
|
587
|
-
Parameters: see description of the ZopfliDeflate function.
|
588
|
-
*/
|
589
|
-
static void DeflateSplittingLast(const ZopfliOptions* options,
|
590
|
-
int btype, int final,
|
591
|
-
const unsigned char* in,
|
592
|
-
size_t instart, size_t inend,
|
593
|
-
unsigned char* bp,
|
594
|
-
unsigned char** out, size_t* outsize) {
|
595
|
-
size_t i;
|
596
|
-
ZopfliBlockState s;
|
597
|
-
ZopfliLZ77Store store;
|
598
|
-
size_t* splitpoints = 0;
|
599
|
-
size_t npoints = 0;
|
839
|
+
ZopfliCleanBlockState(&s);
|
840
|
+
ZopfliCleanLZ77Store(&store);
|
841
|
+
return;
|
842
|
+
}
|
600
843
|
|
601
|
-
if (btype == 0) {
|
602
|
-
/* This function only supports LZ77 compression. DeflateSplittingFirst
|
603
|
-
supports the special case of noncompressed data. Punt it to that one. */
|
604
|
-
DeflateSplittingFirst(options, btype, final,
|
605
|
-
in, instart, inend,
|
606
|
-
bp, out, outsize);
|
607
|
-
}
|
608
|
-
assert(btype == 1 || btype == 2);
|
609
|
-
|
610
|
-
ZopfliInitLZ77Store(&store);
|
611
|
-
|
612
|
-
s.options = options;
|
613
|
-
s.blockstart = instart;
|
614
|
-
s.blockend = inend;
|
615
|
-
#ifdef ZOPFLI_LONGEST_MATCH_CACHE
|
616
|
-
s.lmc = (ZopfliLongestMatchCache*)malloc(sizeof(ZopfliLongestMatchCache));
|
617
|
-
ZopfliInitCache(inend - instart, s.lmc);
|
618
|
-
#endif
|
619
844
|
|
620
|
-
if (
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
845
|
+
if (options->blocksplitting) {
|
846
|
+
ZopfliBlockSplit(options, in, instart, inend,
|
847
|
+
options->blocksplittingmax,
|
848
|
+
&splitpoints_uncompressed, &npoints);
|
849
|
+
splitpoints = (size_t*)malloc(sizeof(*splitpoints) * npoints);
|
625
850
|
}
|
626
851
|
|
627
|
-
|
628
|
-
/* If all blocks are fixed tree, splitting into separate blocks only
|
629
|
-
increases the total size. Leave npoints at 0, this represents 1 block. */
|
630
|
-
} else {
|
631
|
-
ZopfliBlockSplitLZ77(options, store.litlens, store.dists, store.size,
|
632
|
-
options->blocksplittingmax, &splitpoints, &npoints);
|
633
|
-
}
|
852
|
+
ZopfliInitLZ77Store(in, &lz77);
|
634
853
|
|
635
854
|
for (i = 0; i <= npoints; i++) {
|
636
|
-
size_t start = i == 0 ?
|
637
|
-
size_t end = i == npoints ?
|
638
|
-
|
639
|
-
|
640
|
-
|
855
|
+
size_t start = i == 0 ? instart : splitpoints_uncompressed[i - 1];
|
856
|
+
size_t end = i == npoints ? inend : splitpoints_uncompressed[i];
|
857
|
+
ZopfliBlockState s;
|
858
|
+
ZopfliLZ77Store store;
|
859
|
+
ZopfliInitLZ77Store(in, &store);
|
860
|
+
ZopfliInitBlockState(options, start, end, 1, &s);
|
861
|
+
ZopfliLZ77Optimal(&s, in, start, end, options->numiterations, &store);
|
862
|
+
totalcost += ZopfliCalculateBlockSizeAutoType(&store, 0, store.size);
|
863
|
+
|
864
|
+
ZopfliAppendLZ77Store(&store, &lz77);
|
865
|
+
if (i < npoints) splitpoints[i] = lz77.size;
|
866
|
+
|
867
|
+
ZopfliCleanBlockState(&s);
|
868
|
+
ZopfliCleanLZ77Store(&store);
|
641
869
|
}
|
642
870
|
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
871
|
+
/* Second block splitting attempt */
|
872
|
+
if (options->blocksplitting && npoints > 1) {
|
873
|
+
size_t* splitpoints2 = 0;
|
874
|
+
size_t npoints2 = 0;
|
875
|
+
double totalcost2 = 0;
|
647
876
|
|
648
|
-
|
649
|
-
|
877
|
+
ZopfliBlockSplitLZ77(options, &lz77,
|
878
|
+
options->blocksplittingmax, &splitpoints2, &npoints2);
|
650
879
|
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
const unsigned char* in, size_t instart, size_t inend,
|
662
|
-
unsigned char* bp, unsigned char** out,
|
663
|
-
size_t* outsize) {
|
664
|
-
if (options->blocksplitting) {
|
665
|
-
if (options->blocksplittinglast) {
|
666
|
-
DeflateSplittingLast(options, btype, final, in, instart, inend,
|
667
|
-
bp, out, outsize);
|
880
|
+
for (i = 0; i <= npoints2; i++) {
|
881
|
+
size_t start = i == 0 ? 0 : splitpoints2[i - 1];
|
882
|
+
size_t end = i == npoints2 ? lz77.size : splitpoints2[i];
|
883
|
+
totalcost2 += ZopfliCalculateBlockSizeAutoType(&lz77, start, end);
|
884
|
+
}
|
885
|
+
|
886
|
+
if (totalcost2 < totalcost) {
|
887
|
+
free(splitpoints);
|
888
|
+
splitpoints = splitpoints2;
|
889
|
+
npoints = npoints2;
|
668
890
|
} else {
|
669
|
-
|
670
|
-
bp, out, outsize);
|
891
|
+
free(splitpoints2);
|
671
892
|
}
|
672
|
-
} else {
|
673
|
-
DeflateBlock(options, btype, final, in, instart, inend, bp, out, outsize);
|
674
893
|
}
|
894
|
+
|
895
|
+
for (i = 0; i <= npoints; i++) {
|
896
|
+
size_t start = i == 0 ? 0 : splitpoints[i - 1];
|
897
|
+
size_t end = i == npoints ? lz77.size : splitpoints[i];
|
898
|
+
AddLZ77BlockAutoType(options, i == npoints && final,
|
899
|
+
&lz77, start, end, 0,
|
900
|
+
bp, out, outsize);
|
901
|
+
}
|
902
|
+
|
903
|
+
ZopfliCleanLZ77Store(&lz77);
|
904
|
+
free(splitpoints);
|
905
|
+
free(splitpoints_uncompressed);
|
675
906
|
}
|
676
907
|
|
677
908
|
void ZopfliDeflate(const ZopfliOptions* options, int btype, int final,
|
678
909
|
const unsigned char* in, size_t insize,
|
679
910
|
unsigned char* bp, unsigned char** out, size_t* outsize) {
|
911
|
+
size_t offset = *outsize;
|
680
912
|
#if ZOPFLI_MASTER_BLOCK_SIZE == 0
|
681
913
|
ZopfliDeflatePart(options, btype, final, in, 0, insize, bp, out, outsize);
|
682
914
|
#else
|
683
915
|
size_t i = 0;
|
684
|
-
|
916
|
+
do {
|
685
917
|
int masterfinal = (i + ZOPFLI_MASTER_BLOCK_SIZE >= insize);
|
686
918
|
int final2 = final && masterfinal;
|
687
919
|
size_t size = masterfinal ? insize - i : ZOPFLI_MASTER_BLOCK_SIZE;
|
688
920
|
ZopfliDeflatePart(options, btype, final2,
|
689
921
|
in, i, i + size, bp, out, outsize);
|
690
922
|
i += size;
|
691
|
-
}
|
923
|
+
} while (i < insize);
|
692
924
|
#endif
|
693
925
|
if (options->verbose) {
|
694
926
|
fprintf(stderr,
|
695
|
-
"Original Size: %
|
696
|
-
(
|
697
|
-
100.0 * (double)(insize - *outsize) / (double)insize);
|
927
|
+
"Original Size: %lu, Deflate: %lu, Compression: %f%% Removed\n",
|
928
|
+
(unsigned long)insize, (unsigned long)(*outsize - offset),
|
929
|
+
100.0 * (double)(insize - (*outsize - offset)) / (double)insize);
|
698
930
|
}
|
699
931
|
}
|