pub type Pixel = (u8, u8, u8); pub struct Image { pub width: u32, pub height: u32, data: Vec, } impl Image { pub fn load(path: impl AsRef) -> Result> { let decoder = png::Decoder::new(std::fs::File::open(path)?); let mut reader = decoder.read_info()?; let mut buf = vec![0u8; reader.output_buffer_size()]; let info = reader.next_frame(buf.as_mut_slice())?; let mut data = Vec::new(); let skip = match info.color_type { png::ColorType::Rgb => 3, png::ColorType::Rgba => 4, other => panic!("Unhandled color type: {:?}", other), }; let rs = buf.iter().step_by(skip); let gs = buf.iter().skip(1).step_by(skip); let bs = buf.iter().skip(2).step_by(skip); for ((r, g), b) in rs.zip(gs).zip(bs) { data.push((*r, *g, *b)) } Ok(Image { width: info.width, height: info.height, data, }) } pub fn iter(&self) -> ImageIterator { ImageIterator { width: self.width, x: 0, y: 0, values: self.data.iter(), } } } pub struct ImageIterator<'a> { width: u32, x: u32, y: u32, values: std::slice::Iter<'a, Pixel>, } impl<'a> Iterator for ImageIterator<'a> { type Item = ((u32, u32), Pixel); fn next(&mut self) -> Option { let px = self.values.next(); if let Some(px) = px { let ret = ((self.x, self.y), *px); self.x += 1; if self.x == self.width { self.x = 0; self.y += 1; } Some(ret) } else { None } } }