Commits

Christian Fischer  committed 3532f94

moving image loading from engine into seperate module

  • Participants
  • Parent commits dc4d813

Comments (0)

Files changed (24)

File libraries/desktop/wiesel-common/module.cmake

 else()
 	message(FATAL_ERROR "required library SDL not found!")
 endif()
-
-
-# add SDL_image dependency
-include(FindSDL_image)
-
-if(DEFINED SDL_FOUND)
-	wiesel_target_add_libraries(wiesel-common ${SDLIMAGE_LIBRARY})
-else()
-	message(FATAL_ERROR "required library SDL not found!")
-endif()

File libraries/desktop/wiesel-sdl/module.cmake

+# wiesel-sdl library
+
+
+# create the SDL module
+wiesel_create_module(wiesel-sdl ${WIESEL_SRC_DIR}/sdl ${WIESEL_TESTS_DIR}/sdl)
+
+# add required modules
+wiesel_module_add_dependency(wiesel-sdl wiesel-base)
+wiesel_module_add_dependency(wiesel-sdl wiesel-common)
+#wiesel_module_add_dependency(wiesel-sdl glee third-party/glee)
+
+
+
+# add SDL dependency
+include(FindSDL)
+
+if(DEFINED SDL_FOUND)
+	wiesel_target_add_includes(wiesel-sdl ${SDL_INCLUDE_DIR})
+	wiesel_target_add_libraries(wiesel-sdl ${SDL_LIBRARY})
+	wiesel_target_add_compileflags(wiesel-sdl "-DWIESEL_USE_LIBSDL")
+else()
+	message(FATAL_ERROR "required library SDL not found!")
+endif()
+
+
+# add SDL_image dependency
+include(FindSDL_image)
+
+if(DEFINED SDLIMAGE_FOUND)
+	wiesel_target_add_libraries(wiesel-sdl ${SDLIMAGE_LIBRARY})
+else()
+	message(FATAL_ERROR "required library SDL_image not found!")
+endif()

File samples/HelloWiesel/CMakeLists.txt

 # add required libraries
 wiesel_module_add_dependency(HelloWiesel wiesel-base)
 wiesel_module_add_dependency(HelloWiesel wiesel-common)
+wiesel_module_add_dependency(HelloWiesel wiesel-sdl)
 
 wiesel_target_add_compileflags(HelloWiesel "-DWIESEL_USE_LIBSDL")
 

File src/common/wiesel/engine.h

 	public:
 		virtual TouchHandler *getTouchHandler() = 0;
 
-	// stuff
-	public:
-		/**
-		 * @brief decodes an image from file into a buffer.
-		 * Takes care of power-of-two size.
-		 * @param data				A \ref DataSource, the image data will be loaded from.
-		 * @param pBuffer			A buffer to receive the image data.
-		 * @param pSize				A pointer to receive the size of the buffer.
-		 * @param pWidth			A pointer to receive the dimension of the image.
-		 * @param pHeight			A pointer to receive the dimension of the image.
-		 * @param pOriginalWidth	A pointer to receive the original dimension of the image, if it was resized to match pot-size.
-		 * @param pOriginalHeight	A pointer to receive the original dimension of the image, if it was resized to match pot-size.
-		 * @param p*Bits			Points to store the bit size of each RGBA component.
-		 * 							If non-zero, the implementation should try to force the bit-size to the given value.
-		 * @param as_textzre		When \c true, the implementation may try to fit the texture into required parameters.
-		 */
-		virtual bool decodeImage(
-								DataSource *data,
-								unsigned char **pBuffer, size_t *pSize,
-								unsigned int *pWidth, unsigned int *pHeight,
-								unsigned int *pOriginalWidth, unsigned int *pOriginalHeight,
-								int *pRbits, int *pGbits, int *pBbits, int *pAbits,
-								bool as_texture
-		) = 0;
-
 	// static members
 	private:
 		static WIESEL_COMMON_EXPORT Engine*			    current_instance;

File src/common/wiesel/gl/texture/texture.cpp

  */
 #include "texture.h"
 #include <wiesel.h>
-#include <wiesel/util/imageutils.h>
-#include <malloc.h>
+#include <wiesel/resources/graphics/image.h>
+#include <wiesel/resources/graphics/imageutils.h>
+#include <wiesel/resources/graphics/image_loader.h>
+#include <wiesel/modules.h>
 
 
 using namespace wiesel;
 
 	// release the previous buffer
 	release_texture();
+	
+	Image *image = NULL;
+	dimension new_original_size;
 
-	unsigned char*	buffer		= NULL;
-	size_t			buffer_size	= 0;
-	unsigned int	width		= 0;
-	unsigned int	height		= 0;
-	unsigned int	orig_width	= 0;
-	unsigned int	orig_height	= 0;
-	int				r_bits		= 0;
-	int				g_bits		= 0;
-	int				b_bits		= 0;
-	int				a_bits		= 0;
+	std::vector<ModuleLoader<IImageLoader>*> loaders = ModuleRegistry::getInstance()->findModules<IImageLoader>();
+	for(std::vector<ModuleLoader<IImageLoader>*>::iterator it=loaders.begin(); it!=loaders.end(); it++) {
+		IImageLoader *loader = (*it)->create();
+		if (loader == NULL) {
+			continue;
+		}
 
-	bool successful = Engine::getCurrent()->decodeImage(
-												data,
-												&buffer, &buffer_size,
-												&width, &height,
-												&orig_width, &orig_height,
-												&r_bits, &g_bits, &b_bits, &a_bits,
-												true
-	);
+		image = loader->loadPowerOfTwoImage(data, &new_original_size);
+		if (image == NULL) {
+			continue;
+		}
 
-	// compute the byte-size of the image
-	int bytesPerPixel = (r_bits + g_bits + b_bits + a_bits) / 8;
+		break;
+	}
 
-	unsigned int texture_width	= width;
-	unsigned int texture_height	= height;
+	// check if loading was successful
+	if (image == NULL) {
+		return false;
+	}
 
