[DEV] add an API to load raw buffer

This commit is contained in:
Edouard DUPIN 2017-06-25 15:00:33 +02:00
parent f345c9c664
commit 1181bc52e7
10 changed files with 304 additions and 156 deletions

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);

View File

@ -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.

View 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++);

View File

@ -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.

View 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);

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}