FIFE
2008.0
|
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 = 0; 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 00182 fp = fopen(filename.c_str(), "wb"); 00183 00184 if (fp == NULL) { 00185 return; 00186 } 00187 00188 //create the png file 00189 pngptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 00190 NULL, NULL, NULL); 00191 if (pngptr == NULL) { 00192 fclose(fp); 00193 return; 00194 } 00195 00196 //create information struct 00197 infoptr = png_create_info_struct(pngptr); 00198 if (infoptr == NULL) { 00199 fclose(fp); 00200 png_destroy_write_struct(&pngptr, (png_infopp)NULL); 00201 return; 00202 } 00203 00204 if (setjmp(png_jmpbuf(pngptr))) { 00205 png_destroy_write_struct(&pngptr, &infoptr); 00206 fclose(fp); 00207 return; 00208 } 00209 00210 //initialize io 00211 png_init_io(pngptr, fp); 00212 00213 //lock the surface for access 00214 SDL_LockSurface(&surface); 00215 00216 colortype = PNG_COLOR_TYPE_RGB; 00217 if(m_surface->format->palette){ 00218 colortype |= PNG_COLOR_TYPE_PALETTE; 00219 } 00220 else if (m_surface->format->Amask){ 00221 colortype |= PNG_COLOR_TYPE_RGB_ALPHA; 00222 } 00223 else{} 00224 00225 png_set_IHDR(pngptr, infoptr, surface.w, surface.h, 8, colortype, 00226 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 00227 00228 png_write_info(pngptr, infoptr); 00229 png_set_packing(pngptr); 00230 00231 rowpointers = new png_bytep[surface.h]; 00232 for (int i = 0; i < surface.h; i++) { 00233 rowpointers[i] = (png_bytep)(Uint8 *)surface.pixels + i*surface.pitch; 00234 } 00235 //write the image 00236 png_write_image(pngptr, rowpointers); 00237 png_write_end(pngptr, infoptr); 00238 00239 SDL_UnlockSurface(&surface); 00240 delete [] rowpointers; 00241 png_destroy_write_struct(&pngptr, &infoptr); 00242 fclose(fp); 00243 00244 } 00245 }