use crate::{common::Result, Point};
use crate::{point_f, Exceptions};
use super::{BitMatrix, PerspectiveTransform, Quadrilateral};
pub trait GridSampler {
#[allow(clippy::too_many_arguments)]
fn sample_grid_detailed(
&self,
image: &BitMatrix,
dimensionX: u32,
dimensionY: u32,
dst: Quadrilateral,
src: Quadrilateral,
) -> Result<(BitMatrix, [Point; 4])> {
let transform = PerspectiveTransform::quadrilateralToQuadrilateral(dst, src)?;
self.sample_grid(
image,
dimensionX,
dimensionY,
&[SamplerControl::new(dimensionX, dimensionY, transform)],
)
}
fn sample_grid(
&self,
image: &BitMatrix,
dimensionX: u32,
dimensionY: u32,
controls: &[SamplerControl],
) -> Result<(BitMatrix, [Point; 4])> {
if dimensionX == 0 || dimensionY == 0 {
return Err(Exceptions::NOT_FOUND);
}
let mut bits = BitMatrix::new(dimensionX, dimensionY)?;
let mut points = vec![Point::default(); dimensionX as usize];
for y in 0..dimensionY {
let max = points.len();
let i_value = y as f32 + 0.5;
let mut x = 0;
while x < max {
points[x].x = (x as f32) + 0.5;
points[x].y = i_value;
x += 1;
}
controls
.first()
.unwrap()
.transform
.transform_points_single(&mut points);
self.checkAndNudgePoints(image, &mut points)?;
let mut x = 0;
while x < max {
if image
.try_get(points[x].x as u32, points[x].y as u32)
.ok_or(Exceptions::not_found_with(
"index out of bounds, see documentation in file for explanation",
))?
{
bits.set(x as u32, y);
}
x += 1;
}
}
Ok((
bits,
[
Point::default(),
Point::default(),
Point::default(),
Point::default(),
],
))
}
fn checkAndNudgePoints(&self, image: &BitMatrix, points: &mut [Point]) -> Result<()> {
let width = image.getWidth();
let height = image.getHeight();
let mut nudged = true;
let max_offset = points.len() - 1; let mut offset = 0;
while offset < max_offset && nudged {
let x = points[offset].x as i32;
let y = points[offset].y as i32;
if x < -1 || x > width as i32 || y < -1 || y > height as i32 {
return Err(Exceptions::NOT_FOUND);
}
nudged = false;
if x == -1 {
points[offset].x = 0.0;
nudged = true;
} else if x == width as i32 {
points[offset].x = width as f32 - 1.0;
nudged = true;
}
if y == -1 {
points[offset].y = 0.0;
nudged = true;
} else if y == height as i32 {
points[offset].y = height as f32 - 1.0;
nudged = true;
}
offset += 1;
}
nudged = true;
let mut offset = points.len() as isize - 1;
while offset >= 0 && nudged {
let x = points[offset as usize].x as i32;
let y = points[offset as usize].y as i32;
if x < -1 || x > width as i32 || y < -1 || y > height as i32 {
return Err(Exceptions::NOT_FOUND);
}
nudged = false;
if x == -1 {
points[offset as usize].x = 0.0;
nudged = true;
} else if x == width as i32 {
points[offset as usize].x = width as f32 - 1.0;
nudged = true;
}
if y == -1 {
points[offset as usize].y = 0.0;
nudged = true;
} else if y == height as i32 {
points[offset as usize].y = height as f32 - 1.0;
nudged = true;
}
offset += -1;
}
Ok(())
}
}
pub struct SamplerControl {
pub p0: Point,
pub p1: Point,
pub transform: PerspectiveTransform,
}
impl SamplerControl {
pub fn new(width: u32, height: u32, transform: PerspectiveTransform) -> Self {
Self {
p0: point_f(0.0, 0.0),
p1: point_f(width as f32, height as f32),
transform,
}
}
}