mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-22 17:49:43 +01:00
Update LodePNG to 20220109
This updates LodePNG to the commit pushed on January 9, 2022.
This commit is contained in:
parent
ed4d3d0fa8
commit
38d25c0850
2 changed files with 283 additions and 126 deletions
300
third_party/lodepng/lodepng.c
vendored
300
third_party/lodepng/lodepng.c
vendored
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
LodePNG version 20200306
|
LodePNG version 20220109
|
||||||
|
|
||||||
Copyright (c) 2005-2020 Lode Vandevenne
|
Copyright (c) 2005-2022 Lode Vandevenne
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -44,7 +44,7 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for
|
||||||
#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
|
#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
|
||||||
#endif /*_MSC_VER */
|
#endif /*_MSC_VER */
|
||||||
|
|
||||||
const char* LODEPNG_VERSION_STRING = "20200306";
|
const char* LODEPNG_VERSION_STRING = "20220109";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This source file is built up in the following large parts. The code sections
|
This source file is built up in the following large parts. The code sections
|
||||||
|
@ -267,7 +267,7 @@ typedef struct ucvector {
|
||||||
} ucvector;
|
} ucvector;
|
||||||
|
|
||||||
/*returns 1 if success, 0 if failure ==> nothing done*/
|
/*returns 1 if success, 0 if failure ==> nothing done*/
|
||||||
static unsigned ucvector_resize(ucvector* p, size_t size) {
|
static unsigned ucvector_reserve(ucvector* p, size_t size) {
|
||||||
if(size > p->allocsize) {
|
if(size > p->allocsize) {
|
||||||
size_t newsize = size + (p->allocsize >> 1u);
|
size_t newsize = size + (p->allocsize >> 1u);
|
||||||
void* data = lodepng_realloc(p->data, newsize);
|
void* data = lodepng_realloc(p->data, newsize);
|
||||||
|
@ -277,10 +277,15 @@ static unsigned ucvector_resize(ucvector* p, size_t size) {
|
||||||
}
|
}
|
||||||
else return 0; /*error: not enough memory*/
|
else return 0; /*error: not enough memory*/
|
||||||
}
|
}
|
||||||
p->size = size;
|
|
||||||
return 1; /*success*/
|
return 1; /*success*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*returns 1 if success, 0 if failure ==> nothing done*/
|
||||||
|
static unsigned ucvector_resize(ucvector* p, size_t size) {
|
||||||
|
p->size = size;
|
||||||
|
return ucvector_reserve(p, size);
|
||||||
|
}
|
||||||
|
|
||||||
static ucvector ucvector_init(unsigned char* buffer, size_t size) {
|
static ucvector ucvector_init(unsigned char* buffer, size_t size) {
|
||||||
ucvector v;
|
ucvector v;
|
||||||
v.data = buffer;
|
v.data = buffer;
|
||||||
|
@ -299,6 +304,7 @@ static void string_cleanup(char** out) {
|
||||||
*out = NULL;
|
*out = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*also appends null termination character*/
|
||||||
static char* alloc_string_sized(const char* in, size_t insize) {
|
static char* alloc_string_sized(const char* in, size_t insize) {
|
||||||
char* out = (char*)lodepng_malloc(insize + 1);
|
char* out = (char*)lodepng_malloc(insize + 1);
|
||||||
if(out) {
|
if(out) {
|
||||||
|
@ -479,71 +485,62 @@ static unsigned LodePNGBitReader_init(LodePNGBitReader* reader, const unsigned c
|
||||||
ensureBits functions:
|
ensureBits functions:
|
||||||
Ensures the reader can at least read nbits bits in one or more readBits calls,
|
Ensures the reader can at least read nbits bits in one or more readBits calls,
|
||||||
safely even if not enough bits are available.
|
safely even if not enough bits are available.
|
||||||
Returns 1 if there are enough bits available, 0 if not.
|
The nbits parameter is unused but is given for documentation purposes, error
|
||||||
|
checking for amount of bits must be done beforehand.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*See ensureBits documentation above. This one ensures exactly 1 bit */
|
|
||||||
/*static unsigned ensureBits1(LodePNGBitReader* reader) {
|
|
||||||
if(reader->bp >= reader->bitsize) return 0;
|
|
||||||
reader->buffer = (unsigned)reader->data[reader->bp >> 3u] >> (reader->bp & 7u);
|
|
||||||
return 1;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*See ensureBits documentation above. This one ensures up to 9 bits */
|
/*See ensureBits documentation above. This one ensures up to 9 bits */
|
||||||
static unsigned ensureBits9(LodePNGBitReader* reader, size_t nbits) {
|
static LODEPNG_INLINE void ensureBits9(LodePNGBitReader* reader, size_t nbits) {
|
||||||
size_t start = reader->bp >> 3u;
|
size_t start = reader->bp >> 3u;
|
||||||
size_t size = reader->size;
|
size_t size = reader->size;
|
||||||
if(start + 1u < size) {
|
if(start + 1u < size) {
|
||||||
reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u);
|
reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u);
|
||||||
reader->buffer >>= (reader->bp & 7u);
|
reader->buffer >>= (reader->bp & 7u);
|
||||||
return 1;
|
|
||||||
} else {
|
} else {
|
||||||
reader->buffer = 0;
|
reader->buffer = 0;
|
||||||
if(start + 0u < size) reader->buffer |= reader->data[start + 0];
|
if(start + 0u < size) reader->buffer = reader->data[start + 0];
|
||||||
reader->buffer >>= (reader->bp & 7u);
|
reader->buffer >>= (reader->bp & 7u);
|
||||||
return reader->bp + nbits <= reader->bitsize;
|
|
||||||
}
|
}
|
||||||
|
(void)nbits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*See ensureBits documentation above. This one ensures up to 17 bits */
|
/*See ensureBits documentation above. This one ensures up to 17 bits */
|
||||||
static unsigned ensureBits17(LodePNGBitReader* reader, size_t nbits) {
|
static LODEPNG_INLINE void ensureBits17(LodePNGBitReader* reader, size_t nbits) {
|
||||||
size_t start = reader->bp >> 3u;
|
size_t start = reader->bp >> 3u;
|
||||||
size_t size = reader->size;
|
size_t size = reader->size;
|
||||||
if(start + 2u < size) {
|
if(start + 2u < size) {
|
||||||
reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) |
|
reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) |
|
||||||
((unsigned)reader->data[start + 2] << 16u);
|
((unsigned)reader->data[start + 2] << 16u);
|
||||||
reader->buffer >>= (reader->bp & 7u);
|
reader->buffer >>= (reader->bp & 7u);
|
||||||
return 1;
|
|
||||||
} else {
|
} else {
|
||||||
reader->buffer = 0;
|
reader->buffer = 0;
|
||||||
if(start + 0u < size) reader->buffer |= reader->data[start + 0];
|
if(start + 0u < size) reader->buffer |= reader->data[start + 0];
|
||||||
if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u);
|
if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u);
|
||||||
reader->buffer >>= (reader->bp & 7u);
|
reader->buffer >>= (reader->bp & 7u);
|
||||||
return reader->bp + nbits <= reader->bitsize;
|
|
||||||
}
|
}
|
||||||
|
(void)nbits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*See ensureBits documentation above. This one ensures up to 25 bits */
|
/*See ensureBits documentation above. This one ensures up to 25 bits */
|
||||||
static LODEPNG_INLINE unsigned ensureBits25(LodePNGBitReader* reader, size_t nbits) {
|
static LODEPNG_INLINE void ensureBits25(LodePNGBitReader* reader, size_t nbits) {
|
||||||
size_t start = reader->bp >> 3u;
|
size_t start = reader->bp >> 3u;
|
||||||
size_t size = reader->size;
|
size_t size = reader->size;
|
||||||
if(start + 3u < size) {
|
if(start + 3u < size) {
|
||||||
reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) |
|
reader->buffer = (unsigned)reader->data[start + 0] | ((unsigned)reader->data[start + 1] << 8u) |
|
||||||
((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u);
|
((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u);
|
||||||
reader->buffer >>= (reader->bp & 7u);
|
reader->buffer >>= (reader->bp & 7u);
|
||||||
return 1;
|
|
||||||
} else {
|
} else {
|
||||||
reader->buffer = 0;
|
reader->buffer = 0;
|
||||||
if(start + 0u < size) reader->buffer |= reader->data[start + 0];
|
if(start + 0u < size) reader->buffer |= reader->data[start + 0];
|
||||||
if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u);
|
if(start + 1u < size) reader->buffer |= ((unsigned)reader->data[start + 1] << 8u);
|
||||||
if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u);
|
if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u);
|
||||||
reader->buffer >>= (reader->bp & 7u);
|
reader->buffer >>= (reader->bp & 7u);
|
||||||
return reader->bp + nbits <= reader->bitsize;
|
|
||||||
}
|
}
|
||||||
|
(void)nbits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*See ensureBits documentation above. This one ensures up to 32 bits */
|
/*See ensureBits documentation above. This one ensures up to 32 bits */
|
||||||
static LODEPNG_INLINE unsigned ensureBits32(LodePNGBitReader* reader, size_t nbits) {
|
static LODEPNG_INLINE void ensureBits32(LodePNGBitReader* reader, size_t nbits) {
|
||||||
size_t start = reader->bp >> 3u;
|
size_t start = reader->bp >> 3u;
|
||||||
size_t size = reader->size;
|
size_t size = reader->size;
|
||||||
if(start + 4u < size) {
|
if(start + 4u < size) {
|
||||||
|
@ -551,7 +548,6 @@ static LODEPNG_INLINE unsigned ensureBits32(LodePNGBitReader* reader, size_t nbi
|
||||||
((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u);
|
((unsigned)reader->data[start + 2] << 16u) | ((unsigned)reader->data[start + 3] << 24u);
|
||||||
reader->buffer >>= (reader->bp & 7u);
|
reader->buffer >>= (reader->bp & 7u);
|
||||||
reader->buffer |= (((unsigned)reader->data[start + 4] << 24u) << (8u - (reader->bp & 7u)));
|
reader->buffer |= (((unsigned)reader->data[start + 4] << 24u) << (8u - (reader->bp & 7u)));
|
||||||
return 1;
|
|
||||||
} else {
|
} else {
|
||||||
reader->buffer = 0;
|
reader->buffer = 0;
|
||||||
if(start + 0u < size) reader->buffer |= reader->data[start + 0];
|
if(start + 0u < size) reader->buffer |= reader->data[start + 0];
|
||||||
|
@ -559,48 +555,28 @@ static LODEPNG_INLINE unsigned ensureBits32(LodePNGBitReader* reader, size_t nbi
|
||||||
if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u);
|
if(start + 2u < size) reader->buffer |= ((unsigned)reader->data[start + 2] << 16u);
|
||||||
if(start + 3u < size) reader->buffer |= ((unsigned)reader->data[start + 3] << 24u);
|
if(start + 3u < size) reader->buffer |= ((unsigned)reader->data[start + 3] << 24u);
|
||||||
reader->buffer >>= (reader->bp & 7u);
|
reader->buffer >>= (reader->bp & 7u);
|
||||||
return reader->bp + nbits <= reader->bitsize;
|
|
||||||
}
|
}
|
||||||
|
(void)nbits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get bits without advancing the bit pointer. Must have enough bits available with ensureBits. Max nbits is 31. */
|
/* Get bits without advancing the bit pointer. Must have enough bits available with ensureBits. Max nbits is 31. */
|
||||||
static unsigned peekBits(LodePNGBitReader* reader, size_t nbits) {
|
static LODEPNG_INLINE unsigned peekBits(LodePNGBitReader* reader, size_t nbits) {
|
||||||
/* The shift allows nbits to be only up to 31. */
|
/* The shift allows nbits to be only up to 31. */
|
||||||
return reader->buffer & ((1u << nbits) - 1u);
|
return reader->buffer & ((1u << nbits) - 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must have enough bits available with ensureBits */
|
/* Must have enough bits available with ensureBits */
|
||||||
static void advanceBits(LodePNGBitReader* reader, size_t nbits) {
|
static LODEPNG_INLINE void advanceBits(LodePNGBitReader* reader, size_t nbits) {
|
||||||
reader->buffer >>= nbits;
|
reader->buffer >>= nbits;
|
||||||
reader->bp += nbits;
|
reader->bp += nbits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must have enough bits available with ensureBits */
|
/* Must have enough bits available with ensureBits */
|
||||||
static unsigned readBits(LodePNGBitReader* reader, size_t nbits) {
|
static LODEPNG_INLINE unsigned readBits(LodePNGBitReader* reader, size_t nbits) {
|
||||||
unsigned result = peekBits(reader, nbits);
|
unsigned result = peekBits(reader, nbits);
|
||||||
advanceBits(reader, nbits);
|
advanceBits(reader, nbits);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Public for testing only. steps and result must have numsteps values. */
|
|
||||||
unsigned lode_png_test_bitreader(const unsigned char* data, size_t size,
|
|
||||||
size_t numsteps, const size_t* steps, unsigned* result) {
|
|
||||||
size_t i;
|
|
||||||
LodePNGBitReader reader;
|
|
||||||
unsigned error = LodePNGBitReader_init(&reader, data, size);
|
|
||||||
if(error) return 0;
|
|
||||||
for(i = 0; i < numsteps; i++) {
|
|
||||||
size_t step = steps[i];
|
|
||||||
unsigned ok;
|
|
||||||
if(step > 25) ok = ensureBits32(&reader, step);
|
|
||||||
else if(step > 17) ok = ensureBits25(&reader, step);
|
|
||||||
else if(step > 9) ok = ensureBits17(&reader, step);
|
|
||||||
else ok = ensureBits9(&reader, step);
|
|
||||||
if(!ok) return 0;
|
|
||||||
result[i] = readBits(&reader, step);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif /*LODEPNG_COMPILE_DECODER*/
|
#endif /*LODEPNG_COMPILE_DECODER*/
|
||||||
|
|
||||||
static unsigned reverseBits(unsigned bits, unsigned num) {
|
static unsigned reverseBits(unsigned bits, unsigned num) {
|
||||||
|
@ -1102,11 +1078,10 @@ static unsigned huffmanDecodeSymbol(LodePNGBitReader* reader, const HuffmanTree*
|
||||||
advanceBits(reader, l);
|
advanceBits(reader, l);
|
||||||
return value;
|
return value;
|
||||||
} else {
|
} else {
|
||||||
unsigned index2;
|
|
||||||
advanceBits(reader, FIRSTBITS);
|
advanceBits(reader, FIRSTBITS);
|
||||||
index2 = value + peekBits(reader, l - FIRSTBITS);
|
value += peekBits(reader, l - FIRSTBITS);
|
||||||
advanceBits(reader, codetree->table_len[index2] - FIRSTBITS);
|
advanceBits(reader, codetree->table_len[value] - FIRSTBITS);
|
||||||
return codetree->table_value[index2];
|
return codetree->table_value[value];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /*LODEPNG_COMPILE_DECODER*/
|
#endif /*LODEPNG_COMPILE_DECODER*/
|
||||||
|
@ -1139,7 +1114,8 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
|
||||||
unsigned* bitlen_cl = 0;
|
unsigned* bitlen_cl = 0;
|
||||||
HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/
|
HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/
|
||||||
|
|
||||||
if(!ensureBits17(reader, 14)) return 49; /*error: the bit pointer is or will go past the memory*/
|
if(reader->bitsize - reader->bp < 14) return 49; /*error: the bit pointer is or will go past the memory*/
|
||||||
|
ensureBits17(reader, 14);
|
||||||
|
|
||||||
/*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/
|
/*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/
|
||||||
HLIT = readBits(reader, 5) + 257;
|
HLIT = readBits(reader, 5) + 257;
|
||||||
|
@ -1260,10 +1236,14 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
|
||||||
|
|
||||||
/*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/
|
/*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/
|
||||||
static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
|
static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
|
||||||
unsigned btype) {
|
unsigned btype, size_t max_output_size) {
|
||||||
unsigned error = 0;
|
unsigned error = 0;
|
||||||
HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/
|
HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/
|
||||||
HuffmanTree tree_d; /*the huffman tree for distance codes*/
|
HuffmanTree tree_d; /*the huffman tree for distance codes*/
|
||||||
|
const size_t reserved_size = 260; /* must be at least 258 for max length, and a few extra for adding a few extra literals */
|
||||||
|
int done = 0;
|
||||||
|
|
||||||
|
if(!ucvector_reserve(out, out->size + reserved_size)) return 83; /*alloc fail*/
|
||||||
|
|
||||||
HuffmanTree_init(&tree_ll);
|
HuffmanTree_init(&tree_ll);
|
||||||
HuffmanTree_init(&tree_d);
|
HuffmanTree_init(&tree_d);
|
||||||
|
@ -1271,14 +1251,21 @@ static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
|
||||||
if(btype == 1) error = getTreeInflateFixed(&tree_ll, &tree_d);
|
if(btype == 1) error = getTreeInflateFixed(&tree_ll, &tree_d);
|
||||||
else /*if(btype == 2)*/ error = getTreeInflateDynamic(&tree_ll, &tree_d, reader);
|
else /*if(btype == 2)*/ error = getTreeInflateDynamic(&tree_ll, &tree_d, reader);
|
||||||
|
|
||||||
while(!error) /*decode all symbols until end reached, breaks at end code*/ {
|
|
||||||
|
while(!error && !done) /*decode all symbols until end reached, breaks at end code*/ {
|
||||||
/*code_ll is literal, length or end code*/
|
/*code_ll is literal, length or end code*/
|
||||||
unsigned code_ll;
|
unsigned code_ll;
|
||||||
ensureBits25(reader, 20); /* up to 15 for the huffman symbol, up to 5 for the length extra bits */
|
/* ensure enough bits for 2 huffman code reads (15 bits each): if the first is a literal, a second literal is read at once. This
|
||||||
|
appears to be slightly faster, than ensuring 20 bits here for 1 huffman symbol and the potential 5 extra bits for the length symbol.*/
|
||||||
|
ensureBits32(reader, 30);
|
||||||
code_ll = huffmanDecodeSymbol(reader, &tree_ll);
|
code_ll = huffmanDecodeSymbol(reader, &tree_ll);
|
||||||
|
if(code_ll <= 255) {
|
||||||
|
/*slightly faster code path if multiple literals in a row*/
|
||||||
|
out->data[out->size++] = (unsigned char)code_ll;
|
||||||
|
code_ll = huffmanDecodeSymbol(reader, &tree_ll);
|
||||||
|
}
|
||||||
if(code_ll <= 255) /*literal symbol*/ {
|
if(code_ll <= 255) /*literal symbol*/ {
|
||||||
if(!ucvector_resize(out, out->size + 1)) ERROR_BREAK(83 /*alloc fail*/);
|
out->data[out->size++] = (unsigned char)code_ll;
|
||||||
out->data[out->size - 1] = (unsigned char)code_ll;
|
|
||||||
} else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ {
|
} else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ {
|
||||||
unsigned code_d, distance;
|
unsigned code_d, distance;
|
||||||
unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/
|
unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/
|
||||||
|
@ -1291,6 +1278,7 @@ static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
|
||||||
numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX];
|
numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX];
|
||||||
if(numextrabits_l != 0) {
|
if(numextrabits_l != 0) {
|
||||||
/* bits already ensured above */
|
/* bits already ensured above */
|
||||||
|
ensureBits25(reader, 5);
|
||||||
length += readBits(reader, numextrabits_l);
|
length += readBits(reader, numextrabits_l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1318,7 +1306,7 @@ static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
|
||||||
if(distance > start) ERROR_BREAK(52); /*too long backward distance*/
|
if(distance > start) ERROR_BREAK(52); /*too long backward distance*/
|
||||||
backward = start - distance;
|
backward = start - distance;
|
||||||
|
|
||||||
if(!ucvector_resize(out, out->size + length)) ERROR_BREAK(83 /*alloc fail*/);
|
out->size += length;
|
||||||
if(distance < length) {
|
if(distance < length) {
|
||||||
size_t forward;
|
size_t forward;
|
||||||
lodepng_memcpy(out->data + start, out->data + backward, distance);
|
lodepng_memcpy(out->data + start, out->data + backward, distance);
|
||||||
|
@ -1330,10 +1318,13 @@ static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
|
||||||
lodepng_memcpy(out->data + start, out->data + backward, length);
|
lodepng_memcpy(out->data + start, out->data + backward, length);
|
||||||
}
|
}
|
||||||
} else if(code_ll == 256) {
|
} else if(code_ll == 256) {
|
||||||
break; /*end code, break the loop*/
|
done = 1; /*end code, finish the loop*/
|
||||||
} else /*if(code_ll == INVALIDSYMBOL)*/ {
|
} else /*if(code_ll == INVALIDSYMBOL)*/ {
|
||||||
ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/
|
ERROR_BREAK(16); /*error: tried to read disallowed huffman symbol*/
|
||||||
}
|
}
|
||||||
|
if(out->allocsize - out->size < reserved_size) {
|
||||||
|
if(!ucvector_reserve(out, out->size + reserved_size)) ERROR_BREAK(83); /*alloc fail*/
|
||||||
|
}
|
||||||
/*check if any of the ensureBits above went out of bounds*/
|
/*check if any of the ensureBits above went out of bounds*/
|
||||||
if(reader->bp > reader->bitsize) {
|
if(reader->bp > reader->bitsize) {
|
||||||
/*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
|
/*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
|
||||||
|
@ -1341,6 +1332,9 @@ static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
|
||||||
/* TODO: revise error codes 10,11,50: the above comment is no longer valid */
|
/* TODO: revise error codes 10,11,50: the above comment is no longer valid */
|
||||||
ERROR_BREAK(51); /*error, bit pointer jumps past memory*/
|
ERROR_BREAK(51); /*error, bit pointer jumps past memory*/
|
||||||
}
|
}
|
||||||
|
if(max_output_size && out->size > max_output_size) {
|
||||||
|
ERROR_BREAK(109); /*error, larger than max size*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HuffmanTree_cleanup(&tree_ll);
|
HuffmanTree_cleanup(&tree_ll);
|
||||||
|
@ -1392,15 +1386,16 @@ static unsigned lodepng_inflatev(ucvector* out,
|
||||||
|
|
||||||
while(!BFINAL) {
|
while(!BFINAL) {
|
||||||
unsigned BTYPE;
|
unsigned BTYPE;
|
||||||
if(!ensureBits9(&reader, 3)) return 52; /*error, bit pointer will jump past memory*/
|
if(reader.bitsize - reader.bp < 3) return 52; /*error, bit pointer will jump past memory*/
|
||||||
|
ensureBits9(&reader, 3);
|
||||||
BFINAL = readBits(&reader, 1);
|
BFINAL = readBits(&reader, 1);
|
||||||
BTYPE = readBits(&reader, 2);
|
BTYPE = readBits(&reader, 2);
|
||||||
|
|
||||||
if(BTYPE == 3) return 20; /*error: invalid BTYPE*/
|
if(BTYPE == 3) return 20; /*error: invalid BTYPE*/
|
||||||
else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/
|
else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/
|
||||||
else error = inflateHuffmanBlock(out, &reader, BTYPE); /*compression, BTYPE 01 or 10*/
|
else error = inflateHuffmanBlock(out, &reader, BTYPE, settings->max_output_size); /*compression, BTYPE 01 or 10*/
|
||||||
|
if(!error && settings->max_output_size && out->size > settings->max_output_size) error = 109;
|
||||||
if(error) return error;
|
if(error) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
@ -1421,6 +1416,12 @@ static unsigned inflatev(ucvector* out, const unsigned char* in, size_t insize,
|
||||||
if(settings->custom_inflate) {
|
if(settings->custom_inflate) {
|
||||||
unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings);
|
unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings);
|
||||||
out->allocsize = out->size;
|
out->allocsize = out->size;
|
||||||
|
if(error) {
|
||||||
|
/*the custom inflate is allowed to have its own error codes, however, we translate it to code 110*/
|
||||||
|
error = 110;
|
||||||
|
/*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/
|
||||||
|
if(settings->max_output_size && out->size > settings->max_output_size) error = 109;
|
||||||
|
}
|
||||||
return error;
|
return error;
|
||||||
} else {
|
} else {
|
||||||
return lodepng_inflatev(out, in, insize, settings);
|
return lodepng_inflatev(out, in, insize, settings);
|
||||||
|
@ -2116,7 +2117,9 @@ static unsigned deflate(unsigned char** out, size_t* outsize,
|
||||||
const unsigned char* in, size_t insize,
|
const unsigned char* in, size_t insize,
|
||||||
const LodePNGCompressSettings* settings) {
|
const LodePNGCompressSettings* settings) {
|
||||||
if(settings->custom_deflate) {
|
if(settings->custom_deflate) {
|
||||||
return settings->custom_deflate(out, outsize, in, insize, settings);
|
unsigned error = settings->custom_deflate(out, outsize, in, insize, settings);
|
||||||
|
/*the custom deflate is allowed to have its own error codes, however, we translate it to code 111*/
|
||||||
|
return error ? 111 : 0;
|
||||||
} else {
|
} else {
|
||||||
return lodepng_deflate(out, outsize, in, insize, settings);
|
return lodepng_deflate(out, outsize, in, insize, settings);
|
||||||
}
|
}
|
||||||
|
@ -2213,10 +2216,16 @@ unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const uns
|
||||||
/*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */
|
/*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */
|
||||||
static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size,
|
static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size,
|
||||||
const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) {
|
const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) {
|
||||||
|
unsigned error;
|
||||||
if(settings->custom_zlib) {
|
if(settings->custom_zlib) {
|
||||||
return settings->custom_zlib(out, outsize, in, insize, settings);
|
error = settings->custom_zlib(out, outsize, in, insize, settings);
|
||||||
|
if(error) {
|
||||||
|
/*the custom zlib is allowed to have its own error codes, however, we translate it to code 110*/
|
||||||
|
error = 110;
|
||||||
|
/*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/
|
||||||
|
if(settings->max_output_size && *outsize > settings->max_output_size) error = 109;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned error;
|
|
||||||
ucvector v = ucvector_init(*out, *outsize);
|
ucvector v = ucvector_init(*out, *outsize);
|
||||||
if(expected_size) {
|
if(expected_size) {
|
||||||
/*reserve the memory to avoid intermediate reallocations*/
|
/*reserve the memory to avoid intermediate reallocations*/
|
||||||
|
@ -2226,8 +2235,8 @@ static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t exp
|
||||||
error = lodepng_zlib_decompressv(&v, in, insize, settings);
|
error = lodepng_zlib_decompressv(&v, in, insize, settings);
|
||||||
*out = v.data;
|
*out = v.data;
|
||||||
*outsize = v.size;
|
*outsize = v.size;
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*LODEPNG_COMPILE_DECODER*/
|
#endif /*LODEPNG_COMPILE_DECODER*/
|
||||||
|
@ -2275,7 +2284,9 @@ unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsig
|
||||||
static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
|
static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
|
||||||
size_t insize, const LodePNGCompressSettings* settings) {
|
size_t insize, const LodePNGCompressSettings* settings) {
|
||||||
if(settings->custom_zlib) {
|
if(settings->custom_zlib) {
|
||||||
return settings->custom_zlib(out, outsize, in, insize, settings);
|
unsigned error = settings->custom_zlib(out, outsize, in, insize, settings);
|
||||||
|
/*the custom zlib is allowed to have its own error codes, however, we translate it to code 111*/
|
||||||
|
return error ? 111 : 0;
|
||||||
} else {
|
} else {
|
||||||
return lodepng_zlib_compress(out, outsize, in, insize, settings);
|
return lodepng_zlib_compress(out, outsize, in, insize, settings);
|
||||||
}
|
}
|
||||||
|
@ -2334,13 +2345,14 @@ const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT
|
||||||
void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) {
|
void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) {
|
||||||
settings->ignore_adler32 = 0;
|
settings->ignore_adler32 = 0;
|
||||||
settings->ignore_nlen = 0;
|
settings->ignore_nlen = 0;
|
||||||
|
settings->max_output_size = 0;
|
||||||
|
|
||||||
settings->custom_zlib = 0;
|
settings->custom_zlib = 0;
|
||||||
settings->custom_inflate = 0;
|
settings->custom_inflate = 0;
|
||||||
settings->custom_context = 0;
|
settings->custom_context = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0};
|
const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
#endif /*LODEPNG_COMPILE_DECODER*/
|
#endif /*LODEPNG_COMPILE_DECODER*/
|
||||||
|
|
||||||
|
@ -2872,8 +2884,8 @@ static void LodePNGText_cleanup(LodePNGInfo* info) {
|
||||||
|
|
||||||
static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
|
static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
dest->text_keys = 0;
|
dest->text_keys = NULL;
|
||||||
dest->text_strings = 0;
|
dest->text_strings = NULL;
|
||||||
dest->text_num = 0;
|
dest->text_num = 0;
|
||||||
for(i = 0; i != source->text_num; ++i) {
|
for(i = 0; i != source->text_num; ++i) {
|
||||||
CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i]));
|
CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i]));
|
||||||
|
@ -2932,10 +2944,10 @@ static void LodePNGIText_cleanup(LodePNGInfo* info) {
|
||||||
|
|
||||||
static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
|
static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
dest->itext_keys = 0;
|
dest->itext_keys = NULL;
|
||||||
dest->itext_langtags = 0;
|
dest->itext_langtags = NULL;
|
||||||
dest->itext_transkeys = 0;
|
dest->itext_transkeys = NULL;
|
||||||
dest->itext_strings = 0;
|
dest->itext_strings = NULL;
|
||||||
dest->itext_num = 0;
|
dest->itext_num = 0;
|
||||||
for(i = 0; i != source->itext_num; ++i) {
|
for(i = 0; i != source->itext_num; ++i) {
|
||||||
CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i],
|
CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i],
|
||||||
|
@ -4093,10 +4105,12 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
|
||||||
case 0:
|
case 0:
|
||||||
for(i = 0; i != length; ++i) recon[i] = scanline[i];
|
for(i = 0; i != length; ++i) recon[i] = scanline[i];
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1: {
|
||||||
|
size_t j = 0;
|
||||||
for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
|
for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
|
||||||
for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth];
|
for(i = bytewidth; i != length; ++i, ++j) recon[i] = scanline[i] + recon[j];
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 2:
|
case 2:
|
||||||
if(precon) {
|
if(precon) {
|
||||||
for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i];
|
for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i];
|
||||||
|
@ -4106,24 +4120,56 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if(precon) {
|
if(precon) {
|
||||||
|
size_t j = 0;
|
||||||
for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u);
|
for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u);
|
||||||
for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1u);
|
/* Unroll independent paths of this predictor. A 6x and 8x version is also possible but that adds
|
||||||
|
too much code. Whether this speeds up anything depends on compiler and settings. */
|
||||||
|
if(bytewidth >= 4) {
|
||||||
|
for(; i + 3 < length; i += 4, j += 4) {
|
||||||
|
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3];
|
||||||
|
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3];
|
||||||
|
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3];
|
||||||
|
recon[i + 0] = s0 + ((r0 + p0) >> 1u);
|
||||||
|
recon[i + 1] = s1 + ((r1 + p1) >> 1u);
|
||||||
|
recon[i + 2] = s2 + ((r2 + p2) >> 1u);
|
||||||
|
recon[i + 3] = s3 + ((r3 + p3) >> 1u);
|
||||||
|
}
|
||||||
|
} else if(bytewidth >= 3) {
|
||||||
|
for(; i + 2 < length; i += 3, j += 3) {
|
||||||
|
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2];
|
||||||
|
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2];
|
||||||
|
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2];
|
||||||
|
recon[i + 0] = s0 + ((r0 + p0) >> 1u);
|
||||||
|
recon[i + 1] = s1 + ((r1 + p1) >> 1u);
|
||||||
|
recon[i + 2] = s2 + ((r2 + p2) >> 1u);
|
||||||
|
}
|
||||||
|
} else if(bytewidth >= 2) {
|
||||||
|
for(; i + 1 < length; i += 2, j += 2) {
|
||||||
|
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1];
|
||||||
|
unsigned char r0 = recon[j + 0], r1 = recon[j + 1];
|
||||||
|
unsigned char p0 = precon[i + 0], p1 = precon[i + 1];
|
||||||
|
recon[i + 0] = s0 + ((r0 + p0) >> 1u);
|
||||||
|
recon[i + 1] = s1 + ((r1 + p1) >> 1u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(; i != length; ++i, ++j) recon[i] = scanline[i] + ((recon[j] + precon[i]) >> 1u);
|
||||||
} else {
|
} else {
|
||||||
|
size_t j = 0;
|
||||||
for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
|
for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
|
||||||
for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1u);
|
for(i = bytewidth; i != length; ++i, ++j) recon[i] = scanline[i] + (recon[j] >> 1u);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if(precon) {
|
if(precon) {
|
||||||
|
size_t j = 0;
|
||||||
for(i = 0; i != bytewidth; ++i) {
|
for(i = 0; i != bytewidth; ++i) {
|
||||||
recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
|
recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unroll independent paths of the paeth predictor. A 6x and 8x version would also be possible but that
|
/* Unroll independent paths of the paeth predictor. A 6x and 8x version is also possible but that
|
||||||
adds too much code. Whether this actually speeds anything up at all depends on compiler and settings. */
|
adds too much code. Whether this speeds up anything depends on compiler and settings. */
|
||||||
if(bytewidth >= 4) {
|
if(bytewidth >= 4) {
|
||||||
for(; i + 3 < length; i += 4) {
|
for(; i + 3 < length; i += 4, j += 4) {
|
||||||
size_t j = i - bytewidth;
|
|
||||||
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3];
|
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3];
|
||||||
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3];
|
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3];
|
||||||
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3];
|
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3];
|
||||||
|
@ -4134,8 +4180,7 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
|
||||||
recon[i + 3] = s3 + paethPredictor(r3, p3, q3);
|
recon[i + 3] = s3 + paethPredictor(r3, p3, q3);
|
||||||
}
|
}
|
||||||
} else if(bytewidth >= 3) {
|
} else if(bytewidth >= 3) {
|
||||||
for(; i + 2 < length; i += 3) {
|
for(; i + 2 < length; i += 3, j += 3) {
|
||||||
size_t j = i - bytewidth;
|
|
||||||
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2];
|
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2];
|
||||||
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2];
|
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2];
|
||||||
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2];
|
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2];
|
||||||
|
@ -4145,8 +4190,7 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
|
||||||
recon[i + 2] = s2 + paethPredictor(r2, p2, q2);
|
recon[i + 2] = s2 + paethPredictor(r2, p2, q2);
|
||||||
}
|
}
|
||||||
} else if(bytewidth >= 2) {
|
} else if(bytewidth >= 2) {
|
||||||
for(; i + 1 < length; i += 2) {
|
for(; i + 1 < length; i += 2, j += 2) {
|
||||||
size_t j = i - bytewidth;
|
|
||||||
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1];
|
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1];
|
||||||
unsigned char r0 = recon[j + 0], r1 = recon[j + 1];
|
unsigned char r0 = recon[j + 0], r1 = recon[j + 1];
|
||||||
unsigned char p0 = precon[i + 0], p1 = precon[i + 1];
|
unsigned char p0 = precon[i + 0], p1 = precon[i + 1];
|
||||||
|
@ -4156,16 +4200,17 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(; i != length; ++i) {
|
for(; i != length; ++i, ++j) {
|
||||||
recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
|
recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[j]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
size_t j = 0;
|
||||||
for(i = 0; i != bytewidth; ++i) {
|
for(i = 0; i != bytewidth; ++i) {
|
||||||
recon[i] = scanline[i];
|
recon[i] = scanline[i];
|
||||||
}
|
}
|
||||||
for(i = bytewidth; i < length; ++i) {
|
for(i = bytewidth; i != length; ++i, ++j) {
|
||||||
/*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/
|
/*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/
|
||||||
recon[i] = (scanline[i] + recon[i - bytewidth]);
|
recon[i] = (scanline[i] + recon[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -4447,10 +4492,13 @@ static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, siz
|
||||||
}
|
}
|
||||||
|
|
||||||
/*compressed text chunk (zTXt)*/
|
/*compressed text chunk (zTXt)*/
|
||||||
static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
|
static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder,
|
||||||
const unsigned char* data, size_t chunkLength) {
|
const unsigned char* data, size_t chunkLength) {
|
||||||
unsigned error = 0;
|
unsigned error = 0;
|
||||||
|
|
||||||
|
/*copy the object to change parameters in it*/
|
||||||
|
LodePNGDecompressSettings zlibsettings = decoder->zlibsettings;
|
||||||
|
|
||||||
unsigned length, string2_begin;
|
unsigned length, string2_begin;
|
||||||
char *key = 0;
|
char *key = 0;
|
||||||
unsigned char* str = 0;
|
unsigned char* str = 0;
|
||||||
|
@ -4473,12 +4521,14 @@ static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
||||||
if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
|
if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
|
||||||
|
|
||||||
length = (unsigned)chunkLength - string2_begin;
|
length = (unsigned)chunkLength - string2_begin;
|
||||||
|
zlibsettings.max_output_size = decoder->max_text_size;
|
||||||
/*will fail if zlib error, e.g. if length is too small*/
|
/*will fail if zlib error, e.g. if length is too small*/
|
||||||
error = zlib_decompress(&str, &size, 0, &data[string2_begin],
|
error = zlib_decompress(&str, &size, 0, &data[string2_begin],
|
||||||
length, zlibsettings);
|
length, &zlibsettings);
|
||||||
|
/*error: compressed text larger than decoder->max_text_size*/
|
||||||
|
if(error && size > zlibsettings.max_output_size) error = 112;
|
||||||
if(error) break;
|
if(error) break;
|
||||||
error = lodepng_add_text_sized(info, key, (char*)str, size);
|
error = lodepng_add_text_sized(info, key, (char*)str, size);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4489,11 +4539,14 @@ static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
||||||
}
|
}
|
||||||
|
|
||||||
/*international text chunk (iTXt)*/
|
/*international text chunk (iTXt)*/
|
||||||
static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
|
static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder,
|
||||||
const unsigned char* data, size_t chunkLength) {
|
const unsigned char* data, size_t chunkLength) {
|
||||||
unsigned error = 0;
|
unsigned error = 0;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
/*copy the object to change parameters in it*/
|
||||||
|
LodePNGDecompressSettings zlibsettings = decoder->zlibsettings;
|
||||||
|
|
||||||
unsigned length, begin, compressed;
|
unsigned length, begin, compressed;
|
||||||
char *key = 0, *langtag = 0, *transkey = 0;
|
char *key = 0, *langtag = 0, *transkey = 0;
|
||||||
|
|
||||||
|
@ -4550,9 +4603,12 @@ static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
||||||
if(compressed) {
|
if(compressed) {
|
||||||
unsigned char* str = 0;
|
unsigned char* str = 0;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
zlibsettings.max_output_size = decoder->max_text_size;
|
||||||
/*will fail if zlib error, e.g. if length is too small*/
|
/*will fail if zlib error, e.g. if length is too small*/
|
||||||
error = zlib_decompress(&str, &size, 0, &data[begin],
|
error = zlib_decompress(&str, &size, 0, &data[begin],
|
||||||
length, zlibsettings);
|
length, &zlibsettings);
|
||||||
|
/*error: compressed text larger than decoder->max_text_size*/
|
||||||
|
if(error && size > zlibsettings.max_output_size) error = 112;
|
||||||
if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)str, size);
|
if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)str, size);
|
||||||
lodepng_free(str);
|
lodepng_free(str);
|
||||||
} else {
|
} else {
|
||||||
|
@ -4628,11 +4684,13 @@ static unsigned readChunk_sRGB(LodePNGInfo* info, const unsigned char* data, siz
|
||||||
return 0; /* OK */
|
return 0; /* OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
|
static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecoderSettings* decoder,
|
||||||
const unsigned char* data, size_t chunkLength) {
|
const unsigned char* data, size_t chunkLength) {
|
||||||
unsigned error = 0;
|
unsigned error = 0;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
/*copy the object to change parameters in it*/
|
||||||
|
LodePNGDecompressSettings zlibsettings = decoder->zlibsettings;
|
||||||
|
|
||||||
unsigned length, string2_begin;
|
unsigned length, string2_begin;
|
||||||
|
|
||||||
|
@ -4655,9 +4713,12 @@ static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecompressSetting
|
||||||
if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/
|
if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/
|
||||||
|
|
||||||
length = (unsigned)chunkLength - string2_begin;
|
length = (unsigned)chunkLength - string2_begin;
|
||||||
|
zlibsettings.max_output_size = decoder->max_icc_size;
|
||||||
error = zlib_decompress(&info->iccp_profile, &size, 0,
|
error = zlib_decompress(&info->iccp_profile, &size, 0,
|
||||||
&data[string2_begin],
|
&data[string2_begin],
|
||||||
length, zlibsettings);
|
length, &zlibsettings);
|
||||||
|
/*error: ICC profile larger than decoder->max_icc_size*/
|
||||||
|
if(error && size > zlibsettings.max_output_size) error = 113;
|
||||||
info->iccp_profile_size = size;
|
info->iccp_profile_size = size;
|
||||||
if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/
|
if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/
|
||||||
return error;
|
return error;
|
||||||
|
@ -4688,9 +4749,9 @@ unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "tEXt")) {
|
} else if(lodepng_chunk_type_equals(chunk, "tEXt")) {
|
||||||
error = readChunk_tEXt(&state->info_png, data, chunkLength);
|
error = readChunk_tEXt(&state->info_png, data, chunkLength);
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
|
} else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
|
||||||
error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
|
error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength);
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
|
} else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
|
||||||
error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
|
error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength);
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "tIME")) {
|
} else if(lodepng_chunk_type_equals(chunk, "tIME")) {
|
||||||
error = readChunk_tIME(&state->info_png, data, chunkLength);
|
error = readChunk_tIME(&state->info_png, data, chunkLength);
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "pHYs")) {
|
} else if(lodepng_chunk_type_equals(chunk, "pHYs")) {
|
||||||
|
@ -4702,7 +4763,7 @@ unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "sRGB")) {
|
} else if(lodepng_chunk_type_equals(chunk, "sRGB")) {
|
||||||
error = readChunk_sRGB(&state->info_png, data, chunkLength);
|
error = readChunk_sRGB(&state->info_png, data, chunkLength);
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
|
} else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
|
||||||
error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
|
error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength);
|
||||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||||
} else {
|
} else {
|
||||||
/* unhandled chunk is ok (is not an error) */
|
/* unhandled chunk is ok (is not an error) */
|
||||||
|
@ -4820,13 +4881,13 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
|
} else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
|
||||||
/*compressed text chunk (zTXt)*/
|
/*compressed text chunk (zTXt)*/
|
||||||
if(state->decoder.read_text_chunks) {
|
if(state->decoder.read_text_chunks) {
|
||||||
state->error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
|
state->error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength);
|
||||||
if(state->error) break;
|
if(state->error) break;
|
||||||
}
|
}
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
|
} else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
|
||||||
/*international text chunk (iTXt)*/
|
/*international text chunk (iTXt)*/
|
||||||
if(state->decoder.read_text_chunks) {
|
if(state->decoder.read_text_chunks) {
|
||||||
state->error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
|
state->error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength);
|
||||||
if(state->error) break;
|
if(state->error) break;
|
||||||
}
|
}
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "tIME")) {
|
} else if(lodepng_chunk_type_equals(chunk, "tIME")) {
|
||||||
|
@ -4845,7 +4906,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
state->error = readChunk_sRGB(&state->info_png, data, chunkLength);
|
state->error = readChunk_sRGB(&state->info_png, data, chunkLength);
|
||||||
if(state->error) break;
|
if(state->error) break;
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
|
} else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
|
||||||
state->error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
|
state->error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength);
|
||||||
if(state->error) break;
|
if(state->error) break;
|
||||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||||
} else /*it's not an implemented chunk type, so ignore it: skip over the data*/ {
|
} else /*it's not an implemented chunk type, so ignore it: skip over the data*/ {
|
||||||
|
@ -4871,7 +4932,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize);
|
if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) {
|
if(!state->error && state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) {
|
||||||
state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */
|
state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4955,6 +5016,11 @@ unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, co
|
||||||
lodepng_state_init(&state);
|
lodepng_state_init(&state);
|
||||||
state.info_raw.colortype = colortype;
|
state.info_raw.colortype = colortype;
|
||||||
state.info_raw.bitdepth = bitdepth;
|
state.info_raw.bitdepth = bitdepth;
|
||||||
|
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||||
|
/*disable reading things that this function doesn't output*/
|
||||||
|
state.decoder.read_text_chunks = 0;
|
||||||
|
state.decoder.remember_unknown_chunks = 0;
|
||||||
|
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||||
error = lodepng_decode(out, w, h, &state, in, insize);
|
error = lodepng_decode(out, w, h, &state, in, insize);
|
||||||
lodepng_state_cleanup(&state);
|
lodepng_state_cleanup(&state);
|
||||||
return error;
|
return error;
|
||||||
|
@ -4997,6 +5063,8 @@ void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) {
|
||||||
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||||
settings->read_text_chunks = 1;
|
settings->read_text_chunks = 1;
|
||||||
settings->remember_unknown_chunks = 0;
|
settings->remember_unknown_chunks = 0;
|
||||||
|
settings->max_text_size = 16777216;
|
||||||
|
settings->max_icc_size = 16777216; /* 16MB is much more than enough for any reasonable ICC profile */
|
||||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||||
settings->ignore_crc = 0;
|
settings->ignore_crc = 0;
|
||||||
settings->ignore_critical = 0;
|
settings->ignore_critical = 0;
|
||||||
|
@ -5871,11 +5939,15 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
|
||||||
if(!state->error) {
|
if(!state->error) {
|
||||||
state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h);
|
state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h);
|
||||||
}
|
}
|
||||||
if(!state->error) preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder);
|
if(!state->error) {
|
||||||
|
state->error = preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder);
|
||||||
|
}
|
||||||
lodepng_free(converted);
|
lodepng_free(converted);
|
||||||
if(state->error) goto cleanup;
|
if(state->error) goto cleanup;
|
||||||
|
} else {
|
||||||
|
state->error = preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder);
|
||||||
|
if(state->error) goto cleanup;
|
||||||
}
|
}
|
||||||
else preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder);
|
|
||||||
|
|
||||||
/* output all PNG chunks */ {
|
/* output all PNG chunks */ {
|
||||||
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||||
|
@ -6200,6 +6272,16 @@ const char* lodepng_error_text(unsigned code) {
|
||||||
case 106: return "PNG file must have PLTE chunk if color type is palette";
|
case 106: return "PNG file must have PLTE chunk if color type is palette";
|
||||||
case 107: return "color convert from palette mode requested without setting the palette data in it";
|
case 107: return "color convert from palette mode requested without setting the palette data in it";
|
||||||
case 108: return "tried to add more than 256 values to a palette";
|
case 108: return "tried to add more than 256 values to a palette";
|
||||||
|
/*this limit can be configured in LodePNGDecompressSettings*/
|
||||||
|
case 109: return "tried to decompress zlib or deflate data larger than desired max_output_size";
|
||||||
|
case 110: return "custom zlib or inflate decompression failed";
|
||||||
|
case 111: return "custom zlib or deflate compression failed";
|
||||||
|
/*max text size limit can be configured in LodePNGDecoderSettings. This error prevents
|
||||||
|
unreasonable memory consumption when decoding due to impossibly large text sizes.*/
|
||||||
|
case 112: return "compressed text unreasonably large";
|
||||||
|
/*max ICC size limit can be configured in LodePNGDecoderSettings. This error prevents
|
||||||
|
unreasonable memory consumption when decoding due to impossibly large ICC profile*/
|
||||||
|
case 113: return "ICC profile unreasonably large";
|
||||||
}
|
}
|
||||||
return "unknown error code";
|
return "unknown error code";
|
||||||
}
|
}
|
||||||
|
|
109
third_party/lodepng/lodepng.h
vendored
109
third_party/lodepng/lodepng.h
vendored
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
LodePNG version 20200306
|
LodePNG version 20220109
|
||||||
|
|
||||||
Copyright (c) 2005-2020 Lode Vandevenne
|
Copyright (c) 2005-2022 Lode Vandevenne
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -142,16 +142,24 @@ unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
/*
|
/*
|
||||||
Load PNG from disk, from file with given name.
|
Load PNG from disk, from file with given name.
|
||||||
Same as the other decode functions, but instead takes a filename as input.
|
Same as the other decode functions, but instead takes a filename as input.
|
||||||
*/
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory.*/
|
||||||
unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h,
|
unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
const char* filename,
|
const char* filename,
|
||||||
LodePNGColorType colortype, unsigned bitdepth);
|
LodePNGColorType colortype, unsigned bitdepth);
|
||||||
|
|
||||||
/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.*/
|
/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory.*/
|
||||||
unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h,
|
unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
const char* filename);
|
const char* filename);
|
||||||
|
|
||||||
/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.*/
|
/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory.*/
|
||||||
unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h,
|
unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
const char* filename);
|
const char* filename);
|
||||||
#endif /*LODEPNG_COMPILE_DISK*/
|
#endif /*LODEPNG_COMPILE_DISK*/
|
||||||
|
@ -191,17 +199,26 @@ unsigned lodepng_encode24(unsigned char** out, size_t* outsize,
|
||||||
/*
|
/*
|
||||||
Converts raw pixel data into a PNG file on disk.
|
Converts raw pixel data into a PNG file on disk.
|
||||||
Same as the other encode functions, but instead takes a filename as output.
|
Same as the other encode functions, but instead takes a filename as output.
|
||||||
|
|
||||||
NOTE: This overwrites existing files without warning!
|
NOTE: This overwrites existing files without warning!
|
||||||
*/
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and encode in-memory.*/
|
||||||
unsigned lodepng_encode_file(const char* filename,
|
unsigned lodepng_encode_file(const char* filename,
|
||||||
const unsigned char* image, unsigned w, unsigned h,
|
const unsigned char* image, unsigned w, unsigned h,
|
||||||
LodePNGColorType colortype, unsigned bitdepth);
|
LodePNGColorType colortype, unsigned bitdepth);
|
||||||
|
|
||||||
/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.*/
|
/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and encode in-memory.*/
|
||||||
unsigned lodepng_encode32_file(const char* filename,
|
unsigned lodepng_encode32_file(const char* filename,
|
||||||
const unsigned char* image, unsigned w, unsigned h);
|
const unsigned char* image, unsigned w, unsigned h);
|
||||||
|
|
||||||
/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.*/
|
/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and encode in-memory.*/
|
||||||
unsigned lodepng_encode24_file(const char* filename,
|
unsigned lodepng_encode24_file(const char* filename,
|
||||||
const unsigned char* image, unsigned w, unsigned h);
|
const unsigned char* image, unsigned w, unsigned h);
|
||||||
#endif /*LODEPNG_COMPILE_DISK*/
|
#endif /*LODEPNG_COMPILE_DISK*/
|
||||||
|
@ -223,6 +240,9 @@ unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
|
||||||
/*
|
/*
|
||||||
Converts PNG file from disk to raw pixel data in memory.
|
Converts PNG file from disk to raw pixel data in memory.
|
||||||
Same as the other decode functions, but instead takes a filename as input.
|
Same as the other decode functions, but instead takes a filename as input.
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory.
|
||||||
*/
|
*/
|
||||||
unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
|
unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
|
@ -243,7 +263,11 @@ unsigned encode(std::vector<unsigned char>& out,
|
||||||
/*
|
/*
|
||||||
Converts 32-bit RGBA raw pixel data into a PNG file on disk.
|
Converts 32-bit RGBA raw pixel data into a PNG file on disk.
|
||||||
Same as the other encode functions, but instead takes a filename as output.
|
Same as the other encode functions, but instead takes a filename as output.
|
||||||
|
|
||||||
NOTE: This overwrites existing files without warning!
|
NOTE: This overwrites existing files without warning!
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory.
|
||||||
*/
|
*/
|
||||||
unsigned encode(const std::string& filename,
|
unsigned encode(const std::string& filename,
|
||||||
const unsigned char* in, unsigned w, unsigned h,
|
const unsigned char* in, unsigned w, unsigned h,
|
||||||
|
@ -270,12 +294,21 @@ struct LodePNGDecompressSettings {
|
||||||
unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/
|
unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/
|
||||||
unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/
|
unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/
|
||||||
|
|
||||||
/*use custom zlib decoder instead of built in one (default: null)*/
|
/*Maximum decompressed size, beyond this the decoder may (and is encouraged to) stop decoding,
|
||||||
|
return an error, output a data size > max_output_size and all the data up to that point. This is
|
||||||
|
not hard limit nor a guarantee, but can prevent excessive memory usage. This setting is
|
||||||
|
ignored by the PNG decoder, but is used by the deflate/zlib decoder and can be used by custom ones.
|
||||||
|
Set to 0 to impose no limit (the default).*/
|
||||||
|
size_t max_output_size;
|
||||||
|
|
||||||
|
/*use custom zlib decoder instead of built in one (default: null).
|
||||||
|
Should return 0 if success, any non-0 if error (numeric value not exposed).*/
|
||||||
unsigned (*custom_zlib)(unsigned char**, size_t*,
|
unsigned (*custom_zlib)(unsigned char**, size_t*,
|
||||||
const unsigned char*, size_t,
|
const unsigned char*, size_t,
|
||||||
const LodePNGDecompressSettings*);
|
const LodePNGDecompressSettings*);
|
||||||
/*use custom deflate decoder instead of built in one (default: null)
|
/*use custom deflate decoder instead of built in one (default: null)
|
||||||
if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate)*/
|
if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate).
|
||||||
|
Should return 0 if success, any non-0 if error (numeric value not exposed).*/
|
||||||
unsigned (*custom_inflate)(unsigned char**, size_t*,
|
unsigned (*custom_inflate)(unsigned char**, size_t*,
|
||||||
const unsigned char*, size_t,
|
const unsigned char*, size_t,
|
||||||
const LodePNGDecompressSettings*);
|
const LodePNGDecompressSettings*);
|
||||||
|
@ -454,30 +487,36 @@ typedef struct LodePNGInfo {
|
||||||
unsigned background_b; /*blue component of suggested background color*/
|
unsigned background_b; /*blue component of suggested background color*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
non-international text chunks (tEXt and zTXt)
|
Non-international text chunks (tEXt and zTXt)
|
||||||
|
|
||||||
The char** arrays each contain num strings. The actual messages are in
|
The char** arrays each contain num strings. The actual messages are in
|
||||||
text_strings, while text_keys are keywords that give a short description what
|
text_strings, while text_keys are keywords that give a short description what
|
||||||
the actual text represents, e.g. Title, Author, Description, or anything else.
|
the actual text represents, e.g. Title, Author, Description, or anything else.
|
||||||
|
|
||||||
All the string fields below including keys, names and language tags are null terminated.
|
All the string fields below including strings, keys, names and language tags are null terminated.
|
||||||
The PNG specification uses null characters for the keys, names and tags, and forbids null
|
The PNG specification uses null characters for the keys, names and tags, and forbids null
|
||||||
characters to appear in the main text which is why we can use null termination everywhere here.
|
characters to appear in the main text which is why we can use null termination everywhere here.
|
||||||
|
|
||||||
A keyword is minimum 1 character and maximum 79 characters long. It's
|
A keyword is minimum 1 character and maximum 79 characters long (plus the
|
||||||
discouraged to use a single line length longer than 79 characters for texts.
|
additional null terminator). It's discouraged to use a single line length
|
||||||
|
longer than 79 characters for texts.
|
||||||
|
|
||||||
Don't allocate these text buffers yourself. Use the init/cleanup functions
|
Don't allocate these text buffers yourself. Use the init/cleanup functions
|
||||||
correctly and use lodepng_add_text and lodepng_clear_text.
|
correctly and use lodepng_add_text and lodepng_clear_text.
|
||||||
|
|
||||||
|
Standard text chunk keywords and strings are encoded using Latin-1.
|
||||||
*/
|
*/
|
||||||
size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/
|
size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/
|
||||||
char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/
|
char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/
|
||||||
char** text_strings; /*the actual text*/
|
char** text_strings; /*the actual text*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
international text chunks (iTXt)
|
International text chunks (iTXt)
|
||||||
Similar to the non-international text chunks, but with additional strings
|
Similar to the non-international text chunks, but with additional strings
|
||||||
"langtags" and "transkeys".
|
"langtags" and "transkeys", and the following text encodings are used:
|
||||||
|
keys: Latin-1, langtags: ASCII, transkeys and strings: UTF-8.
|
||||||
|
keys must be 1-79 characters (plus the additional null terminator), the other
|
||||||
|
strings are any length.
|
||||||
*/
|
*/
|
||||||
size_t itext_num; /*the amount of international texts in this PNG*/
|
size_t itext_num; /*the amount of international texts in this PNG*/
|
||||||
char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/
|
char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/
|
||||||
|
@ -639,8 +678,19 @@ typedef struct LodePNGDecoderSettings {
|
||||||
|
|
||||||
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||||
unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/
|
unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/
|
||||||
|
|
||||||
/*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/
|
/*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/
|
||||||
unsigned remember_unknown_chunks;
|
unsigned remember_unknown_chunks;
|
||||||
|
|
||||||
|
/* maximum size for decompressed text chunks. If a text chunk's text is larger than this, an error is returned,
|
||||||
|
unless reading text chunks is disabled or this limit is set higher or disabled. Set to 0 to allow any size.
|
||||||
|
By default it is a value that prevents unreasonably large strings from hogging memory. */
|
||||||
|
size_t max_text_size;
|
||||||
|
|
||||||
|
/* maximum size for compressed ICC chunks. If the ICC profile is larger than this, an error will be returned. Set to
|
||||||
|
0 to allow any size. By default this is a value that prevents ICC profiles that would be much larger than any
|
||||||
|
legitimate profile could be to hog memory. */
|
||||||
|
size_t max_icc_size;
|
||||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||||
} LodePNGDecoderSettings;
|
} LodePNGDecoderSettings;
|
||||||
|
|
||||||
|
@ -950,6 +1000,9 @@ out: output parameter, contains pointer to loaded buffer.
|
||||||
outsize: output parameter, size of the allocated out buffer
|
outsize: output parameter, size of the allocated out buffer
|
||||||
filename: the path to the file to load
|
filename: the path to the file to load
|
||||||
return value: error code (0 means ok)
|
return value: error code (0 means ok)
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory.
|
||||||
*/
|
*/
|
||||||
unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename);
|
unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename);
|
||||||
|
|
||||||
|
@ -960,6 +1013,9 @@ buffer: the buffer to write
|
||||||
buffersize: size of the buffer to write
|
buffersize: size of the buffer to write
|
||||||
filename: the path to the file to save to
|
filename: the path to the file to save to
|
||||||
return value: error code (0 means ok)
|
return value: error code (0 means ok)
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and encode in-memory
|
||||||
*/
|
*/
|
||||||
unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename);
|
unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename);
|
||||||
#endif /*LODEPNG_COMPILE_DISK*/
|
#endif /*LODEPNG_COMPILE_DISK*/
|
||||||
|
@ -1000,12 +1056,18 @@ unsigned encode(std::vector<unsigned char>& out,
|
||||||
/*
|
/*
|
||||||
Load a file from disk into an std::vector.
|
Load a file from disk into an std::vector.
|
||||||
return value: error code (0 means ok)
|
return value: error code (0 means ok)
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory
|
||||||
*/
|
*/
|
||||||
unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename);
|
unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Save the binary data in an std::vector to a file on disk. The file is overwritten
|
Save the binary data in an std::vector to a file on disk. The file is overwritten
|
||||||
without warning.
|
without warning.
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and encode in-memory
|
||||||
*/
|
*/
|
||||||
unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename);
|
unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename);
|
||||||
#endif /* LODEPNG_COMPILE_DISK */
|
#endif /* LODEPNG_COMPILE_DISK */
|
||||||
|
@ -1505,6 +1567,11 @@ of the error in English as a string.
|
||||||
|
|
||||||
Check the implementation of lodepng_error_text to see the meaning of each code.
|
Check the implementation of lodepng_error_text to see the meaning of each code.
|
||||||
|
|
||||||
|
It is not recommended to use the numerical values to programmatically make
|
||||||
|
different decisions based on error types as the numbers are not guaranteed to
|
||||||
|
stay backwards compatible. They are for human consumption only. Programmatically
|
||||||
|
only 0 or non-0 matter.
|
||||||
|
|
||||||
|
|
||||||
8. chunks and PNG editing
|
8. chunks and PNG editing
|
||||||
-------------------------
|
-------------------------
|
||||||
|
@ -1678,6 +1745,9 @@ try to fix it if the compiler is modern and standards compliant.
|
||||||
This decoder example shows the most basic usage of LodePNG. More complex
|
This decoder example shows the most basic usage of LodePNG. More complex
|
||||||
examples can be found on the LodePNG website.
|
examples can be found on the LodePNG website.
|
||||||
|
|
||||||
|
NOTE: these examples do not support wide-character filenames, you can use an
|
||||||
|
external method to handle such files and encode or decode in-memory
|
||||||
|
|
||||||
10.1. decoder C++ example
|
10.1. decoder C++ example
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
@ -1775,6 +1845,11 @@ symbol.
|
||||||
Not all changes are listed here, the commit history in github lists more:
|
Not all changes are listed here, the commit history in github lists more:
|
||||||
https://github.com/lvandeve/lodepng
|
https://github.com/lvandeve/lodepng
|
||||||
|
|
||||||
|
*) 09 jan 2022: minor decoder speed improvements.
|
||||||
|
*) 27 jun 2021: added warnings that file reading/writing functions don't support
|
||||||
|
wide-character filenames (support for this is not planned, opening files is
|
||||||
|
not the core part of PNG decoding/decoding and is platform dependent).
|
||||||
|
*) 17 okt 2020: prevent decoding too large text/icc chunks by default.
|
||||||
*) 06 mar 2020: simplified some of the dynamic memory allocations.
|
*) 06 mar 2020: simplified some of the dynamic memory allocations.
|
||||||
*) 12 jan 2020: (!) added 'end' argument to lodepng_chunk_next to allow correct
|
*) 12 jan 2020: (!) added 'end' argument to lodepng_chunk_next to allow correct
|
||||||
overflow checks.
|
overflow checks.
|
||||||
|
@ -1941,5 +2016,5 @@ Domain: gmail dot com.
|
||||||
Account: lode dot vandevenne.
|
Account: lode dot vandevenne.
|
||||||
|
|
||||||
|
|
||||||
Copyright (c) 2005-2020 Lode Vandevenne
|
Copyright (c) 2005-2022 Lode Vandevenne
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue