/src/FreeImage/Source/FreeImage/PluginDDS.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 651 lines · 489 code · 88 blank · 74 comment · 43 complexity · 115199d9243e618af5b1566826901c25 MD5 · raw file

  1. // ==========================================================
  2. // DDS Loader
  3. //
  4. // Design and implementation by
  5. // - Volker Gärtner (volkerg@gmx.at)
  6. // - Sherman Wilcox
  7. //
  8. // This file is part of FreeImage 3
  9. //
  10. // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
  11. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
  12. // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
  13. // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
  14. // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
  15. // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
  16. // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
  17. // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  18. // THIS DISCLAIMER.
  19. //
  20. // Use at your own risk!
  21. // ==========================================================
  22. #include "FreeImage.h"
  23. #include "Utilities.h"
  24. // ----------------------------------------------------------
  25. // Definitions for the DDS format
  26. // ----------------------------------------------------------
  27. #ifdef _WIN32
  28. #pragma pack(push, 1)
  29. #else
  30. #pragma pack(1)
  31. #endif
  32. typedef struct tagDDPIXELFORMAT {
  33. DWORD dwSize; // size of this structure (must be 32)
  34. DWORD dwFlags; // see DDPF_*
  35. DWORD dwFourCC;
  36. DWORD dwRGBBitCount; // Total number of bits for RGB formats
  37. DWORD dwRBitMask;
  38. DWORD dwGBitMask;
  39. DWORD dwBBitMask;
  40. DWORD dwRGBAlphaBitMask;
  41. } DDPIXELFORMAT;
  42. // DIRECTDRAW PIXELFORMAT FLAGS
  43. enum {
  44. DDPF_ALPHAPIXELS = 0x00000001l, // surface has alpha channel
  45. DDPF_ALPHA = 0x00000002l, // alpha only
  46. DDPF_FOURCC = 0x00000004l, // FOURCC available
  47. DDPF_RGB = 0x00000040l // RGB(A) bitmap
  48. };
  49. typedef struct tagDDCAPS2 {
  50. DWORD dwCaps1; // Zero or more of the DDSCAPS_* members
  51. DWORD dwCaps2; // Zero or more of the DDSCAPS2_* members
  52. DWORD dwReserved[2];
  53. } DDCAPS2;
  54. // DIRECTDRAWSURFACE CAPABILITY FLAGS
  55. enum {
  56. DDSCAPS_ALPHA = 0x00000002l, // alpha only surface
  57. DDSCAPS_COMPLEX = 0x00000008l, // complex surface structure
  58. DDSCAPS_TEXTURE = 0x00001000l, // used as texture (should always be set)
  59. DDSCAPS_MIPMAP = 0x00400000l // Mipmap present
  60. };
  61. enum {
  62. DDSCAPS2_CUBEMAP = 0x00000200L,
  63. DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400L,
  64. DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800L,
  65. DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000L,
  66. DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000L,
  67. DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000L,
  68. DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000L,
  69. DDSCAPS2_VOLUME = 0x00200000L
  70. };
  71. typedef struct tagDDSURFACEDESC2 {
  72. DWORD dwSize; // size of this structure (must be 124)
  73. DWORD dwFlags; // combination of the DDSS_* flags
  74. DWORD dwHeight;
  75. DWORD dwWidth;
  76. DWORD dwPitchOrLinearSize;
  77. DWORD dwDepth; // Depth of a volume texture
  78. DWORD dwMipMapCount;
  79. DWORD dwReserved1[11];
  80. DDPIXELFORMAT ddpfPixelFormat;
  81. DDCAPS2 ddsCaps;
  82. DWORD dwReserved2;
  83. } DDSURFACEDESC2;
  84. enum {
  85. DDSD_CAPS = 0x00000001l,
  86. DDSD_HEIGHT = 0x00000002l,
  87. DDSD_WITH = 0x00000004l,
  88. DDSD_PITCH = 0x00000008l,
  89. DDSD_ALPHABITDEPTH = 0x00000080l,
  90. DDSD_PIXELFORMAT = 0x00001000l,
  91. DDSD_MIPMAPCOUNT = 0x00020000l,
  92. DDSD_LINEARSIZE = 0x00080000l,
  93. DDSD_DEPTH = 0x00800000l
  94. };
  95. typedef struct tagDDSHEADER {
  96. DWORD dwMagic; // FOURCC: "DDS "
  97. DDSURFACEDESC2 surfaceDesc;
  98. } DDSHEADER;
  99. #define MAKEFOURCC(ch0, ch1, ch2, ch3) \
  100. ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
  101. ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
  102. #define FOURCC_DXT1 MAKEFOURCC('D','X','T','1')
  103. #define FOURCC_DXT2 MAKEFOURCC('D','X','T','2')
  104. #define FOURCC_DXT3 MAKEFOURCC('D','X','T','3')
  105. #define FOURCC_DXT4 MAKEFOURCC('D','X','T','4')
  106. #define FOURCC_DXT5 MAKEFOURCC('D','X','T','5')
  107. // ----------------------------------------------------------
  108. // Structures used by DXT textures
  109. // ----------------------------------------------------------
  110. typedef struct tagColor8888 {
  111. BYTE b;
  112. BYTE g;
  113. BYTE r;
  114. BYTE a;
  115. } Color8888;
  116. typedef struct tagColor565 {
  117. WORD b : 5;
  118. WORD g : 6;
  119. WORD r : 5;
  120. } Color565;
  121. typedef struct tagDXTColBlock {
  122. Color565 colors[2];
  123. BYTE row[4];
  124. } DXTColBlock;
  125. typedef struct tagDXTAlphaBlockExplicit {
  126. WORD row[4];
  127. } DXTAlphaBlockExplicit;
  128. typedef struct tagDXTAlphaBlock3BitLinear {
  129. BYTE alpha[2];
  130. BYTE data[6];
  131. } DXTAlphaBlock3BitLinear;
  132. typedef struct tagDXT1Block
  133. {
  134. DXTColBlock color;
  135. } DXT1Block;
  136. typedef struct tagDXT3Block { // also used by dxt2
  137. DXTAlphaBlockExplicit alpha;
  138. DXTColBlock color;
  139. } DXT3Block;
  140. typedef struct tagDXT5Block { // also used by dxt4
  141. DXTAlphaBlock3BitLinear alpha;
  142. DXTColBlock color;
  143. } DXT5Block;
  144. #ifdef _WIN32
  145. # pragma pack(pop)
  146. #else
  147. # pragma pack()
  148. #endif
  149. // ----------------------------------------------------------
  150. // Internal functions
  151. // ----------------------------------------------------------
  152. #ifdef FREEIMAGE_BIGENDIAN
  153. static void
  154. SwapHeader(DDSHEADER *header) {
  155. SwapLong(&header->dwMagic);
  156. SwapLong(&header->surfaceDesc.dwSize);
  157. SwapLong(&header->surfaceDesc.dwFlags);
  158. SwapLong(&header->surfaceDesc.dwHeight);
  159. SwapLong(&header->surfaceDesc.dwWidth);
  160. SwapLong(&header->surfaceDesc.dwPitchOrLinearSize);
  161. SwapLong(&header->surfaceDesc.dwDepth);
  162. SwapLong(&header->surfaceDesc.dwMipMapCount);
  163. for(int i=0; i<11; i++) {
  164. SwapLong(&header->surfaceDesc.dwReserved1[i]);
  165. }
  166. SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwSize);
  167. SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwFlags);
  168. SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwFourCC);
  169. SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwRGBBitCount);
  170. SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwRBitMask);
  171. SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwGBitMask);
  172. SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwBBitMask);
  173. SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwRGBAlphaBitMask);
  174. SwapLong(&header->surfaceDesc.ddsCaps.dwCaps1);
  175. SwapLong(&header->surfaceDesc.ddsCaps.dwCaps2);
  176. SwapLong(&header->surfaceDesc.ddsCaps.dwReserved[0]);
  177. SwapLong(&header->surfaceDesc.ddsCaps.dwReserved[1]);
  178. SwapLong(&header->surfaceDesc.dwReserved2);
  179. }
  180. #endif
  181. // ==========================================================
  182. // Get the 4 possible colors for a block
  183. //
  184. static void
  185. GetBlockColors (const DXTColBlock &block, Color8888 colors[4], bool isDXT1) {
  186. int i;
  187. // expand from 565 to 888
  188. for (i = 0; i < 2; i++) {
  189. colors[i].a = 0xff;
  190. /*
  191. colors[i].r = (BYTE)(block.colors[i].r * 0xff / 0x1f);
  192. colors[i].g = (BYTE)(block.colors[i].g * 0xff / 0x3f);
  193. colors[i].b = (BYTE)(block.colors[i].b * 0xff / 0x1f);
  194. */
  195. colors[i].r = (BYTE)((block.colors[i].r << 3U) | (block.colors[i].r >> 2U));
  196. colors[i].g = (BYTE)((block.colors[i].g << 2U) | (block.colors[i].g >> 4U));
  197. colors[i].b = (BYTE)((block.colors[i].b << 3U) | (block.colors[i].b >> 2U));
  198. }
  199. WORD *wCol = (WORD *)block.colors;
  200. if (wCol[0] > wCol[1] || !isDXT1) {
  201. // 4 color block
  202. for (i = 0; i < 2; i++) {
  203. colors[i + 2].a = 0xff;
  204. colors[i + 2].r = (BYTE)((WORD (colors[0].r) * (2 - i) + WORD (colors[1].r) * (1 + i)) / 3);
  205. colors[i + 2].g = (BYTE)((WORD (colors[0].g) * (2 - i) + WORD (colors[1].g) * (1 + i)) / 3);
  206. colors[i + 2].b = (BYTE)((WORD (colors[0].b) * (2 - i) + WORD (colors[1].b) * (1 + i)) / 3);
  207. }
  208. }
  209. else {
  210. // 3 color block, number 4 is transparent
  211. colors[2].a = 0xff;
  212. colors[2].r = (BYTE)((WORD (colors[0].r) + WORD (colors[1].r)) / 2);
  213. colors[2].g = (BYTE)((WORD (colors[0].g) + WORD (colors[1].g)) / 2);
  214. colors[2].b = (BYTE)((WORD (colors[0].b) + WORD (colors[1].b)) / 2);
  215. colors[3].a = 0x00;
  216. colors[3].g = 0x00;
  217. colors[3].b = 0x00;
  218. colors[3].r = 0x00;
  219. }
  220. }
  221. struct DXT_INFO_1 {
  222. typedef DXT1Block Block;
  223. enum {
  224. isDXT1 = 1,
  225. bytesPerBlock = 8
  226. };
  227. };
  228. struct DXT_INFO_3 {
  229. typedef DXT3Block Block;
  230. enum {
  231. isDXT1 = 1,
  232. bytesPerBlock = 16
  233. };
  234. };
  235. struct DXT_INFO_5 {
  236. typedef DXT5Block Block;
  237. enum
  238. {
  239. isDXT1 = 1,
  240. bytesPerBlock = 16
  241. };
  242. };
  243. template <class INFO> class DXT_BLOCKDECODER_BASE {
  244. protected:
  245. Color8888 m_colors[4];
  246. const typename INFO::Block *m_pBlock;
  247. unsigned m_colorRow;
  248. public:
  249. void Setup (const BYTE *pBlock) {
  250. m_pBlock = (const typename INFO::Block *)pBlock;
  251. GetBlockColors (m_pBlock->color, m_colors, INFO::isDXT1);
  252. }
  253. void SetY (int y) {
  254. m_colorRow = m_pBlock->color.row[y];
  255. }
  256. void GetColor (int x, int y, Color8888 &color) {
  257. unsigned bits = (m_colorRow >> (x * 2)) & 3;
  258. color = m_colors[bits];
  259. }
  260. };
  261. class DXT_BLOCKDECODER_1 : public DXT_BLOCKDECODER_BASE <DXT_INFO_1> {
  262. public:
  263. typedef DXT_INFO_1 INFO;
  264. };
  265. class DXT_BLOCKDECODER_3 : public DXT_BLOCKDECODER_BASE <DXT_INFO_3> {
  266. public:
  267. typedef DXT_BLOCKDECODER_BASE <DXT_INFO_3> base;
  268. typedef DXT_INFO_3 INFO;
  269. protected:
  270. unsigned m_alphaRow;
  271. public:
  272. void SetY (int y) {
  273. base::SetY (y);
  274. m_alphaRow = m_pBlock->alpha.row[y];
  275. }
  276. void GetColor (int x, int y, Color8888 &color) {
  277. base::GetColor (x, y, color);
  278. const unsigned bits = (m_alphaRow >> (x * 4)) & 0xF;
  279. color.a = (BYTE)((bits * 0xFF) / 0xF);
  280. }
  281. };
  282. class DXT_BLOCKDECODER_5 : public DXT_BLOCKDECODER_BASE <DXT_INFO_5> {
  283. public:
  284. typedef DXT_BLOCKDECODER_BASE <DXT_INFO_5> base;
  285. typedef DXT_INFO_5 INFO;
  286. protected:
  287. unsigned m_alphas[8];
  288. unsigned m_alphaBits;
  289. int m_offset;
  290. public:
  291. void Setup (const BYTE *pBlock) {
  292. base::Setup (pBlock);
  293. const DXTAlphaBlock3BitLinear &block = m_pBlock->alpha;
  294. m_alphas[0] = block.alpha[0];
  295. m_alphas[1] = block.alpha[1];
  296. if (m_alphas[0] > m_alphas[1]) {
  297. // 8 alpha block
  298. for (int i = 0; i < 6; i++) {
  299. m_alphas[i + 2] = ((6 - i) * m_alphas[0] + (1 + i) * m_alphas[1] + 3) / 7;
  300. }
  301. }
  302. else {
  303. // 6 alpha block
  304. for (int i = 0; i < 4; i++) {
  305. m_alphas[i + 2] = ((4 - i) * m_alphas[0] + (1 + i) * m_alphas[1] + 2) / 5;
  306. }
  307. m_alphas[6] = 0;
  308. m_alphas[7] = 0xFF;
  309. }
  310. }
  311. void SetY (int y) {
  312. base::SetY (y);
  313. int i = y / 2;
  314. const DXTAlphaBlock3BitLinear &block = m_pBlock->alpha;
  315. m_alphaBits = unsigned(block.data[0 + i * 3]) | (unsigned(block.data[1 + i * 3]) << 8)
  316. | (unsigned(block.data[2 + i * 3]) << 16);
  317. m_offset = (y & 1) * 12;
  318. }
  319. void GetColor (int x, int y, Color8888 &color) {
  320. base::GetColor (x, y, color);
  321. unsigned bits = (m_alphaBits >> (x * 3 + m_offset)) & 7;
  322. color.a = (BYTE)m_alphas[bits];
  323. }
  324. };
  325. template <class DECODER> void DecodeDXTBlock (BYTE *dstData, const BYTE *srcBlock, long dstPitch, int bw, int bh) {
  326. DECODER decoder;
  327. decoder.Setup (srcBlock);
  328. for (int y = 0; y < bh; y++) {
  329. BYTE *dst = dstData - y * dstPitch;
  330. decoder.SetY (y);
  331. for (int x = 0; x < bw; x++) {
  332. decoder.GetColor (x, y, (Color8888 &)*dst);
  333. dst += 4;
  334. }
  335. }
  336. }
  337. // ==========================================================
  338. // Plugin Interface
  339. // ==========================================================
  340. static int s_format_id;
  341. // ==========================================================
  342. // Internal functions
  343. // ==========================================================
  344. static FIBITMAP *
  345. LoadRGB (DDSURFACEDESC2 &desc, FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
  346. int width = (int)desc.dwWidth & ~3;
  347. int height = (int)desc.dwHeight & ~3;
  348. int bpp = (int)desc.ddpfPixelFormat.dwRGBBitCount;
  349. // allocate a new dib
  350. FIBITMAP *dib = FreeImage_Allocate (width, height, bpp, desc.ddpfPixelFormat.dwRBitMask,
  351. desc.ddpfPixelFormat.dwGBitMask, desc.ddpfPixelFormat.dwBBitMask);
  352. if (dib == NULL)
  353. return NULL;
  354. #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
  355. // Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
  356. int bytespp = FreeImage_GetLine(dib) / FreeImage_GetWidth(dib);
  357. #endif
  358. // read the file
  359. int line = CalculateLine(width, bpp);
  360. int filePitch = (desc.dwFlags & DDSD_PITCH) ? (int)desc.dwPitchOrLinearSize : line;
  361. long delta = (long)filePitch - (long)line;
  362. for (int i = 0; i < height; i++) {
  363. BYTE *pixels = FreeImage_GetScanLine(dib, height - i - 1);
  364. io->read_proc (pixels, 1, line, handle);
  365. io->seek_proc (handle, delta, SEEK_CUR);
  366. #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
  367. for(int x = 0; x < width; x++) {
  368. INPLACESWAP(pixels[FI_RGBA_RED],pixels[FI_RGBA_BLUE]);
  369. pixels += bytespp;
  370. }
  371. #endif
  372. }
  373. // enable transparency
  374. FreeImage_SetTransparent (dib, (desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) ? TRUE : FALSE);
  375. if (!(desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) && bpp == 32) {
  376. // no transparency: convert to 24-bit
  377. FIBITMAP *old = dib;
  378. dib = FreeImage_ConvertTo24Bits (old);
  379. FreeImage_Unload (old);
  380. }
  381. return dib;
  382. }
  383. template <class DECODER> static void
  384. LoadDXT_Helper (FreeImageIO *io, fi_handle handle, int page, int flags, void *data, FIBITMAP *dib, int width, int height, int line) {
  385. typedef typename DECODER::INFO INFO;
  386. typedef typename INFO::Block Block;
  387. Block *input_buffer = new(std::nothrow) Block[(width + 3) / 4];
  388. if(!input_buffer) return;
  389. int widthRest = (int) width & 3;
  390. int heightRest = (int) height & 3;
  391. int inputLine = (width + 3) / 4;
  392. int y = 0;
  393. if (height >= 4) {
  394. for (; y < height; y += 4) {
  395. io->read_proc (input_buffer, sizeof (typename INFO::Block), inputLine, handle);
  396. // TODO: probably need some endian work here
  397. BYTE *pbSrc = (BYTE *)input_buffer;
  398. BYTE *pbDst = FreeImage_GetScanLine (dib, height - y - 1);
  399. if (width >= 4) {
  400. for (int x = 0; x < width; x += 4) {
  401. DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, 4, 4);
  402. pbSrc += INFO::bytesPerBlock;
  403. pbDst += 4 * 4;
  404. }
  405. }
  406. if (widthRest) {
  407. DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, widthRest, 4);
  408. }
  409. }
  410. }
  411. if (heightRest) {
  412. io->read_proc (input_buffer, sizeof (typename INFO::Block), inputLine, handle);
  413. // TODO: probably need some endian work here
  414. BYTE *pbSrc = (BYTE *)input_buffer;
  415. BYTE *pbDst = FreeImage_GetScanLine (dib, height - y - 1);
  416. if (width >= 4) {
  417. for (int x = 0; x < width; x += 4) {
  418. DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, 4, heightRest);
  419. pbSrc += INFO::bytesPerBlock;
  420. pbDst += 4 * 4;
  421. }
  422. }
  423. if (widthRest) {
  424. DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, widthRest, heightRest);
  425. }
  426. }
  427. delete [] input_buffer;
  428. }
  429. static FIBITMAP *
  430. LoadDXT (int type, DDSURFACEDESC2 &desc, FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
  431. int width = (int)desc.dwWidth & ~3;
  432. int height = (int)desc.dwHeight & ~3;
  433. // allocate a 32-bit dib
  434. FIBITMAP *dib = FreeImage_Allocate (width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
  435. if (dib == NULL)
  436. return NULL;
  437. int bpp = FreeImage_GetBPP (dib);
  438. int line = CalculateLine (width, bpp);
  439. BYTE *bits = FreeImage_GetBits (dib);
  440. // select the right decoder
  441. switch (type) {
  442. case 1:
  443. LoadDXT_Helper <DXT_BLOCKDECODER_1> (io, handle, page, flags, data, dib, width, height, line);
  444. break;
  445. case 3:
  446. LoadDXT_Helper <DXT_BLOCKDECODER_3> (io, handle, page, flags, data, dib, width, height, line);
  447. break;
  448. case 5:
  449. LoadDXT_Helper <DXT_BLOCKDECODER_5> (io, handle, page, flags, data, dib, width, height, line);
  450. break;
  451. }
  452. return dib;
  453. }
  454. // ==========================================================
  455. // Plugin Implementation
  456. // ==========================================================
  457. static const char * DLL_CALLCONV
  458. Format() {
  459. return "DDS";
  460. }
  461. static const char * DLL_CALLCONV
  462. Description() {
  463. return "DirectX Surface";
  464. }
  465. static const char * DLL_CALLCONV
  466. Extension() {
  467. return "dds";
  468. }
  469. static const char * DLL_CALLCONV
  470. RegExpr() {
  471. return NULL;
  472. }
  473. static const char * DLL_CALLCONV
  474. MimeType() {
  475. return "image/x-dds";
  476. }
  477. static BOOL DLL_CALLCONV
  478. Validate(FreeImageIO *io, fi_handle handle) {
  479. DDSHEADER header;
  480. memset(&header, 0, sizeof(header));
  481. io->read_proc(&header, 1, sizeof(header), handle);
  482. #ifdef FREEIMAGE_BIGENDIAN
  483. SwapHeader(&header);
  484. #endif
  485. if (header.dwMagic != MAKEFOURCC ('D','D','S',' '))
  486. return FALSE;
  487. if (header.surfaceDesc.dwSize != sizeof (header.surfaceDesc) ||
  488. header.surfaceDesc.ddpfPixelFormat.dwSize != sizeof (header.surfaceDesc.ddpfPixelFormat))
  489. return FALSE;
  490. return TRUE;
  491. }
  492. static BOOL DLL_CALLCONV
  493. SupportsExportDepth(int depth) {
  494. return FALSE;
  495. }
  496. static BOOL DLL_CALLCONV
  497. SupportsExportType(FREE_IMAGE_TYPE type) {
  498. return FALSE;
  499. }
  500. // ----------------------------------------------------------
  501. static void * DLL_CALLCONV
  502. Open(FreeImageIO *io, fi_handle handle, BOOL read) {
  503. return NULL;
  504. }
  505. static void DLL_CALLCONV
  506. Close(FreeImageIO *io, fi_handle handle, void *data) {
  507. }
  508. // ----------------------------------------------------------
  509. static FIBITMAP * DLL_CALLCONV
  510. Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
  511. DDSHEADER header;
  512. FIBITMAP *dib = NULL;
  513. memset(&header, 0, sizeof(header));
  514. io->read_proc(&header, 1, sizeof(header), handle);
  515. #ifdef FREEIMAGE_BIGENDIAN
  516. SwapHeader(&header);
  517. #endif
  518. if (header.surfaceDesc.ddpfPixelFormat.dwFlags & DDPF_RGB) {
  519. dib = LoadRGB (header.surfaceDesc, io, handle, page, flags, data);
  520. }
  521. else if (header.surfaceDesc.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
  522. switch (header.surfaceDesc.ddpfPixelFormat.dwFourCC) {
  523. case FOURCC_DXT1:
  524. dib = LoadDXT (1, header.surfaceDesc, io, handle, page, flags, data);
  525. break;
  526. case FOURCC_DXT3:
  527. dib = LoadDXT (3, header.surfaceDesc, io, handle, page, flags, data);
  528. break;
  529. case FOURCC_DXT5:
  530. dib = LoadDXT (5, header.surfaceDesc, io, handle, page, flags, data);
  531. break;
  532. }
  533. }
  534. return dib;
  535. }
  536. /*
  537. static BOOL DLL_CALLCONV
  538. Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
  539. return FALSE;
  540. }
  541. */
  542. // ==========================================================
  543. // Init
  544. // ==========================================================
  545. void DLL_CALLCONV
  546. InitDDS(Plugin *plugin, int format_id) {
  547. s_format_id = format_id;
  548. plugin->format_proc = Format;
  549. plugin->description_proc = Description;
  550. plugin->extension_proc = Extension;
  551. plugin->regexpr_proc = RegExpr;
  552. plugin->open_proc = Open;
  553. plugin->close_proc = Close;
  554. plugin->pagecount_proc = NULL;
  555. plugin->pagecapability_proc = NULL;
  556. plugin->load_proc = Load;
  557. plugin->save_proc = NULL; //Save; // not implemented (yet?)
  558. plugin->validate_proc = Validate;
  559. plugin->mime_proc = MimeType;
  560. plugin->supports_export_bpp_proc = SupportsExportDepth;
  561. plugin->supports_export_type_proc = SupportsExportType;
  562. plugin->supports_icc_profiles_proc = NULL;
  563. }