1#[macro_use]
24extern crate serde_derive;
25extern crate bincode;
26extern crate rgb;
27extern crate serde;
28
29use bincode::{serialize, deserialize, Infinite, ErrorKind};
30
31use std::cmp;
32use std::fmt;
33use std::io;
34use rgb::{ComponentBytes, RGBA};
35
36
37#[derive(Debug)]
39pub enum ParseError {
40 IO(io::Error),
41 Deserialize(Box<ErrorKind>),
42 Parse(String),
43}
44
45impl From<io::Error> for ParseError {
46 fn from(err: io::Error) -> ParseError {
47 ParseError::IO(err)
48 }
49}
50
51impl<'a> From<&'a str> for ParseError {
52 fn from(err: &'a str) -> ParseError {
53 ParseError::Parse(err.into())
54 }
55}
56
57impl From<String> for ParseError {
58 fn from(err: String) -> ParseError {
59 ParseError::Parse(err)
60 }
61}
62
63impl From<Box<ErrorKind>> for ParseError {
64 fn from(err: Box<ErrorKind>) -> ParseError {
65 ParseError::Deserialize(err)
66 }
67}
68
69#[derive(Debug)]
72pub enum EncodeError {
73 Encode(String),
74}
75
76impl<'a> From<&'a str> for EncodeError {
77 fn from(err: &'a str) -> EncodeError {
78 EncodeError::Encode(err.into())
79 }
80}
81
82impl From<String> for EncodeError {
83 fn from(err: String) -> EncodeError {
84 EncodeError::Encode(err)
85 }
86}
87
88
89#[repr(C)]
94#[derive(Serialize, Deserialize, PartialEq, Debug)]
95pub struct RawPixelFormat {
96 pub size: u32,
97 pub flags: u32,
98 pub four_cc: [u8; 4],
99 pub rgb_bit_count: u32,
100 pub red_bit_mask: u32,
101 pub green_bit_mask: u32,
102 pub blue_bit_mask: u32,
103 pub alpha_bit_mask: u32,
104}
105
106
107#[repr(C)]
112#[derive(Serialize, Deserialize, PartialEq, Debug)]
113pub struct RawHeader {
114 pub size: u32,
115 pub flags: u32,
116 pub height: u32,
117 pub width: u32,
118 pub pitch_or_linear_size: u32,
119 pub depth: u32,
120 pub mipmap_count: u32,
121 pub reserved: [u32; 11],
122 pub pixel_format: RawPixelFormat,
123 pub caps: u32,
124 pub caps2: u32,
125 pub caps3: u32,
126 pub caps4: u32,
127 pub reserved2: u32,
128}
129
130#[derive(Debug, PartialEq)]
135pub enum PixelFormat {
136 A1R5G5B5,
137 A2B10G10R10,
138 A2R10G10B10,
139 A4L4,
140 A4R4G4B4,
141 A8,
142 A8B8G8R8,
143 A8L8,
144 A8R3G3B2,
145 A8R8G8B8,
146 G16R16,
147 L16,
148 L8,
149 R5G6B5,
150 R8G8B8,
151 Unknown,
152 X1R5G5B5,
153 X4R4G4B4,
154 X8B8G8R8,
155 X8R8G8B8,
156}
157
158impl fmt::Display for PixelFormat {
159 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160 write!(f, "{:?}", self)
161 }
162}
163
164#[derive(Debug)]
167pub enum Compression {
168 DXT1,
169 DXT2,
170 DXT3,
171 DXT4,
172 DXT5,
173 DX10,
174 None,
175 Other(u8, u8, u8, u8),
176}
177
178impl Compression {
179 fn from_bytes(bytes: &[u8; 4]) -> Compression {
180 match bytes {
181 b"\x00\x00\x00\x00" => Compression::None,
182 b"DXT1" => Compression::DXT1,
183 b"DXT2" => Compression::DXT2,
184 b"DXT3" => Compression::DXT3,
185 b"DXT4" => Compression::DXT4,
186 b"DXT5" => Compression::DXT5,
187 b"DX10" => Compression::DX10,
188 _ => Compression::Other(bytes[0], bytes[1], bytes[2], bytes[3]),
189 }
190 }
191}
192
193impl fmt::Display for Compression {
194 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
195 write!(f, "{:?}", self)
196 }
197}
198
199#[derive(Debug)]
201pub struct Header {
202 pub height: u32,
204
205 pub width: u32,
207
208 pub mipmap_count: u32,
210
211 pub compression: Compression,
213
214 pub fourcc: [u8; 4],
216
217 pub pixel_format: PixelFormat,
219
220 pub pixel_bytes: usize,
222
223 pub channel_masks: [u32; 4],
225}
226
227impl Header {
228 fn get_layer_sizes(&self) -> Vec<(usize, usize)> {
230 (0..cmp::max(self.mipmap_count, 1))
234 .map(|i: u32| (
235 (self.height / 2u32.pow(i)) as usize,
236 (self.width / 2u32.pow(i)) as usize,
237 ))
238 .collect::<Vec<_>>()
239 }
240}
241
242
243pub struct DDS {
245 pub header: Header,
247
248 pub layers: Vec<Vec<RGBA<u8>>>,
250}
251
252
253impl DDS {
254 fn parse_pixel_format(header: &RawHeader) -> PixelFormat {
256 let p = &header.pixel_format;
257
258 match (p.rgb_bit_count, p.red_bit_mask, p.green_bit_mask, p.blue_bit_mask, p.alpha_bit_mask) {
259 (16, 0x7C00, 0x3E0, 0x1F, 0x8000) => PixelFormat::A1R5G5B5,
260 (32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000) => PixelFormat::A2B10G10R10,
261 (32, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000) => PixelFormat::A2R10G10B10,
262 ( 8, 0xF, 0x0, 0x0, 0xF0) => PixelFormat::A4L4,
263 (16, 0xF00, 0xF0, 0xF, 0xF000) => PixelFormat::A4R4G4B4,
264 ( 8, 0x0, 0x0, 0x0, 0xFF) => PixelFormat::A8,
265 (32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000) => PixelFormat::A8B8G8R8,
266 (16, 0xFF, 0x0, 0x0, 0xFF00) => PixelFormat::A8L8,
267 (16, 0xE0, 0x1C, 0x3, 0xFF00) => PixelFormat::A8R3G3B2,
268 (32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000) => PixelFormat::A8R8G8B8,
269 (32, 0xFFFF, 0xFFFF0000, 0x0, 0x0) => PixelFormat::G16R16,
270 (16, 0xFFFF, 0x0, 0x0, 0x0) => PixelFormat::L16,
271 ( 8, 0xFF, 0x0, 0x0, 0x0) => PixelFormat::L8,
272 (16, 0xF800, 0x7E0, 0x1F, 0x0) => PixelFormat::R5G6B5,
273 (24, 0xFF0000, 0xFF00, 0xFF, 0x0) => PixelFormat::R8G8B8,
274 (16, 0x7C00, 0x3E0, 0x1F, 0x0) => PixelFormat::X1R5G5B5,
275 (16, 0xF00, 0xF0, 0xF, 0x0) => PixelFormat::X4R4G4B4,
276 (32, 0xFF, 0xFF00, 0xFF0000, 0x0) => PixelFormat::X8B8G8R8,
277 (32, 0xFF0000, 0xFF00, 0xFF, 0x0) => PixelFormat::X8R8G8B8,
278 ( _, _, _, _, _) => PixelFormat::Unknown,
279 }
280 }
281
282 pub fn parse_header<R: io::Read>(buf: &mut R) -> Result<Header, ParseError> {
284 let raw_header = DDS::parse_header_raw(buf)?;
285
286 Ok(Header {
287 height: raw_header.height,
288 width: raw_header.width,
289 mipmap_count: raw_header.mipmap_count,
290 compression: Compression::from_bytes(&raw_header.pixel_format.four_cc),
291 fourcc: raw_header.pixel_format.four_cc,
292 pixel_format: DDS::parse_pixel_format(&raw_header),
293 pixel_bytes: raw_header.pixel_format.rgb_bit_count as usize / 8,
294 channel_masks: [
295 raw_header.pixel_format.red_bit_mask,
296 raw_header.pixel_format.green_bit_mask,
297 raw_header.pixel_format.blue_bit_mask,
298 raw_header.pixel_format.alpha_bit_mask,
299 ],
300 })
301 }
302
303 pub fn parse_header_raw<R: io::Read>(buf: &mut R) -> Result<RawHeader, ParseError> {
306 let mut magic_buf = [0; 4];
307 let mut header_buf = [0u8; 124];
308
309 buf.read_exact(&mut magic_buf[..]).expect("Not enough bytes to read magic bytes!");
310
311 if &magic_buf != b"DDS " {
313 return Err(format!("Expected the file to start with `DDS `, got `{}` instead.", String::from_utf8_lossy(&magic_buf)).into());
314 }
315
316 buf.read_exact(&mut header_buf[..]).expect("Not enough bytes to read header!");
317
318 Ok(deserialize(&header_buf[..])?)
319 }
320 fn decode_uncompressed(header: &Header, data_buf: &mut Vec<u8>) -> Vec<Vec<RGBA<u8>>> {
322 let layer_sizes = header.get_layer_sizes();
323
324 layer_sizes
326 .iter()
327 .map(|&(h, w)| {
328 data_buf
329 .drain(..h * w * header.pixel_bytes)
331 .collect::<Vec<_>>()
332 .chunks(header.pixel_bytes)
334 .map(|p| {
335 let pixel: u32 = p[0] as u32 + ((p[1] as u32) << 8) + ((p[2] as u32) << 16) + ((p[3] as u32) << 24);
336
337 let convert = |mask: u32| -> u8 {
340 ((pixel & mask) >> mask.trailing_zeros() * 255 / (2u32.pow(mask.count_ones()) - 1)) as u8
341 };
342
343 RGBA {
344 r: convert(header.channel_masks[0]),
345 g: convert(header.channel_masks[1]),
346 b: convert(header.channel_masks[2]),
347 a: convert(header.channel_masks[3]),
348 }
349 })
350 .collect()
351 })
352 .collect()
353 }
354
355 fn bytes_to_pixels_dxt1(bytes: &[u8], alpha: bool) -> Vec<RGBA<u8>> {
358 let color0 = (((bytes[1] as u16) << 8) + bytes[0] as u16) as u32;
360 let color1 = (((bytes[3] as u16) << 8) + bytes[2] as u16) as u32;
361
362 bytes[4..]
365 .iter()
366 .rev()
367 .flat_map(|&code| {
368 (0..4)
369 .map(|i| {
370 let lookup = |c0: u32, c1: u32, inflate_by: u32| {
383 let c0 = c0 * 255 / (2u32.pow(inflate_by) - 1);
385 let c1 = c1 * 255 / (2u32.pow(inflate_by) - 1);
386
387 match (color0 > color1, (code >> (i * 2)) & 0x3) {
388 ( true, 0) => Some(c0),
389 ( true, 1) => Some(c1),
390 ( true, 2) => Some((2 * c0 + c1) / 3),
391 ( true, 3) => Some((c0 + 2 * c1) / 3),
392 (false, 0) => Some(c0),
393 (false, 1) => Some(c1),
394 (false, 2) => Some((c0 + c1) / 2),
395 (false, 3) => None,
396 _ => unreachable!(),
397 }
398 };
399
400 let red0 = (color0 & 0xF800) >> 11;
401 let red1 = (color1 & 0xF800) >> 11;
402 let green0 = (color0 & 0x7E0) >> 5;
403 let green1 = (color1 & 0x7E0) >> 5;
404 let blue0 = color0 & 0x1F;
405 let blue1 = color1 & 0x1F;
406
407 let r = lookup(red0, red1, 5);
410 let g = lookup(green0, green1, 6);
411 let b = lookup(blue0, blue1, 5);
412 let a = if !alpha || r.is_some() || g.is_some() || b.is_some() {
413 255
414 } else {
415 0
416 };
417
418 RGBA {
419 r: r.unwrap_or(0) as u8,
420 g: g.unwrap_or(0) as u8,
421 b: b.unwrap_or(0) as u8,
422 a,
423 }
424 })
425 .collect::<Vec<_>>()
426 })
427 .collect::<Vec<_>>()
428 }
429
430 fn bytes_to_pixels_dxt3(bytes: &[u8]) -> Vec<RGBA<u8>> {
432 let color0 = (((bytes[9] as u16) << 8) + bytes[8] as u16) as u32;
434 let color1 = (((bytes[11] as u16) << 8) + bytes[10] as u16) as u32;
435
436 bytes[12..]
439 .iter()
440 .rev()
441 .enumerate()
442 .flat_map(|(i, &code)| {
443 (0..4)
444 .map(|j| {
445 let lookup = |c0: u32, c1: u32, inflate_by: u32| -> u32 {
446 let c0 = c0 * 255 / (2u32.pow(inflate_by) - 1);
448 let c1 = c1 * 255 / (2u32.pow(inflate_by) - 1);
449
450 match (code >> (j * 2)) & 0x3 {
451 0 => c0,
452 1 => c1,
453 2 => (2 * c0 + c1) / 3,
454 3 => (c0 + 2 * c1) / 3,
455 _ => unreachable!(),
456 }
457 };
458
459 let alpha_nibble = (bytes[2 * (3 - i) + j / 2] >> (4 * (j % 2))) & 0xF;
460
461 let red0 = (color0 & 0xF800) >> 11;
462 let red1 = (color1 & 0xF800) >> 11;
463 let green0 = (color0 & 0x7E0) >> 5;
464 let green1 = (color1 & 0x7E0) >> 5;
465 let blue0 = color0 & 0x1F;
466 let blue1 = color1 & 0x1F;
467
468 RGBA {
469 r: lookup(red0, red1, 5) as u8,
470 g: lookup(green0, green1, 6) as u8,
471 b: lookup(blue0, blue1, 5) as u8,
472 a: (alpha_nibble as u32 * 255 / 15) as u8,
473 }
474 })
475 .collect::<Vec<_>>()
476 })
477 .collect::<Vec<_>>()
478 }
479
480 fn bytes_to_pixels_dxt5(bytes: &[u8]) -> Vec<RGBA<u8>> {
482 let color0 = (((bytes[9] as u16) << 8) + bytes[8] as u16) as u32;
483 let color1 = (((bytes[11] as u16) << 8) + bytes[10] as u16) as u32;
484
485 let alpha0 = bytes[0] as u32;
486 let alpha1 = bytes[1] as u32;
487
488 let alpha_info = bytes[2..8]
491 .iter()
492 .enumerate()
493 .fold(0u64, |memo, (i, &x)| memo + ((x as u64) << 8 * i) as u64);
494
495 bytes[12..]
496 .iter()
497 .rev()
498 .enumerate()
499 .flat_map(|(i, &code)| {
500 (0..4)
501 .map(|j| {
502 let lookup = |c0: u32, c1: u32, inflate_by: u32| -> u32 {
513 let c0 = c0 * 255 / (2u32.pow(inflate_by) - 1);
515 let c1 = c1 * 255 / (2u32.pow(inflate_by) - 1);
516
517 match (code >> (j * 2)) & 0x3 {
518 0 => c0,
519 1 => c1,
520 2 => (2 * c0 + c1) / 3,
521 3 => (c0 + 2 * c1) / 3,
522 _ => unreachable!(),
523 }
524 };
525
526 let red0 = (color0 & 0xF800) >> 11;
527 let red1 = (color1 & 0xF800) >> 11;
528 let green0 = (color0 & 0x7E0) >> 5;
529 let green1 = (color1 & 0x7E0) >> 5;
530 let blue0 = color0 & 0x1F;
531 let blue1 = color1 & 0x1F;
532
533
534 let alpha = match (alpha0 > alpha1, (alpha_info >> (3 * (4 * (3 - i) + j))) & 0x07) {
537 (true, 0) => alpha0,
538 (true, 1) => alpha1,
539 (true, 2) => (6 * alpha0 + 1 * alpha1) / 7,
540 (true, 3) => (5 * alpha0 + 2 * alpha1) / 7,
541 (true, 4) => (4 * alpha0 + 3 * alpha1) / 7,
542 (true, 5) => (3 * alpha0 + 4 * alpha1) / 7,
543 (true, 6) => (2 * alpha0 + 5 * alpha1) / 7,
544 (true, 7) => (1 * alpha0 + 6 * alpha1) / 7,
545 (false, 0) => alpha0,
546 (false, 1) => alpha1,
547 (false, 2) => (4 * alpha0 + 1 * alpha1) / 5,
548 (false, 3) => (3 * alpha0 + 2 * alpha1) / 5,
549 (false, 4) => (2 * alpha0 + 3 * alpha1) / 5,
550 (false, 5) => (1 * alpha0 + 4 * alpha1) / 5,
551 (false, 6) => 0,
552 (false, 7) => 255,
553 t => unreachable!(format!("This value should not have occurred: `{:?}`", t)),
554 };
555
556 RGBA {
557 r: lookup(red0, red1, 5) as u8,
558 g: lookup(green0, green1, 6) as u8,
559 b: lookup(blue0, blue1, 5) as u8,
560 a: alpha as u8,
561 }
562 })
563 .collect::<Vec<_>>()
564 })
565 .collect::<Vec<_>>()
566 }
567
568 fn decode_dxt(header: &Header, data_buf: &mut Vec<u8>) -> Vec<Vec<RGBA<u8>>> {
570 let layer_sizes = header.get_layer_sizes();
571
572 layer_sizes
574 .iter()
575 .map(|&(height, width)| {
576 let h = (cmp::max(height, 4) as f32 / 4.0).ceil() as usize * 4;
581 let w = (cmp::max(width, 4) as f32 / 4.0).ceil() as usize * 4;
582
583 let (layer_bytes, chunk_size) = match header.compression {
587 Compression::DXT1 => (h * w / 2, 8),
588 _ => (h * w, 16),
589 };
590
591 let chunk_transform: Box<Fn(&[u8]) -> Vec<RGBA<u8>>> = match header.compression {
595 Compression::DXT1 => Box::new(|chunk|
596 DDS::bytes_to_pixels_dxt1(chunk, header.pixel_format != PixelFormat::Unknown)
597 ),
598 Compression::DXT2 | Compression::DXT3 => Box::new(|chunk|
599 DDS::bytes_to_pixels_dxt3(chunk)
600 ),
601 Compression::DXT4 | Compression::DXT5 => Box::new(|chunk|
602 DDS::bytes_to_pixels_dxt5(chunk)
603 ),
604 _ => unreachable!(format!("This function cannot handle `{:?}` images", header.compression)),
605 };
606
607 data_buf
608 .drain(..layer_bytes)
610 .collect::<Vec<_>>()
611 .chunks(chunk_size)
613 .flat_map(|chunk| chunk_transform(chunk))
617 .collect::<Vec<_>>()
618 .chunks(4 * w)
621 .flat_map(|p| {
622 let mut pixels = Vec::new();
623
624 for i in (0..4).rev() {
625 for j in 0..w / 4 {
626 let block_width = if j + 1 == w / 4 {
630 4 - (w - width)
631 } else {
632 4
633 };
634
635 for k in 0..block_width {
636 pixels.push(p[(i + j * 4) * 4 + k]);
637 }
638 }
639 }
640
641 pixels
642 })
643 .collect::<Vec<_>>()
645 })
646 .collect::<Vec<_>>()
647 }
648
649 pub fn decode<R: io::Read>(buf: &mut R) -> Result<DDS, ParseError> {
652 let header = DDS::parse_header(buf)?;
653
654 let mut data_buf = Vec::new();
655 buf.read_to_end(&mut data_buf)?;
656
657 let layers = match header.compression {
658 Compression::None => {
659 DDS::decode_uncompressed(&header, &mut data_buf)
660 }
661 Compression::DXT1 | Compression::DXT2| Compression::DXT3 | Compression::DXT4 | Compression::DXT5 => {
662 DDS::decode_dxt(&header, &mut data_buf)
663 }
664 _ => {
665 let compression_type = String::from_utf8_lossy(&header.fourcc[..]);
666 return Err(format!("The compression type `{}` is unsupported!", compression_type).into());
667 }
668 };
669
670 Ok(DDS {
671 header,
672 layers,
673 })
674 }
675
676 pub fn encode(pixels: &Vec<RGBA<u8>>, size: (u32, u32), compression: Compression) -> Result<Vec<u8>, EncodeError> {
679 if size.0 * size.1 < pixels.len() as u32 {
681 return Err(format!("Found {} extra bytes!", pixels.len() as u32 - size.0 * size.1).into());
682 }
683
684 if size.0 * size.1 > pixels.len() as u32 {
685 return Err(format!("Need {} extra bytes!", size.0 * size.1 - pixels.len() as u32).into());
686 }
687
688 match compression {
689 Compression::None => {
690 let mut data = b"DDS ".to_vec();
692
693 data.extend(serialize(&RawHeader {
695 size: size.0 * size.1 * 4,
696 flags: 0,
697 height: size.0,
698 width: size.1,
699 pitch_or_linear_size: 0,
700 depth: 0,
701 mipmap_count: 0,
702 reserved: [0; 11],
703 pixel_format: RawPixelFormat {
704 size: 0,
705 flags: 0x41,
706 four_cc: [0; 4],
707 rgb_bit_count: 32,
708 red_bit_mask: 0xFF,
709 green_bit_mask: 0xFF00,
710 blue_bit_mask: 0xFF0000,
711 alpha_bit_mask: 0xFF000000,
712 },
713 caps: 0,
714 caps2: 0,
715 caps3: 0,
716 caps4: 0,
717 reserved2: 0,
718 }, Infinite).unwrap());
719
720 data.extend(pixels.as_bytes());
722
723 Ok(data)
724 }
725 _ => Err(format!("Cannot encode {:?}!", compression).into())
726 }
727
728 }
729}