imageloader.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005-2011 by the FIFE team                              *
00003  *   http://www.fifengine.net                                              *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 
00022 // Standard C++ library includes
00023 
00024 // 3rd party library includes
00025 #include <boost/scoped_array.hpp>
00026 #include <boost/scoped_ptr.hpp>
00027 #include <SDL.h>
00028 #include <SDL_image.h>
00029 
00030 // FIFE includes
00031 // These includes are split up in two parts, separated by one empty line
00032 // First block: files included from the FIFE root src directory
00033 // Second block: files included from the same folder
00034 #include "controller/engine.h"
00035 #include "util/base/exception.h"
00036 #include "util/resource/resource.h"
00037 #include "vfs/raw/rawdata.h"
00038 #include "vfs/vfs.h"
00039 #include "video/renderbackend.h"
00040 #include "video/image.h"
00041 
00042 #include "imageloader.h"
00043 
00044 namespace FIFE {
00045     void ImageLoader::load(IResource* res) {
00046         VFS* vfs = VFS::instance();
00047 
00048         Image* img = dynamic_cast<Image*>(res);
00049 
00050         //Have to save the images x and y shift or it gets lost when it's
00051         //loaded again.
00052         int32_t xShiftSave = img->getXShift();
00053         int32_t yShiftSave = img->getYShift();
00054 
00055         if(!img->isSharedImage()) {
00056             const std::string& filename = img->getName();
00057             boost::scoped_ptr<RawData> data (vfs->open(filename));
00058             size_t datalen = data->getDataLength();
00059             boost::scoped_array<uint8_t> darray(new uint8_t[datalen]);
00060             data->readInto(darray.get(), datalen);
00061             SDL_RWops* rwops = SDL_RWFromConstMem(darray.get(), static_cast<int>(datalen));
00062 
00063             SDL_Surface* surface = IMG_Load_RW(rwops, false);
00064 
00065             if (!surface) {
00066                 throw SDLException(std::string("Fatal Error when loading image into a SDL_Surface: ") + SDL_GetError());
00067             }
00068 
00069             RenderBackend* rb = RenderBackend::instance();
00070             // in case of SDL we don't need to convert the surface
00071             if (rb->getName() == "SDL") {
00072                 img->setSurface(surface);
00073             // in case of OpenGL we need a 32bit surface
00074             } else {
00075                 SDL_PixelFormat dst_format = rb->getPixelFormat();
00076                 SDL_PixelFormat src_format = *surface->format;
00077                 uint8_t dstbits = dst_format.BitsPerPixel;
00078                 uint8_t srcbits = src_format.BitsPerPixel;
00079 
00080                 if (srcbits != 32 || dst_format.Rmask != src_format.Rmask || dst_format.Gmask != src_format.Gmask ||
00081                     dst_format.Bmask != src_format.Bmask || dst_format.Amask != src_format.Amask) {
00082                     dst_format.BitsPerPixel = 32;
00083                     SDL_Surface* conv = SDL_ConvertSurface(surface, &dst_format, SDL_SWSURFACE | SDL_SRCALPHA);
00084                     dst_format.BitsPerPixel = dstbits;
00085 
00086                     if (!conv) {
00087                         throw SDLException(std::string("Fatal Error when converting surface to the screen format: ") + SDL_GetError());
00088                     }
00089 
00090                     img->setSurface(conv);
00091                     SDL_FreeSurface(surface);
00092                 } else {
00093                     img->setSurface(surface);
00094                 }
00095             }
00096 
00097             SDL_FreeRW(rwops);
00098         }
00099         //restore saved x and y shifts
00100         img->setXShift(xShiftSave);
00101         img->setYShift(yShiftSave);
00102     }
00103 }  //FIFE