summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLode <lvandeve@gmail.com>2015-10-24 23:49:28 +0200
committerLode <lvandeve@gmail.com>2015-10-24 23:49:28 +0200
commit942c151c7b92dc727fc2d0a00211e9fa83ef6e83 (patch)
treee1ac6558c617f1c9a18ec4c6f38f180d0ad3f2f0
parent3b04aa3394b756157b8c67fa71955fe277e8defe (diff)
output palette fix
-rw-r--r--lodepng.cpp40
-rw-r--r--lodepng.h5
-rw-r--r--lodepng_unittest.cpp73
3 files changed, 103 insertions, 15 deletions
diff --git a/lodepng.cpp b/lodepng.cpp
index 643bfd5..a5a5b78 100644
--- a/lodepng.cpp
+++ b/lodepng.cpp
@@ -1,5 +1,5 @@
/*
-LodePNG version 20150912
+LodePNG version 20151024
Copyright (c) 2005-2015 Lode Vandevenne
@@ -42,7 +42,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 = "20150912";
+const char* LODEPNG_VERSION_STRING = "20151024";
/*
This source file is built up in the following large parts. The code sections
@@ -779,7 +779,7 @@ unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequen
{
if(frequencies[i] > 0)
{
- leaves[numpresent].weight = frequencies[i];
+ leaves[numpresent].weight = (int)frequencies[i];
leaves[numpresent].index = i;
++numpresent;
}
@@ -832,7 +832,7 @@ unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequen
}
/*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/
- for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, maxbitlen - 1, i);
+ for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i);
for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail)
{
@@ -2598,10 +2598,15 @@ static int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColo
if(a->key_g != b->key_g) return 0;
if(a->key_b != b->key_b) return 0;
}
- if(a->palettesize != b->palettesize) return 0;
- for(i = 0; i != a->palettesize * 4; ++i)
- {
- if(a->palette[i] != b->palette[i]) return 0;
+ /*if one of the palette sizes is 0, then we consider it to be the same as the
+ other: it means that e.g. the palette was not given by the user and should be
+ considered the same as the palette inside the PNG.*/
+ if(1/*a->palettesize != 0 && b->palettesize != 0*/) {
+ if(a->palettesize != b->palettesize) return 0;
+ for(i = 0; i != a->palettesize * 4; ++i)
+ {
+ if(a->palette[i] != b->palette[i]) return 0;
+ }
}
return 1;
}
@@ -3419,7 +3424,7 @@ static void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned s
}
unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
- LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
+ const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
unsigned w, unsigned h)
{
size_t i;
@@ -3435,12 +3440,21 @@ unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
if(mode_out->colortype == LCT_PALETTE)
{
+ size_t palettesize = mode_out->palettesize;
+ const unsigned char* palette = mode_out->palette;
size_t palsize = 1u << mode_out->bitdepth;
- if(mode_out->palettesize < palsize) palsize = mode_out->palettesize;
+ /*if the user specified output palette but did not give the values, assume
+ they want the values of the input color type (assuming that one is palette).
+ Note that we never create a new palette ourselves.*/
+ if(palettesize == 0) {
+ palettesize = mode_in->palettesize;
+ palette = mode_in->palette;
+ }
+ if(palettesize < palsize) palsize = palettesize;
color_tree_init(&tree);
for(i = 0; i != palsize; ++i)
{
- unsigned char* p = &mode_out->palette[i * 4];
+ const unsigned char* p = &palette[i * 4];
color_tree_add(&tree, p[0], p[1], p[2], p[3], i);
}
}
@@ -3468,7 +3482,7 @@ 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);
- rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a);
+ CERROR_TRY_RETURN(rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a));
}
}
@@ -3477,7 +3491,7 @@ unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
color_tree_cleanup(&tree);
}
- return 0; /*no error (this function currently never has one, but maybe OOM detection added later.)*/
+ return 0; /*no error*/
}
#ifdef LODEPNG_COMPILE_ENCODER
diff --git a/lodepng.h b/lodepng.h
index 86e56a3..86c24f9 100644
--- a/lodepng.h
+++ b/lodepng.h
@@ -1,5 +1,5 @@
/*
-LodePNG version 20150912
+LodePNG version 20151024
Copyright (c) 2005-2015 Lode Vandevenne
@@ -508,7 +508,7 @@ For 16-bit per channel colors, uses big endian format like PNG does.
Return value is LodePNG error code
*/
unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
- LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
+ const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
unsigned w, unsigned h);
#ifdef LODEPNG_COMPILE_DECODER
@@ -1564,6 +1564,7 @@ yyyymmdd.
Some changes aren't backwards compatible. Those are indicated with a (!)
symbol.
+*) 24 okt 2015: Bugfix with decoding to palette output.
*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding.
*) 23 aug 2014: Reduced needless memory usage of decoder.
*) 28 jun 2014: Removed fix_png setting, always support palette OOB for
diff --git a/lodepng_unittest.cpp b/lodepng_unittest.cpp
index 92fc370..6d9cbab 100644
--- a/lodepng_unittest.cpp
+++ b/lodepng_unittest.cpp
@@ -1799,6 +1799,77 @@ void testAutoColorModels()
testAutoColorModel(alpha16, 16, LCT_RGBA, 16, false);
}
+void testPaletteToPaletteDecode() {
+ std::cout << "testPaletteToPaletteDecode" << std::endl;
+ // It's a bit big for a 2x2 image... but this tests needs one with 256 palette entries in it.
+ std::string base64 = "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAMAAABFaP0WAAAAA3NCSVQICAjb4U/gAAADAFBMVEUA"
+ "AAAAADMAAGYAAJkAAMwAAP8AMwAAMzMAM2YAM5kAM8wAM/8AZgAAZjMAZmYAZpkAZswAZv8AmQAA"
+ "mTMAmWYAmZkAmcwAmf8AzAAAzDMAzGYAzJkAzMwAzP8A/wAA/zMA/2YA/5kA/8wA//8zAAAzADMz"
+ "AGYzAJkzAMwzAP8zMwAzMzMzM2YzM5kzM8wzM/8zZgAzZjMzZmYzZpkzZswzZv8zmQAzmTMzmWYz"
+ "mZkzmcwzmf8zzAAzzDMzzGYzzJkzzMwzzP8z/wAz/zMz/2Yz/5kz/8wz//9mAABmADNmAGZmAJlm"
+ "AMxmAP9mMwBmMzNmM2ZmM5lmM8xmM/9mZgBmZjNmZmZmZplmZsxmZv9mmQBmmTNmmWZmmZlmmcxm"
+ "mf9mzABmzDNmzGZmzJlmzMxmzP9m/wBm/zNm/2Zm/5lm/8xm//+ZAACZADOZAGaZAJmZAMyZAP+Z"
+ "MwCZMzOZM2aZM5mZM8yZM/+ZZgCZZjOZZmaZZpmZZsyZZv+ZmQCZmTOZmWaZmZmZmcyZmf+ZzACZ"
+ "zDOZzGaZzJmZzMyZzP+Z/wCZ/zOZ/2aZ/5mZ/8yZ///MAADMADPMAGbMAJnMAMzMAP/MMwDMMzPM"
+ "M2bMM5nMM8zMM//MZgDMZjPMZmbMZpnMZszMZv/MmQDMmTPMmWbMmZnMmczMmf/MzADMzDPMzGbM"
+ "zJnMzMzMzP/M/wDM/zPM/2bM/5nM/8zM////AAD/ADP/AGb/AJn/AMz/AP//MwD/MzP/M2b/M5n/"
+ "M8z/M///ZgD/ZjP/Zmb/Zpn/Zsz/Zv//mQD/mTP/mWb/mZn/mcz/mf//zAD/zDP/zGb/zJn/zMz/"
+ "zP///wD//zP//2b//5n//8z///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlenwdAAABAHRSTlP/////////////////////////"
+ "////////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////////"
+ "////////////////////////////////////////////////////////////////////////////"
+ "//////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAG8mZagAAAAlwSFlzAAAOTQAADpwB3vacVwAAAA5JREFUCJlj2CLHwHodAATjAa+k"
+ "lTE5AAAAAElFTkSuQmCC";
+ std::vector<unsigned char> png;
+ fromBase64(png, base64);
+
+ std::vector<unsigned char> image;
+ unsigned width, height;
+ unsigned error = lodepng::decode(image, width, height, png, LCT_PALETTE, 8);
+ ASSERT_EQUALS(0, error);
+ ASSERT_EQUALS(2, width);
+ ASSERT_EQUALS(2, height);
+ ASSERT_EQUALS(180, image[0]);
+ ASSERT_EQUALS(30, image[1]);
+ ASSERT_EQUALS(5, image[2]);
+ ASSERT_EQUALS(215, image[3]);
+}
+
+//2-bit palette
+void testPaletteToPaletteDecode2() {
+ std::cout << "testPaletteToPaletteDecode2" << std::endl;
+ std::string base64 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgAgMAAAAOFJJnAAAADFBMVEX/AAAA/wAAAP/////7AGD2AAAAE0lEQVR4AWMQhAKG3VCALDIqAgDl2WYBCQHY9gAAAABJRU5ErkJggg==";
+ std::vector<unsigned char> png;
+ fromBase64(png, base64);
+
+ std::vector<unsigned char> image;
+ unsigned width, height;
+ unsigned error = lodepng::decode(image, width, height, png, LCT_PALETTE, 8);
+ ASSERT_EQUALS(0, error);
+ ASSERT_EQUALS(32, width);
+ ASSERT_EQUALS(32, height);
+ ASSERT_EQUALS(0, image[0]);
+ ASSERT_EQUALS(1, image[1]);
+
+ //Now add a user-specified output palette, that differs from the input palette. That should give error 82.
+ LodePNGState state;
+ lodepng_state_init(&state);
+ state.info_raw.colortype = LCT_PALETTE;
+ state.info_raw.bitdepth = 8;
+ lodepng_palette_add(&state.info_raw, 0, 0, 0, 255);
+ lodepng_palette_add(&state.info_raw, 1, 1, 1, 255);
+ lodepng_palette_add(&state.info_raw, 2, 2, 2, 255);
+ 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);
+ free(image2);
+}
+
void doMain()
{
//PNG
@@ -1809,6 +1880,8 @@ void doMain()
testPredefinedFilters();
testFuzzing();
testWrongWindowSizeGivesError();
+ testPaletteToPaletteDecode();
+ testPaletteToPaletteDecode2();
//Colors
testColorKeyConvert();