diff options
Diffstat (limited to 'lodepng.cpp')
-rw-r--r-- | lodepng.cpp | 120 |
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 */ |