zopfli 0.0.5 → 0.0.7

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +1 -1
  3. data/.travis.yml +24 -0
  4. data/Gemfile +2 -0
  5. data/Rakefile +8 -10
  6. data/ext/extconf.rb +1 -0
  7. data/ext/zopfli.c +37 -17
  8. data/lib/zopfli/version.rb +1 -1
  9. data/smoke.sh +9 -0
  10. data/{test → spec}/fixtures/alice29.txt +0 -0
  11. data/spec/spec_helper.rb +2 -0
  12. data/spec/zopfli_spec.rb +68 -0
  13. data/vendor/zopfli/src/zopfli/blocksplitter.c +34 -44
  14. data/vendor/zopfli/src/zopfli/blocksplitter.h +2 -6
  15. data/vendor/zopfli/src/zopfli/cache.c +3 -1
  16. data/vendor/zopfli/src/zopfli/deflate.c +351 -287
  17. data/vendor/zopfli/src/zopfli/deflate.h +8 -2
  18. data/vendor/zopfli/src/zopfli/gzip_container.c +54 -47
  19. data/vendor/zopfli/src/zopfli/hash.c +18 -10
  20. data/vendor/zopfli/src/zopfli/hash.h +6 -3
  21. data/vendor/zopfli/src/zopfli/katajainen.c +73 -62
  22. data/vendor/zopfli/src/zopfli/lz77.c +190 -42
  23. data/vendor/zopfli/src/zopfli/lz77.h +32 -19
  24. data/vendor/zopfli/src/zopfli/squeeze.c +75 -61
  25. data/vendor/zopfli/src/zopfli/squeeze.h +1 -0
  26. data/vendor/zopfli/src/zopfli/symbols.h +239 -0
  27. data/vendor/zopfli/src/zopfli/util.c +0 -178
  28. data/vendor/zopfli/src/zopfli/util.h +6 -23
  29. data/vendor/zopfli/src/zopfli/zlib_container.c +1 -1
  30. data/vendor/zopfli/src/zopfli/zopfli.h +1 -4
  31. data/vendor/zopfli/src/zopfli/zopfli_bin.c +11 -8
  32. data/zopfli.gemspec +8 -27
  33. metadata +13 -20
  34. data/test/test_zopfli_deflate.rb +0 -45
  35. data/vendor/zopfli/CONTRIBUTING.md +0 -24
  36. data/vendor/zopfli/CONTRIBUTORS +0 -8
  37. data/vendor/zopfli/Makefile +0 -42
  38. data/vendor/zopfli/README +0 -32
  39. data/vendor/zopfli/README.zopflipng +0 -35
  40. data/vendor/zopfli/src/zopflipng/lodepng/lodepng.cpp +0 -6252
  41. data/vendor/zopfli/src/zopflipng/lodepng/lodepng.h +0 -1716
  42. data/vendor/zopfli/src/zopflipng/lodepng/lodepng_util.cpp +0 -656
  43. data/vendor/zopfli/src/zopflipng/lodepng/lodepng_util.h +0 -151
  44. data/vendor/zopfli/src/zopflipng/zopflipng_bin.cc +0 -408
  45. data/vendor/zopfli/src/zopflipng/zopflipng_lib.cc +0 -492
  46. data/vendor/zopfli/src/zopflipng/zopflipng_lib.h +0 -134
@@ -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 unsigned short* litlens,
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
  /*
@@ -32,7 +32,9 @@ void ZopfliInitCache(size_t blocksize, ZopfliLongestMatchCache* lmc) {
32
32
  /* Rather large amount of memory. */
33
33
  lmc->sublen = (unsigned char*)malloc(ZOPFLI_CACHE_LENGTH * 3 * blocksize);
34
34
  if(lmc->sublen == NULL) {
35
- fprintf(stderr,"Error: Out of memory. Tried allocating %lu bytes of memory.\n",(unsigned long)(ZOPFLI_CACHE_LENGTH * 3 * blocksize));
35
+ fprintf(stderr,
36
+ "Error: Out of memory. Tried allocating %lu bytes of memory.\n",
37
+ ZOPFLI_CACHE_LENGTH * 3 * blocksize);
36
38
  exit (EXIT_FAILURE);
37
39
  }
