Image.h

Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /////////////////////////////////////////////////////////////////////////////
00003 //
00004 // Image.h -- Copyright (c) 2006-2007 David Henry
00005 // last modification: july 13, 2007
00006 //
00007 // This code is licenced under the MIT license.
00008 //
00009 // This software is provided "as is" without express or implied
00010 // warranties. You may freely copy and compile this source into
00011 // applications you distribute provided that the copyright text
00012 // below is included in the resulting source code.
00013 //
00014 // Declaration of TGA and JPEG image loader classes.
00015 //
00016 /////////////////////////////////////////////////////////////////////////////
00017 
00018 #ifndef __IMAGE_H__
00019 #define __IMAGE_H__
00020 
00021 #ifdef _WIN32
00022 #define WIN32_LEAN_AND_MEAN
00023 #include <windows.h>
00024 #endif // _WIN32
00025 
00026 #include <GL/gl.h>
00027 #include <stdexcept>
00028 #include <iostream>
00029 #include <fstream>
00030 #include <string>
00031 #include <csetjmp>
00032 
00033 #include <string.h>
00034 
00035 extern "C" {
00036 #include <jpeglib.h>
00037 }
00038 
00039 using std::cout;
00040 using std::endl;
00041 using std::string;
00042 
00043 
00044 /////////////////////////////////////////////////////////////////////////////
00045 // Image class diagram:
00046 //
00047 //    +------- (abs)                     +---------------+
00048 //    |  Image  |                        | runtime_error |
00049 //    +---------+                        +---------------+
00050 //         ^                                     ^
00051 //         |   +------------+                    |
00052 //         +---|  ImageTGA  |            +----------------+
00053 //         |   +------------+            | ImageException |
00054 //         |                             +----------------+
00055 //         |   +------------+
00056 //         +---|  ImageJPEG |
00057 //             +------------+
00058 //
00059 //    +---------------+                  +----------------+
00060 //    |  ImageBuffer  |                  |  ImageFactory  |
00061 //    +---------------+                  +----------------+
00062 //
00063 /////////////////////////////////////////////////////////////////////////////
00064 
00065 
00066 /////////////////////////////////////////////////////////////////////////////
00067 //
00068 // class ImageException - Exception class for ImageBuffer and Image
00069 // loaders.  This acts like a standard runtime_error exception but
00070 // know which file has failed to be loaded.
00071 //
00072 /////////////////////////////////////////////////////////////////////////////
00073 
00074 class ImageException : public std::runtime_error
00075 {
00076 public:
00077   // Constructors
00078   ImageException (const string &error)
00079     : std::runtime_error (error) { }
00080   ImageException (const string &error, const string &filename)
00081     : std::runtime_error (error), _which (filename) { }
00082   virtual ~ImageException () throw () { }
00083 
00084 public:
00085   // Public interface
00086   virtual const char *which () const throw () {
00087     return _which.c_str ();
00088   }
00089 
00090 private:
00091   // Member variables
00092   string _which;
00093 };
00094 
00095 
00096 /////////////////////////////////////////////////////////////////////////////
00097 //
00098 // class ImageBuffer - An image file loader class.  Load a whole file
00099 // into a memory buffer.
00100 //
00101 /////////////////////////////////////////////////////////////////////////////
00102 
00103 class ImageBuffer
00104 {
00105 public:
00106   // Constructors/destructor
00107   ImageBuffer (const string &filename);
00108 
00109   ImageBuffer (const ImageBuffer &that)
00110     : _filename (that._filename), _data (NULL), _length (that._length)
00111   {
00112     _data = new GLubyte[_length];
00113     memcpy (_data, that._data, _length);
00114   }
00115 
00116   ~ImageBuffer ();
00117 
00118 private:
00119   // Disable default constructor
00120   ImageBuffer ();
00121 
00122 public:
00123   // Accessors
00124   const string &filename () const { return _filename; }
00125   const GLubyte *data () const { return _data; }
00126   size_t length () const { return _length; }
00127 
00128   ImageBuffer &operator= (const ImageBuffer &rhs)
00129   {
00130     this->~ImageBuffer ();
00131     new (this) ImageBuffer (rhs);
00132     return *this;
00133   }
00134 
00135 private:
00136   // Member variables
00137   string _filename;
00138 
00139   GLubyte *_data;
00140   size_t _length;
00141 };
00142 
00143 
00144 /////////////////////////////////////////////////////////////////////////////
00145 //
00146 // class Image - A generic image loader class for creating OpenGL
00147 // textures from.  All other specific image loader are derived from it.
00148 //
00149 /////////////////////////////////////////////////////////////////////////////
00150 
00151 class Image
00152 {
00153 protected:
00154   // Default constructor
00155   Image ()
00156     : _width (0), _height (0), _numMipmaps (0),
00157       _format (0), _components (0), _pixels (NULL),
00158       _standardCoordSystem (true) { }
00159 
00160 private:
00161   // Disable copy constructor.
00162   Image (const Image &img);
00163 
00164 public:
00165   // Constructors/destructor
00166   Image (const string &name, GLsizei w, GLsizei h, GLint numMipMaps,
00167          GLenum format, GLint components, const GLubyte *pixels,
00168          bool stdCoordSystem);
00169 
00170   virtual ~Image();
00171 
00172 public:
00173   bool isPowerOfTwo () const;
00174 
00175   // Accessors
00176   GLsizei width () const { return _width; }
00177   GLsizei height () const { return _height; }
00178   GLint numMipmaps () const { return _numMipmaps; }
00179   GLenum format () const { return _format; }
00180   GLint components () const { return _components; }
00181   const GLubyte *pixels () const { return _pixels; }
00182   const string &name () const { return _name; }
00183   bool stdCoordSystem () const { return _standardCoordSystem; }
00184 
00185 protected:
00186   // Member variables
00187   GLsizei _width;
00188   GLsizei _height;
00189   GLint _numMipmaps;
00190 
00191   // OpenGL texture format and internal
00192   // format (components)
00193   GLenum _format;
00194   GLint _components;
00195 
00196   // Image data
00197   GLubyte *_pixels;
00198 
00199   string _name;
00200 
00201   // Is the picture in standard OpenGL 2D coordinate
00202   // system? (starts lower-left corner)
00203   bool _standardCoordSystem;
00204 };
00205 
00206 
00207 /////////////////////////////////////////////////////////////////////////////
00208 //
00209 // class glImageTGA - A TrueVision TARGA (TGA) image loader class.
00210 // Support 24-32 bits BGR files; 16 bits RGB; 8 bits indexed (BGR
00211 // palette); 8 and 16 bits grayscale; all compressed and uncompressed.
00212 // Compressed TGA images use RLE algorithm.
00213 //
00214 /////////////////////////////////////////////////////////////////////////////
00215 
00216 class ImageTGA : public Image
00217 {
00218 public:
00219   // Constructor
00220   ImageTGA (const ImageBuffer &ibuff);
00221 
00222 private:
00223   // Internal functions
00224   void getTextureInfo ();
00225 
00226   void readTGA8bits (const GLubyte *data, const GLubyte *colormap);
00227   void readTGA16bits (const GLubyte *data);
00228   void readTGA24bits (const GLubyte *data);
00229   void readTGA32bits (const GLubyte *data);
00230   void readTGAgray8bits (const GLubyte *data);
00231   void readTGAgray16bits (const GLubyte *data);
00232 
00233   void readTGA8bitsRLE (const GLubyte *data, const GLubyte *colormap);
00234   void readTGA16bitsRLE (const GLubyte *data);
00235   void readTGA24bitsRLE (const GLubyte *data);
00236   void readTGA32bitsRLE (const GLubyte *data);
00237   void readTGAgray8bitsRLE (const GLubyte *data);
00238   void readTGAgray16bitsRLE (const GLubyte *data);
00239 
00240 private:
00241   // Member variables
00242 #pragma pack(push, 1)
00243   // tga header
00244   struct TGA_Header
00245   {
00246     GLubyte id_lenght;        // size of image id
00247     GLubyte colormap_type;    // 1 is has a colormap
00248     GLubyte image_type;       // compression type
00249 
00250     short cm_first_entry;     // colormap origin
00251     short cm_length;          // colormap length
00252     GLubyte cm_size;          // colormap size
00253 
00254     short x_origin;           // bottom left x coord origin
00255     short y_origin;           // bottom left y coord origin
00256 
00257     short width;              // picture width (in pixels)
00258     short height;             // picture height (in pixels)
00259 
00260     GLubyte pixel_depth;      // bits per pixel: 8, 16, 24 or 32
00261     GLubyte image_descriptor; // 24 bits = 0x00; 32 bits = 0x80
00262 
00263   };
00264 #pragma pack(pop)
00265 
00266   const TGA_Header *_header;
00267 
00268   // NOTE:
00269   // 16 bits images are stored in RGB
00270   // 8-24-32 images are stored in BGR(A)
00271 
00272   // RGBA/BGRA component table access -- usefull for
00273   // switching from bgra to rgba at load time.
00274   static int rgbaTable[4]; // bgra to rgba: 2, 1, 0, 3
00275   static int bgraTable[4]; // bgra to bgra: 0, 1, 2, 3
00276 };
00277 
00278 
00279 /////////////////////////////////////////////////////////////////////////////
00280 //
00281 // class ImageJPEG - A JPEG image loader class using libjpeg.
00282 //
00283 /////////////////////////////////////////////////////////////////////////////
00284 
00285 class ImageJPEG : public Image
00286 {
00287 public:
00288   // Constructor
00289   ImageJPEG (const ImageBuffer &ibuff);
00290 
00291 private:
00292   // Error manager, using C's setjmp/longjmp
00293   struct my_error_mgr
00294   {
00295     jpeg_error_mgr pub;     // "public" fields
00296     jmp_buf setjmp_buffer;  // for return to caller
00297 
00298     string errorMsg;        // last error message
00299   };
00300 
00301   typedef my_error_mgr *my_error_ptr;
00302 
00303 private:
00304   // libjpeg's callback functions for reading data
00305   static void initSource_callback (j_decompress_ptr cinfo);
00306   static boolean fillInputBuffer_callback (j_decompress_ptr cinfo);
00307   static void skipInputData_callback (j_decompress_ptr cinfo,
00308                                       long num_bytes);
00309   static void termSource_callback (j_decompress_ptr cinfo);
00310 
00311   // libjpeg's callback functions for error handling
00312   static void errorExit_callback (j_common_ptr cinfo);
00313   static void outputMessage_callback (j_common_ptr cinfo);
00314 };
00315 
00316 
00317 /////////////////////////////////////////////////////////////////////////////
00318 //
00319 // class ImageFactory - An Image Factory Class.
00320 //
00321 /////////////////////////////////////////////////////////////////////////////
00322 
00323 class ImageFactory
00324 {
00325 public:
00326   // Public interface
00327   static Image *createImage (const ImageBuffer &ibuff)
00328   {
00329     string ext;
00330     Image *result;
00331 
00332     // Extract file extension
00333     const string &filename = ibuff.filename ();
00334     ext.assign (filename, filename.find_last_of ('.') + 1, string::npos);
00335 
00336     if (ext.compare ("tga") == 0)
00337       {
00338         result = new ImageTGA (ibuff);
00339       }
00340     else if (ext.compare ("jpg") == 0)
00341       {
00342         result = new ImageJPEG (ibuff);
00343       }
00344     else
00345       {
00346         throw ImageException ("Unhandled image file format", filename);
00347       }
00348 
00349     return result;
00350   }
00351 };
00352 
00353 #endif // __IMAGE_H__