# Visualization Library

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

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

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlCore/plugins/vlDDS.cpp

Go to the documentation of this file.

    00001 /**************************************************************************************/
    00002 /*                                                                                    */
    00003 /*  Visualization Library                                                             */
    00004 /*  http://www.visualizationlibrary.com                                               */
    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 "vlDDS.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 using namespace vl;
    00041
    00042 #include <vlCore/ImageTools.hpp>
    00043
    00044 //-----------------------------------------------------------------------------
    00045 // DDS loader
    00046 //-----------------------------------------------------------------------------
    00047 namespace
    00048 {
    00049   // DDSURFACEDESC2.dwFlags
    00050   const unsigned long DDS_CAPS            = 0x00000001;
    00051   const unsigned long DDS_HEIGHT          = 0x00000002;
    00052   const unsigned long DDS_WIDTH           = 0x00000004;
    00053   const unsigned long DDS_PITCH           = 0x00000008;
    00054   const unsigned long DDS_BACKBUFFERCOUNT = 0x00000020;
    00055   const unsigned long DDS_ZBUFFERBITDEPTH = 0x00000040;
    00056   const unsigned long DDS_ALPHABITDEPTH   = 0x00000080;
    00057   const unsigned long DDS_LPSURFACE       = 0x00000800;
    00058   const unsigned long DDS_PIXELFORMAT     = 0x00001000;
    00059   const unsigned long DDS_CKDESTOVERLAY   = 0x00002000;
    00060   const unsigned long DDS_CKDESTBLT       = 0x00004000;
    00061   const unsigned long DDS_CKSRCOVERLAY    = 0x00008000;
    00062   const unsigned long DDS_CKSRCBLT        = 0x00010000;
    00063   const unsigned long DDS_MIPMAPCOUNT     = 0x00020000;
    00064   const unsigned long DDS_REFRESHRATE     = 0x00040000;
    00065   const unsigned long DDS_LINEARSIZE      = 0x00080000;
    00066   const unsigned long DDS_TEXTURESTAGE    = 0x00100000;
    00067   const unsigned long DDS_FVF             = 0x00200000;
    00068   const unsigned long DDS_SRCVBHANDLE     = 0x00400000;
    00069   const unsigned long DDS_DEPTH           = 0x00800000;
    00070   const unsigned long DDS_ALL             = 0x007FF9EE;
    00071   const unsigned long DDS_REQUIRED_FLAGS  = DDS_CAPS|DDS_PIXELFORMAT|DDS_WIDTH|DDS_HEIGHT;
    00072
    00073   // DDPIXELFORMAT.dwFlags
    00074   const unsigned long DDPF_ALPHAPIXELS     = 0x00000001;
    00075   const unsigned long DDPF_ALPHA           = 0x00000002;
    00076   const unsigned long DDPF_FOURCC          = 0x00000004;
    00077   const unsigned long DDPF_INDEXED4        = 0x00000008;
    00078   const unsigned long DDPF_INDEXEDTO8      = 0x00000010;
    00079   const unsigned long DDPF_INDEXED8        = 0x00000020;
    00080   const unsigned long DDPF_RGB             = 0x00000040;
    00081   const unsigned long DDPF_COMPRESSED      = 0x00000080;
    00082   const unsigned long DDPF_RGBTOYUV        = 0x00000100;
    00083   const unsigned long DDPF_YUV             = 0x00000200;
    00084   const unsigned long DDPF_ZBUFFER         = 0x00000400;
    00085   const unsigned long DDPF_PALETTEINDEXED1 = 0x00000800;
    00086   const unsigned long DDPF_PALETTEINDEXED2 = 0x00001000;
    00087   const unsigned long DDPF_ZPIXELS         = 0x00002000;
    00088   const unsigned long DDPF_STENCILBUFFER   = 0x00004000;
    00089   const unsigned long DDPF_ALPHAPREMULT    = 0x00008000;
    00090   const unsigned long DDPF_LUMINANCE       = 0x00020000;
    00091   const unsigned long DDPF_BUMPLUMINANCE   = 0x00040000;
    00092   const unsigned long DDPF_BUMPDUDV        = 0x00080000;
    00093
    00094   // DDSCAPS2.dwCaps1
    00095   const unsigned long DDSCAPS_COMPLEX  = 0x00000008;
    00096   const unsigned long DDSCAPS_TEXTURE  = 0x00001000;
    00097   const unsigned long DDSCAPS_MIPMAP  = 0x00400000;
    00098
    00099   // DDSCAPS2.dwCaps2
    00100   const unsigned long DDSCAPS2_CUBEMAP  = 0x00000200;
    00101   const unsigned long DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400;
    00102   const unsigned long DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800;
    00103   const unsigned long DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000;
    00104   const unsigned long DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000;
    00105   const unsigned long DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000;
    00106   const unsigned long DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000;
    00107   const unsigned long DDSCAPS2_CUBEMAP_FACES =
    00108     DDSCAPS2_CUBEMAP_POSITIVEX + DDSCAPS2_CUBEMAP_POSITIVEY + DDSCAPS2_CUBEMAP_POSITIVEZ +
    00109     DDSCAPS2_CUBEMAP_NEGATIVEX + DDSCAPS2_CUBEMAP_NEGATIVEY + DDSCAPS2_CUBEMAP_NEGATIVEZ;
    00110
    00111   const unsigned long DDSCAPS2_VOLUME  = 0x00200000;
    00112
    00113   // DDPIXELFORMAT.dwFourCC compressed texture type
    00114   //const char* FOURCC_DXT1 = "DXT1";
    00115   //const char* FOURCC_DXT2 = "DXT2";
    00116   //const char* FOURCC_DXT3 = "DXT3";
    00117   //const char* FOURCC_DXT4 = "DXT4";
    00118   //const char* FOURCC_DXT5 = "DXT5";
    00119   //const char* FOURCC_PALETTE8 = "P8  ";
    00120   //const char* FOURCC_GRAY8ALPHA8 = "AG8 ";
    00121
    00122   bool isFOURCC(const char* code, unsigned long fcc)
    00123   {
    00124     return memcmp(code, &fcc, 4) == 0;
    00125   }
    00126
    00127   // quick surface type macros
    00128   #define IS_BGRA8(pf) \
    00129     ((pf.dwFlags & DDPF_RGB) && \
    00130      (pf.dwFlags & DDPF_ALPHAPIXELS) && \
    00131      (pf.dwRGBBitCount == 32))
    00132
    00133   #define IS_BGRX8(pf) \
    00134     ((pf.dwFlags & DDPF_RGB) && \
    00135      !(pf.dwFlags & DDPF_ALPHAPIXELS) && \
    00136      (pf.dwRGBBitCount == 32))
    00137
    00138   #define IS_BGR8(pf) \
    00139     ((pf.dwFlags & DDPF_RGB) && \
    00140     !(pf.dwFlags & DDPF_ALPHAPIXELS) && \
    00141      (pf.dwRGBBitCount == 24))
    00142
    00143   #define IS_GRAY8(pf) \
    00144     ((((pf.dwFlags & DDPF_LUMINANCE) || (pf.dwFlags & DDPF_ALPHA) ) && \
    00145     (pf.dwRGBBitCount == 8) && !(pf.dwFlags & DDPF_ALPHAPIXELS) ) || \
    00146      isFOURCC("G8  ", pf.dwFourCC ) )
    00147
    00148   #define IS_GRAY8_ALPHA8(pf) \
    00149     (((pf.dwFlags & DDPF_LUMINANCE) && \
    00150     (pf.dwRGBBitCount == 16) && (pf.dwFlags & DDPF_ALPHAPIXELS)) || \
    00151      isFOURCC("AG8 ", pf.dwFourCC ) )
    00152
    00153   #define IS_PALETTE8(pf) isFOURCC("P8  ", pf.dwFourCC )
    00154
    00155   #define IS_DXT1(pf) isFOURCC("DXT1", pf.dwFourCC)
    00156
    00157   #define IS_DXT3(pf) isFOURCC("DXT3", pf.dwFourCC)
    00158
    00159   #define IS_DXT5(pf) isFOURCC("DXT5", pf.dwFourCC)
    00160
    00161   typedef struct
    00162   {
    00163     unsigned int dwSize;
    00164     unsigned int dwFlags;
    00165     unsigned int dwHeight;
    00166     unsigned int dwWidth;
    00167     unsigned int dwPitchOrLinearSize;
    00168     unsigned int dwDepth;
    00169     unsigned int dwMipMapCount;
    00170     unsigned int dwReserved1[ 11 ];
    00171
    00172     // DDPIXELFORMAT
    00173     struct
    00174     {
    00175       unsigned int dwSize;
    00176       unsigned int dwFlags;
    00177       unsigned int dwFourCC;
    00178       unsigned int dwRGBBitCount;
    00179       unsigned int dwRBitMask;
    00180       unsigned int dwGBitMask;
    00181       unsigned int dwBBitMask;
    00182       unsigned int dwAlphaBitMask;
    00183     } ddpfPixelFormat;
    00184
    00185     // DDCAPS2
    00186     struct
    00187     {
    00188       unsigned int dwCaps1;
    00189       unsigned int dwCaps2;
    00190       unsigned int dwReserved[2];
    00191     } ddsCaps;
    00192
    00193     unsigned int dwReserved2;
    00194
    00195   } DDSURFACEDESC2;
    00196
    00197   enum
    00198   {
    00199     DDS_IMAGE_NULL = 0,
    00200     DDS_IMAGE_2D = 2,
    00201     DDS_IMAGE_3D = 3,
    00202     DDS_IMAGE_CUBEMAP = 4
    00203   };
    00204 }
    00205 //-----------------------------------------------------------------------------
    00225 ref<Image> vl::loadDDS(const String& path)
    00226 {
    00227   ref<VirtualFile> file = defFileSystem()->locateFile(path);
    00228   if ( !file )
    00229   {
    00230     Log::error( Say("File '%s' not found.\n") << path );
    00231     return NULL;
    00232   }
    00233
    00234   // FILE * fin = fopen( path.toStdString().c_str(), "rb");
    00235   // if (!fin)
    00236   return loadDDS(file.get());
    00237 }
    00238
    00239 VL_COMPILE_TIME_CHECK( sizeof(DDSURFACEDESC2) == 124 );
    00240
    00241 ref<Image> vl::loadDDS(VirtualFile* file)
    00242 {
    00243   if ( !file->open(OM_ReadOnly) )
    00244   {
    00245     Log::error( Say("DDS: could not open file '%s'.\n") << file->path() );
    00246     return NULL;
    00247   }
    00248
    00249   ref<Image> img = new Image;
    00250   img->setObjectName( file->path().toStdString() );
    00251
    00252   char signature[4];
    00253   // fread(signature, 1, 4, fin);
    00254   file->read(signature,4);
    00255   if (strncmp(signature, "DDS ", 4) != 0)
    00256   {
    00257     // fclose(fin);
    00258     file->close();
    00259     Log::error( Say("DDS: '%s' is not a DDS file.\n") << file->path() );
    00260     return NULL;
    00261   }
    00262
    00263   DDSURFACEDESC2 header;
    00264   memset(&header, 0, sizeof(header));
    00265
    00266   // fread(&header, 1, sizeof(header), fin);
    00267
    00268   header.dwSize = file->readUInt32();
    00269   header.dwFlags = file->readUInt32();
    00270   header.dwHeight = file->readUInt32();
    00271   header.dwWidth = file->readUInt32();
    00272   header.dwPitchOrLinearSize = file->readUInt32();
    00273   header.dwDepth = file->readUInt32();
    00274   header.dwMipMapCount = file->readUInt32();
    00275   // fread(header.dwReserved1, 1, 11*sizeof(unsigned long), fin);
    00276   file->read(header.dwReserved1, 11*sizeof(unsigned long));
    00277   header.ddpfPixelFormat.dwSize = file->readUInt32();
    00278   header.ddpfPixelFormat.dwFlags = file->readUInt32();
    00279   header.ddpfPixelFormat.dwFourCC = file->readUInt32();
    00280   header.ddpfPixelFormat.dwRGBBitCount = file->readUInt32();
    00281   header.ddpfPixelFormat.dwRBitMask = file->readUInt32();
    00282   header.ddpfPixelFormat.dwGBitMask = file->readUInt32();
    00283   header.ddpfPixelFormat.dwBBitMask = file->readUInt32();
    00284   header.ddpfPixelFormat.dwAlphaBitMask = file->readUInt32();
    00285   header.ddsCaps.dwCaps1 = file->readUInt32();
    00286   header.ddsCaps.dwCaps2 = file->readUInt32();
    00287   header.ddsCaps.dwReserved[0] = file->readUInt32();
    00288   header.ddsCaps.dwReserved[1] = file->readUInt32();
    00289   header.dwReserved2 = file->readUInt32();
    00290
    00291   if (header.dwSize != 124 || header.ddpfPixelFormat.dwSize != 32)
    00292   {
    00293     Log::error( Say("DDS file '%s': corrupted header.\n") << file->path() );
    00294     // fclose(fin);
    00295     file->close();
    00296     return NULL;
    00297   }
    00298
    00299   if ((header.dwFlags & DDS_REQUIRED_FLAGS) != DDS_REQUIRED_FLAGS )
    00300     Log::warning( Say("DDS file '%s': missing DDS_REQUIRED_FLAGS flags.\n") << file->path() );
    00301
    00302   if ((header.ddsCaps.dwCaps1 & DDSCAPS_TEXTURE) != DDSCAPS_TEXTURE)
    00303     Log::warning( Say("DDS file '%s': missing DDSCAPS_TEXTURE flag.\n") << file->path() );
    00304
    00305   //if (header.ddsCaps.dwCaps1 & DDSCAPS_MIPMAP)
    00306   //{
    00307   //  printf("we got mipmaps: %d!\n", header.dwMipMapCount);
    00308   //}
    00309
    00310   int image_type = header.dwDepth ? DDS_IMAGE_3D : DDS_IMAGE_2D;
    00311
    00312   if (header.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
    00313   {
    00314     // printf("we got a cubemap!\n");
    00315     bool allfaces = (header.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_FACES) != 0;
    00316
    00317     if (!allfaces)
    00318     {
    00319       // printf("Error: the cubemap is incomplete, one or more faces are missing!\n");
    00320       Log::error( Say("DDS: '%s' contains an invalid cubemap.\n") << file->path() );
    00321       // fclose(fin);
    00322       file->close();
    00323       return NULL;
    00324     }
    00325     else
    00326       image_type = DDS_IMAGE_CUBEMAP;
    00327   }
    00328
    00329   bool reverse_rgba_bgra = false;
    00330   if (header.ddpfPixelFormat.dwRBitMask != 0xFF)
    00331     reverse_rgba_bgra = true;
    00332
    00333   // loosen alpha mask checks
    00334
    00335   // int width = header.dwWidth;
    00336   // int height = header.dwHeight;
    00337   // int depth = (header.dwFlags & DDS_DEPTH) ? header.dwDepth : 0;
    00338   int mipmaps = (header.dwFlags & DDS_MIPMAPCOUNT) ? header.dwMipMapCount : 1; // implies DDSCAPS_MIPMAP | DDSCAPS_COMPLEX
    00339   int hasalpha = header.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS;
    00340
    00341   // int pitch = (header.dwFlags & DDS_PITCH) ? header.dwPitchOrLinearSize : 0;
    00342   // int linearsize = (header.dwFlags & DDS_LINEARSIZE) ? header.dwPitchOrLinearSize : 0;
    00343   // int luminance = header.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE;
    00344   // int fourcc = (header.ddpfPixelFormat.dwFlags & DDPF_FOURCC) ? header.ddpfPixelFormat.dwFourCC : 0;
    00345   // int indexed4 = header.ddpfPixelFormat.dwFlags & DDPF_INDEXED4;
    00346   // int indexed8 = header.ddpfPixelFormat.dwFlags & DDPF_INDEXED8;
    00347   // int indexedto8 = header.ddpfPixelFormat.dwFlags & DDPF_INDEXEDTO8;
    00348   // int fcc = header.ddpfPixelFormat.dwFlags & DDPF_FOURCC;
    00349   int rgb = header.ddpfPixelFormat.dwFlags & DDPF_RGB;
    00350   // int alpha = header.ddpfPixelFormat.dwFlags & DDPF_ALPHA;
    00351   int bitcount = header.ddpfPixelFormat.dwRGBBitCount;
    00352
    00353   if (rgb && bitcount == 8)
    00354   {
    00355     Log::warning( Say("%s: corrupted DDS format! will try to recover...\n") << file->path() );
    00356     header.ddpfPixelFormat.dwFlags &= ~DDPF_RGB;
    00357     header.ddpfPixelFormat.dwFlags |= DDPF_LUMINANCE;
    00358   }
    00359
    00360   int max_face = 1;
    00361   if (image_type == DDS_IMAGE_CUBEMAP)
    00362     max_face = 6;
    00363
    00364   std::vector< ref<Image> > image;
    00365   for(int i=0; i<mipmaps; ++i)
    00366   {
    00367     image.push_back( new Image );
    00368     image.back()->setObjectName(file->path().toStdString());
    00369   }
    00370
    00371   //  char ptr[] = {
    00372   //  ((char*)&header.ddpfPixelFormat.dwFourCC)[0],
    00373   //  ((char*)&header.ddpfPixelFormat.dwFourCC)[1],
    00374   //  ((char*)&header.ddpfPixelFormat.dwFourCC)[2],
    00375   //  ((char*)&header.ddpfPixelFormat.dwFourCC)[3],
    00376   //  0
    00377   //};
    00378   //printf("===> '%s'\n", ptr);
    00379
    00380   if (IS_BGRA8(header.ddpfPixelFormat) || IS_BGRX8(header.ddpfPixelFormat))
    00381   {
    00382     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00383     {
    00384       w = w == 0 ? 1 : w;
    00385       h = h == 0 ? 1 : h;
    00386       d = d == 0 ? 1 : d;
    00387
    00388       if (image_type == DDS_IMAGE_2D)
    00389         image[i]->allocate2D(w, h, 1, IF_RGBA, IT_UNSIGNED_BYTE);
    00390       else
    00391       if (image_type == DDS_IMAGE_CUBEMAP)
    00392         image[i]->allocateCubemap(w, h, 1, IF_RGBA, IT_UNSIGNED_BYTE);
    00393       else
    00394       if (image_type == DDS_IMAGE_3D)
    00395         image[i]->allocate3D(w, h, d, 1, IF_RGBA, IT_UNSIGNED_BYTE);
    00396     }
    00397
    00398     for(int face=0; face<max_face; ++face)
    00399     {
    00400       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00401       {
    00402         w = w == 0 ? 1 : w;
    00403         h = h == 0 ? 1 : h;
    00404         d = d == 0 ? 1 : d;
    00405
    00406         int req_mem = Image::requiredMemory( w, h, d, 1, IF_RGBA, IT_UNSIGNED_BYTE, false );
    00407         int offset = req_mem*face;
    00408         // fread(image[i]->pixels() + offset, 1, req_mem, fin);
    00409         file->read(image[i]->pixels() + offset, req_mem);
    00410
    00411         if(reverse_rgba_bgra)
    00412           swapBytes32_BGRA_RGBA(image[i]->pixels() + offset, req_mem);
    00413
    00414         if (IS_BGRX8(header.ddpfPixelFormat))
    00415           fillRGBA32_Alpha(image[i]->pixels() + offset, req_mem, 0xFF);
    00416       }
    00417     }
    00418   }
    00419   else
    00420   if (IS_BGR8(header.ddpfPixelFormat))
    00421   {
    00422     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00423     {
    00424       w = w == 0 ? 1 : w;
    00425       h = h == 0 ? 1 : h;
    00426       d = d == 0 ? 1 : d;
    00427
    00428       if (image_type == DDS_IMAGE_2D)
    00429         image[i]->allocate2D(w, h, 1, IF_RGB, IT_UNSIGNED_BYTE);
    00430       else
    00431       if (image_type == DDS_IMAGE_CUBEMAP)
    00432         image[i]->allocateCubemap(w, h, 1, IF_RGB, IT_UNSIGNED_BYTE);
    00433       else
    00434       if (image_type == DDS_IMAGE_3D)
    00435         image[i]->allocate3D(w, h, d, 1, IF_RGB, IT_UNSIGNED_BYTE);
    00436     }
    00437
    00438     for(int face=0; face<max_face; ++face)
    00439     {
    00440       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00441       {
    00442         w = w == 0 ? 1 : w;
    00443         h = h == 0 ? 1 : h;
    00444         d = d == 0 ? 1 : d;
    00445
    00446         int req_mem = Image::requiredMemory( w, h, d, 1, IF_RGB, IT_UNSIGNED_BYTE, false );
    00447         int offset = req_mem*face;
    00448         // fread(image[i]->pixels() + offset, 1, req_mem, fin);
    00449         file->read(image[i]->pixels() + offset, req_mem);
    00450
    00451         if(reverse_rgba_bgra)
    00452           swapBytes24_BGR_RGB(image[i]->pixels() + offset, req_mem);
    00453       }
    00454     }
    00455   }
    00456   else
    00457   if (IS_GRAY8(header.ddpfPixelFormat))
    00458   {
    00459     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00460     {
    00461       w = w == 0 ? 1 : w;
    00462       h = h == 0 ? 1 : h;
    00463       d = d == 0 ? 1 : d;
    00464
    00465       if (image_type == DDS_IMAGE_2D)
    00466         image[i]->allocate2D(w, h, 1, IF_LUMINANCE, IT_UNSIGNED_BYTE);
    00467       else
    00468       if (image_type == DDS_IMAGE_CUBEMAP)
    00469         image[i]->allocateCubemap(w, h, 1, IF_LUMINANCE, IT_UNSIGNED_BYTE);
    00470       else
    00471       if (image_type == DDS_IMAGE_3D)
    00472         image[i]->allocate3D(w, h, d, 1, IF_LUMINANCE, IT_UNSIGNED_BYTE);
    00473     }
    00474
    00475     for(int face=0; face<max_face; ++face)
    00476     {
    00477       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00478       {
    00479         w = w == 0 ? 1 : w;
    00480         h = h == 0 ? 1 : h;
    00481         d = d == 0 ? 1 : d;
    00482
    00483         int req_mem = Image::requiredMemory( w, h, d, 1, IF_LUMINANCE, IT_UNSIGNED_BYTE, false );
    00484         int offset = req_mem*face;
    00485         // fread(image[i]->pixels() + offset, 1, req_mem, fin);
    00486         file->read(image[i]->pixels() + offset, req_mem);
    00487       }
    00488     }
    00489   }
    00490   else
    00491   if (IS_GRAY8_ALPHA8(header.ddpfPixelFormat))
    00492   {
    00493     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00494     {
    00495       w = w == 0 ? 1 : w;
    00496       h = h == 0 ? 1 : h;
    00497       d = d == 0 ? 1 : d;
    00498
    00499       if (image_type == DDS_IMAGE_2D)
    00500         image[i]->allocate2D(w, h, 1, IF_LUMINANCE_ALPHA, IT_UNSIGNED_BYTE);
    00501       else
    00502       if (image_type == DDS_IMAGE_CUBEMAP)
    00503         image[i]->allocateCubemap(w, h, 1, IF_LUMINANCE_ALPHA, IT_UNSIGNED_BYTE);
    00504       else
    00505       if (image_type == DDS_IMAGE_3D)
    00506         image[i]->allocate3D(w, h, d, 1, IF_LUMINANCE_ALPHA, IT_UNSIGNED_BYTE);
    00507     }
    00508
    00509     for(int face=0; face<max_face; ++face)
    00510     {
    00511       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00512       {
    00513         w = w == 0 ? 1 : w;
    00514         h = h == 0 ? 1 : h;
    00515         d = d == 0 ? 1 : d;
    00516
    00517         int req_mem = Image::requiredMemory( w, h, d, 1, IF_LUMINANCE_ALPHA, IT_UNSIGNED_BYTE, false );
    00518         int offset = req_mem*face;
    00519         // fread(image[i]->pixels() + offset, 1, req_mem, fin);
    00520         file->read(image[i]->pixels() + offset, req_mem);
    00521         if (!hasalpha)
    00522           fillGray8Alpha8_Alpha(image[i]->pixels() + offset, req_mem, 0xFF);
    00523       }
    00524     }
    00525   }
    00526   else
    00527   if (IS_PALETTE8(header.ddpfPixelFormat))
    00528   {
    00529     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00530     {
    00531       w = w == 0 ? 1 : w;
    00532       h = h == 0 ? 1 : h;
    00533       d = d == 0 ? 1 : d;
    00534
    00535       if (image_type == DDS_IMAGE_2D)
    00536         image[i]->allocate2D(w, h, 1, IF_RGBA, IT_UNSIGNED_BYTE);
    00537       else
    00538       if (image_type == DDS_IMAGE_CUBEMAP)
    00539         image[i]->allocateCubemap(w, h, 1, IF_RGBA, IT_UNSIGNED_BYTE);
    00540       else
    00541       if (image_type == DDS_IMAGE_3D)
    00542         image[i]->allocate3D(w, h, d, 1, IF_RGBA, IT_UNSIGNED_BYTE);
    00543     }
    00544
    00545     for(int face=0; face<max_face; ++face)
    00546     {
    00547       TPalette4x256 palette;
    00548       // fread( palette, 1, sizeof(TPalette4x256), fin );
    00549       file->read( palette, sizeof(TPalette4x256) );
    00550       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00551       {
    00552         w = w == 0 ? 1 : w;
    00553         h = h == 0 ? 1 : h;
    00554         d = d == 0 ? 1 : d;
    00555
    00556         int req_mem1 = w*h*d*1;
    00557         int req_mem4 = w*h*d*4;
    00558         int offset = req_mem4*face;
    00559         // read the palette first
    00560         // fread(image[i]->pixels() + offset, 1, req_mem1, fin);
    00561         file->read( image[i]->pixels() + offset, req_mem1 );
    00562         convert8ToRGBA( palette, image[i]->pixels() + offset, w, h * d );
    00563         swapBytes32_BGRA_RGBA(image[i]->pixels() + offset, req_mem4);
    00564         if (!hasalpha)
    00565           fillRGBA32_Alpha(image[i]->pixels() + offset, req_mem4, 0xFF);
    00566       }
    00567     }
    00568   }
    00569   else
    00570   if ( IS_DXT1(header.ddpfPixelFormat) )
    00571   {
    00572     EImageFormat DXT1 = hasalpha ? IF_COMPRESSED_RGBA_S3TC_DXT1 : IF_COMPRESSED_RGB_S3TC_DXT1;
    00573
    00574     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00575     {
    00576       w = w == 0 ? 1 : w;
    00577       h = h == 0 ? 1 : h;
    00578       d = d == 0 ? 1 : d;
    00579
    00580       if (image_type == DDS_IMAGE_2D)
    00581         image[i]->allocate2D(w, h, 1, DXT1, IT_IMPLICIT_TYPE);
    00582       else
    00583       if (image_type == DDS_IMAGE_CUBEMAP)
    00584         image[i]->allocateCubemap(w, h, 1, DXT1, IT_IMPLICIT_TYPE);
    00585       else
    00586       if (image_type == DDS_IMAGE_3D)
    00587         image[i]->allocate3D(w, h, d, 1, DXT1, IT_IMPLICIT_TYPE);
    00588     }
    00589
    00590     for(int face=0; face<max_face; ++face)
    00591     {
    00592       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00593       {
    00594         w = w == 0 ? 1 : w;
    00595         h = h == 0 ? 1 : h;
    00596         d = d == 0 ? 1 : d;
    00597
    00598         int req_mem = Image::requiredMemory( w, h, d, 1, DXT1, IT_IMPLICIT_TYPE, false );
    00599         int offset = req_mem*face;
    00600         // fread(image[i]->pixels() + offset, 1, req_mem, fin);
    00601         file->read(image[i]->pixels() + offset, req_mem);
    00602       }
    00603     }
    00604   }
    00605   else
    00606   if ( IS_DXT3(header.ddpfPixelFormat) )
    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       if (image_type == DDS_IMAGE_2D)
    00615         image[i]->allocate2D(w, h, 1, IF_COMPRESSED_RGBA_S3TC_DXT3, IT_IMPLICIT_TYPE);
    00616       else
    00617       if (image_type == DDS_IMAGE_CUBEMAP)
    00618         image[i]->allocateCubemap(w, h, 1, IF_COMPRESSED_RGBA_S3TC_DXT3, IT_IMPLICIT_TYPE);
    00619       else
    00620       if (image_type == DDS_IMAGE_3D)
    00621         image[i]->allocate3D(w, h, d, 1, IF_COMPRESSED_RGBA_S3TC_DXT3, IT_IMPLICIT_TYPE);
    00622     }
    00623
    00624     for(int face=0; face<max_face; ++face)
    00625     {
    00626       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00627       {
    00628         w = w == 0 ? 1 : w;
    00629         h = h == 0 ? 1 : h;
    00630         d = d == 0 ? 1 : d;
    00631
    00632         int req_mem = Image::requiredMemory( w, h, d, 1, IF_COMPRESSED_RGBA_S3TC_DXT3, IT_IMPLICIT_TYPE, false );
    00633         int offset = req_mem*face;
    00634         // fread(image[i]->pixels() + offset, 1, req_mem, fin);
    00635         file->read(image[i]->pixels() + offset, req_mem);
    00636       }
    00637     }
    00638   }
    00639   else
    00640   if ( IS_DXT5(header.ddpfPixelFormat) )
    00641   {
    00642     for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00643     {
    00644       w = w == 0 ? 1 : w;
    00645       h = h == 0 ? 1 : h;
    00646       d = d == 0 ? 1 : d;
    00647
    00648       if (image_type == DDS_IMAGE_2D)
    00649         image[i]->allocate2D(w, h, 1, IF_COMPRESSED_RGBA_S3TC_DXT5, IT_IMPLICIT_TYPE);
    00650       else
    00651       if (image_type == DDS_IMAGE_CUBEMAP)
    00652         image[i]->allocateCubemap(w, h, 1, IF_COMPRESSED_RGBA_S3TC_DXT5, IT_IMPLICIT_TYPE);
    00653       else
    00654       if (image_type == DDS_IMAGE_3D)
    00655         image[i]->allocate3D(w, h, d, 1, IF_COMPRESSED_RGBA_S3TC_DXT5, IT_IMPLICIT_TYPE);
    00656     }
    00657
    00658     for(int face=0; face<max_face; ++face)
    00659     {
    00660       for(int i=0, w = header.dwWidth, h = header.dwHeight, d = header.dwDepth; i<mipmaps; ++i, w/=2, h/=2, d/=2)
    00661       {
    00662         w = w == 0 ? 1 : w;
    00663         h = h == 0 ? 1 : h;
    00664         d = d == 0 ? 1 : d;
    00665
    00666         int req_mem = Image::requiredMemory( w, h, d, 1, IF_COMPRESSED_RGBA_S3TC_DXT5, IT_IMPLICIT_TYPE, false );
    00667         int offset = req_mem*face;
    00668         // fread(image[i]->pixels() + offset, 1, req_mem, fin);
    00669         file->read(image[i]->pixels() + offset, req_mem);
    00670       }
    00671     }
    00672   }
    00673   else
    00674   {
    00675     Log::error( Say("DDS: not supported format for '%s'.\n") << file->path() );
    00676     // fclose(fin);
    00677     file->close();
    00678     return NULL;
    00679   }
    00680
    00681   // fclose(fin);
    00682   file->close();
    00683
    00684   // We don't flip at all the DDS to be consistent since flipping
    00685   // vertically/horizontally compressed images is not possible.
    00686   // The textures must be already flipped using the OpenGL reference system.
    00687
    00688   #if 0
    00689     if (image_type == DDS_IMAGE_2D && !s3tc_compressed)
    00690     {
    00691       for (int i=0; i<(int)image.size(); ++i)
    00692         internal_FlipVertically(image[i]);
    00693     }
    00694     else
    00695     if (image_type == DDS_IMAGE_3D)
    00696     {
    00697       // should be flipped vertically and then
    00698       // invert their order along the z-axis
    00699       // ...
    00700     }
    00701     else
    00702     if (image_type == DDS_IMAGE_CUBEMAP)
    00703     {
    00704       // should be flipped in a more sofisticated way, sg like:
    00705       // X+- flip orizontally
    00706       // Y+- flip vertically
    00707       // Z+- exchange one with the other
    00708       // ...
    00709     }
    00710   #endif
    00711
    00712   VL_CHECK(image.size());
    00713   *img = *image[0];
    00714   image.erase(image.begin());
    00715   img->setMipmaps(image);
    00716
    00717   return img;
    00718 }
    00719 //-----------------------------------------------------------------------------
    00720 bool vl::isDDS(VirtualFile* file)
    00721 {
    00722   if (!file->open(OM_ReadOnly))
    00723     return false;
    00724
    00725   char signature[4];
    00726   file->read(signature, 4);
    00727   if (strncmp(signature, "DDS ", 4) != 0)
    00728   {
    00729     file->close();
    00730     return false;
    00731   }
    00732
    00733   DDSURFACEDESC2 header;
    00734   memset(&header, 0, sizeof(header));
    00735
    00736   // fread(&header, 1, sizeof(header), fin);
    00737
    00738   header.dwSize = file->readUInt32();
    00739   header.dwFlags = file->readUInt32();
    00740   header.dwHeight = file->readUInt32();
    00741   header.dwWidth = file->readUInt32();
    00742   header.dwPitchOrLinearSize = file->readUInt32();
    00743   header.dwDepth = file->readUInt32();
    00744   header.dwMipMapCount = file->readUInt32();
    00745   // fread(header.dwReserved1, 1, 11*sizeof(unsigned long), fin);
    00746   file->read(header.dwReserved1, 11*sizeof(unsigned long));
    00747   header.ddpfPixelFormat.dwSize = file->readUInt32();
    00748   header.ddpfPixelFormat.dwFlags = file->readUInt32();
    00749   header.ddpfPixelFormat.dwFourCC = file->readUInt32();
    00750   header.ddpfPixelFormat.dwRGBBitCount = file->readUInt32();
    00751   header.ddpfPixelFormat.dwRBitMask = file->readUInt32();
    00752   header.ddpfPixelFormat.dwGBitMask = file->readUInt32();
    00753   header.ddpfPixelFormat.dwBBitMask = file->readUInt32();
    00754   header.ddpfPixelFormat.dwAlphaBitMask = file->readUInt32();
    00755   header.ddsCaps.dwCaps1 = file->readUInt32();
    00756   header.ddsCaps.dwCaps2 = file->readUInt32();
    00757   header.ddsCaps.dwReserved[0] = file->readUInt32();
    00758   header.ddsCaps.dwReserved[1] = file->readUInt32();
    00759   header.dwReserved2 = file->readUInt32();
    00760
    00761   file->close();
    00762
    00763   if (header.dwSize != 124 || header.ddpfPixelFormat.dwSize != 32)
    00764     return false;
    00765
    00766   // warn only when actually loading
    00767 #if 0
    00768   if ((header.dwFlags & DDS_REQUIRED_FLAGS) != DDS_REQUIRED_FLAGS )
    00769     Log::warning( Say("DDS file '%s': missing DDS_REQUIRED_FLAGS flags.\n") << file->path() );
    00770
    00771   if ((header.ddsCaps.dwCaps1 & DDSCAPS_TEXTURE) != DDSCAPS_TEXTURE)
    00772     Log::warning( Say("DDS file '%s': missing DDSCAPS_TEXTURE flag.\n") << file->path() );
    00773 #endif
    00774
    00775   return true;
    00776 }
    00777 //-----------------------------------------------------------------------------

Visualization Library v2011.05.1142 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 26 2011 22:51:21.
Permission is granted to use this page to write and publish articles regarding Visualization Library.