zopfli 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
}
|