Files
rxing/src/common/default_grid_sampler.rs
2023-04-22 16:17:05 -05:00

100 lines
3.5 KiB
Rust

/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// package com.google.zxing.common;
// import com.google.zxing.NotFoundException;
use crate::common::Result;
use crate::{point, Exceptions, Point};
use super::{BitMatrix, GridSampler, SamplerControl};
/**
* @author Sean Owen
*/
#[derive(Default)]
pub struct DefaultGridSampler;
impl GridSampler for DefaultGridSampler {
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);
}
for SamplerControl { p0, p1, transform } in controls {
// To deal with remaining examples (see #251 and #267) of "numercial instabilities" that have not been
// prevented with the Quadrilateral.h:IsConvex() check, we check for all boundary points of the grid to
// be inside.
let isInside =
|p: Point| -> bool { image.is_in(transform.transform_point(p.centered())) };
for y in (p0.y as i32)..(p1.y as i32) {
// for (int y = y0; y < y1; ++y)
if !isInside(point(p0.x, y as f32)) || !isInside(point(p1.x - 1.0, y as f32)) {
return Err(Exceptions::NOT_FOUND);
}
}
for x in (p0.x as i32)..(p1.x as i32) {
// for (int x = x0; x < x1; ++x)
if !isInside(point(x as f32, p0.y)) || !isInside(point(x as f32, p1.y - 1.0)) {
return Err(Exceptions::NOT_FOUND);
}
}
}
let mut bits = BitMatrix::new(dimensionX, dimensionY)?;
for SamplerControl { p0, p1, transform } in controls {
// for (auto&& [x0, x1, y0, y1, mod2Pix] : rois) {
for y in (p0.y as i32)..(p1.y as i32) {
// for (int y = y0; y < y1; ++y)
for x in (p0.x as i32)..(p1.x as i32) {
// for (int x = x0; x < x1; ++x) {
let p = transform.transform_point(Point::from((x, y)).centered()); //mod2Pix(centered(PointI{x, y}));
if image.get_point(p) {
bits.set(x as u32, y as u32);
}
}
}
}
// dbg!(image.to_string());
// dbg!(bits.to_string());
let projectCorner = |p: Point| -> Point {
for SamplerControl { p0, p1, transform } in controls {
if p0.x <= p.x && p.x <= p1.x && p0.y <= p.y && p.y <= p1.y {
return transform.transform_point(p) + point(0.5, 0.5);
}
}
Point::default()
};
let tl = projectCorner(Point::default());
let tr = projectCorner(Point::from((dimensionX, 0)));
let bl = projectCorner(Point::from((dimensionX, dimensionY)));
let br = projectCorner(Point::from((0, dimensionX)));
Ok((bits, [tl,tr,bl,br]))
}
}