38
40
 
@@ -24,8 +24,8 @@ 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
31
  /*
@@ -294,8 +294,7 @@ Adds all lit/len and dist codes from the lists as huffman symbols. Does not add
294
294
  end code 256. expected_data_size is the uncompressed block size, used for
295
295
  assert, but you can set it to 0 to not do the assertion.
296
296
  */
297
- static void AddLZ77Data(const unsigned short* litlens,
298
- const unsigned short* dists,
297
+ static void AddLZ77Data(const ZopfliLZ77Store* lz77,
299
298
  size_t lstart, size_t lend,
300
299
  size_t expected_data_size,
301
300
  const unsigned* ll_symbols, const unsigned* ll_lengths,
@@ -306,8 +305,8 @@ static void AddLZ77Data(const unsigned short* litlens,
306
305
  size_t i;
307
306
 
308
307
  for (i = lstart; i < lend; i++) {
309
- unsigned dist = dists[i];
310
- unsigned litlen = litlens[i];
308
+ unsigned dist = lz77->dists[i];
309
+ unsigned litlen = lz77->litlens[i];
311
310
  if (dist == 0) {
312
311
  assert(litlen < 256);
313
312
  assert(ll_lengths[litlen] > 0);
@@ -343,29 +342,83 @@ static void GetFixedTree(unsigned* ll_lengths, unsigned* d_lengths) {
343
342
  }
344
343
 
345
344
  /*
346
- Calculates size of the part after the header and tree of an LZ77 block, in bits.
345
+ Same as CalculateBlockSymbolSize, but for block size smaller than histogram
346
+ size.
347
347
  */
348
- static size_t CalculateBlockSymbolSize(const unsigned* ll_lengths,
349
- const unsigned* d_lengths,
350
- const unsigned short* litlens,
351
- const unsigned short* dists,
352
- 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) {
353
352
  size_t result = 0;
354
353
  size_t i;
355
354
  for (i = lstart; i < lend; i++) {
356
- if (dists[i] == 0) {
357
- result += ll_lengths[litlens[i]];
355
+ assert(i < lz77->size);
356
+ assert(lz77->litlens[i] < 259);
357
+ if (lz77->dists[i] == 0) {
358
+ result += ll_lengths[lz77->litlens[i]];
358
359
  } else {
359
- result += ll_lengths[ZopfliGetLengthSymbol(litlens[i])];
360
- result += d_lengths[ZopfliGetDistSymbol(dists[i])];
361
- result += ZopfliGetLengthExtraBits(litlens[i]);
362
- result += ZopfliGetDistExtraBits(dists[i]);
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);
363
366
  }
364
367
  }
365
368
  result += ll_lengths[256]; /*end symbol*/
366
369
  return result;
367
370
  }
368
371
 
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
+ }
402
+
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
+ }
421
+
369
422
  static size_t AbsDiff(size_t x, size_t y) {
370
423
  if (x > y)
371
424
  return x - y;
@@ -374,9 +427,9 @@ static size_t AbsDiff(size_t x, size_t y) {
374
427
  }
375
428
 
376
429
  /*
377
- Change the population counts in a way that the consequent Hufmann tree
378
- compression, especially its rle-part will be more likely to compress this data
379
- more efficiently. length containts the size of the histogram.
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.
380
433
  */
381
434
  void OptimizeHuffmanForRle(int length, size_t* counts) {
382
435
  int i, k, stride;
@@ -464,50 +517,151 @@ void OptimizeHuffmanForRle(int length, size_t* counts) {
464
517
  free(good_for_rle);
465
518
  }
466
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
+
467
562
  /*
468
563
  Calculates the bit lengths for the symbols for dynamic blocks. Chooses bit
469
564
  lengths that give the smallest size of tree encoding + encoding of all the
470
565
  symbols to have smallest output size. This are not necessarily the ideal Huffman
471
- bit lengths.
566
+ bit lengths. Returns size of encoded tree and data in bits, not including the
567
+ 3-bit block header.
472
568
  */
473
- static void GetDynamicLengths(const unsigned short* litlens,
474
- const unsigned short* dists,
475
- size_t lstart, size_t lend,
476
- unsigned* ll_lengths, unsigned* d_lengths) {
477
- size_t ll_counts[288];
478
- size_t d_counts[32];
479
-
480
- ZopfliLZ77Counts(litlens, dists, lstart, lend, ll_counts, d_counts);
481
- OptimizeHuffmanForRle(288, ll_counts);
482
- OptimizeHuffmanForRle(32, d_counts);
483
- ZopfliCalculateBitLengths(ll_counts, 288, 15, ll_lengths);
484
- ZopfliCalculateBitLengths(d_counts, 32, 15, d_lengths);
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);
485
579
  PatchDistanceCodesForBuggyDecoders(d_lengths);
580
+ return TryOptimizeHuffmanForRle(
581
+ lz77, lstart, lend, ll_counts, d_counts, ll_lengths, d_lengths);
486
582
  }
487
583
 
488
- double ZopfliCalculateBlockSize(const unsigned short* litlens,
489
- const unsigned short* dists,
584
+ double ZopfliCalculateBlockSize(const ZopfliLZ77Store* lz77,
490
585
  size_t lstart, size_t lend, int btype) {
491
- unsigned ll_lengths[288];
492
- unsigned d_lengths[32];
586
+ unsigned ll_lengths[ZOPFLI_NUM_LL];
587
+ unsigned d_lengths[ZOPFLI_NUM_D];
493
588
 
494
589
  double result = 3; /* bfinal and btype bits */
495
590
 
496
- assert(btype == 1 || btype == 2); /* This is not for uncompressed blocks. */
497
-
498
- if(btype == 1) {
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) {
499
600
  GetFixedTree(ll_lengths, d_lengths);
601
+ result += CalculateBlockSymbolSize(
602
+ ll_lengths, d_lengths, lz77, lstart, lend);
500
603
  } else {
501
- GetDynamicLengths(litlens, dists, lstart, lend, ll_lengths, d_lengths);
502
- result += CalculateTreeSize(ll_lengths, d_lengths);
604
+ result += GetDynamicLengths(lz77, lstart, lend, ll_lengths, d_lengths);
503
605
  }
504
606
 
505
- result += CalculateBlockSymbolSize(
506
- ll_lengths, d_lengths, litlens, dists, lstart, lend);
507
-
508
607
  return result;
509
608
  }
510
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
+
511
665
  /*
512
666
  Adds a deflate block with the given LZ77 data to the output.
513
667
  options: global program options
@@ -526,20 +680,27 @@ out: dynamic output array to append to
526
680
  outsize: dynamic output array size
527
681
  */
528
682
  static void AddLZ77Block(const ZopfliOptions* options, int btype, int final,
529
- const unsigned short* litlens,
530
- const unsigned short* dists,
683
+ const ZopfliLZ77Store* lz77,
531
684
  size_t lstart, size_t lend,
532
685
  size_t expected_data_size,
533
686
  unsigned char* bp,
534
687
  unsigned char** out, size_t* outsize) {
535
- unsigned ll_lengths[288];
536
- unsigned d_lengths[32];
537
- unsigned ll_symbols[288];
538
- unsigned d_symbols[32];
539
- size_t detect_block_size;
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];
692
+ size_t detect_block_size = *outsize;
540
693
  size_t compressed_size;
541
694
  size_t uncompressed_size = 0;
542
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
+ }
543
704
 
544
705
  AddBit(final, bp, out, outsize);
545
706
  AddBit(btype & 1, bp, out, outsize);
@@ -553,7 +714,7 @@ static void AddLZ77Block(const ZopfliOptions* options, int btype, int final,
553
714
  unsigned detect_tree_size;
554
715
  assert(btype == 2);
555
716
 
556
- GetDynamicLengths(litlens, dists, lstart, lend, ll_lengths, d_lengths);
717
+ GetDynamicLengths(lz77, lstart, lend, ll_lengths, d_lengths);
557
718
 
558
719
  detect_tree_size = *outsize;
559
720
  AddDynamicTree(ll_lengths, d_lengths, bp, out, outsize);
@@ -562,18 +723,18 @@ static void AddLZ77Block(const ZopfliOptions* options, int btype, int final,
562
723
  }
563
724
  }
564
725
 
565
- ZopfliLengthsToSymbols(ll_lengths, 288, 15, ll_symbols);
566
- ZopfliLengthsToSymbols(d_lengths, 32, 15, d_symbols);
726
+ ZopfliLengthsToSymbols(ll_lengths, ZOPFLI_NUM_LL, 15, ll_symbols);
727
+ ZopfliLengthsToSymbols(d_lengths, ZOPFLI_NUM_D, 15, d_symbols);
567
728
 
568
729
  detect_block_size = *outsize;
569
- AddLZ77Data(litlens, dists, lstart, lend, expected_data_size,
730
+ AddLZ77Data(lz77, lstart, lend, expected_data_size,
570
731
  ll_symbols, ll_lengths, d_symbols, d_lengths,
571
732
  bp, out, outsize);
572
733
  /* End symbol. */
573
734
  AddHuffmanBits(ll_symbols[256], ll_lengths[256], bp, out, outsize);
574
735
 
575
736
  for (i = lstart; i < lend; i++) {
576
- uncompressed_size += dists[i] == 0 ? 1 : litlens[i];
737
+ uncompressed_size += lz77->dists[i] == 0 ? 1 : lz77->litlens[i];
577
738
  }
578
739
  compressed_size = *outsize - detect_block_size;
579
740
  if (options->verbose) {
@@ -583,262 +744,165 @@ static void AddLZ77Block(const ZopfliOptions* options, int btype, int final,
583
744
  }
584
745
  }
585
746
 
586
- static void DeflateDynamicBlock(const ZopfliOptions* options, int final,
587
- const unsigned char* in,
588
- size_t instart, size_t inend,
589
- unsigned char* bp,
590
- unsigned char** out, size_t* outsize) {
591
- ZopfliBlockState s;
592
- size_t blocksize = inend - instart;
593
- ZopfliLZ77Store store;
594
- int btype = 2;
595
-
596
- ZopfliInitLZ77Store(&store);
597
-
598
- s.options = options;
599
- s.blockstart = instart;
600
- s.blockend = inend;
601
- #ifdef ZOPFLI_LONGEST_MATCH_CACHE
602
- s.lmc = (ZopfliLongestMatchCache*)malloc(sizeof(ZopfliLongestMatchCache));
603
- ZopfliInitCache(blocksize, s.lmc);
604
- #endif
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;
769
+ }
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);
781
+ }
605
782
 
606
- ZopfliLZ77Optimal(&s, in, instart, inend, &store);
607
-
608
- /* For small block, encoding with fixed tree can be smaller. For large block,
609
- don't bother doing this expensive test, dynamic tree will be better.*/
610
- if (store.size < 1000) {
611
- double dyncost, fixedcost;
612
- ZopfliLZ77Store fixedstore;
613
- ZopfliInitLZ77Store(&fixedstore);
614
- ZopfliLZ77OptimalFixed(&s, in, instart, inend, &fixedstore);
615
- dyncost = ZopfliCalculateBlockSize(store.litlens, store.dists,
616
- 0, store.size, 2);
617
- fixedcost = ZopfliCalculateBlockSize(fixedstore.litlens, fixedstore.dists,
618
- 0, fixedstore.size, 1);
619
- if (fixedcost < dyncost) {
620
- btype = 1;
621
- ZopfliCleanLZ77Store(&store);
622
- store = fixedstore;
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);
623
790
  } else {
624
- ZopfliCleanLZ77Store(&fixedstore);
791
+ AddLZ77Block(options, 1, final, lz77, lstart, lend,
792
+ expected_data_size, bp, out, outsize);
625
793
  }
794
+ } else {
795
+ AddLZ77Block(options, 2, final, lz77, lstart, lend,
796
+ expected_data_size, bp, out, outsize);
626
797
  }
627
798
 
628
- AddLZ77Block(s.options, btype, final,
629
- store.litlens, store.dists, 0, store.size,
630
- blocksize, bp, out, outsize);
631
-
632
- #ifdef ZOPFLI_LONGEST_MATCH_CACHE
633
- ZopfliCleanCache(s.lmc);
634
- free(s.lmc);
635
- #endif
636
- ZopfliCleanLZ77Store(&store);
637
- }
638
-
639
- static void DeflateFixedBlock(const ZopfliOptions* options, int final,
640
- const unsigned char* in,
641
- size_t instart, size_t inend,
642
- unsigned char* bp,
643
- unsigned char** out, size_t* outsize) {
644
- ZopfliBlockState s;
645
- size_t blocksize = inend - instart;
646
- ZopfliLZ77Store store;
647
-
648
- ZopfliInitLZ77Store(&store);
649
-
650
- s.options = options;
651
- s.blockstart = instart;
652
- s.blockend = inend;
653
- #ifdef ZOPFLI_LONGEST_MATCH_CACHE
654
- s.lmc = (ZopfliLongestMatchCache*)malloc(sizeof(ZopfliLongestMatchCache));
655
- ZopfliInitCache(blocksize, s.lmc);
656
- #endif
657
-
658
- ZopfliLZ77OptimalFixed(&s, in, instart, inend, &store);
659
-
660
- AddLZ77Block(s.options, 1, final, store.litlens, store.dists, 0, store.size,
661
- blocksize, bp, out, outsize);
662
-
663
- #ifdef ZOPFLI_LONGEST_MATCH_CACHE
664
- ZopfliCleanCache(s.lmc);
665
- free(s.lmc);
666
- #endif
667
- ZopfliCleanLZ77Store(&store);
799
+ ZopfliCleanLZ77Store(&fixedstore);
668
800
  }
669
801
 
670
- static void DeflateNonCompressedBlock(const ZopfliOptions* options, int final,
671
- const unsigned char* in, size_t instart,
672
- size_t inend,
673
- unsigned char* bp,
674
- unsigned char** out, size_t* outsize) {
802
+ /*
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.
810
+ */
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) {
675
815
  size_t i;
676
- size_t blocksize = inend - instart;
677
- unsigned short nlen = ~blocksize;
678
-
679
- (void)options;
680
- assert(blocksize < 65536); /* Non compressed blocks are max this size. */
681
-
682
- AddBit(final, bp, out, outsize);
683
- /* BTYPE 00 */
684
- AddBit(0, bp, out, outsize);
685
- AddBit(0, bp, out, outsize);
816
+ /* byte coordinates rather than lz77 index */
817
+ size_t* splitpoints_uncompressed = 0;
818
+ size_t npoints = 0;
819
+ size_t* splitpoints = 0;
820
+ double totalcost = 0;
821
+ ZopfliLZ77Store lz77;
686
822
 
687
- /* Any bits of input up to the next byte boundary are ignored. */
688
- *bp = 0;
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. */
826
+ if (btype == 0) {
827
+ AddNonCompressedBlock(options, final, in, instart, inend, bp, out, outsize);
828
+ return;
829
+ } else if (btype == 1) {
830
+ ZopfliLZ77Store store;
831
+ ZopfliBlockState s;
832
+ ZopfliInitLZ77Store(in, &store);
833
+ ZopfliInitBlockState(options, instart, inend, 1, &s);
689
834
 
690
- ZOPFLI_APPEND_DATA(blocksize % 256, out, outsize);
691
- ZOPFLI_APPEND_DATA((blocksize / 256) % 256, out, outsize);
692
- ZOPFLI_APPEND_DATA(nlen % 256, out, outsize);
693
- ZOPFLI_APPEND_DATA((nlen / 256) % 256, out, outsize);
835
+ ZopfliLZ77OptimalFixed(&s, in, instart, inend, &store);
836
+ AddLZ77Block(options, btype, final, &store, 0, store.size, 0,
837
+ bp, out, outsize);
694
838
 
695
- for (i = instart; i < inend; i++) {
696
- ZOPFLI_APPEND_DATA(in[i], out, outsize);
839
+ ZopfliCleanBlockState(&s);
840
+ ZopfliCleanLZ77Store(&store);
841
+ return;
697
842
  }
698
- }
699
843
 
700
- static void DeflateBlock(const ZopfliOptions* options,
701
- int btype, int final,
702
- const unsigned char* in, size_t instart, size_t inend,
703
- unsigned char* bp,
704
- unsigned char** out, size_t* outsize) {
705
- if (btype == 0) {
706
- DeflateNonCompressedBlock(
707
- options, final, in, instart, inend, bp, out, outsize);
708
- } else if (btype == 1) {
709
- DeflateFixedBlock(options, final, in, instart, inend, bp, out, outsize);
710
- } else {
711
- assert (btype == 2);
712
- DeflateDynamicBlock(options, final, in, instart, inend, bp, out, outsize);
713
- }
714
- }
715
844
 
716
- /*
717
- Does squeeze strategy where first block splitting is done, then each block is
718
- squeezed.
719
- Parameters: see description of the ZopfliDeflate function.
720
- */
721
- static void DeflateSplittingFirst(const ZopfliOptions* options,
722
- int btype, int final,
723
- const unsigned char* in,
724
- size_t instart, size_t inend,
725
- unsigned char* bp,
726
- unsigned char** out, size_t* outsize) {
727
- size_t i;
728
- size_t* splitpoints = 0;
729
- size_t npoints = 0;
730
- if (btype == 0) {
731
- ZopfliBlockSplitSimple(in, instart, inend, 65535, &splitpoints, &npoints);
732
- } else if (btype == 1) {
733
- /* If all blocks are fixed tree, splitting into separate blocks only
734
- increases the total size. Leave npoints at 0, this represents 1 block. */
735
- } else {
845
+ if (options->blocksplitting) {
736
846
  ZopfliBlockSplit(options, in, instart, inend,
737
- options->blocksplittingmax, &splitpoints, &npoints);
847
+ options->blocksplittingmax,
848
+ &splitpoints_uncompressed, &npoints);
849
+ splitpoints = (size_t*)malloc(sizeof(*splitpoints) * npoints);
738
850
  }
739
851
 
852
+ ZopfliInitLZ77Store(in, &lz77);
853
+
740
854
  for (i = 0; i <= npoints; i++) {
741
- size_t start = i == 0 ? instart : splitpoints[i - 1];
742
- size_t end = i == npoints ? inend : splitpoints[i];
743
- DeflateBlock(options, btype, i == npoints && final, in, start, end,
744
- bp, out, outsize);
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);
745
869
  }
746
870
 
747
- free(splitpoints);
748
- }
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;
749
876
 
750
- /*
751
- Does squeeze strategy where first the best possible lz77 is done, and then based
752
- on that data, block splitting is done.
753
- Parameters: see description of the ZopfliDeflate function.
754
- */
755
- static void DeflateSplittingLast(const ZopfliOptions* options,
756
- int btype, int final,
757
- const unsigned char* in,
758
- size_t instart, size_t inend,
759
- unsigned char* bp,
760
- unsigned char** out, size_t* outsize) {
761
- size_t i;
762
- ZopfliBlockState s;
763
- ZopfliLZ77Store store;
764
- size_t* splitpoints = 0;
765
- size_t npoints = 0;
766
-
767
- if (btype == 0) {
768
- /* This function only supports LZ77 compression. DeflateSplittingFirst
769
- supports the special case of noncompressed data. Punt it to that one. */
770
- DeflateSplittingFirst(options, btype, final,
771
- in, instart, inend,
772
- bp, out, outsize);
773
- }
774
- assert(btype == 1 || btype == 2);
775
-
776
- ZopfliInitLZ77Store(&store);
777
-
778
- s.options = options;
779
- s.blockstart = instart;
780
- s.blockend = inend;
781
- #ifdef ZOPFLI_LONGEST_MATCH_CACHE
782
- s.lmc = (ZopfliLongestMatchCache*)malloc(sizeof(ZopfliLongestMatchCache));
783
- ZopfliInitCache(inend - instart, s.lmc);
784
- #endif
877
+ ZopfliBlockSplitLZ77(options, &lz77,
878
+ options->blocksplittingmax, &splitpoints2, &npoints2);
785
879
 
786
- if (btype == 2) {
787
- ZopfliLZ77Optimal(&s, in, instart, inend, &store);
788
- } else {
789
- assert (btype == 1);
790
- ZopfliLZ77OptimalFixed(&s, in, instart, inend, &store);
791
- }
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
+ }
792
885
 
793
- if (btype == 1) {
794
- /* If all blocks are fixed tree, splitting into separate blocks only
795
- increases the total size. Leave npoints at 0, this represents 1 block. */
796
- } else {
797
- ZopfliBlockSplitLZ77(options, store.litlens, store.dists, store.size,
798
- options->blocksplittingmax, &splitpoints, &npoints);
886
+ if (totalcost2 < totalcost) {
887
+ free(splitpoints);
888
+ splitpoints = splitpoints2;
889
+ npoints = npoints2;
890
+ } else {
891
+ free(splitpoints2);
892
+ }
799
893
  }
800
894
 
801
895
  for (i = 0; i <= npoints; i++) {
802
896
  size_t start = i == 0 ? 0 : splitpoints[i - 1];
803
- size_t end = i == npoints ? store.size : splitpoints[i];
804
- AddLZ77Block(options, btype, i == npoints && final,
805
- store.litlens, store.dists, start, end, 0,
806
- bp, out, outsize);
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);
807
901
  }
