Skip to content
Snippets Groups Projects
Commit 7e8af607 authored by Janis Born's avatar Janis Born
Browse files

ensure correct endianness for decoding and encoding 16 bit raw data using LodePNG

parent c021ba6b
No related branches found
No related tags found
No related merge requests found
......@@ -15,6 +15,7 @@
#include <cstdio>
#include <ctime>
#include <stdexcept>
#include <fstream>
#include "lodepng/lodepng.h"
#include "rgbe/rgbe.hh"
......@@ -163,34 +164,52 @@ bool saveScreenshotWithDate(const std::string& _prefix, const std::string& _file
// library specific load
///////////////////////////////////////////////////////////////////////////////////////////////////
struct LodepngFile
{
public:
LodepngFile(const std::string& _filename)
{
unsigned int errorCode = lodepng_load_file(&mData, &mSize, _filename.c_str());
if(errorCode)
{
std::stringstream errorMsg;
errorMsg << "LodePNG error while loading file " << _filename << " - " << errorCode << ": " << lodepng_error_text(errorCode);
mData = nullptr;
throw std::runtime_error(errorMsg.str());
}
}
~LodepngFile()
{
free(mData);
}
unsigned char* mData;
size_t mSize;
};
SharedTextureData loadTextureDataFromLodepng(const std::string &_filename)
{
SharedTextureData data;
unsigned int errorCode;
unsigned int width, height;
unsigned char* png;
size_t pngsize;
LodePNGState state;
// Load the PNG file from disk
lodepng_state_init(&state);
errorCode = lodepng_load_file(&png, &pngsize, _filename.c_str());
if(errorCode)
try
{
ACGL::Utils::error() << "LodePNG error while loading file " << _filename << " - " << errorCode << ": " << lodepng_error_text(errorCode) << std::endl;
return data;
}
LodepngFile lodepngFile(_filename);
// Extract metadata (bit depth, color type)
errorCode = lodepng_inspect(&width, &height, &state, png, pngsize);
errorCode = lodepng_inspect(&width, &height, &state, lodepngFile.mData, lodepngFile.mSize);
if(errorCode)
{
ACGL::Utils::error() << "LodePNG error " << errorCode << ": " << lodepng_error_text(errorCode) << std::endl;
return data;
std::stringstream errorMsg;
errorMsg << "LodePNG error " << errorCode << ": " << lodepng_error_text(errorCode);
throw std::runtime_error(errorMsg.str());
}
unsigned int bitdepth = state.info_png.color.bitdepth;
......@@ -208,28 +227,32 @@ SharedTextureData loadTextureDataFromLodepng(const std::string &_filename)
GLenum glType = 0;
if(bitdepth == 8) glType = GL_UNSIGNED_BYTE;
if(bitdepth == 16) glType = GL_UNSIGNED_SHORT;
if(bitdepth == 32) glType = GL_UNSIGNED_INT;
if(channels == 0 || glFormat == 0 || glType == 0)
{
ACGL::Utils::error() << "Could not load " << _filename << ": " << "unsupported bit depth or format" << std::endl;
return data;
std::stringstream errorMsg;
errorMsg << "Could not load " << _filename << ": " << "unsupported bit depth or format";
throw std::runtime_error(errorMsg.str());
}
// Decode the image
unsigned char* image;
errorCode = lodepng_decode_memory(&image, &width, &height, png, pngsize, colorType, bitdepth);
errorCode = lodepng_decode_memory(&image, &width, &height, lodepngFile.mData, lodepngFile.mSize, colorType, bitdepth);
if(errorCode)
{
ACGL::Utils::error() << "LodePNG error while loading file " << _filename << " - " << errorCode << ": " << lodepng_error_text(errorCode) << std::endl;
return data;
std::stringstream errorMsg;
errorMsg << "LodePNG error while decoding file " << _filename << " - " << errorCode << ": " << lodepng_error_text(errorCode);
throw std::runtime_error(errorMsg.str());
}
free(png);
// LodePNG decodes 16 bit PNGs in big endian format ==> Convert
#ifndef ACGL_BIG_ENDIAN
if(bitdepth == 16)
for(int i = 0; i < (width * height * channels * 2); i += 2)
std::swap(image[i], image[i+1]);
#endif
// Wrap the data in a TextureData object
data = SharedTextureData(new TextureData());
data->setData((GLubyte*)image);
data->setWidth(width);
......@@ -239,6 +262,11 @@ SharedTextureData loadTextureDataFromLodepng(const std::string &_filename)
// Flip
data->flipVertically();
}
catch(std::runtime_error& error)
{
ACGL::Utils::error() << error.what() << std::endl;
}
return data;
}
......@@ -626,6 +654,12 @@ bool saveTextureDataToLodepng( const SharedTextureData &_data, const std::string
return false;
}
// LodePNG expects 16 bit image data in big endian format ==> convert
#ifndef ACGL_BIG_ENDIAN
if(channelBitCount == 16)
for(int i = 0; i < _data->getWidth() * _data->getHeight() * _data->getNumberOfChannels() * 2; i += 2)
std::swap(processedData[i], processedData[i+1]);
#endif
LodePNGColorType colorType;
if (channelCount == 1) colorType = LCT_GREY;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment