zopfli 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|