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 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 .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 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 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 "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}