sdlimage.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 
00028 // FIFE includes
00029 // These includes are split up in two parts, separated by one empty line
00030 // First block: files included from the FIFE root src directory
00031 // Second block: files included from the same folder
00032 #include "util/log/logger.h"
00033 #include "util/structures/rect.h"
00034 #include "video/renderbackend.h"
00035 
00036 #include "renderbackendsdl.h"
00037 #include "sdlblendingfunctions.h"
00038 #include "sdlimage.h"
00039 
00040 namespace FIFE {
00041     static Logger _log(LM_VIDEO);
00042 
00043     SDLImage::SDLImage(SDL_Surface* surface):
00044         Image(surface) {
00045         resetSdlimage();
00046      }
00047 
00048     SDLImage::SDLImage(const uint8_t* data, unsigned int width, unsigned int height):
00049         Image(data, width, height) {
00050         resetSdlimage();
00051     }
00052 
00053     void SDLImage::resetSdlimage() {
00054         m_last_alpha = 255;
00055         m_finalized = false;
00056         m_isalphaoptimized = false;
00057         m_colorkey = RenderBackend::instance()->getColorKey();
00058     }
00059 
00060     SDLImage::~SDLImage() { }
00061 
00062 
00063     void SDL_BlitSurfaceWithAlpha( const SDL_Surface* src, const SDL_Rect* srcRect,
00064         SDL_Surface* dst,  SDL_Rect* dstRect, unsigned char alpha ) {
00065         if( 0 == alpha ) {
00066             return;
00067         }
00068 
00069         int screenX, screenY;
00070         if( dstRect ) {
00071             screenX = dstRect->x;
00072             screenY = dstRect->y;
00073         } else {
00074             screenX = dst->clip_rect.x;
00075             screenY = dst->clip_rect.y;
00076         }
00077 
00078         int width, height, tX, tY;
00079         if( srcRect ) {
00080             tX = srcRect->x;
00081             tY = srcRect->y;
00082             width = srcRect->w;
00083             height = srcRect->h;
00084         } else {
00085             tX = src->clip_rect.x;
00086             tY = src->clip_rect.y;
00087             width = src->clip_rect.w;
00088             height = src->clip_rect.h;
00089         }
00090 
00091         // Clipping.
00092         if( ( screenX >= ( dst->clip_rect.x + dst->clip_rect.w ) ) ||
00093             ( screenY >= ( dst->clip_rect.y + dst->clip_rect.h ) ) ||
00094             ( ( screenX + width ) <= dst->clip_rect.x ) ||
00095             ( ( screenY + height ) <= dst->clip_rect.y ) ) {
00096             return;
00097         }
00098 
00099         if( screenX < dst->clip_rect.x ) {
00100             int dX = dst->clip_rect.x - screenX;
00101             screenX += dX;
00102             width -= dX;
00103             tX += dX;
00104         }
00105 
00106         if( ( screenX + width ) > ( dst->clip_rect.x + dst->clip_rect.w ) ) {
00107             int dX = ( screenX + width ) - ( dst->clip_rect.x + dst->clip_rect.w );
00108             width -= dX;
00109         }
00110 
00111         if( screenY < dst->clip_rect.y ) {
00112             int dY = dst->clip_rect.y - screenY;
00113             screenY += dY;
00114             height -= dY;
00115             tY += dY;
00116         }
00117 
00118         if( ( screenY + height ) > ( dst->clip_rect.y + dst->clip_rect.h ) ) {
00119             int dY = ( screenY + height ) - ( dst->clip_rect.y + dst->clip_rect.h );
00120             height -= dY;
00121         }
00122 
00123         if( ( 0 >= height ) || ( 0 >= width ) ) {
00124             return;
00125         }
00126 
00127         SDL_LockSurface( dst );
00128 
00129         unsigned char* srcData = reinterpret_cast< unsigned char* > ( src->pixels );
00130         unsigned char* dstData = reinterpret_cast< unsigned char* > ( dst->pixels );
00131 
00132         // move data pointers to the start of the pixels we're copying
00133         srcData += tY * src->pitch  + tX * src->format->BytesPerPixel;
00134         dstData += screenY * dst->pitch + screenX * dst->format->BytesPerPixel;
00135 
00136         switch( src->format->BitsPerPixel ) {
00137             case 32: {
00138                 switch( dst->format->BitsPerPixel ) {
00139                     case 16: {
00140                         if( 0xFFFF == ( dst->format->Rmask | dst->format->Gmask | dst->format->Bmask ) ) {
00141                             for( int y = height; y > 0; --y ) {
00142                                 SDL_BlendRow_RGBA8_to_RGB565( srcData, dstData, alpha, width );
00143                                 srcData += src->pitch;
00144                                 dstData += dst->pitch;
00145                             }
00146                         }
00147                     }
00148                     break;
00149 
00150                     case 24: {
00151                         for( int y = height; y > 0; --y ) {
00152                             SDL_BlendRow_RGBA8_to_RGB8( srcData, dstData, alpha, width );
00153                             srcData += src->pitch;
00154                             dstData += dst->pitch;
00155                         }
00156                     }
00157                     break;
00158 
00159                     case 32: {
00160                         for( int y = height; y > 0; --y ) {
00161                             SDL_BlendRow_RGBA8_to_RGBA8( srcData, dstData, alpha, width );
00162                             srcData += src->pitch;
00163                             dstData += dst->pitch;
00164                         }
00165                     }
00166                     break;
00167 
00168                     default:
00169                         break;
00170                 }   
00171             }
00172             break;
00173 
00174             case 16: {
00175                 if( 0x000F == src->format->Amask ) {
00176                     if( ( 16 == dst->format->BitsPerPixel ) &&
00177                         ( 0xFFFF == ( dst->format->Rmask | dst->format->Gmask | dst->format->Bmask ) ) ) {
00178                         for( int y = height; y > 0; --y ) {
00179                             SDL_BlendRow_RGBA4_to_RGB565( srcData, dstData, alpha, width );
00180                             srcData += src->pitch;
00181                             dstData += dst->pitch;
00182                         }
00183                     }
00184                 }
00185             }
00186             break;
00187 
00188             default:
00189                 break;
00190         }   
00191 
00192         SDL_UnlockSurface( dst );
00193     }
00194 
00195     void SDLImage::render(const Rect& rect, SDL_Surface* screen, unsigned char alpha) {
00196         if (alpha == 0) {
00197             return;
00198         }
00199 
00200         if (rect.right() < 0 || rect.x > static_cast<int>(screen->w) || rect.bottom() < 0 || rect.y > static_cast<int>(screen->h)) {
00201             return;
00202         }
00203         finalize();
00204 
00205         SDL_Surface* surface = screen;
00206         SDL_Rect r;
00207         r.x = rect.x;
00208         r.y = rect.y;
00209         r.w = rect.w;
00210         r.h = rect.h;
00211 
00212         if (m_surface->format->Amask == 0) {
00213             // Image has no alpha channel. This allows us to use the per-surface alpha.
00214             if (m_last_alpha != alpha) {
00215                 m_last_alpha = alpha;
00216                 SDL_SetAlpha(m_surface, SDL_SRCALPHA | SDL_RLEACCEL, alpha);
00217             }
00218             SDL_BlitSurface(m_surface, 0, surface, &r);
00219         } else {
00220             if( 255 != alpha ) {
00221                 // Special blitting routine with alpha blending:
00222                 // dst.rgb = ( src.rgb * src.a * alpha ) + ( dst.rgb * (255 - ( src.a * alpha ) ) );
00223                 SDL_BlitSurfaceWithAlpha( m_surface, 0, surface, &r, alpha );
00224             } else {
00225                 SDL_BlitSurface(m_surface, 0, surface, &r);
00226             }
00227         }
00228     }
00229 
00230     void SDLImage::finalize() {
00231         if( m_finalized ) {
00232             return;
00233         }
00234         m_finalized = true;
00235         SDL_Surface *old_surface = m_surface;
00236         Uint32 key = SDL_MapRGB(m_surface->format, m_colorkey.r, m_colorkey.g, m_colorkey.b);
00237 
00238         if (m_surface->format->Amask == 0) {
00239             SDL_SetAlpha(m_surface, SDL_SRCALPHA | SDL_RLEACCEL, 255);
00240 
00241             // only use color key if feature is enabled
00242             if (RenderBackend::instance()->isColorKeyEnabled()) {
00243                 SDL_SetColorKey(m_surface, SDL_SRCCOLORKEY, key);
00244             }
00245 
00246             m_surface = SDL_DisplayFormat(m_surface);
00247         } else {
00248             RenderBackendSDL* be = static_cast<RenderBackendSDL*>(RenderBackend::instance());
00249             m_isalphaoptimized &= be->isAlphaOptimizerEnabled();
00250             if( m_isalphaoptimized ) {
00251                 m_surface = optimize(m_surface);
00252             } else  {
00253                 SDL_SetAlpha(m_surface, SDL_SRCALPHA, 255);
00254 
00255                 // only use color key if feature is enabled
00256                 if (RenderBackend::instance()->isColorKeyEnabled()) {
00257                     SDL_SetColorKey(m_surface, SDL_SRCCOLORKEY, key);
00258                 }
00259 
00260                 m_surface = SDL_DisplayFormatAlpha(m_surface);
00261             }
00262         }
00263         SDL_FreeSurface(old_surface);
00264     }
00265 
00266     SDL_Surface* SDLImage::optimize(SDL_Surface* src) {
00267         // The algorithm is originally by "Tim Goya" <tuxdev103@gmail.com>
00268         // Few modifications and adaptions by the FIFE team.
00269         //
00270         // It tries to determine whether an image with a alpha channel
00271         // actually uses that. Often PNGs contains an alpha channels
00272         // as they don't provide a colorkey feature(?) - so to speed
00273         // up SDL rendering we try to remove the alpha channel.
00274 
00275         // As a reminder: src->format->Amask != 0 here
00276 
00277         int transparent = 0;
00278         int opaque = 0;
00279         int semitransparent = 0;
00280         int alphasum = 0;
00281         int alphasquaresum = 0;
00282         bool colors[(1 << 12)];
00283         memset(colors, 0, (1 << 12) * sizeof(bool));
00284 
00285         int bpp = src->format->BytesPerPixel;
00286         if(SDL_MUSTLOCK(src)) {
00287             SDL_LockSurface(src);
00288         }
00289         /*  In the first pass through we calculate avg(alpha), avg(alpha^2)
00290             and the number of semitransparent pixels.
00291             We also try to find a useable color.
00292         */
00293         for(int y = 0;y < src->h;y++) {
00294             for(int x = 0;x < src->w;x++) {
00295                 Uint8 *pixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
00296                 Uint32 mapped = 0;
00297                 switch(bpp) {
00298                     case 1:
00299                         mapped = *pixel;
00300                         break;
00301                     case 2:
00302                         mapped = *(Uint16 *)pixel;
00303                         break;
00304                     case 3:
00305 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00306                         mapped |= pixel[0] << 16;
00307                         mapped |= pixel[1] << 8;
00308                         mapped |= pixel[2] << 0;
00309 #else
00310                         mapped |= pixel[0] << 0;
00311                         mapped |= pixel[1] << 8;
00312                         mapped |= pixel[2] << 16;
00313 #endif
00314                         break;
00315                     case 4:
00316                         mapped = *(Uint32 *)pixel;
00317                         break;
00318                 }
00319                 Uint8 red, green, blue, alpha;
00320                 SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
00321                 if(alpha < 16) {
00322                     transparent++;
00323                 } else if (alpha > 240) {
00324                     opaque++;
00325                     alphasum += alpha;
00326                     alphasquaresum += alpha*alpha;
00327                 } else {
00328                     semitransparent++;
00329                     alphasum += alpha;
00330                     alphasquaresum += alpha*alpha;
00331                 }
00332                 // mark the color as used.
00333                 if( alpha != 0 ) {
00334                     colors[((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0) >> 4)] = true;
00335                 }
00336             }
00337         }
00338         int avgalpha = (opaque + semitransparent) ? alphasum / (opaque + semitransparent) : 0;
00339         int alphavariance = 0;
00340 
00341         if(SDL_MUSTLOCK(src)) {
00342             SDL_UnlockSurface(src);
00343         }
00344         alphasquaresum /= (opaque + semitransparent) ? (opaque + semitransparent) : 1;
00345         alphavariance = alphasquaresum - avgalpha*avgalpha;
00346         if(semitransparent > ((transparent + opaque + semitransparent) / 8)
00347            && alphavariance > 16) {
00348             FL_DBG(_log, LMsg("sdlimage")
00349                 << "Trying to alpha-optimize image. FAILED: real alpha usage. "
00350                 << " alphavariance=" << alphavariance
00351                 << " total=" << (transparent + opaque + semitransparent)
00352                 << " semitransparent=" << semitransparent
00353                 << "(" << (float(semitransparent)/(transparent + opaque + semitransparent))
00354                 << ")");
00355             return SDL_DisplayFormatAlpha(src);
00356         }
00357 
00358         // check availability of a suitable color as colorkey
00359         int keycolor = -1;
00360         for(int i = 0;i < (1 << 12);i++) {
00361             if(!colors[i]) {
00362                 keycolor = i;
00363                 break;
00364             }
00365         }
00366         if(keycolor == -1) {
00367             FL_DBG(_log, LMsg("sdlimage") << "Trying to alpha-optimize image. FAILED: no free color");
00368             return SDL_DisplayFormatAlpha(src);
00369         }
00370 
00371         SDL_Surface *dst = SDL_CreateRGBSurface(src->flags & ~(SDL_SRCALPHA) | SDL_SWSURFACE,
00372                                                 src->w, src->h,
00373                                                 src->format->BitsPerPixel,
00374                                                 src->format->Rmask,  src->format->Gmask,
00375                                                 src->format->Bmask, 0);
00376         bpp = dst->format->BytesPerPixel;
00377         
00378         Uint32 key = SDL_MapRGB(dst->format, m_colorkey.r, m_colorkey.g, m_colorkey.b);
00379 
00380         // if the global color key feature is disabled, then use the manually found color key
00381         if (!RenderBackend::instance()->isColorKeyEnabled()) {
00382             key = SDL_MapRGB(dst->format,
00383                             (((keycolor & 0xf00) >> 4) | 0xf),
00384                             ((keycolor & 0xf0) | 0xf),
00385                             (((keycolor & 0xf) << 4) | 0xf));
00386         }
00387         
00388         if(SDL_MUSTLOCK(src)) {
00389             SDL_LockSurface(src);
00390         }
00391         if(SDL_MUSTLOCK(dst)) {
00392             SDL_LockSurface(dst);
00393         }
00394         for(int y = 0;y < dst->h;y++) {
00395             for(int x = 0;x < dst->w;x++) {
00396                 Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
00397                 Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
00398                 Uint32 mapped = 0;
00399                 switch(bpp) {
00400                     case 1:
00401                         mapped = *srcpixel;
00402                         break;
00403                     case 2:
00404                         mapped = *(Uint16 *)srcpixel;
00405                         break;
00406                     case 3:
00407 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00408                         mapped |= srcpixel[0] << 16;
00409                         mapped |= srcpixel[1] << 8;
00410                         mapped |= srcpixel[2] << 0;
00411 #else
00412                         mapped |= srcpixel[0] << 0;
00413                         mapped |= srcpixel[1] << 8;
00414                         mapped |= srcpixel[2] << 16;
00415 #endif
00416                         break;
00417                     case 4:
00418                         mapped = *(Uint32 *)srcpixel;
00419                         break;
00420                 }
00421                 Uint8 red, green, blue, alpha;
00422                 SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha);
00423                 if(alpha < (avgalpha / 4)) {
00424                     mapped = key;
00425                 } else {
00426                     mapped = SDL_MapRGB(dst->format, red, green, blue);
00427                 }
00428                 switch(bpp) {
00429                     case 1:
00430                         *dstpixel = mapped;
00431                         break;
00432                     case 2:
00433                         *(Uint16 *)dstpixel = mapped;
00434                         break;
00435                     case 3:
00436 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00437                         dstpixel[0] = (mapped >> 16) & 0xff;
00438                         dstpixel[1] = (mapped >> 8) & 0xff;
00439                         dstpixel[2] = (mapped >> 0) & 0xff;
00440 #else
00441                         dstpixel[0] = (mapped >> 0) & 0xff;
00442                         dstpixel[1] = (mapped >> 8) & 0xff;
00443                         dstpixel[2] = (mapped >> 16) & 0xff;
00444 #endif
00445                         break;
00446                     case 4:
00447                         *(Uint32 *)dstpixel = mapped;
00448                         break;
00449                 }
00450             }
00451         }
00452         if(SDL_MUSTLOCK(dst)) {
00453             SDL_UnlockSurface(dst);
00454         }
00455         if(SDL_MUSTLOCK(src)) {
00456             SDL_UnlockSurface(src);
00457         }
00458         // Using the per surface alpha value does not
00459         // work out for mostly transparent pixels.
00460         // Thus disabling the part here - this needs a
00461         // more complex refactoring.
00462         // if(avgalpha < 240) {
00463         //  SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, avgalpha);
00464         //}
00465         SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, key);
00466         SDL_Surface *convert = SDL_DisplayFormat(dst);
00467         SDL_FreeSurface(dst);
00468         FL_DBG(_log, LMsg("sdlimage ")
00469             << "Trying to alpha-optimize image. SUCCESS: colorkey is " << key);
00470         return convert;
00471     } // end optimize
00472 
00473     bool SDLImage::putPixel(int x, int y, int r, int g, int b) {
00474         if ((x < 0) || (x >= m_surface->w) || (y < 0) || (y >= m_surface->h)) {
00475             return false;
00476         }
00477 
00478         int bpp = m_surface->format->BytesPerPixel;
00479         SDL_LockSurface(m_surface);
00480         Uint8* p = (Uint8*)m_surface->pixels + y * m_surface->pitch + x * bpp;
00481         Uint32 pixel = SDL_MapRGB(m_surface->format, r, g, b);
00482         switch(bpp)
00483         {
00484             case 1:
00485                 *p = pixel;
00486                 break;
00487 
00488             case 2:
00489                 *(Uint16 *)p = pixel;
00490                 break;
00491 
00492             case 3:
00493                 if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00494                     p[0] = (pixel >> 16) & 0xff;
00495                     p[1] = (pixel >> 8) & 0xff;
00496                     p[2] = pixel & 0xff;
00497                 }
00498                 else {
00499                     p[0] = pixel & 0xff;
00500                     p[1] = (pixel >> 8) & 0xff;
00501                     p[2] = (pixel >> 16) & 0xff;
00502                 }
00503                 break;
00504 
00505             case 4:
00506                 *(Uint32 *)p = pixel;
00507                 break;
00508         }
00509         SDL_UnlockSurface(m_surface);
00510         return true;
00511     }
00512 
00513     void SDLImage::drawLine(const Point& p1, const Point& p2, int r, int g, int b) {
00514         // Draw a line with Bresenham, imitated from guichan
00515         int x1 = p1.x;
00516         int x2 = p2.x;
00517         int y1 = p1.y;
00518         int y2 = p2.y;
00519         int dx = ABS(x2 - x1);
00520         int dy = ABS(y2 - y1);
00521 
00522         if (dx > dy) {
00523             if (x1 > x2) {
00524                 // swap x1, x2
00525                 x1 ^= x2;
00526                 x2 ^= x1;
00527                 x1 ^= x2;
00528 
00529                 // swap y1, y2
00530                 y1 ^= y2;
00531                 y2 ^= y1;
00532                 y1 ^= y2;
00533             }
00534 
00535             if (y1 < y2) {
00536                 int y = y1;
00537                 int p = 0;
00538 
00539                 for (int x = x1; x <= x2; x++) {
00540                     putPixel(x, y, r, g, b);
00541                     p += dy;
00542                     if (p * 2 >= dx) {
00543                         y++;
00544                         p -= dx;
00545                     }
00546                 }
00547             }
00548             else {
00549                 int y = y1;
00550                 int p = 0;
00551 
00552                 for (int x = x1; x <= x2; x++) {
00553                     putPixel(x, y, r, g, b);
00554 
00555                     p += dy;
00556                     if (p * 2 >= dx) {
00557                         y--;
00558                         p -= dx;
00559                     }
00560                 }
00561             }
00562         }
00563         else {
00564             if (y1 > y2) {
00565                 // swap y1, y2
00566                 y1 ^= y2;
00567                 y2 ^= y1;
00568                 y1 ^= y2;
00569 
00570                 // swap x1, x2
00571                 x1 ^= x2;
00572                 x2 ^= x1;
00573                 x1 ^= x2;
00574             }
00575 
00576             if (x1 < x2) {
00577                 int x = x1;
00578                 int p = 0;
00579 
00580                 for (int y = y1; y <= y2; y++) {
00581                     putPixel(x, y, r, g, b);
00582                     p += dx;
00583                     if (p * 2 >= dy) {
00584                         x++;
00585                         p -= dy;
00586                     }
00587                 }
00588             }
00589             else {
00590                 int x = x1;
00591                 int p = 0;
00592 
00593                 for (int y = y1; y <= y2; y++) {
00594                     putPixel(x, y, r, g, b);
00595                     p += dx;
00596                     if (p * 2 >= dy) {
00597                         x--;
00598                         p -= dy;
00599                     }
00600                 }
00601             }
00602         }
00603     }
00604 
00605     void SDLImage::drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4,  int r, int g, int b) {
00606         drawLine(p1, p2, r, g, b);
00607         drawLine(p2, p3, r, g, b);
00608         drawLine(p3, p4, r, g, b);
00609         drawLine(p4, p1, r, g, b);
00610     }
00611 
00612     void SDLImage::drawVertex(const Point& p, const uint8_t size, int r, int g, int b){
00613         Point p1 = Point(p.x-size, p.y+size);
00614         Point p2 = Point(p.x+size, p.y+size);
00615         Point p3 = Point(p.x+size, p.y-size);
00616         Point p4 = Point(p.x-size, p.y-size);
00617 
00618         drawLine(p1, p2, r, g, b);
00619         drawLine(p2, p3, r, g, b);
00620         drawLine(p3, p4, r, g, b);
00621         drawLine(p4, p1, r, g, b);
00622     }
00623 
00624     void SDLImage::saveImage(const std::string& filename) {
00625         if(m_surface) {
00626             const unsigned int swidth = getWidth();
00627             const unsigned int sheight = getHeight();
00628             Uint32 rmask, gmask, bmask, amask;
00629             SDL_Surface *surface = NULL;
00630 
00631             #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00632             rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff;
00633             #else
00634             rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000;
00635             #endif
00636 
00637             surface = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth,
00638                 sheight, 24,
00639                 rmask, gmask, bmask, 0);
00640 
00641             if(surface == NULL) {
00642                 return;
00643             }
00644 
00645             SDL_BlitSurface(m_surface, NULL, surface, NULL);
00646 
00647             saveAsPng(filename, *surface);
00648             SDL_FreeSurface(surface);
00649         }
00650     }
00651 
00652     void SDLImage::setClipArea(const Rect& cliparea, bool clear) {
00653         SDL_Rect rect;
00654         rect.x = cliparea.x;
00655         rect.y = cliparea.y;
00656         rect.w = cliparea.w;
00657         rect.h = cliparea.h;
00658         SDL_SetClipRect(m_surface, &rect);
00659         if (clear) {
00660             SDL_FillRect(m_surface, &rect, 0x00);
00661         }
00662     }
00663 }