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 "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
00046
00047 namespace
00048 {
00049
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
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
00095 const unsigned long DDSCAPS_COMPLEX = 0x00000008;
00096 const unsigned long DDSCAPS_TEXTURE = 0x00001000;
00097 const unsigned long DDSCAPS_MIPMAP = 0x00400000;
00098
00099
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
00114
00115
00116
00117
00118
00119
00120
00121
00122 bool isFOURCC(const char* code, unsigned long fcc)
00123 {
00124 return memcmp(code, &fcc, 4) == 0;
00125 }
00126
00127
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
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
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
00235
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
00254 file->read(signature,4);
00255 if (strncmp(signature, "DDS ", 4) != 0)
00256 {
00257
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
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
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
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
00306
00307
00308
00309
00310 int image_type = header.dwDepth ? DDS_IMAGE_3D : DDS_IMAGE_2D;
00311
00312 if (header.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
00313 {
00314
00315 bool allfaces = (header.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_FACES) != 0;
00316
00317 if (!allfaces)
00318 {
00319
00320 Log::error( Say("DDS: '%s' contains an invalid cubemap.\n") << file->path() );
00321
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
00334
00335
00336
00337
00338 int mipmaps = (header.dwFlags & DDS_MIPMAPCOUNT) ? header.dwMipMapCount : 1;
00339 int hasalpha = header.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS;
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 int rgb = header.ddpfPixelFormat.dwFlags & DDPF_RGB;
00350
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
00372
00373
00374
00375
00376
00377
00378
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
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
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
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
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
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
00560
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
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
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
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
00677 file->close();
00678 return NULL;
00679 }
00680
00681
00682 file->close();
00683
00684
00685
00686
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
00698
00699
00700 }
00701 else
00702 if (image_type == DDS_IMAGE_CUBEMAP)
00703 {
00704
00705
00706
00707
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
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
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
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