mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2024-11-09 23:11:39 +00:00
updated lodepng from mainstream git.
This commit is contained in:
parent
f6a15400ba
commit
f8132afd0f
2 changed files with 298 additions and 63 deletions
258
Quake/lodepng.c
258
Quake/lodepng.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
LodePNG version 20220109
|
||||
LodePNG version 20220717
|
||||
|
||||
Copyright (c) 2005-2022 Lode Vandevenne
|
||||
|
||||
|
@ -44,10 +44,10 @@ 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*/
|
||||
#endif /*_MSC_VER */
|
||||
|
||||
const char* LODEPNG_VERSION_STRING = "20220109";
|
||||
const char* LODEPNG_VERSION_STRING = "20220717";
|
||||
|
||||
/*
|
||||
This source file is built up in the following large parts. The code sections
|
||||
This source file is divided into the following large parts. The code sections
|
||||
with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way.
|
||||
-Tools for C and common code for PNG and Zlib
|
||||
-C Code for Zlib (huffman, deflate, ...)
|
||||
|
@ -713,10 +713,11 @@ static unsigned HuffmanTree_makeTable(HuffmanTree* tree) {
|
|||
numpresent = 0;
|
||||
for(i = 0; i < tree->numcodes; ++i) {
|
||||
unsigned l = tree->lengths[i];
|
||||
unsigned symbol = tree->codes[i]; /*the huffman bit pattern. i itself is the value.*/
|
||||
/*reverse bits, because the huffman bits are given in MSB first order but the bit reader reads LSB first*/
|
||||
unsigned reverse = reverseBits(symbol, l);
|
||||
unsigned symbol, reverse;
|
||||
if(l == 0) continue;
|
||||
symbol = tree->codes[i]; /*the huffman bit pattern. i itself is the value.*/
|
||||
/*reverse bits, because the huffman bits are given in MSB first order but the bit reader reads LSB first*/
|
||||
reverse = reverseBits(symbol, l);
|
||||
numpresent++;
|
||||
|
||||
if(l <= FIRSTBITS) {
|
||||
|
@ -1369,8 +1370,11 @@ static unsigned inflateNoCompression(ucvector* out, LodePNGBitReader* reader,
|
|||
/*read the literal data: LEN bytes are now stored in the out buffer*/
|
||||
if(bytepos + LEN > size) return 23; /*error: reading outside of in buffer*/
|
||||
|
||||
lodepng_memcpy(out->data + out->size - LEN, reader->data + bytepos, LEN);
|
||||
bytepos += LEN;
|
||||
/*out->data can be NULL (when LEN is zero), and arithmetics on NULL ptr is undefined*/
|
||||
if (LEN) {
|
||||
lodepng_memcpy(out->data + out->size - LEN, reader->data + bytepos, LEN);
|
||||
bytepos += LEN;
|
||||
}
|
||||
|
||||
reader->bp = bytepos << 3u;
|
||||
|
||||
|
@ -2371,7 +2375,7 @@ const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0,
|
|||
/* ////////////////////////////////////////////////////////////////////////// */
|
||||
|
||||
|
||||
#ifndef LODEPNG_NO_COMPILE_CRC
|
||||
#ifdef LODEPNG_COMPILE_CRC
|
||||
/* CRC polynomial: 0xedb88320 */
|
||||
static unsigned lodepng_crc32_table[256] = {
|
||||
0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u,
|
||||
|
@ -2417,9 +2421,11 @@ unsigned lodepng_crc32(const unsigned char* data, size_t length) {
|
|||
}
|
||||
return r ^ 0xffffffffu;
|
||||
}
|
||||
#else /* !LODEPNG_NO_COMPILE_CRC */
|
||||
#else /* LODEPNG_COMPILE_CRC */
|
||||
/*in this case, the function is only declared here, and must be defined externally
|
||||
so that it will be linked in*/
|
||||
unsigned lodepng_crc32(const unsigned char* data, size_t length);
|
||||
#endif /* !LODEPNG_NO_COMPILE_CRC */
|
||||
#endif /* LODEPNG_COMPILE_CRC */
|
||||
|
||||
/* ////////////////////////////////////////////////////////////////////////// */
|
||||
/* / Reading and writing PNG color channel bits / */
|
||||
|
@ -2457,7 +2463,7 @@ static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream,
|
|||
/* ////////////////////////////////////////////////////////////////////////// */
|
||||
|
||||
unsigned lodepng_chunk_length(const unsigned char* chunk) {
|
||||
return lodepng_read32bitInt(&chunk[0]);
|
||||
return lodepng_read32bitInt(chunk);
|
||||
}
|
||||
|
||||
void lodepng_chunk_type(char type[5], const unsigned char* chunk) {
|
||||
|
@ -2507,34 +2513,32 @@ void lodepng_chunk_generate_crc(unsigned char* chunk) {
|
|||
}
|
||||
|
||||
unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end) {
|
||||
if(chunk >= end || end - chunk < 12) return end; /*too small to contain a chunk*/
|
||||
size_t available_size = (size_t)(end - chunk);
|
||||
if(chunk >= end || available_size < 12) return end; /*too small to contain a chunk*/
|
||||
if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47
|
||||
&& chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) {
|
||||
/* Is PNG magic header at start of PNG file. Jump to first actual chunk. */
|
||||
return chunk + 8;
|
||||
} else {
|
||||
size_t total_chunk_length;
|
||||
unsigned char* result;
|
||||
if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end;
|
||||
result = chunk + total_chunk_length;
|
||||
if(result < chunk) return end; /*pointer overflow*/
|
||||
return result;
|
||||
if(total_chunk_length > available_size) return end; /*outside of range*/
|
||||
return chunk + total_chunk_length;
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end) {
|
||||
if(chunk >= end || end - chunk < 12) return end; /*too small to contain a chunk*/
|
||||
size_t available_size = (size_t)(end - chunk);
|
||||
if(chunk >= end || available_size < 12) return end; /*too small to contain a chunk*/
|
||||
if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47
|
||||
&& chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) {
|
||||
/* Is PNG magic header at start of PNG file. Jump to first actual chunk. */
|
||||
return chunk + 8;
|
||||
} else {
|
||||
size_t total_chunk_length;
|
||||
const unsigned char* result;
|
||||
if(lodepng_addofl(lodepng_chunk_length(chunk), 12, &total_chunk_length)) return end;
|
||||
result = chunk + total_chunk_length;
|
||||
if(result < chunk) return end; /*pointer overflow*/
|
||||
return result;
|
||||
if(total_chunk_length > available_size) return end; /*outside of range*/
|
||||
return chunk + total_chunk_length;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3044,6 +3048,9 @@ void lodepng_info_init(LodePNGInfo* info) {
|
|||
info->iccp_name = NULL;
|
||||
info->iccp_profile = NULL;
|
||||
|
||||
info->sbit_defined = 0;
|
||||
info->sbit_r = info->sbit_g = info->sbit_b = info->sbit_a = 0;
|
||||
|
||||
LodePNGUnknownChunks_init(info);
|
||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||
}
|
||||
|
@ -3938,7 +3945,7 @@ static unsigned auto_choose_color(LodePNGColorMode* mode_out,
|
|||
if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize
|
||||
&& mode_in->bitdepth == mode_out->bitdepth) {
|
||||
/*If input should have same palette colors, keep original to preserve its order and prevent conversion*/
|
||||
lodepng_color_mode_cleanup(mode_out);
|
||||
lodepng_color_mode_cleanup(mode_out); /*clears palette, keeps the above set colortype and bitdepth fields as-is*/
|
||||
lodepng_color_mode_copy(mode_out, mode_in);
|
||||
}
|
||||
} else /*8-bit or 16-bit per channel*/ {
|
||||
|
@ -4725,6 +4732,47 @@ static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecoderSettings*
|
|||
if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/
|
||||
return error;
|
||||
}
|
||||
|
||||
/*significant bits chunk (sBIT)*/
|
||||
static unsigned readChunk_sBIT(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
|
||||
unsigned bitdepth = (info->color.colortype == LCT_PALETTE) ? 8 : info->color.bitdepth;
|
||||
if(info->color.colortype == LCT_GREY) {
|
||||
/*error: this chunk must be 1 bytes for grayscale image*/
|
||||
if(chunkLength != 1) return 114;
|
||||
if(data[0] == 0 || data[0] > bitdepth) return 115;
|
||||
info->sbit_defined = 1;
|
||||
info->sbit_r = info->sbit_g = info->sbit_b = data[0]; /*setting g and b is not required, but sensible*/
|
||||
} else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_PALETTE) {
|
||||
/*error: this chunk must be 3 bytes for RGB and palette image*/
|
||||
if(chunkLength != 3) return 114;
|
||||
if(data[0] == 0 || data[1] == 0 || data[2] == 0) return 115;
|
||||
if(data[0] > bitdepth || data[1] > bitdepth || data[2] > bitdepth) return 115;
|
||||
info->sbit_defined = 1;
|
||||
info->sbit_r = data[0];
|
||||
info->sbit_g = data[1];
|
||||
info->sbit_b = data[2];
|
||||
} else if(info->color.colortype == LCT_GREY_ALPHA) {
|
||||
/*error: this chunk must be 2 byte for grayscale with alpha image*/
|
||||
if(chunkLength != 2) return 114;
|
||||
if(data[0] == 0 || data[1] == 0) return 115;
|
||||
if(data[0] > bitdepth || data[1] > bitdepth) return 115;
|
||||
info->sbit_defined = 1;
|
||||
info->sbit_r = info->sbit_g = info->sbit_b = data[0]; /*setting g and b is not required, but sensible*/
|
||||
info->sbit_a = data[1];
|
||||
} else if(info->color.colortype == LCT_RGBA) {
|
||||
/*error: this chunk must be 4 bytes for grayscale image*/
|
||||
if(chunkLength != 4) return 114;
|
||||
if(data[0] == 0 || data[1] == 0 || data[2] == 0 || data[3] == 0) return 115;
|
||||
if(data[0] > bitdepth || data[1] > bitdepth || data[2] > bitdepth || data[3] > bitdepth) return 115;
|
||||
info->sbit_defined = 1;
|
||||
info->sbit_r = data[0];
|
||||
info->sbit_g = data[1];
|
||||
info->sbit_b = data[2];
|
||||
info->sbit_a = data[3];
|
||||
}
|
||||
|
||||
return 0; /* OK */
|
||||
}
|
||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||
|
||||
unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
|
||||
|
@ -4739,7 +4787,7 @@ unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
|
|||
chunkLength = lodepng_chunk_length(chunk);
|
||||
if(chunkLength > 2147483647) return 63;
|
||||
data = lodepng_chunk_data_const(chunk);
|
||||
if(data + chunkLength + 4 > in + insize) return 30;
|
||||
if(chunkLength + 12 > insize - pos) return 30;
|
||||
|
||||
if(lodepng_chunk_type_equals(chunk, "PLTE")) {
|
||||
error = readChunk_PLTE(&state->info_png.color, data, chunkLength);
|
||||
|
@ -4766,6 +4814,8 @@ unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
|
|||
error = readChunk_sRGB(&state->info_png, data, chunkLength);
|
||||
} else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
|
||||
error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength);
|
||||
} else if(lodepng_chunk_type_equals(chunk, "sBIT")) {
|
||||
error = readChunk_sBIT(&state->info_png, data, chunkLength);
|
||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||
} else {
|
||||
/* unhandled chunk is ok (is not an error) */
|
||||
|
@ -4784,7 +4834,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
|
|||
LodePNGState* state,
|
||||
const unsigned char* in, size_t insize) {
|
||||
unsigned char IEND = 0;
|
||||
const unsigned char* chunk;
|
||||
const unsigned char* chunk; /*points to beginning of next chunk*/
|
||||
unsigned char* idat; /*the data from idat chunks, zlib compressed*/
|
||||
size_t idatsize = 0;
|
||||
unsigned char* scanlines = 0;
|
||||
|
@ -4820,14 +4870,15 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
|
|||
while(!IEND && !state->error) {
|
||||
unsigned chunkLength;
|
||||
const unsigned char* data; /*the data in the chunk*/
|
||||
size_t pos = (size_t)(chunk - in);
|
||||
|
||||
/*error: size of the in buffer too small to contain next chunk*/
|
||||
if((size_t)((chunk - in) + 12) > insize || chunk < in) {
|
||||
/*error: next chunk out of bounds of the in buffer*/
|
||||
if(chunk < in || pos + 12 > insize) {
|
||||
if(state->decoder.ignore_end) break; /*other errors may still happen though*/
|
||||
CERROR_BREAK(state->error, 30);
|
||||
}
|
||||
|
||||
/*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/
|
||||
/*length of the data of the chunk, excluding the 12 bytes for length, chunk type and CRC*/
|
||||
chunkLength = lodepng_chunk_length(chunk);
|
||||
/*error: chunk length larger than the max PNG chunk size*/
|
||||
if(chunkLength > 2147483647) {
|
||||
|
@ -4835,8 +4886,8 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
|
|||
CERROR_BREAK(state->error, 63);
|
||||
}
|
||||
|
||||
if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in) {
|
||||
CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/
|
||||
if(pos + (size_t)chunkLength + 12 > insize || pos + (size_t)chunkLength + 12 < pos) {
|
||||
CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk (or int overflow)*/
|
||||
}
|
||||
|
||||
data = lodepng_chunk_data_const(chunk);
|
||||
|
@ -4910,6 +4961,9 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
|
|||
} else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
|
||||
state->error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength);
|
||||
if(state->error) break;
|
||||
} else if(lodepng_chunk_type_equals(chunk, "sBIT")) {
|
||||
state->error = readChunk_sBIT(&state->info_png, data, chunkLength);
|
||||
if(state->error) break;
|
||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||
} else /*it's not an implemented chunk type, so ignore it: skip over the data*/ {
|
||||
/*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/
|
||||
|
@ -5145,6 +5199,10 @@ static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) {
|
|||
unsigned char* chunk;
|
||||
size_t i, j = 8;
|
||||
|
||||
if(info->palettesize == 0 || info->palettesize > 256) {
|
||||
return 68; /*invalid palette size, it is only allowed to be 1-256*/
|
||||
}
|
||||
|
||||
CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, info->palettesize * 3, "PLTE"));
|
||||
|
||||
for(i = 0; i != info->palettesize; ++i) {
|
||||
|
@ -5400,6 +5458,42 @@ static unsigned addChunk_iCCP(ucvector* out, const LodePNGInfo* info, LodePNGCom
|
|||
return error;
|
||||
}
|
||||
|
||||
static unsigned addChunk_sBIT(ucvector* out, const LodePNGInfo* info) {
|
||||
unsigned bitdepth = (info->color.colortype == LCT_PALETTE) ? 8 : info->color.bitdepth;
|
||||
unsigned char* chunk = 0;
|
||||
if(info->color.colortype == LCT_GREY) {
|
||||
if(info->sbit_r == 0 || info->sbit_r > bitdepth) return 115;
|
||||
CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 1, "sBIT"));
|
||||
chunk[8] = info->sbit_r;
|
||||
} else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_PALETTE) {
|
||||
if(info->sbit_r == 0 || info->sbit_g == 0 || info->sbit_b == 0) return 115;
|
||||
if(info->sbit_r > bitdepth || info->sbit_g > bitdepth || info->sbit_b > bitdepth) return 115;
|
||||
CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 3, "sBIT"));
|
||||
chunk[8] = info->sbit_r;
|
||||
chunk[9] = info->sbit_g;
|
||||
chunk[10] = info->sbit_b;
|
||||
} else if(info->color.colortype == LCT_GREY_ALPHA) {
|
||||
if(info->sbit_r == 0 || info->sbit_a == 0) return 115;
|
||||
if(info->sbit_r > bitdepth || info->sbit_a > bitdepth) return 115;
|
||||
CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 2, "sBIT"));
|
||||
chunk[8] = info->sbit_r;
|
||||
chunk[9] = info->sbit_a;
|
||||
} else if(info->color.colortype == LCT_RGBA) {
|
||||
if(info->sbit_r == 0 || info->sbit_g == 0 || info->sbit_b == 0 || info->sbit_a == 0 ||
|
||||
info->sbit_r > bitdepth || info->sbit_g > bitdepth ||
|
||||
info->sbit_b > bitdepth || info->sbit_a > bitdepth) {
|
||||
return 115;
|
||||
}
|
||||
CERROR_TRY_RETURN(lodepng_chunk_init(&chunk, out, 4, "sBIT"));
|
||||
chunk[8] = info->sbit_r;
|
||||
chunk[9] = info->sbit_g;
|
||||
chunk[10] = info->sbit_b;
|
||||
chunk[11] = info->sbit_a;
|
||||
}
|
||||
if(chunk) lodepng_chunk_generate_crc(chunk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||
|
||||
static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline,
|
||||
|
@ -5845,8 +5939,10 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
|
|||
ucvector outv = ucvector_init(NULL, 0);
|
||||
LodePNGInfo info;
|
||||
const LodePNGInfo* info_png = &state->info_png;
|
||||
LodePNGColorMode auto_color;
|
||||
|
||||
lodepng_info_init(&info);
|
||||
lodepng_color_mode_init(&auto_color);
|
||||
|
||||
/*provide some proper output values if error will happen*/
|
||||
*out = 0;
|
||||
|
@ -5856,6 +5952,10 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
|
|||
/*check input values validity*/
|
||||
if((info_png->color.colortype == LCT_PALETTE || state->encoder.force_palette)
|
||||
&& (info_png->color.palettesize == 0 || info_png->color.palettesize > 256)) {
|
||||
/*this error is returned even if auto_convert is enabled and thus encoder could
|
||||
generate the palette by itself: while allowing this could be possible in theory,
|
||||
it may complicate the code or edge cases, and always requiring to give a palette
|
||||
when setting this color type is a simpler contract*/
|
||||
state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -5876,6 +5976,7 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
|
|||
lodepng_info_copy(&info, &state->info_png);
|
||||
if(state->encoder.auto_convert) {
|
||||
LodePNGColorStats stats;
|
||||
unsigned allow_convert = 1;
|
||||
lodepng_color_stats_init(&stats);
|
||||
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||
if(info_png->iccp_defined &&
|
||||
|
@ -5897,23 +5998,85 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
|
|||
/*the background chunk's color must be taken into account as well*/
|
||||
unsigned r = 0, g = 0, b = 0;
|
||||
LodePNGColorMode mode16 = lodepng_color_mode_make(LCT_RGB, 16);
|
||||
lodepng_convert_rgb(&r, &g, &b, info_png->background_r, info_png->background_g, info_png->background_b, &mode16, &info_png->color);
|
||||
lodepng_convert_rgb(&r, &g, &b,
|
||||
info_png->background_r, info_png->background_g, info_png->background_b, &mode16, &info_png->color);
|
||||
state->error = lodepng_color_stats_add(&stats, r, g, b, 65535);
|
||||
if(state->error) goto cleanup;
|
||||
}
|
||||
#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */
|
||||
state->error = auto_choose_color(&info.color, &state->info_raw, &stats);
|
||||
state->error = auto_choose_color(&auto_color, &state->info_raw, &stats);
|
||||
if(state->error) goto cleanup;
|
||||
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||
/*also convert the background chunk*/
|
||||
if(info_png->background_defined) {
|
||||
if(lodepng_convert_rgb(&info.background_r, &info.background_g, &info.background_b,
|
||||
info_png->background_r, info_png->background_g, info_png->background_b, &info.color, &info_png->color)) {
|
||||
state->error = 104;
|
||||
goto cleanup;
|
||||
if(info_png->sbit_defined) {
|
||||
/*if sbit is defined, due to strict requirements of which sbit values can be present for which color modes,
|
||||
auto_convert can't be done in many cases. However, do support a few cases here.
|
||||
TODO: more conversions may be possible, and it may also be possible to get a more appropriate color type out of
|
||||
auto_choose_color if knowledge about sbit is used beforehand
|
||||
*/
|
||||
unsigned sbit_max = LODEPNG_MAX(LODEPNG_MAX(LODEPNG_MAX(info_png->sbit_r, info_png->sbit_g),
|
||||
info_png->sbit_b), info_png->sbit_a);
|
||||
unsigned equal = (!info_png->sbit_g || info_png->sbit_g == info_png->sbit_r)
|
||||
&& (!info_png->sbit_b || info_png->sbit_b == info_png->sbit_r)
|
||||
&& (!info_png->sbit_a || info_png->sbit_a == info_png->sbit_r);
|
||||
allow_convert = 0;
|
||||
if(info.color.colortype == LCT_PALETTE &&
|
||||
auto_color.colortype == LCT_PALETTE) {
|
||||
/* input and output are palette, and in this case it may happen that palette data is
|
||||
expected to be copied from info_raw into the info_png */
|
||||
allow_convert = 1;
|
||||
}
|
||||
/*going from 8-bit RGB to palette (or 16-bit as long as sbit_max <= 8) is possible
|
||||
since both are 8-bit RGB for sBIT's purposes*/
|
||||
if(info.color.colortype == LCT_RGB &&
|
||||
auto_color.colortype == LCT_PALETTE && sbit_max <= 8) {
|
||||
allow_convert = 1;
|
||||
}
|
||||
/*going from 8-bit RGBA to palette is also ok but only if sbit_a is exactly 8*/
|
||||
if(info.color.colortype == LCT_RGBA && auto_color.colortype == LCT_PALETTE &&
|
||||
info_png->sbit_a == 8 && sbit_max <= 8) {
|
||||
allow_convert = 1;
|
||||
}
|
||||
/*going from 16-bit RGB(A) to 8-bit RGB(A) is ok if all sbit values are <= 8*/
|
||||
if((info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA) && info.color.bitdepth == 16 &&
|
||||
auto_color.colortype == info.color.colortype && auto_color.bitdepth == 8 &&
|
||||
sbit_max <= 8) {
|
||||
allow_convert = 1;
|
||||
}
|
||||
/*going to less channels is ok if all bit values are equal (all possible values in sbit,
|
||||
as well as the chosen bitdepth of the result). Due to how auto_convert works,
|
||||
we already know that auto_color.colortype has less than or equal amount of channels than
|
||||
info.colortype. Palette is not used here. This conversion is not allowed if
|
||||
info_png->sbit_r < auto_color.bitdepth, because specifically for alpha, non-presence of
|
||||
an sbit value heavily implies that alpha's bit depth is equal to the PNG bit depth (rather
|
||||
than the bit depths set in the r, g and b sbit values, by how the PNG specification describes
|
||||
handling tRNS chunk case with sBIT), so be conservative here about ignoring user input.*/
|
||||
if(info.color.colortype != LCT_PALETTE && auto_color.colortype != LCT_PALETTE &&
|
||||
equal && info_png->sbit_r == auto_color.bitdepth) {
|
||||
allow_convert = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(state->encoder.force_palette) {
|
||||
if(info.color.colortype != LCT_GREY && info.color.colortype != LCT_GREY_ALPHA &&
|
||||
(auto_color.colortype == LCT_GREY || auto_color.colortype == LCT_GREY_ALPHA)) {
|
||||
/*user speficially forced a PLTE palette, so cannot convert to grayscale types because
|
||||
the PNG specification only allows writing a suggested palette in PLTE for truecolor types*/
|
||||
allow_convert = 0;
|
||||
}
|
||||
}
|
||||
if(allow_convert) {
|
||||
lodepng_color_mode_copy(&info.color, &auto_color);
|
||||
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||
/*also convert the background chunk*/
|
||||
if(info_png->background_defined) {
|
||||
if(lodepng_convert_rgb(&info.background_r, &info.background_g, &info.background_b,
|
||||
info_png->background_r, info_png->background_g, info_png->background_b, &info.color, &info_png->color)) {
|
||||
state->error = 104;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */
|
||||
}
|
||||
}
|
||||
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||
if(info_png->iccp_defined) {
|
||||
|
@ -5984,6 +6147,10 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
|
|||
state->error = addChunk_cHRM(&outv, &info);
|
||||
if(state->error) goto cleanup;
|
||||
}
|
||||
if(info_png->sbit_defined) {
|
||||
state->error = addChunk_sBIT(&outv, &info);
|
||||
if(state->error) goto cleanup;
|
||||
}
|
||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||
/*PLTE*/
|
||||
if(info.color.colortype == LCT_PALETTE) {
|
||||
|
@ -6090,6 +6257,7 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
|
|||
cleanup:
|
||||
lodepng_info_cleanup(&info);
|
||||
lodepng_free(data);
|
||||
lodepng_color_mode_cleanup(&auto_color);
|
||||
|
||||
/*instead of cleaning the vector up, give it to the output*/
|
||||
*out = outv.data;
|
||||
|
@ -6284,6 +6452,8 @@ const char* lodepng_error_text(unsigned code) {
|
|||
/*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";
|
||||
case 114: return "sBIT chunk has wrong size for the color type of the image";
|
||||
case 115: return "sBIT value out of range";
|
||||
}
|
||||
return "unknown error code";
|
||||
}
|
||||
|
@ -6322,7 +6492,7 @@ unsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, si
|
|||
size_t buffersize = 0;
|
||||
unsigned error = zlib_decompress(&buffer, &buffersize, 0, in, insize, &settings);
|
||||
if(buffer) {
|
||||
out.insert(out.end(), &buffer[0], &buffer[buffersize]);
|
||||
out.insert(out.end(), buffer, &buffer[buffersize]);
|
||||
lodepng_free(buffer);
|
||||
}
|
||||
return error;
|
||||
|
@ -6341,7 +6511,7 @@ unsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size
|
|||
size_t buffersize = 0;
|
||||
unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings);
|
||||
if(buffer) {
|
||||
out.insert(out.end(), &buffer[0], &buffer[buffersize]);
|
||||
out.insert(out.end(), buffer, &buffer[buffersize]);
|
||||
lodepng_free(buffer);
|
||||
}
|
||||
return error;
|
||||
|
@ -6386,7 +6556,7 @@ unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const
|
|||
state.info_raw.colortype = colortype;
|
||||
state.info_raw.bitdepth = bitdepth;
|
||||
size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);
|
||||
out.insert(out.end(), &buffer[0], &buffer[buffersize]);
|
||||
out.insert(out.end(), buffer, &buffer[buffersize]);
|
||||
}
|
||||
lodepng_free(buffer);
|
||||
return error;
|
||||
|
@ -6404,7 +6574,7 @@ unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
|
|||
unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize);
|
||||
if(buffer && !error) {
|
||||
size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);
|
||||
out.insert(out.end(), &buffer[0], &buffer[buffersize]);
|
||||
out.insert(out.end(), buffer, &buffer[buffersize]);
|
||||
}
|
||||
lodepng_free(buffer);
|
||||
return error;
|
||||
|
@ -6436,7 +6606,7 @@ unsigned encode(std::vector<unsigned char>& out, const unsigned char* in, unsign
|
|||
size_t buffersize;
|
||||
unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth);
|
||||
if(buffer) {
|
||||
out.insert(out.end(), &buffer[0], &buffer[buffersize]);
|
||||
out.insert(out.end(), buffer, &buffer[buffersize]);
|
||||
lodepng_free(buffer);
|
||||
}
|
||||
return error;
|
||||
|
@ -6456,7 +6626,7 @@ unsigned encode(std::vector<unsigned char>& out,
|
|||
size_t buffersize;
|
||||
unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state);
|
||||
if(buffer) {
|
||||
out.insert(out.end(), &buffer[0], &buffer[buffersize]);
|
||||
out.insert(out.end(), buffer, &buffer[buffersize]);
|
||||
lodepng_free(buffer);
|
||||
}
|
||||
return error;
|
||||
|
|
103
Quake/lodepng.h
103
Quake/lodepng.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
LodePNG version 20220109
|
||||
LodePNG version 20220717
|
||||
|
||||
Copyright (c) 2005-2022 Lode Vandevenne
|
||||
|
||||
|
@ -35,43 +35,50 @@ The following #defines are used to create code sections. They can be disabled
|
|||
to disable code sections, which can give faster compile time and smaller binary.
|
||||
The "NO_COMPILE" defines are designed to be used to pass as defines to the
|
||||
compiler command to disable them without modifying this header, e.g.
|
||||
-DLODEPNG_NO_COMPILE_ZLIB for gcc.
|
||||
In addition to those below, you can also define LODEPNG_NO_COMPILE_CRC to
|
||||
allow implementing a custom lodepng_crc32.
|
||||
-DLODEPNG_NO_COMPILE_ZLIB for gcc or clang.
|
||||
*/
|
||||
/*deflate & zlib. If disabled, you must specify alternative zlib functions in
|
||||
the custom_zlib field of the compress and decompress settings*/
|
||||
#ifndef LODEPNG_NO_COMPILE_ZLIB
|
||||
/*pass -DLODEPNG_NO_COMPILE_ZLIB to the compiler to disable this, or comment out LODEPNG_COMPILE_ZLIB below*/
|
||||
#define LODEPNG_COMPILE_ZLIB
|
||||
#endif
|
||||
|
||||
/*png encoder and png decoder*/
|
||||
#ifndef LODEPNG_NO_COMPILE_PNG
|
||||
/*pass -DLODEPNG_NO_COMPILE_PNG to the compiler to disable this, or comment out LODEPNG_COMPILE_PNG below*/
|
||||
#define LODEPNG_COMPILE_PNG
|
||||
#endif
|
||||
|
||||
/*deflate&zlib decoder and png decoder*/
|
||||
#ifndef LODEPNG_NO_COMPILE_DECODER
|
||||
/*pass -DLODEPNG_NO_COMPILE_DECODER to the compiler to disable this, or comment out LODEPNG_COMPILE_DECODER below*/
|
||||
#define LODEPNG_COMPILE_DECODER
|
||||
#endif
|
||||
|
||||
/*deflate&zlib encoder and png encoder*/
|
||||
#ifndef LODEPNG_NO_COMPILE_ENCODER
|
||||
/*pass -DLODEPNG_NO_COMPILE_ENCODER to the compiler to disable this, or comment out LODEPNG_COMPILE_ENCODER below*/
|
||||
#define LODEPNG_COMPILE_ENCODER
|
||||
#endif
|
||||
|
||||
/*the optional built in harddisk file loading and saving functions*/
|
||||
#ifndef LODEPNG_NO_COMPILE_DISK
|
||||
/*pass -DLODEPNG_NO_COMPILE_DISK to the compiler to disable this, or comment out LODEPNG_COMPILE_DISK below*/
|
||||
#define LODEPNG_COMPILE_DISK
|
||||
#endif
|
||||
|
||||
/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/
|
||||
#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS
|
||||
/*pass -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS to the compiler to disable this,
|
||||
or comment out LODEPNG_COMPILE_ANCILLARY_CHUNKS below*/
|
||||
#define LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||
#endif
|
||||
|
||||
/*ability to convert error numerical codes to English text string*/
|
||||
#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT
|
||||
/*pass -DLODEPNG_NO_COMPILE_ERROR_TEXT to the compiler to disable this,
|
||||
or comment out LODEPNG_COMPILE_ERROR_TEXT below*/
|
||||
#define LODEPNG_COMPILE_ERROR_TEXT
|
||||
#endif
|
||||
|
||||
|
@ -79,12 +86,24 @@ the custom_zlib field of the compress and decompress settings*/
|
|||
you can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your
|
||||
source files with custom allocators.*/
|
||||
#ifndef LODEPNG_NO_COMPILE_ALLOCATORS
|
||||
/*pass -DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler to disable the built-in ones,
|
||||
or comment out LODEPNG_COMPILE_ALLOCATORS below*/
|
||||
#define LODEPNG_COMPILE_ALLOCATORS
|
||||
#endif
|
||||
|
||||
/*Disable built-in CRC function, in that case a custom implementation of
|
||||
lodepng_crc32 must be defined externally so that it can be linked in.*/
|
||||
#ifndef LODEPNG_NO_COMPILE_CRC
|
||||
/*pass -DLODEPNG_NO_COMPILE_CRC to the compiler to disable the built-in one,
|
||||
or comment out LODEPNG_COMPILE_CRC below*/
|
||||
#define LODEPNG_COMPILE_CRC
|
||||
#endif
|
||||
|
||||
/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/
|
||||
#ifdef __cplusplus
|
||||
#ifndef LODEPNG_NO_COMPILE_CPP
|
||||
/*pass -DLODEPNG_NO_COMPILE_CPP to the compiler to disable C++ (not needed if a C-only compiler),
|
||||
or comment out LODEPNG_COMPILE_CPP below*/
|
||||
#define LODEPNG_COMPILE_CPP
|
||||
#endif
|
||||
#endif
|
||||
|
@ -374,8 +393,10 @@ typedef struct LodePNGColorMode {
|
|||
|
||||
The alpha channels must be set as well, set them to 255 for opaque images.
|
||||
|
||||
When decoding, by default you can ignore this palette, since LodePNG already
|
||||
fills the palette colors in the pixels of the raw RGBA output.
|
||||
When decoding, with the default settings you can ignore this palette, since
|
||||
LodePNG already fills the palette colors in the pixels of the raw RGBA output,
|
||||
but when decoding to the original PNG color mode it is needed to reconstruct
|
||||
the colors.
|
||||
|
||||
The palette is only supported for color type 3.
|
||||
*/
|
||||
|
@ -465,10 +486,12 @@ typedef struct LodePNGInfo {
|
|||
with values truncated to the bit depth in the unsigned integer.
|
||||
|
||||
For grayscale and palette PNGs, the value is stored in background_r. The values
|
||||
in background_g and background_b are then unused.
|
||||
in background_g and background_b are then unused. The decoder will set them
|
||||
equal to background_r, the encoder ignores them in this case.
|
||||
|
||||
So when decoding, you may get these in a different color mode than the one you requested
|
||||
for the raw pixels.
|
||||
When decoding, you may get these in a different color mode than the one you requested
|
||||
for the raw pixels: the colortype and bitdepth defined by info_png.color, that is the
|
||||
ones defined in the header of the PNG image, are used.
|
||||
|
||||
When encoding with auto_convert, you must use the color model defined in info_png.color for
|
||||
these values. The encoder normally ignores info_png.color when auto_convert is on, but will
|
||||
|
@ -535,7 +558,7 @@ typedef struct LodePNGInfo {
|
|||
unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/
|
||||
|
||||
/*
|
||||
Color profile related chunks: gAMA, cHRM, sRGB, iCPP
|
||||
Color profile related chunks: gAMA, cHRM, sRGB, iCPP, sBIT
|
||||
|
||||
LodePNG does not apply any color conversions on pixels in the encoder or decoder and does not interpret these color
|
||||
profile values. It merely passes on the information. If you wish to use color profiles and convert colors, please
|
||||
|
@ -598,6 +621,45 @@ typedef struct LodePNGInfo {
|
|||
unsigned char* iccp_profile;
|
||||
unsigned iccp_profile_size; /* The size of iccp_profile in bytes */
|
||||
|
||||
/*
|
||||
sBIT chunk: significant bits. Optional metadata, only set this if needed.
|
||||
|
||||
If defined, these values give the bit depth of the original data. Since PNG only stores 1, 2, 4, 8 or 16-bit
|
||||
per channel data, the significant bits value can be used to indicate the original encoded data has another
|
||||
sample depth, such as 10 or 12.
|
||||
|
||||
Encoders using this value, when storing the pixel data, should use the most significant bits
|
||||
of the data to store the original bits, and use a good sample depth scaling method such as
|
||||
"left bit replication" to fill in the least significant bits, rather than fill zeroes.
|
||||
|
||||
Decoders using this value, if able to work with data that's e.g. 10-bit or 12-bit, should right
|
||||
shift the data to go back to the original bit depth, but decoders are also allowed to ignore
|
||||
sbit and work e.g. with the 8-bit or 16-bit data from the PNG directly, since thanks
|
||||
to the encoder contract, the values encoded in PNG are in valid range for the PNG bit depth.
|
||||
|
||||
For grayscale images, sbit_g and sbit_b are not used, and for images that don't use color
|
||||
type RGBA or grayscale+alpha, sbit_a is not used (it's not used even for palette images with
|
||||
translucent palette values, or images with color key). The values that are used must be
|
||||
greater than zero and smaller than or equal to the PNG bit depth.
|
||||
|
||||
The color type from the header in the PNG image defines these used and unused fields: if
|
||||
decoding with a color mode conversion, such as always decoding to RGBA, this metadata still
|
||||
only uses the color type of the original PNG, and may e.g. lack the alpha channel info
|
||||
if the PNG was RGB. When encoding with auto_convert (as well as without), also always the
|
||||
color model defined in info_png.color determines this.
|
||||
|
||||
NOTE: enabling sbit can hurt compression, because the encoder can then not always use
|
||||
auto_convert to choose a more optimal color mode for the data, because the PNG format has
|
||||
strict requirements for the allowed sbit values in combination with color modes.
|
||||
For example, setting these fields to 10-bit will force the encoder to keep using a 16-bit per channel
|
||||
color mode, even if the pixel data would in fact fit in a more efficient 8-bit mode.
|
||||
*/
|
||||
unsigned sbit_defined; /*is significant bits given? if not, the values below are unused*/
|
||||
unsigned sbit_r; /*red or gray component of significant bits*/
|
||||
unsigned sbit_g; /*green component of significant bits*/
|
||||
unsigned sbit_b; /*blue component of significant bits*/
|
||||
unsigned sbit_a; /*alpha component of significant bits*/
|
||||
|
||||
/* End of color profile related chunks */
|
||||
|
||||
|
||||
|
@ -770,7 +832,11 @@ typedef struct LodePNGEncoderSettings {
|
|||
const unsigned char* predefined_filters;
|
||||
|
||||
/*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette).
|
||||
If colortype is 3, PLTE is _always_ created.*/
|
||||
If colortype is 3, PLTE is always created. If color type is explicitely set
|
||||
to a grayscale type (1 or 4), this is not done and is ignored. If enabling this,
|
||||
a palette must be present in the info_png.
|
||||
NOTE: enabling this may worsen compression if auto_convert is used to choose
|
||||
optimal color mode, because it cannot use grayscale color modes in this case*/
|
||||
unsigned force_palette;
|
||||
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||
/*add LodePNG identifier and version as a text chunk, for debugging*/
|
||||
|
@ -824,8 +890,8 @@ unsigned lodepng_inspect(unsigned* w, unsigned* h,
|
|||
#endif /*LODEPNG_COMPILE_DECODER*/
|
||||
|
||||
/*
|
||||
Reads one metadata chunk (other than IHDR) of the PNG file and outputs what it
|
||||
read in the state. Returns error code on failure.
|
||||
Reads one metadata chunk (other than IHDR, which is handled by lodepng_inspect)
|
||||
of the PNG file and outputs what it read in the state. Returns error code on failure.
|
||||
Use lodepng_inspect first with a new state, then e.g. lodepng_chunk_find_const
|
||||
to find the desired chunk type, and if non null use lodepng_inspect_chunk (with
|
||||
chunk_pointer - start_of_file as pos).
|
||||
|
@ -1103,7 +1169,7 @@ TODO:
|
|||
[.] check compatibility with various compilers - done but needs to be redone for every newer version
|
||||
[X] converting color to 16-bit per channel types
|
||||
[X] support color profile chunk types (but never let them touch RGB values by default)
|
||||
[ ] support all public PNG chunk types (almost done except sBIT, sPLT and hIST)
|
||||
[ ] support all public PNG chunk types (almost done except sPLT and hIST)
|
||||
[ ] make sure encoder generates no chunks with size > (2^31)-1
|
||||
[ ] partial decoding (stream processing)
|
||||
[X] let the "isFullyOpaque" function check color keys and transparent palettes too
|
||||
|
@ -1230,18 +1296,16 @@ The following features are supported by the decoder:
|
|||
gAMA: RGB gamma correction
|
||||
iCCP: ICC color profile
|
||||
sRGB: rendering intent
|
||||
sBIT: significant bits
|
||||
|
||||
1.2. features not supported
|
||||
---------------------------
|
||||
|
||||
The following features are _not_ supported:
|
||||
The following features are not (yet) supported:
|
||||
|
||||
*) some features needed to make a conformant PNG-Editor might be still missing.
|
||||
*) partial loading/stream processing. All data must be available and is processed in one call.
|
||||
*) The following public chunks are not (yet) supported but treated as unknown chunks by LodePNG:
|
||||
sBIT
|
||||
hIST
|
||||
sPLT
|
||||
*) The hIST and sPLT public chunks are not (yet) supported but treated as unknown chunks
|
||||
|
||||
|
||||
2. C and C++ version
|
||||
|
@ -1845,6 +1909,7 @@ symbol.
|
|||
Not all changes are listed here, the commit history in github lists more:
|
||||
https://github.com/lvandeve/lodepng
|
||||
|
||||
*) 13 jun 2022: added support for the sBIT chunk.
|
||||
*) 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
|
||||
|
|
Loading…
Reference in a new issue