| 1 | use crate::{ |
| 2 | util::{read_u16, read_u32, Endian}, |
| 3 | ImageResult, ImageSize, |
| 4 | }; |
| 5 | use std::io::{BufRead, Seek, SeekFrom}; |
| 6 | |
| 7 | pub fn size<R: BufRead + Seek>(reader: &mut R) -> ImageResult<ImageSize> { |
| 8 | // skip the IFF header |
| 9 | reader.seek(SeekFrom::Start(12))?; |
| 10 | |
| 11 | let mut chunk_id = [0; 4]; |
| 12 | |
| 13 | loop { |
| 14 | reader.read_exact(&mut chunk_id)?; |
| 15 | let chunk_length = read_u32(reader, &Endian::Big)? as i64; |
| 16 | |
| 17 | if &chunk_id == b"BMHD" { |
| 18 | return Ok(ImageSize { |
| 19 | width: read_u16(reader, &Endian::Big)? as usize, |
| 20 | height: read_u16(reader, &Endian::Big)? as usize, |
| 21 | }); |
| 22 | } |
| 23 | |
| 24 | // the BMHD chunk must occur before the BODY chunk |
| 25 | if &chunk_id == b"BODY" { |
| 26 | return Err(crate::ImageError::CorruptedImage); |
| 27 | } |
| 28 | |
| 29 | // skip over the chunk; chunks of odd length have a padding byte |
| 30 | reader.seek(SeekFrom::Current(chunk_length + chunk_length % 2))?; |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | pub fn matches(header: &[u8]) -> bool { |
| 35 | header.len() >= 12 |
| 36 | && &header[0..4] == b"FORM" |
| 37 | && (&header[8..12] == b"ILBM" || &header[8..12] == b"PBM " ) |
| 38 | } |
| 39 | |