use crate::{error, util};
use crate::error::ImgProcResult;
use crate::image::{Image, BaseImage};
pub fn erode(input: &Image<u8>, radius: u32) -> ImgProcResult<Image<u8>> {
error::check_grayscale(input)?;
let (width, height) = input.info().wh();
let size = 2 * radius + 1;
let max_sum = (size * size * 255) as f64;
let table = util::generate_summed_area_table(&input.clone().into());
let mut output = Image::blank(input.info());
for y in 0..height {
for x in 0..width {
let mut x_top = x;
let mut x_bot = x;
let mut y_top = y;
let mut y_bot = y;
if x >= radius {
x_top -= radius;
}
if x < width - radius {
x_bot += radius;
}
if y >= radius {
y_top -= radius;
}
if y < height - radius {
y_bot += radius;
}
if util::rectangular_intensity_sum(&table, x_top, y_top, x_bot, y_bot)[0] == max_sum {
output.set_pixel(x, y, &[255]);
}
}
}
Ok(output)
}
pub fn dilate(input: &Image<u8>, radius: u32) -> ImgProcResult<Image<u8>> {
error::check_grayscale(input)?;
let (width, height) = input.info().wh();
let table = util::generate_summed_area_table(&input.clone().into());
let mut output = Image::blank(input.info());
for y in 0..height {
for x in 0..width {
let mut x_top = x;
let mut x_bot = x;
let mut y_top = y;
let mut y_bot = y;
if x >= radius {
x_top -= radius;
}
if x < width - radius {
x_bot += radius;
}
if y >= radius {
y_top -= radius;
}
if y < height - radius {
y_bot += radius;
}
if util::rectangular_intensity_sum(&table, x_top, y_top, x_bot, y_bot)[0] >= 255.0 {
output.set_pixel(x, y, &[255]);
}
}
}
Ok(output)
}
pub fn majority(input: &Image<u8>, radius: u32) -> ImgProcResult<Image<u8>> {
error::check_grayscale(input)?;
let (width, height) = input.info().wh();
let table = util::generate_summed_area_table(&input.clone().into());
let mut output = Image::blank(input.info());
for y in 0..height {
for x in 0..width {
let mut x_top = x;
let mut x_bot = x;
let mut y_top = y;
let mut y_bot = y;
if x >= radius {
x_top -= radius;
}
if x < width - radius {
x_bot += radius;
}
if y >= radius {
y_top -= radius;
}
if y < height - radius {
y_bot += radius;
}
if util::rectangular_intensity_sum(&table, x_top, y_top, x_bot, y_bot)[0] >= 255.0 {
output.set_pixel(x, y, &[255]);
}
}
}
Ok(output)
}
pub fn open(input: &Image<u8>, radius: u32) -> ImgProcResult<Image<u8>> {
Ok(dilate(&erode(input, radius)?, radius)?)
}
pub fn close(input: &Image<u8>, radius: u32) -> ImgProcResult<Image<u8>> {
Ok(erode(&dilate(input, radius)?, radius)?)
}
#[allow(unused_parens)]
pub fn gradient(input: &Image<u8>, radius: u32) -> ImgProcResult<Image<u8>> {
error::check_grayscale(input)?;
let (width, height) = input.info().wh();
let size = 2 * radius + 1;
let max_sum = (size * size * 255) as f64;
let table = util::generate_summed_area_table(&input.clone().into());
let mut output = Image::blank(input.info());
for y in 0..height {
for x in 0..width {
let mut x_top = x;
let mut x_bot = x;
let mut y_top = y;
let mut y_bot = y;
if x >= radius {
x_top -= radius;
}
if x < width - radius {
x_bot += radius;
}
if y >= radius {
y_top -= radius;
}
if y < height - radius {
y_bot += radius;
}
let sum = util::rectangular_intensity_sum(&table, x_top, y_top, x_bot, y_bot)[0];
let erode = (sum == max_sum);
let dilate = (sum >= 255.0);
if erode ^ dilate {
output.set_pixel(x, y, &[255]);
}
}
}
Ok(output)
}