00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <cassert>
00024 #include <iostream>
00025
00026
00027 #include <SDL.h>
00028
00029
00030
00031
00032
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
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
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
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
00211 png_init_io(pngptr, fp);
00212
00213
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
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 }