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