VRUT::ImageDDS Class Reference

Image container with support for many formats readable by wxImage. More...

#include <imagedds.h>

Inheritance diagram for VRUT::ImageDDS:

VRUT::Image

List of all members.

Public Member Functions

 ImageDDS ()
 Class constructor.
virtual ~ImageDDS ()
 Class destructor.
virtual bool IsOk () const
 Is image properly loaded? - Image overload.
virtual bool Load (const wxString &fname)
 Load image data from file - Image overload.
virtual GLuint BuildOglTexture () const
virtual bool HasTransparency () const
 Get true if image has alpha channel - Image overload.
virtual int GetWidth () const
 Get the widht of the image.
virtual int GetHeight () const
 Get the height of the image.

Protected Attributes

struct VRUT::ImageDDS::DdsLoadInfo image

Classes

union  DDS_header
 Texture header info. More...
struct  DdsLoadInfo
 Image data. More...


Detailed Description

Image container with support for many formats readable by wxImage.

Definition at line 126 of file imagedds.h.


Constructor & Destructor Documentation

ImageDDS::ImageDDS (  ) 

Class constructor.

Definition at line 21 of file imagedds.cpp.

00021                    : Image()
00022 {
00023 }

ImageDDS::~ImageDDS (  )  [virtual]

Class destructor.

Definition at line 26 of file imagedds.cpp.

00027 {
00028 }


Member Function Documentation

bool ImageDDS::IsOk (  )  const [virtual]

Is image properly loaded? - Image overload.

Implements VRUT::Image.

Definition at line 31 of file imagedds.cpp.

00032 {
00033        return (image.data != (unsigned char *)NULL);
00034 }

bool ImageDDS::Load ( const wxString &  fname  )  [virtual]

Load image data from file - Image overload.

Reimplemented from VRUT::Image.

Definition at line 37 of file imagedds.cpp.

00038 {
00039        if (Image::Load(fname))
00040        {
00041               SAFE_DELETE_ARR(image.data);
00042               /* Open the file */
00043               wxFileInputStream fin(fname);
00044               /* Get the surface descriptor */
00045               fin.Read(&image.header, sizeof(image.header));
00046 
00047               if ( image.header.dwMagic != DDS_MAGIC || image.header.dwSize != 124 ||
00048                   !(image.header.dwFlags & DDSD_PIXELFORMAT) || !(image.header.dwFlags & DDSD_CAPS) )
00049               {
00050                      LOGERROR(wxString::Format(wxT("<ImageDDS>File '%s' doesn't appear to be a valid .dds file"), fname.c_str()));
00051                      return false;
00052               }
00053 
00054               if ( PF_IS_DXT1( image.header.sPixelFormat ) )
00055               {
00056                      image.compressed = true;
00057                      image.swap = false;
00058                      image.palette = false;
00059                      image.divSize = 4;
00060                      image.blockBytes = 8;
00061                      image.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
00062               }
00063               else if ( PF_IS_DXT3( image.header.sPixelFormat ) )
00064               {
00065                      image.compressed = true;
00066                      image.swap = false;
00067                      image.palette = false;
00068                      image.divSize = 4;
00069                      image.blockBytes = 16;
00070                      image.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
00071               }
00072               else if ( PF_IS_DXT5( image.header.sPixelFormat ) )
00073               {
00074                      image.compressed = true;
00075                      image.swap = false;
00076                      image.palette = false;
00077                      image.divSize = 4;
00078                      image.blockBytes = 16;
00079                      image.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
00080               }
00081               else if ( PF_IS_BGRA8( image.header.sPixelFormat ) )
00082               {
00083                      image.compressed = false;
00084                      image.swap = false;
00085                      image.palette = false;
00086                      image.divSize = 1;
00087                      image.blockBytes = 4;
00088                      image.internalFormat = GL_RGBA8;
00089                      image.externalFormat = GL_BGRA;
00090                      image.type = GL_UNSIGNED_BYTE;
00091               }
00092               else if ( PF_IS_BGR8( image.header.sPixelFormat ) )
00093               {
00094                      image.compressed = false;
00095                      image.swap = false;
00096                      image.palette = false;
00097                      image.divSize = 1;
00098                      image.blockBytes = 3;
00099                      image.internalFormat = GL_RGB8;
00100                      image.externalFormat = GL_BGR;
00101                      image.type = GL_UNSIGNED_BYTE;
00102               }
00103               else if ( PF_IS_BGR5A1( image.header.sPixelFormat ) )
00104               {
00105                      image.compressed = false;
00106                      image.swap = true;
00107                      image.palette = false;
00108                      image.divSize = 1;
00109                      image.blockBytes = 2;
00110                      image.internalFormat = GL_RGB5_A1;
00111                      image.externalFormat = GL_BGRA;
00112                      image.type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
00113               }
00114               else if ( PF_IS_BGR565( image.header.sPixelFormat ) )
00115               {
00116                      image.compressed = false;
00117                      image.swap = true;
00118                      image.palette = false;
00119                      image.divSize = 1;
00120                      image.blockBytes = 2;
00121                      image.internalFormat = GL_RGB5;
00122                      image.externalFormat = GL_RGB;
00123                      image.type = GL_UNSIGNED_SHORT_5_6_5;
00124               }
00125               else if ( PF_IS_INDEX8( image.header.sPixelFormat ) )
00126               {
00127                      image.compressed = false;
00128                      image.swap = false;
00129                      image.palette = true;
00130                      image.divSize = 1;
00131                      image.blockBytes = 1;
00132                      image.internalFormat = GL_RGB8;
00133                      image.externalFormat = GL_BGRA;
00134                      image.type = GL_UNSIGNED_BYTE;
00135               }
00136               else
00137               {
00138                      LOGERROR(wxString::Format(wxT("<ImageDDS>Unknown pixel format in DDS file '%s'"), fname.c_str()));
00139                      return false;
00140               }
00141 
00142               /* Calculate pixel data size */
00143               unsigned curr = fin.TellI();
00144               unsigned end = fin.SeekI(0, wxFromEnd);
00145               fin.SeekI(curr);
00146               unsigned bufferSize = end - curr;
00147               /* Read pixel data with mipmaps */
00148               image.data = new unsigned char[bufferSize];
00149               fin.Read(image.data, sizeof(unsigned char) * bufferSize);
00150 
00151               return true;
00152        }
00153        return false;
00154 }

