Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://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 //-----------------------------------------------------------------------------