ai_imagesize/container/
atc.rs1use no_std_io::io::{BufRead, Seek, SeekFrom};
2
3use crate::{
4 util::{read_u16, read_u32, Endian},
5 ImageResult, ImageSize,
6};
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub enum AtcCompression {
13 Rgb,
15 RgbaExplicit,
17 RgbaInterpolated,
19 Unknown,
21}
22
23pub fn size<R: BufRead + Seek>(reader: &mut R) -> ImageResult<ImageSize> {
24 let mut header = [0u8; 4];
29 reader.read_exact(&mut header)?;
30
31 if header == *b"DDS " {
32 reader.seek(SeekFrom::Start(12))?;
34 let height = read_u32(reader, &Endian::Little)? as usize;
35 let width = read_u32(reader, &Endian::Little)? as usize;
36 return Ok(ImageSize { width, height });
37 }
38
39 reader.seek(SeekFrom::Start(0))?;
41 let mut pkm_header = [0u8; 8];
42 reader.read_exact(&mut pkm_header)?;
43
44 if pkm_header.starts_with(b"PKM ")
45 && (pkm_header[4..6] == [b'1', b'0'] || pkm_header[4..6] == [b'2', b'0'])
46 {
47 let data_type = u16::from_be_bytes([pkm_header[6], pkm_header[7]]);
49 if matches!(data_type, 0x8C92 | 0x8C93 | 0x87EE) {
50 reader.seek(SeekFrom::Start(8))?; let _extended_width = read_u16(reader, &Endian::Big)?;
53 let _extended_height = read_u16(reader, &Endian::Big)?;
54 let width = read_u16(reader, &Endian::Big)? as usize;
55 let height = read_u16(reader, &Endian::Big)? as usize;
56 return Ok(ImageSize { width, height });
57 }
58 }
59
60 reader.seek(SeekFrom::Start(4))?;
62 let height = read_u32(reader, &Endian::Little)? as usize;
63 let width = read_u32(reader, &Endian::Little)? as usize;
64 Ok(ImageSize { width, height })
65}
66
67pub fn matches(header: &[u8]) -> bool {
68 if header.len() >= 8
71 && header.starts_with(b"PKM ")
72 && (header[4..6] == [b'1', b'0'] || header[4..6] == [b'2', b'0'])
73 {
74 let data_type = u16::from_be_bytes([header[6], header[7]]);
75 return matches!(data_type, 0x8C92 | 0x8C93 | 0x87EE);
76 }
77
78 false
79}
80
81pub fn detect_compression<R: BufRead + Seek>(reader: &mut R) -> ImageResult<AtcCompression> {
82 let mut header = [0u8; 8];
84 reader.seek(SeekFrom::Start(0))?;
85 reader.read_exact(&mut header)?;
86
87 if header.starts_with(b"PKM ") && (header[4..6] == [b'1', b'0'] || header[4..6] == [b'2', b'0'])
88 {
89 let data_type = u16::from_be_bytes([header[6], header[7]]);
90 let compression = match data_type {
91 0x8C92 => AtcCompression::Rgb, 0x8C93 => AtcCompression::RgbaExplicit, 0x87EE => AtcCompression::RgbaInterpolated, _ => AtcCompression::Unknown,
95 };
96 return Ok(compression);
97 }
98
99 if header[0..4] == *b"DDS " {
101 return Ok(AtcCompression::Unknown); }
105
106 Ok(AtcCompression::Unknown)
107}