use crate::{buffer::Buffer, orientation::Orientation, pixel, view::View};
pub trait Flip<P, C>
where
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
{
fn flip(self, mode: Orientation);
fn flipped(self, mode: Orientation) -> Buffer<P, C, Vec<C>>;
}
impl<'a, P, C, T> Flip<P, C> for T
where
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
T: Into<View<'a, P, C>>,
{
fn flip(self, mode: Orientation) {
it(self, mode)
}
fn flipped(self, mode: Orientation) -> Buffer<P, C, Vec<C>> {
let mut output = self.into().into_owned();
it(&mut output, mode);
output
}
}
pub fn it<'a, P, C, T>(value: T, mode: Orientation)
where
P: pixel::Write<C> + pixel::Read<C>,
C: pixel::Channel,
T: Into<View<'a, P, C>>,
{
let mut view = value.into();
let width = view.width();
let height = view.height();
match mode {
Orientation::Vertical => {
if height <= 1 {
return;
}
for y in 0..height {
let reverse = height - y - 1;
if y >= reverse {
break;
}
for x in 0..width {
let top = view.get(x, y);
let bottom = view.get(x, reverse);
view.set(x, y, &bottom);
view.set(x, reverse, &top);
}
}
}
Orientation::Horizontal => {
if width <= 1 {
return;
}
for x in 0..width {
let reverse = width - x - 1;
if x >= reverse {
break;
}
for y in 0..height {
let left = view.get(x, y);
let right = view.get(reverse, y);
view.set(x, y, &right);
view.set(reverse, y, &left);
}
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::{buffer::Buffer, color::Rgb, orientation::Orientation};
#[test]
fn vertical_none() {
let mut image = Buffer::<Rgb, u8, _>::new(2, 1);
image.set(0, 0, &Rgb::new(1.0, 1.0, 1.0));
image.set(1, 0, &Rgb::new(1.0, 1.0, 1.0));
image.flip(Orientation::Vertical);
assert_eq!(Rgb::new(1.0, 1.0, 1.0), image.get(0, 0));
assert_eq!(Rgb::new(1.0, 1.0, 1.0), image.get(1, 0));
}
#[test]
fn vertical_even() {
let mut image = Buffer::<Rgb, u8, _>::new(2, 2);
image.set(0, 0, &Rgb::new(1.0, 1.0, 1.0));
image.set(1, 0, &Rgb::new(1.0, 1.0, 1.0));
image.set(0, 1, &Rgb::new(0.0, 0.0, 0.0));
image.set(1, 1, &Rgb::new(0.0, 0.0, 0.0));
image.flip(Orientation::Vertical);
assert_eq!(Rgb::new(0.0, 0.0, 0.0), image.get(0, 0));
assert_eq!(Rgb::new(0.0, 0.0, 0.0), image.get(1, 0));
assert_eq!(Rgb::new(1.0, 1.0, 1.0), image.get(0, 1));
assert_eq!(Rgb::new(1.0, 1.0, 1.0), image.get(1, 1));
}
#[test]
fn vertical_odd() {
let mut image = Buffer::<Rgb, u8, _>::new(2, 3);
image.set(0, 0, &Rgb::new(1.0, 1.0, 1.0));
image.set(1, 0, &Rgb::new(1.0, 1.0, 1.0));
image.set(0, 1, &Rgb::new(0.0, 0.0, 0.0));
image.set(1, 1, &Rgb::new(0.0, 0.0, 0.0));
image.set(0, 2, &Rgb::new(0.0, 1.0, 0.0));
image.set(1, 2, &Rgb::new(0.0, 1.0, 0.0));
image.flip(Orientation::Vertical);
assert_eq!(Rgb::new(0.0, 1.0, 0.0), image.get(0, 0));
assert_eq!(Rgb::new(0.0, 1.0, 0.0), image.get(1, 0));
assert_eq!(Rgb::new(0.0, 0.0, 0.0), image.get(0, 1));
assert_eq!(Rgb::new(0.0, 0.0, 0.0), image.get(1, 1));
assert_eq!(Rgb::new(1.0, 1.0, 1.0), image.get(0, 2));
assert_eq!(Rgb::new(1.0, 1.0, 1.0), image.get(1, 2));
}
#[test]
fn horizontal_none() {
let mut image = Buffer::<Rgb, u8, _>::new(1, 2);
image.set(0, 0, &Rgb::new(1.0, 1.0, 1.0));
image.set(0, 1, &Rgb::new(1.0, 1.0, 1.0));
image.flip(Orientation::Horizontal);
assert_eq!(Rgb::new(1.0, 1.0, 1.0), image.get(0, 0));
assert_eq!(Rgb::new(1.0, 1.0, 1.0), image.get(0, 1));
}
#[test]
fn horizontal_even() {
let mut image = Buffer::<Rgb, u8, _>::new(2, 2);
image.set(0, 0, &Rgb::new(1.0, 1.0, 1.0));
image.set(1, 0, &Rgb::new(0.0, 0.0, 0.0));
image.set(0, 1, &Rgb::new(1.0, 1.0, 1.0));
image.set(1, 1, &Rgb::new(0.0, 0.0, 0.0));
image.flip(Orientation::Horizontal);
assert_eq!(Rgb::new(0.0, 0.0, 0.0), image.get(0, 0));
assert_eq!(Rgb::new(1.0, 1.0, 1.0), image.get(1, 0));
assert_eq!(Rgb::new(0.0, 0.0, 0.0), image.get(0, 1));
assert_eq!(Rgb::new(1.0, 1.0, 1.0), image.get(1, 1));
}
#[test]
fn horizontal_odd() {
let mut image = Buffer::<Rgb, u8, _>::new(3, 2);
image.set(0, 0, &Rgb::new(1.0, 1.0, 1.0));
image.set(1, 0, &Rgb::new(0.0, 0.0, 0.0));
image.set(2, 0, &Rgb::new(0.0, 1.0, 0.0));
image.set(0, 1, &Rgb::new(1.0, 1.0, 1.0));
image.set(1, 1, &Rgb::new(0.0, 0.0, 0.0));
image.set(2, 1, &Rgb::new(0.0, 1.0, 0.0));
image.flip(Orientation::Horizontal);
assert_eq!(Rgb::new(0.0, 1.0, 0.0), image.get(0, 0));
assert_eq!(Rgb::new(0.0, 0.0, 0.0), image.get(1, 0));
assert_eq!(Rgb::new(1.0, 1.0, 1.0), image.get(2, 0));
assert_eq!(Rgb::new(0.0, 1.0, 0.0), image.get(0, 1));
assert_eq!(Rgb::new(0.0, 0.0, 0.0), image.get(1, 1));
assert_eq!(Rgb::new(1.0, 1.0, 1.0), image.get(2, 1));
}
}