image.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005-2008 by the FIFE team                              *
00003  *   http://www.fifengine.de                                               *
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 #include <cassert>
00024 #include <iostream>
00025 
00026 // 3rd party library includes
00027 #include <SDL.h>
00028 
00029 // FIFE includes
00030 // These includes are split up in two parts, separated by one empty line
00031 // First block: files included from the FIFE root src directory
00032 // Second block: files included from the same folder
00033 #include "image.h"
00034 
00035 namespace FIFE {
00036 
00037     Image::Image(SDL_Surface* surface): 
00038         m_surface(NULL) {
00039         reset(surface);
00040     }
00041 
00042     Image::Image(const uint8_t* data, unsigned int width, unsigned int height): 
00043         m_surface(NULL) {
00044         SDL_Surface* surface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, width,height, 32,
00045                                                     RMASK, GMASK, BMASK ,AMASK);
00046         SDL_LockSurface(surface);
00047 
00048         unsigned int size = width * height * 4;
00049         uint8_t* pixeldata = static_cast<uint8_t*>(surface->pixels);
00050         std::copy(data, data + size, pixeldata);
00051         SDL_UnlockSurface(surface);
00052         reset(surface);
00053     }
00054 
00055     void Image::reset(SDL_Surface* surface) {
00056         if( m_surface ) {
00057             SDL_FreeSurface(m_surface);
00058         }
00059         m_surface = surface;
00060         m_xshift = 0;
00061         m_yshift = 0;
00062         while (!m_clipstack.empty()) {
00063             m_clipstack.pop();
00064         }
00065         m_area.x = m_area.y = m_area.w = m_area.h = 0;
00066         m_surface = surface;
00067     }
00068     
00069     Image::~Image() {
00070         //assert(m_refcount == 0);
00071         reset(NULL);
00072     }
00073 
00074     SDL_Surface* Image::detachSurface() {
00075         SDL_Surface* srf = m_surface;
00076         m_surface = NULL;
00077         return srf;
00078     }
00079     
00080     unsigned int Image::getWidth() const {
00081         if (!m_surface) {
00082             return 0;
00083         }
00084         return m_surface->w;
00085     }
00086 
00087     unsigned int Image::getHeight() const {
00088         if (!m_surface) {
00089             return 0;
00090         }
00091         return m_surface->h;
00092     }
00093     
00094     const Rect& Image::getArea() {
00095         m_area.w = getWidth();
00096         m_area.h = getHeight();
00097         return m_area;
00098     }
00099 
00100     void Image::setXShift(int xshift) {
00101         m_xshift = xshift;
00102     }
00103 
00104     void Image::setYShift(int yshift) {
00105         m_yshift = yshift;
00106     }
00107 
00108     void Image::getPixelRGBA(int x, int y, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) {
00109         if ((x < 0) || (x >= m_surface->w) || (y < 0) || (y >= m_surface->h)) {
00110             r = 0;
00111             g = 0;
00112             b = 0;
00113             a = 0;
00114             return;
00115         }
00116         
00117         int bpp = m_surface->format->BytesPerPixel;
00118         Uint8 *p = (Uint8*)m_surface->pixels + y * m_surface->pitch + x * bpp;
00119         uint32_t pixel;
00120         switch(bpp) {
00121         case 1:
00122             pixel = *p;
00123         
00124         case 2:
00125             pixel = *(Uint16 *)p;
00126         
00127         case 3:
00128             if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00129                 pixel = p[0] << 16 | p[1] << 8 | p[2];
00130             } else {
00131                 pixel = p[0] | p[1] << 8 | p[2] << 16;
00132             }
00133         
00134         case 4:
00135             pixel = *(Uint32 *)p;
00136         }
00137         SDL_GetRGBA(pixel, m_surface->format, r, g, b, a);
00138     }
00139 
00140     void Image::render(const Rect& rect, unsigned char alpha) {
00141         render(rect, SDL_GetVideoSurface(), alpha);
00142     }
00143 
00144     void Image::pushClipArea(const Rect& cliparea, bool clear) {
00145         ClipInfo ci;
00146         ci.r = cliparea;
00147         ci.clearing = clear;
00148         m_clipstack.push(ci);
00149         setClipArea(cliparea, clear);
00150     }
00151     
00152     void Image::popClipArea() {
00153         assert(!m_clipstack.empty());
00154         m_clipstack.pop();
00155         if (m_clipstack.empty()) {
00156             clearClipArea();
00157         } else {
00158             ClipInfo ci = m_clipstack.top();
00159             setClipArea(ci.r, ci.clearing);
00160         }
00161     }
00162     
00163     const Rect& Image::getClipArea() const {
00164         if (m_clipstack.empty()) {
00165             return m_clipstack.top().r;
00166         } else {
00167             return m_area;
00168         }
00169     }
00170 
00171     void Image::clearClipArea() {
00172         setClipArea(m_area, true);
00173     }
00174 
00175     void Image::saveAsPng(const std::string& filename, SDL_Surface& surface) {
00176         FILE *fp;
00177         png_structp pngptr;
00178         png_infop infoptr;
00179         int colortype;
00180         png_bytep *rowpointers = NULL;
00181         Uint32 rmask, gmask, bmask, amask;
00182         //get endian
00183         #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00184         rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff;
00185         #else
00186         rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000;
00187         #endif
00188 
00189         fp = fopen(filename.c_str(), "wb");
00190             
00191         if (fp == NULL) {
00192             return;
00193         }
00194 
00195         //create the png file
00196         pngptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 
00197         NULL, NULL, NULL);
00198         if (pngptr == NULL) {
00199             fclose(fp);
00200             return;
00201         }
00202         
00203         //create information struct
00204         infoptr = png_create_info_struct(pngptr);
00205         if (infoptr == NULL) {
00206             fclose(fp);
00207             png_destroy_write_struct(&pngptr, (png_infopp)NULL);
00208             return;             
00209         }
00210         
00211         if (setjmp(png_jmpbuf(pngptr))) {
00212             png_destroy_write_struct(&pngptr, &infoptr);
00213             fclose(fp);
00214             return;
00215         }
00216         
00217         //initialize io
00218         png_init_io(pngptr, fp);
00219         
00220         //lock the surface for access
00221         SDL_LockSurface(&surface);
00222 
00223         colortype = PNG_COLOR_TYPE_RGB;
00224         if(m_surface->format->palette){
00225             colortype |= PNG_COLOR_TYPE_PALETTE;
00226         }
00227         else if (m_surface->format->Amask){
00228             colortype |= PNG_COLOR_TYPE_RGB_ALPHA;
00229         }
00230         else{}
00231 
00232         png_set_IHDR(pngptr, infoptr, surface.w, surface.h, 8, colortype,   
00233             PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00234         
00235         png_write_info(pngptr, infoptr);
00236         png_set_packing(pngptr);
00237 
00238         rowpointers = new png_bytep[surface.h];
00239         for (int i = 0; i < surface.h; i++) {
00240             rowpointers[i] = (png_bytep)(Uint8 *)surface.pixels + i*surface.pitch;
00241         }
00242         //write the image
00243         png_write_image(pngptr, rowpointers);
00244         png_write_end(pngptr, infoptr);
00245 
00246         SDL_UnlockSurface(&surface);
00247         delete [] rowpointers;
00248         png_destroy_write_struct(&pngptr, &infoptr);
00249         fclose(fp);
00250 
00251     }
00252 }
Generated by  doxygen 1.6.2-20100208