summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE21
-rw-r--r--lodepng.cpp87
-rw-r--r--lodepng.h14
-rw-r--r--lodepng_benchmark.cpp8
-rw-r--r--lodepng_unittest.cpp66
-rw-r--r--lodepng_util.cpp10
-rw-r--r--lodepng_util.h2
-rw-r--r--pngdetail.cpp81
8 files changed, 203 insertions, 86 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..a5fb060
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2005-2018 Lode Vandevenne
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source
+ distribution.
+
diff --git a/lodepng.cpp b/lodepng.cpp
index 70381fb..c62a22f 100644
--- a/lodepng.cpp
+++ b/lodepng.cpp
@@ -1,7 +1,7 @@
/*
-LodePNG version 20161127
+LodePNG version 20180114
-Copyright (c) 2005-2016 Lode Vandevenne
+Copyright (c) 2005-2018 Lode Vandevenne
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -39,7 +39,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*/
#endif /*_MSC_VER */
-const char* LODEPNG_VERSION_STRING = "20161127";
+const char* LODEPNG_VERSION_STRING = "20180114";
/*
This source file is built up in the following large parts. The code sections
@@ -1171,7 +1171,7 @@ static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size
code_d = huffmanDecodeSymbol(in, bp, &tree_d, inbitlength);
if(code_d > 29)
{
- if(code_ll == (unsigned)(-1)) /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/
+ if(code_d == (unsigned)(-1)) /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/
{
/*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
(10=no endcode, 11=wrong jump outside of tree)*/
@@ -3463,6 +3463,7 @@ unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
size_t i;
ColorTree tree;
size_t numpixels = w * h;
+ unsigned error = 0;
if(lodepng_color_mode_equal(mode_out, mode_in))
{
@@ -3516,7 +3517,8 @@ unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
for(i = 0; i != numpixels; ++i)
{
getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in);
- CERROR_TRY_RETURN(rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a));
+ error = rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a);
+ if (error) break;
}
}
@@ -3525,7 +3527,7 @@ unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
color_tree_cleanup(&tree);
}
- return 0; /*no error*/
+ return error;
}
#ifdef LODEPNG_COMPILE_ENCODER
@@ -4563,12 +4565,20 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
const unsigned char* data; /*the data in the chunk*/
/*error: size of the in buffer too small to contain next chunk*/
- if((size_t)((chunk - in) + 12) > insize || chunk < in) CERROR_BREAK(state->error, 30);
+ if((size_t)((chunk - in) + 12) > insize || chunk < in)
+ {
+ 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*/
chunkLength = lodepng_chunk_length(chunk);
/*error: chunk length larger than the max PNG chunk size*/
- if(chunkLength > 2147483647) CERROR_BREAK(state->error, 63);
+ if(chunkLength > 2147483647)
+ {
+ if(state->decoder.ignore_end) break; /*other errors may still happen though*/
+ CERROR_BREAK(state->error, 63);
+ }
if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in)
{
@@ -4655,7 +4665,10 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
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)*/
- if(!lodepng_chunk_ancillary(chunk)) CERROR_BREAK(state->error, 69);
+ if(!state->decoder.ignore_critical && !lodepng_chunk_ancillary(chunk))
+ {
+ CERROR_BREAK(state->error, 69);
+ }
unknown = 1;
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
@@ -4820,6 +4833,8 @@ void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings)
settings->remember_unknown_chunks = 0;
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
settings->ignore_crc = 0;
+ settings->ignore_critical = 0;
+ settings->ignore_end = 0;
lodepng_decompress_settings_init(&settings->zlibsettings);
}
@@ -5651,22 +5666,12 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
*outsize = 0;
state->error = 0;
- lodepng_info_init(&info);
- lodepng_info_copy(&info, &state->info_png);
-
- if((info.color.colortype == LCT_PALETTE || state->encoder.force_palette)
- && (info.color.palettesize == 0 || info.color.palettesize > 256))
- {
- state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/
- return state->error;
- }
-
- if(state->encoder.auto_convert)
+ /*check input values validity*/
+ if((state->info_png.color.colortype == LCT_PALETTE || state->encoder.force_palette)
+ && (state->info_png.color.palettesize == 0 || state->info_png.color.palettesize > 256))
{
- state->error = lodepng_auto_choose_color(&info.color, image, w, h, &state->info_raw);
+ CERROR_RETURN_ERROR(state->error, 68); /*invalid palette size, it is only allowed to be 1-256*/
}
- if(state->error) return state->error;
-
if(state->encoder.zlibsettings.btype > 2)
{
CERROR_RETURN_ERROR(state->error, 61); /*error: unexisting btype*/
@@ -5675,28 +5680,38 @@ unsigned lodepng_encode(unsigned char** out, size_t* outsize,
{
CERROR_RETURN_ERROR(state->error, 71); /*error: unexisting interlace mode*/
}
-
- state->error = checkColorValidity(info.color.colortype, info.color.bitdepth);
+ state->error = checkColorValidity(state->info_png.color.colortype, state->info_png.color.bitdepth);
if(state->error) return state->error; /*error: unexisting color type given*/
state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth);
if(state->error) return state->error; /*error: unexisting color type given*/
- if(!lodepng_color_mode_equal(&state->info_raw, &info.color))
+ /* color convert and compute scanline filter types */
+ lodepng_info_init(&info);
+ lodepng_info_copy(&info, &state->info_png);
+ if(state->encoder.auto_convert)
{
- unsigned char* converted;
- size_t size = (w * h * (size_t)lodepng_get_bpp(&info.color) + 7) / 8;
-
- converted = (unsigned char*)lodepng_malloc(size);
- if(!converted && size) state->error = 83; /*alloc fail*/
- if(!state->error)
+ state->error = lodepng_auto_choose_color(&info.color, image, w, h, &state->info_raw);
+ }
+ if (!state->error)
+ {
+ if(!lodepng_color_mode_equal(&state->info_raw, &info.color))
{
- state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h);
+ unsigned char* converted;
+ size_t size = (w * h * (size_t)lodepng_get_bpp(&info.color) + 7) / 8;
+
+ converted = (unsigned char*)lodepng_malloc(size);
+ if(!converted && size) state->error = 83; /*alloc fail*/
+ if(!state->error)
+ {
+ 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);
+ lodepng_free(converted);
}
- if(!state->error) preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder);
- lodepng_free(converted);
+ else preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder);
}
- else preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder);
+ /* output all PNG chunks */
ucvector_init(&outv);
while(!state->error) /*while only executed once, to break on error*/
{
diff --git a/lodepng.h b/lodepng.h
index 8c634d2..cf6667c 100644
--- a/lodepng.h
+++ b/lodepng.h
@@ -1,7 +1,7 @@
/*
-LodePNG version 20161127
+LodePNG version 20180114
-Copyright (c) 2005-2016 Lode Vandevenne
+Copyright (c) 2005-2018 Lode Vandevenne
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -255,6 +255,7 @@ const char* lodepng_error_text(unsigned code);
typedef struct LodePNGDecompressSettings LodePNGDecompressSettings;
struct LodePNGDecompressSettings
{
+ /* Check LodePNGDecoderSettings for more ignorable errors */
unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/
/*use custom zlib decoder instead of built in one (default: null)*/
@@ -520,7 +521,10 @@ typedef struct LodePNGDecoderSettings
{
LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/
+ /* Check LodePNGDecompressSettings for more ignorable errors */
unsigned ignore_crc; /*ignore CRC checksums*/
+ unsigned ignore_critical; /*ignore unknown critical chunks*/
+ unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*/
unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/
@@ -1567,6 +1571,8 @@ For decoding:
state.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums
state.decoder.zlibsettings.custom_...: use custom inflate function
state.decoder.ignore_crc: ignore CRC checksums
+state.decoder.ignore_critical: ignore unknown critical chunks
+state.decoder.ignore_end: ignore missing IEND chunk. May fail if this corruption causes other errors
state.decoder.color_convert: convert internal PNG color to chosen one
state.decoder.read_text_chunks: whether to read in text metadata chunks
state.decoder.remember_unknown_chunks: whether to read in unknown chunks
@@ -1608,6 +1614,8 @@ yyyymmdd.
Some changes aren't backwards compatible. Those are indicated with a (!)
symbol.
+*) 14 jan 2018: allow optionally ignoring a few more recoverable errors
+*) 17 sep 2017: fix memory leak for some encoder input error cases
*) 27 nov 2016: grey+alpha auto color model detection bugfix
*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort).
*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within
@@ -1757,5 +1765,5 @@ Domain: gmail dot com.
Account: lode dot vandevenne.
-Copyright (c) 2005-2016 Lode Vandevenne
+Copyright (c) 2005-2017 Lode Vandevenne
*/
diff --git a/lodepng_benchmark.cpp b/lodepng_benchmark.cpp
index 791ced0..66de123 100644
--- a/lodepng_benchmark.cpp
+++ b/lodepng_benchmark.cpp
@@ -499,10 +499,10 @@ int main(int argc, char *argv[])
}
}
- std::cout << "Total decoding time: " << total_dec_time/NUM_DECODE << "s" << std::endl;
- std::cout << "Total encoding time: " << total_enc_time << "s" << std::endl;
- std::cout << "Total input size : " << total_in_size << std::endl;
- std::cout << "Total encoded size: " << total_enc_size << std::endl;
+ std::cout << "Total decoding time: " << total_dec_time/NUM_DECODE << "s (" << ((total_in_size/1024.0/1024.0)/(total_dec_time/NUM_DECODE)) << " MB/s)" << std::endl;
+ std::cout << "Total encoding time: " << total_enc_time << "s (" << ((total_in_size/1024.0/1024.0)/(total_enc_time)) << " MB/s)" << std::endl;
+ std::cout << "Total uncompressed size : " << total_in_size << std::endl;
+ std::cout << "Total encoded size: " << total_enc_size << " (" << (100.0 * total_enc_size / total_in_size) << "%)" << std::endl;
if(verbose) std::cout << "benchmark done" << std::endl;
}
diff --git a/lodepng_unittest.cpp b/lodepng_unittest.cpp
index 5297a35..975f2b4 100644
--- a/lodepng_unittest.cpp
+++ b/lodepng_unittest.cpp
@@ -28,6 +28,8 @@ freely, subject to the following restrictions:
/*
Testing instructions:
+*) Ensure no tests commented out below or early return in doMain
+
*) Compile with g++ with all warnings and run the unit test
g++ lodepng.cpp lodepng_util.cpp lodepng_unittest.cpp -Wall -Wextra -Wshadow -pedantic -ansi -O3 && ./a.out
@@ -760,7 +762,8 @@ void testColorConvert()
colorConvertTest("1011010110110101", LCT_GREY, 16, "10110101", LCT_GREY, 8);
//others
- colorConvertTest("11111111 11111111 11111111 00000000 00000000 00000000", LCT_RGB, 1, "10", LCT_GREY, 1);
+ colorConvertTest("11111111 11111111 11111111 00000000 00000000 00000000", LCT_RGB, 8, "10", LCT_GREY, 1);
+ colorConvertTest("11111111 11111111 11111111 11111111 11111111 11111111 00000000 00000000 00000000 00000000 00000000 00000000", LCT_RGB, 16, "10", LCT_GREY, 1);
}
//This tests color conversions from any color model to any color model, with any bit depth
@@ -1712,26 +1715,59 @@ void testPredefinedFilters() {
for(size_t i = 0; i < h; i++) ASSERT_EQUALS(3, outfilters[i]);
}
-void testWrongWindowSizeGivesError() {
+void testEncoderErrors() {
+ std::cout << "testEncoderErrors" << std::endl;
+
std::vector<unsigned char> png;
unsigned w = 32, h = 32;
Image image;
generateTestImage(image, w, h);
- unsigned error = 0;
+
+ lodepng::State def;
lodepng::State state;
+
+ ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
+
+ // test window sizes
state.encoder.zlibsettings.windowsize = 0;
- error = lodepng::encode(png, &image.data[0], w, h, state);
- ASSERT_EQUALS(60, error);
+ ASSERT_EQUALS(60, lodepng::encode(png, &image.data[0], w, h, state));
state.encoder.zlibsettings.windowsize = 65536;
- error = lodepng::encode(png, &image.data[0], w, h, state);
- ASSERT_EQUALS(60, error);
+ ASSERT_EQUALS(60, lodepng::encode(png, &image.data[0], w, h, state));
state.encoder.zlibsettings.windowsize = 1000; // not power of two
- error = lodepng::encode(png, &image.data[0], w, h, state);
- ASSERT_EQUALS(90, error);
+ ASSERT_EQUALS(90, lodepng::encode(png, &image.data[0], w, h, state));
state.encoder.zlibsettings.windowsize = 256;
- error = lodepng::encode(png, &image.data[0], w, h, state);
- ASSERT_EQUALS(0, error);
+ ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
+
+ state = def;
+ state.info_png.color.bitdepth = 3;
+ ASSERT_EQUALS(37, lodepng::encode(png, &image.data[0], w, h, state));
+
+ state = def;
+ state.info_png.color.colortype = (LodePNGColorType)5;
+ ASSERT_EQUALS(31, lodepng::encode(png, &image.data[0], w, h, state));
+
+ state = def;
+ state.info_png.color.colortype = LCT_PALETTE;
+ ASSERT_EQUALS(68, lodepng::encode(png, &image.data[0], w, h, state));
+
+ state = def;
+ state.info_png.interlace_method = 0;
+ ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
+ state.info_png.interlace_method = 1;
+ ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
+ state.info_png.interlace_method = 2;
+ ASSERT_EQUALS(71, lodepng::encode(png, &image.data[0], w, h, state));
+
+ state = def;
+ state.encoder.zlibsettings.btype = 0;
+ ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
+ state.encoder.zlibsettings.btype = 1;
+ ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
+ state.encoder.zlibsettings.btype = 2;
+ ASSERT_EQUALS(0, lodepng::encode(png, &image.data[0], w, h, state));
+ state.encoder.zlibsettings.btype = 3;
+ ASSERT_EQUALS(61, lodepng::encode(png, &image.data[0], w, h, state));
}
void addColor(std::vector<unsigned char>& colors, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
@@ -1996,26 +2032,26 @@ void testPaletteToPaletteDecode2() {
lodepng_palette_add(&state.info_raw, 3, 3, 3, 255);
unsigned char* image2 = 0;
unsigned error2 = lodepng_decode(&image2, &width, &height, &state, &png[0], png.size());
- ASSERT_EQUALS(82, error2);
lodepng_state_cleanup(&state);
+ ASSERT_EQUALS(82, error2);
free(image2);
}
void doMain()
{
//PNG
- testPNGCodec();
+ testPNGCodec(); // this one is slow for valgrind
testPngSuiteTiny();
testPaletteFilterTypesZero();
testComplexPNG();
testPredefinedFilters();
testFuzzing();
- testWrongWindowSizeGivesError();
+ testEncoderErrors();
testPaletteToPaletteDecode();
testPaletteToPaletteDecode2();
//Colors
- testFewColors();
+ testFewColors(); // this one is slow for valgrind
testColorKeyConvert();
testColorConvert();
testColorConvert2();
diff --git a/lodepng_util.cpp b/lodepng_util.cpp
index 76efdea..6fa1618 100644
--- a/lodepng_util.cpp
+++ b/lodepng_util.cpp
@@ -1,7 +1,7 @@
/*
LodePNG Utils
-Copyright (c) 2005-2014 Lode Vandevenne
+Copyright (c) 2005-2018 Lode Vandevenne
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -52,9 +52,9 @@ unsigned getChunkInfo(std::vector<std::string>& names, std::vector<size_t>& size
if(std::string(type).size() != 4) return 1;
unsigned length = lodepng_chunk_length(chunk);
- if(chunk + length + 12 > end) return 1;
names.push_back(type);
sizes.push_back(length);
+ if(chunk + length + 12 > end) return 1;
next = lodepng_chunk_next_const(chunk);
if (next <= chunk) return 1; // integer overflow
@@ -185,7 +185,7 @@ unsigned getFilterTypesInterlaced(std::vector<std::vector<unsigned char> >& filt
{
char type[5];
lodepng_chunk_type(type, chunk);
- if(std::string(type).size() != 4) return 1; //Probably not a PNG file
+ if(std::string(type).size() != 4) break; //Probably not a PNG file
if(std::string(type) == "IDAT")
{
@@ -203,11 +203,11 @@ unsigned getFilterTypesInterlaced(std::vector<std::vector<unsigned char> >& filt
}
next = lodepng_chunk_next_const(chunk);
- if (next <= chunk) return 1; // integer overflow
+ if (next <= chunk) break; // integer overflow
chunk = next;
}
- //Decompress all IDAT data
+ //Decompress all IDAT data (if the while loop ended early, this might fail)
std::vector<unsigned char> data;
error = lodepng::decompress(data, &zdata[0], zdata.size());
diff --git a/lodepng_util.h b/lodepng_util.h
index 236ad46..19fcbcb 100644
--- a/lodepng_util.h
+++ b/lodepng_util.h
@@ -1,7 +1,7 @@
/*
LodePNG Utils
-Copyright (c) 2005-2014 Lode Vandevenne
+Copyright (c) 2005-2018 Lode Vandevenne
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
diff --git a/pngdetail.cpp b/pngdetail.cpp
index 41952a4..b11d78c 100644
--- a/pngdetail.cpp
+++ b/pngdetail.cpp
@@ -1,7 +1,7 @@
/*
LodePNG pngdetail
-Copyright (c) 2005-2015 Lode Vandevenne
+Copyright (c) 2005-2018 Lode Vandevenne
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -184,7 +184,13 @@ void displayChunkNames(const std::vector<unsigned char>& buffer, const Options&
std::vector<std::string> names;
std::vector<size_t> sizes;
unsigned error = lodepng::getChunkInfo(names, sizes, buffer);
- if(error) std::cout << "Error while identifying chunks. Listing identified chunks anyway." << std::endl;
+ if(error) {
+ if(!names.empty() && names.back() == "IEND" && sizes.back() == 0) {
+ std::cout << "Corruption or superfluous data detected after the IEND chunk" << std::endl;
+ } else {
+ std::cout << "Error while identifying chunks. Listing identified chunks anyway." << std::endl;
+ }
+ }
if(options.show_chunks2)
{
@@ -711,7 +717,7 @@ void showHelp()
"-b: show Zlib blocks\n"
"-B: show Zlib block symbol counts\n"
"-7: show all lz77 values (huge output)\n"
- "-x: print most numbers in hexadecimal\n"
+ "-x: print most integer numbers in hexadecimal (includes e.g. year, num unique colors, ...)\n"
<< std::endl;
}
@@ -797,6 +803,11 @@ unsigned showFileInfo(const std::string& filename, const Options& options)
std::vector<unsigned char> image;
unsigned w, h;
+ if(options.show_png_info)
+ {
+ std::cout << "pngdetail version: " << LODEPNG_VERSION_STRING << std::endl;
+ }
+
unsigned error = lodepng::load_file(buffer, filename); //load the image file with given filename
if(error)
@@ -810,27 +821,45 @@ unsigned showFileInfo(const std::string& filename, const Options& options)
state.info_raw.bitdepth = 16;
error = lodepng::decode(image, w, h, state, buffer);
- // In case of checksum errors, disable checksums
- while (error == 57 || error == 58) {
+ // In case of checksum errors and some other ignorable errors, report it but ignore it and retry
+ while (error) {
+ std::cerr << "Decoder error " << error << ": " << lodepng_error_text(error) << std::endl;
+ unsigned error2 = error;
if(error == 57)
{
- std::cout << "Error: invalid CRC checksum" << std::endl;
+ std::cerr << "Ignoring the error: enabling ignore_crc" << std::endl;
state.decoder.ignore_crc = 1;
error = lodepng::decode(image, w, h, state, buffer);
}
-
- if(error == 58)
+ else if(error == 58)
{
- std::cout << "Error: invalid Adler32 checksum" << std::endl;
+ std::cerr << "Ignoring the error: enabling ignore_adler32" << std::endl;
state.decoder.zlibsettings.ignore_adler32 = 1;
error = lodepng::decode(image, w, h, state, buffer);
}
- }
-
- if(error)
- {
- std::cout << "Decoder error " << error << ": " << lodepng_error_text(error) << std::endl;
- // Do not return: some sections may still show partial info about a corrupted PNG.
+ else if(error == 69)
+ {
+ std::cerr << "Ignoring the error: enabling ignore_critical" << std::endl;
+ state.decoder.ignore_critical = 1;
+ error = lodepng::decode(image, w, h, state, buffer);
+ }
+ else if(error == 30 || error == 63)
+ {
+ std::cerr << "Ignoring the error: enabling ignore_end" << std::endl;
+ state.decoder.ignore_end = 1;
+ error = lodepng::decode(image, w, h, state, buffer);
+ }
+ else
+ {
+ if(error == 0) std::cerr << "This error is unrecoverable" << std::endl;
+ break; // other error that we cannot ignore
+ }
+ if(error == 0) std::cerr << "Successfully ignored the error" << std::endl;
+ if(error == error2)
+ {
+ std::cerr << "Failed to ignore the error" << std::endl;
+ break; // avoid infinite loop if ignoring did not fix the error code
+ }
}
bool extra_newlines = false;
@@ -850,15 +879,23 @@ unsigned showFileInfo(const std::string& filename, const Options& options)
std::cout << "Height: " << h << std::endl;
if(options.show_extra_png_info) std::cout << "Num pixels: " << w * h << std::endl;
+ std::cout << "Num unique colors: " << countColors(image, w, h) << std::endl;
if(options.show_extra_png_info && w > 0 && h > 0)
{
- std::ios_base::fmtflags flags = std::cout.flags();
- std::cout << "Top left pixel color: #"
- << std::hex << std::setfill('0')
- << std::setw(2) << (int)image[0] << std::setw(2) << (int)image[1] << std::setw(2) << (int)image[2] << std::setw(2) << (int)image[3]
- << std::endl;
- std::cout.flags(flags);
- std::cout << "Num unique colors: " << countColors(image, w, h) << std::endl;
+ double r = 0, g = 0, b = 0, a = 0;
+ for(unsigned y = 0; y < h; y++) {
+ for(unsigned x = 0; x < w; x++) {
+ r += 256 * image[y * 8 * w + x * 8 + 0] + image[y * 8 * w + x * 8 + 1];
+ g += 256 * image[y * 8 * w + x * 8 + 2] + image[y * 8 * w + x * 8 + 3];
+ b += 256 * image[y * 8 * w + x * 8 + 4] + image[y * 8 * w + x * 8 + 5];
+ a += 256 * image[y * 8 * w + x * 8 + 6] + image[y * 8 * w + x * 8 + 7];
+ }
+ }
+ r /= (w * h * 257.0);
+ g /= (w * h * 257.0);
+ b /= (w * h * 257.0);
+ a /= (w * h * 257.0);
+ std::cout << "Average color: " << r << ", " << g << ", " << b << ", " << a << std::endl;
}
displayPNGInfo(state.info_png, options);