use crate::{ format::ser::{Sink, Source}, helpers::{pixel::Pixel, vector::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) } pub fn set(&mut self, pos: Vec2, color: Pixel) { if pos.x >= 0 && pos.y >= 0 && pos.x < self.size.x && pos.y < self.size.y { self[pos] = color } } } 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 Frame { #[inline] pub fn sample(&self, p: Vec2) -> Pixel { self[Vec2 { x: p.x as isize, y: p.y as isize, }] // let fx = p.x.floor() as isize; // let fy = p.y.floor() as isize; // let cx = p.x.ceil() as isize; // let cy = p.y.ceil() as isize; // // TODO dont loose accuracy here // Pixel::average( // Pixel::average(self[Vec2 { x: fx, y: fy }], self[Vec2 { x: fx, y: cy }]), // Pixel::average(self[Vec2 { x: cx, y: fx }], self[Vec2 { x: cx, y: fy }]), // ) } } 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 }] } }