use crate::{
buffer::Buffer,
color::{ComponentWise, Limited, Rgba},
pixel,
processing::blur,
view,
};
pub trait Sharpen<P, C>
where
P: From<Rgba> + Into<Rgba>,
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
{
fn sharpen(self, sigma: f32, threshold: f32) -> Buffer<P, C, Vec<C>>;
}
impl<'i, P, C, I> Sharpen<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 sharpen(self, sigma: f32, threshold: f32) -> Buffer<P, C, Vec<C>> {
by::<_, P, C, P, C>(self, sigma, threshold)
}
}
#[inline]
pub fn by<'i, I, PI, CI, PO, CO>(input: I, sigma: f32, threshold: f32) -> Buffer<PO, CO, Vec<CO>>
where
I: Into<view::Read<'i, PI, CI>>,
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,
{
let input = input.into();
let mut output = blur::by::<_, PI, CI, PO, CO>(&input, sigma);
for ((_, _, i), (_, _, mut o)) in input.pixels().zip(output.pixels_mut()) {
let a = i.get().into();
let b = o.get().into();
o.set(
&a.component_wise(&b, |a, b| {
let diff = (a - b).abs();
if diff > threshold {
a + diff
}
else {
a
}
})
.clamp()
.into(),
)
}
output
}