OSDLImage.cc

Go to the documentation of this file.
00001 #include "OSDLImage.h"
00002 
00003 #include "OSDLVideo.h"              // for VideoModule
00004 #include "OSDLUtils.h"              // for getBackendLastError
00005 #include "OSDLSurface.h"
00006 #include "OSDLPixel.h"
00007 
00008 
00009 #include "SDL_image.h"              // for IMG_GetError and al
00010 
00011 #include "png.h"                    // for png_structp and many others
00012 
00013 
00014 #ifdef OSDL_USES_CONFIG_H
00015 #include <OSDLConfig.h>             // for OSDL_DEBUG and al 
00016 #endif // OSDL_USES_CONFIG_H
00017 
00018 
00019 using std::string ;
00020 
00021 using namespace Ceylan::Log ;
00022 using namespace Ceylan::System ;
00023 
00024 using namespace OSDL::Video ;
00025 using namespace OSDL::Video::TwoDimensional ;
00026 
00027 
00029 
00030 const string Image::JPGTag  = "JPG" ;
00031 const string Image::PNGTag  = "PNG" ;
00032 
00033 
00035 
00036 const string Image::BMPTag  = "BMP" ;
00037 const string Image::GIFTag  = "GIF" ;
00038 const string Image::LBMTag  = "LBM" ;
00039 const string Image::PCXTag  = "PCX" ;
00040 const string Image::PNMTag  = "PNM" ;
00041 const string Image::TGATag  = "TGA" ;
00042 const string Image::XPMTag  = "XPM" ;
00043 
00044 
00045 
00046 ImageException::ImageException( const std::string & reason ) throw() :
00047     VideoException( reason )
00048 {
00049 
00050 }
00051 
00052 
00053 ImageException::~ImageException() throw()
00054 {
00055 
00056 }
00057     
00058 
00059 
00065 Image::Image( const string & filename ) throw( ImageException ) 
00066 {
00067 
00068 }
00069 
00070 
00071 Image::~Image() throw() 
00072 {
00073 
00074 }   
00075 
00076 
00077 Surface & Image::LoadIcon( const string & filename, 
00078     Pixels::ColorElement ** mask ) throw( ImageException )
00079 {
00080 
00081     // Adapted from SDL example (testwm.c).
00082     
00083 #if OSDL_DEBUG_IMAGE
00084     LogPlug::debug( "Loading icon." ) ;
00085 #endif // OSDL_DEBUG_IMAGE
00086 
00087     // Do not convert to display, setMode should not have been called already !
00088     
00089     // Image format should be auto-detected :
00090     Surface & iconSurface = Surface::LoadImage( filename, 
00091         /* blitOnly */ false, /* convertToDisplay */ false ) ;
00092 
00093     
00094 #if OSDL_DEBUG_IMAGE
00095     LogPlug::debug( "Icon loaded." ) ;
00096     
00097     LogPlug::debug( "Displaying icon informations : " 
00098         + iconSurface.toString() ) ;
00099 #endif // OSDL_DEBUG_IMAGE
00100     
00101     if ( iconSurface.getPixelFormat().palette == 0 ) 
00102     {
00103     
00104         delete & iconSurface ;
00105         throw ImageException( "Image::LoadIcon : image " + filename
00106             + " does not seem to have a palette as it should." ) ;
00107                         
00108     }
00109     
00110     // Use upper left pixel index as color key :
00111     iconSurface.setColorKey( Surface::ColorkeyBlit, 
00112             * ( (Pixels::ColorElement *) iconSurface.getPixels() ) ) ;
00113 
00114     ColorElement * pixels = (ColorElement *) iconSurface.getPixels() ;
00115     
00116 #if OSDL_DEBUG_IMAGE
00117 
00118     LogPlug::debug( "Image::LoadIcon : index of upper left pixel is "
00119         + Ceylan::toString( static_cast<unsigned short>( *pixels ) ) ) ;
00120     
00121     LogPlug::debug( "Image::LoadIcon : transparent pixel is : "
00122         + Pixels::toString(
00123             iconSurface.getPixelFormat().palette->colors[*pixels] ) ) ;
00124 
00125 
00126     LogPlug::debug( 
00127         "Creating image mask (one bit per image pixel, rounded up)" ) ;
00128         
00129 #endif // OSDL_DEBUG_IMAGE
00130         
00131     int maskLen = ( iconSurface.getWidth() * iconSurface.getHeight() + 7 ) / 8 ;
00132     ColorElement * constructedMask = new ColorElement[ maskLen ] ;
00133     
00134     if ( constructedMask == 0 ) 
00135     {
00136         delete & iconSurface ;
00137         throw ImageException( "Image::LoadIcon : not enough memory." ) ;
00138     }
00139     
00140     ::memset( constructedMask, 0, maskLen ) ;
00141     
00142     int paletteIndex ;
00143     int maskIndex ;
00144     
00145     
00146     for ( Coordinate i = 0; i < iconSurface.getHeight(); i++ )
00147     {
00148     
00149         //LogPlug::debug( "Scanning line [ " + Ceylan::toString( i ) + "]" ) ;
00150          
00151         for ( Coordinate j = 0; j < iconSurface.getWidth(); j++ ) 
00152         {
00153         
00154             /*
00155              *
00156              
00157             LogPlug::debug( "Scanning pixel [ " 
00158                 + Ceylan::toString( j ) + " ]" ) ;
00159                 
00160              *
00161              */
00162                 
00163             paletteIndex = i * iconSurface.getPitch() + j ;
00164             maskIndex    = i * iconSurface.getWidth() + j ;
00165             
00166             /*
00167              * Write the corresponding bit to 1 when current pixel is 
00168              * not the color key :
00169              *
00170              */
00171             if ( pixels[ paletteIndex ] != *pixels )
00172                 constructedMask[ maskIndex >>3 ] |= 
00173                     1 << ( 7 - ( maskIndex & 7) ) ;
00174         }
00175         
00176     }   
00177 
00178 #if OSDL_DEBUG_IMAGE    
00179     LogPlug::debug( "Icon scanned." ) ;
00180 #endif // OSDL_DEBUG_IMAGE
00181     
00182     *mask = constructedMask ;
00183     
00184 #if OSDL_DEBUG_IMAGE
00185     LogPlug::debug( "Icon fully loaded." ) ;
00186 #endif // OSDL_DEBUG_IMAGE
00187     
00188     return iconSurface ;
00189     
00190 }
00191 
00192 
00193 
00194 void Image::Load( Surface & targetSurface, const std::string & filename, 
00195         bool blitOnly, bool convertToDisplay, bool convertWithAlpha ) 
00196     throw( ImageException )
00197 {
00198 
00199 #if OSDL_DEBUG_IMAGE    
00200     LogPlug::debug( "Image::Load : loading image from " + filename ) ;
00201 #endif // OSDL_DEBUG_IMAGE
00202     
00203     if ( ! File::Exists( filename ) )
00204         throw ImageException( "Unable to load JPG file " + filename 
00205             + " : file not found." ) ;
00206             
00207     SDL_Surface * image = IMG_Load( filename.c_str() ) ;    
00208         
00209     if ( image == 0 ) 
00210         throw ImageException( "Unable to load image stored in " + filename 
00211             + " thanks to IMG_Load : "
00212             + string( IMG_GetError() ) ) ;   
00213             
00214 #if OSDL_DEBUG_IMAGE    
00215     LogPlug::debug( "Image loaded." ) ;
00216 #endif // OSDL_DEBUG_IMAGE
00217     
00218     /*
00219      * If conversion to display format is needed, substitute the 
00220      * converted image to the loaded one :
00221      *
00222      */
00223     
00224     if ( convertToDisplay )
00225     {
00226     
00227         if ( ! VideoModule::IsDisplayInitialized() )
00228             throw ImageException( 
00229                 "Image::Load called with request to convert surface "
00230                 "to display, whereas display not initialized "
00231                 "(VideoModule::setMode never called)." ) ;
00232                 
00233         SDL_Surface * formattedImage ;
00234         
00235         /*
00236          * SDL_DisplayFormat* copies the surface, which therefore is 
00237          * to be deallocated :
00238          *
00239          */
00240         
00241         if ( convertWithAlpha )
00242         {
00243         
00244 #if OSDL_DEBUG_IMAGE    
00245             LogPlug::debug( 
00246                 "Converting image to display format, with alpha." ) ;
00247 #endif // OSDL_DEBUG_IMAGE
00248 
00249             formattedImage = SDL_DisplayFormatAlpha( image ) ;  
00250             
00251         }
00252         else
00253         {
00254         
00255 #if OSDL_DEBUG_IMAGE    
00256             LogPlug::debug( "Converting image to display format, no alpha." ) ;
00257 #endif // OSDL_DEBUG_IMAGE
00258 
00259             formattedImage = SDL_DisplayFormat( image ) ;   
00260 
00261         }   
00262         
00263         SDL_FreeSurface( image ) ;
00264         
00265         image = formattedImage ;
00266         
00267         if ( image == 0 )
00268             throw ImageException( 
00269                 "Unable to convert to display the image loaded from " 
00270                 + filename + "." ) ;
00271         
00272     }
00273         
00274     /*
00275      * Now we have our image surface, we can either blit it or have 
00276      * it replace the former one :
00277      *
00278      */
00279             
00280     if ( blitOnly )
00281     {
00282     
00283         // We should blit the loaded image in already existing internal surface.
00284 #if OSDL_DEBUG_IMAGE    
00285         LogPlug::debug( "Blitting loaded image to already existing surface." ) ;
00286 #endif // OSDL_DEBUG_IMAGE
00287         
00288 #if OSDL_DEBUG
00289 
00290         if ( ! targetSurface.isInternalSurfaceAvailable() )
00291             throw ImageException( "Image::Load : trying to blit image "
00292                 "whereas target SDL_surface pointer is null" ) ;
00293                 
00294 #endif // OSDL_DEBUG
00295         
00296             
00297 #if OSDL_DEBUG
00298         
00299         // The target surface should not be locked :    
00300 
00301         if ( targetSurface.isLocked() )
00302             throw ImageException( "Image::Load : trying to blit an image "
00303                 "whereas target surface is locked" ) ;
00304                 
00305 #endif // OSDL_DEBUG
00306         
00307         int result = SDL_BlitSurface( image, 0, 
00308             & targetSurface.getSDLSurface(), 0 ) ;
00309         
00310         if ( result == -1)
00311             throw ImageException( "Image::Load : error in blit : " 
00312                 + Utils::getBackendLastError() ) ;
00313     
00314         if ( result == -2 )
00315             throw ImageException( 
00316                 "Image::Load : video memory was lost during blit." ) ;
00317     
00318         /*
00319          * In this case, the loaded image has been used and therefore 
00320          * is not needed any more :
00321          *
00322          */
00323      
00324         SDL_FreeSurface( image ) ;      
00325         
00326     }
00327     else
00328     {
00329     
00330 #if OSDL_DEBUG_IMAGE    
00331         LogPlug::debug( "Replacing already existing image by loaded one." ) ; 
00332 #endif // OSDL_DEBUG
00333         
00334         /*
00335          * Simply replace the former internal surface by this new one.
00336          * The former surface gets automatically deallocated by setSDLSurface.
00337          *
00338          * The target surface is, from now on, the new owner of the buffer
00339          * pointed to by the image pointer.
00340          *
00341          */
00342 
00343         targetSurface.setSDLSurface( * image ) ;
00344         
00345     }
00346     
00347     
00348     /*
00349      * In all cases :
00350      *  - no memory leak should occur with the internal surface, since 
00351      * blit does not change anything for that, and replacement triggers
00352      * deallocation
00353      *  - any used temporary surface got deallocated (it is the case 
00354      * for display format conversion and for blitted image)
00355      *
00356      */  
00357     
00358 #if OSDL_DEBUG_IMAGE    
00359     LogPlug::debug( "Image loaded." ) ;
00360 #endif // OSDL_DEBUG
00361     
00362 }
00363     
00364 
00365 
00366 void Image::LoadJPG( Surface & targetSurface, const std::string & filename, 
00367         bool blitOnly, bool convertToDisplay, bool convertWithAlpha ) 
00368     throw( ImageException )
00369 {
00370 
00371     if ( ! File::Exists( filename ) )
00372         throw ImageException( "Unable to load JPG file " 
00373             + filename + " : file not found." ) ;
00374             
00375     SDL_Surface * image ;
00376     
00377     image = IMG_LoadTyped_RW( SDL_RWFromFile( filename.c_str(), "rb" ), 
00378         1, const_cast<char *>( JPGTag.c_str() ) ) ;
00379                     
00380     if ( image == 0 ) 
00381         throw ImageException( "Unable to load JPG image stored in " + filename 
00382             + " thanks to IMG_Load_RW : "
00383             + string( IMG_GetError() ) ) ;   
00384     
00385     
00386     /*
00387      * If conversion to display format is needed, substitute the 
00388      * converted image to the loaded one :
00389      *
00390      */
00391     
00392     if ( convertToDisplay )
00393     {
00394 
00395         if ( ! VideoModule::IsDisplayInitialized() )
00396             throw ImageException( 
00397                 "Image::LoadJPG called with request to convert surface "
00398                 "to display, whereas display not initialized "
00399                 "(VideoModule::setMode never called)." ) ;
00400     
00401         SDL_Surface * formattedImage ;
00402         
00403         /*
00404          * SDL_DisplayFormat* copies the surface, which therefore is to 
00405          * be deallocated :
00406          *
00407          */
00408         
00409         if ( convertWithAlpha )
00410         {
00411         
00412             formattedImage = SDL_DisplayFormatAlpha( image ) ;  
00413             
00414         }
00415         else
00416         {
00417         
00418             formattedImage = SDL_DisplayFormat( image ) ;   
00419         
00420         }   
00421         
00422         SDL_FreeSurface( image ) ;
00423         
00424         image = formattedImage ;
00425         
00426     }
00427         
00428     /*
00429      * Now we have our image surface, we can either blit it or have 
00430      * it replace the former one :
00431      *
00432      */
00433             
00434     if ( blitOnly )
00435     {
00436     
00437         // We should blit the loaded image in already existing internal surface.
00438         
00439 #if OSDL_DEBUG
00440 
00441         if ( ! targetSurface.isInternalSurfaceAvailable() )
00442             throw ImageException( "Image::LoadJPG : trying to blit image "
00443                 "whereas target SDL_surface pointer is null" ) ;
00444                 
00445 #endif // OSDL_DEBUG
00446         
00447             
00448 #if OSDL_DEBUG
00449         
00450         // The target surface should not be locked :    
00451 
00452         if ( targetSurface.isLocked() )
00453             throw ImageException( "Image::LoadJPG : trying to blit an image "
00454                 "whereas target surface is locked" ) ;
00455                 
00456 #endif // OSDL_DEBUG
00457         
00458 
00459         int result = SDL_BlitSurface( image, 0, 
00460             & targetSurface.getSDLSurface(), 0 ) ;
00461         
00462         if ( result == -1)
00463             throw ImageException( "Image::LoadJPG : error in blit : " 
00464                 + Utils::getBackendLastError() ) ;
00465     
00466         if ( result == -2 )
00467             throw ImageException( 
00468                 "Image::LoadJPG : video memory was lost during blit." ) ;
00469     
00470 
00471         /*
00472          * In this case, the loaded image has been used and therefore 
00473          * is not needed any more :
00474          *
00475          */
00476      
00477         SDL_FreeSurface( image ) ;      
00478         
00479     }
00480     else
00481     {
00482     
00483         /*
00484          * Simply replace the former internal surface by this new one.
00485          * The former surface gets automatically deallocated by setSDLSurface.
00486          * The target surface is, from now on, the new owner of the 
00487          * buffer pointed to by the image pointer.
00488          *
00489          */
00490 
00491         targetSurface.setSDLSurface( * image ) ;
00492     }
00493     
00494     
00495     /*
00496      * In all cases :
00497      *  - no memory leak should occur with the internal surface, since 
00498      * blit does not change anything for that, and replacement triggers
00499      * deallocation
00500      *  - any used temporary surface got deallocated (it is the case 
00501      * for display format conversion and for blitted image)
00502      *
00503      */  
00504     
00505 }
00506     
00507     
00508     
00509 void Image::LoadPNG( Surface & targetSurface, const std::string & filename, 
00510         bool blitOnly, bool convertToDisplay, bool convertWithAlpha ) 
00511     throw( ImageException )
00512 {
00513 
00514     if ( ! File::Exists( filename ) )
00515         throw ImageException( "Unable to load PNG file " 
00516             + filename + " : file not found." ) ;
00517             
00518     SDL_Surface * image ;
00519         
00520     image = IMG_LoadTyped_RW( SDL_RWFromFile( filename.c_str(), "rb" ), 
00521         1, const_cast<char *>( PNGTag.c_str() ) ) ;
00522     
00523     if ( image == 0 ) 
00524         throw ImageException( "Unable to load PNG image stored in " 
00525             + filename + " thanks to IMG_Load_RW : "
00526             + string( IMG_GetError() ) ) ;   
00527     
00528     
00529     /*
00530      * If conversion to display format is needed, substitute the 
00531      * converted image to the loaded one :
00532      *
00533      */
00534     
00535     if ( convertToDisplay )
00536     {
00537 
00538         if ( ! VideoModule::IsDisplayInitialized() )
00539             throw ImageException( 
00540                 "Image::LoadPNG called with request to convert surface "
00541                 "to display, whereas display not initialized "
00542                 "(VideoModule::setMode never called)." ) ;
00543     
00544         SDL_Surface * formattedImage ;
00545         
00546         /*
00547          * SDL_DisplayFormat* copies the surface, which therefore is 
00548          * to be deallocated :
00549          *
00550          */
00551         
00552         if ( convertWithAlpha )
00553         {
00554         
00555             formattedImage = SDL_DisplayFormatAlpha( image ) ;  
00556             
00557         }
00558         else
00559         {
00560         
00561             formattedImage = SDL_DisplayFormat( image ) ;   
00562         
00563         }   
00564         
00565         SDL_FreeSurface( image ) ;
00566         
00567         image = formattedImage ;
00568         
00569     }
00570         
00571     /*
00572      * Now we have our image surface, we can either blit it or have 
00573      * it replace the former one :
00574      *
00575      */
00576             
00577     if ( blitOnly )
00578     {
00579     
00580         // We should blit the loaded image in already existing internal surface.
00581         
00582 #if OSDL_DEBUG
00583 
00584         if ( ! targetSurface.isInternalSurfaceAvailable() )
00585             throw ImageException( "Image::LoadPNG : trying to blit image "
00586                 "whereas target SDL_surface pointer is null" ) ;
00587                 
00588 #endif // OSDL_DEBUG
00589         
00590             
00591 #if OSDL_DEBUG
00592         
00593         // The target surface should not be locked :    
00594 
00595         if ( targetSurface.isLocked() )
00596             throw ImageException( "Image::LoadPNG : trying to blit an image "
00597                 "whereas target surface is locked" ) ;
00598                 
00599 #endif // OSDL_DEBUG
00600         
00601         int result = SDL_BlitSurface( image, 0, 
00602             & targetSurface.getSDLSurface(), 0 ) ;
00603         
00604         if ( result == -1)
00605             throw ImageException( "Image::LoadPNG : error in blit : " 
00606                 + Utils::getBackendLastError() ) ;
00607     
00608         if ( result == -2 )
00609             throw ImageException( 
00610                 "Image::LoadPNG : video memory was lost during blit." ) ;
00611 
00612         /*
00613          * In this case, the loaded image has been used and therefore 
00614          * is not needed any more :
00615          *
00616          */
00617      
00618         SDL_FreeSurface( image ) ;      
00619         
00620     }
00621     else
00622     {
00623     
00624         /*
00625          * Simply replace the former internal surface by this new one.
00626          * The former surface gets automatically deallocated by setSDLSurface.
00627          * The target surface is, from now on, the new owner of the 
00628          * buffer pointed to by the image pointer.
00629          *
00630          */
00631          
00632         targetSurface.setSDLSurface( * image ) ;
00633         
00634     }
00635     
00636     /*
00637      * In all cases :
00638      *  - no memory leak should occur with the internal surface, since 
00639      * blit does not change
00640      * anything for that, and replacement triggers deallocation
00641      *  - any used temporary surface got deallocated (it is the case 
00642      * for display format conversion and for blitted image)
00643      *
00644      */ 
00645     
00646 }
00647     
00648     
00649 void Image::LoadBMP( Surface & targetSurface, const std::string & filename, 
00650         bool blitOnly, bool convertToDisplay, bool convertWithAlpha ) 
00651     throw( ImageException )
00652 {
00653 
00654     if ( ! File::Exists( filename ) )
00655         throw ImageException( "Unable to load BMP file " 
00656             + filename + " : file not found." ) ;
00657             
00658     SDL_Surface * image ;
00659     
00660     image = IMG_LoadTyped_RW( SDL_RWFromFile( filename.c_str(), "rb" ), 
00661         1, const_cast<char *>( BMPTag.c_str() ) ) ;
00662             
00663     if ( image == 0 ) 
00664         throw ImageException( "Unable to load BMP image stored in " 
00665             + filename 
00666             + " thanks to IMG_Load_RW : "
00667             + string( IMG_GetError() ) ) ;   
00668     
00669     
00670     /*
00671      * If conversion to display format is needed, substitute the 
00672      * converted image to the loaded one :
00673      *
00674      */
00675     
00676     if ( convertToDisplay )
00677     {
00678 
00679         if ( ! VideoModule::IsDisplayInitialized() )
00680             throw ImageException( 
00681                 "Image::LoadBMP called with request to convert surface "
00682                 "to display, whereas display not initialized "
00683                 "(VideoModule::setMode never called)." ) ;
00684     
00685         SDL_Surface * formattedImage ;
00686         
00687         /*
00688          * SDL_DisplayFormat* copies the surface, which therefore is 
00689          * to be deallocated :
00690          *
00691          */
00692         
00693         if ( convertWithAlpha )
00694         {
00695         
00696             formattedImage = SDL_DisplayFormatAlpha( image ) ;  
00697             
00698         }
00699         else
00700         {
00701         
00702             formattedImage = SDL_DisplayFormat( image ) ;   
00703         
00704         }   
00705         
00706         SDL_FreeSurface( image ) ;
00707         
00708         image = formattedImage ;
00709         
00710     }
00711         
00712     /*
00713      * Now we have our image surface, we can either blit it or have 
00714      * it replace the former one :
00715      *
00716      */
00717             
00718     if ( blitOnly )
00719     {
00720     
00721         // We should blit the loaded image in already existing internal surface.
00722         
00723 #if OSDL_DEBUG
00724 
00725         if ( ! targetSurface.isInternalSurfaceAvailable() )
00726             throw ImageException( "Image::LoadBMP : trying to blit image "
00727                 "whereas target SDL_surface pointer is null" ) ;
00728                 
00729 #endif // OSDL_DEBUG
00730         
00731             
00732 #if OSDL_DEBUG
00733         
00734         // The target surface should not be locked :    
00735 
00736         if ( targetSurface.isLocked() )
00737             throw ImageException( "Image::LoadBMP : trying to blit an image "
00738                 "whereas target surface is locked" ) ;
00739                 
00740 #endif // OSDL_DEBUG
00741         
00742         int result = SDL_BlitSurface( image, 0, 
00743             & targetSurface.getSDLSurface(), 0 ) ;
00744         
00745         if ( result == -1)
00746             throw ImageException( "Image::LoadBMP : error in blit : " 
00747                 + Utils::getBackendLastError() ) ;
00748     
00749         if ( result == -2 )
00750             throw ImageException( 
00751                 "Image::LoadBMP : video memory was lost during blit." ) ;
00752 
00753         /*
00754          * In this case, the loaded image has been used and therefore 
00755          * is not needed any more :
00756          *
00757          */
00758      
00759         SDL_FreeSurface( image ) ;      
00760         
00761     }
00762     else
00763     {
00764 
00765         /*
00766          * Simply replace the former internal surface by this new one.
00767          * The former surface gets automatically deallocated by setSDLSurface.
00768          *
00769          * The target surface is, from now on, the new owner of the 
00770          * buffer pointed to by the image pointer.
00771          *
00772          */
00773          
00774         targetSurface.setSDLSurface( * image ) ;
00775     }
00776     
00777     /*
00778      * In all cases :
00779      *  - no memory leak should occur with the internal surface, since 
00780      * blit does not change
00781      * anything for that, and replacement triggers deallocation
00782      *  - any used temporary surface got deallocated (it is the case 
00783      * for display format conversion and for blitted image)
00784      *
00785      */      
00786     
00787 }
00788         
00789     
00790     
00791 void Image::LoadGIF( Surface & targetSurface, const std::string & filename, 
00792         bool blitOnly, bool convertToDisplay, bool convertWithAlpha ) 
00793     throw( ImageException )
00794 {
00795 
00796     if ( ! File::Exists( filename ) )
00797         throw ImageException( "Unable to load GIF file " 
00798             + filename + " : file not found." ) ;
00799             
00800     SDL_Surface * image ;
00801     
00802     image = IMG_LoadTyped_RW( SDL_RWFromFile( filename.c_str(), "rb" ), 
00803         1, const_cast<char *>( GIFTag.c_str() ) ) ;
00804     
00805     if ( image == 0 ) 
00806         throw ImageException( "Unable to load GIF image stored in " + filename 
00807             + " thanks to IMG_Load_RW : "
00808             + string( IMG_GetError() ) ) ;   
00809     
00810     
00811     /*
00812      * If conversion to display format is needed, substitute the 
00813      * converted image to the loaded one :
00814      *
00815      */
00816     
00817     if ( convertToDisplay )
00818     {
00819     
00820         if ( ! VideoModule::IsDisplayInitialized() )
00821             throw ImageException( 
00822                 "Image::LoadGIF called with request to convert surface "
00823                 "to display, whereas display not initialized "
00824                 "(VideoModule::setMode never called)." ) ;
00825 
00826         SDL_Surface * formattedImage ;
00827         
00828         /*
00829          * SDL_DisplayFormat* copies the surface, which therefore is to 
00830          * be deallocated :
00831          *
00832          */
00833         
00834         if ( convertWithAlpha )
00835         {
00836         
00837             formattedImage = SDL_DisplayFormatAlpha( image ) ;  
00838             
00839         }
00840         else
00841         {
00842         
00843             formattedImage = SDL_DisplayFormat( image ) ;   
00844         
00845         }   
00846         
00847         SDL_FreeSurface( image ) ;
00848         
00849         image = formattedImage ;
00850         
00851     }
00852         
00853     /*
00854      * Now we have our image surface, we can either blit it or have 
00855      * it replace the former one :
00856      *
00857      */
00858             
00859     if ( blitOnly )
00860     {
00861         // We should blit the loaded image in already existing internal surface.
00862         
00863 #if OSDL_DEBUG
00864 
00865         if ( ! targetSurface.isInternalSurfaceAvailable() )
00866             throw ImageException( "Image::LoadGIF : trying to blit image "
00867                 "whereas target SDL_surface pointer is null" ) ;
00868                 
00869 #endif // OSDL_DEBUG
00870         
00871             
00872 #if OSDL_DEBUG
00873         
00874         // The target surface should not be locked :    
00875 
00876         if ( targetSurface.isLocked() )
00877             throw ImageException( "Image::LoadGIF : trying to blit an image "
00878                 "whereas target surface is locked" ) ;
00879                 
00880 #endif // OSDL_DEBUG
00881         
00882         int result = SDL_BlitSurface( image, 0, 
00883             & targetSurface.getSDLSurface(), 0 ) ;
00884         
00885         if ( result == -1)
00886             throw ImageException( "Image::LoadGIF : error in blit : " 
00887                 + Utils::getBackendLastError() ) ;
00888     
00889         if ( result == -2 )
00890             throw ImageException( 
00891                 "Image::LoadGIF : video memory was lost during blit." ) ;
00892 
00893         /*
00894          * In this case, the loaded image has been used and therefore 
00895          * is not needed any more :
00896          *
00897          */
00898      
00899         SDL_FreeSurface( image ) ;      
00900         
00901     }
00902     else
00903     {
00904 
00905         /*
00906          * Simply replace the former internal surface by this new one.
00907          * The former surface gets automatically deallocated by setSDLSurface.
00908          *
00909          * The target surface is, from now on, the new owner of the buffer
00910          * pointed to by the image pointer.
00911          *
00912          */
00913          
00914         targetSurface.setSDLSurface( * image ) ;
00915     }
00916     
00917     
00918     /*
00919      * In all cases :
00920      *  - no memory leak should occur with the internal surface, since 
00921      * blit does not change anything for that, and replacement triggers
00922      * deallocation
00923      *  - any used temporary surface got deallocated (it is the case for 
00924      * display format conversion and for blitted image)
00925      *
00926      */  
00927     
00928 }
00929     
00930     
00931 void Image::LoadLBM( Surface & targetSurface, const std::string & filename, 
00932         bool blitOnly, bool convertToDisplay, bool convertWithAlpha ) 
00933     throw( ImageException )
00934 {
00935 
00936     if ( ! File::Exists( filename ) )
00937         throw ImageException( "Unable to load LBM file " 
00938             + filename + " : file not found." ) ;
00939             
00940     SDL_Surface * image ;
00941         
00942     image = IMG_LoadTyped_RW( SDL_RWFromFile( filename.c_str(), "rb" ), 
00943         1, const_cast<char *>( LBMTag.c_str() ) ) ;
00944             
00945     if ( image == 0 ) 
00946         throw ImageException( "Unable to load LBM image stored in " + filename 
00947             + " thanks to IMG_Load_RW : "
00948             + string( IMG_GetError() ) ) ;   
00949     
00950     
00951     /*
00952      * If conversion to display format is needed, substitute the converted 
00953      * image to the loaded one :
00954      *
00955      */
00956     
00957     if ( convertToDisplay )
00958     {
00959     
00960         if ( ! VideoModule::IsDisplayInitialized() )
00961             throw ImageException( 
00962                 "Image::LoadLBM called with request to convert surface "
00963                 "to display, whereas display not initialized "
00964                 "(VideoModule::setMode never called)." ) ;
00965 
00966         SDL_Surface * formattedImage ;
00967         
00968         /*
00969          * SDL_DisplayFormat* copies the surface, which therefore is 
00970          * to be deallocated :
00971          *
00972          */
00973         
00974         if ( convertWithAlpha )
00975         {
00976         
00977             formattedImage = SDL_DisplayFormatAlpha( image ) ;  
00978             
00979         }
00980         else
00981         {
00982         
00983             formattedImage = SDL_DisplayFormat( image ) ;   
00984         
00985         }   
00986         
00987         SDL_FreeSurface( image ) ;
00988         
00989         image = formattedImage ;
00990         
00991     }
00992         
00993     /*
00994      * Now we have our image surface, we can either blit it or have 
00995      * it replace the former one :
00996      *
00997      */
00998             
00999     if ( blitOnly )
01000     {
01001         // We should blit the loaded image in already existing internal surface.
01002         
01003 #if OSDL_DEBUG
01004 
01005         if ( ! targetSurface.isInternalSurfaceAvailable() )
01006             throw ImageException( "Image::LoadLBM : trying to blit image "
01007                 "whereas target SDL_surface pointer is null" ) ;
01008                 
01009 #endif // OSDL_DEBUG
01010         
01011             
01012 #if OSDL_DEBUG
01013         
01014         // The target surface should not be locked :    
01015 
01016         if ( targetSurface.isLocked() )
01017             throw ImageException( "Image::LoadLBM : trying to blit an image "
01018                 "whereas target surface is locked" ) ;
01019                 
01020 #endif // OSDL_DEBUG
01021         
01022         int result = SDL_BlitSurface( image, 0, 
01023             & targetSurface.getSDLSurface(), 0 ) ;
01024         
01025         if ( result == -1)
01026             throw ImageException( "Image::LoadLBM : error in blit : " 
01027                 + Utils::getBackendLastError() ) ;
01028     
01029         if ( result == -2 )
01030             throw ImageException( 
01031                 "Image::LoadLBM : video memory was lost during blit." ) ;
01032 
01033         /*
01034          * In this case, the loaded image has been used and therefore 
01035          * is not needed any more :
01036          *
01037          */
01038      
01039         SDL_FreeSurface( image ) ;      
01040         
01041     }
01042     else
01043     {
01044     
01045         /*
01046          * Simply replace the former internal surface by this new one.
01047          *
01048          * The former surface gets automatically deallocated by setSDLSurface.
01049          *
01050          * The target surface is, from now on, the new owner of the buffer
01051          * pointed to by the image pointer.
01052          *
01053          */
01054          
01055         targetSurface.setSDLSurface( * image ) ;
01056     }
01057     
01058          
01059     /*
01060      * In all cases :
01061      *  - no memory leak should occur with the internal surface, since 
01062      * blit does not change anything for that, and replacement triggers
01063      * deallocation
01064      *  - any used temporary surface got deallocated (it is the case for 
01065      * display format conversion and for blitted image)
01066      *
01067      */  
01068      
01069 }
01070     
01071     
01072     
01073 void Image::LoadPCX( Surface & targetSurface, const std::string & filename, 
01074         bool blitOnly, bool convertToDisplay, bool convertWithAlpha ) 
01075     throw( ImageException )
01076 {
01077 
01078     if ( ! File::Exists( filename ) )
01079         throw ImageException( "Unable to load PCX file " 
01080             + filename + " : file not found." ) ;
01081             
01082     SDL_Surface * image ;
01083       
01084     image = IMG_LoadTyped_RW( SDL_RWFromFile( filename.c_str(), "rb" ), 
01085         1, const_cast<char *>( PCXTag.c_str() ) ) ;
01086             
01087     if ( image == 0 ) 
01088         throw ImageException( "Unable to load PCX image stored in " + filename 
01089             + " thanks to IMG_Load_RW : "
01090             + string( IMG_GetError() ) ) ;   
01091     
01092     
01093     /*
01094      * If conversion to display format is needed, substitute the converted 
01095      * image to the loaded one :
01096      *
01097      */
01098     
01099     if ( convertToDisplay )
01100     {
01101     
01102 
01103         if ( ! VideoModule::IsDisplayInitialized() )
01104             throw ImageException( 
01105                 "Image::LoadPCX called with request to convert surface "
01106                 "to display, whereas display not initialized "
01107                 "(VideoModule::setMode never called)." ) ;
01108 
01109         SDL_Surface * formattedImage ;
01110         
01111         /*
01112          * SDL_DisplayFormat* copies the surface, which therefore is 
01113          * to be deallocated :
01114          *
01115          */
01116         
01117         if ( convertWithAlpha )
01118         {
01119         
01120             formattedImage = SDL_DisplayFormatAlpha( image ) ;  
01121             
01122         }
01123         else
01124         {
01125         
01126             formattedImage = SDL_DisplayFormat( image ) ;   
01127         
01128         }   
01129         
01130         SDL_FreeSurface( image ) ;
01131         
01132         image = formattedImage ;
01133         
01134     }
01135         
01136     /*
01137      * Now we have our image surface, we can either blit it or have 
01138      * it replace the former one :
01139      *
01140      */
01141             
01142     if ( blitOnly )
01143     {
01144         // We should blit the loaded image in already existing internal surface.
01145         
01146 #if OSDL_DEBUG
01147 
01148         if ( ! targetSurface.isInternalSurfaceAvailable() )
01149             throw ImageException( "Image::LoadPCX : trying to blit image "
01150                 "whereas target SDL_surface pointer is null" ) ;
01151                 
01152 #endif // OSDL_DEBUG
01153         
01154             
01155 #if OSDL_DEBUG
01156         
01157         // The target surface should not be locked :    
01158 
01159         if ( targetSurface.isLocked() )
01160             throw ImageException( "Image::LoadPCX : trying to blit an image "
01161                 "whereas target surface is locked" ) ;
01162                 
01163 #endif // OSDL_DEBUG
01164         
01165         int result = SDL_BlitSurface( image, 0, 
01166             & targetSurface.getSDLSurface(), 0 ) ;
01167         
01168         if ( result == -1)
01169             throw ImageException( "Image::LoadPCX : error in blit : " 
01170                 + Utils::getBackendLastError() ) ;
01171     
01172         if ( result == -2 )
01173             throw ImageException( 
01174                 "Image::LoadPCX : video memory was lost during blit." ) ;
01175 
01176         /*
01177          * In this case, the loaded image has been used and therefore 
01178          * is not needed any more :
01179          *
01180          */
01181      
01182         SDL_FreeSurface( image ) ;      
01183         
01184     }
01185     else
01186     {
01187     
01188         /*
01189          * Simply replace the former internal surface by this new one.
01190          *
01191          * The former surface gets automatically deallocated by setSDLSurface.
01192          *
01193          * The target surface is, from now on, the new owner of the buffer
01194          * pointed to by the image pointer.
01195          *
01196          */
01197          
01198         targetSurface.setSDLSurface( * image ) ;
01199     }
01200     
01201     /*
01202      * In all cases :
01203      *  - no memory leak should occur with the internal surface, since 
01204      * blit does not change anything for that, and replacement triggers
01205      * deallocation
01206      *  - any used temporary surface got deallocated (it is the case for 
01207      * display format conversion and for blitted image)
01208      *
01209      */  
01210      
01211     
01212 }
01213     
01214     
01215 void Image::LoadPNM( Surface & targetSurface, const std::string & filename, 
01216         bool blitOnly, bool convertToDisplay, bool convertWithAlpha ) 
01217     throw( ImageException )
01218 {
01219 
01220     if ( ! File::Exists( filename ) )
01221         throw ImageException( "Unable to load PNM file " 
01222             + filename + " : file not found." ) ;
01223             
01224     SDL_Surface * image ;
01225         
01226     image = IMG_LoadTyped_RW( SDL_RWFromFile( filename.c_str(), "rb" ), 
01227         1, const_cast<char *>( PNMTag.c_str() ) ) ;
01228     
01229     if ( image == 0 ) 
01230         throw ImageException( "Unable to load PNM image stored in " + filename 
01231             + " thanks to IMG_Load_RW : "
01232             + string( IMG_GetError() ) ) ;   
01233     
01234     
01235     /*
01236      * If conversion to display format is needed, substitute the converted 
01237      * image to the loaded one :
01238      *
01239      */
01240     
01241     if ( convertToDisplay )
01242     {
01243 
01244         if ( ! VideoModule::IsDisplayInitialized() )
01245             throw ImageException( 
01246                 "Image::LoadPNM called with request to convert surface "
01247                 "to display, whereas display not initialized "
01248                 "(VideoModule::setMode never called)." ) ;
01249     
01250         SDL_Surface * formattedImage ;
01251         
01252         /*
01253          * SDL_DisplayFormat* copies the surface, which therefore is 
01254          * to be deallocated :
01255          *
01256          */
01257         
01258         if ( convertWithAlpha )
01259         {
01260         
01261             formattedImage = SDL_DisplayFormatAlpha( image ) ;  
01262             
01263         }
01264         else
01265         {
01266         
01267             formattedImage = SDL_DisplayFormat( image ) ;   
01268         
01269         }   
01270         
01271         SDL_FreeSurface( image ) ;
01272         
01273         image = formattedImage ;
01274         
01275     }
01276         
01277     /*
01278      * Now we have our image surface, we can either blit it or have 
01279      * it replace the former one :
01280      *
01281      */
01282             
01283     if ( blitOnly )
01284     {
01285         // We should blit the loaded image in already existing internal surface.
01286         
01287 #if OSDL_DEBUG
01288 
01289         if ( ! targetSurface.isInternalSurfaceAvailable() )
01290             throw ImageException( "Image::LoadPNM : trying to blit image "
01291                 "whereas target SDL_surface pointer is null" ) ;
01292                 
01293 #endif // OSDL_DEBUG
01294         
01295             
01296 #if OSDL_DEBUG
01297         
01298         // The target surface should not be locked :    
01299 
01300         if ( targetSurface.isLocked() )
01301             throw ImageException( "Image::LoadPNM : trying to blit an image "
01302                 "whereas target surface is locked" ) ;
01303 #endif // OSDL_DEBUG
01304         
01305         int result = SDL_BlitSurface( image, 0, 
01306             & targetSurface.getSDLSurface(), 0 ) ;
01307         
01308         if ( result == -1)
01309             throw ImageException( "Image::LoadPNM : error in blit : " 
01310                 + Utils::getBackendLastError() ) ;
01311     
01312         if ( result == -2 )
01313             throw ImageException( 
01314                 "Image::LoadPNM : video memory was lost during blit." ) ;
01315 
01316         /*
01317          * In this case, the loaded image has been used and therefore 
01318          * is not needed any more :
01319          *
01320          */
01321      
01322         SDL_FreeSurface( image ) ;      
01323         
01324     }
01325     else
01326     {
01327 
01328         /*
01329          * Simply replace the former internal surface by this new one.
01330          *
01331          * The former surface gets automatically deallocated by setSDLSurface.
01332          *
01333          * The target surface is, from now on, the new owner of the buffer
01334          * pointed to by the image pointer.
01335          *
01336          */
01337          
01338         targetSurface.setSDLSurface( * image ) ;
01339     }
01340     
01341     /*
01342      * In all cases :
01343      *  - no memory leak should occur with the internal surface, since 
01344      * blit does not change anything for that, and replacement triggers
01345      * deallocation
01346      *  - any used temporary surface got deallocated (it is the case for 
01347      * display format conversion and for blitted image)
01348      *
01349      */  
01350     
01351 }
01352     
01353     
01354 void Image::LoadTGA( Surface & targetSurface, const std::string & filename, 
01355         bool blitOnly, bool convertToDisplay, bool convertWithAlpha ) 
01356     throw( ImageException )
01357 {
01358 
01359     if ( ! File::Exists( filename ) )
01360         throw ImageException( "Unable to load TGA file " 
01361             + filename + " : file not found." ) ;
01362             
01363     SDL_Surface * image ;
01364         
01365     image = IMG_LoadTyped_RW( SDL_RWFromFile( filename.c_str(), "rb" ), 
01366         1, const_cast<char *>( TGATag.c_str() ) ) ;
01367         
01368     if ( image == 0 ) 
01369         throw ImageException( "Unable to load TGA image stored in " + filename 
01370             + " thanks to IMG_Load_RW : "
01371             + string( IMG_GetError() ) ) ;   
01372     
01373     
01374     /*
01375      * If conversion to display format is needed, substitute the converted 
01376      * image to the loaded one :
01377      *
01378      */
01379     
01380     if ( convertToDisplay )
01381     {
01382 
01383         if ( ! VideoModule::IsDisplayInitialized() )
01384             throw ImageException( 
01385                 "Image::LoadTGA called with request to convert surface "
01386                 "to display, whereas display not initialized "
01387                 "(VideoModule::setMode never called)." ) ;
01388     
01389         SDL_Surface * formattedImage ;
01390         
01391         /*
01392          * SDL_DisplayFormat* copies the surface, which therefore is 
01393          * to be deallocated :
01394          *
01395          */
01396         
01397         if ( convertWithAlpha )
01398         {
01399         
01400             formattedImage = SDL_DisplayFormatAlpha( image ) ;  
01401             
01402         }
01403         else
01404         {
01405         
01406             formattedImage = SDL_DisplayFormat( image ) ;   
01407         
01408         }   
01409         
01410         SDL_FreeSurface( image ) ;
01411         
01412         image = formattedImage ;
01413         
01414     }
01415         
01416     /*
01417      * Now we have our image surface, we can either blit it or have 
01418      * it replace the former one :
01419      *
01420      */
01421             
01422     if ( blitOnly )
01423     {
01424         // We should blit the loaded image in already existing internal surface.
01425         
01426 #if OSDL_DEBUG
01427 
01428         if ( ! targetSurface.isInternalSurfaceAvailable() )
01429             throw ImageException( "Image::LoadTGA : trying to blit image "
01430                 "whereas target SDL_surface pointer is null" ) ;
01431                 
01432 #endif // OSDL_DEBUG
01433         
01434             
01435 #if OSDL_DEBUG
01436         
01437         // The target surface should not be locked :    
01438 
01439         if ( targetSurface.isLocked() )
01440             throw ImageException( "Image::LoadTGA : trying to blit an image "
01441                 "whereas target surface is locked" ) ;
01442                 
01443 #endif // OSDL_DEBUG
01444         
01445         int result = SDL_BlitSurface( image, 0, 
01446             & targetSurface.getSDLSurface(), 0 ) ;
01447         
01448         if ( result == -1)
01449             throw ImageException( "Image::LoadTGA : error in blit : " 
01450                 + Utils::getBackendLastError() ) ;
01451     
01452         if ( result == -2 )
01453             throw ImageException( 
01454                 "Image::LoadTGA : video memory was lost during blit." ) ;
01455 
01456         /*
01457          * In this case, the loaded image has been used and therefore 
01458          * is not needed any more :
01459          *
01460          */
01461      
01462         SDL_FreeSurface( image ) ;      
01463         
01464     }
01465     else
01466     {
01467 
01468         /*
01469          * Simply replace the former internal surface by this new one.
01470          *
01471          * The former surface gets automatically deallocated by setSDLSurface.
01472          *
01473          * The target surface is, from now on, the new owner of the buffer
01474          * pointed to by the image pointer.
01475          *
01476          */
01477 
01478         targetSurface.setSDLSurface( * image ) ;
01479     }
01480     
01481     
01482     /*
01483      * In all cases :
01484      *  - no memory leak should occur with the internal surface, since 
01485      * blit does not change anything for that, and replacement triggers
01486      * deallocation
01487      *  - any used temporary surface got deallocated (it is the case for 
01488      * display format conversion and for blitted image)
01489      *
01490      */  
01491 }
01492     
01493 
01494 
01495 void Image::LoadXPM( Surface & targetSurface, const std::string & filename, 
01496         bool blitOnly, bool convertToDisplay, bool convertWithAlpha ) 
01497     throw( ImageException )
01498 {
01499 
01500     if ( ! File::Exists( filename ) )
01501         throw ImageException( "Unable to load XPM file " 
01502             + filename + " : file not found." ) ;
01503             
01504     SDL_Surface * image ;
01505         
01506     image = IMG_LoadTyped_RW( SDL_RWFromFile( filename.c_str(), "rb" ), 
01507         1, const_cast<char *>( XPMTag.c_str() ) ) ;
01508         
01509     if ( image == 0 ) 
01510         throw ImageException( "Unable to load XPM image stored in " + filename 
01511             + " thanks to IMG_Load_RW : "
01512             + string( IMG_GetError() ) ) ;   
01513     
01514     
01515     /*
01516      * If conversion to display format is needed, substitute the converted 
01517      * image to the loaded one :
01518      *
01519      */
01520     
01521     if ( convertToDisplay )
01522     {
01523     
01524         if ( ! VideoModule::IsDisplayInitialized() )
01525             throw ImageException( 
01526                 "Image::LoadXPM called with request to convert surface "
01527                 "to display, whereas display not initialized "
01528                 "(VideoModule::setMode never called)." ) ;
01529 
01530         SDL_Surface * formattedImage ;
01531         
01532         /*
01533          * SDL_DisplayFormat* copies the surface, which therefore is 
01534          * to be deallocated :
01535          *
01536          */
01537         
01538         if ( convertWithAlpha )
01539         {
01540         
01541             formattedImage = SDL_DisplayFormatAlpha( image ) ;  
01542             
01543         }
01544         else
01545         {
01546         
01547             formattedImage = SDL_DisplayFormat( image ) ;   
01548         
01549         }   
01550         
01551         SDL_FreeSurface( image ) ;
01552         
01553         image = formattedImage ;
01554         
01555     }
01556         
01557     /*
01558      * Now we have our image surface, we can either blit it or have 
01559      * it replace the former one :
01560      *
01561      */
01562             
01563     if ( blitOnly )
01564     {
01565         // We should blit the loaded image in already existing internal surface.
01566         
01567 #if OSDL_DEBUG
01568 
01569         if ( ! targetSurface.isInternalSurfaceAvailable() )
01570             throw ImageException( "Image::LoadXPM : trying to blit image "
01571                 "whereas target SDL_surface pointer is null" ) ;
01572                 
01573 #endif // OSDL_DEBUG
01574         
01575             
01576 #if OSDL_DEBUG
01577         
01578         // The target surface should not be locked :    
01579 
01580         if ( targetSurface.isLocked() )
01581             throw ImageException( "Image::LoadXPM : trying to blit an image "
01582                 "whereas target surface is locked" ) ;
01583                 
01584 #endif // OSDL_DEBUG
01585         
01586         int result = SDL_BlitSurface( image, 0, 
01587             & targetSurface.getSDLSurface(), 0 ) ;
01588         
01589         if ( result == -1)
01590             throw ImageException( 
01591                 "Image::LoadXPM : error in blit : " 
01592                 + Utils::getBackendLastError() ) ;
01593     
01594         if ( result == -2 )
01595             throw ImageException( 
01596                 "Image::LoadXPM : video memory was lost during blit." ) ;
01597 
01598         /*
01599          * In this case, the loaded image has been used and therefore 
01600          * is not needed any more :
01601          *
01602          */
01603      
01604         SDL_FreeSurface( image ) ;      
01605         
01606     }
01607     else
01608     {
01609 
01610         /*
01611          * Simply replace the former internal surface by this new one.
01612          *
01613          * The former surface gets automatically deallocated by setSDLSurface.
01614          *
01615          * The target surface is, from now on, the new owner of the buffer
01616          * pointed to by the image pointer.
01617          *
01618          */
01619          
01620         targetSurface.setSDLSurface( * image ) ;
01621     }
01622     
01623     
01624     /*
01625      * In all cases :
01626      *  - no memory leak should occur with the internal surface, since 
01627      * blit does not change anything for that, and replacement triggers
01628      * deallocation
01629      *  - any used temporary surface got deallocated (it is the case for 
01630      * display format conversion and for blitted image)
01631      *
01632      */  
01633      
01634 }   
01635 
01636 
01637 
01638 void Image::SavePNG( Surface & targetSurface, const std::string & filename, 
01639     bool overwrite ) throw( ImageException )
01640 {
01641 
01642     // See png.h and http://www.libpng.org/pub/png/libpng.html for more details.
01643     
01644     if ( ! overwrite && Ceylan::System::File::Exists( filename ) )
01645         throw TwoDimensional::ImageException( 
01646             "Surface::savePNG : target file '" + filename 
01647             + "' already exists, and overwrite mode is off." ) ;
01648 
01649     png_structp png_ptr ;
01650     png_infop info_ptr ;
01651 
01652     png_ptr = ::png_create_write_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ) ;
01653 
01654     if ( png_ptr == 0 )
01655     {  
01656         ::png_destroy_write_struct( & png_ptr, (png_infopp) 0 ) ;
01657         throw TwoDimensional::ImageException( 
01658             "Surface::savePNG : unable to save image '"
01659             + filename + "' (step 1)" ) ;
01660     }
01661     
01662     info_ptr = ::png_create_info_struct( png_ptr ) ;
01663     
01664     if ( info_ptr == 0 )
01665     {  
01666         ::png_destroy_write_struct( & png_ptr, (png_infopp) 0 ) ;
01667         throw TwoDimensional::ImageException( 
01668             "Surface::savePNG : unable to save image '"
01669                 + filename + "' (step 2)" ) ;
01670     }
01671 
01672 
01673     if ( ::setjmp( png_jmpbuf( png_ptr ) ) )
01674     {  
01675         ::png_destroy_write_struct( & png_ptr, (png_infopp) 0 ) ;
01676         throw TwoDimensional::ImageException( 
01677             "Surface::savePNG : unable to save image '"
01678             + filename + "' (step 3)" ) ;
01679     }
01680     
01681     // Let's create a file with C-style :
01682     
01683     /*
01684      * Something as :
01685      
01686     std::ifstream outputFile = open( filename.c_str(), ifstream::out ) ;
01687 
01688      * could not work since functions like png_init_io wants a FILE *, 
01689      * except maybe with a clumsy ifstream::rdbuf.
01690      *
01691      * ifstream destructor would automatically close the file on any 
01692      * exit scheme.
01693      *
01694      */
01695 
01696     FILE * outputFile = ::fopen( filename.c_str(), "wb" ) ;
01697     
01698     if ( outputFile == 0 )
01699     {  
01700         ::png_destroy_write_struct( & png_ptr, (png_infopp) 0 ) ;
01701         throw TwoDimensional::ImageException( 
01702             "Surface::savePNG : unable to save image '"
01703             + filename + "' (step 4) : " + Ceylan::System::explainError() ) ;
01704     }
01705     
01706     ::png_init_io( png_ptr, outputFile ) ;
01707 
01708     info_ptr->width  = targetSurface.getWidth() ;
01709     info_ptr->height = targetSurface.getHeight() ;
01710     
01711     // Superfluity :
01712     //info_ptr->rowbytes = _width ;
01713     
01714     
01715     // The choice might be not as generic as wished :
01716     info_ptr->bit_depth = 8 ;
01717     
01718     /* 
01719      * At least two other color type should be managed :
01720      *  - PNG_COLOR_TYPE_GRAY
01721      *  - PNG_COLOR_TYPE_PALETTE
01722      *
01723      * No alpha coordinate seems to be managed.
01724      *
01725      */    
01726     info_ptr->color_type = PNG_COLOR_TYPE_RGB ;
01727 
01728 
01729     /* Thanks to Murlock, this method could be a little more generic :
01730     
01731     switch( type_img )
01732     {
01733     
01734         case TYPE_RGB:
01735             info_ptr->rowbytes     *= 3 ;
01736             info_ptr->sig_bit.red   = 8 ;
01737             info_ptr->sig_bit.green = 8 ;
01738             info_ptr->sig_bit.blue  = 8 ;
01739             info_ptr->color_type    = PNG_COLOR_TYPE_RGB ;
01740             break ;
01741             
01742         case TYPE__GRAY:
01743             info_ptr->sig_bit.gray = 8 ;
01744             info_ptr->color_type   = PNG_COLOR_TYPE_GRAY ;
01745             break ;
01746             
01747         case TYPE_PALETTE:
01748             info_ptr->valid       = PNG_INFO_PLTE ;     
01749             info_ptr->num_palette = nb_col;
01750             info_ptr->color_type  = PNG_COLOR_TYPE_PALETTE;
01751             info_ptr->palette     =(png_color*)
01752                 malloc(nb_col*sizeof(png_color));
01753             
01754             // Use OSDLPalette instead :
01755             
01756             for ( unsigned int i=0; i < nb_col; i++ )
01757             {
01758                 info_ptr->palette[i].red   = palette[i].r ;
01759                 info_ptr->palette[i].green = palette[i].g ;
01760                 info_ptr->palette[i].blue  = palette[i].b ;
01761             }
01762             break ;
01763         
01764         default:
01765             throw TwoDimensional::ImageException( 
01766                 "Surface::savePNG : unexpected image type." ) ;
01767             break ; 
01768      }
01769      
01770     */
01771         
01772     // Could be PNG_INTERLACE_NONE or PNG_INTERLACE_ADAM7 :
01773     info_ptr->interlace_type = PNG_INTERLACE_ADAM7 ;
01774     
01775     // No palette used :
01776     info_ptr->num_palette = 0 ;
01777     info_ptr->palette     = 0 ;
01778     
01779     info_ptr->valid = 0 ;
01780 
01781 
01782     ::png_write_info( png_ptr, info_ptr ) ;
01783 
01784 
01785     // Now write the pixels, one by one :
01786     targetSurface.lock() ;
01787     
01788     unsigned char ** png_rows = new unsigned char * 
01789         [ targetSurface.getHeight() ] ;
01790 
01791     for ( Coordinate y = 0; y < targetSurface.getHeight(); y++ )
01792     {
01793     
01794         png_rows[ y ] = new unsigned char[ 3 * targetSurface.getWidth() ] ;
01795 
01796         ColorDefinition readDef ;
01797         
01798         for ( Coordinate x = 0; x < targetSurface.getWidth(); x++ )
01799         {
01800         
01801             readDef = targetSurface.getColorDefinitionAt( x, y ) ;
01802             
01803             /*
01804             SDL_GetRGB( targetSurface.getPixel( x, y ), 
01805                 & targetSurface.getPixelFormat(), & r, & g, & b ) ;
01806              */
01807             png_rows[ y ][ x * 3 + 0 ] = readDef.r ;
01808             png_rows[ y ][ x * 3 + 1 ] = readDef.g ;
01809             png_rows[ y ][ x * 3 + 2 ] = readDef.b ;
01810         }
01811     }
01812 
01813     targetSurface.unlock() ;
01814       
01815     png_write_image( png_ptr, png_rows ) ;
01816 
01817     for ( Coordinate y = 0; y < targetSurface.getHeight(); y++ )
01818         delete [] png_rows[ y ] ;
01819     
01820     delete [] png_rows ;
01821       
01822     ::png_write_end( png_ptr, 0 ) ;
01823 
01824     ::png_destroy_write_struct( & png_ptr, & info_ptr ) ;
01825     
01826     ::fclose( outputFile ) ;
01827 
01828 
01829 }
01830 
01831 
01832 
01833 void Image::SaveBMP( Surface & targetSurface, const std::string & filename, 
01834     bool overwrite ) throw( ImageException )
01835 {
01836 
01837     if ( ! overwrite && Ceylan::System::File::Exists( filename ) )
01838         throw TwoDimensional::ImageException( 
01839             "Surface::saveBMP : target file '" + filename 
01840             + "' already exists, and overwrite mode is off." ) ;
01841             
01842     if ( SDL_SaveBMP( & targetSurface.getSDLSurface(), filename.c_str() ) != 0 )
01843         throw TwoDimensional::ImageException( 
01844             "Surface::saveBMP : error while saving BMP file '" 
01845             + filename + "' : " + OSDL::Utils::getBackendLastError() ) ;
01846 
01847 }
01848 
01849 
01850 
01851 const string Image::toString( Ceylan::VerbosityLevels level ) const throw()
01852 {
01853     
01854     if ( _filename.empty() )
01855         return "Image object not linked to a file" ;
01856         
01857     return "Image object linked with file " + _filename ;
01858     
01859 }
01860 

Generated on Fri Mar 30 14:46:59 2007 for OSDL by  doxygen 1.5.1