use std::convert::TryInto;
use crate::error::{Error, Result};
use crate::Scans;
pub fn scans(input_file: &[u8]) -> Result<Scans> {
let file_size = input_file.len();
if file_size < 48 {
return Err(Error::Format("PNG too small"));
}
let interlace = input_file[28];
let idat_start = find_idat_start(input_file).unwrap_or(38);
Ok(Scans {
metadata_end: Some(37),
frame_render_start: Some(idat_start),
first_scan_end: if interlace != 0 { Some(idat_start + (file_size - idat_start) / 4) } else { None },
good_scan_end: if interlace != 0 { Some(idat_start + (file_size - idat_start) / 2) } else { None },
file_size,
})
}
fn find_idat_start(input_file: &[u8]) -> Option<usize> {
let mut pos = 8;
loop {
let chunk = input_file.get(pos..pos + 12)?;
pos += 12;
if &chunk[4..8] == b"IDAT" {
return Some(pos);
}
let len = u32::from_be_bytes(chunk[..4].try_into().unwrap());
pos += len as usize;
}
}