Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CMakeLists.txt #45

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Auth: Alberto Taiuti, Github usr: snowzufer

cmake_minimum_required(VERSION 2.8)

project(lode-png)

include_directories(${CMAKE_CURRENT_SOURCE_DIR})

add_library(lodepng
${CMAKE_CURRENT_SOURCE_DIR}/lodepng.cpp
${CMAKE_CURRENT_SOURCE_DIR}/lodepng_util.cpp
${CMAKE_CURRENT_SOURCE_DIR}/pngdetail.cpp)

set(LODEPNG_LIBRARY lodepng PARENT_SCOPE)
24 changes: 15 additions & 9 deletions lodepng.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
LodePNG version 20160501
LodePNG version 20161127

Copyright (c) 2005-2016 Lode Vandevenne

Expand Down Expand Up @@ -39,7 +39,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 = "20160501";
const char* LODEPNG_VERSION_STRING = "20161127";

/*
This source file is built up in the following large parts. The code sections
Expand Down Expand Up @@ -3534,8 +3534,8 @@ void lodepng_color_profile_init(LodePNGColorProfile* profile)
{
profile->colored = 0;
profile->key = 0;
profile->alpha = 0;
profile->key_r = profile->key_g = profile->key_b = 0;
profile->alpha = 0;
profile->numcolors = 0;
profile->bits = 1;
}
Expand Down Expand Up @@ -3622,8 +3622,8 @@ unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
if(a != 65535 && (a != 0 || (profile->key && !matchkey)))
{
profile->alpha = 1;
profile->key = 0;
alpha_done = 1;
if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
}
else if(a == 0 && !profile->alpha && !profile->key)
{
Expand All @@ -3636,6 +3636,7 @@ unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
{
/* Color key cannot be used if an opaque pixel also has that RGB color. */
profile->alpha = 1;
profile->key = 0;
alpha_done = 1;
}
}
Expand All @@ -3651,6 +3652,7 @@ unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
{
/* Color key cannot be used if an opaque pixel also has that RGB color. */
profile->alpha = 1;
profile->key = 0;
alpha_done = 1;
}
}
Expand Down Expand Up @@ -3684,6 +3686,7 @@ unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
if(a != 255 && (a != 0 || (profile->key && !matchkey)))
{
profile->alpha = 1;
profile->key = 0;
alpha_done = 1;
if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
}
Expand All @@ -3698,6 +3701,7 @@ unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
{
/* Color key cannot be used if an opaque pixel also has that RGB color. */
profile->alpha = 1;
profile->key = 0;
alpha_done = 1;
if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
}
Expand Down Expand Up @@ -3734,7 +3738,9 @@ unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
{
/* Color key cannot be used if an opaque pixel also has that RGB color. */
profile->alpha = 1;
profile->key = 0;
alpha_done = 1;
if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
}
}
}
Expand All @@ -3760,7 +3766,7 @@ unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,
{
LodePNGColorProfile prof;
unsigned error = 0;
unsigned i, n, palettebits, grey_ok, palette_ok;
unsigned i, n, palettebits, palette_ok;

lodepng_color_profile_init(&prof);
error = lodepng_get_color_profile(&prof, image, w, h, mode_in);
Expand All @@ -3770,14 +3776,14 @@ unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,
if(prof.key && w * h <= 16)
{
prof.alpha = 1; /*too few pixels to justify tRNS chunk overhead*/
prof.key = 0;
if(prof.bits < 8) prof.bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
}
grey_ok = !prof.colored && !prof.alpha; /*grey without alpha, with potentially low bits*/
n = prof.numcolors;
palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8));
palette_ok = n <= 256 && (n * 2 < w * h) && prof.bits <= 8;
palette_ok = n <= 256 && prof.bits <= 8;
if(w * h < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/
if(grey_ok && prof.bits <= palettebits) palette_ok = 0; /*grey is less overhead*/
if(!prof.colored && prof.bits <= palettebits) palette_ok = 0; /*grey is less overhead*/

if(palette_ok)
{
Expand Down Expand Up @@ -3806,7 +3812,7 @@ unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,
mode_out->colortype = prof.alpha ? (prof.colored ? LCT_RGBA : LCT_GREY_ALPHA)
: (prof.colored ? LCT_RGB : LCT_GREY);

if(prof.key && !prof.alpha)
if(prof.key)
{
unsigned mask = (1u << mode_out->bitdepth) - 1u; /*profile always uses 16-bit, mask converts it*/
mode_out->key_r = prof.key_r & mask;
Expand Down
9 changes: 5 additions & 4 deletions lodepng.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
LodePNG version 20160501
LodePNG version 20161127

Copyright (c) 2005-2016 Lode Vandevenne

Expand Down Expand Up @@ -559,11 +559,11 @@ Used internally by default if "auto_convert" is enabled. Public because it's use
typedef struct LodePNGColorProfile
{
unsigned colored; /*not greyscale*/
unsigned key; /*if true, image is not opaque. Only if true and alpha is false, color key is possible.*/
unsigned short key_r; /*these values are always in 16-bit bitdepth in the profile*/
unsigned key; /*image is not opaque and color key is possible instead of full alpha*/
unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/
unsigned short key_g;
unsigned short key_b;
unsigned alpha; /*alpha channel or alpha palette required*/
unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/
unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16.*/
unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order*/
unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for greyscale only. 16 if 16-bit per channel required.*/
Expand Down Expand Up @@ -1608,6 +1608,7 @@ yyyymmdd.
Some changes aren't backwards compatible. Those are indicated with a (!)
symbol.

*) 27 nov 2016: grey+alpha auto color model detection bugfix
*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort).
*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within
the limits of pure C90).
Expand Down
79 changes: 66 additions & 13 deletions lodepng_unittest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ g++ -I ./ lodepng.cpp examples/example_sdl.cpp -Wall -Wextra -pedantic -ansi -O3
*) strip trailing spaces and ensure consistent newlines