-	if (successful && buffer) {
-		// when power-of-two sizes are required, compute the next pot-size of the texture
-		texture_width	= imageutils::getNextPowerOfTwo(texture_width);
-		texture_height	= imageutils::getNextPowerOfTwo(texture_height);
+	// ensure power-of-two size
+	if (image->ensurePowerOfTwo() == false) {
+		return false;
+	}
 
-		if ((texture_width != width) || (texture_height != height)) {
-			unsigned char *new_buffer = imageutils::resizeImage(
-											buffer, bytesPerPixel,
-											width,			height,
-											texture_width,	texture_height
-			);
+	GLint internalFormat;
+	GLenum image_format;
+	GLenum image_type;
 
-			// something went wrong - so delete the current buffer
-			if (new_buffer == NULL) {
-				successful = false;
-				free(buffer);
-			}
+	switch(image->getPixelFormat()) {
+		case PixelFormat_RGBA_8888: {
+			internalFormat = GL_RGBA;
+			image_format   = GL_RGBA;
+			image_type     = GL_UNSIGNED_BYTE;
+			break;
+		}
 
-			buffer = new_buffer;
+		case PixelFormat_RGB_888: {
+			internalFormat = GL_RGB;
+			image_format   = GL_RGB;
+			image_type     = GL_UNSIGNED_BYTE;
+			break;
 		}
 	}
 
-	if (successful && buffer) {
-		// create the hardware texture
-		glGenTextures(1, &handle);
-		glBindTexture(GL_TEXTURE_2D, handle);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_width, texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
-		size          = dimension(texture_width, texture_height);
-		original_size = dimension(orig_width,    orig_height);
-	}
+	// create the hardware texture
+	glGenTextures(1, &handle);
+	glBindTexture(GL_TEXTURE_2D, handle);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
-	if (buffer) {
-		free(buffer);
-	}
+	glTexImage2D(
+					GL_TEXTURE_2D, 0,
+					internalFormat,
+					image->getSize().width, image->getSize().height,
+					0,
+					image_format, image_type,
+					image->getPixelData()->getData()
+	);
 
-	return successful;
+	size          = image->getSize();
+	original_size = new_original_size;
+
+	return true;
 }
 
 

File src/common/wiesel/io/databuffer.cpp

  * Boston, MA 02110-1301 USA
  */
 #include "databuffer.h"
+#include <malloc.h>
 #include <string.h>
 
 using namespace wiesel;
 
 
 
+ExclusiveDataBuffer *ExclusiveDataBuffer::create(size_t size) {
+	mutable_data_t data = new unsigned char[size];
+	if (data) {
+		return new ExclusiveDataBuffer(data, size);
+	}
+
+	return NULL;
+}
+
+
 ExclusiveDataBuffer *ExclusiveDataBuffer::createCopyOf(data_t data, size_t size) {
 	unsigned char *new_buffer = new unsigned char[size];
 	memcpy(new_buffer, data, size);
 }
 
 
+ExclusiveDataBuffer *ExclusiveDataBuffer::createCopyOf(const void* data, size_t size) {
+	return createCopyOf(reinterpret_cast<data_t>(data), size);
+}
+
+
 ExclusiveDataBuffer *ExclusiveDataBuffer::createCopyOf(const char* data, size_t size) {
 	return createCopyOf(reinterpret_cast<data_t>(data), size);
 }
 }
 
 
-ExclusiveDataBuffer::ExclusiveDataBuffer(data_t data, size_t size)
+ExclusiveDataBuffer::ExclusiveDataBuffer(mutable_data_t data, size_t size)
 : data(data), size(size)
 {
 	return;
 	}
 }
 
+ExclusiveDataBuffer::mutable_data_t ExclusiveDataBuffer::getMutableData() {
+	return data;
+}
+
 ExclusiveDataBuffer::data_t ExclusiveDataBuffer::getData() const {
 	return data;
 }
 }
 
 
+bool ExclusiveDataBuffer::resize(size_t new_size) {
+	mutable_data_t new_data = reinterpret_cast<mutable_data_t>(realloc(data, new_size));
+
+	if (new_data) {
+		data = new_data;
+		return true;
+	}
+
+	return false;
+}
+
+
 
 
 
 	// data is an external reference, so it will not be destroyed!
 }
 
+SharedDataBuffer::mutable_data_t SharedDataBuffer::getMutableData() {
+	// changing a shared buffer's content is forbidden, so we return a \c NULL pointer.
+	return NULL;
+}
+
 SharedDataBuffer::data_t SharedDataBuffer::getData() const {
 	return data;
 }
 	return size;
 }
 
+bool SharedDataBuffer::resize(size_t) {
+	// resizing is not supported, because the data is shared with other code
+	return false;
+}
+

File src/common/wiesel/io/databuffer.h

 		DataBuffer();
 
 	public:
+		typedef unsigned char* mutable_data_t;
 		typedef const unsigned char* data_t;
 
 		virtual ~DataBuffer();
 
 		/**
+		 * @brief Receive a pointer to the mutable data.
+		 * The content of this pointer is mutable and can be modified.
+		 * It's not guaranteed, that mutable data is available on all buffers.
+		 * A buffer may return \c NULL, if it's data should not be changed.
+		 * It depends on the buffer's implementation, if the content
+		 * is accessible after the buffer's release.
+		 * The application should not use this pointer after the
+		 * object was released.
+		 */
+		virtual mutable_data_t getMutableData() = 0;
+
+		/**
 		 * @brief Receive a pointer to the data buffer.
 		 * It depends on the buffer's implementation, if the content
 		 * is accessible after the buffer's release.
 		 * object was released.
 		 */
 		virtual const char *getDataAsCharPtr() const;