GLuint ImageDDS::BuildOglTexture (  )  const [virtual]

Build and bind OpenGL texture from image in CURRENT OpenGL context - Image overload

Returns:
OpenGL ID for texture, GL_ID_NONE if failed

Implements VRUT::Image.

Definition at line 157 of file imagedds.cpp.

00158 {
00159        GLuint texID = GL_ID_NONE;
00160        if (IsOk())
00161        {
00162               unsigned x = image.header.dwWidth;
00163               unsigned y = image.header.dwHeight;
00164               unsigned mipMapCount = (image.header.dwFlags & DDSD_MIPMAPCOUNT) ? image.header.dwMipMapCount : 1;
00165               glEnable(GL_TEXTURE_2D);
00166 
00167               if (image.compressed)
00168               {
00169                      unsigned size = __max( image.divSize, x )/image.divSize * __max( image.divSize, y )/image.divSize * image.blockBytes;
00170                      if ( size != image.header.dwPitchOrLinearSize || !(image.header.dwFlags & DDSD_LINEARSIZE) )
00171                      {
00172                             LOGERROR(wxT("<ImageDDS>Texture size mismatch"));
00173                             return texID;
00174                      }
00175                      PFNGLCOMPRESSEDTEXIMAGE2DPROC vrutCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) GLGETPROC("glCompressedTexImage2D");
00176                      if ( vrutCompressedTexImage2D == NULL )
00177                      {
00178                             LOGERROR(wxT("<ImageDDS>Compressed textures not supported"));
00179                             return texID;
00180                      }
00181 
00182                      glGenTextures( 1, &texID );
00183                      glBindTexture( GL_TEXTURE_2D, texID );
00184                      glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE );
00185                      unsigned offset = 0;
00186                      for ( unsigned int ix = 0; ix < mipMapCount; ++ix )
00187                      {
00188                             vrutCompressedTexImage2D( GL_TEXTURE_2D, ix, image.internalFormat, x, y, 0, size, image.data + offset );
00189                             GLCHECKERROR;
00190                             x = (x+1)>>1;
00191                             y = (y+1)>>1;
00192                             offset += size;
00193                             size = __max( image.divSize, x )/image.divSize * __max( image.divSize, y )/image.divSize * image.blockBytes;
00194                      }
00195               }
00196               else if (image.palette) //TODO: not tested
00197               {
00198                      //  currently, we unpack palette into BGRA
00199                      //  I'm not sure we always get pitch...
00200                      unsigned size = image.header.dwPitchOrLinearSize * image.header.dwHeight;
00201                      //  And I'm even less sure we don't get padding on the smaller MIP levels...
00202                      if ( (image.header.dwFlags & DDSD_PITCH) == 0 ||
00203                             image.header.sPixelFormat.dwRGBBitCount != 8 ||
00204                             (size != x * y * image.blockBytes) )
00205                      {
00206                             LOGERROR(wxT("<ImageDDS>Size mismatch"));
00207                             return texID;
00208                      }
00209 
00210                      glGenTextures( 1, &texID );
00211                      glBindTexture( GL_TEXTURE_2D, texID );
00212                      glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE );
00213                      unsigned char * data = image.data + 256 * 4;
00214                      unsigned int * palette = (unsigned int *)image.data;
00215                      unsigned int * unpacked = new unsigned[size * sizeof(unsigned)];
00216                      unsigned offset = 0;
00217                      for ( unsigned ix = 0; ix < mipMapCount; ++ix )
00218                      {
00219                             for ( unsigned zz = 0; zz < size; ++zz )
00220                             {
00221                                    unpacked[ zz ] = palette[ data[ zz ] ];
00222                             }
00223                             glPixelStorei( GL_UNPACK_ROW_LENGTH, y );
00224                             glTexImage2D( GL_TEXTURE_2D, ix, image.internalFormat, x, y, 0, image.externalFormat, image.type, unpacked );
00225                             GLCHECKERROR;
00226                             x = (x+1)>>1;
00227                             y = (y+1)>>1;
00228                             offset += size;
00229                             size = x * y * image.blockBytes;
00230                      }
00231                      delete [] unpacked;
00232               }
00233               else
00234               {
00235                      if (image.swap )  //TODO: not tested
00236                             glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_TRUE );
00237                      glGenTextures( 1, &texID );
00238                      glBindTexture( GL_TEXTURE_2D, texID );
00239                      glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE );
00240                      unsigned size = x * y * image.blockBytes;
00241                      unsigned offset = 0;
00242                      //fixme: how are MIP maps stored for 24-bit if pitch != ySize*3 ?
00243                      for ( unsigned int ix = 0; ix < mipMapCount; ++ix )
00244                      {
00245                             glPixelStorei( GL_UNPACK_ROW_LENGTH, y );
00246                             glTexImage2D( GL_TEXTURE_2D, ix, image.internalFormat, x, y, 0, image.externalFormat, image.type, image.data );
00247                             GLCHECKERROR;
00248                             x = (x+1)>>1;
00249                             y = (y+1)>>1;
00250                             offset += size;
00251                             size = x * y * image.blockBytes;
00252                      }
00253                      glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE );
00254                      GLCHECKERROR;
00255               }
00256               glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipMapCount-1 );
00257               GLCHECKERROR;
00258        }
00259 
00260        return texID;
00261 }

bool ImageDDS::HasTransparency (  )  const [virtual]

Get true if image has alpha channel - Image overload.

Implements VRUT::Image.

Definition at line 264 of file imagedds.cpp.

00265 {
00266        return IsOk() && ( image.header.dwFlags & DDPF_ALPHAPIXELS );
00267 }

int ImageDDS::GetWidth (  )  const [virtual]

Get the widht of the image.

Implements VRUT::Image.

Definition at line 269 of file imagedds.cpp.

00270 {
00271        return (IsOk()?image.header.dwWidth:0);
00272 }

int ImageDDS::GetHeight (  )  const [virtual]

Get the height of the image.

Implements VRUT::Image.

Definition at line 274 of file imagedds.cpp.

00275 {
00276        return (IsOk()?image.header.dwHeight:0);
00277 }


Member Data Documentation


The documentation for this class was generated from the following files:

Generated on Tue Mar 10 14:41:43 2009 for VRUT by  doxygen 1.5.5