dds/
lib.rs

1use std::error::Error as StdError;
2use std::fs::File;
3use std::io::{Read,Write};
4use std::mem;
5use std::cmp::max;
6use std::path::Path;
7use std::fmt::{self, Display, Formatter};
8use std::io::BufReader;
9use std::borrow::{Borrow, Cow};
10
11use bitflags::bitflags;
12
13macro_rules! from_c_str{
14	($c_string: expr) => (
15        {
16            use std::ffi::CStr;
17            use std::str;
18	        str::from_utf8(CStr::from_ptr($c_string).to_bytes()).unwrap()
19        }
20	);
21}
22
23bitflags! {
24	#[derive(Debug,Clone,Copy)]
25	struct Caps: u32{
26		const COMPLEX = 0x8;
27		const MIPMAP = 0x400000;
28		const TEXTURE = 0x1000;
29	}
30}
31
32bitflags! {
33	#[derive(Debug,Clone,Copy)]
34	struct Caps2: u32 {
35		const CUBEMAP = 0x200;
36		const CUBEMAP_POS_X = 0x400;
37		const CUBEMAP_NEG_X = 0x800;
38		const CUBEMAP_POS_Y = 0x1000;
39		const CUBEMAP_NEG_Y = 0x2000;
40		const CUBEMAP_POS_Z = 0x4000;
41		const CUBEMAP_NEG_Z = 0x8000;
42		const VOLUME = 0x200000;
43	}
44}
45
46bitflags! {
47	#[derive(Debug,Clone,Copy)]
48	struct PixelFormatFlags: u32 {
49		const ALPHA_PIXELS = 0x1;
50		const ALPHA = 0x2;
51		const FOUR_CC = 0x4;
52		const RGB = 0x40;
53		const YUV = 0x200;
54		const LUMINANCE = 0x20000;
55		const BUMP_DU_DV = 0x00080000;
56	}
57}
58
59#[derive(Debug,Clone)]
60#[repr(C)]
61struct PixelFormat{
62	size: u32,
63	flags: PixelFormatFlags,
64	fourcc: u32,
65	bitcount: u32,
66	r_bitmask: u32,
67	g_bitmask: u32,
68	b_bitmask: u32,
69	a_bitmask: u32,
70}
71
72bitflags! {
73	#[derive(Debug,Clone,Copy)]
74	struct Flags: u32 {
75		const CAPS = 0x1;
76		const HEIGHT = 0x2;
77		const WIDTH = 0x4;
78		const PITCH = 0x8;
79		const PIXEL_FORMAT = 0x1000;
80		const MIPMAP_COUNT = 0x20000;
81		const LINEAR_SIZE = 0x80000;
82		const DEPTH = 0x800000;
83	}
84}
85
86pub enum Format{
87	Gray,
88	RG,
89	RGB,
90	RGBA,
91}
92
93pub enum Type{
94	UnsignedByte,
95	Float16,
96	Float32,
97}
98
99#[derive(Debug,Clone)]
100#[repr(C)]
101struct Header{
102	header_size: u32,
103	flags: Flags,
104	height: u32,
105	width: u32,
106	linear_size_or_pitch: u32,
107	depth: u32,
108	mipmapcount: u32,
109	reserved: [u32;11],
110	pixel_format: PixelFormat,
111	caps: Caps,
112	caps2: Caps2,
113	caps3: u32,
114	caps4: u32,
115	reserved2: u32,
116}
117
118#[derive(Debug,Clone,Copy,PartialEq)]
119#[allow(non_camel_case_types)]
120#[repr(u32)]
121pub enum DXGIFormat {
122  UNKNOWN                     = 0,
123  R32G32B32A32_TYPELESS       = 1,
124  R32G32B32A32_FLOAT          = 2,
125  R32G32B32A32_UINT           = 3,
126  R32G32B32A32_SINT           = 4,
127  R32G32B32_TYPELESS          = 5,
128  R32G32B32_FLOAT             = 6,
129  R32G32B32_UINT              = 7,
130  R32G32B32_SINT              = 8,
131  R16G16B16A16_TYPELESS       = 9,
132  R16G16B16A16_FLOAT          = 10,
133  R16G16B16A16_UNORM          = 11,
134  R16G16B16A16_UINT           = 12,
135  R16G16B16A16_SNORM          = 13,
136  R16G16B16A16_SINT           = 14,
137  R32G32_TYPELESS             = 15,
138  R32G32_FLOAT                = 16,
139  R32G32_UINT                 = 17,
140  R32G32_SINT                 = 18,
141  R32G8X24_TYPELESS           = 19,
142  D32_FLOAT_S8X24_UINT        = 20,
143  R32_FLOAT_X8X24_TYPELESS    = 21,
144  X32_TYPELESS_G8X24_UINT     = 22,
145  R10G10B10A2_TYPELESS        = 23,
146  R10G10B10A2_UNORM           = 24,
147  R10G10B10A2_UINT            = 25,
148  R11G11B10_FLOAT             = 26,
149  R8G8B8A8_TYPELESS           = 27,
150  R8G8B8A8_UNORM              = 28,
151  R8G8B8A8_UNORM_SRGB         = 29,
152  R8G8B8A8_UINT               = 30,
153  R8G8B8A8_SNORM              = 31,
154  R8G8B8A8_SINT               = 32,
155  R16G16_TYPELESS             = 33,
156  R16G16_FLOAT                = 34,
157  R16G16_UNORM                = 35,
158  R16G16_UINT                 = 36,
159  R16G16_SNORM                = 37,
160  R16G16_SINT                 = 38,
161  R32_TYPELESS                = 39,
162  D32_FLOAT                   = 40,
163  R32_FLOAT                   = 41,
164  R32_UINT                    = 42,
165  R32_SINT                    = 43,
166  R24G8_TYPELESS              = 44,
167  D24_UNORM_S8_UINT           = 45,
168  R24_UNORM_X8_TYPELESS       = 46,
169  X24_TYPELESS_G8_UINT        = 47,
170  R8G8_TYPELESS               = 48,
171  R8G8_UNORM                  = 49,
172  R8G8_UINT                   = 50,
173  R8G8_SNORM                  = 51,
174  R8G8_SINT                   = 52,
175  R16_TYPELESS                = 53,
176  R16_FLOAT                   = 54,
177  D16_UNORM                   = 55,
178  R16_UNORM                   = 56,
179  R16_UINT                    = 57,
180  R16_SNORM                   = 58,
181  R16_SINT                    = 59,
182  R8_TYPELESS                 = 60,
183  R8_UNORM                    = 61,
184  R8_UINT                     = 62,
185  R8_SNORM                    = 63,
186  R8_SINT                     = 64,
187  A8_UNORM                    = 65,
188  R1_UNORM                    = 66,
189  R9G9B9E5_SHAREDEXP          = 67,
190  R8G8_B8G8_UNORM             = 68,
191  G8R8_G8B8_UNORM             = 69,
192  BC1_TYPELESS                = 70,
193  BC1_UNORM                   = 71,
194  BC1_UNORM_SRGB              = 72,
195  BC2_TYPELESS                = 73,
196  BC2_UNORM                   = 74,
197  BC2_UNORM_SRGB              = 75,
198  BC3_TYPELESS                = 76,
199  BC3_UNORM                   = 77,
200  BC3_UNORM_SRGB              = 78,
201  BC4_TYPELESS                = 79,
202  BC4_UNORM                   = 80,
203  BC4_SNORM                   = 81,
204  BC5_TYPELESS                = 82,
205  BC5_UNORM                   = 83,
206  BC5_SNORM                   = 84,
207  B5G6R5_UNORM                = 85,
208  B5G5R5A1_UNORM              = 86,
209  B8G8R8A8_UNORM              = 87,
210  B8G8R8X8_UNORM              = 88,
211  R10G10B10_XR_BIAS_A2_UNORM  = 89,
212  B8G8R8A8_TYPELESS           = 90,
213  B8G8R8A8_UNORM_SRGB         = 91,
214  B8G8R8X8_TYPELESS           = 92,
215  B8G8R8X8_UNORM_SRGB         = 93,
216  BC6H_TYPELESS               = 94,
217  BC6H_UF16                   = 95,
218  BC6H_SF16                   = 96,
219  BC7_TYPELESS                = 97,
220  BC7_UNORM                   = 98,
221  BC7_UNORM_SRGB              = 99,
222  AYUV                        = 100,
223  Y410                        = 101,
224  Y416                        = 102,
225  NV12                        = 103,
226  P010                        = 104,
227  P016                        = 105,
228  I420_OPAQUE                 = 106,
229  YUY2                        = 107,
230  Y210                        = 108,
231  Y216                        = 109,
232  NV11                        = 110,
233  AI44                        = 111,
234  IA44                        = 112,
235  P8                          = 113,
236  A8P8                        = 114,
237  B4G4R4A4_UNORM              = 115,
238  P208                        = 130,
239  V208                        = 131,
240  V408                        = 132,
241  FORCE_UINT                  = 0xffffffff
242}
243
244impl DXGIFormat{
245	pub fn bpp(self) -> Option<usize> {
246		use DXGIFormat::*;
247		match self {
248			UNKNOWN                     => None,
249			R32G32B32A32_TYPELESS       => Some(128),
250			R32G32B32A32_FLOAT          => Some(128),
251			R32G32B32A32_UINT           => Some(128),
252			R32G32B32A32_SINT           => Some(128),
253			R32G32B32_TYPELESS          => Some(32*3),
254			R32G32B32_FLOAT             => Some(32*3),
255			R32G32B32_UINT              => Some(32*3),
256			R32G32B32_SINT              => Some(32*3),
257			R16G16B16A16_TYPELESS       => Some(64),
258			R16G16B16A16_FLOAT          => Some(64),
259			R16G16B16A16_UNORM          => Some(64),
260			R16G16B16A16_UINT           => Some(64),
261			R16G16B16A16_SNORM          => Some(64),
262			R16G16B16A16_SINT           => Some(64),
263			R32G32_TYPELESS             => Some(64),
264			R32G32_FLOAT                => Some(64),
265			R32G32_UINT                 => Some(64),
266			R32G32_SINT                 => Some(64),
267			R32G8X24_TYPELESS           => Some(64),
268			D32_FLOAT_S8X24_UINT        => Some(64),
269			R32_FLOAT_X8X24_TYPELESS    => Some(64),
270			X32_TYPELESS_G8X24_UINT     => Some(64),
271			R10G10B10A2_TYPELESS        => Some(64),
272			R10G10B10A2_UNORM           => Some(64),
273			R10G10B10A2_UINT            => Some(64),
274			R11G11B10_FLOAT             => Some(32),
275			R8G8B8A8_TYPELESS           => Some(32),
276			R8G8B8A8_UNORM              => Some(32),
277			R8G8B8A8_UNORM_SRGB         => Some(32),
278			R8G8B8A8_UINT               => Some(32),
279			R8G8B8A8_SNORM              => Some(32),
280			R8G8B8A8_SINT               => Some(32),
281			R16G16_TYPELESS             => Some(32),
282			R16G16_FLOAT                => Some(32),
283			R16G16_UNORM                => Some(32),
284			R16G16_UINT                 => Some(32),
285			R16G16_SNORM                => Some(32),
286			R16G16_SINT                 => Some(32),
287			R32_TYPELESS                => Some(32),
288			D32_FLOAT                   => Some(32),
289			R32_FLOAT                   => Some(32),
290			R32_UINT                    => Some(32),
291			R32_SINT                    => Some(32),
292			R24G8_TYPELESS              => Some(32),
293			D24_UNORM_S8_UINT           => Some(32),
294			R24_UNORM_X8_TYPELESS       => Some(32),
295			X24_TYPELESS_G8_UINT        => Some(32),
296			R8G8_TYPELESS               => Some(16),
297			R8G8_UNORM                  => Some(16),
298			R8G8_UINT                   => Some(16),
299			R8G8_SNORM                  => Some(16),
300			R8G8_SINT                   => Some(16),
301			R16_TYPELESS                => Some(16),
302			R16_FLOAT                   => Some(16),
303			D16_UNORM                   => Some(16),
304			R16_UNORM                   => Some(16),
305			R16_UINT                    => Some(16),
306			R16_SNORM                   => Some(16),
307			R16_SINT                    => Some(16),
308			R8_TYPELESS                 => Some(8),
309			R8_UNORM                    => Some(8),
310			R8_UINT                     => Some(8),
311			R8_SNORM                    => Some(8),
312			R8_SINT                     => Some(8),
313			A8_UNORM                    => Some(8),
314			R1_UNORM                    => Some(8),
315			R9G9B9E5_SHAREDEXP          => Some(32),
316			R8G8_B8G8_UNORM             => Some(32),
317			G8R8_G8B8_UNORM             => Some(32),
318			BC1_TYPELESS                => None,
319			BC1_UNORM                   => None,
320			BC1_UNORM_SRGB              => None,
321			BC2_TYPELESS                => None,
322			BC2_UNORM                   => None,
323			BC2_UNORM_SRGB              => None,
324			BC3_TYPELESS                => None,
325			BC3_UNORM                   => None,
326			BC3_UNORM_SRGB              => None,
327			BC4_TYPELESS                => None,
328			BC4_UNORM                   => None,
329			BC4_SNORM                   => None,
330			BC5_TYPELESS                => None,
331			BC5_UNORM                   => None,
332			BC5_SNORM                   => None,
333			B5G6R5_UNORM                => Some(16),
334			B5G5R5A1_UNORM              => Some(16),
335			B8G8R8A8_UNORM              => Some(32),
336			B8G8R8X8_UNORM              => Some(32),
337			R10G10B10_XR_BIAS_A2_UNORM  => Some(32),
338			B8G8R8A8_TYPELESS           => Some(32),
339			B8G8R8A8_UNORM_SRGB         => Some(32),
340			B8G8R8X8_TYPELESS           => Some(32),
341			B8G8R8X8_UNORM_SRGB         => Some(32),
342			BC6H_TYPELESS               => None,
343			BC6H_UF16                   => None,
344			BC6H_SF16                   => None,
345			BC7_TYPELESS                => None,
346			BC7_UNORM                   => None,
347			BC7_UNORM_SRGB              => None,
348			AYUV                        => unimplemented!(),
349			Y410                        => unimplemented!(),
350			Y416                        => unimplemented!(),
351			NV12                        => unimplemented!(),
352			P010                        => unimplemented!(),
353			P016                        => unimplemented!(),
354			I420_OPAQUE                 => unimplemented!(),
355			YUY2                        => unimplemented!(),
356			Y210                        => unimplemented!(),
357			Y216                        => unimplemented!(),
358			NV11                        => unimplemented!(),
359			AI44                        => unimplemented!(),
360			IA44                        => unimplemented!(),
361			P8                          => Some(8),
362			A8P8                        => Some(16),
363			B4G4R4A4_UNORM              => Some(16),
364			P208                        => unimplemented!(),
365			V208                        => unimplemented!(),
366			V408                        => unimplemented!(),
367  			FORCE_UINT                  => None,
368		}
369	}
370}
371
372
373#[derive(Debug,Clone,Copy,PartialEq)]
374#[allow(non_camel_case_types)]
375#[repr(u32)]
376pub enum _D3DFORMAT {
377    D3DFMT_UNKNOWN              = 0,
378
379    D3DFMT_R8G8B8               = 20,
380    D3DFMT_A8R8G8B8             = 21,
381    D3DFMT_X8R8G8B8             = 22,
382    D3DFMT_R5G6B5               = 23,
383    D3DFMT_X1R5G5B5             = 24,
384    D3DFMT_A1R5G5B5             = 25,
385    D3DFMT_A4R4G4B4             = 26,
386    D3DFMT_R3G3B2               = 27,
387    D3DFMT_A8                   = 28,
388    D3DFMT_A8R3G3B2             = 29,
389    D3DFMT_X4R4G4B4             = 30,
390    D3DFMT_A2B10G10R10          = 31,
391    D3DFMT_A8B8G8R8             = 32,
392    D3DFMT_X8B8G8R8             = 33,
393    D3DFMT_G16R16               = 34,
394    D3DFMT_A2R10G10B10          = 35,
395    D3DFMT_A16B16G16R16         = 36,
396
397    D3DFMT_A8P8                 = 40,
398    D3DFMT_P8                   = 41,
399
400    D3DFMT_L8                   = 50,
401    D3DFMT_A8L8                 = 51,
402    D3DFMT_A4L4                 = 52,
403
404    D3DFMT_V8U8                 = 60,
405    D3DFMT_L6V5U5               = 61,
406    D3DFMT_X8L8V8U8             = 62,
407    D3DFMT_Q8W8V8U8             = 63,
408    D3DFMT_V16U16               = 64,
409    D3DFMT_A2W10V10U10          = 67,
410
411    D3DFMT_UYVY                 = fourcc_from_bytes('U', 'Y', 'V', 'Y'),
412    D3DFMT_R8G8_B8G8            = fourcc_from_bytes('R', 'G', 'B', 'G'),
413    D3DFMT_YUY2                 = fourcc_from_bytes('Y', 'U', 'Y', '2'),
414    D3DFMT_G8R8_G8B8            = fourcc_from_bytes('G', 'R', 'G', 'B'),
415    D3DFMT_DXT1                 = fourcc_from_bytes('D', 'X', 'T', '1'),
416    D3DFMT_DXT2                 = fourcc_from_bytes('D', 'X', 'T', '2'),
417    D3DFMT_DXT3                 = fourcc_from_bytes('D', 'X', 'T', '3'),
418    D3DFMT_DXT4                 = fourcc_from_bytes('D', 'X', 'T', '4'),
419    D3DFMT_DXT5                 = fourcc_from_bytes('D', 'X', 'T', '5'),
420
421    D3DFMT_D16_LOCKABLE         = 70,
422    D3DFMT_D32                  = 71,
423    D3DFMT_D15S1                = 73,
424    D3DFMT_D24S8                = 75,
425    D3DFMT_D24X8                = 77,
426    D3DFMT_D24X4S4              = 79,
427    D3DFMT_D16                  = 80,
428
429    D3DFMT_D32F_LOCKABLE        = 82,
430    D3DFMT_D24FS8               = 83,
431
432    D3DFMT_D32_LOCKABLE         = 84,
433    D3DFMT_S8_LOCKABLE          = 85,
434
435    D3DFMT_L16                  = 81,
436
437    D3DFMT_VERTEXDATA           = 100,
438    D3DFMT_INDEX16              = 101,
439    D3DFMT_INDEX32              = 102,
440
441    D3DFMT_Q16W16V16U16         = 110,
442
443    D3DFMT_MULTI2_ARGB8         = fourcc_from_bytes('M','E','T','1'),
444
445    D3DFMT_R16F                 = 111,
446    D3DFMT_G16R16F              = 112,
447    D3DFMT_A16B16G16R16F        = 113,
448
449    D3DFMT_R32F                 = 114,
450    D3DFMT_G32R32F              = 115,
451    D3DFMT_A32B32G32R32F        = 116,
452
453    D3DFMT_CxV8U8               = 117,
454
455    D3DFMT_A1                   = 118,
456    D3DFMT_A2B10G10R10_XR_BIAS  = 119,
457    D3DFMT_BINARYBUFFER         = 199,
458
459    D3DFMT_FORCE_DWORD          = 0x7fffffff
460}
461
462#[derive(Debug,Clone)]
463#[allow(dead_code)]
464enum D3D10ResourceDimension {
465  UNKNOWN    = 0,
466  BUFFER     = 1,
467  TEXTURE1D  = 2,
468  TEXTURE2D  = 3,
469  TEXTURE3D  = 4
470}
471
472#[derive(Debug,Clone)]
473#[repr(C)]
474struct HeaderDXT10{
475	dxgi_format: DXGIFormat,
476	resource_dimension: u32,
477	misc_flag: u32,
478	array_size: u32,
479	misc_flags2: u32,
480}
481
482#[derive(Clone,Debug)]
483pub struct Error(String);
484
485impl StdError for Error{
486}
487
488impl Display for Error{
489	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result{
490		self.0.fmt(fmt)
491	}
492}
493
494impl From<String> for Error{
495	fn from(s: String) -> Error{
496		Error(s)
497	}
498}
499
500pub struct Builder{
501	header: Header,
502	header_dxt10: Option<HeaderDXT10>,
503}
504
505impl Builder{
506	pub fn new(w: usize, h: usize, format: Format, ty: Type) -> Builder{
507		let bpc = match ty{
508			Type::UnsignedByte => 8,
509			Type::Float16 => 16,
510			Type::Float32 => 32,
511		};
512		let channels = match format {
513			Format::Gray => 1,
514			Format::RG => 2,
515			Format::RGB => 3,
516			Format::RGBA => 4,
517		};
518		let bpp = channels * bpc;
519		let pitch = (w * bpp + 7) / 8;
520		let pixel_flags = match format {
521			Format::Gray => PixelFormatFlags::LUMINANCE | PixelFormatFlags::FOUR_CC,
522			Format::RG => PixelFormatFlags::FOUR_CC,
523			Format::RGB => PixelFormatFlags::FOUR_CC,
524			Format::RGBA => PixelFormatFlags::FOUR_CC,
525		};
526		let mask = match format{
527			Format::RGBA => (0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000),
528			Format::RG => (0xFF0000, 0x00FF00, 0x0, 0x0),
529			_ => (0xFF0000, 0x00FF00, 0x0000FF, 0x0),
530		};
531		let dxgi_format = match format{
532			Format::Gray => match ty{
533				Type::UnsignedByte => DXGIFormat::R8_UNORM,
534				Type::Float16 => DXGIFormat::R16_FLOAT,
535				Type::Float32 => DXGIFormat::R32_FLOAT,
536			},
537			Format::RG => match ty{
538				Type::UnsignedByte => DXGIFormat::R8G8_UNORM,
539				Type::Float16 => DXGIFormat::R16G16_FLOAT,
540				Type::Float32 => DXGIFormat::R32G32_FLOAT,
541			},
542			Format::RGB => match ty{
543				Type::UnsignedByte => panic!("RGB8 not supported by dds"),
544				Type::Float16 => panic!("RGB16 not supported by dds"),
545				Type::Float32 => DXGIFormat::R32G32B32_FLOAT,
546			},
547			Format::RGBA => match ty{
548				Type::UnsignedByte => DXGIFormat::R8G8B8A8_UNORM,
549				Type::Float16 => DXGIFormat::R16G16B16A16_FLOAT,
550				Type::Float32 => DXGIFormat::R32G32B32A32_FLOAT,
551			},
552		};
553		Builder{
554			header: Header{
555				header_size: 124,
556				flags:  Flags::CAPS |
557						Flags::HEIGHT |
558						Flags::WIDTH |
559						Flags::PITCH |
560						Flags::PIXEL_FORMAT,
561				height: h as u32,
562				width: w as u32,
563				linear_size_or_pitch: pitch as u32,
564				depth: 0,
565				mipmapcount: 1,
566				reserved: [0u32;11],
567				pixel_format: PixelFormat{
568					size: 32,
569					flags: pixel_flags,
570					fourcc: fourcc_from_str("DX10"),
571					bitcount: bpp as u32,
572					r_bitmask: mask.0,
573					g_bitmask: mask.1,
574					b_bitmask: mask.2,
575					a_bitmask: mask.3,
576				},
577				caps: Caps::TEXTURE,
578				caps2: Caps2::empty(),
579				caps3: 0x0,
580				caps4: 0x0,
581				reserved2: 0x0,
582			},
583
584			header_dxt10: Some(HeaderDXT10{
585				dxgi_format,
586				resource_dimension: D3D10ResourceDimension::TEXTURE2D as u32,
587				misc_flag: 0,
588				array_size: 1,
589				misc_flags2: 0,
590			}),
591		}
592	}
593
594	// TODO: missing flags and mask per dxgi
595	// pub fn with_dxgi_format(w: usize, h: usize, dxgi_format: DXGIFormat) -> Builder {
596	// 	let bpp = dxgi_format.bpp().expect("DXGIFormat without bpp");
597	// 	let pitch = (w * bpp + 7) / 8;
598	// 	Builder{
599	// 		header: Header{
600	// 			header_size: 124,
601	// 			flags:  Flags::Caps as u32 |
602	// 					Flags::Height as u32 |
603	// 					Flags::Width as u32 |
604	// 					Flags::Pitch as u32 |
605	// 					Flags::PixelFormat as u32,
606	// 			height: h as u32,
607	// 			width: w as u32,
608	// 			linear_size_or_pitch: pitch as u32,
609	// 			depth: 0,
610	// 			mipmapcount: 1,
611	// 			reserved: [0u32;11],
612	// 			pixel_format: PixelFormat{
613	// 				size: 32,
614	// 				flags: PixelFormatFlags::FourCC as u32,
615	// 				fourcc: fourcc_from_str("DX10"),
616	// 				bitcount: bpp as u32,
617	// 				r_bitmask: mask.0,
618	// 				g_bitmask: mask.1,
619	// 				b_bitmask: mask.2,
620	// 				a_bitmask: mask.3,
621	// 			},
622	// 			caps: Caps::Texture as u32,
623	// 			caps2: 0x0,
624	// 			caps3: 0x0,
625	// 			caps4: 0x0,
626	// 			reserved2: 0x0,
627	// 		},
628
629	// 		header_dxt10: Some(HeaderDXT10{
630	// 			dxgi_format,
631	// 			resource_dimension: D3D10ResourceDimension::TEXTURE2D as u32,
632	// 			misc_flag: 0,
633	// 			array_size: 1,
634	// 			misc_flags2: 0,
635	// 		}),
636	// 	}
637	// }
638
639	pub fn has_mipmaps(&mut self, mipcount: usize) -> &mut Builder{
640		self.header.mipmapcount = mipcount as u32;
641		if mipcount > 1{
642			self.header.flags |= Flags::MIPMAP_COUNT;
643			self.header.caps |= Caps::COMPLEX | Caps::MIPMAP;
644		}
645		self
646	}
647
648	pub fn is_cubemap_allfaces(&mut self) -> &mut Builder{
649		self.header.caps |= Caps::COMPLEX;
650		self.header.caps2 |= Caps2::CUBEMAP |
651			Caps2::CUBEMAP_POS_X |
652			Caps2::CUBEMAP_NEG_X |
653			Caps2::CUBEMAP_POS_Y |
654			Caps2::CUBEMAP_NEG_Y |
655			Caps2::CUBEMAP_POS_Z |
656			Caps2::CUBEMAP_NEG_Z;
657		self.header_dxt10.as_mut().unwrap().misc_flag = 0x4;
658		self
659	}
660
661	pub fn create<S: Borrow<[u8]>>(&mut self, data: S) -> Result<Dds<S>,Error>{
662		let dds = Dds{
663			header: self.header.clone(),
664			header_dxt10: self.header_dxt10.clone(),
665			data: data
666		};
667		let linear_size = dds.try_linear_size()?;
668		if linear_size != dds.data.borrow().len(){
669			Err(Error(format!("Expected {} bytes but passed {}", linear_size, dds.data.borrow().len())))
670		}else{
671			Ok(dds)
672		}
673	}
674}
675
676#[derive(Clone)]
677pub struct Dds<S = Vec<u8>>{
678	header: Header,
679	header_dxt10: Option<HeaderDXT10>,
680	data: S,
681}
682
683
684fn fourcc_to_str(fourcc: u32) -> String{
685    let a = fourcc & 0x000000FF;
686    let b = (fourcc >> 8) & 0x000000FF;
687    let c = (fourcc >> 16) & 0x000000FF;
688    let d = (fourcc >> 24) & 0x000000FF;
689    let c_str: &[i8] = &[a as i8, b as i8, c as i8, d as i8, 0i8];
690    unsafe{
691        from_c_str!(c_str.as_ptr()).to_string()
692    }
693}
694
695fn fourcc_from_str(fourcc: &str) -> u32{
696	let mut bytes = fourcc.bytes();
697	let a = bytes.next().unwrap() as u32;
698	let b = bytes.next().unwrap() as u32;
699	let c = bytes.next().unwrap() as u32;
700	let d = bytes.next().unwrap() as u32;
701	(((((d << 8) | c) << 8) | b) << 8) | a
702}
703
704const fn fourcc_from_bytes(a: char, b: char, c: char, d: char) -> u32{
705	((((((d as u32) << 8) | c as u32) << 8) | b as u32) << 8) | a  as u32
706}
707
708impl Dds{
709	pub fn load<P: AsRef<Path>>(path: P) -> Result<Dds,Error>{
710		let file = File::open(&path)
711			.map_err(|err| err.to_string())?;
712		Dds::read(BufReader::new(file), path.as_ref().display())
713	}
714
715	pub fn from_bytes(bytes: &[u8]) -> Result<Dds,Error>{
716		Dds::read(bytes, "Dds from bytes")
717	}
718
719	fn read<R: Read, P: Display>(mut file: R, path: P) -> Result<Dds,Error> {
720		let mut filecode = [0u8; 4];
721		file.read_exact(&mut filecode)
722			.map_err(|_| format!("Couldn't read header for {}", path))?;
723		unsafe{
724			if filecode[0..3] != ['D' as u8, 'D' as u8, 'S' as u8]{
725				return Err(Error(format!("{} is not a correct dds file", path)));
726			}
727			let mut header_buffer = [0u8; 124];
728			file.read_exact(&mut header_buffer)
729				.map_err(|_| format!("Couldn't read header for {}", path))?;
730			let header: Header = mem::transmute(header_buffer);
731			let header_dxt10 = if header.pixel_format.fourcc == fourcc_from_str("DX10"){
732				let mut header_buffer = [0u8; 20];
733				file
734					.read_exact(&mut header_buffer)
735					.map_err(|_| format!("Couldn't read dxt10 header for {}", path))?;
736				Some(mem::transmute(header_buffer))
737			}else{
738				None
739			};
740
741			let mut dds = Dds{
742				header: header,
743				header_dxt10: header_dxt10,
744				data: vec![ ],
745			};
746			let bufsize = dds.try_linear_size()?;
747			let bytesread = file
748				//.take(bufsize as u64)
749				.read_to_end(&mut dds.data)
750				.map_err(|err| format!("Error reading data from {}: {}", path, err))?;
751			if bytesread != bufsize as usize{
752				return Err(Error(format!("Couldn't read expected size for {}, header specifies {} but only read {}", path, bufsize, bytesread)));
753			}
754
755			Ok(dds)
756		}
757	}
758}
759
760impl<S: Borrow<[u8]>> Dds<S>{
761	pub fn mipmap(&self, level: usize) -> Option<Dds<Cow<[u8]>>>{
762		if level >= self.mipmap_count(){
763			return None;
764		}
765
766
767		let mut header = self.header.clone();
768		let header_dxt10 = self.header_dxt10.clone();
769		header.mipmapcount = 1;
770		header.flags.remove(Flags::MIPMAP_COUNT);
771		header.caps.remove(Caps::MIPMAP);
772		if !self.is_cubemap_allfaces() {
773			header.caps.remove(Caps::COMPLEX);
774		}
775		let mut w;
776		let mut h;
777		let mut linear_size_or_pitch;
778		let data;
779		if self.is_compressed(){
780			if !self.is_cubemap_allfaces(){
781				let blocksize = if self.fourcc_str() == "DXT1" {8} else {16};
782				w = self.width();
783				h = self.height();
784				linear_size_or_pitch = self.header.linear_size_or_pitch as usize;
785				let mut offset = 0;
786				let mut size = ((w+3)/4) * ((h+3)/4) * blocksize;
787				for _ in 0..level{
788					offset += size;
789					w /= 2;
790					h /= 2;
791					linear_size_or_pitch /= 2;
792					size = ((w+3)/4) * ((h+3)/4) * blocksize;
793				}
794				data = Cow::Borrowed(&self.data.borrow()[offset..offset+size]);
795			}else{
796				return None;
797			}
798		}else{
799			if !self.is_cubemap_allfaces(){
800				h = self.height();
801				w = self.width();
802				linear_size_or_pitch = self.pitch();
803				let mut offset = 0;
804				let mut size = linear_size_or_pitch * h;
805				for _ in 0..level{
806					offset += size;
807					h /= 2;
808					linear_size_or_pitch /= 2;
809					w /= 2;
810					size = linear_size_or_pitch * h;
811				}
812				data = Cow::Borrowed(&self.data.borrow()[offset..offset+size]);
813			}else{
814				let face_size = {
815					let mut pitch = self.pitch();
816					let mut h = self.height();
817					let mut face_size = 0;
818					for _level in 0..self.mipmap_count(){
819						face_size += pitch * h;
820						pitch /= 2;
821						h /= 2;
822					}
823					face_size
824				};
825
826				let mut v = vec![];
827				h = self.height();
828				w = self.width();
829				linear_size_or_pitch = self.pitch();
830				for face in 0..6{
831					let mut offset = face_size * face;
832					h = self.height();
833					w = self.width();
834					linear_size_or_pitch = self.pitch();
835					let mut size = linear_size_or_pitch * h;
836					for _ in 0..level{
837						offset += size;
838						h /= 2;
839						linear_size_or_pitch /= 2;
840						w /= 2;
841						size = linear_size_or_pitch * h;
842					}
843					v.extend(&self.data.borrow()[offset..offset+size]);
844				}
845				data = Cow::Owned(v);
846			}
847		};
848
849		header.width = w as u32;
850		header.height = h as u32;
851		header.linear_size_or_pitch = linear_size_or_pitch as u32;
852		Some(Dds{
853			header,
854			header_dxt10,
855			data,
856		})
857
858	}
859
860	pub fn mipmap_face(&self, level: usize, face: usize) -> Result<Dds<&[u8]>, Error>{
861		if self.is_compressed(){
862			Err(Error("Compressed cubemaps not supported yet".to_string()))
863		}else if !self.is_cubemap_allfaces(){
864			Err(Error("Dds is not a cubemap".to_string()))
865		}else{
866			let mut pitch = self.pitch();
867			let mut h = self.height();
868			let mut face_size = 0;
869			for _level in 0..self.mipmap_count(){
870				face_size += pitch * h;
871				pitch /= 2;
872				h /= 2;
873			}
874
875			let mut offset = face_size * face;
876			let mut pitch = self.pitch();
877			let mut h = self.height();
878			let mut w = self.width();
879			let mut size = pitch * h;
880			for _ in 0..level{
881				offset += size;
882				pitch /= 2;
883				w /= 2;
884				h /= 2;
885				size = pitch * h;
886			}
887
888			let data = &self.data.borrow()[offset..offset+size];
889			let mut header = self.header.clone();
890			let header_dxt10 = self.header_dxt10.clone();
891			header.height = h as u32;
892			header.width = w as u32;
893			header.mipmapcount = 1;
894			header.linear_size_or_pitch = pitch as u32;
895			header.flags.remove(Flags::MIPMAP_COUNT);
896			header.caps.remove(Caps::MIPMAP);
897			header.caps2.remove(Caps2::CUBEMAP);
898			header.caps2.remove(Caps2::CUBEMAP_POS_X);
899			header.caps2.remove(Caps2::CUBEMAP_NEG_X);
900			header.caps2.remove(Caps2::CUBEMAP_POS_Y);
901			header.caps2.remove(Caps2::CUBEMAP_NEG_Y);
902			header.caps2.remove(Caps2::CUBEMAP_POS_Z);
903			header.caps2.remove(Caps2::CUBEMAP_NEG_Z);
904			Ok(Dds{
905				header,
906				header_dxt10,
907				data,
908			})
909		}
910	}
911
912	pub fn face(&self, face: usize) -> Result<Dds<&[u8]>, Error>{
913		if self.is_compressed(){
914			Err(Error("Compressed cubemaps not supported yet".to_string()))
915		}else if !self.is_cubemap_allfaces(){
916			Err(Error("Dds is not a cubemap".to_string()))
917		}else{
918			let mut pitch = self.pitch();
919			let mut h = self.height();
920			let mut face_size = 0;
921			for _level in 0..self.mipmap_count(){
922				face_size += pitch * h;
923				pitch /= 2;
924				h /= 2;
925			}
926
927			let offset = face_size * face;
928			let data = &self.data.borrow()[offset..offset+face_size];
929			let mut header = self.header.clone();
930			let header_dxt10 = self.header_dxt10.clone();
931			header.caps2.remove(Caps2::CUBEMAP);
932			if face != 0 {
933				header.caps2.remove(Caps2::CUBEMAP_POS_X);
934			}
935			if face != 1 {
936				header.caps2.remove(Caps2::CUBEMAP_NEG_X);
937			}
938			if face != 2 {
939				header.caps2.remove(Caps2::CUBEMAP_POS_Y);
940			}
941			if face != 3 {
942				header.caps2.remove(Caps2::CUBEMAP_NEG_Y);
943			}
944			if face != 4 {
945				header.caps2.remove(Caps2::CUBEMAP_POS_Z);
946			}
947			if face != 5 {
948				header.caps2.remove(Caps2::CUBEMAP_NEG_Z);
949			}
950			Ok(Dds{
951				header,
952				header_dxt10,
953				data,
954			})
955		}
956	}
957
958	pub fn save<P: AsRef<Path>>(&self, path: P) -> Result<(),Error>{
959		let mut file = File::create(path)
960			.map_err(|err| err.to_string())?;
961		file
962			.write_all(&['D' as u8,'D' as u8,'S' as u8, ' ' as u8])
963			.map_err(|err| err.to_string())?;
964		unsafe{
965			let header: &[u8;124] = mem::transmute(&self.header);
966			file.write_all(header)
967				.map_err(|err| err.to_string())?;
968			if let Some(ref header_dxt) = self.header_dxt10{
969				let header_dxt: &[u8;20] = mem::transmute(header_dxt);
970				file.write_all(header_dxt)
971					.map_err(|err| err.to_string())?;
972			}
973		}
974		file
975			.write_all(self.data.borrow())
976			.map_err(|err| err.to_string())?;
977		Ok(())
978	}
979
980	pub fn data(&self) -> &[u8]{
981		self.data.borrow()
982	}
983}
984
985impl<S> Dds<S>{
986	pub fn width(&self) -> usize{
987		self.header.width as usize
988	}
989
990	pub fn height(&self) -> usize{
991		self.header.height as usize
992	}
993
994	pub fn mipmap_count(&self) -> usize{
995		if self.header.caps.contains(Caps::MIPMAP) {
996			self.header.mipmapcount as usize
997		}else{
998			1
999		}
1000	}
1001
1002	pub fn fourcc(&self) -> u32{
1003		self.header.pixel_format.fourcc
1004	}
1005
1006	pub fn fourcc_str(&self) -> String{
1007		fourcc_to_str(self.fourcc())
1008	}
1009
1010	pub fn bpp(&self) -> Result<usize, Error>{
1011		if self.header.pixel_format.flags.contains(PixelFormatFlags::FOUR_CC) {
1012			match self.header.pixel_format.fourcc {
1013				36 => Ok(64),
1014
1015				110 => Ok(64),
1016
1017				111 => Ok(16),
1018
1019				112 => Ok(32),
1020
1021				113 => Ok(64),
1022
1023				114 => Ok(32),
1024
1025				115 => Ok(64),
1026
1027				116 => Ok(128),
1028
1029				_fourcc => {
1030					let fourcc_str = self.fourcc_str();
1031					match fourcc_str.as_str() {
1032						"DXT1" | "DXT3" | "DXT5" | "DXT2" | "DXT4" | "ATI1" | "BC4U" | "BC4S" | "ATI2" | "BC5U" | "BC5S"
1033							=>  Err(Error::from(format!("Compressed format doesn't have bpp"))),
1034
1035						"RGBG" => Ok(32),
1036
1037						"GRGB" => Ok(32),
1038
1039						"YUY2" => Err(Error::from(format!("YUV format doesn't have bpp"))),
1040
1041						"DX10" => self.header_dxt10.as_ref().unwrap().dxgi_format.bpp()
1042							.ok_or_else(|| Error::from(format!(
1043								"DX10 format {:?} doesn't have bpp",
1044								self.header_dxt10.as_ref().unwrap().dxgi_format))),
1045
1046						other => if let Some(header_dxt10) = self.header_dxt10.as_ref(){
1047							header_dxt10.dxgi_format.bpp()
1048								.ok_or_else(|| Error::from(format!(
1049									"DX10 format {:?} doesn't have bpp",
1050									self.header_dxt10.as_ref().unwrap().dxgi_format)
1051								))
1052						}else{
1053							Err(Error::from(format!(
1054								"Pixel format flags contain FourCC but actual fourCC {} str({other}) is not known",
1055								self.header.pixel_format.fourcc
1056							)))
1057						}
1058					}
1059				}
1060			}
1061		}else{
1062			Ok(self.header.pixel_format.bitcount as usize)
1063		}
1064	}
1065
1066	pub fn r_bitmask(&self) -> u32{
1067		self.header.pixel_format.r_bitmask
1068	}
1069
1070	pub fn g_bitmask(&self) -> u32{
1071		self.header.pixel_format.g_bitmask
1072	}
1073
1074	pub fn b_bitmask(&self) -> u32{
1075		self.header.pixel_format.b_bitmask
1076	}
1077
1078	pub fn a_bitmask(&self) -> u32{
1079		self.header.pixel_format.a_bitmask
1080	}
1081
1082	pub fn linear_size(&self) -> usize{
1083		// This is always queried at the beginning so we can later unwrap it and it should
1084		// never fail
1085		self.try_linear_size().unwrap()
1086	}
1087
1088	fn try_linear_size(&self) -> Result<usize, Error> {
1089		if self.is_compressed(){
1090			if self.mipmap_count() > 1 {
1091				let faces = if self.is_cubemap_allfaces(){
1092					6
1093				}else{
1094					1
1095				};
1096				let blocksize = if self.fourcc_str() == "DXT1" {8} else {16};
1097				let mut w = self.width();
1098				let mut h = self.height();
1099				let mut total_size = 0;
1100				let mut size = ((w+3)/4) * ((h+3)/4) * blocksize * faces;
1101				for _ in 0..self.mipmap_count(){
1102					total_size += size;
1103					w /= 2;
1104					h /= 2;
1105					size = ((w+3)/4) * ((h+3)/4) * blocksize * faces;
1106				}
1107				Ok(total_size)
1108			} else {
1109				Ok(self.header.linear_size_or_pitch as usize)
1110			}
1111		}else{
1112			let faces = if self.is_cubemap_allfaces(){
1113				6
1114			}else{
1115				1
1116			};
1117			let mut h = self.height();
1118			let bpp = self.bpp()?;
1119			let mut pitch = self.pitch() / (bpp / 8);
1120			let mut total_size = 0;
1121			for _ in 0..self.mipmap_count(){
1122				total_size += pitch * h * faces;
1123				h /= 2;
1124				pitch /= 2;
1125			}
1126			Ok(total_size * (bpp / 8))
1127		}
1128	}
1129
1130	pub fn pitch(&self) -> usize{
1131		if self.is_compressed(){
1132			let blocksize = if self.fourcc_str() == "DXT1" {8} else {16};
1133			max((self.header.width as usize + 3) / 4, 1) * blocksize
1134		}else{
1135			self.header.linear_size_or_pitch as usize
1136		}
1137	}
1138
1139	pub fn is_compressed(&self) -> bool{
1140		let fourcc_str = self.fourcc_str();
1141		&fourcc_str == "DXT1"
1142			|| &fourcc_str == "DXT3"
1143			|| &fourcc_str == "DXT5"
1144			|| &fourcc_str == "DXT2"
1145			|| &fourcc_str == "DXT4"
1146			|| &fourcc_str == "ATI1"
1147			|| &fourcc_str == "BC4U"
1148			|| &fourcc_str == "BC4S"
1149			|| &fourcc_str == "ATI2"
1150			|| &fourcc_str == "BC5U"
1151			|| &fourcc_str == "BC5S"
1152			|| (&fourcc_str == "DX10" && {
1153				let header_dxt10 = self.header_dxt10.as_ref().unwrap();
1154				header_dxt10.dxgi_format == DXGIFormat::BC1_TYPELESS
1155					|| header_dxt10.dxgi_format == DXGIFormat::BC1_UNORM
1156					|| header_dxt10.dxgi_format == DXGIFormat::BC1_UNORM_SRGB
1157					|| header_dxt10.dxgi_format == DXGIFormat::BC2_TYPELESS
1158					|| header_dxt10.dxgi_format == DXGIFormat::BC2_UNORM
1159					|| header_dxt10.dxgi_format == DXGIFormat::BC2_UNORM_SRGB
1160					|| header_dxt10.dxgi_format == DXGIFormat::BC3_TYPELESS
1161					|| header_dxt10.dxgi_format == DXGIFormat::BC3_UNORM
1162					|| header_dxt10.dxgi_format == DXGIFormat::BC3_UNORM_SRGB
1163					|| header_dxt10.dxgi_format == DXGIFormat::BC4_TYPELESS
1164					|| header_dxt10.dxgi_format == DXGIFormat::BC4_UNORM
1165					|| header_dxt10.dxgi_format == DXGIFormat::BC4_SNORM
1166					|| header_dxt10.dxgi_format == DXGIFormat::BC5_TYPELESS
1167					|| header_dxt10.dxgi_format == DXGIFormat::BC5_UNORM
1168					|| header_dxt10.dxgi_format == DXGIFormat::BC5_SNORM
1169					|| header_dxt10.dxgi_format == DXGIFormat::BC6H_SF16
1170					|| header_dxt10.dxgi_format == DXGIFormat::BC6H_UF16
1171					|| header_dxt10.dxgi_format == DXGIFormat::BC6H_TYPELESS
1172					|| header_dxt10.dxgi_format == DXGIFormat::BC7_UNORM
1173					|| header_dxt10.dxgi_format == DXGIFormat::BC7_UNORM_SRGB
1174					|| header_dxt10.dxgi_format == DXGIFormat::BC7_TYPELESS
1175			})
1176	}
1177
1178	pub fn format(&self) -> Result<DXGIFormat, Error>{
1179		if self.header.pixel_format.flags.contains(PixelFormatFlags::RGB) {
1180			match self.header.pixel_format.bitcount {
1181				32 if self.header.pixel_format.r_bitmask == 0x000000ff
1182					&& self.header.pixel_format.g_bitmask == 0x0000ff00
1183					&& self.header.pixel_format.b_bitmask == 0x00ff0000
1184					&& self.header.pixel_format.a_bitmask == 0xff000000 => Ok(DXGIFormat::R8G8B8A8_UNORM),
1185
1186				32 if self.header.pixel_format.r_bitmask == 0x00ff0000
1187					&& self.header.pixel_format.g_bitmask == 0x0000ff00
1188					&& self.header.pixel_format.b_bitmask == 0x000000ff
1189					&& self.header.pixel_format.a_bitmask == 0xff000000 => Ok(DXGIFormat::B8G8R8A8_UNORM),
1190
1191				32 if self.header.pixel_format.r_bitmask == 0x00ff0000
1192					&& self.header.pixel_format.g_bitmask == 0x0000ff00
1193					&& self.header.pixel_format.b_bitmask == 0x000000ff
1194					&& self.header.pixel_format.a_bitmask == 0x00000000 => Ok(DXGIFormat::B8G8R8X8_UNORM),
1195
1196				32 if self.header.pixel_format.r_bitmask == 0x0000ffff
1197					&& self.header.pixel_format.g_bitmask == 0xffff0000
1198					&& self.header.pixel_format.b_bitmask == 0x00000000
1199					&& self.header.pixel_format.a_bitmask == 0x00000000 => Ok(DXGIFormat::R16G16_UNORM),
1200
1201				32 if self.header.pixel_format.r_bitmask == 0xffffffff
1202					&& self.header.pixel_format.g_bitmask == 0x00000000
1203					&& self.header.pixel_format.b_bitmask == 0x00000000
1204					&& self.header.pixel_format.a_bitmask == 0x00000000 => Ok(DXGIFormat::R32_FLOAT),
1205
1206				24 => Err(Error::from(format!("Pixel format bitcount specifies 24 which is not valid"))),
1207
1208				16 if self.header.pixel_format.r_bitmask == 0x7c00
1209					&& self.header.pixel_format.g_bitmask == 0x03e0
1210					&& self.header.pixel_format.b_bitmask == 0x001f
1211					&& self.header.pixel_format.a_bitmask == 0x8000 => Ok(DXGIFormat::B5G5R5A1_UNORM),
1212
1213				16 if self.header.pixel_format.r_bitmask == 0xf800
1214					&& self.header.pixel_format.g_bitmask == 0x07e0
1215					&& self.header.pixel_format.b_bitmask == 0x001f
1216					&& self.header.pixel_format.a_bitmask == 0x0000 => Ok(DXGIFormat::B5G6R5_UNORM),
1217
1218				16 if self.header.pixel_format.r_bitmask == 0x0f00
1219					&& self.header.pixel_format.g_bitmask == 0x00f0
1220					&& self.header.pixel_format.b_bitmask == 0x000f
1221					&& self.header.pixel_format.a_bitmask == 0xf000 => Ok(DXGIFormat::B4G4R4A4_UNORM),
1222
1223				bitcount => Err(Error::from(format!(
1224						"RB Pixel format bitcount specifies {} with color masks {:x},{:x},{:x},{:x} which is not valid",
1225						bitcount,
1226						self.header.pixel_format.r_bitmask,
1227						self.header.pixel_format.g_bitmask,
1228						self.header.pixel_format.b_bitmask,
1229						self.header.pixel_format.a_bitmask
1230					)))
1231			}
1232
1233		}else if self.header.pixel_format.flags.contains(PixelFormatFlags::LUMINANCE){
1234			match self.header.pixel_format.bitcount {
1235				8 if self.header.pixel_format.r_bitmask == 0x000000ff
1236					&& self.header.pixel_format.g_bitmask == 0x00000000
1237					&& self.header.pixel_format.b_bitmask == 0x00000000
1238					&& self.header.pixel_format.a_bitmask == 0x00000000 => Ok(DXGIFormat::R8_UNORM),
1239
1240				// Some DDS writers assume the bitcount should be 8 instead of 16
1241				8 if self.header.pixel_format.r_bitmask == 0x000000ff
1242					&& self.header.pixel_format.g_bitmask == 0x00000000
1243					&& self.header.pixel_format.b_bitmask == 0x00000000
1244					&& self.header.pixel_format.a_bitmask == 0x0000ff00 => Ok(DXGIFormat::R8G8_UNORM),
1245
1246				16 if self.header.pixel_format.r_bitmask == 0x0000ffff
1247					&& self.header.pixel_format.g_bitmask == 0x00000000
1248					&& self.header.pixel_format.b_bitmask == 0x00000000
1249					&& self.header.pixel_format.a_bitmask == 0x00000000 => Ok(DXGIFormat::R16_UNORM),
1250
1251				16 if self.header.pixel_format.r_bitmask == 0x000000ff
1252					&& self.header.pixel_format.g_bitmask == 0x00000000
1253					&& self.header.pixel_format.b_bitmask == 0x00000000
1254					&& self.header.pixel_format.a_bitmask == 0x0000ff00 => Ok(DXGIFormat::R8G8_UNORM),
1255
1256				bitcount => Err(Error::from(format!(
1257						"Luminance Pixel format bitcount specifies {} with color masks {:x},{:x},{:x},{:x} which is not valid",
1258						bitcount,
1259						self.header.pixel_format.r_bitmask,
1260						self.header.pixel_format.g_bitmask,
1261						self.header.pixel_format.b_bitmask,
1262						self.header.pixel_format.a_bitmask
1263					)))
1264			}
1265		}else if self.header.pixel_format.flags.contains(PixelFormatFlags::ALPHA)
1266			|| self.header.pixel_format.bitcount == 8
1267		{
1268			Ok(DXGIFormat::A8_UNORM)
1269		}else if self.header.pixel_format.flags.contains(PixelFormatFlags::BUMP_DU_DV) {
1270			match self.header.pixel_format.bitcount {
1271				16 if self.header.pixel_format.r_bitmask == 0x00ff
1272					&& self.header.pixel_format.g_bitmask == 0xff00
1273					&& self.header.pixel_format.b_bitmask == 0x0000
1274					&& self.header.pixel_format.a_bitmask == 0x0000 => Ok(DXGIFormat::R8G8_UNORM),
1275
1276				32 if self.header.pixel_format.r_bitmask == 0x000000ff
1277					&& self.header.pixel_format.g_bitmask == 0x0000ff00
1278					&& self.header.pixel_format.b_bitmask == 0x00ff0000
1279					&& self.header.pixel_format.a_bitmask == 0xff000000 => Ok(DXGIFormat::R8G8B8A8_SNORM),
1280
1281				32 if self.header.pixel_format.r_bitmask == 0x0000ffff
1282					&& self.header.pixel_format.g_bitmask == 0xffff0000
1283					&& self.header.pixel_format.b_bitmask == 0x00000000
1284					&& self.header.pixel_format.a_bitmask == 0x00000000 => Ok(DXGIFormat::R16G16_SNORM),
1285
1286				bitcount => Err(Error::from(format!(
1287						"BumpDuDv Pixel format bitcount specifies {} with color masks {:x},{:x},{:x},{:x} which is not valid",
1288						bitcount,
1289						self.header.pixel_format.r_bitmask,
1290						self.header.pixel_format.g_bitmask,
1291						self.header.pixel_format.b_bitmask,
1292						self.header.pixel_format.a_bitmask
1293					)))
1294			}
1295
1296		}else if self.header.pixel_format.flags.contains(PixelFormatFlags::FOUR_CC) {
1297			match self.header.pixel_format.fourcc {
1298				36 => Ok(DXGIFormat::R16G16B16A16_UNORM),
1299
1300				110 => Ok(DXGIFormat::R16G16B16A16_SNORM),
1301
1302				111 => Ok(DXGIFormat::R16_FLOAT),
1303
1304				112 => Ok(DXGIFormat::R16G16_FLOAT),
1305
1306				113 => Ok(DXGIFormat::R16G16B16A16_FLOAT),
1307
1308				114 => Ok(DXGIFormat::R32_FLOAT),
1309
1310				115 => Ok(DXGIFormat::R32G32_FLOAT),
1311
1312				116 => Ok(DXGIFormat::R32G32B32A32_FLOAT),
1313
1314				fourcc => {
1315					let fourcc_str = self.fourcc_str();
1316					match fourcc_str.as_str() {
1317						"DXT1" => Ok(DXGIFormat::BC1_UNORM),
1318						"DXT3" => Ok(DXGIFormat::BC2_UNORM),
1319						"DXT5" => Ok(DXGIFormat::BC3_UNORM),
1320
1321						// While pre-multiplied alpha isn't directly supported by the DXGI formats,
1322						// they are basically the same as these BC formats so they can be mapped
1323						"DXT2" => Ok(DXGIFormat::BC2_UNORM),
1324						"DXT4" => Ok(DXGIFormat::BC3_UNORM),
1325
1326						"ATI1" | "BC4U" => Ok(DXGIFormat::BC4_UNORM),
1327
1328						"BC4S" => Ok(DXGIFormat::BC4_SNORM),
1329
1330						"ATI2" | "BC5U" => Ok(DXGIFormat::BC5_UNORM),
1331
1332						"BC5S" => Ok(DXGIFormat::BC5_SNORM),
1333
1334						"RGBG" => Ok(DXGIFormat::R8G8_B8G8_UNORM),
1335
1336						"GRGB" => Ok(DXGIFormat::G8R8_G8B8_UNORM),
1337
1338						"YUY2" => Ok(DXGIFormat::YUY2),
1339
1340						"DX10" => {
1341							if let Some(header_dx10) = self.header_dxt10.as_ref(){
1342								Ok(header_dx10.dxgi_format)
1343							}else{
1344								Err(Error::from(format!(
1345									"Pixel format flags contain FourCC DX10 but there's no DX10 header present in the file {} is not known",
1346									fourcc
1347								)))
1348							}
1349						}
1350
1351						_ => Err(Error::from(format!(
1352							"Pixel format flags contain FourCC but actual fourCC {} is not known",
1353							fourcc
1354						)))
1355					}
1356				}
1357			}
1358		}else{
1359			Err(Error::from(format!("Unkown format")))
1360		}
1361	}
1362
1363	pub fn is_cubemap(&self) -> bool{
1364		self.header.caps2.contains(Caps2::CUBEMAP)
1365	}
1366
1367	pub fn is_cubemap_allfaces(&self) -> bool{
1368		self.header.caps2.contains(Caps2::CUBEMAP_POS_X) &&
1369		self.header.caps2.contains(Caps2::CUBEMAP_NEG_X) &&
1370		self.header.caps2.contains(Caps2::CUBEMAP_POS_Y) &&
1371		self.header.caps2.contains(Caps2::CUBEMAP_NEG_Y) &&
1372		self.header.caps2.contains(Caps2::CUBEMAP_POS_Z) &&
1373		self.header.caps2.contains(Caps2::CUBEMAP_NEG_Z)
1374	}
1375}