Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlCore/plugins/ioDDS.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
00005 /*                                                                                    */
00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
00007 /*  All rights reserved.                                                              */
00008 /*                                                                                    */
00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
00010 /*  are permitted provided that the following conditions are met:                     */
00011 /*                                                                                    */
00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
00013 /*  list of conditions and the following disclaimer.                                  */
00014 /*                                                                                    */
00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
00017 /*  other materials provided with the distribution.                                   */
00018 /*                                                                                    */
00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
00029 /*                                                                                    */
00030 /**************************************************************************************/
00031 
00032 #include "ioDDS.hpp"
00033 #include <vlCore/LoadWriterManager.hpp>
00034 #include <vlCore/VisualizationLibrary.hpp>
00035 #include <vlCore/VisualizationLibrary.hpp>
00036 #include <vlCore/FileSystem.hpp>
00037 #include <vlCore/VirtualFile.hpp>
00038 #include <vlCore/Image.hpp>
00039 
00040 // mic fixme: 
00041 // http://msdn.microsoft.com/en-us/library/bb943991(v=vs.85).aspx#dds_variants
00042 // - read and write float and half float images.
00043 // - support directx 10 dds and formats
00044 // - support A8R8G8B8, A1R5G5B5, A4R4G4B4, R8G8B8, R5G6B5
00045 
00046 using namespace vl;
00047 
00048 #include <vlCore/ImageTools.hpp>
00049 
00050 //-----------------------------------------------------------------------------
00051 // DDS loader
00052 //-----------------------------------------------------------------------------
00053 namespace
00054 {
00055   // DDSURFACEDESC2.dwFlags
00056   const unsigned long DDS_CAPS            = 0x00000001;
00057   const unsigned long DDS_HEIGHT          = 0x00000002;
00058   const unsigned long DDS_WIDTH           = 0x00000004;
00059   const unsigned long DDS_PITCH           = 0x00000008;
00060   const unsigned long DDS_BACKBUFFERCOUNT = 0x00000020;
00061   const unsigned long DDS_ZBUFFERBITDEPTH = 0x00000040;
00062   const unsigned long DDS_ALPHABITDEPTH   = 0x00000080;
00063   const unsigned long DDS_LPSURFACE       = 0x00000800;
00064   const unsigned long DDS_PIXELFORMAT     = 0x00001000;
00065   const unsigned long DDS_CKDESTOVERLAY   = 0x00002000;
00066   const unsigned long DDS_CKDESTBLT       = 0x00004000;
00067   const unsigned long DDS_CKSRCOVERLAY    = 0x00008000;
00068   const unsigned long DDS_CKSRCBLT        = 0x00010000;
00069   const unsigned long DDS_MIPMAPCOUNT     = 0x00020000;
00070   const unsigned long DDS_REFRESHRATE     = 0x00040000;
00071   const unsigned long DDS_LINEARSIZE      = 0x00080000;
00072   const unsigned long DDS_TEXTURESTAGE    = 0x00100000;
00073   const unsigned long DDS_FVF             = 0x00200000;
00074   const unsigned long DDS_SRCVBHANDLE     = 0x00400000;
00075   const unsigned long DDS_DEPTH           = 0x00800000;
00076   const unsigned long DDS_ALL             = 0x007FF9EE;
00077   const unsigned long DDS_REQUIRED_FLAGS  = DDS_CAPS|DDS_PIXELFORMAT|DDS_WIDTH|DDS_HEIGHT;
00078 
00079   // DDPIXELFORMAT.dwFlags
00080   const unsigned long DDPF_ALPHAPIXELS     = 0x00000001; // there is an alpha channel
00081   const unsigned long DDPF_ALPHA           = 0x00000002; // the image is an alpha channel only image
00082   const unsigned long DDPF_FOURCC          = 0x00000004; // the foucc code defines the pixel format
00083   const unsigned long DDPF_INDEXED4        = 0x00000008;
00084   const unsigned long DDPF_INDEXEDTO8      = 0x00000010;
00085   const unsigned long DDPF_INDEXED8        = 0x00000020;
00086   const unsigned long DDPF_RGB             = 0x00000040; // RGB, no fourcc
00087   const unsigned long DDPF_RGBA            = 0x00000041; // DDPF_RGB | DDPF_ALPHAPIXELS
00088   const unsigned long DDPF_COMPRESSED      = 0x00000080; // It's a compressed format
00089   const unsigned long DDPF_RGBTOYUV        = 0x00000100;
00090   const unsigned long DDPF_YUV             = 0x00000200;
00091   const unsigned long DDPF_ZBUFFER         = 0x00000400;
00092   const unsigned long DDPF_PALETTEINDEXED1 = 0x00000800;
00093   const unsigned long DDPF_PALETTEINDEXED2 = 0x00001000;
00094   const unsigned long DDPF_ZPIXELS         = 0x00002000;
00095   const unsigned long DDPF_STENCILBUFFER   = 0x00004000;
00096   const unsigned long DDPF_ALPHAPREMULT    = 0x00008000;
00097   const unsigned long DDPF_LUMINANCE       = 0x00020000; // Is a luminance image
00098   const unsigned long DDPF_BUMPLUMINANCE   = 0x00040000;
00099   const unsigned long DDPF_BUMPDUDV        = 0x00080000;
00100 
00101   // DDSCAPS2.dwCaps1
00102   const unsigned long DDSCAPS_COMPLEX = 0x00000008; // Whenever is cubemap or volume
00103   const unsigned long DDSCAPS_TEXTURE = 0x00001000; // Always present
00104   const unsigned long DDSCAPS_MIPMAP  = 0x00400000; // It's a mipmap image
00105 
00106   // DDSCAPS2.dwCaps2
00107   const unsigned long DDSCAPS2_VOLUME            = 0x00200000; // It's a 3D texture
00108   const unsigned long DDSCAPS2_CUBEMAP           = 0x00000200; // It's a cubemap
00109   const unsigned long DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400;
00110   const unsigned long DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800;
00111   const unsigned long DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000;
00112   const unsigned long DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000;
00113   const unsigned long DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000;
00114   const unsigned long DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000;
00115   const unsigned long DDSCAPS2_CUBEMAP_FACES = DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_NEGATIVEX | 
00116                                                DDSCAPS2_CUBEMAP_POSITIVEY | DDSCAPS2_CUBEMAP_NEGATIVEY |
00117                                                DDSCAPS2_CUBEMAP_POSITIVEZ | DDSCAPS2_CUBEMAP_NEGATIVEZ ; 
00118 
00119   inline unsigned int makeFourCC(unsigned int ch0, unsigned int ch1, unsigned int ch2, unsigned int ch3) 
00120   {
00121       return ch0 | (ch1 << 8) | ( ch2 << 16) | ( ch3 << 24 );
00122   }
00123 
00124   inline bool isFourCC(const char* code, unsigned int fcc)
00125   {
00126     return makeFourCC(code[0], code[1], code[2], code[3]) == fcc;
00127   }
00128 
00129   // quick surface type macros
00130 
00131   #define IS_BGRA8(pf) \
00132     ((pf.dwFlags & DDPF_RGB) && \
00133      (pf.dwFlags & DDPF_ALPHAPIXELS) && \
00134      (pf.dwRGBBitCount == 32))
00135 
00136   #define IS_BGRX8(pf) \
00137     ((pf.dwFlags & DDPF_RGB) && \
00138      !(pf.dwFlags & DDPF_ALPHAPIXELS) && \
00139      (pf.dwRGBBitCount == 32))
00140 
00141   #define IS_BGR8(pf) \
00142     ((pf.dwFlags & DDPF_RGB) && \
00143     !(pf.dwFlags & DDPF_ALPHAPIXELS) && \
00144      (pf.dwRGBBitCount == 24))
00145 
00146   #define IS_GRAY8(pf) \
00147     ((((pf.dwFlags & DDPF_LUMINANCE) || (pf.dwFlags & DDPF_ALPHA) ) && \
00148     (pf.dwRGBBitCount == 8) && !(pf.dwFlags & DDPF_ALPHAPIXELS) ) || \
00149      isFourCC("G8  ", pf.dwFourCC ) )
00150 
00151   #define IS_GRAY8_ALPHA8(pf) \
00152     (((pf.dwFlags & DDPF_LUMINANCE) && \
00153     (pf.dwRGBBitCount == 16) && (pf.dwFlags & DDPF_ALPHAPIXELS)) || \
00154      isFourCC("AG8 ", pf.dwFourCC ) )
00155 
00156   #define IS_PALETTE8(pf) isFourCC("P8  ", pf.dwFourCC)
00157 
00158   #define IS_DXT1(pf) isFourCC("DXT1", pf.dwFourCC)
00159 
00160   #define IS_DXT3(pf) isFourCC("DXT3", pf.dwFourCC)
00161 
00162   #define IS_DXT5(pf) isFourCC("DXT5", pf.dwFourCC)
00163 
00164   typedef struct
00165   {
00166     unsigned int dwSize;
00167     unsigned int dwFlags;
00168     unsigned int dwHeight;
00169     unsigned int dwWidth;
00170     unsigned int dwPitchOrLinearSize;
00171     unsigned int dwDepth;
00172     unsigned int dwMipMapCount;
00173     unsigned int dwReserved1[ 11 ];
00174 
00175     // DDPIXELFORMAT
00176     struct
00177     {
00178       unsigned int dwSize;
00179       unsigned int dwFlags;
00180       unsigned int dwFourCC;
00181       unsigned int dwRGBBitCount;
00182       unsigned int dwRBitMask;
00183       unsigned int dwGBitMask;
00184       unsigned int dwBBitMask;
00185       unsigned int dwAlphaBitMask;
00186     } ddpfPixelFormat;
00187 
00188     // DDCAPS2
00189     struct
00190     {
00191       unsigned int dwCaps1;
00192       unsigned int dwCaps2;
00193       unsigned int dwReserved[2];
00194     } ddsCaps;
00195 
00196     unsigned int dwReserved2;
00197 
00198   } DDSURFACEDESC2;
00199 
00200   enum
00201   {
00202     DDS_IMAGE_NULL = 0,
00203     DDS_IMAGE_2D = 2,
00204     DDS_IMAGE_3D = 3,
00205     DDS_IMAGE_CUBEMAP = 4
00206   };
00207 }
00208 //-----------------------------------------------------------------------------
00228 ref<Image> vl::loadDDS(const String& path)
00229 {
00230   ref<VirtualFile> file = defFileSystem()->locateFile(path);
00231   if ( !file )
00232   {
00233     Log::error( Say("File '%s' not found.\n") << path );
00234     return NULL;
00235   }
00236 
00237   return loadDDS(file.get());
00238 }
00239 
00240 VL_COMPILE_TIME_CHECK( sizeof(DDSURFACEDESC2) == 124 );
00241 
00242 ref<Image> vl::loadDDS(VirtualFile* file)
00243 {
00244   if ( !file->open(OM_ReadOnly) )
00245   {
00246     Log::error( Say("DDS: could not open file '%s'.\n") << file->path() );
00247     return NULL;
00248   }
00249 
00250   char signature[4];
00251   file->read(signature,4);
00252   if (strncmp(signature, "DDS ", 4) != 0)
00253   {
00254     file->close();
00255     Log::error( Say("DDS: '%s' is not a DDS file.\n") << file->path() );
00256     return NULL;
00257   }
00258 
00259   DDSURFACEDESC2 header;
00260   memset(&header, 0, sizeof(header));
00261 
00262   file->read(&header, sizeof(header));
00263 
00264   if (header.dwSize != 124 || header.ddpfPixelFormat.dwSize != 32)
00265   {
00266     Log::error( Say("DDS file '%s': corrupted header.\n") << file->path() );
00267     file->close();
00268     return NULL;
00269   }
00270 
00271   if ((header.dwFlags & DDS_REQUIRED_FLAGS) != DDS_REQUIRED_FLAGS )
00272     Log::warning( Say("DDS file '%s': missing DDS_REQUIRED_FLAGS flags.\n") << file->path() );
00273 
00274   if ((header.ddsCaps.dwCaps1 & DDSCAPS_TEXTURE) != DDSCAPS_TEXTURE)
00275     Log::warning( Say("DDS file '%s': missing DDSCAPS_TEXTURE flag.\n") << file->path() );
00276 
00277   int image_type = header.dwDepth ? DDS_IMAGE_3D : DDS_IMAGE_2D;
00278 
00279   if (header.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
00280   {
00281     bool allfaces = (header.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_FACES) != DDSCAPS2_CUBEMAP_FACES;
00282 
00283     if (!allfaces)
00284     {
00285       Log::error( Say("DDS: '%s' contains an invalid cubemap.\n") << file->path() );
00286       file->close();
00287       return NULL;
00288     }
00289     else
00290       image_type = DDS_IMAGE_CUBEMAP;
00291   }
00292 
00293   bool reverse_rgba_bgra = false;
00294   if (header.ddpfPixelFormat.dwRBitMask != 0xFF)
00295     reverse_rgba_bgra = true;
00296 
00297   // loosen alpha mask checks
00298 
00299   // int width = header.dwWidth;
00300   // int height = header.dwHeight;
00301   // int depth = (header.dwFlags & DDS_DEPTH) ? header.dwDepth : 0;
00302   int mipmaps = (header.dwFlags & DDS_MIPMAPCOUNT) ? header.dwMipMapCount : 1; // implies DDSCAPS_MIPMAP | DDSCAPS_COMPLEX
00303   int hasalpha = header.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS;
00304 
00305   // int pitch = (header.dwFlags & DDS_PITCH) ? header.dwPitchOrLinearSize : 0;
00306   // int linearsize = (header.dwFlags & DDS_LINEARSIZE) ? header.dwPitchOrLinearSize : 0;
00307   // int luminance = header.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE;
00308   // int fourcc = (header.ddpfPixelFormat.dwFlags & DDPF_FOURCC) ? header.ddpfPixelFormat.dwFourCC : 0;
00309   // int indexed4 = header.ddpfPixelFormat.dwFlags & DDPF_INDEXED4;
00310   // int indexed8 = header.ddpfPixelFormat.dwFlags & DDPF_INDEXED8;
00311   // int indexedto8 = header.ddpfPixelFormat.dwFlags & DDPF_INDEXEDTO8;
00312   // int fcc = header.ddpfPixelFormat.dwFlags & DDPF_FOURCC;
00313   int rgb = header.ddpfPixelFormat.dwFlags & DDPF_RGB;
00314   // int alpha = header.ddpfPixelFormat.dwFlags & DDPF_ALPHA;
00315   int bitcount = header.ddpfPixelFormat.dwRGBBitCount;
00316 
00317   if (rgb && bitcount == 8)
00318   {
00319     Log::warning( Say("%s: corrupted DDS format! will try to recover...\n") << file->path() );
00320     header.ddpfPixelFormat.dwFlags &= ~DDPF_RGB;
00321     header.ddpfPixelFormat.dwFlags |= DDPF_LUMINANCE;
00322   }
00323 
00324   int max_face = 1;
00325   if (image_type == DDS_IMAGE_CUBEMAP)
00326     max_face = 6;
00327 
00328   std::vector< ref<Image> > image;
00329   for(int i=0; i<mipmaps; ++i)
00330   {
00331     image.push_back( new Image );
00332     image.back()->setObjectName(file->path().toStdString().c_str());
00333   }
00334 
00335   if (IS_BGRA8(header.ddpfPixelFormat) || IS_BGRX8(header.ddpfPixelFormat))
00336   {
00337     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00338     {
00339       w = w == 0 ? 1 : w;
00340       h = h == 0 ? 1 : h;
00341       d = d == 0 ? 1 : d;
00342 
00343       if (image_type == DDS_IMAGE_2D)
00344         image[i]->allocate2D(w, h, 1, IF_RGBA, IT_UNSIGNED_BYTE);
00345       else
00346       if (image_type == DDS_IMAGE_CUBEMAP)
00347         image[i]->allocateCubemap(w, h, 1, IF_RGBA, IT_UNSIGNED_BYTE);
00348       else
00349       if (image_type == DDS_IMAGE_3D)
00350         image[i]->allocate3D(w, h, d, 1, IF_RGBA, IT_UNSIGNED_BYTE);
00351     }
00352 
00353     for(int face=0; face<max_face; ++face)
00354     {
00355       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00356       {
00357         w = w == 0 ? 1 : w;
00358         h = h == 0 ? 1 : h;
00359         d = d == 0 ? 1 : d;
00360 
00361         int req_mem = Image::requiredMemory( w, h, d, 1, IF_RGBA, IT_UNSIGNED_BYTE, false );
00362         int offset = req_mem * face;
00363         file->read(image[i]->pixels() + offset, req_mem);
00364 
00365         if(reverse_rgba_bgra)
00366           swapBytes32_BGRA_RGBA(image[i]->pixels() + offset, req_mem);
00367 
00368         if (IS_BGRX8(header.ddpfPixelFormat))
00369           fillRGBA32_Alpha(image[i]->pixels() + offset, req_mem, 0xFF);
00370       }
00371     }
00372   }
00373   else
00374   if (IS_BGR8(header.ddpfPixelFormat))
00375   {
00376     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00377     {
00378       w = w == 0 ? 1 : w;
00379       h = h == 0 ? 1 : h;
00380       d = d == 0 ? 1 : d;
00381 
00382       if (image_type == DDS_IMAGE_2D)
00383         image[i]->allocate2D(w, h, 1, IF_RGB, IT_UNSIGNED_BYTE);
00384       else
00385       if (image_type == DDS_IMAGE_CUBEMAP)
00386         image[i]->allocateCubemap(w, h, 1, IF_RGB, IT_UNSIGNED_BYTE);
00387       else
00388       if (image_type == DDS_IMAGE_3D)
00389         image[i]->allocate3D(w, h, d, 1, IF_RGB, IT_UNSIGNED_BYTE);
00390     }
00391 
00392     for(int face=0; face<max_face; ++face)
00393     {
00394       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00395       {
00396         w = w == 0 ? 1 : w;
00397         h = h == 0 ? 1 : h;
00398         d = d == 0 ? 1 : d;
00399 
00400         int req_mem = Image::requiredMemory( w, h, d, 1, IF_RGB, IT_UNSIGNED_BYTE, false );
00401         int offset = req_mem * face;
00402         file->read(image[i]->pixels() + offset, req_mem);
00403 
00404         if(reverse_rgba_bgra)
00405           swapBytes24_BGR_RGB(image[i]->pixels() + offset, req_mem);
00406       }
00407     }
00408   }
00409   else
00410   if (IS_GRAY8(header.ddpfPixelFormat))
00411   {
00412     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00413     {
00414       w = w == 0 ? 1 : w;
00415       h = h == 0 ? 1 : h;
00416       d = d == 0 ? 1 : d;
00417 
00418       if (image_type == DDS_IMAGE_2D)
00419         image[i]->allocate2D(w, h, 1, IF_LUMINANCE, IT_UNSIGNED_BYTE);
00420       else
00421       if (image_type == DDS_IMAGE_CUBEMAP)
00422         image[i]->allocateCubemap(w, h, 1, IF_LUMINANCE, IT_UNSIGNED_BYTE);
00423       else
00424       if (image_type == DDS_IMAGE_3D)
00425         image[i]->allocate3D(w, h, d, 1, IF_LUMINANCE, IT_UNSIGNED_BYTE);
00426     }
00427 
00428     for(int face=0; face<max_face; ++face)
00429     {
00430       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00431       {
00432         w = w == 0 ? 1 : w;
00433         h = h == 0 ? 1 : h;
00434         d = d == 0 ? 1 : d;
00435 
00436         int req_mem = Image::requiredMemory( w, h, d, 1, IF_LUMINANCE, IT_UNSIGNED_BYTE, false );
00437         int offset = req_mem*face;
00438         file->read(image[i]->pixels() + offset, req_mem);
00439       }
00440     }
00441   }
00442   else
00443   if (IS_GRAY8_ALPHA8(header.ddpfPixelFormat))
00444   {
00445     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00446     {
00447       w = w == 0 ? 1 : w;
00448       h = h == 0 ? 1 : h;
00449       d = d == 0 ? 1 : d;
00450 
00451       if (image_type == DDS_IMAGE_2D)
00452         image[i]->allocate2D(w, h, 1, IF_LUMINANCE_ALPHA, IT_UNSIGNED_BYTE);
00453       else
00454       if (image_type == DDS_IMAGE_CUBEMAP)
00455         image[i]->allocateCubemap(w, h, 1, IF_LUMINANCE_ALPHA, IT_UNSIGNED_BYTE);
00456       else
00457       if (image_type == DDS_IMAGE_3D)
00458         image[i]->allocate3D(w, h, d, 1, IF_LUMINANCE_ALPHA, IT_UNSIGNED_BYTE);
00459     }
00460 
00461     for(int face=0; face<max_face; ++face)
00462     {
00463       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00464       {
00465         w = w == 0 ? 1 : w;
00466         h = h == 0 ? 1 : h;
00467         d = d == 0 ? 1 : d;
00468 
00469         int req_mem = Image::requiredMemory( w, h, d, 1, IF_LUMINANCE_ALPHA, IT_UNSIGNED_BYTE, false );
00470         int offset = req_mem*face;
00471         file->read(image[i]->pixels() + offset, req_mem);
00472 
00473         if (!hasalpha)
00474           fillGray8Alpha8_Alpha(image[i]->pixels() + offset, req_mem, 0xFF);
00475       }
00476     }
00477   }
00478   else
00479   if (IS_PALETTE8(header.ddpfPixelFormat))
00480   {
00481     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00482     {
00483       w = w == 0 ? 1 : w;
00484       h = h == 0 ? 1 : h;
00485       d = d == 0 ? 1 : d;
00486 
00487       if (image_type == DDS_IMAGE_2D)
00488         image[i]->allocate2D(w, h, 1, IF_RGBA, IT_UNSIGNED_BYTE);
00489       else
00490       if (image_type == DDS_IMAGE_CUBEMAP)
00491         image[i]->allocateCubemap(w, h, 1, IF_RGBA, IT_UNSIGNED_BYTE);
00492       else
00493       if (image_type == DDS_IMAGE_3D)
00494         image[i]->allocate3D(w, h, d, 1, IF_RGBA, IT_UNSIGNED_BYTE);
00495     }
00496 
00497     for(int face=0; face<max_face; ++face)
00498     {
00499       TPalette4x256 palette;
00500       file->read( palette, sizeof(TPalette4x256) );
00501       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00502       {
00503         w = w == 0 ? 1 : w;
00504         h = h == 0 ? 1 : h;
00505         d = d == 0 ? 1 : d;
00506 
00507         int req_mem1 = w*h*d*1;
00508         int req_mem4 = w*h*d*4;
00509         int offset = req_mem4*face;
00510         // read the palette first
00511         file->read( image[i]->pixels() + offset, req_mem1 );
00512         convert8ToRGBA( palette, image[i]->pixels() + offset, w, h * d );
00513         swapBytes32_BGRA_RGBA(image[i]->pixels() + offset, req_mem4);
00514         if (!hasalpha)
00515           fillRGBA32_Alpha(image[i]->pixels() + offset, req_mem4, 0xFF);
00516       }
00517     }
00518   }
00519   else
00520   if ( IS_DXT1(header.ddpfPixelFormat) )
00521   {
00522     EImageFormat DXT1 = hasalpha ? IF_COMPRESSED_RGBA_S3TC_DXT1 : IF_COMPRESSED_RGB_S3TC_DXT1;
00523 
00524     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00525     {
00526       w = w == 0 ? 1 : w;
00527       h = h == 0 ? 1 : h;
00528       d = d == 0 ? 1 : d;
00529 
00530       if (image_type == DDS_IMAGE_2D)
00531         image[i]->allocate2D(w, h, 1, DXT1, IT_IMPLICIT_TYPE);
00532       else
00533       if (image_type == DDS_IMAGE_CUBEMAP)
00534         image[i]->allocateCubemap(w, h, 1, DXT1, IT_IMPLICIT_TYPE);
00535       else
00536       if (image_type == DDS_IMAGE_3D)
00537         image[i]->allocate3D(w, h, d, 1, DXT1, IT_IMPLICIT_TYPE);
00538     }
00539 
00540     for(int face=0; face<max_face; ++face)
00541     {
00542       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00543       {
00544         w = w == 0 ? 1 : w;
00545         h = h == 0 ? 1 : h;
00546         d = d == 0 ? 1 : d;
00547 
00548         int req_mem = Image::requiredMemory( w, h, d, 1, DXT1, IT_IMPLICIT_TYPE, false );
00549         int offset = req_mem*face;
00550         file->read(image[i]->pixels() + offset, req_mem);
00551       }
00552     }
00553   }
00554   else
00555   if ( IS_DXT3(header.ddpfPixelFormat) )
00556   {
00557     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00558     {
00559       w = w == 0 ? 1 : w;
00560       h = h == 0 ? 1 : h;
00561       d = d == 0 ? 1 : d;
00562 
00563       if (image_type == DDS_IMAGE_2D)
00564         image[i]->allocate2D(w, h, 1, IF_COMPRESSED_RGBA_S3TC_DXT3, IT_IMPLICIT_TYPE);
00565       else
00566       if (image_type == DDS_IMAGE_CUBEMAP)
00567         image[i]->allocateCubemap(w, h, 1, IF_COMPRESSED_RGBA_S3TC_DXT3, IT_IMPLICIT_TYPE);
00568       else
00569       if (image_type == DDS_IMAGE_3D)
00570         image[i]->allocate3D(w, h, d, 1, IF_COMPRESSED_RGBA_S3TC_DXT3, IT_IMPLICIT_TYPE);
00571     }
00572 
00573     for(int face=0; face<max_face; ++face)
00574     {
00575       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00576       {
00577         w = w == 0 ? 1 : w;
00578         h = h == 0 ? 1 : h;
00579         d = d == 0 ? 1 : d;
00580 
00581         int req_mem = Image::requiredMemory( w, h, d, 1, IF_COMPRESSED_RGBA_S3TC_DXT3, IT_IMPLICIT_TYPE, false );
00582         int offset = req_mem*face;
00583         file->read(image[i]->pixels() + offset, req_mem);
00584       }
00585     }
00586   }
00587   else
00588   if ( IS_DXT5(header.ddpfPixelFormat) )
00589   {
00590     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00591     {
00592       w = w == 0 ? 1 : w;
00593       h = h == 0 ? 1 : h;
00594       d = d == 0 ? 1 : d;
00595 
00596       if (image_type == DDS_IMAGE_2D)
00597         image[i]->allocate2D(w, h, 1, IF_COMPRESSED_RGBA_S3TC_DXT5, IT_IMPLICIT_TYPE);
00598       else
00599       if (image_type == DDS_IMAGE_CUBEMAP)
00600         image[i]->allocateCubemap(w, h, 1, IF_COMPRESSED_RGBA_S3TC_DXT5, IT_IMPLICIT_TYPE);
00601       else
00602       if (image_type == DDS_IMAGE_3D)
00603         image[i]->allocate3D(w, h, d, 1, IF_COMPRESSED_RGBA_S3TC_DXT5, IT_IMPLICIT_TYPE);
00604     }
00605 
00606     for(int face=0; face<max_face; ++face)
00607     {
00608       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
00609       {
00610         w = w == 0 ? 1 : w;
00611         h = h == 0 ? 1 : h;
00612         d = d == 0 ? 1 : d;
00613 
00614         int req_mem = Image::requiredMemory( w, h, d, 1, IF_COMPRESSED_RGBA_S3TC_DXT5, IT_IMPLICIT_TYPE, false );
00615         int offset = req_mem*face;
00616         file->read(image[i]->pixels() + offset, req_mem);
00617       }
00618     }
00619   }
00620   else
00621   {
00622     Log::error( Say("DDS: not supported format for '%s'.\n") << file->path() );
00623     file->close();
00624     return NULL;
00625   }
00626 
00627   file->close();
00628 
00629   // We don't flip at all the DDS to be consistent since flipping
00630   // vertically/horizontally compressed images is not possible.
00631   // The textures must be already flipped using the OpenGL reference system.
00632 
00633   #if 0
00634     if (image_type == DDS_IMAGE_2D && !s3tc_compressed)
00635     {
00636       for (int i=0; i<(int)image.size(); ++i)
00637         internal_FlipVertically(image[i]);
00638     }
00639     else
00640     if (image_type == DDS_IMAGE_3D)
00641     {
00642       // should be flipped vertically and then
00643       // invert their order along the z-axis
00644       // ...
00645     }
00646     else
00647     if (image_type == DDS_IMAGE_CUBEMAP)
00648     {
00649       // should be flipped in a more sofisticated way, sg like:
00650       // X+- flip orizontally
00651       // Y+- flip vertically
00652       // Z+- exchange one with the other
00653       // ...
00654     }
00655   #endif
00656 
00657   VL_CHECK(image.size());
00658 
00659   ref<Image> img = new Image;
00660   img->setObjectName(file->path().toStdString().c_str());
00661   *img = *image[0];
00662   image.erase(image.begin());
00663   img->setMipmaps(image);
00664 
00665   return img;
00666 }
00667 //-----------------------------------------------------------------------------
00668 bool vl::isDDS(VirtualFile* file)
00669 {
00670   if (!file->open(OM_ReadOnly))
00671     return false;
00672 
00673   char signature[4];
00674   file->read(signature, 4);
00675   if (strncmp(signature, "DDS ", 4) != 0)
00676   {
00677     file->close();
00678     return false;
00679   }
00680 
00681   DDSURFACEDESC2 header;
00682   memset(&header, 0, sizeof(header));
00683 
00684   // fread(&header, 1, sizeof(header), fin);
00685 
00686   header.dwSize = file->readUInt32();
00687   header.dwFlags = file->readUInt32();
00688   header.dwHeight = file->readUInt32();
00689   header.dwWidth = file->readUInt32();
00690   header.dwPitchOrLinearSize = file->readUInt32();
00691   header.dwDepth = file->readUInt32();
00692   header.dwMipMapCount = file->readUInt32();
00693   // fread(header.dwReserved1, 1, 11*sizeof(unsigned long), fin);
00694   file->read(header.dwReserved1, 11*sizeof(unsigned long));
00695   header.ddpfPixelFormat.dwSize = file->readUInt32();
00696   header.ddpfPixelFormat.dwFlags = file->readUInt32();
00697   header.ddpfPixelFormat.dwFourCC = file->readUInt32();
00698   header.ddpfPixelFormat.dwRGBBitCount = file->readUInt32();
00699   header.ddpfPixelFormat.dwRBitMask = file->readUInt32();
00700   header.ddpfPixelFormat.dwGBitMask = file->readUInt32();
00701   header.ddpfPixelFormat.dwBBitMask = file->readUInt32();
00702   header.ddpfPixelFormat.dwAlphaBitMask = file->readUInt32();
00703   header.ddsCaps.dwCaps1 = file->readUInt32();
00704   header.ddsCaps.dwCaps2 = file->readUInt32();
00705   header.ddsCaps.dwReserved[0] = file->readUInt32();
00706   header.ddsCaps.dwReserved[1] = file->readUInt32();
00707   header.dwReserved2 = file->readUInt32();
00708 
00709   file->close();
00710 
00711   if (header.dwSize != 124 || header.ddpfPixelFormat.dwSize != 32)
00712     return false;
00713 
00714   // warn only when actually loading
00715 #if 0
00716   if ((header.dwFlags & DDS_REQUIRED_FLAGS) != DDS_REQUIRED_FLAGS )
00717     Log::warning( Say("DDS file '%s': missing DDS_REQUIRED_FLAGS flags.\n") << file->path() );
00718 
00719   if ((header.ddsCaps.dwCaps1 & DDSCAPS_TEXTURE) != DDSCAPS_TEXTURE)
00720     Log::warning( Say("DDS file '%s': missing DDSCAPS_TEXTURE flag.\n") << file->path() );
00721 #endif
00722 
00723   return true;
00724 }
00725 //-----------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:30.
Permission is granted to use this page to write and publish articles regarding Visualization Library.