+
+	public:
+		/**
+		 * @brief Change the size of the data buffer.
+		 * Resizing is not supported by all buffers. The function will
+		 * return \c false when resizing failed.
+		 * @return \c true, when the buffer was resized, \c false on fail.
+		 */
+		virtual bool resize(size_t new_size) = 0;
 	};
 
 
 
 	public:
 		/**
+		 * @brief Creates a new \ref DataBuffer of a specific size.
+		 * The created buffer's data will be uninitialized.
+		 * @param size	The size of the buffer to create.
+		 * @return A new \ref DataBuffer or \c NULL on fail.
+		 */
+		static ExclusiveDataBuffer *create(size_t size);
+
+		/**
 		 * @brief Creates a new \ref DataBuffer with a copy of \c data.
 		 */
 		static ExclusiveDataBuffer *createCopyOf(data_t data, size_t size);
 		/**
 		 * @brief Creates a new \ref DataBuffer with a copy of \c data.
 		 */
+		static ExclusiveDataBuffer *createCopyOf(const void *data, size_t size);
+
+		/**
+		 * @brief Creates a new \ref DataBuffer with a copy of \c data.
+		 */
 		static ExclusiveDataBuffer *createCopyOf(const char *data, size_t size);
 
 		/**
 		 * will be destroyed.
 		 * To create a copy of an existing buffer use \ref ExclusiveDataBuffer::copyOf(data_t,size_t).
 		 */
-		ExclusiveDataBuffer(data_t data, size_t size);
+		ExclusiveDataBuffer(mutable_data_t data, size_t size);
 		~ExclusiveDataBuffer();
 
+		virtual mutable_data_t getMutableData();
 		virtual data_t getData() const;
 		virtual size_t getSize() const;
 
+		virtual bool resize(size_t size);
+
 	private:
-		data_t	data;
-		size_t	size;
+		mutable_data_t	data;
+		size_t			size;
 	};
 
 
 		SharedDataBuffer(data_t data, size_t size);
 		~SharedDataBuffer();
 
+		virtual mutable_data_t getMutableData();
 		virtual data_t getData() const;
 		virtual size_t getSize() const;
 
+		virtual bool resize(size_t size);
+
 	private:
 		data_t	data;
 		size_t	size;

File src/common/wiesel/io/datasource.cpp

 	}
 }
 
