use crate::{Frame, Pixel, Ref, View, P2}; use std::ops::{Add, AddAssign, Index, IndexMut, Sub}; #[cfg(feature = "parallel")] pub use rayon::join; #[cfg(not(feature = "parallel"))] pub fn join(oper_a: A, oper_b: B) -> (RA, RB) where A: FnOnce() -> RA + Send, B: FnOnce() -> RB + Send, RA: Send, RB: Send, { (oper_a(), oper_b()) } impl Frame { pub fn export(&self, view: View) -> Vec { let mut o = vec![]; for y in view.a.y..view.b.y { for x in view.a.x..view.b.x { o.push(self[P2 { x, y }]) } } o } pub fn import(&mut self, view: View, mut source: &[Pixel]) { for y in view.a.y..view.b.y { for x in view.a.x..view.b.x { self[P2 { x, y }] = source[0]; source = &source[1..]; } } assert_eq!(source.len(), 0) } pub fn new(size: P2) -> Self { Self { pixels: vec![Pixel::default(); size.area()], size, } } } impl Ref { #[inline] pub fn apply(mut self, f: F) -> Self { f(&mut self); self } } impl Pixel { pub const BLACK: Pixel = Pixel { r: 0, g: 0, b: 0 }; pub const RED: Pixel = Pixel { r: 255, g: 0, b: 0 }; pub const GREEN: Pixel = Pixel { r: 0, g: 255, b: 0 }; pub const BLUE: Pixel = Pixel { r: 0, g: 0, b: 255 }; } impl AddAssign for P2 { fn add_assign(&mut self, rhs: Self) { self.x += rhs.x; self.y += rhs.y; } } impl Add for Pixel { type Output = Pixel; #[inline] fn add(self, rhs: Self) -> Self::Output { Self { r: self.r + rhs.r, g: self.g + rhs.g, b: self.b + rhs.b, } } } impl Sub for Pixel { type Output = Pixel; #[inline] fn sub(self, rhs: Self) -> Self::Output { Self { r: self.r - rhs.r, g: self.g - rhs.g, b: self.b - rhs.b, } } } impl P2 { pub const ZERO: P2 = P2 { x: 0, y: 0 }; pub const X: P2 = P2 { x: 1, y: 0 }; pub const Y: P2 = P2 { x: 0, y: 1 }; #[inline] pub fn area(&self) -> usize { (self.x * self.y) as usize } } impl View { #[inline] pub fn all(b: P2) -> Self { Self { a: P2::default(), b, } } #[inline] pub fn size(&self) -> P2 { self.b - self.a } } impl Add for View { type Output = View; #[inline] fn add(self, rhs: P2) -> Self::Output { View { a: self.a + rhs, b: self.b + rhs, } } } impl Add for P2 { type Output = P2; #[inline] fn add(self, rhs: Self) -> Self::Output { Self { x: self.x + rhs.x, y: self.y + rhs.y, } } } impl Sub for P2 { type Output = P2; #[inline] fn sub(self, rhs: Self) -> Self::Output { Self { x: self.x - rhs.x, y: self.y - rhs.y, } } } impl Index for Frame { type Output = Pixel; #[inline] fn index(&self, P2 { x, y }: P2) -> &Self::Output { &self .pixels .get(x as usize + (y as usize * self.size.x as usize)) .unwrap_or(&Pixel { r: 0, g: 0, b: 0 }) } } impl IndexMut for Frame { #[inline] fn index_mut(&mut self, P2 { x, y }: P2) -> &mut Self::Output { &mut self.pixels[x as usize + (y as usize * self.size.x as usize)] } } pub trait ToArray { type Output; fn to_array(self) -> [Self::Output; 2]; } impl ToArray for (A, A) { type Output = A; #[inline] fn to_array(self) -> [A; 2] { [self.0, self.1] } }