From: Mikko Rasa Date: Fri, 26 Aug 2011 11:49:07 +0000 (+0300) Subject: Separate PNG loading to a separate file X-Git-Url: http://git.tdb.fi/?p=libs%2Fgui.git;a=commitdiff_plain;h=cc728fda1325c5358f3ec177d31621b5688371fe Separate PNG loading to a separate file --- diff --git a/source/graphics/image.cpp b/source/graphics/image.cpp index 3360b72..56e7c1b 100644 --- a/source/graphics/image.cpp +++ b/source/graphics/image.cpp @@ -1,33 +1,17 @@ #ifdef WITH_DEVIL #include #endif -#ifdef WITH_LIBPNG -#include #include #include -#endif #include "image.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 @@ -44,69 +28,6 @@ Image::Private::Private() 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) { @@ -174,7 +95,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); diff --git a/source/graphics/image.h b/source/graphics/image.h index db65010..bc7151b 100644 --- a/source/graphics/image.h +++ b/source/graphics/image.h @@ -1,6 +1,7 @@ #ifndef MSP_GRAPHICS_IMAGE_H_ #define MSP_GRAPHICS_IMAGE_H_ +#include #include #include "pixelformat.h" diff --git a/source/graphics/image_png.cpp b/source/graphics/image_png.cpp new file mode 100644 index 0000000..256159c --- /dev/null +++ b/source/graphics/image_png.cpp @@ -0,0 +1,82 @@ +#ifdef WITH_LIBPNG +#include +#include "image_png.h" +#include "image_private.h" + +namespace { + +void read(png_struct *png, png_byte *data, png_size_t size) +{ + Msp::IO::Base *in = reinterpret_cast(png_get_io_ptr(png)); + in->read(reinterpret_cast(data), size); +} + +} + + +namespace Msp { +namespace Graphics { + +bool is_png(const void *buf, unsigned len) +{ + return !png_sig_cmp(reinterpret_cast(const_cast(buf)), 0, len); +} + +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; + } +} + +} // namespace Graphics +} // namespace Msp +#endif diff --git a/source/graphics/image_png.h b/source/graphics/image_png.h new file mode 100644 index 0000000..e07536a --- /dev/null +++ b/source/graphics/image_png.h @@ -0,0 +1,18 @@ +#ifndef MSP_GRAPHICS_IMAGE_PNG_H_ +#define MSP_GRAPHICS_IMAGE_PNG_H_ + +#include +#include "image.h" + +namespace Msp { +namespace Graphics { + +#ifdef WITH_LIBPNG +bool is_png(const void *, unsigned); +void load_png(IO::Base &, Image::Private &); +#endif + +} // namespace Graphics +} // namespace Msp + +#endif diff --git a/source/graphics/image_private.h b/source/graphics/image_private.h new file mode 100644 index 0000000..19f0cef --- /dev/null +++ b/source/graphics/image_private.h @@ -0,0 +1,27 @@ +#ifndef MSP_GRAPHICS_IMAGE_PRIVATE_H_ +#define MSP_GRAPHICS_IMAGE_PRIVATE_H_ + +#include "image.h" + +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(); +}; + +} // namespace Graphics +} // namespace Msp + +#endif