use crate::kernel::{self, SobelKernel};
use bumpalo::Bump;
use std::time::Instant;
impl std::fmt::Debug for CannyWorkspace {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CannyWorkspace")
.field("width", &self.width)
.field("height", &self.height)
.field("capacity", &self.capacity)
.finish_non_exhaustive()
}
}
pub struct CannyWorkspace {
pub width: usize,
pub height: usize,
pub capacity: usize,
pub buffer_a: Vec<f32>, pub buffer_b: Vec<f32>, pub dir_map: Vec<u8>, pub edge_map: Vec<u8>, pub arena: Bump,
pub(crate) kernel: Box<dyn SobelKernel>,
}
impl CannyWorkspace {
pub fn new(width: usize, height: usize) -> Result<Self, crate::CannyError> {
if width < 3 || height < 3 {
return Err(crate::CannyError::InvalidDimensions { width, height });
}
let t0 = Instant::now();
let capacity = width * height;
let arena_bytes = (capacity / 20) * std::mem::size_of::<usize>();
let ws = Self {
width,
height,
capacity,
buffer_a: vec![0.0f32; capacity],
buffer_b: vec![0.0f32; capacity],
dir_map: vec![0u8; capacity],
edge_map: vec![0u8; capacity],
arena: Bump::with_capacity(arena_bytes),
kernel: kernel::detect(),
};
log::info!(
"[CannyWorkspace::new] {}x{}, ~{} KB, {:?}",
width,
height,
(capacity * 10 + arena_bytes) / 1024,
t0.elapsed()
);
Ok(ws)
}
#[inline(always)]
pub fn reset(&mut self) {
self.arena.reset();
self.edge_map.fill(0);
}
#[inline(always)]
pub(crate) fn kernel(&self) -> &dyn SobelKernel {
self.kernel.as_ref()
}
}