use crate::{pixel::Pixel, ser::Source}; use std::{ io, ops::{Index, IndexMut}, }; pub struct Frame { pub size: (usize, usize), buffer: Vec>, } impl Frame { pub fn new(size: (usize, usize)) -> Self { Self { size, buffer: (0..size.0) .map(|_| (0..size.1).map(|_| Pixel::default()).collect()) .collect(), } } pub fn read(source: &mut impl Source, size: (usize, usize)) -> io::Result { let mut frame = Frame::new(size); for x in 0..size.0 { for y in 0..size.1 { let pixel = source.get::()?; frame[(x, y)] = pixel; } } Ok(frame) } pub fn view<'a>(&'a self, offset: (usize, usize), size: (usize, usize)) -> View<'a> { View::new(self, offset, size) } } impl Index<(usize, usize)> for Frame { type Output = Pixel; #[inline] fn index(&self, (x, y): (usize, usize)) -> &Self::Output { &self.buffer[x][y] } } impl IndexMut<(usize, usize)> for Frame { #[inline] fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output { &mut self.buffer[x][y] } } pub struct View<'a> { pub frame: &'a Frame, pub offset: (usize, usize), pub size: (usize, usize), } impl<'a> View<'a> { pub fn new(frame: &'a Frame, offset: (usize, usize), size: (usize, usize)) -> Self { Self { frame, offset, size, } } pub fn diff(va: &Self, vb: &Self) -> f64 { assert_eq!(va.size, vb.size); let mut acc = 0.0; for x in 0..va.size.0 { for y in 0..va.size.1 { let a = va[(x, y)]; let b = vb[(x, y)]; acc += Pixel::distance(a, b); } } acc } pub fn split(&self) -> [Self; 2] { let vert = self.size.0 > self.size.1; [ Self { frame: self.frame, offset: self.offset, size: if vert { (self.size.0 / 2, self.size.1) } else { (self.size.0, self.size.1 / 2) }, }, Self { frame: self.frame, offset: if vert { (self.offset.0 + self.size.0 / 2, self.offset.1) } else { (self.offset.0, self.offset.1 + self.size.1 / 2) }, size: if vert { (self.size.0 - self.size.0 / 2, self.size.1) } else { (self.size.0, self.size.1 - self.size.1 / 2) }, }, ] } } impl Index<(usize, usize)> for View<'_> { type Output = Pixel; #[inline] fn index(&self, (x, y): (usize, usize)) -> &Self::Output { &self.frame[(x + self.offset.0, y + self.offset.1)] } }