*) check diff of lodepng.cpp and lodepng.h before submitting
git difftool -y

*/

Expand Down Expand Up @@ -613,30 +614,28 @@ void testColor(int r, int g, int b, int a)
// Tests combinations of various colors in different orders
void testFewColors()
{
std::cout << "codec test colors " << std::endl;
std::cout << "codec test few 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);
colors.push_back(0); colors.push_back(0); colors.push_back(0); colors.push_back(255); // black
colors.push_back(255); colors.push_back(255); colors.push_back(255); colors.push_back(255); // white
colors.push_back(128); colors.push_back(128); colors.push_back(128); colors.push_back(255); // grey
colors.push_back(0); colors.push_back(0); colors.push_back(255); colors.push_back(255); // blue
colors.push_back(255); colors.push_back(255); colors.push_back(255); colors.push_back(0); // transparent white
colors.push_back(255); colors.push_back(255); colors.push_back(255); colors.push_back(1); // translucent white
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)
{
//std::cout << (i/4) << " " << (j/4) << " " << (k/4) << " " << (l/4) << std::endl;
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++)
{
Expand Down Expand Up @@ -1778,35 +1777,50 @@ void testAutoColorModel(const std::vector<unsigned char>& colors, unsigned inbit
ASSERT_EQUALS(colortype, state.info_png.color.colortype);
ASSERT_EQUALS(bitdepth, state.info_png.color.bitdepth);
ASSERT_EQUALS(key, state.info_png.color.key_defined);
// also check that the PNG decoded correctly and has same colors as input
if(inbitdepth == 8) { for(size_t i = 0; i < colors.size(); i++) ASSERT_EQUALS(colors[i], decoded[i]); }
else { for(size_t i = 0; i < colors.size() / 2; i++) ASSERT_EQUALS(colors[i * 2], decoded[i]); }
}

void testAutoColorModels()
{
// 1-bit grey
std::vector<unsigned char> grey1;
for(size_t i = 0; i < 2; i++) addColor(grey1, i * 255, i * 255, i * 255, 255);
testAutoColorModel(grey1, 8, LCT_GREY, 1, false);

// 2-bit grey
std::vector<unsigned char> grey2;
for(size_t i = 0; i < 4; i++) addColor(grey2, i * 85, i * 85, i * 85, 255);
testAutoColorModel(grey2, 8, LCT_GREY, 2, false);


// 4-bit grey
std::vector<unsigned char> grey4;
for(size_t i = 0; i < 16; i++) addColor(grey4, i * 17, i * 17, i * 17, 255);
testAutoColorModel(grey4, 8, LCT_GREY, 4, false);


// 8-bit grey
std::vector<unsigned char> grey8;
for(size_t i = 0; i < 256; i++) addColor(grey8, i, i, i, 255);
testAutoColorModel(grey8, 8, LCT_GREY, 8, false);


// 16-bit grey
std::vector<unsigned char> grey16;
for(size_t i = 0; i < 257; i++) addColor16(grey16, i, i, i, 65535);
testAutoColorModel(grey16, 16, LCT_GREY, 16, false);

// 8-bit grey+alpha
std::vector<unsigned char> grey8a;
for(size_t i = 0; i < 17; i++) addColor(grey8a, i, i, i, i);
testAutoColorModel(grey8a, 8, LCT_GREY_ALPHA, 8, false);

// 16-bit grey+alpha
std::vector<unsigned char> grey16a;
for(size_t i = 0; i < 257; i++) addColor16(grey16a, i, i, i, i);
testAutoColorModel(grey16a, 16, LCT_GREY_ALPHA, 16, false);


// various palette tests
std::vector<unsigned char> palette;
addColor(palette, 0, 0, 1, 255);
testAutoColorModel(palette, 8, LCT_PALETTE, 1, false);
Expand All @@ -1823,43 +1837,73 @@ void testAutoColorModels()
addColor(palette, 0, 0, 18, 1); // translucent
testAutoColorModel(palette, 8, LCT_PALETTE, 8, false);

// 1-bit grey + alpha not possible, becomes palette
std::vector<unsigned char> grey1a;
for(size_t i = 0; i < 2; i++) addColor(grey1a, i, i, i, 128);
testAutoColorModel(grey1a, 8, LCT_PALETTE, 1, false);

// 2-bit grey + alpha not possible, becomes palette
std::vector<unsigned char> grey2a;
for(size_t i = 0; i < 4; i++) addColor(grey2a, i, i, i, 128);
testAutoColorModel(grey2a, 8, LCT_PALETTE, 2, false);

// 4-bit grey + alpha not possible, becomes palette
std::vector<unsigned char> grey4a;
for(size_t i = 0; i < 16; i++) addColor(grey4a, i, i, i, 128);
testAutoColorModel(grey4a, 8, LCT_PALETTE, 4, false);

// 8-bit rgb
std::vector<unsigned char> rgb = grey8;
addColor(rgb, 255, 0, 0, 255);
testAutoColorModel(rgb, 8, LCT_RGB, 8, false);

// 8-bit rgb + key
std::vector<unsigned char> rgb_key = rgb;
addColor(rgb_key, 128, 0, 0, 0);
testAutoColorModel(rgb_key, 8, LCT_RGB, 8, true);

// 8-bit rgb, not key due to edge case: single key color, but opaque color has same RGB value
std::vector<unsigned char> rgb_key2 = rgb_key;
addColor(rgb_key2, 128, 0, 0, 255); // same color but opaque ==> no more key
testAutoColorModel(rgb_key2, 8, LCT_RGBA, 8, false);

// 8-bit rgb, not key due to semi translucent
std::vector<unsigned char> rgb_key3 = rgb_key;
addColor(rgb_key3, 128, 0, 0, 255); // semi-translucent ==> no more key
testAutoColorModel(rgb_key3, 8, LCT_RGBA, 8, false);

// 8-bit rgb, not key due to multiple transparent colors
std::vector<unsigned char> rgb_key4 = rgb_key;
addColor(rgb_key4, 128, 0, 0, 255);
addColor(rgb_key4, 129, 0, 0, 255); // two different transparent colors ==> no more key
testAutoColorModel(rgb_key4, 8, LCT_RGBA, 8, false);

// 1-bit grey with key
std::vector<unsigned char> grey1_key = grey1;
grey1_key[7] = 0;
testAutoColorModel(grey1_key, 8, LCT_GREY, 1, true);

// 2-bit grey with key
std::vector<unsigned char> grey2_key = grey2;
grey2_key[7] = 0;
testAutoColorModel(grey2_key, 8, LCT_GREY, 2, true);

// 4-bit grey with key
std::vector<unsigned char> grey4_key = grey4;
grey4_key[7] = 0;
testAutoColorModel(grey4_key, 8, LCT_GREY, 4, true);

// 8-bit grey with key
std::vector<unsigned char> grey8_key = grey8;
grey8_key[7] = 0;
testAutoColorModel(grey8_key, 8, LCT_GREY, 8, true);

// 16-bit grey with key
std::vector<unsigned char> grey16_key = grey16;
grey16_key[14] = grey16_key[15] = 0;
testAutoColorModel(grey16_key, 16, LCT_GREY, 16, true);

// a single 16-bit color, can't become palette due to being 16-bit
std::vector<unsigned char> small16;
addColor16(small16, 1, 0, 0, 65535);
testAutoColorModel(small16, 16, LCT_RGB, 16, false);
Expand All @@ -1868,13 +1912,22 @@ void testAutoColorModels()
addColor16(small16a, 1, 0, 0, 1);
testAutoColorModel(small16a, 16, LCT_RGBA, 16, false);

// what we provide as 16-bit is actually representable as 8-bit, so 8-bit palette expected for single color
std::vector<unsigned char> not16;
addColor16(not16, 257, 257, 257, 0);
testAutoColorModel(not16, 16, LCT_PALETTE, 1, false);

// the rgb color is representable as 8-bit, but the alpha channel only as 16-bit, so ensure it uses 16-bit and not palette for this single color
std::vector<unsigned char> alpha16;
addColor16(alpha16, 257, 0, 0, 10000);
testAutoColorModel(alpha16, 16, LCT_RGBA, 16, false);

// 1-bit grey, with attempt to get color key but can't do it due to opaque color with same value
std::vector<unsigned char> grey1k;
addColor(grey1k, 0, 0, 0, 255);
addColor(grey1k, 255, 255, 255, 255);
addColor(grey1k, 255, 255, 255, 0);
testAutoColorModel(grey1k, 8, LCT_PALETTE, 2, false);
}

void testPaletteToPaletteDecode() {
Expand Down