PageRenderTime 84ms CodeModel.GetById 15ms app.highlight 64ms RepoModel.GetById 1ms app.codeStats 0ms

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