808
902
 
809
- #ifdef ZOPFLI_LONGEST_MATCH_CACHE
810
- ZopfliCleanCache(s.lmc);
811
- free(s.lmc);
812
- #endif
813
-
814
- ZopfliCleanLZ77Store(&store);
903
+ ZopfliCleanLZ77Store(&lz77);
815
904
  free(splitpoints);
816
- }
817
-
818
- /*
819
- Deflate a part, to allow ZopfliDeflate() to use multiple master blocks if
820
- needed.
821
- It is possible to call this function multiple times in a row, shifting
822
- instart and inend to next bytes of the data. If instart is larger than 0, then
823
- previous bytes are used as the initial dictionary for LZ77.
824
- This function will usually output multiple deflate blocks. If final is 1, then
825
- the final bit will be set on the last block.
826
- */
827
- void ZopfliDeflatePart(const ZopfliOptions* options, int btype, int final,
828
- const unsigned char* in, size_t instart, size_t inend,
829
- unsigned char* bp, unsigned char** out,
830
- size_t* outsize) {
831
- if (options->blocksplitting) {
832
- if (options->blocksplittinglast) {
833
- DeflateSplittingLast(options, btype, final, in, instart, inend,
834
- bp, out, outsize);
835
- } else {
836
- DeflateSplittingFirst(options, btype, final, in, instart, inend,
837
- bp, out, outsize);
838
- }
839
- } else {
840
- DeflateBlock(options, btype, final, in, instart, inend, bp, out, outsize);
841
- }
905
+ free(splitpoints_uncompressed);
842
906
  }
