use crate::{
buffer::Buffer,
color::Rgba,
pixel,
processing::{sample, sampler::gaussian},
view,
};
pub trait Blur<P, C>
where
P: From<Rgba> + Into<Rgba>,
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
{
fn blur(self, sigma: f32) -> Buffer<P, C, Vec<C>>;
}
impl<'i, P, C, I> Blur<P, C> for I
where
P: From<Rgba> + Into<Rgba>,
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
I: Into<view::Read<'i, P, C>>,
{
#[inline]
fn blur(self, sigma: f32) -> Buffer<P, C, Vec<C>> {
by::<_, P, C, P, C>(self, sigma)
}
}
#[inline]
pub fn by<'i, I, PI, CI, PO, CO>(input: I, mut sigma: f32) -> Buffer<PO, CO, Vec<CO>>
where
PO: From<Rgba> + Into<Rgba>,
PO: pixel::Read<CO> + pixel::Write<CO>,
CO: pixel::Channel,
PI: Into<Rgba>,
PI: pixel::Read<CI>,
CI: pixel::Channel,
I: Into<view::Read<'i, PI, CI>>,
{
let input = input.into();
if sigma < 0.0 {
sigma = 1.0;
}
let mut tmp = Buffer::<PO, CO, _>::new(input.width(), input.height());
sample::vertically_with(&input, &mut tmp, sigma * 2.0, |x| gaussian::function(x, sigma));
let mut out = Buffer::<PO, CO, _>::new(input.width(), input.height());
sample::horizontally_with(&tmp, &mut out, sigma * 2.0, |x| gaussian::function(x, sigma));
out
}