X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fgraphics%2Fimage.cpp;h=5d2a21bb66e969d85da76f34811d4ff5e1f9836b;hb=f608cc1e681e16e21325df56cb96d3f17a348e21;hp=3360b72e7610d0cdf68eb8d9e75a6993682e1a91;hpb=1023b38fa278cea71fba3d2881e1bfde930cd025;p=libs%2Fgui.git diff --git a/source/graphics/image.cpp b/source/graphics/image.cpp index 3360b72..5d2a21b 100644 --- a/source/graphics/image.cpp +++ b/source/graphics/image.cpp @@ -1,130 +1,28 @@ #ifdef WITH_DEVIL #include #endif -#ifdef WITH_LIBPNG -#include +#include #include #include -#endif #include "image.h" +#include "image_devil.h" +#include "image_png.h" +#include "image_private.h" using namespace std; namespace Msp { namespace Graphics { -struct Image::Private -{ -#ifdef WITH_DEVIL - unsigned id; -#endif -#ifdef WITH_LIBPNG - PixelFormat fmt; - unsigned width; - unsigned height; - char *data; -#endif - - Private(); -}; - Image::Private::Private() { #ifdef WITH_DEVIL id = 0; #endif -#ifdef WITH_LIBPNG fmt = RGB; width = 0; height = 0; data = 0; -#endif -} - - -namespace { - -#ifdef WITH_LIBPNG -void read(png_struct *png, png_byte *data, png_size_t size) -{ - IO::Base *in = reinterpret_cast(png_get_io_ptr(png)); - in->read(reinterpret_cast(data), size); -} - -void load_png(IO::Base &in, Image::Private &priv) -{ - png_struct *png = 0; - png_info *info = 0; - priv.data = 0; - - try - { - png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); - info = png_create_info_struct(png); - - if(setjmp(png_jmpbuf(png))) - throw bad_image_data("PNG error"); - - png_set_read_fn(png, &in, read); - png_read_info(png, info); - png_uint_32 width; - png_uint_32 height; - int depth; - int color; - png_get_IHDR(png, info, &width, &height, &depth, &color, 0, 0, 0); - priv.width = width; - priv.height = height; - if(depth!=8) - throw unsupported_image_format("depth!=8"); - switch(color) - { - case PNG_COLOR_TYPE_PALETTE: priv.fmt = COLOR_INDEX; break; - case PNG_COLOR_TYPE_GRAY: priv.fmt = LUMINANCE; break; - case PNG_COLOR_TYPE_GRAY_ALPHA: priv.fmt = LUMINANCE_ALPHA; break; - case PNG_COLOR_TYPE_RGB: priv.fmt = RGB; break; - case PNG_COLOR_TYPE_RGB_ALPHA: priv.fmt = RGBA; break; - default: throw unsupported_image_format("unknown color type"); - } - - unsigned nchans = png_get_channels(png, info); - if(nchans==4 && priv.fmt==RGB) - png_set_strip_alpha(png); - - unsigned rowstride = priv.width*nchans; - priv.data = new char[rowstride*priv.height]; - for(unsigned y=0; y(priv.data+rowstride*(priv.height-1-y)), 0); - - png_read_end(png, 0); - png_destroy_read_struct(&png, &info, 0); - } - catch(...) - { - png_destroy_read_struct(&png, &info, 0); - delete[] priv.data; - throw; - } -} -#endif - -#ifdef WITH_DEVIL -void ensure_devil_image(unsigned &id) -{ - static bool init_done = false; - - if(!init_done) - { - ilInit(); - ilEnable(IL_ORIGIN_SET); - ilOriginFunc(IL_ORIGIN_LOWER_LEFT); - init_done = true; - } - - if(!id) - ilGenImages(1, &id); -} -#endif - } @@ -141,17 +39,17 @@ Image::~Image() #ifdef WITH_DEVIL if(priv->id) ilDeleteImages(1, &priv->id); + else #endif -#ifdef WITH_LIBPNG delete[] priv->data; -#endif delete priv; } void Image::load_file(const string &fn) { + string ext = FS::extpart(fn); #ifdef WITH_LIBPNG - if(fn.size()>4 && !fn.compare(fn.size()-4, 4, ".png")) + if(ext==".png") { IO::BufferedFile file(fn); load_png(file, *priv); @@ -160,10 +58,7 @@ void Image::load_file(const string &fn) #endif { #ifdef WITH_DEVIL - ensure_devil_image(priv->id); - ilBindImage(priv->id); - if(!ilLoadImage(const_cast(fn.c_str()))) - throw bad_image_data("IL error"); + load_devil_file(fn, *priv); #else throw unsupported_image_format("DevIL needed for non-PNG images"); #endif @@ -174,7 +69,7 @@ void Image::load_file(const string &fn) void Image::load_memory(const void *data, unsigned size) { #ifdef WITH_LIBPNG - if(!png_sig_cmp(reinterpret_cast(const_cast(data)), 0, 8)) + if(size>=8 && is_png(data, 8)) { IO::Memory mem(reinterpret_cast(data), size); load_png(mem, *priv); @@ -183,10 +78,7 @@ void Image::load_memory(const void *data, unsigned size) #endif { #ifdef WITH_DEVIL - ensure_devil_image(priv->id); - ilBindImage(priv->id); - if(!ilLoadL(IL_TYPE_UNKNOWN, const_cast(data), size)) - throw bad_image_data("IL error"); + load_devil_mem(data, size, *priv); #else throw unsupported_image_format("DevIL needed for non-PNG images"); #endif @@ -197,77 +89,22 @@ void Image::load_memory(const void *data, unsigned size) PixelFormat Image::get_format() const { -#ifdef WITH_LIBPNG - if(priv->data) - return priv->fmt; -#endif -#ifdef WITH_DEVIL - if(priv->id) - { - ilBindImage(priv->id); - switch(ilGetInteger(IL_IMAGE_FORMAT)) - { - case IL_COLOR_INDEX: return COLOR_INDEX; - case IL_LUMINANCE: return LUMINANCE; - case IL_LUMINANCE_ALPHA: return LUMINANCE_ALPHA; - case IL_RGB: return RGB; - case IL_RGBA: return RGBA; - case IL_BGR: return BGR; - case IL_BGRA: return BGRA; - // XXX bad, should throw when loading - default: throw invalid_argument("unknown pixel format in image"); - } - } -#endif - return RGB; + return priv->fmt; } unsigned Image::get_width() const { -#ifdef WITH_LIBPNG - if(priv->data) - return priv->width; -#endif -#ifdef WITH_DEVIL - if(priv->id) - { - ilBindImage(priv->id); - return ilGetInteger(IL_IMAGE_WIDTH); - } -#endif - return 0; + return priv->width; } unsigned Image::get_height() const { -#ifdef WITH_LIBPNG - if(priv->data) - return priv->height; -#endif -#ifdef WITH_DEVIL - if(priv->id) - { - ilBindImage(priv->id); - return ilGetInteger(IL_IMAGE_HEIGHT); - } -#endif - return 0; + return priv->height; } const void *Image::get_data() const { -#ifdef WITH_LIBPNG - if(priv->data) - return priv->data; -#endif -#ifdef WITH_DEVIL - if(priv->id) - { - ilBindImage(priv->id); - return ilGetData(); - } -#endif - return 0; + return priv->data; } } // namespace Graphics