00001
00002 #ifndef _IOIMAGE_H
00003 #define _IOIMAGE_H
00004
00005 #include <cstdio>
00006 #include <cstdlib>
00007 #include <cassert>
00008
00009 #include "SDLImagePlatform.h"
00010
00011 #ifdef __cplusplus
00012 extern "C" {
00013 #include "rgbe.h"
00014 }
00015 #endif
00016
00017 #include "Geometry.h"
00018 #include "IOResource.h"
00019
00020 #include "IOManager.h"
00021 #include "Image.h"
00022
00023 namespace gk {
00024
00025
00026 class ImageIO : public IOManager<Image>
00027 {
00028
00029 ImageIO( const ImageIO& );
00030 ImageIO& operator=( const ImageIO& );
00031
00032
00033 ImageIO( )
00034 :
00035 IOManager<Image>()
00036 {}
00037
00038 public:
00039 static
00040 bool isColorFile( const std::string& filename )
00041 {
00042 return ((filename.rfind(".bmp") != std::string::npos)
00043 || (filename.rfind(".png") != std::string::npos)
00044 || (filename.rfind(".jpg") != std::string::npos)
00045 || (filename.rfind(".jpeg") != std::string::npos)
00046 || (filename.rfind(".tga") != std::string::npos));
00047 }
00048
00049
00050 static
00051 Image *read( const std::string& filename, const std::string& name= "" )
00052 {
00053
00054 Image *image= manager().find(filename, name);
00055 if(image != NULL)
00056 return image;
00057
00058 #ifdef VERBOSE
00059 printf("loading color image '%s'...\n", filename.c_str());
00060 #endif
00061
00062
00063 SDL_Surface *surface= IMG_Load(filename.c_str());
00064 if(surface == NULL)
00065 return NULL;
00066
00067
00068 const SDL_PixelFormat format= *surface->format;
00069 if(format.BitsPerPixel != 24 && format.BitsPerPixel != 32)
00070 {
00071 SDL_FreeSurface(surface);
00072 return NULL;
00073 }
00074
00075
00076 const int height= surface->h;
00077 const int width= surface->w;
00078 image= new Image(width, height);
00079 if(image == NULL)
00080 return NULL;
00081
00082 #ifdef VERBOSE_DEBUG
00083 printf(" image pixel format : "
00084 "bytes %d, bpp %d, "
00085 "red %x, shift %d, loss %d, "
00086 "green %x, shift %d, loss %d, "
00087 "blue %x, shift %d, loss %d, "
00088 "alpha %x, shift %d, loss %d\n",
00089 format.BytesPerPixel, format.BitsPerPixel,
00090 format.Rmask, format.Rshift, format.Rloss,
00091 format.Gmask, format.Gshift, format.Gloss,
00092 format.Bmask, format.Bshift, format.Bloss,
00093 format.Amask, format.Ashift, format.Aloss);
00094 #endif
00095
00096
00097 Uint8 *p= (Uint8 *) surface->pixels;
00098 int py= 0;
00099 if(format.BitsPerPixel == 32)
00100 {
00101 for(int y= height -1; y >= 0; y--, py++)
00102 {
00103 p= (Uint8 *) surface->pixels + py * surface->pitch;
00104 for(int x= 0; x < width; x++, p+= format.BytesPerPixel)
00105 {
00106 const Uint8 r= p[format.Rshift / 8];
00107 const Uint8 g= p[format.Gshift / 8];
00108 const Uint8 b= p[format.Bshift / 8];
00109 const Uint8 a= p[format.Ashift / 8];
00110
00111 image->setPixel(x, y, Pixel(r, g, b, a));
00112 }
00113 }
00114 }
00115 else if(format.BitsPerPixel == 24)
00116 {
00117 for(int y= height -1; y >= 0; y--, py++)
00118 {
00119 p= (Uint8 *) surface->pixels + py * surface->pitch;
00120 for(int x= 0; x < width; x++, p+= format.BytesPerPixel)
00121 {
00122 const Uint8 r= p[format.Rshift / 8];
00123 const Uint8 g= p[format.Gshift / 8];
00124 const Uint8 b= p[format.Bshift / 8];
00125
00126 image->setPixel(x, y, Pixel(r, g, b));
00127 }
00128 }
00129 }
00130
00131 SDL_FreeSurface(surface);
00132
00133
00134 return manager().insert(image, filename, name);
00135 }
00136
00137
00138 static
00139 int write( const Image *image, const std::string& filename )
00140 {
00141 if(image == NULL)
00142 return -1;
00143
00144
00145 Pixel *flip= new Pixel[image->width() * image->height()];
00146 Pixel *data= flip;
00147 for(int y= image->height() -1; y >= 0; y--)
00148 {
00149 memcpy(data, (Pixel *) image->data() + y * image->width(), image->width() * sizeof(Pixel));
00150 data+= image->width();
00151 }
00152
00153 SDL_Surface *bmp= SDL_CreateRGBSurfaceFrom((void *) flip,
00154 image->width(), image->height(),
00155 32, image->width() * 4,
00156 #if 0
00157 0xFF000000,
00158 0x00FF0000,
00159 0x0000FF00,
00160 0x000000FF
00161 #else
00162 0x000000FF,
00163 0x0000FF00,
00164 0x00FF0000,
00165 0xFF000000
00166 #endif
00167 );
00168
00169 int code= SDL_SaveBMP(bmp, filename.c_str());
00170 SDL_FreeSurface(bmp);
00171 delete [] flip;
00172 return code;
00173 }
00174
00175 static
00176 ImageIO& manager( )
00177 {
00178 static ImageIO manager;
00179 return manager;
00180 }
00181 };
00182
00183
00184
00185 class HDRImageIO : public IOManager<HDRImage>
00186 {
00187 HDRImageIO( const HDRImageIO& );
00188 HDRImageIO& operator=( const HDRImageIO& );
00189
00190
00191 HDRImageIO( )
00192 :
00193 IOManager<HDRImage>()
00194 {}
00195
00196 public:
00197
00198 static
00199 HDRImage *RGBEread( const std::string& filename, const std::string& name= "" )
00200 {
00201 FILE *in= fopen( filename.c_str(), "rb" );
00202 if(in == NULL)
00203 {
00204 printf("\n -- read error '%s'\n", filename.c_str());
00205 return NULL;
00206 }
00207
00208 rgbe_header_info info;
00209 int width, height;
00210 int code = RGBE_ReadHeader(in, &width, &height, &info);
00211 if(code != RGBE_RETURN_SUCCESS)
00212 {
00213 fclose(in);
00214 printf("\n -- read error '%s'\n", filename.c_str());
00215 return NULL;
00216 }
00217
00218 float *data= new float[width*height*3];
00219 code= RGBE_ReadPixels_RLE(in, data, width, height);
00220 if(code != RGBE_RETURN_SUCCESS)
00221 {
00222 fclose(in);
00223 delete [] data;
00224 printf("\n -- read error '%s'\n", filename.c_str());
00225 return NULL;
00226 }
00227
00228 fclose(in);
00229
00230
00231 HDRImage *image= new HDRImage(width, height);
00232 if(image == NULL)
00233 return NULL;
00234
00235 float *p= data;
00236 for(int y= height -1; y >= 0; y--)
00237 for(int x= 0; x < width; x++, p+= 3)
00238 image->setPixel(x, y, HDRPixel(p[0], p[1], p[2]));
00239
00240 delete [] data;
00241
00242
00243 return manager().insert(image, filename, name);
00244 }
00245
00246 static
00247 bool is_rgbe_file( const std::string& filename )
00248 {
00249 return (filename.rfind(".hdr") != std::string::npos);
00250 }
00251
00252
00253 static
00254 HDRImage *EXRread( const std::string& filename, const std::string& name= "" )
00255 {
00256 return NULL;
00257 }
00258
00259 static
00260 bool is_exr_file( const std::string& filename )
00261 {
00262 return (filename.rfind(".exr") != std::string::npos);
00263 }
00264
00265 static
00266 bool isHDRFile( const std::string& filename )
00267 {
00268 return is_rgbe_file(filename);
00269 }
00270
00271
00272 static
00273 HDRImage *read( const std::string& filename, const std::string& name= "" )
00274 {
00275
00276 HDRImage *image= manager().find(filename, name);
00277 if(image != NULL)
00278 return image;
00279
00280 #ifdef VERBOSE
00281 printf("loading image '%s'...\n", filename.c_str());
00282 #endif
00283
00284 if(is_rgbe_file(filename))
00285 return RGBEread(filename, name);
00286
00287 if(ImageIO::isColorFile(filename))
00288 {
00289
00290 Image *color= ImageIO::read(filename, name);
00291 if(color == NULL)
00292 return NULL;
00293
00294
00295 HDRImage *hdr= new HDRImage(color->width(), color->height());
00296
00297 for(int y= 0; y < color->height(); y++)
00298 for(int x= 0; x < color->width(); x++)
00299 hdr->setPixel(x, y,
00300 color->getPixel(x, y));
00301
00302
00303 return manager().insert(hdr, filename, name);
00304 }
00305
00306
00307 return NULL;
00308 }
00309
00310
00311 static
00312 int write( const HDRImage *image, const std::string& filename )
00313 {
00314 if(image == NULL)
00315 return -1;
00316
00317 FILE *out= fopen(filename.c_str(), "wb");
00318 if(out == NULL)
00319 {
00320 printf("\n -- write error '%s'\n", filename.c_str());
00321 return -1;
00322 }
00323
00324 int code= RGBE_WriteHeader(out, image->width(), image->height(), NULL);
00325 if(code != RGBE_RETURN_SUCCESS)
00326 {
00327 printf("\n -- write error '%s'\n", filename.c_str());
00328 fclose(out);
00329 return -1;
00330 }
00331
00332 float *data= new float[image->width() * image->height() * 3];
00333 float *p= data;
00334 for(int y= image->height() -1; y > 0; y--)
00335 {
00336 for(int x= 0; x < image->width(); x++, p+= 3)
00337 {
00338 const HDRPixel& pixel= image->getPixel(x, y);
00339 p[0]= pixel.r;
00340 p[1]= pixel.g;
00341 p[2]= pixel.b;
00342 }
00343 }
00344
00345 code= RGBE_WritePixels_RLE(out, (const float *) data, image->width(), image->height());
00346 fclose(out);
00347 delete [] data;
00348
00349 if(code != RGBE_RETURN_SUCCESS)
00350 {
00351 printf("\n -- write error '%s'\n", filename.c_str());
00352 return -1;
00353 }
00354
00355 return 0;
00356 }
00357
00358 static
00359 HDRImageIO& manager( )
00360 {
00361 static HDRImageIO manager;
00362 return manager;
00363 }
00364 };
00365
00366 }
00367
00368 #endif