imagesize/formats/
mod.rs

1pub mod aesprite;
2pub mod bmp;
3pub mod dds;
4pub mod exr;
5pub mod farbfeld;
6pub mod gif;
7pub mod hdr;
8pub mod ico;
9pub mod ilbm;
10pub mod jpeg;
11pub mod jxl;
12pub mod ktx2;
13pub mod png;
14pub mod pnm;
15pub mod psd;
16pub mod qoi;
17pub mod tga;
18pub mod tiff;
19pub mod vtf;
20pub mod webp;
21
22use crate::{container, ImageError, ImageResult, ImageType};
23use std::io::{BufRead, Seek};
24
25pub fn image_type<R: BufRead + Seek>(reader: &mut R) -> ImageResult<ImageType> {
26    let mut header = [0; 12];
27    reader.read_exact(&mut header)?;
28
29    // Currently there are no formats where 1 byte is enough to determine format
30    if header.len() < 2 {
31        return Err(
32            std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "Not enough data").into(),
33        );
34    }
35
36    // This is vaguely organized in what I assume are the most commonly used formats.
37    // I don't know how much this matters for actual execution time.
38    if jpeg::matches(&header) {
39        return Ok(ImageType::Jpeg);
40    }
41
42    if png::matches(&header) {
43        return Ok(ImageType::Png);
44    }
45
46    if gif::matches(&header) {
47        return Ok(ImageType::Gif);
48    }
49
50    if tiff::matches(&header) {
51        return Ok(ImageType::Tiff);
52    }
53
54    if webp::matches(&header) {
55        return Ok(ImageType::Webp);
56    }
57
58    if let Some(c) = container::heif::matches(&header, reader) {
59        return Ok(ImageType::Heif(c));
60    }
61
62    if jxl::matches(&header) {
63        return Ok(ImageType::Jxl);
64    }
65
66    if bmp::matches(&header) {
67        return Ok(ImageType::Bmp);
68    }
69
70    if psd::matches(&header) {
71        return Ok(ImageType::Psd);
72    }
73
74    if ico::matches(&header) {
75        return Ok(ImageType::Ico);
76    }
77
78    if aesprite::matches(&header) {
79        return Ok(ImageType::Aseprite);
80    }
81
82    if exr::matches(&header) {
83        return Ok(ImageType::Exr);
84    }
85
86    if hdr::matches(&header) {
87        return Ok(ImageType::Hdr);
88    }
89
90    if dds::matches(&header) {
91        return Ok(ImageType::Dds);
92    }
93
94    if ktx2::matches(&header) {
95        return Ok(ImageType::Ktx2);
96    }
97
98    if qoi::matches(&header) {
99        return Ok(ImageType::Qoi);
100    }
101
102    if farbfeld::matches(&header) {
103        return Ok(ImageType::Farbfeld);
104    }
105
106    if pnm::matches(&header) {
107        return Ok(ImageType::Pnm);
108    }
109
110    if vtf::matches(&header) {
111        return Ok(ImageType::Vtf);
112    }
113
114    if ilbm::matches(&header) {
115        return Ok(ImageType::Ilbm);
116    }
117
118    // Keep TGA last because it has the highest probability of false positives
119    if tga::matches(&header, reader) {
120        return Ok(ImageType::Tga);
121    }
122
123    Err(ImageError::NotSupported)
124}