# Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics

[Home] [Tutorials] [All Classes] [Grouped Classes]

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/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 v2011.09.1162 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu Jan 26 2012 00:43:30.
Permission is granted to use this page to write and publish articles regarding Visualization Library.