summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLode <lvandeve@gmail.com>2016-04-09 16:21:25 +0200
committerLode <lvandeve@gmail.com>2016-04-09 16:21:25 +0200
commit1bdcf470b3416f24aefcb99bb4bba2fb0df9704d (patch)
tree7ed39ab7e7e0c604363c88017049faae99170947
parent3ea25a82805137025516375b8fdc005a8a951b18 (diff)
color key and file handling
-rw-r--r--lodepng.cpp120
-rw-r--r--lodepng.h4
-rw-r--r--lodepng_unittest.cpp42
3 files changed, 121 insertions, 45 deletions
diff --git a/lodepng.cpp b/lodepng.cpp
index 0fca1a9..6132ae5 100644
--- a/lodepng.cpp
+++ b/lodepng.cpp
@@ -1,5 +1,5 @@
/*
-LodePNG version 20160124
+LodePNG version 20160409
Copyright (c) 2005-2016 Lode Vandevenne
@@ -30,19 +30,16 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for
#include "lodepng.h"
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
-#ifdef LODEPNG_COMPILE_CPP
-#include <fstream>
-#endif /*LODEPNG_COMPILE_CPP*/
-
#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/
#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/
#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 = "20160124";
+const char* LODEPNG_VERSION_STRING = "20160409";
/*
This source file is built up in the following large parts. The code sections
@@ -350,31 +347,53 @@ static void lodepng_add32bitInt(ucvector* buffer, unsigned value)
#ifdef LODEPNG_COMPILE_DISK
-unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename)
+/* returns negative value on error. This should be pure C compatible, so no fstat. */
+static long lodepng_filesize(const char* filename)
{
FILE* file;
long size;
+ file = fopen(filename, "rb");
+ if(!file) return -1;
- /*provide some proper output values if error will happen*/
- *out = 0;
- *outsize = 0;
+ if(fseek(file, 0, SEEK_END) != 0)
+ {
+ fclose(file);
+ return -1;
+ }
+
+ size = ftell(file);
+ /* It may give LONG_MAX as directory size, this is invalid for us. */
+ if(size == LONG_MAX) size = -1;
+
+ fclose(file);
+ return size;
+}
+/* load file into buffer that already has the correct allocated size. Returns error code.*/
+static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename)
+{
+ FILE* file;
+ size_t readsize;
file = fopen(filename, "rb");
if(!file) return 78;
- /*get filesize:*/
- fseek(file , 0 , SEEK_END);
- size = ftell(file);
- rewind(file);
+ readsize = fread(out, 1, size, file);
+ fclose(file);
+
+ if (readsize != size) return 78;
+ return 0;
+}
+
+unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename)
+{
+ long size = lodepng_filesize(filename);
+ if (size < 0) return 78;
+ *outsize = (size_t)size;
- /*read contents of the file into the vector*/
- *outsize = 0;
*out = (unsigned char*)lodepng_malloc((size_t)size);
- if(size && (*out)) (*outsize) = fread(*out, 1, (size_t)size, file);
+ if(!(*out) && size > 0) return 83; /*the above malloc failed*/
- fclose(file);
- if(!(*out) && size) return 83; /*the above malloc failed*/
- return 0;
+ return lodepng_buffer_file(*out, (size_t)size, filename);
}
/*write given buffer to the file, overwriting the file, it doesn't append to it.*/
@@ -2671,7 +2690,7 @@ unsigned lodepng_can_have_alpha(const LodePNGColorMode* info)
size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color)
{
/*will not overflow for any color type if roughly w * h < 268435455*/
- int bpp = lodepng_get_bpp(color);
+ size_t bpp = lodepng_get_bpp(color);
size_t n = w * h;
return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8;
}
@@ -2679,7 +2698,7 @@ size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* colo
size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth)
{
/*will not overflow for any color type if roughly w * h < 268435455*/
- int bpp = lodepng_get_bpp_lct(colortype, bitdepth);
+ size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth);
size_t n = w * h;
return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8;
}
@@ -2691,7 +2710,7 @@ size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colorty
static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, const LodePNGColorMode* color)
{
/*will not overflow for any color type if roughly w * h < 268435455*/
- int bpp = lodepng_get_bpp(color);
+ size_t bpp = lodepng_get_bpp(color);
size_t line = ((w / 8) * bpp) + ((w & 7) * bpp + 7) / 8;
return h * line;
}
@@ -3602,15 +3621,28 @@ unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
alpha_done = 1;
}
}
-
if(alpha_done && numcolors_done && colored_done && bits_done) break;
}
+
+ if(profile->key && !profile->alpha)
+ {
+ for(i = 0; i != numpixels; ++i)
+ {
+ getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode);
+ if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b)
+ {
+ /* Color key cannot be used if an opaque pixel also has that RGB color. */
+ profile->alpha = 1;
+ alpha_done = 1;
+ }
+ }
+ }
}
else /* < 16-bit */
{
+ unsigned char r = 0, g = 0, b = 0, a = 0;
for(i = 0; i != numpixels; ++i)
{
- unsigned char r = 0, g = 0, b = 0, a = 0;
getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode);
if(!bits_done && profile->bits < 8)
@@ -3675,6 +3707,20 @@ unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
if(alpha_done && numcolors_done && colored_done && bits_done) break;
}
+ if(profile->key && !profile->alpha)
+ {
+ for(i = 0; i != numpixels; ++i)
+ {
+ getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode);
+ if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b)
+ {
+ /* Color key cannot be used if an opaque pixel also has that RGB color. */
+ profile->alpha = 1;
+ alpha_done = 1;
+ }
+ }
+ }
+
/*make the profile's key always 16-bit for consistency - repeat each byte twice*/
profile->key_r += (profile->key_r << 8);
profile->key_g += (profile->key_g << 8);
@@ -4718,7 +4764,7 @@ unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const u
unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename,
LodePNGColorType colortype, unsigned bitdepth)
{
- unsigned char* buffer;
+ unsigned char* buffer = 0;
size_t buffersize;
unsigned error;
error = lodepng_load_file(&buffer, &buffersize, filename);
@@ -5942,28 +5988,16 @@ namespace lodepng
#ifdef LODEPNG_COMPILE_DISK
unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename)
{
- std::ifstream file(filename.c_str(), std::ios::in|std::ios::binary|std::ios::ate);
- if(!file) return 78;
-
- /*get filesize*/
- std::streamsize size = 0;
- if(file.seekg(0, std::ios::end).good()) size = file.tellg();
- if(file.seekg(0, std::ios::beg).good()) size -= file.tellg();
-
- /*read contents of the file into the vector*/
- buffer.resize(size_t(size));
- if(size > 0) file.read((char*)(&buffer[0]), size);
-
- return 0; /* OK */
+ long size = lodepng_filesize(filename.c_str());
+ if(size < 0) return 78;
+ buffer.resize((size_t)size);
+ return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str());
}
/*write given buffer to the file, overwriting the file, it doesn't append to it.*/
unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename)
{
- std::ofstream file(filename.c_str(), std::ios::out|std::ios::binary);
- if(!file) return 79;
- file.write(buffer.empty() ? 0 : (char*)&buffer[0], std::streamsize(buffer.size()));
- return 0;
+ return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str());
}
#endif /* LODEPNG_COMPILE_DISK */
diff --git a/lodepng.h b/lodepng.h
index 9ecedd1..33f1051 100644
--- a/lodepng.h
+++ b/lodepng.h
@@ -1,5 +1,5 @@
/*
-LodePNG version 20160124
+LodePNG version 20160409
Copyright (c) 2005-2016 Lode Vandevenne
@@ -1607,6 +1607,8 @@ yyyymmdd.
Some changes aren't backwards compatible. Those are indicated with a (!)
symbol.
+*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within
+ the limits of pure C90).
*) 08 dec 2015: Made load_file function return error if file can't be opened.
*) 24 okt 2015: Bugfix with decoding to palette output.
*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding.
diff --git a/lodepng_unittest.cpp b/lodepng_unittest.cpp
index 8259db5..fcfea54 100644
--- a/lodepng_unittest.cpp
+++ b/lodepng_unittest.cpp
@@ -1,7 +1,7 @@
/*
LodePNG Unit Test
-Copyright (c) 2005-2015 Lode Vandevenne
+Copyright (c) 2005-2016 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
@@ -608,6 +608,45 @@ void testColor(int r, int g, int b, int a)
testSinglePixel(r, g, b, a);
}
+// Tests combinations of various colors in different orders
+void testFewColors()
+{
+ std::cout << "codec test colors " << std::endl;
+ Image image;
+ image.width = 20;
+ image.height = 20;
+ image.colorType = LCT_RGBA;
+ image.bitDepth = 8;
+ image.data.resize(image.width * image.height * 4);
+ std::vector<unsigned char> colors;
+ colors.push_back(0); colors.push_back(0); colors.push_back(0); colors.push_back(255);
+ colors.push_back(255); colors.push_back(255); colors.push_back(255); colors.push_back(255);
+ colors.push_back(128); colors.push_back(128); colors.push_back(128); colors.push_back(255);
+ colors.push_back(0); colors.push_back(0); colors.push_back(255); colors.push_back(255);
+ colors.push_back(255); colors.push_back(255); colors.push_back(255); colors.push_back(0);
+ colors.push_back(255); colors.push_back(255); colors.push_back(255); colors.push_back(1);
+ for(size_t i = 0; i < colors.size(); i += 4)
+ for(size_t j = 0; j < colors.size(); j += 4)
+ for(size_t k = 0; k < colors.size(); k += 4)
+ for(size_t l = 0; l < colors.size(); l += 4)
+ {
+ for(size_t c = 0; c < 4; c++)
+ {
+ /*image.data[0 + c] = colors[i + c];
+ image.data[4 + c] = colors[j + c];
+ image.data[8 + c] = colors[k + c];*/
+ for(unsigned y = 0; y < image.height; y++)
+ for(unsigned x = 0; x < image.width; x++)
+ {
+ image.data[y * image.width * 4 + x * 4 + c] = (x ^ y) ? colors[i + c] : colors[j + c];
+ }
+ image.data[c] = colors[k + c];
+ image.data[image.data.size() - 4 + c] = colors[l + c];
+ }
+ doCodecTest(image);
+ }
+}
+
void testSize(unsigned w, unsigned h)
{
std::cout << "codec test size " << w << " " << h << std::endl;
@@ -1921,6 +1960,7 @@ void doMain()
testPaletteToPaletteDecode2();
//Colors
+ testFewColors();
testColorKeyConvert();
testColorConvert();
testColorConvert2();