-BufferDataSource::BufferDataSource(DataBuffer::data_t data, size_t size)
+BufferDataSource::BufferDataSource(DataBuffer::mutable_data_t data, size_t size)
 : buffer(new ExclusiveDataBuffer(data, size))
 {
 	buffer->retain();

File src/common/wiesel/io/datasource.h

 		/**
 		 * @brief Creates a new \ref BufferDataSource with existing data.
 		 */
-		BufferDataSource(DataBuffer::data_t data, size_t size);
+		BufferDataSource(DataBuffer::mutable_data_t data, size_t size);
 
 		/**
 		 * @brief Creates a new \ref BufferDataSource with an existing \ref DataBuffer.

File src/common/wiesel/modules.h

 #include <vector>
 
 
+#include <wiesel/util/log.h>
+#include <ios>
+
 
 /**
  * @brief Registers a new module class.
 #define REGISTER_MODULE(interface_class, implementation_class, factory, api, api_version, priotiry) \
 	ModuleLoaderImpl<interface_class, implementation_class> implementation_class##_Loader(factory, api, api_version, priotiry);
 
-
 /**
  * @brief Registers a new module class.
  * Each time the module is requested, a new instance will be created.
 	class WIESEL_COMMON_EXPORT IModuleLoader;
 
 	template <class INTERFACE_CLASS>
-	class WIESEL_COMMON_EXPORT ModuleLoader;
+	class ModuleLoader;
 
-	template <class INTERFACE_CLASS, class IMPLEMENTATION_CLASS>
-	class WIESEL_COMMON_EXPORT ModuleLoaderImpl;
-
-	bool SortModuleLoadersPredicate(IModuleLoader *a, IModuleLoader *b);
+	bool WIESEL_COMMON_EXPORT SortModuleLoadersPredicate(IModuleLoader *a, IModuleLoader *b);
 
 
 
 		template <class INTERFACE_CLASS>
 		INTERFACE_CLASS* createFirst() const {
 			std::vector<ModuleLoader<INTERFACE_CLASS>*> loaders = findModules<INTERFACE_CLASS>();
-			for(std::vector<ModuleLoader<INTERFACE_CLASS>*>::iterator it=loeaders.begin(); it!=loaders.end(); it++) {
+			for(typename std::vector<ModuleLoader<INTERFACE_CLASS>*>::iterator it=loaders.begin(); it!=loaders.end(); it++) {
 				INTERFACE_CLASS *module = (*it)->create();
 				if (module) {
 					return module;
 		virtual ~IModuleLoader() {}
 
 	public:
+		/**
+		 * @brief Get the API name, which is implemented by this module.
+		 */
 		inline const std::string& getApi() const {
 			return api;
 		}
 
+		/**
+		 * @brief Get the version number of the module's API implementation.
+		 * Modules with the same API will be ordered by their version number.
+		 * The version number will be displayed as hexadecimal numeric value,
+		 * for example version number 3.1.17 could be 0x03011700u.
+		 */
 		inline ApiVersion getApiVersion() const {
 			return version;
 		}
 
+		/**
+		 * @brief Get the priority value of this module.
+		 * Modules with a higher priority value should be preferred.
+		 */
 		inline Priority getPriority() const {
 			return priority;
 		}
 	 * @brief A class for loading a module of a specific interface.
 	 */
 	template <class INTERFACE_CLASS>
-	class WIESEL_COMMON_EXPORT ModuleLoader : public IModuleLoader
+	class ModuleLoader : public IModuleLoader
 	{
 	protected:
 		/**
 	 * This class would be usually be instanciated via macro \ref REGISTER_MODULE.
 	 */
 	template <class INTERFACE_CLASS, class IMPLEMENTATION_CLASS>
-	class WIESEL_COMMON_EXPORT ModuleLoaderImpl : public ModuleLoader<INTERFACE_CLASS>
+	class ModuleLoaderImpl : public ModuleLoader<INTERFACE_CLASS>
 	{
 	public:
 		/**
 		 * The loader will be automatically registered into module registry.
 		 * @see REGISTER_MODULE
 		 */
-		ModuleLoaderImpl(Factory factory, const std::string &api, IModuleLoader::ApiVersion version, IModuleLoader::Priority priority=IModuleLoader::PriorityNormal) :
+		ModuleLoaderImpl<INTERFACE_CLASS,IMPLEMENTATION_CLASS>(Factory factory, const std::string &api, unsigned int version, unsigned short priority=IModuleLoader::PriorityNormal) :
 		ModuleLoader<INTERFACE_CLASS>(api, version, priority) {
 			this->module_factory = factory;
 			return;
 	 * This class would be usually be instanciated via macro \ref REGISTER_MODULE.
 	 */
 	template <class INTERFACE_CLASS, class IMPLEMENTATION_CLASS>
-	class WIESEL_COMMON_EXPORT ModuleLoaderSingletonImpl : public ModuleLoader<INTERFACE_CLASS>
+	class ModuleLoaderSingletonImpl : public ModuleLoader<INTERFACE_CLASS>
 	{
 	public:
 		/**

File src/common/wiesel/platform/sdl/sdl_engine.cpp

 
 
 bool SdlEngine::onInit() {
-	int initialized = IMG_Init(IMG_INIT_PNG|IMG_INIT_JPG);
-	if((initialized & IMG_INIT_PNG) == 0) {
-		Log::err << "Loading libPNG failed." << std::endl;
-	}
-	if((initialized & IMG_INIT_JPG) == 0) {
-		Log::err << "Loading libJPG failed." << std::endl;
-	}
-
 	return true;
 }
 
 		screen = NULL;
 	}
 
-	IMG_Quit();
-
 	return;
 }
 
 	return touch_handler;
 }
 
-
-bool SdlEngine::decodeImage(
-		DataSource *data,
-		unsigned char **pBuffer, size_t *pSize,
-		unsigned int *pWidth, unsigned int *pHeight,
-		unsigned int *pOriginalWidth, unsigned int *pOriginalHeight,
-		int *pRbits, int *pGbits, int *pBbits, int *pAbits,
-		bool as_texture
-) {
-	SDL_Surface *surface = NULL;
-
-	FileDataSource *fds = dynamic_cast<FileDataSource*>(data);
-	if (fds) {
-		File *file = fds->getFile();
-		string path = file->getNativePath();
-
-		if (path.empty() == false) {
-			surface = IMG_Load(path.c_str());
-		}
-	}
-
-	// when loading from file failed, try loading via buffer
-	if (surface == NULL) {
-		DataBuffer *buffer = data->getDataBuffer();
-		SDL_RWops *rw = SDL_RWFromConstMem(buffer->getData(), buffer->getSize());
-		surface = IMG_Load_RW(rw, 0);
-		SDL_FreeRW(rw);
-	}
-
-	if (surface) {
-		int r=0, g=0, b=0, a=0;
-		switch(surface->format->BytesPerPixel) {
-			case 4:		r = 8;	g = 8;	b = 8;	a = 8;	break;
-			case 3:		r = 8;	g = 8;	b = 8;	a = 0;	break;
-
-			default: {
-				// no compatible pixel format
-				SDL_FreeSurface(surface);
-				return false;
-			}
-		}
-		
-		// compute the buffer size
-		size_t image_size = surface->w * surface->h * surface->format->BytesPerPixel;
-		
-		// copy the pixel data into the buffer
-		if  (pBuffer) {
-			*pBuffer = reinterpret_cast<unsigned char*>(malloc(image_size));
-			memcpy(*pBuffer, surface->pixels, image_size);
-		}
-
-		// set results
-		if (pWidth)				*pWidth				= surface->w;
-		if (pHeight)			*pHeight			= surface->h;
-		if (pOriginalWidth)		*pOriginalWidth		= surface->w;
-		if (pOriginalHeight)	*pOriginalHeight	= surface->h;
-		if (pSize)				*pSize				= image_size;
-		if (pRbits)				*pRbits				= r;
-		if (pGbits)				*pGbits				= g;
-		if (pBbits)				*pBbits				= b;
-		if (pAbits)				*pAbits				= a;
-
-		// release the surface
-		SDL_FreeSurface(surface);
-
-		return true;
-	}
-
-	return false;
-}
-
 #endif // WIESEL_USE_LIBSDL

File src/common/wiesel/platform/sdl/sdl_engine.h

 
 		virtual TouchHandler *getTouchHandler();
 
-	public:
-		virtual bool decodeImage(
-				DataSource *data,
-				unsigned char **pBuffer, size_t *pSize,
-				unsigned int *pWidth, unsigned int *pHeight,
-				unsigned int *pOriginalWidth, unsigned int *pOriginalHeight,
-				int *pRbits, int *pGbits, int *pBbits, int *pAbits,
-				bool as_texture
-		);
-
 	protected:
 		FileSystem*		root_fs;
 		FileSystem*		asset_fs;

File src/common/wiesel/resources/graphics/image.cpp

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#include "image.h"
+#include "imageutils.h"
+#include <assert.h>
+#include <string.h>
+
+
+using namespace wiesel;
+
+
+
+Image::Image() {
+	this->pixel_data = NULL;
+}
+
+
+Image::Image(DataBuffer* data, PixelFormat format, const dimension& size) {
+	this->pixel_data = NULL;
+
+	bool assigned = assignImageData(data, format, size);
+	assert(assigned);
+
+	return;
+}
+
+
+Image::~Image() {
+	if (pixel_data) {
+		pixel_data->release();
+		pixel_data = NULL;
+	}
+
+	return;
+}
+
+
+bool Image::assignImageData(DataBuffer* data, PixelFormat format, const dimension& size) {
+	size_t new_image_size = getBytesPerPixel(format) * size.width * size.height;
+	assert(new_image_size == data->getSize());
+
+	if (new_image_size == data->getSize()) {
+		if (this->pixel_data) {
+			this->pixel_data->release();
+			this->pixel_data = NULL;
+		}
+
+		this->pixel_data = data;
+		this->pixel_data->retain();
+		this->pixel_format = format;
+		this->image_size   = size;
+	}
+
+	return true;
+}
+
+
+bool Image::changePixelFormat(PixelFormat new_pixel_format) {
+	// not supported yet.
+	return false;
+}
+
+
+bool Image::resize(const dimension &new_image_size) {
+	// oops - we got an empty buffer...
+	if (pixel_data == NULL || pixel_data->getData() == NULL) {
+		return false;
+	}
+
+	// both dimensions will remain the same, so we have nothing to do
+	if (image_size == new_image_size) {
+		return true;
+	}
+
+	// an uncommon case, one dimension will be increased, the other decreased
+	// we have to do this in two steps
+	if (
+			((new_image_size.width > image_size.width) && (new_image_size.height < image_size.height))
+		||	((new_image_size.width < image_size.width) && (new_image_size.height > image_size.height))
+	) {
+		bool success = false;
+		success &= resize(dimension(new_image_size.width, image_size.height));
+		success &= resize(dimension(new_image_size.width, new_image_size.height));
+		return success;
+	}
+
+	// prepare some attributes...
+	size_t bytesPerPixel = getBytesPerPixel(getPixelFormat());
+	unsigned int old_width  = static_cast<unsigned int>(image_size.width);
+	unsigned int old_height = static_cast<unsigned int>(image_size.height);
+	unsigned int new_width  = static_cast<unsigned int>(new_image_size.width);
+	unsigned int new_height = static_cast<unsigned int>(new_image_size.height);
+
+	// increase the image's size
+	if ((new_width >= old_width) && (new_height >= old_height)) {
+		size_t old_line_length	= old_width * bytesPerPixel;
+		size_t new_line_length	= new_width * bytesPerPixel;
+	//	size_t old_size			= old_line_length * old_height;
+		size_t new_size			= new_line_length * new_height;
+		size_t gap				= new_line_length - old_line_length;
+
+		// resize the buffer to it's new size
+		bool resize_successfull = pixel_data->resize(new_size);
+
+		// check, if reallocating the buffer failed
+		if (resize_successfull == false) {
+			return NULL;
+		}
+
+		// get pointers to required offsets.
+		DataBuffer::mutable_data_t buffer = pixel_data->getMutableData();
+		unsigned char *ptr_old_line = buffer + (bytesPerPixel * old_width * old_height);
+		unsigned char *ptr_new_line = buffer + (bytesPerPixel * new_width * old_height);
+		unsigned char *ptr_buf_end  = buffer + new_size;
+
+		// fill remaining space to the end of the buffer
+		memset(ptr_new_line, 0x00, (ptr_buf_end - ptr_new_line));
+
+		// re-arrange the lines
+		do {
+			// fill the gap to the next line with zero, which should result in transparent, black pixels
+			for(int cnt=gap; --cnt>=0;) {
+				*(--ptr_new_line) = 0x00;
+			}
+
+			// copy the line to it's new position
+			for(int cnt=old_line_length; --cnt>=0;) {
+				*(--ptr_new_line) = *(--ptr_old_line);
+			}
+		}
+		while(ptr_old_line > buffer);
+
+		return true;
+	}
+
+	// increase the image's size
+	if ((new_width <= old_width) && (new_height <= old_height)) {
+		size_t old_line_length	= old_width * bytesPerPixel;
+		size_t new_line_length	= new_width * bytesPerPixel;
+	//	size_t old_size			= old_line_length * old_height;
+		size_t new_size			= new_line_length * new_height;
+		size_t gap				= old_line_length - new_line_length;
+
+		DataBuffer::mutable_data_t buffer = pixel_data->getMutableData();
+		unsigned char *ptr_old_line = buffer - 1;
+		unsigned char *ptr_new_line = buffer - 1;
+		unsigned char *ptr_buf_end  = buffer + new_size;
+
+		// re-arrange the lines
+		do {
+			// copy the line to it's new position
+			for(int cnt=new_line_length; --cnt>=0;) {
+				*(++ptr_new_line) = *(++ptr_old_line);
+			}
+
+			// skip the gap
+			ptr_old_line += gap;
+		}
+		while(ptr_new_line < ptr_buf_end);
+
+		// finally, shrink the buffer to it's new size
+		bool resize_successfull = pixel_data->resize(new_size);
+
+		// check, if reallocating the buffer failed
+		if (resize_successfull == false) {
+			return false;
+		}
+
+		return true;
+	}
+
+	// did we have forgotten a single case?
+	assert(false);
+
+	return false;
+}
+
+
+bool Image::ensurePowerOfTwo() {
+	// current size as integer
+	int cur_width  = static_cast<int>(image_size.width);
+	int cur_height = static_cast<int>(image_size.width);
+
+	// compute the next pot-size
+	int pot_width  = getNextPowerOfTwo(cur_width);
+	int pot_height = getNextPowerOfTwo(cur_height);
+
+	if ((cur_width != pot_width) || (cur_height != pot_height)) {
+		return resize(dimension(pot_width, pot_height));
+	}
+
+	return true;
+}

File src/common/wiesel/resources/graphics/image.h

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_RESOURCES_GRAPHICS_IMAGE_H__
+#define __WIESEL_RESOURCES_GRAPHICS_IMAGE_H__
+
+#include <wiesel/wiesel-common.def>
+
+#include <wiesel/geometry.h>
+#include <wiesel/util/shared_object.h>
+#include "wiesel/io/databuffer.h"
+
+
+namespace wiesel {
+
+
+	/**
+	 * @brief Describes color components and their order for each pixel of an image.
+	 */
+	enum PixelFormat {
+		PixelFormat_RGB_888,
+		PixelFormat_RGBA_8888,
+	};
+
+
+	/**
+	 * @brief A class containing image data and a description of it.
+	 */
+	class WIESEL_COMMON_EXPORT Image : public virtual SharedObject
+	{
+	public:
+		/**
+		 * @brief Creates a new image without data assigned.
+		 */
+		Image();
+
+		/**
+		 * @brief Creates a new image and assigns image data to it.
+		 */
+		Image(DataBuffer *data, PixelFormat format, const dimension &size);
+
+		virtual ~Image();
+
+	public:
+		/**
+		 * @brief Get the \ref DataBuffer object containing the image data.
+		 */
+		inline DataBuffer *getPixelData() const {
+			return pixel_data;
+		}
+		
+		/**
+		 * @brief Get the current pixel format of this image.
+		 */
+		inline PixelFormat getPixelFormat() const {
+			return pixel_format;
+		}
+
+		/**
+		 * @brief Get the size of this image.
+		 */
+		inline const dimension& getSize() const {
+			return image_size;
+		}
+
+	public:
+		/**
+		 * @brief Assigns new image data to this image object.
+		 * Before the data will be assigned, it will be checked if the buffer size matches
+		 * pixel format and image size.
+		 * @param data		A \ref DataBuffer containing the pixel data.
+		 * @param format	The pixel format of the assigned pixel data.
+		 * @param size		The size of the image.
+		 * @return \c true, if the data was successfully assigned, \c false otherwise.
+		 */
+		virtual bool assignImageData(DataBuffer *data, PixelFormat format, const dimension &size);
+
+		/**
+		 * @brief Change the pixel format of this image.
+		 * The image will be converted into the new format, which may take a few milliseconds.
+		 * @return \c true, if the operation was successfull, \c false otherwise.
+		 */
+		virtual bool changePixelFormat(PixelFormat new_pixel_format);
+
+		/**
+		 * @brief Change the image's size.
+		 * The DataBuffer will be converted into the new size, which may take a few milliseconds.
+		 * When the size is decreased, the right and bottom parts of the image will be lost.
+		 * When increasing the image, the original image is aligned on the top left corner,
+		 * and the bottom right part will be filled with black.
+		 * @return \c true, if the operation was successfull, \c false otherwise.
+		 */
+		virtual bool resize(const dimension &new_size);
+
+		/**
+		 * @brief Checks, if the image's size is a power-of-two and resizes the image
+		 * if neccessary.
+		 */
+		virtual bool ensurePowerOfTwo();
+
+	private:
+		DataBuffer*		pixel_data;
+		PixelFormat		pixel_format;
+		dimension		image_size;
+	};
+}
+
+#endif

File src/common/wiesel/resources/graphics/image_loader.cpp

Empty file added.

File src/common/wiesel/resources/graphics/image_loader.h

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_RESOURCES_IMAGES_IMAGELOADER_H__
+#define __WIESEL_RESOURCES_IMAGES_IMAGELOADER_H__
+
+#include <wiesel/wiesel-common.def>
+
+#include "wiesel/modules.h"
+#include "wiesel/io/datasource.h"
+#include "image.h"
+
+
+namespace wiesel {
+
+
+	/**
+	 * @brief An interface for a module for loading images from a data source.
+	 */
+	class WIESEL_COMMON_EXPORT IImageLoader : public Module
+	{
+	public:
+		IImageLoader() {}
+		virtual ~IImageLoader() {}
+
+	public:
+		/**
+		 * @brief Loads a new image from a data source.
+		 */
+		virtual Image *loadImage(DataSource *source) = 0;
+
+		/**
+		 * @brief Loads a new image from a data source.
+		 * The image should be created with a size which is a power of two.
+		 * @param source			The data source of the image.
+		 * @param original_size		Pointer to a dimension-object, which will receive
+		 *							the original size of the image, if the size was increased
+		 *							to match a power of two value.
+		 * @return The image which was loaded from the data source or \c NULL, when the loading failed.
+		 */
+		virtual Image *loadPowerOfTwoImage(DataSource *source, dimension *pOriginal_size) = 0;
+	};
+
+}
+
+#endif // __WIESEL_RESOURCES_IMAGES_IMAGELOADER_H__

File src/common/wiesel/resources/graphics/imageutils.cpp

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#include "imageutils.h"
+
+
+namespace wiesel {
+
+	unsigned int getNextPowerOfTwo(unsigned int num) {
+		unsigned int out_num = 1;
+		for(; out_num<num; out_num<<=1) { }
+
+		return out_num;
+	}
+
+
+
+	size_t getBytesPerPixel(PixelFormat pixel_format) {
+		switch(pixel_format) {
+			case PixelFormat_RGB_888: {
+				return 3;
+			}
+
+			case PixelFormat_RGBA_8888: {
+				return 4;
+			}
+		}
+
+		return 0;
+	}
+
+} // namespace wiesel
+

File src/common/wiesel/resources/graphics/imageutils.h

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_RESOURCES_GRAPHICS_IMAGEUTILS_H__
+#define __WIESEL_RESOURCES_GRAPHICS_IMAGEUTILS_H__
+
+#include <wiesel/wiesel-common.def>
+
+#include "image.h"
+
+
+namespace wiesel {
+
+	/**
+	 * @brief compute the next power-of-two size, which is equal or greater than the input number.
+	 */
+	WIESEL_COMMON_EXPORT unsigned int getNextPowerOfTwo(unsigned int number);
+
+	/**
+	 * @brief Get the size in bytes for a pixel in a specific pixel format.
+	 */
+	WIESEL_COMMON_EXPORT size_t getBytesPerPixel(PixelFormat pixel_format);
+}
+
+
+#endif /* __WIESEL_RESOURCES_GRAPHICS_IMAGEUTILS_H__ */

File src/common/wiesel/util/imageutils.cpp

-/**
- * Copyright (C) 2012
- * Christian Fischer
- *
- * https://bitbucket.org/baldur/wiesel/
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-#include "imageutils.h"
-#include <assert.h>
-#include <malloc.h>
-#include <stddef.h>
-#include <string.h>
-
-
-using namespace wiesel;
-using namespace wiesel::imageutils;
-
-
-unsigned int imageutils::getNextPowerOfTwo(unsigned int num) {
-	unsigned int out_num = 1;
-	for(; out_num<num; out_num<<=1) { }
-
-	return out_num;
-}
-
-
-
-unsigned char* imageutils::resizeImage(
-		unsigned char *buffer,		unsigned char bytesPerPixel,
-		unsigned int old_width,		unsigned int old_height,
-		unsigned int new_width,		unsigned int new_height
-) {
-	// oops - we got an empty buffer...
-	if (buffer == NULL) {
-		return NULL;
-	}
-
-	// both dimensions will remain the same, so we have nothing to do
-	if ((new_width == old_width) && (new_height == old_height)) {
-		return buffer;
-	}
-
-	// an uncommon case, one dimension will be increased, the other decreased
-	// we have to do this in two steps
-	if (
-			((new_width > old_width) && (new_height < old_height))
-		||	((new_width < old_width) && (new_height > old_height))
-	) {
-		buffer = resizeImage(buffer, bytesPerPixel, old_width, old_height, new_width, old_height);
-		buffer = resizeImage(buffer, bytesPerPixel, new_width, old_height, new_width, new_height);
-		return buffer;
-	}
-
-	// increase the image's size
-	if ((new_width >= old_width) && (new_height >= old_height)) {
-		size_t old_line_length	= old_width * bytesPerPixel;
-		size_t new_line_length	= new_width * bytesPerPixel;
-	//	size_t old_size			= old_line_length * old_height;
-		size_t new_size			= new_line_length * new_height;
-		size_t gap				= new_line_length - old_line_length;
-
-		buffer = reinterpret_cast<unsigned char*>(realloc(buffer, new_size));
-		unsigned char *ptr_old_line = buffer + (bytesPerPixel * old_width * old_height);
-		unsigned char *ptr_new_line = buffer + (bytesPerPixel * new_width * old_height);
-		unsigned char *ptr_buf_end  = buffer + new_size;
-
-		// check, if reallocating the buffer failed
-		if (buffer == NULL) {
-			return NULL;
-		}
-
-		// fill remaining space to the end of the buffer
-		memset(ptr_new_line, 0x00, (ptr_buf_end - ptr_new_line));
-
-		// re-arrange the lines
-		do {
-			// fill the gap to the next line with zero, which should result in transparent, black pixels
-			for(int cnt=gap; --cnt>=0;) {
-				*(--ptr_new_line) = 0x00;
-			}
-
-			// copy the line to it's new position
-			for(int cnt=old_line_length; --cnt>=0;) {
-				*(--ptr_new_line) = *(--ptr_old_line);
-			}
-		}
-		while(ptr_old_line > buffer);
-
-		return buffer;
-	}
-
-	// increase the image's size
-	if ((new_width <= old_width) && (new_height <= old_height)) {
-		size_t old_line_length	= old_width * bytesPerPixel;
-		size_t new_line_length	= new_width * bytesPerPixel;
-	//	size_t old_size			= old_line_length * old_height;
-		size_t new_size			= new_line_length * new_height;
-		size_t gap				= old_line_length - new_line_length;
-
-		unsigned char *ptr_old_line = buffer - 1;
-		unsigned char *ptr_new_line = buffer - 1;
-		unsigned char *ptr_buf_end  = buffer + new_size;
-
-		// re-arrange the lines
-		do {
-			// copy the line to it's new position
-			for(int cnt=new_line_length; --cnt>=0;) {
-				*(++ptr_new_line) = *(++ptr_old_line);
-			}
-
-			// skip the gap
-			ptr_old_line += gap;
-		}
-		while(ptr_new_line < ptr_buf_end);
-
-		// finally, shrink the buffer to it's new size
-		buffer = reinterpret_cast<unsigned char*>(realloc(buffer, new_size));
-
-		// check, if reallocating the buffer failed
-		if (buffer == NULL) {
-			return NULL;
-		}
-
-		return buffer;
-	}
-
-	// did we have forgotten a single case?
-	assert(false);
-
-	return buffer;
-}

File src/common/wiesel/util/imageutils.h

-/**
- * Copyright (C) 2012
- * Christian Fischer
- *
- * https://bitbucket.org/baldur/wiesel/
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-#ifndef __WIESEL_UTIL_IMAGEUTILS_H__
-#define __WIESEL_UTIL_IMAGEUTILS_H__
-
-#include <wiesel/wiesel-common.def>
-
-namespace wiesel {
-namespace imageutils {
-
-	/**
-	 * @brief compute the next power-of-two size, which is equal or greater than the input number.
-	 */
-	WIESEL_COMMON_EXPORT unsigned int getNextPowerOfTwo(unsigned int number);
-
-	/**
-	 * @brief increase or decrease the size of the image.
-	 * @return the buffer of the resized image, which may be the same as the original input.
-	 */
-	WIESEL_COMMON_EXPORT unsigned char* resizeImage(
-			unsigned char *buffer,			unsigned char bytesPerPixel,
-			unsigned int original_width,	unsigned int original_height,
-			unsigned int new_width,			unsigned int new_height
-	);
-}
-}
-
-
-#endif /* IMAGEUTILS_H_ */

File src/sdl/wiesel/sdl/loaders/sdl_image_loader.cpp

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#include "sdl_image_loader.h"
+
+#include <wiesel/util/log.h>
+
+#include <SDL_image.h>
+#include <string>
+
+
+using namespace wiesel;
+using namespace std;
+
+
+SdlImageLoader::SdlImageLoader() : IImageLoader() {
+	int initialized = IMG_Init(IMG_INIT_PNG|IMG_INIT_JPG);
+	if((initialized & IMG_INIT_PNG) == 0) {
+		Log::err << "Loading libPNG failed." << std::endl;
+	}
+	if((initialized & IMG_INIT_JPG) == 0) {
+		Log::err << "Loading libJPG failed." << std::endl;
+	}
+
+	return;
+}
+
+SdlImageLoader *SdlImageLoader::create() {
+	return new SdlImageLoader();
+}
+
+SdlImageLoader::~SdlImageLoader() {
+	IMG_Quit();
+	return;
+}
+
+
+Image *SdlImageLoader::loadImage(DataSource *source) {
+	return internal_loadImage(source, NULL, false);
+}
+
+
+Image *SdlImageLoader::loadPowerOfTwoImage(DataSource *source, dimension *pOriginal_size) {
+	return internal_loadImage(source, pOriginal_size, true);
+}
+
+
+Image *SdlImageLoader::internal_loadImage(DataSource *source, dimension *pOriginalSize, bool pot) {
+	SDL_Surface *surface = NULL;
+
+	FileDataSource *fds = dynamic_cast<FileDataSource*>(source);
+	if (fds) {
+		File *file = fds->getFile();
+		string path = file->getNativePath();
+
+		if (path.empty() == false) {
+			surface = IMG_Load(path.c_str());
+		}
+	}
+
+	// when loading from file failed, try loading via buffer
+	if (surface == NULL) {
+		DataBuffer *buffer = source->getDataBuffer();
+		SDL_RWops *rw = SDL_RWFromConstMem(buffer->getData(), buffer->getSize());
+		surface = IMG_Load_RW(rw, 0);
+		SDL_FreeRW(rw);
+	}
+
+	if (surface) {
+		PixelFormat pixelformat;
+
+		switch(surface->format->BytesPerPixel) {
+			case 4: {
+				pixelformat = PixelFormat_RGBA_8888;
+				break;
+			}
+
+			case 3: {
+				pixelformat = PixelFormat_RGB_888;
+				break;
+			}
+
+			default: {
+				// no compatible pixel format
+				SDL_FreeSurface(surface);
+				return NULL;
+			}
+		}
+
+		// compute the buffer size
+		size_t image_size = surface->w * surface->h * surface->format->BytesPerPixel;
+
+		// copy the pixel data into the buffer
+		DataBuffer *buffer = ExclusiveDataBuffer::createCopyOf(surface->pixels, image_size);
+		if (buffer == NULL) {
+			return NULL;
+		}
+
+		// create the image object
+		Image *image = new Image(buffer, pixelformat, dimension(surface->w, surface->h));
+
+		// set results
+		if (pOriginalSize) {
+			pOriginalSize->width  = surface->w;
+			pOriginalSize->height = surface->h;
+		}
+
+		// check power-of-two size
+		if (pot) {
+			image->ensurePowerOfTwo();
+		}
+
+		// release the surface
+		SDL_FreeSurface(surface);
+
+		return image;
+	}
+
+	return NULL;
+}
+
+
+
+// add the module to the module registry
+REGISTER_MODULE_SINGLETON(
+		IImageLoader,
+		SdlImageLoader,
+		&SdlImageLoader::create,
+		"SDL",
+		0x01020000u,
+		IModuleLoader::PriorityNormal
+)

File src/sdl/wiesel/sdl/loaders/sdl_image_loader.h

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_SDL_LOADERS_SDLIMAGELOADER_H__
+#define __WIESEL_SDL_LOADERS_SDLIMAGELOADER_H__
+
+#include <wiesel/io/databuffer.h>
+#include <wiesel/io/file.h>
+#include <wiesel/modules.h>
+#include <wiesel/resources/graphics/image_loader.h>
+#include <wiesel/wiesel-sdl.def>
+
+
+namespace wiesel {
+
+	class WIESEL_SDL_EXPORT SdlImageLoader : public IImageLoader
+	{
+	private:
+		SdlImageLoader();
+
+	public:
+		static SdlImageLoader *create();
+		
+		virtual ~SdlImageLoader();
+
+
+		virtual Image *loadImage(DataSource *source);
+		virtual Image *loadPowerOfTwoImage(DataSource *source, dimension *pOriginal_size);
+		
+	private:
+		virtual Image *internal_loadImage(DataSource *source, dimension *pOriginalSize, bool pot);
+	};
+}
+
+#endif // __WIESEL_SDL_LOADERS_SDLIMAGELOADER_H__

File src/sdl/wiesel/wiesel-sdl.def

+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_SDL_DEF_H__
+#define __WIESEL_SDL_DEF_H__
+
+/**
+ * some defines and flags specially for the wiesel-sdl library
+ */
+
+#if defined(_WIN32)
+	#if defined(wiesel_sdl_EXPORTS)
+		#define WIESEL_SDL_EXPORT		__declspec(dllexport)
+	#else
+		#define WIESEL_SDL_EXPORT		__declspec(dllimport)
+	#endif
+#else
+		#define WIESEL_SDL_EXPORT
+#endif
+
+
+#endif // __WIESEL_SDL_DEF_H__

File tests/common/modules.cpp

 		return;
 	}
 
+	virtual ~TestMod17() {
+		return;
+	}
+
 	static TestMod17* create() {
 		return new TestMod17();
 	}
 
-	virtual ~TestMod17() {
-		return;
-	}
-
 	virtual int getTestValue() {
 		return 17;
 	}
 		return;
 	}
 
+	virtual ~TestMod23() {
+		return;
+	}
+
 	static TestMod23* create() {
 		return new TestMod23();
 	}
 
-	virtual ~TestMod23() {
-		return;
-	}
-
 	virtual int getTestValue() {
 		return 23;
 	}
 		return;
 	}
 
+	virtual ~TestMod42() {
+		return;
+	}
+
 	static TestMod42* create() {
 		return new TestMod42();
 	}
 
-	virtual ~TestMod42() {
-		return;
-	}
-
 	virtual int getTestValue() {
 		return 42;
 	}