use crate::{ pixel::Pixel, ser::{Sink, Source}, vec2::Vec2, view::View, }; use std::ops::{Index, IndexMut}; #[derive(Debug, Clone)] pub struct Frame { pub size: Vec2, buffer: Vec, } impl Frame { pub fn new(size: Vec2) -> Self { Self { size, buffer: (0..size.x * size.y).map(|_| Pixel::default()).collect(), } } pub fn read(source: &mut impl Source, size: Vec2) -> anyhow::Result { let mut frame = Frame::new(size); for y in 0..size.y { for x in 0..size.x { let pixel = source.get::()?; frame[(x, y)] = pixel; } } Ok(frame) } pub fn write(&self, sink: &mut impl Sink) -> anyhow::Result<()> { for y in 0..self.size.y { for x in 0..self.size.x { sink.put(self[(x, y)])?; } } Ok(()) } pub fn view<'a>(&'a self) -> View<&'a Frame> { View::new(self, Vec2::ZERO, self.size) } pub fn view_mut<'a>(&'a mut self) -> View<&'a mut Frame> { View::new(self, Vec2::ZERO, self.size) } pub fn view_area<'a>(&'a self, offset: Vec2, size: Vec2) -> View<&'a Frame> { View::new(self, offset, size) } pub fn view_area_mut<'a>(&'a mut self, offset: Vec2, size: Vec2) -> View<&'a mut Frame> { View::new(self, offset, size) } } impl Index for Frame { type Output = Pixel; #[inline] fn index(&self, Vec2 { x, y }: Vec2) -> &Self::Output { if x >= 0 && y >= 0 && x < self.size.x && y < self.size.y { &self.buffer[(x + y * self.size.x) as usize] } else { &Pixel::BLACK } } } impl IndexMut for Frame { #[inline] fn index_mut(&mut self, Vec2 { x, y }: Vec2) -> &mut Self::Output { &mut self.buffer[(x + y * self.size.x) as usize] } } impl Index<(isize, isize)> for Frame { type Output = Pixel; #[inline] fn index(&self, (x, y): (isize, isize)) -> &Self::Output { &self[Vec2 { x, y }] } } impl IndexMut<(isize, isize)> for Frame { #[inline] fn index_mut(&mut self, (x, y): (isize, isize)) -> &mut Self::Output { &mut self[Vec2 { x, y }] } }