use crate::image::GrayFrame;
use crate::imgproc::threshold::otsu_threshold;
#[derive(Debug)]
pub(crate) struct DownGrid {
pub width: usize,
pub height: usize,
pub scale: usize,
pub luma: Vec<u8>,
pub dark: Vec<bool>,
}
impl DownGrid {
pub fn build(frame: &GrayFrame<'_>, scale: usize) -> DownGrid {
let scale = scale.max(1);
let w = frame.width();
let h = frame.height();
let width = (w / scale).max(1);
let height = (h / scale).max(1);
let off = scale / 2;
let mut luma = vec![0u8; width * height];
for dy in 0..height {
let sy = (dy * scale + off).min(h - 1);
let dst = dy * width;
for dx in 0..width {
let sx = (dx * scale + off).min(w - 1);
luma[dst + dx] = frame.get_unchecked(sx, sy);
}
}
let threshold = {
let view = GrayFrame::new(&luma, width, height).expect("reduced dimensions valid");
otsu_threshold(&view)
};
let dark: Vec<bool> = luma.iter().map(|&v| v <= threshold).collect();
DownGrid {
width,
height,
scale,
luma,
dark,
}
}
#[inline]
pub fn dark(&self, x: usize, y: usize) -> bool {
if x >= self.width || y >= self.height {
return false;
}
self.dark[y * self.width + x]
}
#[inline]
pub fn luma(&self, x: usize, y: usize) -> u8 {
if x >= self.width || y >= self.height {
return 0;
}
self.luma[y * self.width + x]
}
}