00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
00041
00042
00043
00044
00045
00046 using namespace vl;
00047
00048 #include <vlCore/ImageTools.hpp>
00049
00050
00051
00052
00053 namespace
00054 {
00055
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
00080 const unsigned long DDPF_ALPHAPIXELS = 0x00000001;
00081 const unsigned long DDPF_ALPHA = 0x00000002;
00082 const unsigned long DDPF_FOURCC = 0x00000004;
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;
00087 const unsigned long DDPF_RGBA = 0x00000041;
00088 const unsigned long DDPF_COMPRESSED = 0x00000080;
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;
00098 const unsigned long DDPF_BUMPLUMINANCE = 0x00040000;
00099 const unsigned long DDPF_BUMPDUDV = 0x00080000;
00100
00101
00102 const unsigned long DDSCAPS_COMPLEX = 0x00000008;
00103 const unsigned long DDSCAPS_TEXTURE = 0x00001000;
00104 const unsigned long DDSCAPS_MIPMAP = 0x00400000;
00105
00106
00107 const unsigned long DDSCAPS2_VOLUME = 0x00200000;
00108 const unsigned long DDSCAPS2_CUBEMAP = 0x00000200;
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
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
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
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
00298
00299
00300
00301
00302 int mipmaps = (header.dwFlags & DDS_MIPMAPCOUNT) ? header.dwMipMapCount : 1;
00303 int hasalpha = header.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS;
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 int rgb = header.ddpfPixelFormat.dwFlags & DDPF_RGB;
00314
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
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
00630
00631
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
00643
00644
00645 }
00646 else
00647 if (image_type == DDS_IMAGE_CUBEMAP)
00648 {
00649
00650
00651
00652
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
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
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
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