diff options
| author | Lode <lvandeve@gmail.com> | 2016-04-09 16:21:25 +0200 | 
|---|---|---|
| committer | Lode <lvandeve@gmail.com> | 2016-04-09 16:21:25 +0200 | 
| commit | 1bdcf470b3416f24aefcb99bb4bba2fb0df9704d (patch) | |
| tree | 7ed39ab7e7e0c604363c88017049faae99170947 | |
| parent | 3ea25a82805137025516375b8fdc005a8a951b18 (diff) | |
color key and file handling
| -rw-r--r-- | lodepng.cpp | 120 | ||||
| -rw-r--r-- | lodepng.h | 4 | ||||
| -rw-r--r-- | lodepng_unittest.cpp | 42 | 
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 */ @@ -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(); | 
