#[derive(Debug, Copy, Clone)]
pub struct Kernel<'a, K>
where
K: Copy,
{
pub(crate) data: &'a [K],
pub(crate) width: u32,
pub(crate) height: u32,
}
impl<'a, K> Kernel<'a, K>
where
K: Copy,
{
pub const fn new(data: &'a [K], width: u32, height: u32) -> Kernel<'a, K> {
assert!(width > 0 && height > 0, "width and height must be non-zero");
assert!(width * height == data.len() as u32);
Kernel {
data,
width,
height,
}
}
#[inline]
pub fn get(&self, x: u32, y: u32) -> K {
debug_assert!(x < self.width);
debug_assert!(y < self.height);
let at = usize::try_from(y * self.width + x).unwrap();
self.data[at]
}
#[inline]
pub unsafe fn get_unchecked(&self, x: u32, y: u32) -> K {
unsafe {
debug_assert!(x < self.width);
debug_assert!(y < self.height);
let at = usize::try_from(y * self.width + x).unwrap();
debug_assert!(at < self.data.len());
*self.data.get_unchecked(at)
}
}
}
pub const SOBEL_HORIZONTAL_3X3: Kernel<'static, i32> =
Kernel::new(&[-1, 0, 1, -2, 0, 2, -1, 0, 1], 3, 3);
pub const SOBEL_VERTICAL_3X3: Kernel<'static, i32> =
Kernel::new(&[-1, -2, -1, 0, 0, 0, 1, 2, 1], 3, 3);
pub const SCHARR_HORIZONTAL_3X3: Kernel<'static, i32> =
Kernel::new(&[-3, 0, 3, -10, 0, 10, -3, 0, 3], 3, 3);
pub const SCHARR_VERTICAL_3X3: Kernel<'static, i32> =
Kernel::new(&[-3, -10, -3, 0, 0, 0, 3, 10, 3], 3, 3);
pub const PREWITT_HORIZONTAL_3X3: Kernel<'static, i32> =
Kernel::new(&[-1, 0, 1, -1, 0, 1, -1, 0, 1], 3, 3);
pub const PREWITT_VERTICAL_3X3: Kernel<'static, i32> =
Kernel::new(&[-1, -1, -1, 0, 0, 0, 1, 1, 1], 3, 3);
pub const ROBERTS_HORIZONTAL_2X2: Kernel<'static, i32> = Kernel::new(&[1, 0, 0, -1], 2, 2);
pub const ROBERTS_VERTICAL_2X2: Kernel<'static, i32> = Kernel::new(&[0, 1, -1, -0], 2, 2);
pub const LAPLACIAN_3X3: Kernel<'static, i16> = Kernel::new(&[0, 1, 0, 1, -4, 1, 0, 1, 0], 3, 3);