[DEV] add an API to load raw buffer
This commit is contained in:
parent
f345c9c664
commit
1181bc52e7
@ -9,6 +9,11 @@
|
||||
#include <egami/ImagePrivate.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
|
||||
std::ostream& egami::operator <<(std::ostream& _os, const egami::Image& _obj) {
|
||||
_os << "egami::Image{" << _obj.getSize() << " on GPU: " << _obj.getGPUSize() << " color=" << _obj.getType();
|
||||
return _os;
|
||||
}
|
||||
|
||||
std::ostream& egami::operator <<(std::ostream& _os, const enum egami::colorType _type) {
|
||||
switch (_type) {
|
||||
case egami::colorType::undefined:
|
||||
@ -80,6 +85,16 @@ egami::Image::Image() :
|
||||
|
||||
}
|
||||
|
||||
egami::Image::Image(const egami::Image& _image):
|
||||
m_data(_image.m_data) {
|
||||
|
||||
}
|
||||
|
||||
egami::Image& egami::Image::operator=(const egami::Image& _image) {
|
||||
m_data = _image.m_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
egami::Image::~Image() {
|
||||
|
||||
}
|
||||
@ -204,6 +219,8 @@ const ivec2& egami::Image::getSize() const {
|
||||
return m_data->getSize();
|
||||
}
|
||||
|
||||
#if defined(__TARGET_OS__Android) \
|
||||
|| defined(__TARGET_OS__IOs)
|
||||
/**
|
||||
* @brief get the next power 2 if the input
|
||||
* @param[in] value Value that we want the next power of 2
|
||||
@ -220,6 +237,7 @@ static int32_t nextP2(int32_t _value) {
|
||||
EGAMI_CRITICAL("impossible CASE....");
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
ivec2 egami::Image::getGPUSize() const {
|
||||
if (m_data == nullptr) {
|
||||
|
@ -79,6 +79,8 @@ namespace egami {
|
||||
* @note use @ref configure to set a correct image
|
||||
*/
|
||||
Image();
|
||||
Image(const egami::Image& _image);
|
||||
Image& operator=(const egami::Image& _image);
|
||||
Image(const ivec2& _size,
|
||||
enum colorType _type = egami::colorType::undefined);
|
||||
~Image();
|
||||
@ -142,5 +144,6 @@ namespace egami {
|
||||
void set(const std::vector<etk::Color<float,4>>& _data, const ivec2& _size);
|
||||
void set(const std::vector<etk::Color<uint8_t,4>>& _data, const ivec2& _size);
|
||||
};
|
||||
std::ostream& operator <<(std::ostream& _os, const egami::Image& _obj);
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,39 @@ egami::Image egami::load(const std::string& _fileName, const ivec2& _size) {
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
egami::Image egami::load(const std::string& _mineType, const std::vector<uint8_t>& _buffer, const ivec2& _size) {
|
||||
egami::Image out;
|
||||
// select the corect Loader :
|
||||
if (_mineType == "image/bmp") {
|
||||
out = egami::loadBMP(_buffer);
|
||||
if (out.exist() == false) {
|
||||
EGAMI_ERROR("Error to load BMP file '" << _buffer.size() << "'");
|
||||
}
|
||||
}else if (_mineType == "image/png") {
|
||||
#ifdef EGAMI_BUILD_PNG
|
||||
out = egami::loadPNG(_buffer);
|
||||
if (out.exist() == false) {
|
||||
EGAMI_ERROR("Error to load PNG file '" << _buffer.size() << "'");
|
||||
}
|
||||
#else
|
||||
EGAMI_WARNING("egamy not compile with the PNG dependency for file '" << _buffer.size() << "'");
|
||||
#endif
|
||||
} else if (_mineType == "image/jpg") {
|
||||
#ifdef EGAMI_BUILD_JPEG
|
||||
out = egami::loadJPG(_buffer);
|
||||
if (out.exist() == false) {
|
||||
EGAMI_ERROR("Error to load JPG file '" << _buffer.size() << "'");
|
||||
}
|
||||
#else
|
||||
EGAMI_WARNING("egamy not compile with the JPEG dependency for file '" << _buffer.size() << "'");
|
||||
#endif
|
||||
} else {
|
||||
EGAMI_ERROR("Extention not managed '" << _mineType << "' Sopported extention : image/bmp, image/png, image/jpg");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool egami::store(const egami::Image& _input, const std::string& _fileName) {
|
||||
std::string tmpName = etk::tolower(_fileName);
|
||||
EGAMI_DEBUG("Store file : " << _fileName);
|
||||
|
@ -19,6 +19,13 @@ namespace egami {
|
||||
* @param[in] _size Dimention of the file when resizable (SVG).
|
||||
*/
|
||||
egami::Image load(const std::string& _fileName, const ivec2& _size=ivec2(-1,-1) );
|
||||
/**
|
||||
* @brief Load a specific ilage file in the requested image data.
|
||||
* @param[in] _mineType mineType of the buffer.
|
||||
* @param[in] _buffer memory file.
|
||||
* @param[in] _size Dimention of the file when resizable (SVG).
|
||||
*/
|
||||
egami::Image load(const std::string& _mineType, const std::vector<uint8_t>& _buffer, const ivec2& _size=ivec2(-1,-1) );
|
||||
/**
|
||||
* @brief Save an image in a file.
|
||||
* @param[in] _input Data of the image.
|
||||
@ -26,6 +33,13 @@ namespace egami {
|
||||
* @return true if the file is corectly Stored, false otherwise
|
||||
*/
|
||||
bool store(const egami::Image& _input, const std::string& _fileName);
|
||||
/**
|
||||
* @brief Save an image in a memory buffer.
|
||||
* @param[in] _input Data of the image.
|
||||
* @param[out] _buffer Store file in this buffer.
|
||||
* @return true if the file is corectly Stored, false otherwise
|
||||
*/
|
||||
bool store(const egami::Image& _input, std::vector<uint8_t>& _buffer);
|
||||
/**
|
||||
* @brief know if a file can have multiple size definition.
|
||||
* @param[in] _fileName Name of the file.
|
||||
|
@ -106,9 +106,22 @@ static void display(struct bitmapFileHeader _header, struct bitmapInfoHeader _in
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
egami::Image egami::loadBMP(const std::string& _inputFile) {
|
||||
etk::FSNode fileName(_inputFile);
|
||||
if (fileName.exist() == false) {
|
||||
EGAMI_ERROR("File does not existed='" << fileName << "'");
|
||||
return egami::Image();
|
||||
}
|
||||
if(fileName.fileOpenRead() == false) {
|
||||
EGAMI_ERROR("Can not find the file name='" << fileName << "'");
|
||||
return egami::Image();
|
||||
}
|
||||
std::vector<uint8_t> allData = fileName.fileReadAll<uint8_t>();
|
||||
fileName.fileClose();
|
||||
return egami::loadBMP(allData);
|
||||
}
|
||||
|
||||
egami::Image egami::loadBMP(const std::vector<uint8_t>& _buffer) {
|
||||
egami::Image out;
|
||||
enum modeBitmap m_dataMode = BITS_16_R5G6B5;
|
||||
int32_t m_width = 0;
|
||||
@ -117,34 +130,18 @@ egami::Image egami::loadBMP(const std::string& _inputFile) {
|
||||
bool useExtended = false;
|
||||
struct bitmapInfoHeader m_InfoHeader;
|
||||
struct bitmapInfoHeaderExtended m_InfoHeaderExtended;
|
||||
|
||||
etk::FSNode fileName(_inputFile);
|
||||
// get the fileSize ...
|
||||
/*if (fileName.size() < (int32_t)(sizeof(struct bitmapFileHeader) + sizeof(struct bitmapFileHeader) ) ) {
|
||||
EGAMI_ERROR("not enought data in the file named=\"" << fileName << "\"");
|
||||
return;
|
||||
}*/
|
||||
if (fileName.exist() == false) {
|
||||
EGAMI_ERROR("File does not existed=\"" << fileName << "\"");
|
||||
return out;
|
||||
}
|
||||
if(fileName.fileOpenRead() ==false) {
|
||||
EGAMI_ERROR("Can not find the file name=\"" << fileName << "\"");
|
||||
return out;
|
||||
}
|
||||
// get the data :
|
||||
if (fileName.fileRead(&m_FileHeader,sizeof(struct bitmapFileHeader),1) != 1) {
|
||||
EGAMI_ERROR("error loading file header");
|
||||
fileName.fileClose();
|
||||
if (_buffer.size() < sizeof(struct bitmapFileHeader)) {
|
||||
EGAMI_ERROR("error loading file header, not enough data");
|
||||
return out;
|
||||
}
|
||||
memcpy(&m_FileHeader, &_buffer[0], sizeof(struct bitmapFileHeader));
|
||||
if (m_FileHeader.bfOffBits > sizeof(struct bitmapFileHeader) + sizeof(struct bitmapInfoHeader)) {
|
||||
EGAMI_VERBOSE("Read bitmap in EXTENDED mode ...");
|
||||
if (fileName.fileRead(&m_InfoHeaderExtended,sizeof(struct bitmapInfoHeaderExtended),1) != 1) {
|
||||
EGAMI_ERROR("error loading file header");
|
||||
fileName.fileClose();
|
||||
if (_buffer.size() < sizeof(struct bitmapFileHeader) + sizeof(struct bitmapInfoHeaderExtended)) {
|
||||
EGAMI_ERROR("error loading file header, not enough data");
|
||||
return out;
|
||||
}
|
||||
memcpy(&m_FileHeader, &_buffer[sizeof(struct bitmapFileHeader)], sizeof(struct bitmapInfoHeaderExtended));
|
||||
useExtended = true;
|
||||
m_InfoHeader.biSize = m_InfoHeaderExtended.biSize;
|
||||
m_InfoHeader.biWidth = m_InfoHeaderExtended.biWidth;
|
||||
@ -158,29 +155,22 @@ egami::Image egami::loadBMP(const std::string& _inputFile) {
|
||||
m_InfoHeader.biYPelsPerMeter = m_InfoHeaderExtended.biYPelsPerMeter;
|
||||
} else {
|
||||
EGAMI_VERBOSE("Read bitmap in BASIC mode ...");
|
||||
if (fileName.fileRead(&m_InfoHeader,sizeof(struct bitmapInfoHeader),1) != 1) {
|
||||
EGAMI_ERROR("error loading file header");
|
||||
fileName.fileClose();
|
||||
if (_buffer.size() < sizeof(struct bitmapFileHeader) + sizeof(struct bitmapInfoHeader)) {
|
||||
EGAMI_ERROR("error loading file header, not enough data");
|
||||
return out;
|
||||
}
|
||||
memcpy(&m_FileHeader, &_buffer[sizeof(struct bitmapFileHeader)], sizeof(struct bitmapInfoHeader));
|
||||
useExtended = false;
|
||||
}
|
||||
int32_t offset = m_FileHeader.bfOffBits;
|
||||
//display(m_FileHeader, m_InfoHeader);
|
||||
//EGAMI_ERROR("plopppppppppppppp " << m_FileHeader.bfOffBits);
|
||||
if(fileName.fileSeek(m_FileHeader.bfOffBits, etk::seekNode_start) == false) {
|
||||
EGAMI_ERROR("error with the 'bfOffBits' in the file named=\"" << fileName << "\"");
|
||||
fileName.fileClose();
|
||||
return out;
|
||||
}
|
||||
// check the header error :
|
||||
if (m_FileHeader.bfType != 0x4D42) {
|
||||
EGAMI_ERROR("the file=\"" << fileName << "\" is not a bitmap file ...");
|
||||
fileName.fileClose();
|
||||
EGAMI_ERROR("the Buffer is not a bitmap file ...");
|
||||
return out;
|
||||
}
|
||||
if (m_FileHeader.bfReserved != 0x00000000) {
|
||||
EGAMI_ERROR("the bfReserved feald is not at 0 == > not supported format ...");
|
||||
fileName.fileClose();
|
||||
return out;
|
||||
}
|
||||
m_width = m_InfoHeader.biWidth;
|
||||
@ -207,25 +197,21 @@ egami::Image egami::loadBMP(const std::string& _inputFile) {
|
||||
out.configure(ivec2(m_width,m_height), egami::colorType::RGBA8);
|
||||
} else {
|
||||
EGAMI_ERROR("the biBitCount & biCompression fealds are unknow == > not supported format ...");
|
||||
fileName.fileClose();;
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> m_data;
|
||||
if(m_InfoHeader.biSizeImage != 0) {
|
||||
m_data.resize(m_InfoHeader.biSizeImage, 0);
|
||||
if (fileName.fileRead(&m_data[0],m_InfoHeader.biSizeImage,1) != 1){
|
||||
if (_buffer.size() < offset + m_InfoHeader.biSizeImage) {
|
||||
EGAMI_CRITICAL("Can not read the file with the good size...");
|
||||
}
|
||||
}
|
||||
fileName.fileClose();
|
||||
|
||||
etk::Color<> tmpColor(0,0,0,0);
|
||||
|
||||
// need now to generate RGBA data ...
|
||||
switch(m_dataMode) {
|
||||
case BITS_16_R5G6B5: {
|
||||
uint16_t * pointer = (uint16_t*)(&m_data[0]);
|
||||
const uint16_t * pointer = (const uint16_t*)(&_buffer[offset]);
|
||||
for(int32_t yyy=0; yyy<m_height; yyy++) {
|
||||
for(int32_t xxx=0; xxx<m_width; xxx++) {
|
||||
tmpColor.setB((uint8_t)((*pointer & 0xF800) >> 8));
|
||||
@ -239,7 +225,7 @@ egami::Image egami::loadBMP(const std::string& _inputFile) {
|
||||
}
|
||||
break;
|
||||
case BITS_16_X1R5G5B5: {
|
||||
uint16_t * pointer = (uint16_t*)(&m_data[0]);
|
||||
const uint16_t * pointer = (const uint16_t*)(&_buffer[offset]);
|
||||
for(int32_t yyy=0; yyy<m_height; yyy++) {
|
||||
for(int32_t xxx=0; xxx<m_width; xxx++) {
|
||||
tmpColor.setB((int8_t)((*pointer & 0x7C00) >> 7));
|
||||
@ -262,7 +248,7 @@ egami::Image egami::loadBMP(const std::string& _inputFile) {
|
||||
} else if ((baseLine%4) == 3) {
|
||||
offset = 1;
|
||||
}
|
||||
uint8_t * pointer = (&m_data[0]);
|
||||
const uint8_t * pointer = (&_buffer[offset]);
|
||||
for(int32_t yyy=0; yyy<m_height; yyy++) {
|
||||
for(int32_t xxx=0; xxx<m_width; xxx++) {
|
||||
tmpColor.setB(*pointer++);
|
||||
@ -278,7 +264,7 @@ egami::Image egami::loadBMP(const std::string& _inputFile) {
|
||||
}
|
||||
break;
|
||||
case BITS_32_X8R8G8B8: {
|
||||
uint8_t * pointer = (&m_data[0]);
|
||||
const uint8_t * pointer = (&_buffer[offset]);
|
||||
for(int32_t yyy=0; yyy<m_height; yyy++) {
|
||||
for(int32_t xxx=0; xxx<m_width; xxx++) {
|
||||
pointer++;
|
||||
@ -292,7 +278,7 @@ egami::Image egami::loadBMP(const std::string& _inputFile) {
|
||||
}
|
||||
break;
|
||||
case BITS_32_A8R8G8B8: {
|
||||
uint8_t * pointer = (&m_data[0]);
|
||||
const uint8_t * pointer = (&_buffer[offset]);
|
||||
for(int32_t yyy=0; yyy<m_height; yyy++) {
|
||||
for(int32_t xxx=0; xxx<m_width; xxx++) {
|
||||
tmpColor.setB(*pointer++);
|
||||
|
@ -14,6 +14,12 @@ namespace egami {
|
||||
* @return Generate image or empty image
|
||||
*/
|
||||
egami::Image loadBMP(const std::string& _fileName);
|
||||
/**
|
||||
* @breif Load a bmp file in the image.
|
||||
* @param[in] _buffer file buffer
|
||||
* @return Generate image or empty image
|
||||
*/
|
||||
egami::Image loadBMP(const std::vector<uint8_t>& _buffer);
|
||||
/**
|
||||
* @breif Store a bmp file in the image.
|
||||
* @param[in] _fileName Name of the file.
|
||||
|
@ -40,19 +40,22 @@ void put_scanline_someplace(const uint8_t* _buffer, int32_t _row_stride) {
|
||||
|
||||
|
||||
egami::Image egami::loadJPG(const std::string& _inputFile) {
|
||||
egami::Image out;
|
||||
etk::FSNode fileName(_inputFile);
|
||||
if (fileName.exist() == false) {
|
||||
EGAMI_ERROR("File does not existed='" << fileName << "'");
|
||||
return out;
|
||||
return egami::Image();
|
||||
}
|
||||
if(fileName.fileOpenRead() == false) {
|
||||
EGAMI_ERROR("Can not find the file name='" << fileName << "'");
|
||||
return out;
|
||||
return egami::Image();
|
||||
}
|
||||
std::vector<uint8_t> allData = fileName.fileReadAll<uint8_t>();
|
||||
fileName.fileClose();
|
||||
return egami::loadJPG(allData);
|
||||
}
|
||||
|
||||
egami::Image egami::loadJPG(const std::vector<uint8_t>& _buffer) {
|
||||
egami::Image out;
|
||||
// This struct contains the JPEG decompression parameters and pointers to working space (which is allocated as needed by the JPEG library).
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
// We use our private extension JPEG error handler. Note that this struct must live as long as the main JPEG parameter struct, to avoid dangling-pointer problems.
|
||||
@ -76,7 +79,7 @@ egami::Image egami::loadJPG(const std::string& _inputFile) {
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
// Step 2: specify data source (eg, a file)
|
||||
jpeg_mem_src(&cinfo, &allData[0], allData.size());
|
||||
jpeg_mem_src(&cinfo, &_buffer[0], _buffer.size());
|
||||
|
||||
// Step 3: read file parameters with jpeg_read_header()
|
||||
(void)jpeg_read_header(&cinfo, TRUE);
|
||||
|
@ -14,5 +14,11 @@ namespace egami {
|
||||
* @return Read Image.
|
||||
*/
|
||||
egami::Image loadJPG(const std::string& _fileName);
|
||||
/**
|
||||
* @breif Load a jpeg file in the image.
|
||||
* @param[in] _buffer file Buffer
|
||||
* @return Read Image.
|
||||
*/
|
||||
egami::Image loadJPG(const std::vector<uint8_t>& _buffer);
|
||||
}
|
||||
|
||||
|
@ -10,12 +10,47 @@
|
||||
#include <egami/wrapperPNG.hpp>
|
||||
#include <etk/os/FSNode.hpp>
|
||||
#include <png/png.h>
|
||||
namespace egami {
|
||||
class ReaderInstance {
|
||||
public:
|
||||
virtual ~ReaderInstance() = default;
|
||||
virtual void read(png_bytep data, png_size_t length) = 0;
|
||||
};
|
||||
|
||||
class ReaderInstanceFSNode : public egami::ReaderInstance {
|
||||
private:
|
||||
etk::FSNode& m_data;
|
||||
public:
|
||||
ReaderInstanceFSNode(etk::FSNode& _data):
|
||||
m_data(_data) {
|
||||
|
||||
}
|
||||
void read(png_bytep data, png_size_t length) override {
|
||||
m_data.fileRead(data, 1, length);
|
||||
}
|
||||
};
|
||||
|
||||
class ReaderInstanceBuffer : public egami::ReaderInstance {
|
||||
private:
|
||||
const std::vector<uint8_t>& m_data;
|
||||
int32_t m_offset;
|
||||
public:
|
||||
ReaderInstanceBuffer(const std::vector<uint8_t>& _data, int32_t _offset):
|
||||
m_data(_data),
|
||||
m_offset(_offset) {
|
||||
|
||||
}
|
||||
void read(png_bytep data, png_size_t length) override {
|
||||
memcpy(data, &m_data[m_offset], length);
|
||||
m_offset += length;
|
||||
}
|
||||
};
|
||||
}
|
||||
// we must change the access of the IO of the png lib :
|
||||
static void local_ReadData(png_structp png_ptr, png_bytep data, png_size_t length) {
|
||||
etk::FSNode* fileNode = static_cast<etk::FSNode*>(png_get_io_ptr(png_ptr));
|
||||
if (fileNode != nullptr) {
|
||||
fileNode->fileRead(data, 1, length);
|
||||
egami::ReaderInstance* instance = static_cast<egami::ReaderInstance*>(png_get_io_ptr(png_ptr));
|
||||
if (instance != nullptr) {
|
||||
instance->read(data, length);
|
||||
}
|
||||
}
|
||||
/*
|
||||
@ -44,74 +79,18 @@ void user_warning_fn(png_structp _pngPtr, png_const_charp _warningMsg) {
|
||||
EGAMI_WARNING("libpng warning: '" << _warningMsg << "'");
|
||||
}
|
||||
|
||||
egami::Image egami::loadPNG(const std::string& _inputFile) {
|
||||
static egami::Image genericLoader(png_structp _pngPtr, png_infop _infoPtr) {
|
||||
egami::Image out;
|
||||
etk::FSNode fileName(_inputFile);
|
||||
if (fileName.exist() == false) {
|
||||
EGAMI_ERROR("File does not existed='" << fileName << "'");
|
||||
return out;
|
||||
}
|
||||
if(fileName.fileOpenRead() == false) {
|
||||
EGAMI_ERROR("Can not find the file name='" << fileName << "'");
|
||||
return out;
|
||||
}
|
||||
unsigned char header[8];
|
||||
png_infop info_ptr;
|
||||
png_structp png_ptr;
|
||||
|
||||
if (fileName.fileRead(header,1,8) != 8) {
|
||||
EGAMI_ERROR("error loading file header");
|
||||
fileName.fileClose();
|
||||
return out;
|
||||
}
|
||||
if (png_sig_cmp(header, 0, 8)) {
|
||||
EGAMI_ERROR("Invalid file :" << fileName);
|
||||
return out;
|
||||
}
|
||||
|
||||
// PNG read setup
|
||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, user_error_fn, user_warning_fn);
|
||||
if (png_ptr == nullptr) {
|
||||
EGAMI_ERROR("Can not Allocate PNG structure");
|
||||
fileName.fileClose();
|
||||
return out;
|
||||
}
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == nullptr) {
|
||||
EGAMI_ERROR("Can not Allocate PNG info structure");
|
||||
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
|
||||
fileName.fileClose();
|
||||
return out;
|
||||
}
|
||||
/*
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
EGAMI_ERROR(" Can not set the JUMP buffer adresses");
|
||||
// Free all of the memory associated with the png_ptr and info_ptr
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||
fileName.fileClose();
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
// overwrite the read and write function :
|
||||
png_set_read_fn(png_ptr,
|
||||
&fileName,
|
||||
&local_ReadData);
|
||||
/*
|
||||
png_set_write_fn(png_ptr,
|
||||
&fileName,
|
||||
&LocalWriteData,
|
||||
&localFlushData);
|
||||
*/
|
||||
// If we have already read some of the signature
|
||||
png_set_sig_bytes(png_ptr, 8);
|
||||
png_set_sig_bytes(_pngPtr, 8);
|
||||
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
png_read_info(_pngPtr, _infoPtr);
|
||||
png_uint_32 width = 0;
|
||||
png_uint_32 height = 0;
|
||||
int bit_depth = 0;
|
||||
int colorType = 0;
|
||||
int interlace_type = 0;
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &colorType, &interlace_type, nullptr, nullptr);
|
||||
png_get_IHDR(_pngPtr, _infoPtr, &width, &height, &bit_depth, &colorType, &interlace_type, nullptr, nullptr);
|
||||
// reallocate the image
|
||||
EGAMI_VERBOSE("Load PNG image : (" << width << "," << height << ")" );
|
||||
switch (colorType) {
|
||||
@ -133,34 +112,34 @@ egami::Image egami::loadPNG(const std::string& _inputFile) {
|
||||
|
||||
// Tell libpng to strip 16 bits/color files down to 8 bits/color. Use accurate scaling if it's available, otherwise just chop off the low byte.
|
||||
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
|
||||
png_set_scale_16(png_ptr);
|
||||
png_set_scale_16(_pngPtr);
|
||||
#else
|
||||
png_set_strip_16(png_ptr);
|
||||
png_set_strip_16(_pngPtr);
|
||||
#endif
|
||||
|
||||
// Strip alpha bytes from the input data without combining with the background (not recommended).
|
||||
//png_set_strip_alpha(png_ptr);
|
||||
//png_set_strip_alpha(_pngPtr);
|
||||
|
||||
// Extract multiple pixels with bit depths of 1, 2, and 4 from a single byte into separate bytes (useful for paletted and grayscale images).
|
||||
png_set_packing(png_ptr);
|
||||
png_set_packing(_pngPtr);
|
||||
|
||||
// Change the order of packed pixels to least significant bit first (not useful if you are using png_set_packing).
|
||||
png_set_packswap(png_ptr);
|
||||
png_set_packswap(_pngPtr);
|
||||
|
||||
/* Expand paletted colors into true RGB triplets */
|
||||
if (colorType == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
png_set_palette_to_rgb(_pngPtr);
|
||||
}
|
||||
|
||||
// Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel
|
||||
if ( colorType == PNG_COLOR_TYPE_GRAY
|
||||
&& bit_depth < 8) {
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
png_set_expand_gray_1_2_4_to_8(_pngPtr);
|
||||
}
|
||||
|
||||
// Expand paletted or RGB images with transparency to full alpha channels so the data will be available as RGBA quartets.
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0) {
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
if (png_get_valid(_pngPtr, _infoPtr, PNG_INFO_tRNS) != 0) {
|
||||
png_set_tRNS_to_alpha(_pngPtr);
|
||||
}
|
||||
|
||||
/* Set the background color to draw transparent and alpha images over.
|
||||
@ -171,19 +150,19 @@ egami::Image egami::loadPNG(const std::string& _inputFile) {
|
||||
*/
|
||||
/*
|
||||
png_color::16 my_background, *image_background;
|
||||
if (png_get_bKGD(png_ptr, info_ptr, &image_background) != 0) {
|
||||
png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
|
||||
if (png_get_bKGD(_pngPtr, _infoPtr, &image_background) != 0) {
|
||||
png_set_background(_pngPtr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
|
||||
} else {
|
||||
png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
|
||||
png_set_background(_pngPtr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
|
||||
}
|
||||
*/
|
||||
/* Optional call to gamma correct and add the background to the palette
|
||||
* and update info structure. REQUIRED if you are expecting libpng to
|
||||
* update the palette for you (ie you selected such a transform above).
|
||||
*/
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
png_read_update_info(_pngPtr, _infoPtr);
|
||||
|
||||
// Allocate the memory to hold the image using the fields of info_ptr.
|
||||
// Allocate the memory to hold the image using the fields of _infoPtr.
|
||||
// The easiest way to read the image:
|
||||
png_bytep row_pointers[height];
|
||||
/* Clear the pointer array */
|
||||
@ -191,15 +170,13 @@ egami::Image egami::loadPNG(const std::string& _inputFile) {
|
||||
row_pointers[row] = nullptr;
|
||||
}
|
||||
for (png_uint_32 row = 0; row < height; row++) {
|
||||
row_pointers[row] = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
|
||||
row_pointers[row] = (png_bytep)png_malloc(_pngPtr, png_get_rowbytes(_pngPtr, _infoPtr));
|
||||
}
|
||||
EGAMI_DEBUG("Load image: " << _inputFile);
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
EGAMI_DEBUG("Load image: " << _inputFile << " DONE");
|
||||
// Read rest of file, and get additional chunks in info_ptr - REQUIRED
|
||||
png_read_end(png_ptr, info_ptr);
|
||||
png_read_image(_pngPtr, row_pointers);
|
||||
// Read rest of file, and get additional chunks in _infoPtr - REQUIRED
|
||||
png_read_end(_pngPtr, _infoPtr);
|
||||
|
||||
//png_set_expand(png_ptr);
|
||||
//png_set_expand(_pngPtr);
|
||||
|
||||
etk::Color<> tmpColor(0,0,0,0);
|
||||
switch (colorType) {
|
||||
@ -252,21 +229,117 @@ egami::Image egami::loadPNG(const std::string& _inputFile) {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
EGAMI_ERROR("Must be RGB+alpha?/GRAY+alpha? not supported : " << (int64_t)png_get_color_type(png_ptr, info_ptr));
|
||||
if ((png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_PALETTE) != 0) {
|
||||
EGAMI_ERROR("Must be RGB+alpha?/GRAY+alpha? not supported : " << (int64_t)png_get_color_type(_pngPtr, _infoPtr));
|
||||
if ((png_get_color_type(_pngPtr, _infoPtr) & PNG_COLOR_MASK_PALETTE) != 0) {
|
||||
EGAMI_ERROR(" palette");
|
||||
}
|
||||
if ((png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_COLOR) != 0) {
|
||||
if ((png_get_color_type(_pngPtr, _infoPtr) & PNG_COLOR_MASK_COLOR) != 0) {
|
||||
EGAMI_ERROR(" color");
|
||||
}
|
||||
if ((png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_ALPHA) != 0) {
|
||||
if ((png_get_color_type(_pngPtr, _infoPtr) & PNG_COLOR_MASK_ALPHA) != 0) {
|
||||
EGAMI_ERROR(" Alpha");
|
||||
}
|
||||
return egami::Image();
|
||||
}
|
||||
fileName.fileClose();
|
||||
// Clean up after the read, and free any memory allocated - REQUIRED
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||
png_destroy_read_struct(&_pngPtr, &_infoPtr, nullptr);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
egami::Image egami::loadPNG(const std::string& _inputFile) {
|
||||
egami::Image out;
|
||||
etk::FSNode fileName(_inputFile);
|
||||
if (fileName.exist() == false) {
|
||||
EGAMI_ERROR("File does not existed='" << fileName << "'");
|
||||
return out;
|
||||
}
|
||||
if(fileName.fileOpenRead() == false) {
|
||||
EGAMI_ERROR("Can not find the file name='" << fileName << "'");
|
||||
return out;
|
||||
}
|
||||
unsigned char header[8];
|
||||
|
||||
if (fileName.fileRead(header,1,8) != 8) {
|
||||
EGAMI_ERROR("error loading file header");
|
||||
fileName.fileClose();
|
||||
return out;
|
||||
}
|
||||
if (png_sig_cmp(header, 0, 8)) {
|
||||
EGAMI_ERROR("Invalid file :" << fileName);
|
||||
return out;
|
||||
}
|
||||
|
||||
// PNG read setup
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, user_error_fn, user_warning_fn);
|
||||
if (png_ptr == nullptr) {
|
||||
EGAMI_ERROR("Can not Allocate PNG structure");
|
||||
fileName.fileClose();
|
||||
return out;
|
||||
}
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == nullptr) {
|
||||
EGAMI_ERROR("Can not Allocate PNG info structure");
|
||||
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
|
||||
fileName.fileClose();
|
||||
return out;
|
||||
}
|
||||
/*
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
EGAMI_ERROR(" Can not set the JUMP buffer adresses");
|
||||
// Free all of the memory associated with the png_ptr and info_ptr
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||
fileName.fileClose();
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
ReaderInstanceFSNode tmpNode(fileName);
|
||||
|
||||
ReaderInstance* tmpPoiter = &tmpNode;
|
||||
|
||||
// overwrite the read and write function :
|
||||
png_set_read_fn(png_ptr,
|
||||
tmpPoiter,
|
||||
&local_ReadData);
|
||||
/*
|
||||
png_set_write_fn(png_ptr,
|
||||
&fileName,
|
||||
&LocalWriteData,
|
||||
&localFlushData);
|
||||
*/
|
||||
out = genericLoader(png_ptr, info_ptr);
|
||||
fileName.fileClose();
|
||||
return out;
|
||||
}
|
||||
|
||||
egami::Image egami::loadPNG(const std::vector<uint8_t>& _buffer) {
|
||||
egami::Image out;
|
||||
unsigned char header[8];
|
||||
if (png_sig_cmp(&_buffer[0], 0, 8)) {
|
||||
EGAMI_ERROR("Invalid start buffer:");
|
||||
return out;
|
||||
}
|
||||
|
||||
// PNG read setup
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, user_error_fn, user_warning_fn);
|
||||
if (png_ptr == nullptr) {
|
||||
EGAMI_ERROR("Can not Allocate PNG structure");
|
||||
return out;
|
||||
}
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == nullptr) {
|
||||
EGAMI_ERROR("Can not Allocate PNG info structure");
|
||||
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
|
||||
return out;
|
||||
}
|
||||
egami::ReaderInstanceBuffer tmpNode(_buffer, 8);
|
||||
|
||||
egami::ReaderInstance* tmpPoiter = &tmpNode;
|
||||
|
||||
// overwrite the read and write function :
|
||||
png_set_read_fn(png_ptr,
|
||||
tmpPoiter,
|
||||
&local_ReadData);
|
||||
out = genericLoader(png_ptr, info_ptr);
|
||||
return out;
|
||||
}
|
||||
|
@ -14,5 +14,11 @@ namespace egami {
|
||||
* @return Read Image.
|
||||
*/
|
||||
egami::Image loadPNG(const std::string& _fileName);
|
||||
/**
|
||||
* @breif Load a png file in the image.
|
||||
* @param[in] _buffer File buffer.
|
||||
* @return Read Image.
|
||||
*/
|
||||
egami::Image loadPNG(const std::vector<uint8_t>& _buffer);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user