update lodepng to 20190824 version from mainstream.

git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1623 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
Ozkan Sezer 2019-08-28 00:10:02 +00:00
parent e4eae98ab4
commit 0e6c4f27cc
2 changed files with 111 additions and 140 deletions

View file

@ -1,5 +1,5 @@
/* /*
LodePNG version 20190814 LodePNG version 20190824
Copyright (c) 2005-2019 Lode Vandevenne Copyright (c) 2005-2019 Lode Vandevenne
@ -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 = "20190814"; const char* LODEPNG_VERSION_STRING = "20190824";
/* /*
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
@ -317,10 +317,12 @@ static char* alloc_string(const char* in) {
/* ////////////////////////////////////////////////////////////////////////// */ /* ////////////////////////////////////////////////////////////////////////// */
static #if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG)
unsigned lodepng_read32bitInt(const unsigned char* buffer) { static unsigned lodepng_read32bitInt(const unsigned char* buffer) {
return (((unsigned)buffer[0] << 24u) | ((unsigned)buffer[1] << 16u) | ((unsigned)buffer[2] << 8u) | (unsigned)buffer[3]); return (((unsigned)buffer[0] << 24u) | ((unsigned)buffer[1] << 16u) |
((unsigned)buffer[2] << 8u) | (unsigned)buffer[3]);
} }
#endif /*defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_PNG)*/
#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER) #if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)
/*buffer must have at least 4 allocated bytes available*/ /*buffer must have at least 4 allocated bytes available*/
@ -332,13 +334,6 @@ static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) {
} }
#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ #endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/
#ifdef LODEPNG_COMPILE_ENCODER
static void lodepng_add32bitInt(ucvector* buffer, unsigned value) {
ucvector_resize(buffer, buffer->size + 4); /*todo: give error if resize failed*/
lodepng_set32bitInt(&buffer->data[buffer->size - 4], value);
}
#endif /*LODEPNG_COMPILE_ENCODER*/
/* ////////////////////////////////////////////////////////////////////////// */ /* ////////////////////////////////////////////////////////////////////////// */
/* / File IO / */ /* / File IO / */
/* ////////////////////////////////////////////////////////////////////////// */ /* ////////////////////////////////////////////////////////////////////////// */
@ -2116,14 +2111,23 @@ static unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsi
unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
size_t insize, const LodePNGCompressSettings* settings) { size_t insize, const LodePNGCompressSettings* settings) {
/*initially, *out must be NULL and outsize 0, if you just give some random *out
that's pointing to a non allocated buffer, this'll crash*/
ucvector outv;
size_t i; size_t i;
unsigned error; unsigned error;
unsigned char* deflatedata = 0; unsigned char* deflatedata = 0;
size_t deflatesize = 0; size_t deflatesize = 0;
error = deflate(&deflatedata, &deflatesize, in, insize, settings);
*out = NULL;
*outsize = 0;
if(!error) {
*outsize = deflatesize + 6;
*out = (unsigned char*)lodepng_malloc(*outsize);
if(!out) error = 83; /*alloc fail*/
}
if(!error) {
unsigned ADLER32 = adler32(in, (unsigned)insize);
/*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/ /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/
unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/ unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/
unsigned FLEVEL = 0; unsigned FLEVEL = 0;
@ -2132,24 +2136,13 @@ unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsig
unsigned FCHECK = 31 - CMFFLG % 31; unsigned FCHECK = 31 - CMFFLG % 31;
CMFFLG += FCHECK; CMFFLG += FCHECK;
/*ucvector-controlled version of the output buffer, for dynamic array*/ (*out)[0] = (unsigned char)(CMFFLG >> 8);
ucvector_init_buffer(&outv, *out, *outsize); (*out)[1] = (unsigned char)(CMFFLG & 255);
for(i = 0; i != deflatesize; ++i) (*out)[i + 2] = deflatedata[i];
ucvector_push_back(&outv, (unsigned char)(CMFFLG >> 8)); lodepng_set32bitInt(&(*out)[*outsize - 4], ADLER32);
ucvector_push_back(&outv, (unsigned char)(CMFFLG & 255));
error = deflate(&deflatedata, &deflatesize, in, insize, settings);
if(!error) {
unsigned ADLER32 = adler32(in, (unsigned)insize);
for(i = 0; i != deflatesize; ++i) ucvector_push_back(&outv, deflatedata[i]);
lodepng_free(deflatedata);
lodepng_add32bitInt(&outv, ADLER32);
} }
*out = outv.data; lodepng_free(deflatedata);
*outsize = outv.size;
return error; return error;
} }
@ -2604,8 +2597,7 @@ unsigned lodepng_can_have_alpha(const LodePNGColorMode* info) {
|| lodepng_has_palette_alpha(info); || lodepng_has_palette_alpha(info);
} }
static static size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) {
size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) {
size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth); size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth);
size_t n = (size_t)w * (size_t)h; size_t n = (size_t)w * (size_t)h;
return ((n / 8u) * bpp) + ((n & 7u) * bpp + 7u) / 8u; return ((n / 8u) * bpp) + ((n & 7u) * bpp + 7u) / 8u;
@ -2827,6 +2819,8 @@ unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langt
/* same as set but does not delete */ /* same as set but does not delete */
static unsigned lodepng_assign_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) { static unsigned lodepng_assign_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) {
if(profile_size == 0) return 100; /*invalid ICC profile size*/
info->iccp_name = alloc_string(name); info->iccp_name = alloc_string(name);
info->iccp_profile = (unsigned char*)lodepng_malloc(profile_size); info->iccp_profile = (unsigned char*)lodepng_malloc(profile_size);
@ -4393,6 +4387,7 @@ static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecompressSetting
&data[string2_begin], &data[string2_begin],
length, zlibsettings); length, zlibsettings);
if(!error) { if(!error) {
if(decoded.size) {
info->iccp_profile_size = decoded.size; info->iccp_profile_size = decoded.size;
info->iccp_profile = (unsigned char*)lodepng_malloc(decoded.size); info->iccp_profile = (unsigned char*)lodepng_malloc(decoded.size);
if(info->iccp_profile) { if(info->iccp_profile) {
@ -4400,6 +4395,9 @@ static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecompressSetting
} else { } else {
error = 83; /* alloc fail */ error = 83; /* alloc fail */
} }
} else {
error = 100; /*invalid ICC profile size*/
}
} }
ucvector_cleanup(&decoded); ucvector_cleanup(&decoded);
return error; return error;
@ -4466,8 +4464,8 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
const unsigned char* chunk; const unsigned char* chunk;
size_t i; size_t i;
ucvector idat; /*the data from idat chunks*/ ucvector idat; /*the data from idat chunks*/
ucvector scanlines; unsigned char* scanlines = 0;
size_t predict; size_t scanlines_size = 0, expected_size = 0;
size_t outsize = 0; size_t outsize = 0;
/*for unknown chunk order*/ /*for unknown chunk order*/
@ -4610,28 +4608,35 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
if(!IEND) chunk = lodepng_chunk_next_const(chunk); if(!IEND) chunk = lodepng_chunk_next_const(chunk);
} }
ucvector_init(&scanlines);
/*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation. /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation.
If the decompressed size does not match the prediction, the image must be corrupt.*/ If the decompressed size does not match the prediction, the image must be corrupt.*/
if(state->info_png.interlace_method == 0) { if(state->info_png.interlace_method == 0) {
predict = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color); expected_size = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color);
} else { } else {
/*Adam-7 interlaced: predicted size is the sum of the 7 sub-images sizes*/ /*Adam-7 interlaced: expected size is the sum of the 7 sub-images sizes*/
const LodePNGColorMode* color = &state->info_png.color; const LodePNGColorMode* color = &state->info_png.color;
predict = 0; expected_size = 0;
predict += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, color); expected_size += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, color);
if(*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, color); if(*w > 4) expected_size += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, color);
predict += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, color); expected_size += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, color);
if(*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, color); if(*w > 2) expected_size += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, color);
predict += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, color); expected_size += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, color);
if(*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, color); if(*w > 1) expected_size += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, color);
predict += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, color); expected_size += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, color);
} }
if(!state->error && !ucvector_reserve(&scanlines, predict)) state->error = 83; /*alloc fail*/
if(!state->error) { if(!state->error) {
state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data, /* This allocated data will be realloced by zlib_decompress, initially at
smaller size again. But the fact that it's already allocated at full size
here speeds the multiple reallocs up. TODO: make zlib_decompress support
receiving already allocated buffer with expected size instead. */
scanlines = (unsigned char*)lodepng_malloc(expected_size);
if(!scanlines) state->error = 83; /*alloc fail*/
scanlines_size = 0;
}
if(!state->error) {
state->error = zlib_decompress(&scanlines, &scanlines_size, idat.data,
idat.size, &state->decoder.zlibsettings); idat.size, &state->decoder.zlibsettings);
if(!state->error && scanlines.size != predict) state->error = 91; /*decompressed size doesn't match prediction*/ if(!state->error && scanlines_size != expected_size) state->error = 91; /*decompressed size doesn't match prediction*/
} }
ucvector_cleanup(&idat); ucvector_cleanup(&idat);
@ -4642,9 +4647,9 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
} }
if(!state->error) { if(!state->error) {
for(i = 0; i < outsize; i++) (*out)[i] = 0; for(i = 0; i < outsize; i++) (*out)[i] = 0;
state->error = postProcessScanlines(*out, scanlines.data, *w, *h, &state->info_png); state->error = postProcessScanlines(*out, scanlines, *w, *h, &state->info_png);
} }
ucvector_cleanup(&scanlines); lodepng_free(scanlines);
} }
unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,
@ -4800,22 +4805,17 @@ static void writeSignature(ucvector* out) {
static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h,
LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) { LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) {
unsigned error = 0; unsigned char data[13];
ucvector header;
ucvector_init(&header);
lodepng_add32bitInt(&header, w); /*width*/ lodepng_set32bitInt(data + 0, w); /*width*/
lodepng_add32bitInt(&header, h); /*height*/ lodepng_set32bitInt(data + 4, h); /*height*/
ucvector_push_back(&header, (unsigned char)bitdepth); /*bit depth*/ data[8] = (unsigned char)bitdepth; /*bit depth*/
ucvector_push_back(&header, (unsigned char)colortype); /*color type*/ data[9] = (unsigned char)colortype; /*color type*/
ucvector_push_back(&header, 0); /*compression method*/ data[10] = 0; /*compression method*/
ucvector_push_back(&header, 0); /*filter method*/ data[11] = 0; /*filter method*/
ucvector_push_back(&header, interlace_method); /*interlace method*/ data[12] = interlace_method; /*interlace method*/
error = addChunk(out, "IHDR", header.data, header.size); return addChunk(out, "IHDR", data, sizeof(data));
ucvector_cleanup(&header);
return error;
} }
static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) { static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) {
@ -4968,33 +4968,29 @@ static unsigned addChunk_iTXt(ucvector* out, unsigned compressed, const char* ke
} }
static unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info) { static unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info) {
unsigned error = 0; unsigned char data[6];
ucvector bKGD; size_t size = 0;
ucvector_init(&bKGD);
if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) { if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) {
ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8)); data[0] = (unsigned char)(info->background_r >> 8);
ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); data[1] = (unsigned char)(info->background_r & 255);
size = 2;
} else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) { } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) {
ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8)); data[0] = (unsigned char)(info->background_r >> 8);
ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); data[1] = (unsigned char)(info->background_r & 255);
ucvector_push_back(&bKGD, (unsigned char)(info->background_g >> 8)); data[2] = (unsigned char)(info->background_g >> 8);
ucvector_push_back(&bKGD, (unsigned char)(info->background_g & 255)); data[3] = (unsigned char)(info->background_g & 255);
ucvector_push_back(&bKGD, (unsigned char)(info->background_b >> 8)); data[4] = (unsigned char)(info->background_b >> 8);
ucvector_push_back(&bKGD, (unsigned char)(info->background_b & 255)); data[5] = (unsigned char)(info->background_b & 255);
size = 6;
} else if(info->color.colortype == LCT_PALETTE) { } else if(info->color.colortype == LCT_PALETTE) {
ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); /*palette index*/ data[0] =(unsigned char)(info->background_r & 255); /*palette index*/
size = 1;
} }
return addChunk(out, "bKGD", data, size);
error = addChunk(out, "bKGD", bKGD.data, bKGD.size);
ucvector_cleanup(&bKGD);
return error;
} }
static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) { static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) {
unsigned error = 0; unsigned char data[7];
unsigned char* data = (unsigned char*)lodepng_malloc(7);
if(!data) return 83; /*alloc fail*/
data[0] = (unsigned char)(time->year >> 8); data[0] = (unsigned char)(time->year >> 8);
data[1] = (unsigned char)(time->year & 255); data[1] = (unsigned char)(time->year & 255);
data[2] = (unsigned char)time->month; data[2] = (unsigned char)time->month;
@ -5002,57 +4998,33 @@ static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) {
data[4] = (unsigned char)time->hour; data[4] = (unsigned char)time->hour;
data[5] = (unsigned char)time->minute; data[5] = (unsigned char)time->minute;
data[6] = (unsigned char)time->second; data[6] = (unsigned char)time->second;
error = addChunk(out, "tIME", data, 7); return addChunk(out, "tIME", data, sizeof(data));
lodepng_free(data);
return error;
} }
static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) { static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) {
unsigned error = 0; unsigned char data[9];
ucvector data; lodepng_set32bitInt(data + 0, info->phys_x);
ucvector_init(&data); lodepng_set32bitInt(data + 4, info->phys_y); data[8] = info->phys_unit;
return addChunk(out, "pHYs", data, sizeof(data));
lodepng_add32bitInt(&data, info->phys_x);
lodepng_add32bitInt(&data, info->phys_y);
ucvector_push_back(&data, info->phys_unit);
error = addChunk(out, "pHYs", data.data, data.size);
ucvector_cleanup(&data);
return error;
} }
static unsigned addChunk_gAMA(ucvector* out, const LodePNGInfo* info) { static unsigned addChunk_gAMA(ucvector* out, const LodePNGInfo* info) {
unsigned error = 0; unsigned char data[4];
ucvector data; lodepng_set32bitInt(data, info->gama_gamma);
ucvector_init(&data); return addChunk(out, "gAMA", data, sizeof(data));
lodepng_add32bitInt(&data, info->gama_gamma);
error = addChunk(out, "gAMA", data.data, data.size);
ucvector_cleanup(&data);
return error;
} }
static unsigned addChunk_cHRM(ucvector* out, const LodePNGInfo* info) { static unsigned addChunk_cHRM(ucvector* out, const LodePNGInfo* info) {
unsigned error = 0; unsigned char data[32];
ucvector data; lodepng_set32bitInt(data + 0, info->chrm_white_x);
ucvector_init(&data); lodepng_set32bitInt(data + 4, info->chrm_white_y);
lodepng_set32bitInt(data + 8, info->chrm_red_x);
lodepng_add32bitInt(&data, info->chrm_white_x); lodepng_set32bitInt(data + 12, info->chrm_red_y);
lodepng_add32bitInt(&data, info->chrm_white_y); lodepng_set32bitInt(data + 16, info->chrm_green_x);
lodepng_add32bitInt(&data, info->chrm_red_x); lodepng_set32bitInt(data + 20, info->chrm_green_y);
lodepng_add32bitInt(&data, info->chrm_red_y); lodepng_set32bitInt(data + 24, info->chrm_blue_x);
lodepng_add32bitInt(&data, info->chrm_green_x); lodepng_set32bitInt(data + 28, info->chrm_blue_y);
lodepng_add32bitInt(&data, info->chrm_green_y); return addChunk(out, "cHRM", data, sizeof(data));
lodepng_add32bitInt(&data, info->chrm_blue_x);
lodepng_add32bitInt(&data, info->chrm_blue_y);
error = addChunk(out, "cHRM", data.data, data.size);
ucvector_cleanup(&data);
return error;
} }
static unsigned addChunk_sRGB(ucvector* out, const LodePNGInfo* info) { static unsigned addChunk_sRGB(ucvector* out, const LodePNGInfo* info) {

View file

@ -1,5 +1,5 @@
/* /*
LodePNG version 20190814 LodePNG version 20190824
Copyright (c) 2005-2019 Lode Vandevenne Copyright (c) 2005-2019 Lode Vandevenne
@ -275,8 +275,7 @@ struct LodePNGDecompressSettings {
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 used, custom_deflate is ignored since only the built in if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate)*/
zlib function will call custom_deflate*/
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*);