use std::io::{BufRead, Seek, SeekFrom};
use crate::{
util::{read_u16, Endian},
ImageResult, ImageSize,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum PkmCompression {
Etc1,
Etc2,
Etc2A1,
Etc2A8,
EacR,
EacRg,
EacRSigned,
EacRgSigned,
Unknown,
}
pub fn size<R: BufRead + Seek>(reader: &mut R) -> ImageResult<ImageSize> {
reader.seek(SeekFrom::Start(8))?; let _extended_width = read_u16(reader, &Endian::Big)?;
let _extended_height = read_u16(reader, &Endian::Big)?;
let width = read_u16(reader, &Endian::Big)? as usize;
let height = read_u16(reader, &Endian::Big)? as usize;
Ok(ImageSize { width, height })
}
pub fn matches(header: &[u8]) -> bool {
if header.len() >= 6 {
return header.starts_with(b"PKM ")
&& (header[4..6] == [b'1', b'0'] || header[4..6] == [b'2', b'0']);
}
false
}
pub fn matches_eac(header: &[u8]) -> bool {
if header.len() >= 8
&& header.starts_with(b"PKM ")
&& (header[4..6] == [b'1', b'0'] || header[4..6] == [b'2', b'0'])
{
let data_type = u16::from_be_bytes([header[6], header[7]]);
return matches!(data_type, 0x1608..=0x160B);
}
false
}
pub fn detect_compression<R: BufRead + Seek>(reader: &mut R) -> ImageResult<PkmCompression> {
reader.seek(SeekFrom::Start(6))?; let data_type = read_u16(reader, &Endian::Big)?;
let compression = match data_type {
0x0000 => PkmCompression::Etc1,
0x0001 => PkmCompression::Etc2, 0x0002 => PkmCompression::Etc2A1, 0x0003 => PkmCompression::Etc2A8, 0x0004 => PkmCompression::Etc2A1, 0x0005 => PkmCompression::Etc2A8,
0x1608 => PkmCompression::EacRgSigned, 0x1609 => PkmCompression::EacRSigned, 0x160A => PkmCompression::EacR, 0x160B => PkmCompression::EacRg,
_ => PkmCompression::Unknown,
};
Ok(compression)
}