zopfli 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +1 -1
  3. data/.travis.yml +24 -0
  4. data/Gemfile +2 -0
  5. data/Rakefile +8 -10
  6. data/ext/extconf.rb +1 -0
  7. data/ext/zopfli.c +37 -17
  8. data/lib/zopfli/version.rb +1 -1
  9. data/smoke.sh +9 -0
  10. data/{test → spec}/fixtures/alice29.txt +0 -0
  11. data/spec/spec_helper.rb +2 -0
  12. data/spec/zopfli_spec.rb +68 -0
  13. data/vendor/zopfli/src/zopfli/blocksplitter.c +34 -44
  14. data/vendor/zopfli/src/zopfli/blocksplitter.h +2 -6
  15. data/vendor/zopfli/src/zopfli/cache.c +3 -1
  16. data/vendor/zopfli/src/zopfli/deflate.c +351 -287
  17. data/vendor/zopfli/src/zopfli/deflate.h +8 -2
  18. data/vendor/zopfli/src/zopfli/gzip_container.c +54 -47
  19. data/vendor/zopfli/src/zopfli/hash.c +18 -10
  20. data/vendor/zopfli/src/zopfli/hash.h +6 -3
  21. data/vendor/zopfli/src/zopfli/katajainen.c +73 -62
  22. data/vendor/zopfli/src/zopfli/lz77.c +190 -42
  23. data/vendor/zopfli/src/zopfli/lz77.h +32 -19
  24. data/vendor/zopfli/src/zopfli/squeeze.c +75 -61
  25. data/vendor/zopfli/src/zopfli/squeeze.h +1 -0
  26. data/vendor/zopfli/src/zopfli/symbols.h +239 -0
  27. data/vendor/zopfli/src/zopfli/util.c +0 -178
  28. data/vendor/zopfli/src/zopfli/util.h +6 -23
  29. data/vendor/zopfli/src/zopfli/zlib_container.c +1 -1
  30. data/vendor/zopfli/src/zopfli/zopfli.h +1 -4
  31. data/vendor/zopfli/src/zopfli/zopfli_bin.c +11 -8
  32. data/zopfli.gemspec +8 -27
  33. metadata +13 -20
  34. data/test/test_zopfli_deflate.rb +0 -45
  35. data/vendor/zopfli/CONTRIBUTING.md +0 -24
  36. data/vendor/zopfli/CONTRIBUTORS +0 -8
  37. data/vendor/zopfli/Makefile +0 -42
  38. data/vendor/zopfli/README +0 -32
  39. data/vendor/zopfli/README.zopflipng +0 -35
  40. data/vendor/zopfli/src/zopflipng/lodepng/lodepng.cpp +0 -6252
  41. data/vendor/zopfli/src/zopflipng/lodepng/lodepng.h +0 -1716
  42. data/vendor/zopfli/src/zopflipng/lodepng/lodepng_util.cpp +0 -656
  43. data/vendor/zopfli/src/zopflipng/lodepng/lodepng_util.h +0 -151
  44. data/vendor/zopfli/src/zopflipng/zopflipng_bin.cc +0 -408
  45. data/vendor/zopfli/src/zopflipng/zopflipng_lib.cc +0 -492
  46. data/vendor/zopfli/src/zopflipng/zopflipng_lib.h +0 -134
@@ -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
  }