From 1181bc52e779505c5e5898128e603fb353366401 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Sun, 25 Jun 2017 15:00:33 +0200 Subject: [PATCH] [DEV] add an API to load raw buffer --- egami/Image.cpp | 46 +++++--- egami/Image.hpp | 3 + egami/egami.cpp | 33 ++++++ egami/egami.hpp | 14 +++ egami/wrapperBMP.cpp | 78 ++++++------- egami/wrapperBMP.hpp | 6 + egami/wrapperJPG.cpp | 13 ++- egami/wrapperJPG.hpp | 6 + egami/wrapperPNG.cpp | 255 ++++++++++++++++++++++++++++--------------- egami/wrapperPNG.hpp | 6 + 10 files changed, 304 insertions(+), 156 deletions(-) diff --git a/egami/Image.cpp b/egami/Image.cpp index 67aec24..92ba603 100644 --- a/egami/Image.cpp +++ b/egami/Image.cpp @@ -9,6 +9,11 @@ #include #include +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,22 +219,25 @@ const ivec2& egami::Image::getSize() const { return m_data->getSize(); } -/** - * @brief get the next power 2 if the input - * @param[in] value Value that we want the next power of 2 - * @return result value - */ -static int32_t nextP2(int32_t _value) { - int32_t val=1; - for (int32_t iii=1; iii<31; iii++) { - if (_value <= val) { - return val; +#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 + * @return result value + */ + static int32_t nextP2(int32_t _value) { + int32_t val=1; + for (int32_t iii=1; iii<31; iii++) { + if (_value <= val) { + return val; + } + val *=2; } - val *=2; + EGAMI_CRITICAL("impossible CASE...."); + return val; } - EGAMI_CRITICAL("impossible CASE...."); - return val; -} +#endif ivec2 egami::Image::getGPUSize() const { if (m_data == nullptr) { diff --git a/egami/Image.hpp b/egami/Image.hpp index 0e43048..5dcff40 100644 --- a/egami/Image.hpp +++ b/egami/Image.hpp @@ -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>& _data, const ivec2& _size); void set(const std::vector>& _data, const ivec2& _size); }; + std::ostream& operator <<(std::ostream& _os, const egami::Image& _obj); } diff --git a/egami/egami.cpp b/egami/egami.cpp index a34fbb3..5c3a1bb 100644 --- a/egami/egami.cpp +++ b/egami/egami.cpp @@ -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& _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); diff --git a/egami/egami.hpp b/egami/egami.hpp index 149f376..41fdbcb 100644 --- a/egami/egami.hpp +++ b/egami/egami.hpp @@ -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& _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& _buffer); /** * @brief know if a file can have multiple size definition. * @param[in] _fileName Name of the file. diff --git a/egami/wrapperBMP.cpp b/egami/wrapperBMP.cpp index 16990c5..2cf5d2a 100644 --- a/egami/wrapperBMP.cpp +++ b/egami/wrapperBMP.cpp @@ -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 allData = fileName.fileReadAll(); + fileName.fileClose(); + return egami::loadBMP(allData); +} + +egami::Image egami::loadBMP(const std::vector& _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 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> 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> 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& _buffer); /** * @breif Store a bmp file in the image. * @param[in] _fileName Name of the file. diff --git a/egami/wrapperJPG.cpp b/egami/wrapperJPG.cpp index d619ef9..e4855aa 100644 --- a/egami/wrapperJPG.cpp +++ b/egami/wrapperJPG.cpp @@ -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 allData = fileName.fileReadAll(); fileName.fileClose(); - + return egami::loadJPG(allData); +} + +egami::Image egami::loadJPG(const std::vector& _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); diff --git a/egami/wrapperJPG.hpp b/egami/wrapperJPG.hpp index 2d3a352..8587583 100644 --- a/egami/wrapperJPG.hpp +++ b/egami/wrapperJPG.hpp @@ -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& _buffer); } diff --git a/egami/wrapperPNG.cpp b/egami/wrapperPNG.cpp index dd871a3..09c0321 100644 --- a/egami/wrapperPNG.cpp +++ b/egami/wrapperPNG.cpp @@ -10,12 +10,47 @@ #include #include #include - +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& m_data; + int32_t m_offset; + public: + ReaderInstanceBuffer(const std::vector& _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(png_get_io_ptr(png_ptr)); - if (fileNode != nullptr) { - fileNode->fileRead(data, 1, length); + egami::ReaderInstance* instance = static_cast(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& _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; +} diff --git a/egami/wrapperPNG.hpp b/egami/wrapperPNG.hpp index f042943..0d27ad9 100644 --- a/egami/wrapperPNG.hpp +++ b/egami/wrapperPNG.hpp @@ -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& _buffer); }