summaryrefslogtreecommitdiff
path: root/lodepng.cpp
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 /lodepng.cpp
parent3ea25a82805137025516375b8fdc005a8a951b18 (diff)
color key and file handling
Diffstat (limited to 'lodepng.cpp')
-rw-r--r--lodepng.cpp120
1 files changed, 77 insertions, 43 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 */