zopfli 0.0.3 → 0.0.4
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 +4 -4
- data/lib/zopfli/version.rb +1 -1
- data/vendor/zopfli/{makefile → Makefile} +0 -0
- data/vendor/zopfli/src/zopfli/blocksplitter.c +7 -9
- data/vendor/zopfli/src/zopfli/deflate.c +281 -114
- data/vendor/zopfli/src/zopfli/lz77.h +7 -4
- data/vendor/zopfli/src/zopflipng/lodepng/lodepng.cpp +255 -248
- data/vendor/zopfli/src/zopflipng/lodepng/lodepng.h +19 -8
- data/vendor/zopfli/src/zopflipng/zopflipng_lib.cc +61 -12
- data/vendor/zopfli/src/zopflipng/zopflipng_lib.h +3 -3
- metadata +15 -15
@@ -33,10 +33,13 @@ compression.
|
|
33
33
|
|
34
34
|
/*
|
35
35
|
Stores lit/length and dist pairs for LZ77.
|
36
|
-
litlens: Contains the literal symbols or length values.
|
37
|
-
dists:
|
38
|
-
litlens
|
39
|
-
|
36
|
+
Parameter litlens: Contains the literal symbols or length values.
|
37
|
+
Parameter dists: Contains the distances. A value is 0 to indicate that there is
|
38
|
+
no dist and the corresponding litlens value is a literal instead of a length.
|
39
|
+
Parameter size: The size of both the litlens and dists arrays.
|
40
|
+
The memory can best be managed by using ZopfliInitLZ77Store to initialize it,
|
41
|
+
ZopfliCleanLZ77Store to destroy it, and ZopfliStoreLitLenDist to append values.
|
42
|
+
|
40
43
|
*/
|
41
44
|
typedef struct ZopfliLZ77Store {
|
42
45
|
unsigned short* litlens; /* Lit or len. */
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
LodePNG version
|
2
|
+
LodePNG version 20131222
|
3
3
|
|
4
4
|
Copyright (c) 2005-2013 Lode Vandevenne
|
5
5
|
|
@@ -37,7 +37,7 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for
|
|
37
37
|
#include <fstream>
|
38
38
|
#endif /*LODEPNG_COMPILE_CPP*/
|
39
39
|
|
40
|
-
#define VERSION_STRING "
|
40
|
+
#define VERSION_STRING "20131222"
|
41
41
|
|
42
42
|
/*
|
43
43
|
This source file is built up in the following large parts. The code sections
|
@@ -190,15 +190,6 @@ static unsigned uivector_copy(uivector* p, const uivector* q)
|
|
190
190
|
for(i = 0; i < q->size; i++) p->data[i] = q->data[i];
|
191
191
|
return 1;
|
192
192
|
}
|
193
|
-
|
194
|
-
static void uivector_swap(uivector* p, uivector* q)
|
195
|
-
{
|
196
|
-
size_t tmp;
|
197
|
-
unsigned* tmpp;
|
198
|
-
tmp = p->size; p->size = q->size; q->size = tmp;
|
199
|
-
tmp = p->allocsize; p->allocsize = q->allocsize; q->allocsize = tmp;
|
200
|
-
tmpp = p->data; p->data = q->data; q->data = tmpp;
|
201
|
-
}
|
202
193
|
#endif /*LODEPNG_COMPILE_ENCODER*/
|
203
194
|
#endif /*LODEPNG_COMPILE_ZLIB*/
|
204
195
|
|
@@ -404,13 +395,13 @@ unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const
|
|
404
395
|
#ifdef LODEPNG_COMPILE_ZLIB
|
405
396
|
#ifdef LODEPNG_COMPILE_ENCODER
|
406
397
|
/*TODO: this ignores potential out of memory errors*/
|
407
|
-
|
408
|
-
{
|
409
|
-
/*add a new byte at the end
|
410
|
-
if((*bitpointer)
|
411
|
-
/*earlier bit of huffman code is in a lesser significant bit of an earlier byte
|
412
|
-
(bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7))
|
413
|
-
(*bitpointer)
|
398
|
+
#define addBitToStream(/*size_t**/ bitpointer, /*ucvector**/ bitstream, /*unsigned char*/ bit)\
|
399
|
+
{\
|
400
|
+
/*add a new byte at the end*/\
|
401
|
+
if(((*bitpointer) & 7) == 0) ucvector_push_back(bitstream, (unsigned char)0);\
|
402
|
+
/*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\
|
403
|
+
(bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7));\
|
404
|
+
(*bitpointer)++;\
|
414
405
|
}
|
415
406
|
|
416
407
|
static void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits)
|
@@ -580,7 +571,7 @@ static unsigned HuffmanTree_make2DTree(HuffmanTree* tree)
|
|
580
571
|
}
|
581
572
|
}
|
582
573
|
|
583
|
-
for(n = 0;
|
574
|
+
for(n = 0; n < tree->numcodes * 2; n++)
|
584
575
|
{
|
585
576
|
if(tree->tree2d[n] == 32767) tree->tree2d[n] = 0; /*remove possible remaining 32767's*/
|
586
577
|
}
|
@@ -698,32 +689,10 @@ static void cleanup_coins(Coin* coins, size_t num)
|
|
698
689
|
for(i = 0; i < num; i++) coin_cleanup(&coins[i]);
|
699
690
|
}
|
700
691
|
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
static void sort_coins(Coin* data, size_t amount)
|
706
|
-
{
|
707
|
-
size_t gap = amount;
|
708
|
-
unsigned char swapped = 0;
|
709
|
-
while((gap > 1) || swapped)
|
710
|
-
{
|
711
|
-
size_t i;
|
712
|
-
gap = (gap * 10) / 13; /*shrink factor 1.3*/
|
713
|
-
if(gap == 9 || gap == 10) gap = 11; /*combsort11*/
|
714
|
-
if(gap < 1) gap = 1;
|
715
|
-
swapped = 0;
|
716
|
-
for(i = 0; i < amount - gap; i++)
|
717
|
-
{
|
718
|
-
size_t j = i + gap;
|
719
|
-
if(data[j].weight < data[i].weight)
|
720
|
-
{
|
721
|
-
float temp = data[j].weight; data[j].weight = data[i].weight; data[i].weight = temp;
|
722
|
-
uivector_swap(&data[i].symbols, &data[j].symbols);
|
723
|
-
swapped = 1;
|
724
|
-
}
|
725
|
-
}
|
726
|
-
}
|
692
|
+
static int coin_compare(const void* a, const void* b) {
|
693
|
+
float wa = ((const Coin*)a)->weight;
|
694
|
+
float wb = ((const Coin*)b)->weight;
|
695
|
+
return wa > wb ? 1 : wa < wb ? -1 : 0;
|
727
696
|
}
|
728
697
|
|
729
698
|
static unsigned append_symbol_coins(Coin* coins, const unsigned* frequencies, unsigned numcodes, size_t sum)
|
@@ -795,14 +764,19 @@ unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequen
|
|
795
764
|
coinmem = numpresent * 2; /*max amount of coins needed with the current algo*/
|
796
765
|
coins = (Coin*)lodepng_malloc(sizeof(Coin) * coinmem);
|
797
766
|
prev_row = (Coin*)lodepng_malloc(sizeof(Coin) * coinmem);
|
798
|
-
if(!coins || !prev_row)
|
767
|
+
if(!coins || !prev_row)
|
768
|
+
{
|
769
|
+
lodepng_free(coins);
|
770
|
+
lodepng_free(prev_row);
|
771
|
+
return 83; /*alloc fail*/
|
772
|
+
}
|
799
773
|
init_coins(coins, coinmem);
|
800
774
|
init_coins(prev_row, coinmem);
|
801
775
|
|
802
776
|
/*first row, lowest denominator*/
|
803
777
|
error = append_symbol_coins(coins, frequencies, numcodes, sum);
|
804
778
|
numcoins = numpresent;
|
805
|
-
|
779
|
+
qsort(coins, numcoins, sizeof(Coin), coin_compare);
|
806
780
|
if(!error)
|
807
781
|
{
|
808
782
|
unsigned numprev = 0;
|
@@ -833,7 +807,7 @@ unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequen
|
|
833
807
|
error = append_symbol_coins(coins + numcoins, frequencies, numcodes, sum);
|
834
808
|
numcoins += numpresent;
|
835
809
|
}
|
836
|
-
|
810
|
+
qsort(coins, numcoins, sizeof(Coin), coin_compare);
|
837
811
|
}
|
838
812
|
}
|
839
813
|
|
@@ -1356,6 +1330,7 @@ static void addLengthDistance(uivector* values, size_t length, size_t distance)
|
|
1356
1330
|
uivector_push_back(values, extra_distance);
|
1357
1331
|
}
|
1358
1332
|
|
1333
|
+
static const unsigned HASH_BIT_MASK = 65535;
|
1359
1334
|
static const unsigned HASH_NUM_VALUES = 65536;
|
1360
1335
|
static const unsigned HASH_NUM_CHARACTERS = 3;
|
1361
1336
|
static const unsigned HASH_SHIFT = 2;
|
@@ -1411,12 +1386,18 @@ static void hash_cleanup(Hash* hash)
|
|
1411
1386
|
static unsigned getHash(const unsigned char* data, size_t size, size_t pos)
|
1412
1387
|
{
|
1413
1388
|
unsigned result = 0;
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1389
|
+
if (HASH_NUM_CHARACTERS == 3 && pos + 2 < size) {
|
1390
|
+
result ^= (data[pos + 0] << (0 * HASH_SHIFT));
|
1391
|
+
result ^= (data[pos + 1] << (1 * HASH_SHIFT));
|
1392
|
+
result ^= (data[pos + 2] << (2 * HASH_SHIFT));
|
1393
|
+
} else {
|
1394
|
+
size_t amount, i;
|
1395
|
+
if(pos >= size) return 0;
|
1396
|
+
amount = HASH_NUM_CHARACTERS;
|
1397
|
+
if(pos + amount >= size) amount = size - pos;
|
1398
|
+
for(i = 0; i < amount; i++) result ^= (data[pos + i] << (i * HASH_SHIFT));
|
1399
|
+
}
|
1400
|
+
return result & HASH_BIT_MASK;
|
1420
1401
|
}
|
1421
1402
|
|
1422
1403
|
static unsigned countZeros(const unsigned char* data, size_t size, size_t pos)
|
@@ -1430,9 +1411,9 @@ static unsigned countZeros(const unsigned char* data, size_t size, size_t pos)
|
|
1430
1411
|
return (unsigned)(data - start);
|
1431
1412
|
}
|
1432
1413
|
|
1433
|
-
|
1414
|
+
/*wpos = pos & (windowsize - 1)*/
|
1415
|
+
static void updateHashChain(Hash* hash, size_t wpos, int hashval)
|
1434
1416
|
{
|
1435
|
-
unsigned wpos = pos % windowsize;
|
1436
1417
|
hash->val[wpos] = hashval;
|
1437
1418
|
if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval];
|
1438
1419
|
hash->head[hashval] = wpos;
|
@@ -1451,154 +1432,165 @@ static unsigned encodeLZ77(uivector* out, Hash* hash,
|
|
1451
1432
|
const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize,
|
1452
1433
|
unsigned minmatch, unsigned nicematch, unsigned lazymatching)
|
1453
1434
|
{
|
1454
|
-
unsigned short numzeros = 0;
|
1455
|
-
int usezeros = windowsize >= 8192; /*for small window size, the 'max chain length' optimization does a better job*/
|
1456
1435
|
unsigned pos, i, error = 0;
|
1457
1436
|
/*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/
|
1458
1437
|
unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8;
|
1459
1438
|
unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64;
|
1460
1439
|
|
1461
|
-
if
|
1462
|
-
|
1463
|
-
unsigned offset; /*the offset represents the distance in LZ77 terminology*/
|
1464
|
-
unsigned length;
|
1465
|
-
unsigned lazy = 0;
|
1466
|
-
unsigned lazylength = 0, lazyoffset = 0;
|
1467
|
-
unsigned hashval;
|
1468
|
-
unsigned current_offset, current_length;
|
1469
|
-
const unsigned char *lastptr, *foreptr, *backptr;
|
1470
|
-
unsigned short hashpos, prevpos;
|
1471
|
-
|
1472
|
-
for(pos = inpos; pos < insize; pos++)
|
1473
|
-
{
|
1474
|
-
size_t wpos = pos % windowsize; /*position for in 'circular' hash buffers*/
|
1440
|
+
unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/
|
1441
|
+
unsigned numzeros = 0;
|
1475
1442
|
|
1476
|
-
|
1477
|
-
|
1443
|
+
unsigned offset; /*the offset represents the distance in LZ77 terminology*/
|
1444
|
+
unsigned length;
|
1445
|
+
unsigned lazy = 0;
|
1446
|
+
unsigned lazylength = 0, lazyoffset = 0;
|
1447
|
+
unsigned hashval;
|
1448
|
+
unsigned current_offset, current_length;
|
1449
|
+
const unsigned char *lastptr, *foreptr, *backptr;
|
1450
|
+
unsigned hashpos, prevpos;
|
1478
1451
|
|
1479
|
-
|
1480
|
-
|
1481
|
-
numzeros = countZeros(in, insize, pos);
|
1482
|
-
hash->zeros[wpos] = numzeros;
|
1483
|
-
}
|
1452
|
+
if(windowsize <= 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/
|
1453
|
+
if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/
|
1484
1454
|
|
1485
|
-
|
1486
|
-
length = 0;
|
1487
|
-
offset = 0;
|
1455
|
+
if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH;
|
1488
1456
|
|
1489
|
-
|
1490
|
-
|
1457
|
+
for(pos = inpos; pos < insize; pos++)
|
1458
|
+
{
|
1459
|
+
size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/
|
1460
|
+
unsigned chainlength = 0;
|
1491
1461
|
|
1492
|
-
|
1462
|
+
hashval = getHash(in, insize, pos);
|
1463
|
+
updateHashChain(hash, wpos, hashval);
|
1493
1464
|
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1465
|
+
if(usezeros && hashval == 0)
|
1466
|
+
{
|
1467
|
+
if (numzeros == 0) numzeros = countZeros(in, insize, pos);
|
1468
|
+
else if (pos + numzeros >= insize || in[pos + numzeros - 1] != 0) numzeros--;
|
1469
|
+
hash->zeros[wpos] = numzeros;
|
1470
|
+
}
|
1471
|
+
else
|
1472
|
+
{
|
1473
|
+
numzeros = 0;
|
1474
|
+
}
|
1504
1475
|
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
/*test the next characters*/
|
1509
|
-
foreptr = &in[pos];
|
1510
|
-
backptr = &in[pos - current_offset];
|
1476
|
+
/*the length and offset found for the current position*/
|
1477
|
+
length = 0;
|
1478
|
+
offset = 0;
|
1511
1479
|
|
1512
|
-
|
1513
|
-
|
1514
|
-
{
|
1515
|
-
unsigned short skip = hash->zeros[hashpos];
|
1516
|
-
if(skip > numzeros) skip = numzeros;
|
1517
|
-
backptr += skip;
|
1518
|
-
foreptr += skip;
|
1519
|
-
}
|
1480
|
+
prevpos = hash->head[hashval];
|
1481
|
+
hashpos = hash->chain[prevpos];
|
1520
1482
|
|
1521
|
-
|
1522
|
-
while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/
|
1523
|
-
{
|
1524
|
-
++backptr;
|
1525
|
-
++foreptr;
|
1526
|
-
}
|
1527
|
-
current_length = (unsigned)(foreptr - &in[pos]);
|
1483
|
+
lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH];
|
1528
1484
|
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
}
|
1485
|
+
/*search for the longest string*/
|
1486
|
+
for(;;)
|
1487
|
+
{
|
1488
|
+
/*stop when went completely around the circular buffer*/
|
1489
|
+
if(prevpos < wpos && hashpos > prevpos && hashpos <= wpos) break;
|
1490
|
+
if(prevpos > wpos && (hashpos <= wpos || hashpos > prevpos)) break;
|
1491
|
+
if(chainlength++ >= maxchainlength) break;
|
1537
1492
|
|
1538
|
-
|
1493
|
+
current_offset = hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize;
|
1494
|
+
if(current_offset > 0)
|
1495
|
+
{
|
1496
|
+
/*test the next characters*/
|
1497
|
+
foreptr = &in[pos];
|
1498
|
+
backptr = &in[pos - current_offset];
|
1539
1499
|
|
1540
|
-
|
1541
|
-
|
1500
|
+
/*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/
|
1501
|
+
if(usezeros && hashval == 0 && hash->val[hashpos] == 0 /*hashval[hashpos] may be out of date*/)
|
1502
|
+
{
|
1503
|
+
unsigned skip = hash->zeros[hashpos];
|
1504
|
+
if(skip > numzeros) skip = numzeros;
|
1505
|
+
backptr += skip;
|
1506
|
+
foreptr += skip;
|
1542
1507
|
}
|
1543
|
-
}
|
1544
1508
|
|
1545
|
-
|
1546
|
-
{
|
1547
|
-
if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH)
|
1509
|
+
while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/
|
1548
1510
|
{
|
1549
|
-
|
1550
|
-
|
1551
|
-
lazyoffset = offset;
|
1552
|
-
continue; /*try the next byte*/
|
1511
|
+
++backptr;
|
1512
|
+
++foreptr;
|
1553
1513
|
}
|
1554
|
-
|
1514
|
+
current_length = (unsigned)(foreptr - &in[pos]);
|
1515
|
+
|
1516
|
+
if(current_length > length)
|
1555
1517
|
{
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/);
|
1562
|
-
}
|
1563
|
-
else
|
1564
|
-
{
|
1565
|
-
length = lazylength;
|
1566
|
-
offset = lazyoffset;
|
1567
|
-
hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/
|
1568
|
-
pos--;
|
1569
|
-
}
|
1518
|
+
length = current_length; /*the longest length*/
|
1519
|
+
offset = current_offset; /*the offset that is related to this longest length*/
|
1520
|
+
/*jump out once a length of max length is found (speed gain). This also jumps
|
1521
|
+
out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/
|
1522
|
+
if(current_length >= nicematch) break;
|
1570
1523
|
}
|
1571
1524
|
}
|
1572
|
-
if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/);
|
1573
1525
|
|
1574
|
-
|
1575
|
-
|
1526
|
+
if(hashpos == hash->chain[hashpos]) break;
|
1527
|
+
|
1528
|
+
prevpos = hashpos;
|
1529
|
+
hashpos = hash->chain[hashpos];
|
1530
|
+
}
|
1531
|
+
|
1532
|
+
if(lazymatching)
|
1533
|
+
{
|
1534
|
+
if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH)
|
1576
1535
|
{
|
1577
|
-
|
1536
|
+
lazy = 1;
|
1537
|
+
lazylength = length;
|
1538
|
+
lazyoffset = offset;
|
1539
|
+
continue; /*try the next byte*/
|
1578
1540
|
}
|
1579
|
-
|
1541
|
+
if(lazy)
|
1580
1542
|
{
|
1581
|
-
|
1582
|
-
|
1583
|
-
if(
|
1543
|
+
lazy = 0;
|
1544
|
+
if(pos == 0) ERROR_BREAK(81);
|
1545
|
+
if(length > lazylength + 1)
|
1546
|
+
{
|
1547
|
+
/*push the previous character as literal*/
|
1548
|
+
if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/);
|
1549
|
+
}
|
1550
|
+
else
|
1551
|
+
{
|
1552
|
+
length = lazylength;
|
1553
|
+
offset = lazyoffset;
|
1554
|
+
hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/
|
1555
|
+
pos--;
|
1556
|
+
}
|
1584
1557
|
}
|
1585
|
-
|
1558
|
+
}
|
1559
|
+
if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/);
|
1560
|
+
|
1561
|
+
/*encode it as length/distance pair or literal value*/
|
1562
|
+
if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/
|
1563
|
+
{
|
1564
|
+
if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);
|
1565
|
+
}
|
1566
|
+
else if(length < minmatch || (length == 3 && offset > 4096))
|
1567
|
+
{
|
1568
|
+
/*compensate for the fact that longer offsets have more extra bits, a
|
1569
|
+
length of only 3 may be not worth it then*/
|
1570
|
+
if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);
|
1571
|
+
}
|
1572
|
+
else
|
1573
|
+
{
|
1574
|
+
addLengthDistance(out, length, offset);
|
1575
|
+
for(i = 1; i < length; i++)
|
1586
1576
|
{
|
1587
|
-
|
1588
|
-
|
1577
|
+
pos++;
|
1578
|
+
wpos = pos & (windowsize - 1);
|
1579
|
+
hashval = getHash(in, insize, pos);
|
1580
|
+
updateHashChain(hash, wpos, hashval);
|
1581
|
+
if(usezeros && hashval == 0)
|
1589
1582
|
{
|
1590
|
-
pos
|
1591
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1583
|
+
if (numzeros == 0) numzeros = countZeros(in, insize, pos);
|
1584
|
+
else if (pos + numzeros >= insize || in[pos + numzeros - 1] != 0) numzeros--;
|
1585
|
+
hash->zeros[wpos] = numzeros;
|
1586
|
+
}
|
1587
|
+
else
|
1588
|
+
{
|
1589
|
+
numzeros = 0;
|
1597
1590
|
}
|
1598
1591
|
}
|
1599
|
-
|
1600
|
-
|
1601
|
-
} /*end of "if(!error)"*/
|
1592
|
+
}
|
1593
|
+
} /*end of the loop through each character of input*/
|
1602
1594
|
|
1603
1595
|
return error;
|
1604
1596
|
}
|
@@ -2125,9 +2117,13 @@ static unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsi
|
|
2125
2117
|
size_t insize, const LodePNGDecompressSettings* settings)
|
2126
2118
|
{
|
2127
2119
|
if(settings->custom_zlib)
|
2120
|
+
{
|
2128
2121
|
return settings->custom_zlib(out, outsize, in, insize, settings);
|
2122
|
+
}
|
2129
2123
|
else
|
2124
|
+
{
|
2130
2125
|
return lodepng_zlib_decompress(out, outsize, in, insize, settings);
|
2126
|
+
}
|
2131
2127
|
}
|
2132
2128
|
|
2133
2129
|
#endif /*LODEPNG_COMPILE_DECODER*/
|
@@ -2267,46 +2263,53 @@ const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0,
|
|
2267
2263
|
/* / CRC32 / */
|
2268
2264
|
/* ////////////////////////////////////////////////////////////////////////// */
|
2269
2265
|
|
2270
|
-
|
2271
|
-
static unsigned
|
2272
|
-
|
2273
|
-
|
2274
|
-
|
2275
|
-
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2284
|
-
|
2285
|
-
|
2286
|
-
|
2287
|
-
|
2288
|
-
|
2266
|
+
/* CRC polynomial: 0xedb88320 */
|
2267
|
+
static unsigned lodepng_crc32_table[256] = {
|
2268
|
+
0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u,
|
2269
|
+
249268274u, 2044508324u, 3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u,
|
2270
|
+
498536548u, 1789927666u, 4089016648u, 2227061214u, 450548861u, 1843258603u, 4107580753u, 2211677639u,
|
2271
|
+
325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u, 4195302755u, 2366115317u,
|
2272
|
+
997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u,
|
2273
|
+
901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u,
|
2274
|
+
651767980u, 1373503546u, 3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u,
|
2275
|
+
671266974u, 1594198024u, 3322730930u, 2970347812u, 795835527u, 1483230225u, 3244367275u, 3060149565u,
|
2276
|
+
1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u, 2680153253u, 3904427059u,
|
2277
|
+
2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u,
|
2278
|
+
1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u,
|
2279
|
+
1706088902u, 314042704u, 2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u,
|
2280
|
+
1303535960u, 984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u,
|
2281
|
+
1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u, 2852801631u, 3708648649u,
|
2282
|
+
1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u,
|
2283
|
+
1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u,
|
2284
|
+
3988292384u, 2596254646u, 62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u,
|
2285
|
+
3814918930u, 2489596804u, 225274430u, 2053790376u, 3826175755u, 2466906013u, 167816743u, 2097651377u,
|
2286
|
+
4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u, 426522225u, 1852507879u,
|
2287
|
+
4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u,
|
2288
|
+
3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u,
|
2289
|
+
3624741850u, 2936675148u, 906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u,
|
2290
|
+
3412177804u, 3160834842u, 628085408u, 1382605366u, 3423369109u, 3138078467u, 570562233u, 1426400815u,
|
2291
|
+
3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u, 752459403u, 1541320221u,
|
2292
|
+
2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u,
|
2293
|
+
2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u,
|
2294
|
+
2262029012u, 4057260610u, 1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u,
|
2295
|
+
2282248934u, 4279200368u, 1711684554u, 285281116u, 2405801727u, 4167216745u, 1634467795u, 376229701u,
|
2296
|
+
2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u,
|
2297
|
+
2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u,
|
2298
|
+
3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u,
|
2299
|
+
3009837614u, 3294710456u, 1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u
|
2300
|
+
};
|
2289
2301
|
|
2290
|
-
/*
|
2291
|
-
|
2292
|
-
final running CRC (see the crc() routine below).*/
|
2293
|
-
static unsigned Crc32_update_crc(const unsigned char* buf, unsigned crc, size_t len)
|
2302
|
+
/*Return the CRC of the bytes buf[0..len-1].*/
|
2303
|
+
unsigned lodepng_crc32(const unsigned char* buf, size_t len)
|
2294
2304
|
{
|
2295
|
-
unsigned c =
|
2305
|
+
unsigned c = 0xffffffffL;
|
2296
2306
|
size_t n;
|
2297
2307
|
|
2298
|
-
if(!Crc32_crc_table_computed) Crc32_make_crc_table();
|
2299
2308
|
for(n = 0; n < len; n++)
|
2300
2309
|
{
|
2301
|
-
c =
|
2310
|
+
c = lodepng_crc32_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
|
2302
2311
|
}
|
2303
|
-
return c;
|
2304
|
-
}
|
2305
|
-
|
2306
|
-
/*Return the CRC of the bytes buf[0..len-1].*/
|
2307
|
-
unsigned lodepng_crc32(const unsigned char* buf, size_t len)
|
2308
|
-
{
|
2309
|
-
return Crc32_update_crc(buf, 0xffffffffL, len) ^ 0xffffffffL;
|
2312
|
+
return c ^ 0xffffffffL;
|
2310
2313
|
}
|
2311
2314
|
|
2312
2315
|
/* ////////////////////////////////////////////////////////////////////////// */
|
@@ -2890,13 +2893,14 @@ void lodepng_info_swap(LodePNGInfo* a, LodePNGInfo* b)
|
|
2890
2893
|
|
2891
2894
|
/* ////////////////////////////////////////////////////////////////////////// */
|
2892
2895
|
|
2893
|
-
/*index: bitgroup index, bits: bitgroup size(1, 2 or 4, in: bitgroup value, out: octet array to add bits to*/
|
2896
|
+
/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/
|
2894
2897
|
static void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in)
|
2895
2898
|
{
|
2899
|
+
unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/
|
2896
2900
|
/*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/
|
2897
|
-
unsigned p = index
|
2901
|
+
unsigned p = index & m;
|
2898
2902
|
in &= (1 << bits) - 1; /*filter out any other bits of the input value*/
|
2899
|
-
in = in << (bits * (
|
2903
|
+
in = in << (bits * (m - p));
|
2900
2904
|
if(p == 0) out[index * bits / 8] = in;
|
2901
2905
|
else out[index * bits / 8] |= in;
|
2902
2906
|
}
|
@@ -3387,7 +3391,7 @@ the out buffer must have (w * h * bpp + 7) / 8 bytes, where bpp is the bits per
|
|
3387
3391
|
(lodepng_get_bpp) for < 8 bpp images, there may _not_ be padding bits at the end of scanlines.
|
3388
3392
|
*/
|
3389
3393
|
unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
|
3390
|
-
LodePNGColorMode* mode_out, LodePNGColorMode* mode_in,
|
3394
|
+
LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
|
3391
3395
|
unsigned w, unsigned h, unsigned fix_png)
|
3392
3396
|
{
|
3393
3397
|
unsigned error = 0;
|
@@ -3482,7 +3486,7 @@ typedef struct ColorProfile
|
|
3482
3486
|
|
3483
3487
|
} ColorProfile;
|
3484
3488
|
|
3485
|
-
static void color_profile_init(ColorProfile* profile, LodePNGColorMode* mode)
|
3489
|
+
static void color_profile_init(ColorProfile* profile, const LodePNGColorMode* mode)
|
3486
3490
|
{
|
3487
3491
|
profile->sixteenbit = 0;
|
3488
3492
|
profile->sixteenbit_done = mode->bitdepth == 16 ? 0 : 1;
|
@@ -3547,8 +3551,9 @@ unsigned getValueRequiredBits(unsigned short value)
|
|
3547
3551
|
/*profile must already have been inited with mode.
|
3548
3552
|
It's ok to set some parameters of profile to done already.*/
|
3549
3553
|
static unsigned get_color_profile(ColorProfile* profile,
|
3550
|
-
const unsigned char* in,
|
3551
|
-
|
3554
|
+
const unsigned char* in,
|
3555
|
+
size_t numpixels /*must be full image size, for certain filesize based choices*/,
|
3556
|
+
const LodePNGColorMode* mode,
|
3552
3557
|
unsigned fix_png)
|
3553
3558
|
{
|
3554
3559
|
unsigned error = 0;
|
@@ -3584,9 +3589,10 @@ static unsigned get_color_profile(ColorProfile* profile,
|
|
3584
3589
|
|
3585
3590
|
if(!profile->alpha_done && a != 65535)
|
3586
3591
|
{
|
3587
|
-
|
3592
|
+
/*only use color key if numpixels large enough to justify tRNS chunk size*/
|
3593
|
+
if(a == 0 && numpixels > 16 && !(profile->key && (r != profile->key_r || g != profile->key_g || b != profile->key_b)))
|
3588
3594
|
{
|
3589
|
-
if(!profile->key)
|
3595
|
+
if(!profile->alpha && !profile->key)
|
3590
3596
|
{
|
3591
3597
|
profile->key = 1;
|
3592
3598
|
profile->key_r = r;
|
@@ -3748,9 +3754,10 @@ static void setColorKeyFrom16bit(LodePNGColorMode* mode_out, unsigned r, unsigne
|
|
3748
3754
|
|
3749
3755
|
/*updates values of mode with a potentially smaller color model. mode_out should
|
3750
3756
|
contain the user chosen color model, but will be overwritten with the new chosen one.*/
|
3751
|
-
|
3752
|
-
|
3753
|
-
|
3757
|
+
unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,
|
3758
|
+
const unsigned char* image, unsigned w, unsigned h,
|
3759
|
+
const LodePNGColorMode* mode_in,
|
3760
|
+
LodePNGAutoConvert auto_convert)
|
3754
3761
|
{
|
3755
3762
|
ColorProfile profile;
|
3756
3763
|
unsigned error = 0;
|
@@ -3807,9 +3814,9 @@ static unsigned doAutoChooseColor(LodePNGColorMode* mode_out,
|
|
3807
3814
|
{
|
3808
3815
|
if(!palette_ok || (grey_ok && profile.greybits <= palettebits))
|
3809
3816
|
{
|
3817
|
+
unsigned grey = profile.key_r;
|
3810
3818
|
mode_out->colortype = LCT_GREY;
|
3811
3819
|
mode_out->bitdepth = profile.greybits;
|
3812
|
-
unsigned grey = profile.key_r;
|
3813
3820
|
if(profile.key) setColorKeyFrom16bit(mode_out, grey, grey, grey, mode_out->bitdepth);
|
3814
3821
|
}
|
3815
3822
|
else
|
@@ -4560,6 +4567,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
|
|
4560
4567
|
const unsigned char* chunk;
|
4561
4568
|
size_t i;
|
4562
4569
|
ucvector idat; /*the data from idat chunks*/
|
4570
|
+
ucvector scanlines;
|
4563
4571
|
|
4564
4572
|
/*for unknown chunk order*/
|
4565
4573
|
unsigned unknown = 0;
|
@@ -4697,36 +4705,33 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
|
|
4697
4705
|
if(!IEND) chunk = lodepng_chunk_next_const(chunk);
|
4698
4706
|
}
|
4699
4707
|
|
4708
|
+
ucvector_init(&scanlines);
|
4700
4709
|
if(!state->error)
|
4701
4710
|
{
|
4702
|
-
ucvector scanlines;
|
4703
|
-
ucvector_init(&scanlines);
|
4704
|
-
|
4705
4711
|
/*maximum final image length is already reserved in the vector's length - this is not really necessary*/
|
4706
4712
|
if(!ucvector_resize(&scanlines, lodepng_get_raw_size(*w, *h, &state->info_png.color) + *h))
|
4707
4713
|
{
|
4708
4714
|
state->error = 83; /*alloc fail*/
|
4709
4715
|
}
|
4710
|
-
if(!state->error)
|
4711
|
-
{
|
4712
|
-
/*decompress with the Zlib decompressor*/
|
4713
|
-
state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data,
|
4714
|
-
idat.size, &state->decoder.zlibsettings);
|
4715
|
-
}
|
4716
|
-
|
4717
|
-
if(!state->error)
|
4718
|
-
{
|
4719
|
-
ucvector outv;
|
4720
|
-
ucvector_init(&outv);
|
4721
|
-
if(!ucvector_resizev(&outv,
|
4722
|
-
lodepng_get_raw_size(*w, *h, &state->info_png.color), 0)) state->error = 83; /*alloc fail*/
|
4723
|
-
if(!state->error) state->error = postProcessScanlines(outv.data, scanlines.data, *w, *h, &state->info_png);
|
4724
|
-
*out = outv.data;
|
4725
|
-
}
|
4726
|
-
ucvector_cleanup(&scanlines);
|
4727
4716
|
}
|
4728
|
-
|
4717
|
+
if(!state->error)
|
4718
|
+
{
|
4719
|
+
/*decompress with the Zlib decompressor*/
|
4720
|
+
state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data,
|
4721
|
+
idat.size, &state->decoder.zlibsettings);
|
4722
|
+
}
|
4729
4723
|
ucvector_cleanup(&idat);
|
4724
|
+
|
4725
|
+
if(!state->error)
|
4726
|
+
{
|
4727
|
+
ucvector outv;
|
4728
|
+
ucvector_init(&outv);
|
4729
|
+
if(!ucvector_resizev(&outv,
|
4730
|
+
lodepng_get_raw_size(*w, *h, &state->info_png.color), 0)) state->error = 83; /*alloc fail*/
|
4731
|
+
if(!state->error) state->error = postProcessScanlines(outv.data, scanlines.data, *w, *h, &state->info_png);
|
4732
|
+
*out = outv.data;
|
4733
|
+
}
|
4734
|
+
ucvector_cleanup(&scanlines);
|
4730
4735
|
}
|
4731
4736
|
|
4732
4737
|
unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,
|
@@ -5679,15 +5684,11 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
|
|
5679
5684
|
|
5680
5685
|
if(state->encoder.auto_convert != LAC_NO)
|
5681
5686
|
{
|
5682
|
-
state->error =
|
5683
|
-
|
5687
|
+
state->error = lodepng_auto_choose_color(&info.color, image, w, h, &state->info_raw,
|
5688
|
+
state->encoder.auto_convert);
|
5684
5689
|
}
|
5685
5690
|
if(state->error) return state->error;
|
5686
5691
|
|
5687
|
-
if(state->encoder.zlibsettings.windowsize > 32768)
|
5688
|
-
{
|
5689
|
-
CERROR_RETURN_ERROR(state->error, 60); /*error: windowsize larger than allowed*/
|
5690
|
-
}
|
5691
5692
|
if(state->encoder.zlibsettings.btype > 2)
|
5692
5693
|
{
|
5693
5694
|
CERROR_RETURN_ERROR(state->error, 61); /*error: unexisting btype*/
|
@@ -5787,9 +5788,13 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
|
|
5787
5788
|
break;
|
5788
5789
|
}
|
5789
5790
|
if(state->encoder.text_compression)
|
5791
|
+
{
|
5790
5792
|
addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings);
|
5793
|
+
}
|
5791
5794
|
else
|
5795
|
+
{
|
5792
5796
|
addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]);
|
5797
|
+
}
|
5793
5798
|
}
|
5794
5799
|
/*LodePNG version id in text chunk*/
|
5795
5800
|
if(state->encoder.add_id)
|
@@ -5804,7 +5809,9 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
|
|
5804
5809
|
}
|
5805
5810
|
}
|
5806
5811
|
if(alread_added_id_text == 0)
|
5812
|
+
{
|
5807
5813
|
addChunk_tEXt(&outv, "LodePNG", VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/
|
5814
|
+
}
|
5808
5815
|
}
|
5809
5816
|
/*iTXt*/
|
5810
5817
|
for(i = 0; i < info.itext_num; i++)
|
@@ -5831,7 +5838,6 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
|
|
5831
5838
|
if(state->error) break;
|
5832
5839
|
}
|
5833
5840
|
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
5834
|
-
/*IEND*/
|
5835
5841
|
addChunk_IEND(&outv);
|
5836
5842
|
|
5837
5843
|
break; /*this isn't really a while loop; no error happened so break out now!*/
|
@@ -6014,6 +6020,8 @@ const char* lodepng_error_text(unsigned code)
|
|
6014
6020
|
case 87: return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined";
|
6015
6021
|
case 88: return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy";
|
6016
6022
|
case 89: return "text chunk keyword too short or long: must have size 1-79";
|
6023
|
+
/*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/
|
6024
|
+
case 90: return "windowsize must be a power of two";
|
6017
6025
|
}
|
6018
6026
|
return "unknown error code";
|
6019
6027
|
}
|
@@ -6025,7 +6033,6 @@ const char* lodepng_error_text(unsigned code)
|
|
6025
6033
|
/* ////////////////////////////////////////////////////////////////////////// */
|
6026
6034
|
/* ////////////////////////////////////////////////////////////////////////// */
|
6027
6035
|
|
6028
|
-
|
6029
6036
|
#ifdef LODEPNG_COMPILE_CPP
|
6030
6037
|
namespace lodepng
|
6031
6038
|
{
|
@@ -6153,14 +6160,14 @@ unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
|
|
6153
6160
|
State& state,
|
6154
6161
|
const unsigned char* in, size_t insize)
|
6155
6162
|
{
|
6156
|
-
unsigned char* buffer;
|
6163
|
+
unsigned char* buffer = NULL;
|
6157
6164
|
unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize);
|
6158
6165
|
if(buffer && !error)
|
6159
6166
|
{
|
6160
6167
|
size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);
|
6161
6168
|
out.insert(out.end(), &buffer[0], &buffer[buffersize]);
|
6162
|
-
lodepng_free(buffer);
|
6163
6169
|
}
|
6170
|
+
lodepng_free(buffer);
|
6164
6171
|
return error;
|
6165
6172
|
}
|
6166
6173
|
|