843
907
 
844
908
  void ZopfliDeflate(const ZopfliOptions* options, int btype, int final,
@@ -849,19 +913,19 @@ void ZopfliDeflate(const ZopfliOptions* options, int btype, int final,
849
913
  ZopfliDeflatePart(options, btype, final, in, 0, insize, bp, out, outsize);
850
914
  #else
851
915
  size_t i = 0;
852
- while (i < insize) {
916
+ do {
853
917
  int masterfinal = (i + ZOPFLI_MASTER_BLOCK_SIZE >= insize);
854
918
  int final2 = final && masterfinal;
855
919
  size_t size = masterfinal ? insize - i : ZOPFLI_MASTER_BLOCK_SIZE;
856
920
  ZopfliDeflatePart(options, btype, final2,
857
921
  in, i, i + size, bp, out, outsize);
858
922
  i += size;
859
- }
923
+ } while (i < insize);
860
924
  #endif
861
925
  if (options->verbose) {
862
926
  fprintf(stderr,
863
- "Original Size: %d, Deflate: %d, Compression: %f%% Removed\n",
864
- (int)insize, (int)(*outsize - offset),
927
+ "Original Size: %lu, Deflate: %lu, Compression: %f%% Removed\n",
928
+ (unsigned long)insize, (unsigned long)(*outsize - offset),
865
929
  100.0 * (double)(insize - (*outsize - offset)) / (double)insize);
866
930
  }
867
931
  }