149 lines
3.8 KiB
C++
149 lines
3.8 KiB
C++
/**
|
|
* @author Edouard DUPIN
|
|
*
|
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
*
|
|
* @license BSD v3 (see license file)
|
|
*/
|
|
|
|
#include <etk/types.h>
|
|
#include <egami/debug.h>
|
|
#include <egami/Image.h>
|
|
#include <egami/wrapperPNG.h>
|
|
#include <etk/os/FSNode.h>
|
|
#include <png/png.h>
|
|
|
|
|
|
#undef __class__
|
|
#define __class__ "wrapperPNG"
|
|
|
|
// 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 (NULL!=fileNode) {
|
|
fileNode->fileRead(data, 1, length);
|
|
}
|
|
}
|
|
/*
|
|
static void LocalWriteData(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 (NULL!=fileNode) {
|
|
fileNode->FileWrite(data, 1, length);
|
|
}
|
|
}
|
|
|
|
static void localFlushData(png_structp png_ptr)
|
|
{
|
|
etk::FSNode* fileNode = static_cast<etk::FSNode*>(png_get_io_ptr(png_ptr));
|
|
if (NULL!=fileNode) {
|
|
fileNode->FileFlush();
|
|
}
|
|
}
|
|
*/
|
|
|
|
bool egami::loadPNG(const etk::UString& _inputFile, egami::Image& _ouputImage) {
|
|
etk::FSNode fileName(_inputFile);
|
|
|
|
if (false == fileName.exist()) {
|
|
EGAMI_ERROR("File does not existed=\"" << fileName << "\"");
|
|
return false;
|
|
}
|
|
if(false == fileName.fileOpenRead() ) {
|
|
EGAMI_ERROR("Can not find the file name=\"" << fileName << "\"");
|
|
return false;
|
|
}
|
|
|
|
// Vars
|
|
int x, y = 0;
|
|
int rowbytes;
|
|
unsigned char header[8];
|
|
png_infop info_ptr;
|
|
png_structp png_ptr;
|
|
png_bytep * row_pointers;
|
|
|
|
if (fileName.fileRead(header,1,8) != 8) {
|
|
EGAMI_ERROR("error loading file header");
|
|
fileName.fileClose();
|
|
return false;
|
|
}
|
|
if (png_sig_cmp(header, 0, 8)) {
|
|
EGAMI_ERROR("Invalid file :" << fileName);
|
|
return false;
|
|
}
|
|
|
|
// PNG read setup
|
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
info_ptr = png_create_info_struct(png_ptr);
|
|
setjmp(png_jmpbuf(png_ptr));
|
|
// overwrite the read and write function :
|
|
#if 1
|
|
png_set_read_fn(png_ptr,
|
|
&fileName,
|
|
&local_ReadData);
|
|
/*
|
|
png_set_write_fn(png_ptr,
|
|
&fileName,
|
|
&LocalWriteData,
|
|
&localFlushData);
|
|
*/
|
|
#else
|
|
png_init_io(png_ptr, fp);
|
|
#endif
|
|
png_set_sig_bytes(png_ptr, 8);
|
|
png_read_info(png_ptr, info_ptr);
|
|
int32_t width = png_get_image_width(png_ptr, info_ptr);
|
|
int32_t height = png_get_image_height(png_ptr, info_ptr);
|
|
// reallocate the image
|
|
EGAMI_DEBUG("Load PNG image : (" << width << "," << height << ")" );
|
|
_ouputImage.resize(ivec2(width,height));
|
|
|
|
int32_t bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
|
png_read_update_info(png_ptr, info_ptr);
|
|
setjmp(png_jmpbuf(png_ptr));
|
|
row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
|
|
rowbytes = width * ((bit_depth == 16) ? 8 : 4);
|
|
|
|
// File read
|
|
for (y = 0; y < height; y++) {
|
|
row_pointers[y] = (png_byte*) malloc(rowbytes);
|
|
}
|
|
png_read_image(png_ptr, row_pointers);
|
|
png_set_expand(png_ptr);
|
|
png_set_strip_16(png_ptr);
|
|
|
|
etk::Color<> tmpColor(0,0,0,0);
|
|
switch (png_get_color_type(png_ptr, info_ptr) ) {
|
|
case PNG_COLOR_TYPE_RGBA:
|
|
// Conversion to OpenGL texture
|
|
for (y = 0; y < height; y++) {
|
|
png_byte* row = row_pointers[y];
|
|
for (x = 0; x < width; x++) {
|
|
png_byte* ptr = &(row[x*4]);
|
|
tmpColor.set(ptr[0], ptr[1],ptr[2],ptr[3]);
|
|
_ouputImage.set(ivec2(x,y), tmpColor);
|
|
}
|
|
delete row_pointers[y];
|
|
}
|
|
break;
|
|
case PNG_COLOR_TYPE_RGB:
|
|
// Conversion to OpenGL texture
|
|
for (y = 0; y < height; y++) {
|
|
png_byte* row = row_pointers[y];
|
|
for (x = 0; x < width; x++) {
|
|
png_byte* ptr = &(row[x*3]);
|
|
tmpColor.set(ptr[0], ptr[1],ptr[2]);
|
|
_ouputImage.set(ivec2(x,y), tmpColor);
|
|
}
|
|
delete row_pointers[y];
|
|
}
|
|
break;
|
|
default:
|
|
EGAMI_ERROR("Must be RGBA/RGB");
|
|
return false;
|
|
}
|
|
fileName.fileClose();
|
|
return true;
|
|
}
|
|
|