use crate::{
BlurError, BlurImage, BlurImageMut, EdgeMode2D, KernelShape, Scalar, ThreadingPolicy,
filter_2d, sigma_size,
};
pub fn laplacian_kernel(size: usize) -> Vec<f32> {
if size & 1 == 0 {
panic!("Kernel size must be odd in 'get_laplacian_kernel'!");
}
let center_x = (size / 2) as f32;
let center_y = (size / 2) as f32;
let sigma = sigma_size(size as f32);
let mut kernel = vec![f32::default(); size * size];
let sigma_p_2 = sigma * sigma;
let scale = -1. / (std::f32::consts::PI * sigma_p_2 * sigma_p_2);
let mut sum = 0f32;
for y in 0..size {
for x in 0..size {
let dx = x as f32 - center_x;
let dy = y as f32 - center_y;
let der = -((dx * dx + dy * dy) / (2. * sigma_p_2));
let v = scale * (1. + der) * f32::exp(der);
kernel[y * size + x] = v;
sum += v;
}
}
if sum != 0. {
let scale = 1. / sum;
for item in kernel.iter_mut() {
*item *= scale;
}
}
kernel
}
pub fn laplacian(
image: &BlurImage<u8>,
destination: &mut BlurImageMut<u8>,
edge_modes: EdgeMode2D,
border_constant: Scalar,
threading_policy: ThreadingPolicy,
) -> Result<(), BlurError> {
image.check_layout()?;
destination.check_layout(Some(image))?;
image.size_matches_mut(destination)?;
let kernel = [-1, -1, -1, -1, 8, -1, -1, -1, -1];
filter_2d::<u8, i16>(
image,
destination,
&kernel,
KernelShape::new(3, 3),
edge_modes,
border_constant,
threading_policy,
)
}