use std::io::{Read, Seek, SeekFrom};
use byteorder::{BigEndian, ReadBytesExt};
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Format {
Png,
Jpeg,
Gif,
Webp,
Tiff,
Bmp,
Ico,
Hdr,
Tga,
Xyz,
}
pub fn guess<R: Read + Seek>(mut input: R) -> Option<Format> {
const MAGIC: &'static [(&'static [u8], Format)] = &[
(b"\x89PNG\r\n\x1a\n", Format::Png),
(&[0xff, 0xd8, 0xff], Format::Jpeg),
(b"GIF89a", Format::Gif),
(b"GIF87a", Format::Gif),
(b"WEBP", Format::Webp),
(b"MM.*", Format::Tiff),
(b"II*.", Format::Tiff),
(b"BM", Format::Bmp),
(b"XYZ1", Format::Xyz),
(&[0x00, 0x00, 0x01, 0x00], Format::Ico),
(b"#?RADIANCE", Format::Hdr),
];
let mut result = None;
for &(magic, format) in MAGIC.iter() {
input.seek(SeekFrom::Start(0)).ok()?;
let mut buffer = vec![0; magic.len()];
if input.read_exact(&mut buffer).is_err() {
continue;
}
if buffer == &magic[..] {
result = Some(format);
break;
}
}
if result.is_none() {
input.seek(SeekFrom::Start(1)).ok()?;
let byte = input.read_u32::<BigEndian>().ok()? & 0xfff7ffff;
if byte == 0x01010000 || byte == 0x00020000 || byte == 0x00030000 {
result = Some(Format::Tga);
}
}
input.seek(SeekFrom::Start(0)).ok()?;
result
}