use crate::{buffer::Buffer, pixel, view};
pub trait Rotate<P, C>
where
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
{
fn rotate(self, by: f32) -> Buffer<P, C, Vec<C>>;
}
impl<'i, P, C, I> Rotate<P, C> for I
where
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
I: Into<view::Read<'i, P, C>>,
{
#[inline]
fn rotate(self, by: f32) -> Buffer<P, C, Vec<C>> {
it::<_, P, C, P, C>(self, by)
}
}
pub fn it<'i, I, PI, CI, PO, CO>(input: I, by: f32) -> Buffer<PO, CO, Vec<CO>>
where
I: Into<view::Read<'i, PI, CI>>,
PO: From<PI>,
PO: pixel::Write<CO>,
CO: pixel::Channel,
PI: pixel::Read<CI>,
CI: pixel::Channel,
{
let input = input.into();
let by = if by.is_sign_positive() {
by % 360.0
}
else {
360.0 - (by % 360.0)
} as u32;
debug_assert!(by % 90 == 0);
if by == 0 {
return input.convert::<PO, CO>();
}
let mut output: Buffer<PO, CO, _>;
match by {
90 => {
output = Buffer::new(input.height(), input.width());
for (x, y, px) in input.pixels() {
output.set(input.height() - 1 - y, x, &px.get().into());
}
}
180 => {
output = Buffer::new(input.width(), input.height());
for (x, y, px) in input.pixels() {
output.set(input.width() - 1 - x, input.height() - 1 - y, &px.get().into());
}
}
270 => {
output = Buffer::new(input.height(), input.width());
for (x, y, px) in input.pixels() {
output.set(y, input.width() - 1 - x, &px.get().into());
}
}
_ => unreachable!(),
}
output
}