mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-25 20:02:34 +00:00
Merge pull request #13 from Asha20/pr/point_refactor
Improve RXingResultPoint usage
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
// import com.google.zxing.aztec.encoder.EncoderTest;
|
||||
|
||||
// import com.google.zxing.FormatException;
|
||||
// import com.google.zxing.RXingResultPoint;
|
||||
// import com.google.zxing.Point;
|
||||
// import com.google.zxing.aztec.AztecDetectorRXingResult;
|
||||
// import com.google.zxing.common.BitArray;
|
||||
// import com.google.zxing.common.BitMatrix;
|
||||
@@ -29,7 +29,7 @@
|
||||
use crate::{
|
||||
aztec::shared_test_methods::{stripSpace, toBitArray, toBooleanArray},
|
||||
common::BitMatrix,
|
||||
RXingResultPoint,
|
||||
Point,
|
||||
};
|
||||
|
||||
use super::{aztec_detector_result::AztecDetectorRXingResult, decoder};
|
||||
@@ -38,7 +38,7 @@ use super::{aztec_detector_result::AztecDetectorRXingResult, decoder};
|
||||
* Tests {@link Decoder}.
|
||||
*/
|
||||
|
||||
const NO_POINTS: [RXingResultPoint; 4] = [RXingResultPoint { x: 0.0, y: 0.0 }; 4];
|
||||
const NO_POINTS: [Point; 4] = [Point { x: 0.0, y: 0.0 }; 4];
|
||||
|
||||
#[test]
|
||||
fn test_high_level_decode() {
|
||||
|
||||
@@ -39,7 +39,7 @@ use rand::Rng;
|
||||
use crate::{aztec::decoder, common::BitMatrix, exceptions::Exceptions};
|
||||
|
||||
use super::{
|
||||
detector::{self, Detector, Point},
|
||||
detector::{self, AztecPoint, Detector},
|
||||
encoder::{self, AztecCode},
|
||||
};
|
||||
|
||||
@@ -261,7 +261,7 @@ fn clone(input: &BitMatrix) -> BitMatrix {
|
||||
result
|
||||
}
|
||||
|
||||
fn get_orientation_points(code: &AztecCode) -> Vec<Point> {
|
||||
fn get_orientation_points(code: &AztecCode) -> Vec<AztecPoint> {
|
||||
let center = code.getMatrix().getWidth() as i32 / 2;
|
||||
let offset = if code.isCompact() { 5 } else { 7 };
|
||||
let mut result = Vec::new();
|
||||
@@ -271,12 +271,15 @@ fn get_orientation_points(code: &AztecCode) -> Vec<Point> {
|
||||
let mut ySign: i32 = -1;
|
||||
while ySign <= 1 {
|
||||
// for (int ySign = -1; ySign <= 1; ySign += 2) {
|
||||
result.push(Point::new(center + xSign * offset, center + ySign * offset));
|
||||
result.push(Point::new(
|
||||
result.push(AztecPoint::new(
|
||||
center + xSign * offset,
|
||||
center + ySign * offset,
|
||||
));
|
||||
result.push(AztecPoint::new(
|
||||
center + xSign * (offset - 1),
|
||||
center + ySign * offset,
|
||||
));
|
||||
result.push(Point::new(
|
||||
result.push(AztecPoint::new(
|
||||
center + xSign * offset,
|
||||
center + ySign * (offset - 1),
|
||||
));
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::{
|
||||
encoder::HighLevelEncoder,
|
||||
shared_test_methods::{stripSpace, toBitArray, toBooleanArray},
|
||||
},
|
||||
BarcodeFormat, EncodeHintType, EncodeHintValue, RXingResultPoint,
|
||||
BarcodeFormat, EncodeHintType, EncodeHintValue, Point,
|
||||
};
|
||||
|
||||
use super::{encoder::aztec_encoder, AztecWriter};
|
||||
@@ -50,7 +50,7 @@ const WINDOWS_1252: EncodingRef = encoding::all::WINDOWS_1252; //Charset.forName
|
||||
|
||||
// const DOTX: &str = "[^.X]";
|
||||
// const SPACES: &str = "\\s+";
|
||||
const NO_POINTS: [RXingResultPoint; 4] = [RXingResultPoint { x: 0.0, y: 0.0 }; 4];
|
||||
const NO_POINTS: [Point; 4] = [Point { x: 0.0, y: 0.0 }; 4];
|
||||
|
||||
// real life tests
|
||||
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
// package com.google.zxing.aztec;
|
||||
|
||||
// import com.google.zxing.RXingResultPoint;
|
||||
// import com.google.zxing.Point;
|
||||
// import com.google.zxing.common.BitMatrix;
|
||||
// import com.google.zxing.common.DetectorRXingResult;
|
||||
|
||||
use crate::{
|
||||
common::{BitMatrix, DetectorRXingResult},
|
||||
RXingResultPoint,
|
||||
Point,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -33,7 +33,7 @@ use crate::{
|
||||
*/
|
||||
pub struct AztecDetectorRXingResult {
|
||||
bits: BitMatrix,
|
||||
points: [RXingResultPoint; 4],
|
||||
points: [Point; 4],
|
||||
compact: bool,
|
||||
nbDatablocks: u32,
|
||||
nbLayers: u32,
|
||||
@@ -44,7 +44,7 @@ impl DetectorRXingResult for AztecDetectorRXingResult {
|
||||
&self.bits
|
||||
}
|
||||
|
||||
fn getPoints(&self) -> &[RXingResultPoint] {
|
||||
fn getPoints(&self) -> &[Point] {
|
||||
&self.points
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ impl DetectorRXingResult for AztecDetectorRXingResult {
|
||||
impl AztecDetectorRXingResult {
|
||||
pub fn new(
|
||||
bits: BitMatrix,
|
||||
points: [RXingResultPoint; 4],
|
||||
points: [Point; 4],
|
||||
compact: bool,
|
||||
nbDatablocks: u32,
|
||||
nbLayers: u32,
|
||||
|
||||
@@ -92,7 +92,7 @@ impl Reader for AztecReader {
|
||||
{
|
||||
// if let DecodeHintValue::NeedResultPointCallback(cb) = rpcb {
|
||||
for point in points {
|
||||
cb(point);
|
||||
cb(*point);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ use std::fmt;
|
||||
|
||||
use crate::{
|
||||
common::{
|
||||
detector::{MathUtils, WhiteRectangleDetector},
|
||||
detector::WhiteRectangleDetector,
|
||||
reedsolomon::{self, ReedSolomonDecoder},
|
||||
BitMatrix, DefaultGridSampler, GridSampler, Result,
|
||||
},
|
||||
exceptions::Exceptions,
|
||||
RXingResultPoint, ResultPoint,
|
||||
point, Point,
|
||||
};
|
||||
|
||||
use super::aztec_detector_result::AztecDetectorRXingResult;
|
||||
@@ -94,10 +94,10 @@ impl<'a> Detector<'_> {
|
||||
// 4. Sample the grid
|
||||
let bits = self.sample_grid(
|
||||
self.image,
|
||||
&bulls_eye_corners[self.shift as usize % 4],
|
||||
&bulls_eye_corners[(self.shift as usize + 1) % 4],
|
||||
&bulls_eye_corners[(self.shift as usize + 2) % 4],
|
||||
&bulls_eye_corners[(self.shift as usize + 3) % 4],
|
||||
bulls_eye_corners[self.shift as usize % 4],
|
||||
bulls_eye_corners[(self.shift as usize + 1) % 4],
|
||||
bulls_eye_corners[(self.shift as usize + 2) % 4],
|
||||
bulls_eye_corners[(self.shift as usize + 3) % 4],
|
||||
)?;
|
||||
|
||||
// 5. Get the corners of the matrix.
|
||||
@@ -118,21 +118,21 @@ impl<'a> Detector<'_> {
|
||||
* @param bullsEyeCorners the array of bull's eye corners
|
||||
* @throws NotFoundException in case of too many errors or invalid parameters
|
||||
*/
|
||||
fn extractParameters(&mut self, bulls_eye_corners: &[RXingResultPoint]) -> Result<()> {
|
||||
if !self.is_valid(&bulls_eye_corners[0])
|
||||
|| !self.is_valid(&bulls_eye_corners[1])
|
||||
|| !self.is_valid(&bulls_eye_corners[2])
|
||||
|| !self.is_valid(&bulls_eye_corners[3])
|
||||
fn extractParameters(&mut self, bulls_eye_corners: &[Point]) -> Result<()> {
|
||||
if !self.is_valid(bulls_eye_corners[0])
|
||||
|| !self.is_valid(bulls_eye_corners[1])
|
||||
|| !self.is_valid(bulls_eye_corners[2])
|
||||
|| !self.is_valid(bulls_eye_corners[3])
|
||||
{
|
||||
return Err(Exceptions::notFoundWith("no valid points"));
|
||||
}
|
||||
let length = 2 * self.nb_center_layers;
|
||||
// Get the bits around the bull's eye
|
||||
let sides = [
|
||||
self.sample_line(&bulls_eye_corners[0], &bulls_eye_corners[1], length), // Right side
|
||||
self.sample_line(&bulls_eye_corners[1], &bulls_eye_corners[2], length), // Bottom
|
||||
self.sample_line(&bulls_eye_corners[2], &bulls_eye_corners[3], length), // Left side
|
||||
self.sample_line(&bulls_eye_corners[3], &bulls_eye_corners[0], length), // Top
|
||||
self.sample_line(bulls_eye_corners[0], bulls_eye_corners[1], length), // Right side
|
||||
self.sample_line(bulls_eye_corners[1], bulls_eye_corners[2], length), // Bottom
|
||||
self.sample_line(bulls_eye_corners[2], bulls_eye_corners[3], length), // Left side
|
||||
self.sample_line(bulls_eye_corners[3], bulls_eye_corners[0], length), // Top
|
||||
];
|
||||
|
||||
// bullsEyeCorners[shift] is the corner of the bulls'eye that has three
|
||||
@@ -262,7 +262,7 @@ impl<'a> Detector<'_> {
|
||||
* @return The corners of the bull-eye
|
||||
* @throws NotFoundException If no valid bull-eye can be found
|
||||
*/
|
||||
fn get_bulls_eye_corners(&mut self, pCenter: Point) -> Result<[RXingResultPoint; 4]> {
|
||||
fn get_bulls_eye_corners(&mut self, pCenter: AztecPoint) -> Result<[Point; 4]> {
|
||||
let mut pina = pCenter;
|
||||
let mut pinb = pCenter;
|
||||
let mut pinc = pCenter;
|
||||
@@ -285,8 +285,8 @@ impl<'a> Detector<'_> {
|
||||
//c b
|
||||
|
||||
if self.nb_center_layers > 2 {
|
||||
let q: f32 = Self::distance_points(&poutd, &pouta) * self.nb_center_layers as f32
|
||||
/ (Self::distance_points(&pind, &pina) * (self.nb_center_layers + 2) as f32);
|
||||
let q: f32 = Self::distance_points(poutd, pouta) * self.nb_center_layers as f32
|
||||
/ (Self::distance_points(pind, pina) * (self.nb_center_layers + 2) as f32);
|
||||
|
||||
// let q: f32 = Self::distance(
|
||||
// &poutd.to_rxing_result_point(),
|
||||
@@ -321,14 +321,10 @@ impl<'a> Detector<'_> {
|
||||
|
||||
// Expand the square by .5 pixel in each direction so that we're on the border
|
||||
// between the white square and the black square
|
||||
let pinax =
|
||||
RXingResultPoint::new(pina.get_x() as f32 + 0.5f32, pina.get_y() as f32 - 0.5f32);
|
||||
let pinbx =
|
||||
RXingResultPoint::new(pinb.get_x() as f32 + 0.5f32, pinb.get_y() as f32 + 0.5f32);
|
||||
let pincx =
|
||||
RXingResultPoint::new(pinc.get_x() as f32 - 0.5f32, pinc.get_y() as f32 + 0.5f32);
|
||||
let pindx =
|
||||
RXingResultPoint::new(pind.get_x() as f32 - 0.5f32, pind.get_y() as f32 - 0.5f32);
|
||||
let pinax = point(pina.get_x() as f32 + 0.5f32, pina.get_y() as f32 - 0.5f32);
|
||||
let pinbx = point(pinb.get_x() as f32 + 0.5f32, pinb.get_y() as f32 + 0.5f32);
|
||||
let pincx = point(pinc.get_x() as f32 - 0.5f32, pinc.get_y() as f32 + 0.5f32);
|
||||
let pindx = point(pind.get_x() as f32 - 0.5f32, pind.get_y() as f32 - 0.5f32);
|
||||
|
||||
// Expand the square so that its corners are the centers of the points
|
||||
// just outside the bull's eye.
|
||||
@@ -344,11 +340,11 @@ impl<'a> Detector<'_> {
|
||||
*
|
||||
* @return the center point
|
||||
*/
|
||||
fn get_matrix_center(&self) -> Point {
|
||||
let mut point_a = RXingResultPoint::default(); // { x: 0.0, y: 0.0 };
|
||||
let mut point_b = RXingResultPoint::default(); // { x: 0.0, y: 0.0 };
|
||||
let mut point_c = RXingResultPoint::default(); // { x: 0.0, y: 0.0 };
|
||||
let mut point_d = RXingResultPoint::default(); // { x: 0.0, y: 0.0 };
|
||||
fn get_matrix_center(&self) -> AztecPoint {
|
||||
let mut point_a = Point::default();
|
||||
let mut point_b = Point::default();
|
||||
let mut point_c = Point::default();
|
||||
let mut point_d = Point::default();
|
||||
|
||||
let mut fnd = false;
|
||||
|
||||
@@ -369,16 +365,16 @@ impl<'a> Detector<'_> {
|
||||
let cx: i32 = (self.image.getWidth() / 2) as i32;
|
||||
let cy: i32 = (self.image.getHeight() / 2) as i32;
|
||||
point_a = self
|
||||
.get_first_different(&Point::new(cx + 7, cy - 7), false, 1, -1)
|
||||
.get_first_different(&AztecPoint::new(cx + 7, cy - 7), false, 1, -1)
|
||||
.into();
|
||||
point_b = self
|
||||
.get_first_different(&Point::new(cx + 7, cy + 7), false, 1, 1)
|
||||
.get_first_different(&AztecPoint::new(cx + 7, cy + 7), false, 1, 1)
|
||||
.into();
|
||||
point_c = self
|
||||
.get_first_different(&Point::new(cx - 7, cy + 7), false, -1, 1)
|
||||
.get_first_different(&AztecPoint::new(cx - 7, cy + 7), false, -1, 1)
|
||||
.into();
|
||||
point_d = self
|
||||
.get_first_different(&Point::new(cx - 7, cy - 7), false, -1, -1)
|
||||
.get_first_different(&AztecPoint::new(cx - 7, cy - 7), false, -1, -1)
|
||||
.into();
|
||||
}
|
||||
// try {
|
||||
@@ -395,20 +391,16 @@ impl<'a> Detector<'_> {
|
||||
// // In that case, surely in the bull's eye, we try to expand the rectangle.
|
||||
// int cx = image.getWidth() / 2;
|
||||
// int cy = image.getHeight() / 2;
|
||||
// pointA = getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toRXingResultPoint();
|
||||
// pointB = getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toRXingResultPoint();
|
||||
// pointC = getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toRXingResultPoint();
|
||||
// pointD = getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toRXingResultPoint();
|
||||
// pointA = getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toPoint();
|
||||
// pointB = getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toPoint();
|
||||
// pointC = getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toPoint();
|
||||
// pointD = getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toPoint();
|
||||
|
||||
// }
|
||||
|
||||
//Compute the center of the rectangle
|
||||
let mut cx = MathUtils::round(
|
||||
(point_a.getX() + point_d.getX() + point_b.getX() + point_c.getX()) / 4.0f32,
|
||||
);
|
||||
let mut cy = MathUtils::round(
|
||||
(point_a.getY() + point_d.getY() + point_b.getY() + point_c.getY()) / 4.0f32,
|
||||
);
|
||||
let mut cx = ((point_a.x + point_d.x + point_b.x + point_c.x) / 4.0).round() as i32;
|
||||
let mut cy = ((point_a.y + point_d.y + point_b.y + point_c.y) / 4.0).round() as i32;
|
||||
|
||||
// Redetermine the white rectangle starting from previously computed center.
|
||||
// This will ensure that we end up with a white rectangle in center bull's eye
|
||||
@@ -427,20 +419,20 @@ impl<'a> Detector<'_> {
|
||||
// In that case we try to expand the rectangle.
|
||||
if !fnd {
|
||||
point_a = self
|
||||
.get_first_different(&Point::new(cx + 7, cy - 7), false, 1, -1)
|
||||
.get_first_different(&AztecPoint::new(cx + 7, cy - 7), false, 1, -1)
|
||||
.into();
|
||||
point_b = self
|
||||
.get_first_different(&Point::new(cx + 7, cy + 7), false, 1, 1)
|
||||
.get_first_different(&AztecPoint::new(cx + 7, cy + 7), false, 1, 1)
|
||||
.into();
|
||||
point_c = self
|
||||
.get_first_different(&Point::new(cx - 7, cy + 7), false, -1, 1)
|
||||
.get_first_different(&AztecPoint::new(cx - 7, cy + 7), false, -1, 1)
|
||||
.into();
|
||||
point_d = self
|
||||
.get_first_different(&Point::new(cx - 7, cy - 7), false, -1, -1)
|
||||
.get_first_different(&AztecPoint::new(cx - 7, cy - 7), false, -1, -1)
|
||||
.into();
|
||||
}
|
||||
// try {
|
||||
// RXingResultPoint[] cornerPoints = new WhiteRectangleDetector(image, 15, cx, cy).detect();
|
||||
// Point[] cornerPoints = new WhiteRectangleDetector(image, 15, cx, cy).detect();
|
||||
// pointA = cornerPoints[0];
|
||||
// pointB = cornerPoints[1];
|
||||
// pointC = cornerPoints[2];
|
||||
@@ -448,21 +440,17 @@ impl<'a> Detector<'_> {
|
||||
// } catch (NotFoundException e) {
|
||||
// // This exception can be in case the initial rectangle is white
|
||||
// // In that case we try to expand the rectangle.
|
||||
// pointA = getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toRXingResultPoint();
|
||||
// pointB = getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toRXingResultPoint();
|
||||
// pointC = getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toRXingResultPoint();
|
||||
// pointD = getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toRXingResultPoint();
|
||||
// pointA = getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toPoint();
|
||||
// pointB = getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toPoint();
|
||||
// pointC = getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toPoint();
|
||||
// pointD = getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toPoint();
|
||||
// }
|
||||
|
||||
// Recompute the center of the rectangle
|
||||
cx = MathUtils::round(
|
||||
(point_a.getX() + point_d.getX() + point_b.getX() + point_c.getX()) / 4.0f32,
|
||||
);
|
||||
cy = MathUtils::round(
|
||||
(point_a.getY() + point_d.getY() + point_b.getY() + point_c.getY()) / 4.0f32,
|
||||
);
|
||||
cx = ((point_a.x + point_d.x + point_b.x + point_c.x) / 4.0).round() as i32;
|
||||
cy = ((point_a.y + point_d.y + point_b.y + point_c.y) / 4.0).round() as i32;
|
||||
|
||||
Point::new(cx, cy)
|
||||
AztecPoint::new(cx, cy)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -471,10 +459,7 @@ impl<'a> Detector<'_> {
|
||||
* @param bullsEyeCorners the array of bull's eye corners
|
||||
* @return the array of aztec code corners
|
||||
*/
|
||||
fn get_matrix_corner_points(
|
||||
&self,
|
||||
bulls_eye_corners: &[RXingResultPoint],
|
||||
) -> [RXingResultPoint; 4] {
|
||||
fn get_matrix_corner_points(&self, bulls_eye_corners: &[Point]) -> [Point; 4] {
|
||||
Self::expand_square(
|
||||
bulls_eye_corners,
|
||||
2 * self.nb_center_layers,
|
||||
@@ -490,10 +475,10 @@ impl<'a> Detector<'_> {
|
||||
fn sample_grid(
|
||||
&self,
|
||||
image: &BitMatrix,
|
||||
top_left: &RXingResultPoint,
|
||||
top_right: &RXingResultPoint,
|
||||
bottom_right: &RXingResultPoint,
|
||||
bottom_left: &RXingResultPoint,
|
||||
top_left: Point,
|
||||
top_right: Point,
|
||||
bottom_right: Point,
|
||||
bottom_left: Point,
|
||||
) -> Result<BitMatrix> {
|
||||
let sampler = DefaultGridSampler::default();
|
||||
let dimension = self.get_dimension();
|
||||
@@ -513,14 +498,14 @@ impl<'a> Detector<'_> {
|
||||
high, // bottomright
|
||||
low,
|
||||
high, // bottomleft
|
||||
top_left.getX(),
|
||||
top_left.getY(),
|
||||
top_right.getX(),
|
||||
top_right.getY(),
|
||||
bottom_right.getX(),
|
||||
bottom_right.getY(),
|
||||
bottom_left.getX(),
|
||||
bottom_left.getY(),
|
||||
top_left.x,
|
||||
top_left.y,
|
||||
top_right.x,
|
||||
top_right.y,
|
||||
bottom_right.x,
|
||||
bottom_right.y,
|
||||
bottom_left.x,
|
||||
bottom_left.y,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -532,20 +517,20 @@ impl<'a> Detector<'_> {
|
||||
* @param size number of bits
|
||||
* @return the array of bits as an int (first bit is high-order bit of result)
|
||||
*/
|
||||
fn sample_line(&self, p1: &RXingResultPoint, p2: &RXingResultPoint, size: u32) -> u32 {
|
||||
fn sample_line(&self, p1: Point, p2: Point, size: u32) -> u32 {
|
||||
let mut result = 0;
|
||||
|
||||
let d = Self::distance(p1, p2);
|
||||
let module_size = d / size as f32;
|
||||
let px = p1.getX();
|
||||
let py = p1.getY();
|
||||
let dx = module_size * (p2.getX() - p1.getX()) / d;
|
||||
let dy = module_size * (p2.getY() - p1.getY()) / d;
|
||||
let px = p1.x;
|
||||
let py = p1.y;
|
||||
let dx = module_size * (p2.x - p1.x) / d;
|
||||
let dy = module_size * (p2.y - p1.y) / d;
|
||||
for i in 0..size {
|
||||
// for (int i = 0; i < size; i++) {
|
||||
if self.image.get(
|
||||
MathUtils::round(px + i as f32 * dx) as u32,
|
||||
MathUtils::round(py + i as f32 * dy) as u32,
|
||||
(px + i as f32 * dx).round() as u32,
|
||||
(py + i as f32 * dy).round() as u32,
|
||||
) {
|
||||
result |= 1 << (size - i - 1);
|
||||
}
|
||||
@@ -557,48 +542,54 @@ impl<'a> Detector<'_> {
|
||||
* @return true if the border of the rectangle passed in parameter is compound of white points only
|
||||
* or black points only
|
||||
*/
|
||||
fn is_white_or_black_rectangle(&self, p1: &Point, p2: &Point, p3: &Point, p4: &Point) -> bool {
|
||||
fn is_white_or_black_rectangle(
|
||||
&self,
|
||||
p1: &AztecPoint,
|
||||
p2: &AztecPoint,
|
||||
p3: &AztecPoint,
|
||||
p4: &AztecPoint,
|
||||
) -> bool {
|
||||
let corr = 3;
|
||||
|
||||
let p1 = Point::new(
|
||||
let p1 = AztecPoint::new(
|
||||
0.max(p1.get_x() - corr),
|
||||
(self.image.getHeight() as i32 - 1).min(p1.get_y() + corr),
|
||||
);
|
||||
// let p1 = Point::new(Math.max(0, p1.getX() - corr), Math.min(image.getHeight() - 1, p1.getY() + corr));
|
||||
let p2 = Point::new(0.max(p2.get_x() - corr), 0.max(p2.get_y() - corr));
|
||||
// let p2 = Point::new(Math.max(0, p2.getX() - corr), Math.max(0, p2.getY() - corr));
|
||||
let p3 = Point::new(
|
||||
// let p1 = point(Math.max(0, p1.getX() - corr), Math.min(image.getHeight() - 1, p1.getY() + corr));
|
||||
let p2 = AztecPoint::new(0.max(p2.get_x() - corr), 0.max(p2.get_y() - corr));
|
||||
// let p2 = point(Math.max(0, p2.getX() - corr), Math.max(0, p2.getY() - corr));
|
||||
let p3 = AztecPoint::new(
|
||||
(self.image.getWidth() as i32 - 1).min(p3.get_x() + corr),
|
||||
0.max((self.image.getHeight() as i32 - 1).min(p3.get_y() - corr)),
|
||||
);
|
||||
// let p3 = Point::new(Math.min(image.getWidth() - 1, p3.getX() + corr),
|
||||
// let p3 = point(Math.min(image.getWidth() - 1, p3.getX() + corr),
|
||||
// Math.max(0, Math.min(image.getHeight() - 1, p3.getY() - corr)));
|
||||
let p4 = Point::new(
|
||||
let p4 = AztecPoint::new(
|
||||
(self.image.getWidth() as i32 - 1).min(p4.get_x() + corr),
|
||||
(self.image.getHeight() as i32 - 1).min(p4.get_y() + corr),
|
||||
);
|
||||
// let p4 = Point::new(Math.min(image.getWidth() - 1, p4.getX() + corr),
|
||||
// let p4 = point(Math.min(image.getWidth() - 1, p4.getX() + corr),
|
||||
// Math.min(image.getHeight() - 1, p4.getY() + corr));
|
||||
|
||||
let c_init = self.get_color(&p4, &p1);
|
||||
let c_init = self.get_color(p4, p1);
|
||||
|
||||
if c_init == 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let c = self.get_color(&p1, &p2);
|
||||
let c = self.get_color(p1, p2);
|
||||
|
||||
if c != c_init {
|
||||
return false;
|
||||
}
|
||||
|
||||
let c = self.get_color(&p2, &p3);
|
||||
let c = self.get_color(p2, p3);
|
||||
|
||||
if c != c_init {
|
||||
return false;
|
||||
}
|
||||
|
||||
let c = self.get_color(&p3, &p4);
|
||||
let c = self.get_color(p3, p4);
|
||||
|
||||
c == c_init
|
||||
}
|
||||
@@ -608,7 +599,7 @@ impl<'a> Detector<'_> {
|
||||
*
|
||||
* @return 1 if segment more than 90% black, -1 if segment is more than 90% white, 0 else
|
||||
*/
|
||||
fn get_color(&self, p1: &Point, p2: &Point) -> i32 {
|
||||
fn get_color(&self, p1: AztecPoint, p2: AztecPoint) -> i32 {
|
||||
let d = Self::distance_points(p1, p2);
|
||||
if d == 0.0f32 {
|
||||
return 0;
|
||||
@@ -626,11 +617,7 @@ impl<'a> Detector<'_> {
|
||||
for _i in 0..i_max {
|
||||
// for (int i = 0; i < iMax; i++) {
|
||||
|
||||
if self
|
||||
.image
|
||||
.get(MathUtils::round(px) as u32, MathUtils::round(py) as u32)
|
||||
!= color_model
|
||||
{
|
||||
if self.image.get(px.round() as u32, py.round() as u32) != color_model {
|
||||
error += 1;
|
||||
}
|
||||
px += dx;
|
||||
@@ -653,7 +640,7 @@ impl<'a> Detector<'_> {
|
||||
/**
|
||||
* Gets the coordinate of the first point with a different color in the given direction
|
||||
*/
|
||||
fn get_first_different(&self, init: &Point, color: bool, dx: i32, dy: i32) -> Point {
|
||||
fn get_first_different(&self, init: &AztecPoint, color: bool, dx: i32, dy: i32) -> AztecPoint {
|
||||
let mut x = init.get_x() + dx;
|
||||
let mut y = init.get_y() + dy;
|
||||
|
||||
@@ -675,7 +662,7 @@ impl<'a> Detector<'_> {
|
||||
}
|
||||
y -= dy;
|
||||
|
||||
Point::new(x, y)
|
||||
AztecPoint::new(x, y)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -686,26 +673,18 @@ impl<'a> Detector<'_> {
|
||||
* @param newSide the new length of the size of the square in the target bit matrix
|
||||
* @return the corners of the expanded square
|
||||
*/
|
||||
fn expand_square(
|
||||
corner_points: &[RXingResultPoint],
|
||||
old_side: u32,
|
||||
new_side: u32,
|
||||
) -> [RXingResultPoint; 4] {
|
||||
fn expand_square(corner_points: &[Point], old_side: u32, new_side: u32) -> [Point; 4] {
|
||||
let ratio = new_side as f32 / (2.0f32 * old_side as f32);
|
||||
let mut dx = corner_points[0].getX() - corner_points[2].getX();
|
||||
let mut dy = corner_points[0].getY() - corner_points[2].getY();
|
||||
let mut centerx = (corner_points[0].getX() + corner_points[2].getX()) / 2.0f32;
|
||||
let mut centery = (corner_points[0].getY() + corner_points[2].getY()) / 2.0f32;
|
||||
|
||||
let result0 = RXingResultPoint::new(centerx + ratio * dx, centery + ratio * dy);
|
||||
let result2 = RXingResultPoint::new(centerx - ratio * dx, centery - ratio * dy);
|
||||
let d = corner_points[0] - corner_points[2];
|
||||
let middle = corner_points[0].middle(corner_points[2]);
|
||||
let result0 = middle + ratio * d;
|
||||
let result2 = middle - ratio * d;
|
||||
|
||||
dx = corner_points[1].getX() - corner_points[3].getX();
|
||||
dy = corner_points[1].getY() - corner_points[3].getY();
|
||||
centerx = (corner_points[1].getX() + corner_points[3].getX()) / 2.0f32;
|
||||
centery = (corner_points[1].getY() + corner_points[3].getY()) / 2.0f32;
|
||||
let result1 = RXingResultPoint::new(centerx + ratio * dx, centery + ratio * dy);
|
||||
let result3 = RXingResultPoint::new(centerx - ratio * dx, centery - ratio * dy);
|
||||
let d = corner_points[1] - corner_points[3];
|
||||
let middle = corner_points[1].middle(corner_points[3]);
|
||||
let result1 = middle + ratio * d;
|
||||
let result3 = middle - ratio * d;
|
||||
|
||||
[result0, result1, result2, result3]
|
||||
}
|
||||
@@ -714,18 +693,18 @@ impl<'a> Detector<'_> {
|
||||
x >= 0 && x < self.image.getWidth() as i32 && y >= 0 && y < self.image.getHeight() as i32
|
||||
}
|
||||
|
||||
fn is_valid(&self, point: &RXingResultPoint) -> bool {
|
||||
let x = MathUtils::round(point.getX());
|
||||
let y = MathUtils::round(point.getY());
|
||||
fn is_valid(&self, point: Point) -> bool {
|
||||
let x = point.x.round() as i32;
|
||||
let y = point.y.round() as i32;
|
||||
self.is_valid_points(x, y)
|
||||
}
|
||||
|
||||
fn distance_points(a: &Point, b: &Point) -> f32 {
|
||||
MathUtils::distance(a.get_x(), a.get_y(), b.get_x(), b.get_y())
|
||||
fn distance_points(a: AztecPoint, b: AztecPoint) -> f32 {
|
||||
Point::from(a).distance(b.into())
|
||||
}
|
||||
|
||||
fn distance(a: &RXingResultPoint, b: &RXingResultPoint) -> f32 {
|
||||
MathUtils::distance(a.getX(), a.getY(), b.getX(), b.getY())
|
||||
fn distance(a: Point, b: Point) -> f32 {
|
||||
a.distance(b)
|
||||
}
|
||||
|
||||
fn get_dimension(&self) -> u32 {
|
||||
@@ -738,12 +717,12 @@ impl<'a> Detector<'_> {
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct Point {
|
||||
pub struct AztecPoint {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
impl AztecPoint {
|
||||
pub fn new(x: i32, y: i32) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
@@ -757,13 +736,13 @@ impl Point {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Point> for RXingResultPoint {
|
||||
fn from(value: Point) -> Self {
|
||||
RXingResultPoint::new(value.x as f32, value.y as f32)
|
||||
impl From<AztecPoint> for Point {
|
||||
fn from(value: AztecPoint) -> Self {
|
||||
point(value.x as f32, value.y as f32)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Point {
|
||||
impl fmt::Display for AztecPoint {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "<{} {}>", &self.x, &self.y)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
use std::fmt;
|
||||
|
||||
use crate::common::Result;
|
||||
use crate::{Exceptions, RXingResultPoint};
|
||||
use crate::{Exceptions, Point};
|
||||
|
||||
use super::BitArray;
|
||||
|
||||
@@ -209,7 +209,7 @@ impl BitMatrix {
|
||||
((self.bits[offset] >> (x & 0x1f)) & 1) != 0
|
||||
}
|
||||
|
||||
pub fn get_point(&self, point: &RXingResultPoint) -> bool {
|
||||
pub fn get_point(&self, point: Point) -> bool {
|
||||
self.get(point.x as u32, point.y as u32)
|
||||
// let offset = self.get_offset(point.y as u32, point.x as u32);
|
||||
// ((self.bits[offset] >> (x & 0x1f)) & 1) != 0
|
||||
@@ -691,7 +691,7 @@ impl BitMatrix {
|
||||
new_bm
|
||||
}
|
||||
|
||||
pub fn isIn(&self, p: &RXingResultPoint, b: i32) -> bool {
|
||||
pub fn isIn(&self, p: Point, b: i32) -> bool {
|
||||
b as f32 <= p.x
|
||||
&& p.x < self.getWidth() as f32 - b as f32
|
||||
&& b as f32 <= p.y
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 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.
|
||||
*/
|
||||
|
||||
use std::{
|
||||
f32, i32,
|
||||
ops::{Add, Sub},
|
||||
};
|
||||
|
||||
/**
|
||||
* General math-related and numeric utility functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its
|
||||
* argument to the nearest int, where x.5 rounds up to x+1. Semantics of this shortcut
|
||||
* differ slightly from {@link Math#round(float)} in that half rounds down for negative
|
||||
* values. -2.5 rounds to -3, not -2. For purposes here it makes no difference.
|
||||
*
|
||||
* @param d real value to round
|
||||
* @return nearest {@code int}
|
||||
*/
|
||||
#[inline(always)]
|
||||
pub fn round(d: f32) -> i32 {
|
||||
// (d + (if d < 0.0f32 { -0.5f32 } else { 0.5f32 })) as i32
|
||||
d.round() as i32
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @param aX point A x coordinate
|
||||
// * @param aY point A y coordinate
|
||||
// * @param bX point B x coordinate
|
||||
// * @param bY point B y coordinate
|
||||
// * @return Euclidean distance between points A and B
|
||||
// */
|
||||
// #[inline(always)]
|
||||
// pub fn distance_float(aX: f32, aY: f32, bX: f32, bY: f32) -> f32 {
|
||||
// let xDiff: f64 = (aX - bX).into();
|
||||
// let yDiff: f64 = (aY - bY).into();
|
||||
// (xDiff * xDiff + yDiff * yDiff).sqrt() as f32
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @param aX point A x coordinate
|
||||
// * @param aY point A y coordinate
|
||||
// * @param bX point B x coordinate
|
||||
// * @param bY point B y coordinate
|
||||
// * @return Euclidean distance between points A and B
|
||||
// */
|
||||
// #[inline(always)]
|
||||
// pub fn distance_int(aX: i32, aY: i32, bX: i32, bY: i32) -> f32 {
|
||||
// let xDiff: f64 = (aX - bX).into();
|
||||
// let yDiff: f64 = (aY - bY).into();
|
||||
// (xDiff * xDiff + yDiff * yDiff).sqrt() as f32
|
||||
// }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn distance<T>(aX: T, aY: T, bX: T, bY: T) -> f32
|
||||
where
|
||||
T: Sub<T, Output = T> + Into<f64>,
|
||||
{
|
||||
let xDiff: f64 = (aX - bX).into();
|
||||
let yDiff: f64 = (aY - bY).into();
|
||||
(xDiff * xDiff + yDiff * yDiff).sqrt() as f32
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array values to sum
|
||||
* @return sum of values in array
|
||||
*/
|
||||
#[inline(always)]
|
||||
pub fn sum<'a, T>(array: &'a [T]) -> T
|
||||
where
|
||||
T: Add + std::iter::Sum<&'a T>,
|
||||
{
|
||||
array.iter().sum()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::common::detector::MathUtils;
|
||||
|
||||
// static EPSILON: f32 = 1.0E-8f32;
|
||||
|
||||
#[test]
|
||||
fn testRound() {
|
||||
assert_eq!(-1, MathUtils::round(-1.0f32));
|
||||
assert_eq!(0, MathUtils::round(0.0f32));
|
||||
assert_eq!(1, MathUtils::round(1.0f32));
|
||||
|
||||
assert_eq!(2, MathUtils::round(1.9f32));
|
||||
assert_eq!(2, MathUtils::round(2.1f32));
|
||||
|
||||
assert_eq!(3, MathUtils::round(2.5f32));
|
||||
|
||||
assert_eq!(-2, MathUtils::round(-1.9f32));
|
||||
assert_eq!(-2, MathUtils::round(-2.1f32));
|
||||
|
||||
assert_eq!(-3, MathUtils::round(-2.5f32)); // This differs from Math.round()
|
||||
|
||||
assert_eq!(i32::MAX, MathUtils::round(i32::MAX as f32));
|
||||
assert_eq!(i32::MIN, MathUtils::round(i32::MIN as f32));
|
||||
|
||||
assert_eq!(i32::MAX, MathUtils::round(f32::MAX));
|
||||
assert_eq!(i32::MIN, MathUtils::round(f32::NEG_INFINITY));
|
||||
|
||||
assert_eq!(0, MathUtils::round(f32::NAN));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testDistance() {
|
||||
assert_eq!(
|
||||
(8.0f32).sqrt(),
|
||||
MathUtils::distance(1.0f32, 2.0f32, 3.0f32, 4.0f32)
|
||||
);
|
||||
assert_eq!(0.0f32, MathUtils::distance(1.0f32, 2.0f32, 1.0f32, 2.0f32));
|
||||
|
||||
assert_eq!((8.0f32).sqrt(), MathUtils::distance(1, 2, 3, 4));
|
||||
assert_eq!(0.0f32, MathUtils::distance(1, 2, 1, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testSum() {
|
||||
assert_eq!(0, MathUtils::sum(&[]));
|
||||
assert_eq!(1, MathUtils::sum(&[1]));
|
||||
assert_eq!(4, MathUtils::sum(&[1, 3]));
|
||||
assert_eq!(0, MathUtils::sum(&[-1, 1]));
|
||||
assert_eq!(0.0, MathUtils::sum(&[-1.0, 1.0]));
|
||||
assert_eq!(4.0, MathUtils::sum(&[1.0, 3.0]));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
pub mod MathUtils;
|
||||
|
||||
mod monochrome_rectangle_detector;
|
||||
pub use monochrome_rectangle_detector::*;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
use crate::{
|
||||
common::{BitMatrix, Result},
|
||||
Exceptions, RXingResultPoint, ResultPoint,
|
||||
point, Exceptions, Point,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -45,13 +45,13 @@ impl<'a> MonochromeRectangleDetector<'_> {
|
||||
* <p>Detects a rectangular region of black and white -- mostly black -- with a region of mostly
|
||||
* white, in an image.</p>
|
||||
*
|
||||
* @return {@link RXingResultPoint}[] describing the corners of the rectangular region. The first and
|
||||
* @return {@link Point}[] describing the corners of the rectangular region. The first and
|
||||
* last points are opposed on the diagonal, as are the second and third. The first point will be
|
||||
* the topmost point and the last, the bottommost. The second point will be leftmost and the
|
||||
* third, the rightmost
|
||||
* @throws NotFoundException if no Data Matrix Code can be found
|
||||
*/
|
||||
pub fn detect(&self) -> Result<[RXingResultPoint; 4]> {
|
||||
pub fn detect(&self) -> Result<[Point; 4]> {
|
||||
let height = self.image.getHeight() as i32;
|
||||
let width = self.image.getWidth() as i32;
|
||||
let halfHeight = height / 2;
|
||||
@@ -74,7 +74,7 @@ impl<'a> MonochromeRectangleDetector<'_> {
|
||||
bottom,
|
||||
halfWidth / 2,
|
||||
)?;
|
||||
top = (pointA.getY() - 1f32) as i32;
|
||||
top = (pointA.y - 1f32) as i32;
|
||||
let pointB = self.findCornerFromCenter(
|
||||
halfWidth,
|
||||
-deltaX,
|
||||
@@ -86,7 +86,7 @@ impl<'a> MonochromeRectangleDetector<'_> {
|
||||
bottom,
|
||||
halfHeight / 2,
|
||||
)?;
|
||||
left = (pointB.getX() - 1f32) as i32;
|
||||
left = (pointB.x - 1f32) as i32;
|
||||
let pointC = self.findCornerFromCenter(
|
||||
halfWidth,
|
||||
deltaX,
|
||||
@@ -98,7 +98,7 @@ impl<'a> MonochromeRectangleDetector<'_> {
|
||||
bottom,
|
||||
halfHeight / 2,
|
||||
)?;
|
||||
right = (pointC.getX() + 1f32) as i32;
|
||||
right = (pointC.x + 1f32) as i32;
|
||||
let pointD = self.findCornerFromCenter(
|
||||
halfWidth,
|
||||
0,
|
||||
@@ -110,7 +110,7 @@ impl<'a> MonochromeRectangleDetector<'_> {
|
||||
bottom,
|
||||
halfWidth / 2,
|
||||
)?;
|
||||
bottom = (pointD.getY() + 1f32) as i32;
|
||||
bottom = (pointD.y + 1f32) as i32;
|
||||
|
||||
// Go try to find point A again with better information -- might have been off at first.
|
||||
pointA = self.findCornerFromCenter(
|
||||
@@ -143,7 +143,7 @@ impl<'a> MonochromeRectangleDetector<'_> {
|
||||
* @param bottom maximum value of y
|
||||
* @param maxWhiteRun maximum run of white pixels that can still be considered to be within
|
||||
* the barcode
|
||||
* @return a {@link RXingResultPoint} encapsulating the corner that was found
|
||||
* @return a {@link Point} encapsulating the corner that was found
|
||||
* @throws NotFoundException if such a point cannot be found
|
||||
*/
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -158,7 +158,7 @@ impl<'a> MonochromeRectangleDetector<'_> {
|
||||
top: i32,
|
||||
bottom: i32,
|
||||
maxWhiteRun: i32,
|
||||
) -> Result<RXingResultPoint> {
|
||||
) -> Result<Point> {
|
||||
let mut lastRange_z: Option<[i32; 2]> = None;
|
||||
let mut y: i32 = centerY;
|
||||
let mut x: i32 = centerX;
|
||||
@@ -178,27 +178,27 @@ impl<'a> MonochromeRectangleDetector<'_> {
|
||||
if lastRange[0] < centerX {
|
||||
if lastRange[1] > centerX {
|
||||
// straddle, choose one or the other based on direction
|
||||
return Ok(RXingResultPoint::new(
|
||||
return Ok(point(
|
||||
lastRange[usize::from(deltaY <= 0)] as f32,
|
||||
lastY as f32,
|
||||
));
|
||||
}
|
||||
return Ok(RXingResultPoint::new(lastRange[0] as f32, lastY as f32));
|
||||
return Ok(point(lastRange[0] as f32, lastY as f32));
|
||||
} else {
|
||||
return Ok(RXingResultPoint::new(lastRange[1] as f32, lastY as f32));
|
||||
return Ok(point(lastRange[1] as f32, lastY as f32));
|
||||
}
|
||||
} else {
|
||||
let lastX = x - deltaX;
|
||||
if lastRange[0] < centerY {
|
||||
if lastRange[1] > centerY {
|
||||
return Ok(RXingResultPoint::new(
|
||||
return Ok(point(
|
||||
lastX as f32,
|
||||
lastRange[usize::from(deltaX >= 0)] as f32,
|
||||
));
|
||||
}
|
||||
return Ok(RXingResultPoint::new(lastX as f32, lastRange[0] as f32));
|
||||
return Ok(point(lastX as f32, lastRange[0] as f32));
|
||||
} else {
|
||||
return Ok(RXingResultPoint::new(lastX as f32, lastRange[1] as f32));
|
||||
return Ok(point(lastX as f32, lastRange[1] as f32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,9 @@
|
||||
|
||||
use crate::{
|
||||
common::{BitMatrix, Result},
|
||||
Exceptions, RXingResultPoint, ResultPoint,
|
||||
point, Exceptions, Point,
|
||||
};
|
||||
|
||||
use super::MathUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Detects a candidate barcode-like rectangular region within an image. It
|
||||
@@ -101,14 +99,14 @@ impl<'a> WhiteRectangleDetector<'_> {
|
||||
* region until it finds a white rectangular region.
|
||||
* </p>
|
||||
*
|
||||
* @return {@link RXingResultPoint}[] describing the corners of the rectangular
|
||||
* @return {@link Point}[] describing the corners of the rectangular
|
||||
* region. The first and last points are opposed on the diagonal, as
|
||||
* are the second and third. The first point will be the topmost
|
||||
* point and the last, the bottommost. The second point will be
|
||||
* leftmost and the third, the rightmost
|
||||
* @throws NotFoundException if no Data Matrix Code can be found
|
||||
*/
|
||||
pub fn detect(&self) -> Result<[RXingResultPoint; 4]> {
|
||||
pub fn detect(&self) -> Result<[Point; 4]> {
|
||||
let mut left: i32 = self.leftInit;
|
||||
let mut right: i32 = self.rightInit;
|
||||
let mut up: i32 = self.upInit;
|
||||
@@ -212,7 +210,7 @@ impl<'a> WhiteRectangleDetector<'_> {
|
||||
if !size_exceeded {
|
||||
let max_size = right - left;
|
||||
|
||||
let mut z: Option<RXingResultPoint> = None;
|
||||
let mut z: Option<Point> = None;
|
||||
let mut i = 1;
|
||||
while z.is_none() && i < max_size {
|
||||
//for (int i = 1; z == null && i < maxSize; i++) {
|
||||
@@ -229,7 +227,7 @@ impl<'a> WhiteRectangleDetector<'_> {
|
||||
return Err(Exceptions::notFound);
|
||||
}
|
||||
|
||||
let mut t: Option<RXingResultPoint> = None;
|
||||
let mut t: Option<Point> = None;
|
||||
//go down right
|
||||
let mut i = 1;
|
||||
while t.is_none() && i < max_size {
|
||||
@@ -247,7 +245,7 @@ impl<'a> WhiteRectangleDetector<'_> {
|
||||
return Err(Exceptions::notFound);
|
||||
}
|
||||
|
||||
let mut x: Option<RXingResultPoint> = None;
|
||||
let mut x: Option<Point> = None;
|
||||
//go down left
|
||||
let mut i = 1;
|
||||
while x.is_none() && i < max_size {
|
||||
@@ -265,7 +263,7 @@ impl<'a> WhiteRectangleDetector<'_> {
|
||||
return Err(Exceptions::notFound);
|
||||
}
|
||||
|
||||
let mut y: Option<RXingResultPoint> = None;
|
||||
let mut y: Option<Point> = None;
|
||||
//go up left
|
||||
let mut i = 1;
|
||||
while y.is_none() && i < max_size {
|
||||
@@ -283,28 +281,25 @@ impl<'a> WhiteRectangleDetector<'_> {
|
||||
return Err(Exceptions::notFound);
|
||||
}
|
||||
|
||||
Ok(self.center_edges(&y.unwrap(), &z.unwrap(), &x.unwrap(), &t.unwrap()))
|
||||
Ok(self.center_edges(y.unwrap(), z.unwrap(), x.unwrap(), t.unwrap()))
|
||||
} else {
|
||||
Err(Exceptions::notFound)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_black_point_on_segment(
|
||||
&self,
|
||||
a_x: f32,
|
||||
a_y: f32,
|
||||
b_x: f32,
|
||||
b_y: f32,
|
||||
) -> Option<RXingResultPoint> {
|
||||
let dist = MathUtils::round(MathUtils::distance(a_x, a_y, b_x, b_y));
|
||||
fn get_black_point_on_segment(&self, a_x: f32, a_y: f32, b_x: f32, b_y: f32) -> Option<Point> {
|
||||
let a = point(a_x, a_y);
|
||||
let b = point(b_x, b_y);
|
||||
|
||||
let dist = a.distance(b).round() as i32;
|
||||
let x_step: f32 = (b_x - a_x) / dist as f32;
|
||||
let y_step: f32 = (b_y - a_y) / dist as f32;
|
||||
|
||||
for i in 0..dist {
|
||||
let x = MathUtils::round(a_x + i as f32 * x_step);
|
||||
let y = MathUtils::round(a_y + i as f32 * y_step);
|
||||
let x = (a_x + i as f32 * x_step).round() as i32;
|
||||
let y = (a_y + i as f32 * y_step).round() as i32;
|
||||
if self.image.get(x as u32, y as u32) {
|
||||
return Some(RXingResultPoint::new(x as f32, y as f32));
|
||||
return Some(point(x as f32, y as f32));
|
||||
}
|
||||
}
|
||||
None
|
||||
@@ -317,19 +312,13 @@ impl<'a> WhiteRectangleDetector<'_> {
|
||||
* @param z left most point
|
||||
* @param x right most point
|
||||
* @param t top most point
|
||||
* @return {@link RXingResultPoint}[] describing the corners of the rectangular
|
||||
* @return {@link Point}[] describing the corners of the rectangular
|
||||
* region. The first and last points are opposed on the diagonal, as
|
||||
* are the second and third. The first point will be the topmost
|
||||
* point and the last, the bottommost. The second point will be
|
||||
* leftmost and the third, the rightmost
|
||||
*/
|
||||
fn center_edges(
|
||||
&self,
|
||||
y: &RXingResultPoint,
|
||||
z: &RXingResultPoint,
|
||||
x: &RXingResultPoint,
|
||||
t: &RXingResultPoint,
|
||||
) -> [RXingResultPoint; 4] {
|
||||
fn center_edges(&self, y: Point, z: Point, x: Point, t: Point) -> [Point; 4] {
|
||||
//
|
||||
// t t
|
||||
// z x
|
||||
@@ -337,28 +326,28 @@ impl<'a> WhiteRectangleDetector<'_> {
|
||||
// y y
|
||||
//
|
||||
|
||||
let yi = y.getX();
|
||||
let yj = y.getY();
|
||||
let zi = z.getX();
|
||||
let zj = z.getY();
|
||||
let xi = x.getX();
|
||||
let xj = x.getY();
|
||||
let ti = t.getX();
|
||||
let tj = t.getY();
|
||||
let yi = y.x;
|
||||
let yj = y.y;
|
||||
let zi = z.x;
|
||||
let zj = z.y;
|
||||
let xi = x.x;
|
||||
let xj = x.y;
|
||||
let ti = t.x;
|
||||
let tj = t.y;
|
||||
|
||||
if yi < self.width as f32 / 2.0f32 {
|
||||
[
|
||||
RXingResultPoint::new(ti - CORR as f32, tj + CORR as f32),
|
||||
RXingResultPoint::new(zi + CORR as f32, zj + CORR as f32),
|
||||
RXingResultPoint::new(xi - CORR as f32, xj - CORR as f32),
|
||||
RXingResultPoint::new(yi + CORR as f32, yj - CORR as f32),
|
||||
point(ti - CORR as f32, tj + CORR as f32),
|
||||
point(zi + CORR as f32, zj + CORR as f32),
|
||||
point(xi - CORR as f32, xj - CORR as f32),
|
||||
point(yi + CORR as f32, yj - CORR as f32),
|
||||
]
|
||||
} else {
|
||||
[
|
||||
RXingResultPoint::new(ti + CORR as f32, tj + CORR as f32),
|
||||
RXingResultPoint::new(zi + CORR as f32, zj - CORR as f32),
|
||||
RXingResultPoint::new(xi - CORR as f32, xj + CORR as f32),
|
||||
RXingResultPoint::new(yi - CORR as f32, yj - CORR as f32),
|
||||
point(ti + CORR as f32, tj + CORR as f32),
|
||||
point(zi + CORR as f32, zj - CORR as f32),
|
||||
point(xi - CORR as f32, xj + CORR as f32),
|
||||
point(yi - CORR as f32, yj - CORR as f32),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
pub mod detector;
|
||||
pub mod reedsolomon;
|
||||
|
||||
use crate::RXingResultPoint;
|
||||
use crate::Point;
|
||||
|
||||
#[cfg(test)]
|
||||
mod StringUtilsTestCase;
|
||||
@@ -44,7 +44,7 @@ pub type Result<T, E = crate::Exceptions> = std::result::Result<T, E>;
|
||||
|
||||
// package com.google.zxing.common;
|
||||
|
||||
// import com.google.zxing.RXingResultPoint;
|
||||
// import com.google.zxing.Point;
|
||||
|
||||
/**
|
||||
* <p>Encapsulates the result of detecting a barcode in an image. This includes the raw
|
||||
@@ -56,12 +56,12 @@ pub type Result<T, E = crate::Exceptions> = std::result::Result<T, E>;
|
||||
pub trait DetectorRXingResult {
|
||||
fn getBits(&self) -> &BitMatrix;
|
||||
|
||||
fn getPoints(&self) -> &[RXingResultPoint];
|
||||
fn getPoints(&self) -> &[Point];
|
||||
}
|
||||
|
||||
// pub struct DetectorRXingResult {
|
||||
// bits: BitMatrix,
|
||||
// points: Vec<RXingResultPoint>,
|
||||
// points: Vec<Point>,
|
||||
// }
|
||||
|
||||
mod bit_matrix;
|
||||
|
||||
@@ -39,7 +39,7 @@ static DECODER: Lazy<Decoder> = Lazy::new(Decoder::new);
|
||||
#[derive(Default)]
|
||||
pub struct DataMatrixReader;
|
||||
|
||||
// private static final RXingResultPoint[] NO_POINTS = new RXingResultPoint[0];
|
||||
// private static final Point[] NO_POINTS = new Point[0];
|
||||
|
||||
// private final Decoder decoder = new Decoder();
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ use crate::{
|
||||
common::{
|
||||
detector::WhiteRectangleDetector, BitMatrix, DefaultGridSampler, GridSampler, Result,
|
||||
},
|
||||
Exceptions, RXingResultPoint, ResultPoint,
|
||||
point, Exceptions, Point,
|
||||
};
|
||||
|
||||
use super::DatamatrixDetectorResult;
|
||||
@@ -68,8 +68,8 @@ impl<'a> Detector<'_> {
|
||||
let bottomRight = points[2];
|
||||
let topRight = points[3];
|
||||
|
||||
let mut dimensionTop = self.transitionsBetween(&topLeft, &topRight) + 1;
|
||||
let mut dimensionRight = self.transitionsBetween(&bottomRight, &topRight) + 1;
|
||||
let mut dimensionTop = self.transitionsBetween(topLeft, topRight) + 1;
|
||||
let mut dimensionRight = self.transitionsBetween(bottomRight, topRight) + 1;
|
||||
if (dimensionTop & 0x01) == 1 {
|
||||
dimensionTop += 1;
|
||||
}
|
||||
@@ -85,10 +85,10 @@ impl<'a> Detector<'_> {
|
||||
|
||||
let bits = Self::sampleGrid(
|
||||
self.image,
|
||||
&topLeft,
|
||||
&bottomLeft,
|
||||
&bottomRight,
|
||||
&topRight,
|
||||
topLeft,
|
||||
bottomLeft,
|
||||
bottomRight,
|
||||
topRight,
|
||||
dimensionTop,
|
||||
dimensionRight,
|
||||
)?;
|
||||
@@ -99,15 +99,15 @@ impl<'a> Detector<'_> {
|
||||
))
|
||||
}
|
||||
|
||||
fn shiftPoint(point: RXingResultPoint, to: RXingResultPoint, div: u32) -> RXingResultPoint {
|
||||
let x = (to.getX() - point.getX()) / (div as f32 + 1.0);
|
||||
let y = (to.getY() - point.getY()) / (div as f32 + 1.0);
|
||||
RXingResultPoint::new(point.getX() + x, point.getY() + y)
|
||||
fn shiftPoint(p: Point, to: Point, div: u32) -> Point {
|
||||
let x = (to.x - p.x) / (div as f32 + 1.0);
|
||||
let y = (to.y - p.y) / (div as f32 + 1.0);
|
||||
point(p.x + x, p.y + y)
|
||||
}
|
||||
|
||||
fn moveAway(point: RXingResultPoint, fromX: f32, fromY: f32) -> RXingResultPoint {
|
||||
let mut x = point.getX();
|
||||
let mut y = point.getY();
|
||||
fn moveAway(p: Point, fromX: f32, fromY: f32) -> Point {
|
||||
let mut x = p.x;
|
||||
let mut y = p.y;
|
||||
|
||||
if x < fromX {
|
||||
x -= 1.0;
|
||||
@@ -121,13 +121,13 @@ impl<'a> Detector<'_> {
|
||||
y += 1.0;
|
||||
}
|
||||
|
||||
RXingResultPoint::new(x, y)
|
||||
point(x, y)
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect a solid side which has minimum transition.
|
||||
*/
|
||||
fn detectSolid1(&self, cornerPoints: [RXingResultPoint; 4]) -> [RXingResultPoint; 4] {
|
||||
fn detectSolid1(&self, cornerPoints: [Point; 4]) -> [Point; 4] {
|
||||
// 0 2
|
||||
// 1 3
|
||||
let pointA = cornerPoints[0];
|
||||
@@ -135,10 +135,10 @@ impl<'a> Detector<'_> {
|
||||
let pointC = cornerPoints[3];
|
||||
let pointD = cornerPoints[2];
|
||||
|
||||
let trAB = self.transitionsBetween(&pointA, &pointB);
|
||||
let trBC = self.transitionsBetween(&pointB, &pointC);
|
||||
let trCD = self.transitionsBetween(&pointC, &pointD);
|
||||
let trDA = self.transitionsBetween(&pointD, &pointA);
|
||||
let trAB = self.transitionsBetween(pointA, pointB);
|
||||
let trBC = self.transitionsBetween(pointB, pointC);
|
||||
let trCD = self.transitionsBetween(pointC, pointD);
|
||||
let trDA = self.transitionsBetween(pointD, pointA);
|
||||
|
||||
// 0..3
|
||||
// : :
|
||||
@@ -172,7 +172,7 @@ impl<'a> Detector<'_> {
|
||||
/**
|
||||
* Detect a second solid side next to first solid side.
|
||||
*/
|
||||
fn detectSolid2(&self, points: [RXingResultPoint; 4]) -> [RXingResultPoint; 4] {
|
||||
fn detectSolid2(&self, points: [Point; 4]) -> [Point; 4] {
|
||||
// A..D
|
||||
// : :
|
||||
// B--C
|
||||
@@ -183,11 +183,11 @@ impl<'a> Detector<'_> {
|
||||
|
||||
// Transition detection on the edge is not stable.
|
||||
// To safely detect, shift the points to the module center.
|
||||
let tr = self.transitionsBetween(&pointA, &pointD);
|
||||
let tr = self.transitionsBetween(pointA, pointD);
|
||||
let pointBs = Self::shiftPoint(pointB, pointC, (tr + 1) * 4);
|
||||
let pointCs = Self::shiftPoint(pointC, pointB, (tr + 1) * 4);
|
||||
let trBA = self.transitionsBetween(&pointBs, &pointA);
|
||||
let trCD = self.transitionsBetween(&pointCs, &pointD);
|
||||
let trBA = self.transitionsBetween(pointBs, pointA);
|
||||
let trCD = self.transitionsBetween(pointCs, pointD);
|
||||
|
||||
// 0..3
|
||||
// | :
|
||||
@@ -212,7 +212,7 @@ impl<'a> Detector<'_> {
|
||||
/**
|
||||
* Calculates the corner position of the white top right module.
|
||||
*/
|
||||
fn correctTopRight(&self, points: &[RXingResultPoint; 4]) -> Option<RXingResultPoint> {
|
||||
fn correctTopRight(&self, points: &[Point; 4]) -> Option<Point> {
|
||||
// A..D
|
||||
// | :
|
||||
// B--C
|
||||
@@ -222,37 +222,37 @@ impl<'a> Detector<'_> {
|
||||
let pointD = points[3];
|
||||
|
||||
// shift points for safe transition detection.
|
||||
let mut trTop = self.transitionsBetween(&pointA, &pointD);
|
||||
let mut trRight = self.transitionsBetween(&pointB, &pointD);
|
||||
let mut trTop = self.transitionsBetween(pointA, pointD);
|
||||
let mut trRight = self.transitionsBetween(pointB, pointD);
|
||||
let pointAs = Self::shiftPoint(pointA, pointB, (trRight + 1) * 4);
|
||||
let pointCs = Self::shiftPoint(pointC, pointB, (trTop + 1) * 4);
|
||||
|
||||
trTop = self.transitionsBetween(&pointAs, &pointD);
|
||||
trRight = self.transitionsBetween(&pointCs, &pointD);
|
||||
trTop = self.transitionsBetween(pointAs, pointD);
|
||||
trRight = self.transitionsBetween(pointCs, pointD);
|
||||
|
||||
let candidate1 = RXingResultPoint::new(
|
||||
pointD.getX() + (pointC.getX() - pointB.getX()) / (trTop as f32 + 1.0),
|
||||
pointD.getY() + (pointC.getY() - pointB.getY()) / (trTop as f32 + 1.0),
|
||||
let candidate1 = point(
|
||||
pointD.x + (pointC.x - pointB.x) / (trTop as f32 + 1.0),
|
||||
pointD.y + (pointC.y - pointB.y) / (trTop as f32 + 1.0),
|
||||
);
|
||||
let candidate2 = RXingResultPoint::new(
|
||||
pointD.getX() + (pointA.getX() - pointB.getX()) / (trRight as f32 + 1.0),
|
||||
pointD.getY() + (pointA.getY() - pointB.getY()) / (trRight as f32 + 1.0),
|
||||
let candidate2 = point(
|
||||
pointD.x + (pointA.x - pointB.x) / (trRight as f32 + 1.0),
|
||||
pointD.y + (pointA.y - pointB.y) / (trRight as f32 + 1.0),
|
||||
);
|
||||
|
||||
if !self.isValid(&candidate1) {
|
||||
if self.isValid(&candidate2) {
|
||||
if !self.isValid(candidate1) {
|
||||
if self.isValid(candidate2) {
|
||||
return Some(candidate2);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
if !self.isValid(&candidate2) {
|
||||
if !self.isValid(candidate2) {
|
||||
return Some(candidate1);
|
||||
}
|
||||
|
||||
let sumc1 = self.transitionsBetween(&pointAs, &candidate1)
|
||||
+ self.transitionsBetween(&pointCs, &candidate1);
|
||||
let sumc2 = self.transitionsBetween(&pointAs, &candidate2)
|
||||
+ self.transitionsBetween(&pointCs, &candidate2);
|
||||
let sumc1 = self.transitionsBetween(pointAs, candidate1)
|
||||
+ self.transitionsBetween(pointCs, candidate1);
|
||||
let sumc2 = self.transitionsBetween(pointAs, candidate2)
|
||||
+ self.transitionsBetween(pointCs, candidate2);
|
||||
|
||||
if sumc1 > sumc2 {
|
||||
Some(candidate1)
|
||||
@@ -264,7 +264,7 @@ impl<'a> Detector<'_> {
|
||||
/**
|
||||
* Shift the edge points to the module center.
|
||||
*/
|
||||
fn shiftToModuleCenter(&self, points: [RXingResultPoint; 4]) -> [RXingResultPoint; 4] {
|
||||
fn shiftToModuleCenter(&self, points: [Point; 4]) -> [Point; 4] {
|
||||
// A..D
|
||||
// | :
|
||||
// B--C
|
||||
@@ -274,16 +274,16 @@ impl<'a> Detector<'_> {
|
||||
let mut pointD = points[3];
|
||||
|
||||
// calculate pseudo dimensions
|
||||
let mut dimH = self.transitionsBetween(&pointA, &pointD) + 1;
|
||||
let mut dimV = self.transitionsBetween(&pointC, &pointD) + 1;
|
||||
let mut dimH = self.transitionsBetween(pointA, pointD) + 1;
|
||||
let mut dimV = self.transitionsBetween(pointC, pointD) + 1;
|
||||
|
||||
// shift points for safe dimension detection
|
||||
let mut pointAs = Self::shiftPoint(pointA, pointB, dimV * 4);
|
||||
let mut pointCs = Self::shiftPoint(pointC, pointB, dimH * 4);
|
||||
|
||||
// calculate more precise dimensions
|
||||
dimH = self.transitionsBetween(&pointAs, &pointD) + 1;
|
||||
dimV = self.transitionsBetween(&pointCs, &pointD) + 1;
|
||||
dimH = self.transitionsBetween(pointAs, pointD) + 1;
|
||||
dimV = self.transitionsBetween(pointCs, pointD) + 1;
|
||||
if (dimH & 0x01) == 1 {
|
||||
dimH += 1;
|
||||
}
|
||||
@@ -293,8 +293,8 @@ impl<'a> Detector<'_> {
|
||||
|
||||
// WhiteRectangleDetector returns points inside of the rectangle.
|
||||
// I want points on the edges.
|
||||
let centerX = (pointA.getX() + pointB.getX() + pointC.getX() + pointD.getX()) / 4.0;
|
||||
let centerY = (pointA.getY() + pointB.getY() + pointC.getY() + pointD.getY()) / 4.0;
|
||||
let centerX = (pointA.x + pointB.x + pointC.x + pointD.x) / 4.0;
|
||||
let centerY = (pointA.y + pointB.y + pointC.y + pointD.y) / 4.0;
|
||||
pointA = Self::moveAway(pointA, centerX, centerY);
|
||||
pointB = Self::moveAway(pointB, centerX, centerY);
|
||||
pointC = Self::moveAway(pointC, centerX, centerY);
|
||||
@@ -316,19 +316,19 @@ impl<'a> Detector<'_> {
|
||||
[pointAs, pointBs, pointCs, pointDs]
|
||||
}
|
||||
|
||||
fn isValid(&self, p: &RXingResultPoint) -> bool {
|
||||
p.getX() >= 0.0
|
||||
&& p.getX() <= self.image.getWidth() as f32 - 1.0
|
||||
&& p.getY() > 0.0
|
||||
&& p.getY() <= self.image.getHeight() as f32 - 1.0
|
||||
fn isValid(&self, p: Point) -> bool {
|
||||
p.x >= 0.0
|
||||
&& p.x <= self.image.getWidth() as f32 - 1.0
|
||||
&& p.y > 0.0
|
||||
&& p.y <= self.image.getHeight() as f32 - 1.0
|
||||
}
|
||||
|
||||
fn sampleGrid(
|
||||
image: &BitMatrix,
|
||||
topLeft: &RXingResultPoint,
|
||||
bottomLeft: &RXingResultPoint,
|
||||
bottomRight: &RXingResultPoint,
|
||||
topRight: &RXingResultPoint,
|
||||
topLeft: Point,
|
||||
bottomLeft: Point,
|
||||
bottomRight: Point,
|
||||
topRight: Point,
|
||||
dimensionX: u32,
|
||||
dimensionY: u32,
|
||||
) -> Result<BitMatrix> {
|
||||
@@ -346,26 +346,26 @@ impl<'a> Detector<'_> {
|
||||
dimensionY as f32 - 0.5,
|
||||
0.5,
|
||||
dimensionY as f32 - 0.5,
|
||||
topLeft.getX(),
|
||||
topLeft.getY(),
|
||||
topRight.getX(),
|
||||
topRight.getY(),
|
||||
bottomRight.getX(),
|
||||
bottomRight.getY(),
|
||||
bottomLeft.getX(),
|
||||
bottomLeft.getY(),
|
||||
topLeft.x,
|
||||
topLeft.y,
|
||||
topRight.x,
|
||||
topRight.y,
|
||||
bottomRight.x,
|
||||
bottomRight.y,
|
||||
bottomLeft.x,
|
||||
bottomLeft.y,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of black/white transitions between two points, using something like Bresenham's algorithm.
|
||||
*/
|
||||
fn transitionsBetween(&self, from: &RXingResultPoint, to: &RXingResultPoint) -> u32 {
|
||||
fn transitionsBetween(&self, from: Point, to: Point) -> u32 {
|
||||
// See QR Code Detector, sizeOfBlackWhiteBlackRun()
|
||||
let mut fromX = from.getX().floor() as i32;
|
||||
let mut fromY = from.getY().floor() as i32;
|
||||
let mut toX = to.getX().floor() as i32;
|
||||
let mut toY = (self.image.getHeight() - 1).min(to.getY().floor() as u32) as i32;
|
||||
let mut fromX = from.x.floor() as i32;
|
||||
let mut fromY = from.y.floor() as i32;
|
||||
let mut toX = to.x.floor() as i32;
|
||||
let mut toY = (self.image.getHeight() - 1).min(to.y.floor() as u32) as i32;
|
||||
|
||||
let steep = (toY - fromY).abs() > (toX - fromX).abs();
|
||||
if steep {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use crate::{
|
||||
common::{BitMatrix, DetectorRXingResult},
|
||||
RXingResultPoint,
|
||||
Point,
|
||||
};
|
||||
|
||||
pub struct DatamatrixDetectorResult(BitMatrix, Vec<RXingResultPoint>);
|
||||
pub struct DatamatrixDetectorResult(BitMatrix, Vec<Point>);
|
||||
|
||||
impl DatamatrixDetectorResult {
|
||||
pub fn new(bits: BitMatrix, points: Vec<RXingResultPoint>) -> Self {
|
||||
pub fn new(bits: BitMatrix, points: Vec<Point>) -> Self {
|
||||
Self(bits, points)
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ impl DetectorRXingResult for DatamatrixDetectorResult {
|
||||
&self.0
|
||||
}
|
||||
|
||||
fn getPoints(&self) -> &[RXingResultPoint] {
|
||||
fn getPoints(&self) -> &[Point] {
|
||||
&self.1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::RXingResultPoint;
|
||||
use crate::Point;
|
||||
|
||||
use super::{util::opposite, Direction, Value};
|
||||
|
||||
@@ -16,28 +16,28 @@ pub trait BitMatrixCursor {
|
||||
|
||||
// BitMatrixCursor(const BitMatrix& image, POINT p, POINT d) : img(&image), p(p) { setDirection(d); }
|
||||
|
||||
fn testAt(&self, p: &RXingResultPoint) -> Value; //const
|
||||
// {
|
||||
// return img->isIn(p) ? Value{img->get(p)} : Value{};
|
||||
// }
|
||||
fn testAt(&self, p: Point) -> Value; //const
|
||||
// {
|
||||
// return img->isIn(p) ? Value{img->get(p)} : Value{};
|
||||
// }
|
||||
|
||||
fn blackAt(&self, pos: &RXingResultPoint) -> bool {
|
||||
fn blackAt(&self, pos: Point) -> bool {
|
||||
self.testAt(pos).isBlack()
|
||||
}
|
||||
fn whiteAt(&self, pos: &RXingResultPoint) -> bool {
|
||||
fn whiteAt(&self, pos: Point) -> bool {
|
||||
self.testAt(pos).isWhite()
|
||||
}
|
||||
|
||||
fn isIn(&self, p: &RXingResultPoint) -> bool; // { return img->isIn(p); }
|
||||
fn isIn(&self, p: Point) -> bool; // { return img->isIn(p); }
|
||||
fn isInSelf(&self) -> bool; // { return self.isIn(p); }
|
||||
fn isBlack(&self) -> bool; // { return blackAt(p); }
|
||||
fn isWhite(&self) -> bool; // { return whiteAt(p); }
|
||||
|
||||
fn front(&self) -> &RXingResultPoint; //{ return d; }
|
||||
fn back(&self) -> RXingResultPoint; // { return {-d.x, -d.y}; }
|
||||
fn left(&self) -> RXingResultPoint; //{ return {d.y, -d.x}; }
|
||||
fn right(&self) -> RXingResultPoint; //{ return {-d.y, d.x}; }
|
||||
fn direction(&self, dir: Direction) -> RXingResultPoint {
|
||||
fn front(&self) -> &Point; //{ return d; }
|
||||
fn back(&self) -> Point; // { return {-d.x, -d.y}; }
|
||||
fn left(&self) -> Point; //{ return {d.y, -d.x}; }
|
||||
fn right(&self) -> Point; //{ return {-d.y, d.x}; }
|
||||
fn direction(&self, dir: Direction) -> Point {
|
||||
self.right() * Into::<i32>::into(dir)
|
||||
}
|
||||
|
||||
@@ -46,30 +46,30 @@ pub trait BitMatrixCursor {
|
||||
fn turnRight(&mut self); //noexcept { d = right(); }
|
||||
fn turn(&mut self, dir: Direction); //noexcept { d = direction(dir); }
|
||||
|
||||
fn edgeAt_point(&self, d: &RXingResultPoint) -> Value;
|
||||
fn edgeAt_point(&self, d: Point) -> Value;
|
||||
// {
|
||||
// Value v = testAt(p);
|
||||
// return testAt(p + d) != v ? v : Value();
|
||||
// }
|
||||
|
||||
fn edgeAtFront(&self) -> Value {
|
||||
return self.edgeAt_point(self.front());
|
||||
return self.edgeAt_point(*self.front());
|
||||
}
|
||||
fn edgeAtBack(&self) -> Value {
|
||||
self.edgeAt_point(&self.back())
|
||||
self.edgeAt_point(self.back())
|
||||
}
|
||||
fn edgeAtLeft(&self) -> Value {
|
||||
self.edgeAt_point(&self.left())
|
||||
self.edgeAt_point(self.left())
|
||||
}
|
||||
fn edgeAtRight(&self) -> Value {
|
||||
self.edgeAt_point(&self.right())
|
||||
self.edgeAt_point(self.right())
|
||||
}
|
||||
fn edgeAt_direction(&self, dir: Direction) -> Value {
|
||||
self.edgeAt_point(&self.direction(dir))
|
||||
self.edgeAt_point(self.direction(dir))
|
||||
}
|
||||
|
||||
fn setDirection(&mut self, dir: &RXingResultPoint); // { d = bresenhamDirection(dir); }
|
||||
// fn setDirection(&self, dir:&RXingResultPoint);// { d = dir; }
|
||||
fn setDirection(&mut self, dir: Point); // { d = bresenhamDirection(dir); }
|
||||
// fn setDirection(&self, dir: Point);// { d = dir; }
|
||||
|
||||
fn step(&mut self, s: Option<f32>) -> bool; // DEF to 1
|
||||
// {
|
||||
@@ -77,7 +77,7 @@ pub trait BitMatrixCursor {
|
||||
// return isIn(p);
|
||||
// }
|
||||
|
||||
fn movedBy<T: BitMatrixCursor>(self, d: &RXingResultPoint) -> Self;
|
||||
fn movedBy<T: BitMatrixCursor>(self, d: Point) -> Self;
|
||||
// {
|
||||
// auto res = *this;
|
||||
// res.p += d;
|
||||
|
||||
@@ -20,8 +20,7 @@ use crate::{
|
||||
DatamatrixDetectorResult,
|
||||
},
|
||||
qrcode::encoder::ByteMatrix,
|
||||
result_point_utils::distance,
|
||||
Exceptions, RXingResultPoint, ResultPoint,
|
||||
Exceptions, Point,
|
||||
};
|
||||
|
||||
use super::{DMRegressionLine, EdgeTracer};
|
||||
@@ -46,10 +45,10 @@ fn Scan(
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut tl = RXingResultPoint::default();
|
||||
let mut bl = RXingResultPoint::default();
|
||||
let mut br = RXingResultPoint::default();
|
||||
let mut tr = RXingResultPoint::default();
|
||||
let mut tl = Point::default();
|
||||
let mut bl = Point::default();
|
||||
let mut br = Point::default();
|
||||
let mut tr = Point::default();
|
||||
|
||||
for l in lines.iter_mut() {
|
||||
l.reset();
|
||||
@@ -76,7 +75,7 @@ fn Scan(
|
||||
// follow left leg upwards
|
||||
t.turnRight();
|
||||
t.state = 1;
|
||||
CHECK!(t.traceLine(&t.right(), lineL)?);
|
||||
CHECK!(t.traceLine(t.right(), lineL)?);
|
||||
CHECK!(t.traceCorner(&mut t.right(), &mut tl)?);
|
||||
lineL.reverse();
|
||||
let mut tlTracer = t;
|
||||
@@ -84,34 +83,34 @@ fn Scan(
|
||||
// follow left leg downwards
|
||||
t = startTracer.clone();
|
||||
t.state = 1;
|
||||
t.setDirection(&tlTracer.right());
|
||||
CHECK!(t.traceLine(&t.left(), lineL)?);
|
||||
t.setDirection(tlTracer.right());
|
||||
CHECK!(t.traceLine(t.left(), lineL)?);
|
||||
if !lineL.isValid() {
|
||||
t.updateDirectionFromOrigin(&tl);
|
||||
t.updateDirectionFromOrigin(tl);
|
||||
}
|
||||
let up = t.back();
|
||||
CHECK!(t.traceCorner(&mut t.left(), &mut bl)?);
|
||||
|
||||
// follow bottom leg right
|
||||
t.state = 2;
|
||||
CHECK!(t.traceLine(&t.left(), lineB)?);
|
||||
CHECK!(t.traceLine(t.left(), lineB)?);
|
||||
if !lineB.isValid() {
|
||||
t.updateDirectionFromOrigin(&bl);
|
||||
t.updateDirectionFromOrigin(bl);
|
||||
}
|
||||
let right = *t.front();
|
||||
CHECK!(t.traceCorner(&mut t.left(), &mut br)?);
|
||||
|
||||
let lenL = distance(&tl, &bl) - 1.0;
|
||||
let lenB = distance(&bl, &br) - 1.0;
|
||||
let lenL = Point::distance(tl, bl) - 1.0;
|
||||
let lenB = Point::distance(bl, br) - 1.0;
|
||||
CHECK!(lenL >= 8.0 && lenB >= 10.0 && lenB >= lenL / 4.0 && lenB <= lenL * 18.0);
|
||||
|
||||
let mut maxStepSize: i32 = (lenB / 5.0 + 1.0) as i32; // datamatrix bottom dim is at least 10
|
||||
|
||||
// at this point we found a plausible L-shape and are now looking for the b/w pattern at the top and right:
|
||||
// follow top row right 'half way' (4 gaps), see traceGaps break condition with 'invalid' line
|
||||
tlTracer.setDirection(&right);
|
||||
tlTracer.setDirection(right);
|
||||
CHECK!(tlTracer.traceGaps(
|
||||
&tlTracer.right(),
|
||||
tlTracer.right(),
|
||||
lineT,
|
||||
maxStepSize,
|
||||
&mut DMRegressionLine::default()
|
||||
@@ -124,13 +123,13 @@ fn Scan(
|
||||
maxStepSize = std::cmp::min(lineT.length() as i32 / 3, (lenL / 5.0) as i32) * 2;
|
||||
|
||||
// follow up until we reach the top line
|
||||
t.setDirection(&up);
|
||||
t.setDirection(up);
|
||||
t.state = 3;
|
||||
CHECK!(t.traceGaps(&t.left(), lineR, maxStepSize, lineT)?);
|
||||
CHECK!(t.traceGaps(t.left(), lineR, maxStepSize, lineT)?);
|
||||
CHECK!(t.traceCorner(&mut t.left(), &mut tr)?);
|
||||
|
||||
let lenT = distance(&tl, &tr) - 1.0;
|
||||
let lenR = distance(&tr, &br) - 1.0;
|
||||
let lenT = Point::distance(tl, tr) - 1.0;
|
||||
let lenR = Point::distance(tr, br) - 1.0;
|
||||
|
||||
CHECK!(
|
||||
(lenT - lenB).abs() / lenB < 0.5
|
||||
@@ -140,7 +139,7 @@ fn Scan(
|
||||
);
|
||||
|
||||
// continue top row right until we cross the right line
|
||||
CHECK!(tlTracer.traceGaps(&tlTracer.right(), lineT, maxStepSize, lineR)?);
|
||||
CHECK!(tlTracer.traceGaps(tlTracer.right(), lineT, maxStepSize, lineR)?);
|
||||
|
||||
// #ifdef PRINT_DEBUG
|
||||
// printf("L: %.1f, %.1f ^ %.1f, %.1f > %.1f, %.1f (%d : %d : %d : %d)\n", bl.x, bl.y,
|
||||
@@ -173,8 +172,8 @@ fn Scan(
|
||||
f64::INFINITY
|
||||
};
|
||||
};
|
||||
splitDouble(lineT.modules(&tl, &tr)?, &mut dimT, &mut fracT);
|
||||
splitDouble(lineR.modules(&br, &tr)?, &mut dimR, &mut fracR);
|
||||
splitDouble(lineT.modules(tl, tr)?, &mut dimT, &mut fracT);
|
||||
splitDouble(lineR.modules(br, tr)?, &mut dimR, &mut fracR);
|
||||
|
||||
// #ifdef PRINT_DEBUG
|
||||
// printf("L: %.1f, %.1f ^ %.1f, %.1f > %.1f, %.1f ^> %.1f, %.1f\n", bl.x, bl.y,
|
||||
@@ -197,24 +196,18 @@ fn Scan(
|
||||
|
||||
CHECK!((10..=144).contains(&dimT) && (8..=144).contains(&dimR));
|
||||
|
||||
let movedTowardsBy = |a: &RXingResultPoint,
|
||||
b1: &RXingResultPoint,
|
||||
b2: &RXingResultPoint,
|
||||
d: f32|
|
||||
-> RXingResultPoint {
|
||||
*a + d * RXingResultPoint::normalized(
|
||||
RXingResultPoint::normalized(*b1 - *a) + RXingResultPoint::normalized(*b2 - *a),
|
||||
)
|
||||
let movedTowardsBy = |a: Point, b1: Point, b2: Point, d: f32| -> Point {
|
||||
a + d * Point::normalized(Point::normalized(b1 - a) + Point::normalized(b2 - a))
|
||||
};
|
||||
|
||||
// shrink shape by half a pixel to go from center of white pixel outside of code to the edge between white and black
|
||||
let sourcePoints = Quadrilateral::with_points(
|
||||
movedTowardsBy(&tl, &tr, &bl, 0.5),
|
||||
movedTowardsBy(tl, tr, bl, 0.5),
|
||||
// move the tr point a little less because the jagged top and right line tend to be statistically slightly
|
||||
// inclined toward the center anyway.
|
||||
movedTowardsBy(&tr, &br, &tl, 0.3),
|
||||
movedTowardsBy(&br, &bl, &tr, 0.5),
|
||||
movedTowardsBy(&bl, &tl, &br, 0.5),
|
||||
movedTowardsBy(tr, br, tl, 0.3),
|
||||
movedTowardsBy(br, bl, tr, 0.5),
|
||||
movedTowardsBy(bl, tl, br, 0.5),
|
||||
);
|
||||
|
||||
let grid_sampler = DefaultGridSampler::default();
|
||||
@@ -232,14 +225,14 @@ fn Scan(
|
||||
dimR as f32,
|
||||
0.0,
|
||||
dimR as f32,
|
||||
sourcePoints.topLeft().getX(),
|
||||
sourcePoints.topLeft().getY(),
|
||||
sourcePoints.topRight().getX(),
|
||||
sourcePoints.topRight().getY(),
|
||||
sourcePoints.bottomRight().getX(),
|
||||
sourcePoints.bottomRight().getY(),
|
||||
sourcePoints.bottomLeft().getX(),
|
||||
sourcePoints.bottomLeft().getY(),
|
||||
sourcePoints.topLeft().x,
|
||||
sourcePoints.topLeft().y,
|
||||
sourcePoints.topRight().x,
|
||||
sourcePoints.topRight().y,
|
||||
sourcePoints.bottomRight().x,
|
||||
sourcePoints.bottomRight().y,
|
||||
sourcePoints.bottomLeft().x,
|
||||
sourcePoints.bottomLeft().y,
|
||||
);
|
||||
|
||||
// let res = grid_sampler.sample_grid(startTracer.img, dimT as u32, dimR as u32, &transform);
|
||||
@@ -292,18 +285,17 @@ pub fn detect(
|
||||
const MIN_SYMBOL_SIZE: u32 = 8 * 2; // minimum realistic size in pixel: 8 modules x 2 pixels per module
|
||||
|
||||
for dir in [
|
||||
RXingResultPoint { x: -1.0, y: 0.0 },
|
||||
RXingResultPoint { x: 1.0, y: 0.0 },
|
||||
RXingResultPoint { x: 0.0, y: -1.0 },
|
||||
RXingResultPoint { x: 0.0, y: 1.0 },
|
||||
Point { x: -1.0, y: 0.0 },
|
||||
Point { x: 1.0, y: 0.0 },
|
||||
Point { x: 0.0, y: -1.0 },
|
||||
Point { x: 0.0, y: 1.0 },
|
||||
] {
|
||||
// for (auto dir : {PointF(-1, 0), PointF(1, 0), PointF(0, -1), PointF(0, 1)}) {
|
||||
let center = RXingResultPoint {
|
||||
let center = Point {
|
||||
x: (image.getWidth() / 2) as f32,
|
||||
y: (image.getHeight() / 2) as f32,
|
||||
}; //PointF(image.width() / 2, image.height() / 2);
|
||||
let startPos =
|
||||
RXingResultPoint::centered(&(center - center * dir + MIN_SYMBOL_SIZE as i32 / 2 * dir));
|
||||
let startPos = Point::centered(center - center * dir + MIN_SYMBOL_SIZE as i32 / 2 * dir);
|
||||
|
||||
if let Some(history) = &mut history {
|
||||
history.borrow_mut().clear(0);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::common::Result;
|
||||
use crate::{Exceptions, RXingResultPoint};
|
||||
use crate::{Exceptions, Point};
|
||||
|
||||
use super::{
|
||||
util::{float_max, float_min},
|
||||
@@ -8,8 +8,8 @@ use super::{
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DMRegressionLine {
|
||||
points: Vec<RXingResultPoint>,
|
||||
direction_inward: RXingResultPoint,
|
||||
points: Vec<Point>,
|
||||
direction_inward: Point,
|
||||
pub(super) a: f32,
|
||||
pub(super) b: f32,
|
||||
pub(super) c: f32,
|
||||
@@ -31,14 +31,13 @@ impl Default for DMRegressionLine {
|
||||
}
|
||||
|
||||
impl RegressionLine for DMRegressionLine {
|
||||
fn points(&self) -> &[RXingResultPoint] {
|
||||
fn points(&self) -> &[Point] {
|
||||
&self.points
|
||||
}
|
||||
|
||||
fn length(&self) -> u32 {
|
||||
if self.points.len() >= 2 {
|
||||
RXingResultPoint::distance(*self.points.first().unwrap(), *self.points.last().unwrap())
|
||||
as u32
|
||||
Point::distance(*self.points.first().unwrap(), *self.points.last().unwrap()) as u32
|
||||
} else {
|
||||
0
|
||||
}
|
||||
@@ -48,9 +47,9 @@ impl RegressionLine for DMRegressionLine {
|
||||
!self.a.is_nan()
|
||||
}
|
||||
|
||||
fn normal(&self) -> RXingResultPoint {
|
||||
fn normal(&self) -> Point {
|
||||
if self.isValid() {
|
||||
RXingResultPoint {
|
||||
Point {
|
||||
x: self.a,
|
||||
y: self.b,
|
||||
}
|
||||
@@ -59,29 +58,29 @@ impl RegressionLine for DMRegressionLine {
|
||||
}
|
||||
}
|
||||
|
||||
fn signedDistance(&self, p: &RXingResultPoint) -> f32 {
|
||||
RXingResultPoint::dot(self.normal(), *p) - self.c
|
||||
fn signedDistance(&self, p: Point) -> f32 {
|
||||
Point::dot(self.normal(), p) - self.c
|
||||
}
|
||||
|
||||
fn distance_single(&self, p: &RXingResultPoint) -> f32 {
|
||||
fn distance_single(&self, p: Point) -> f32 {
|
||||
(self.signedDistance(p)).abs()
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
self.points.clear();
|
||||
self.direction_inward = RXingResultPoint { x: 0.0, y: 0.0 };
|
||||
self.direction_inward = Point { x: 0.0, y: 0.0 };
|
||||
self.a = f32::NAN;
|
||||
self.b = f32::NAN;
|
||||
self.c = f32::NAN;
|
||||
}
|
||||
|
||||
fn add(&mut self, p: &RXingResultPoint) -> Result<()> {
|
||||
if self.direction_inward == RXingResultPoint::default() {
|
||||
fn add(&mut self, p: Point) -> Result<()> {
|
||||
if self.direction_inward == Point::default() {
|
||||
return Err(Exceptions::illegalState);
|
||||
}
|
||||
self.points.push(*p);
|
||||
self.points.push(p);
|
||||
if self.points.len() == 1 {
|
||||
self.c = RXingResultPoint::dot(self.normal(), *p);
|
||||
self.c = Point::dot(self.normal(), p);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -90,8 +89,8 @@ impl RegressionLine for DMRegressionLine {
|
||||
self.points.pop();
|
||||
}
|
||||
|
||||
fn setDirectionInward(&mut self, d: &RXingResultPoint) {
|
||||
self.direction_inward = RXingResultPoint::normalized(*d);
|
||||
fn setDirectionInward(&mut self, d: Point) {
|
||||
self.direction_inward = Point::normalized(d);
|
||||
}
|
||||
|
||||
fn evaluate_max_distance(
|
||||
@@ -113,7 +112,7 @@ impl RegressionLine for DMRegressionLine {
|
||||
// return sd > maxSignedDist || sd < -2 * maxSignedDist;
|
||||
// });
|
||||
// points.erase(end, points.end());
|
||||
points.retain(|p| {
|
||||
points.retain(|&p| {
|
||||
let sd = self.signedDistance(p) as f64;
|
||||
!(sd > maxSignedDist || sd < -2.0 * maxSignedDist)
|
||||
});
|
||||
@@ -143,14 +142,14 @@ impl RegressionLine for DMRegressionLine {
|
||||
max.y = float_max(max.y, p.y);
|
||||
}
|
||||
let diff = max - min;
|
||||
let len = RXingResultPoint::maxAbsComponent(&diff);
|
||||
let steps = float_min((diff.x).abs(), (diff.y).abs());
|
||||
let len = diff.maxAbsComponent();
|
||||
let steps = float_min(diff.x.abs(), diff.y.abs());
|
||||
// due to aliasing we get bad extrapolations if the line is short and too close to vertical/horizontal
|
||||
steps > 2.0 || len > 50.0
|
||||
}
|
||||
|
||||
fn evaluate(&mut self, points: &[RXingResultPoint]) -> bool {
|
||||
let mean = points.iter().sum::<RXingResultPoint>() / points.len() as f32;
|
||||
fn evaluate(&mut self, points: &[Point]) -> bool {
|
||||
let mean = points.iter().sum::<Point>() / points.len() as f32;
|
||||
|
||||
let mut sumXX = 0.0;
|
||||
let mut sumYY = 0.0;
|
||||
@@ -171,18 +170,18 @@ impl RegressionLine for DMRegressionLine {
|
||||
self.a = sumXY / l;
|
||||
self.b = -sumXX / l;
|
||||
}
|
||||
if RXingResultPoint::dot(self.direction_inward, self.normal()) < 0.0 {
|
||||
if Point::dot(self.direction_inward, self.normal()) < 0.0 {
|
||||
// if (dot(_directionInward, normal()) < 0) {
|
||||
self.a = -self.a;
|
||||
self.b = -self.b;
|
||||
}
|
||||
self.c = RXingResultPoint::dot(self.normal(), mean); // (a*mean.x + b*mean.y);
|
||||
RXingResultPoint::dot(self.direction_inward, self.normal()) > 0.5
|
||||
self.c = Point::dot(self.normal(), mean); // (a*mean.x + b*mean.y);
|
||||
Point::dot(self.direction_inward, self.normal()) > 0.5
|
||||
// angle between original and new direction is at most 60 degree
|
||||
}
|
||||
|
||||
fn evaluateSelf(&mut self) -> bool {
|
||||
let mean = self.points.iter().sum::<RXingResultPoint>() / self.points.len() as f32;
|
||||
let mean = self.points.iter().sum::<Point>() / self.points.len() as f32;
|
||||
|
||||
let mut sumXX = 0.0;
|
||||
let mut sumYY = 0.0;
|
||||
@@ -203,13 +202,13 @@ impl RegressionLine for DMRegressionLine {
|
||||
self.a = sumXY / l;
|
||||
self.b = -sumXX / l;
|
||||
}
|
||||
if RXingResultPoint::dot(self.direction_inward, self.normal()) < 0.0 {
|
||||
if Point::dot(self.direction_inward, self.normal()) < 0.0 {
|
||||
// if (dot(_directionInward, normal()) < 0) {
|
||||
self.a = -self.a;
|
||||
self.b = -self.b;
|
||||
}
|
||||
self.c = RXingResultPoint::dot(self.normal(), mean); // (a*mean.x + b*mean.y);
|
||||
RXingResultPoint::dot(self.direction_inward, self.normal()) > 0.5
|
||||
self.c = Point::dot(self.normal(), mean); // (a*mean.x + b*mean.y);
|
||||
Point::dot(self.direction_inward, self.normal()) > 0.5
|
||||
// angle between original and new direction is at most 60 degree
|
||||
}
|
||||
}
|
||||
@@ -236,7 +235,7 @@ impl DMRegressionLine {
|
||||
self.points.reverse();
|
||||
}
|
||||
|
||||
pub fn modules(&mut self, beg: &RXingResultPoint, end: &RXingResultPoint) -> Result<f64> {
|
||||
pub fn modules(&mut self, beg: Point, end: Point) -> Result<f64> {
|
||||
if self.points.len() <= 3 {
|
||||
return Err(Exceptions::illegalState);
|
||||
}
|
||||
@@ -253,21 +252,28 @@ impl DMRegressionLine {
|
||||
// calculate the distance between the points projected onto the regression line
|
||||
for i in 1..self.points.len() {
|
||||
// for (size_t i = 1; i < _points.size(); ++i)
|
||||
gapSizes.push(self.distance(
|
||||
&self.project(&self.points[i]),
|
||||
&self.project(&self.points[i - 1]),
|
||||
gapSizes.push(Point::distance(
|
||||
self.project(self.points[i]),
|
||||
self.project(self.points[i - 1]),
|
||||
) as f64);
|
||||
}
|
||||
|
||||
// calculate the (expected average) distance of two adjacent pixels
|
||||
let unitPixelDist = RXingResultPoint::length(RXingResultPoint::bresenhamDirection(
|
||||
&(*self.points.last().ok_or(Exceptions::indexOutOfBounds)?
|
||||
- *self.points.first().ok_or(Exceptions::indexOutOfBounds)?),
|
||||
let unitPixelDist = Point::length(Point::bresenhamDirection(
|
||||
self.points
|
||||
.last()
|
||||
.copied()
|
||||
.ok_or(Exceptions::indexOutOfBounds)?
|
||||
- self
|
||||
.points
|
||||
.first()
|
||||
.copied()
|
||||
.ok_or(Exceptions::indexOutOfBounds)?,
|
||||
)) as f64;
|
||||
|
||||
// calculate the width of 2 modules (first black pixel to first black pixel)
|
||||
let mut sumFront: f64 =
|
||||
self.distance(beg, &self.project(&self.points[0])) as f64 - unitPixelDist;
|
||||
Point::distance(beg, self.project(self.points[0])) as f64 - unitPixelDist;
|
||||
let mut sumBack: f64 = 0.0; // (last black pixel to last black pixel)
|
||||
for dist in gapSizes {
|
||||
// for (auto dist : gapSizes) {
|
||||
@@ -283,13 +289,18 @@ impl DMRegressionLine {
|
||||
|
||||
modSizes.push(
|
||||
sumFront
|
||||
+ self.distance(
|
||||
+ Point::distance(
|
||||
end,
|
||||
&self.project(self.points.last().ok_or(Exceptions::indexOutOfBounds)?),
|
||||
self.project(
|
||||
self.points
|
||||
.last()
|
||||
.copied()
|
||||
.ok_or(Exceptions::indexOutOfBounds)?,
|
||||
),
|
||||
) as f64,
|
||||
);
|
||||
modSizes[0] = 0.0; // the first element is an invalid sumBack value, would be pop_front() if vector supported this
|
||||
let lineLength = self.distance(beg, end) as f64 - unitPixelDist;
|
||||
let lineLength = Point::distance(beg, end) as f64 - unitPixelDist;
|
||||
let mut meanModSize = Self::average(&modSizes, |_: f64| true);
|
||||
// let meanModSize = average(modSizes, [](double){ return true; });
|
||||
// #ifdef PRINT_DEBUG
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::{cell::RefCell, rc::Rc};
|
||||
use crate::{
|
||||
common::{BitMatrix, Result},
|
||||
qrcode::encoder::ByteMatrix,
|
||||
Exceptions, RXingResultPoint,
|
||||
Exceptions, Point,
|
||||
};
|
||||
|
||||
use super::{BitMatrixCursor, Direction, RegressionLine, StepResult, Value};
|
||||
@@ -12,8 +12,8 @@ use super::{BitMatrixCursor, Direction, RegressionLine, StepResult, Value};
|
||||
pub struct EdgeTracer<'a> {
|
||||
pub(super) img: &'a BitMatrix,
|
||||
|
||||
pub(super) p: RXingResultPoint, // current position
|
||||
d: RXingResultPoint, // current direction
|
||||
pub(super) p: Point, // current position
|
||||
d: Point, // current direction
|
||||
|
||||
// pub history: Option<&'a mut ByteMatrix>, // = nullptr;
|
||||
pub history: Option<Rc<RefCell<ByteMatrix>>>,
|
||||
@@ -35,7 +35,7 @@ pub struct EdgeTracer<'a> {
|
||||
// }
|
||||
|
||||
impl BitMatrixCursor for EdgeTracer<'_> {
|
||||
fn testAt(&self, p: &RXingResultPoint) -> Value {
|
||||
fn testAt(&self, p: Point) -> Value {
|
||||
if self.img.isIn(p, 0) {
|
||||
Value::from(self.img.get_point(p))
|
||||
} else {
|
||||
@@ -43,42 +43,42 @@ impl BitMatrixCursor for EdgeTracer<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn isIn(&self, p: &RXingResultPoint) -> bool {
|
||||
fn isIn(&self, p: Point) -> bool {
|
||||
self.img.isIn(p, 0)
|
||||
}
|
||||
|
||||
fn isInSelf(&self) -> bool {
|
||||
self.isIn(&self.p)
|
||||
self.isIn(self.p)
|
||||
}
|
||||
|
||||
fn isBlack(&self) -> bool {
|
||||
self.blackAt(&self.p)
|
||||
self.blackAt(self.p)
|
||||
}
|
||||
|
||||
fn isWhite(&self) -> bool {
|
||||
self.whiteAt(&self.p)
|
||||
self.whiteAt(self.p)
|
||||
}
|
||||
|
||||
fn front(&self) -> &RXingResultPoint {
|
||||
fn front(&self) -> &Point {
|
||||
&self.d
|
||||
}
|
||||
|
||||
fn back(&self) -> RXingResultPoint {
|
||||
RXingResultPoint {
|
||||
fn back(&self) -> Point {
|
||||
Point {
|
||||
x: -self.d.x,
|
||||
y: -self.d.y,
|
||||
}
|
||||
}
|
||||
|
||||
fn left(&self) -> RXingResultPoint {
|
||||
RXingResultPoint {
|
||||
fn left(&self) -> Point {
|
||||
Point {
|
||||
x: self.d.y,
|
||||
y: -self.d.x,
|
||||
}
|
||||
}
|
||||
|
||||
fn right(&self) -> RXingResultPoint {
|
||||
RXingResultPoint {
|
||||
fn right(&self) -> Point {
|
||||
Point {
|
||||
x: -self.d.y,
|
||||
y: self.d.x,
|
||||
}
|
||||
@@ -100,28 +100,28 @@ impl BitMatrixCursor for EdgeTracer<'_> {
|
||||
self.d = self.direction(dir)
|
||||
}
|
||||
|
||||
fn edgeAt_point(&self, d: &RXingResultPoint) -> Value {
|
||||
let v = self.testAt(&self.p);
|
||||
if self.testAt(&(self.p + *d)) != v {
|
||||
fn edgeAt_point(&self, d: Point) -> Value {
|
||||
let v = self.testAt(self.p);
|
||||
if self.testAt(self.p + d) != v {
|
||||
v
|
||||
} else {
|
||||
Value::Invalid
|
||||
}
|
||||
}
|
||||
|
||||
fn setDirection(&mut self, dir: &RXingResultPoint) {
|
||||
self.d = RXingResultPoint::bresenhamDirection(dir)
|
||||
fn setDirection(&mut self, dir: Point) {
|
||||
self.d = dir.bresenhamDirection();
|
||||
}
|
||||
|
||||
fn step(&mut self, s: Option<f32>) -> bool {
|
||||
let s = if let Some(s) = s { s } else { 1.0 };
|
||||
self.p += self.d * s;
|
||||
self.isIn(&self.p)
|
||||
self.isIn(self.p)
|
||||
}
|
||||
|
||||
fn movedBy<T: BitMatrixCursor>(self, d: &RXingResultPoint) -> Self {
|
||||
fn movedBy<T: BitMatrixCursor>(self, d: Point) -> Self {
|
||||
let mut res = self;
|
||||
res.p += *d;
|
||||
res.p += d;
|
||||
|
||||
res
|
||||
}
|
||||
@@ -139,11 +139,11 @@ impl BitMatrixCursor for EdgeTracer<'_> {
|
||||
let backup = if let Some(b) = backup { b } else { false };
|
||||
// TODO: provide an alternative and faster out-of-bounds check than isIn() inside testAt()
|
||||
let mut steps = 0;
|
||||
let mut lv = self.testAt(&self.p);
|
||||
let mut lv = self.testAt(self.p);
|
||||
|
||||
while nth > 0 && (range <= 0 || steps < range) && lv.isValid() {
|
||||
steps += 1;
|
||||
let v = self.testAt(&(self.p + steps * self.d));
|
||||
let v = self.testAt(self.p + steps * self.d);
|
||||
if lv != v {
|
||||
lv = v;
|
||||
nth -= 1;
|
||||
@@ -158,7 +158,7 @@ impl BitMatrixCursor for EdgeTracer<'_> {
|
||||
}
|
||||
|
||||
impl<'a> EdgeTracer<'_> {
|
||||
pub fn new(image: &'a BitMatrix, p: RXingResultPoint, d: RXingResultPoint) -> EdgeTracer<'a> {
|
||||
pub fn new(image: &'a BitMatrix, p: Point, d: Point) -> EdgeTracer<'a> {
|
||||
// : img(&image), p(p) { setDirection(d); }
|
||||
EdgeTracer {
|
||||
img: image,
|
||||
@@ -171,11 +171,11 @@ impl<'a> EdgeTracer<'_> {
|
||||
|
||||
fn traceStep(
|
||||
&mut self,
|
||||
dEdge: &RXingResultPoint,
|
||||
dEdge: Point,
|
||||
maxStepSize: i32,
|
||||
goodDirection: bool,
|
||||
) -> Result<StepResult> {
|
||||
let dEdge = RXingResultPoint::mainDirection(*dEdge);
|
||||
let dEdge = Point::mainDirection(dEdge);
|
||||
for breadth in 1..=(if maxStepSize == 1 {
|
||||
2
|
||||
} else if goodDirection {
|
||||
@@ -193,19 +193,19 @@ impl<'a> EdgeTracer<'_> {
|
||||
+ (if i & 1 > 0 { (i + 1) / 2 } else { -i / 2 }) * dEdge;
|
||||
// dbg!(pEdge);
|
||||
|
||||
if !self.blackAt(&(pEdge + dEdge)) {
|
||||
if !self.blackAt(pEdge + dEdge) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// found black pixel -> go 'outward' until we hit the b/w border
|
||||
for _j in 0..(std::cmp::max(maxStepSize, 3)) {
|
||||
// for (int j = 0; j < std::max(maxStepSize, 3) && isIn(pEdge); ++j) {
|
||||
if self.whiteAt(&pEdge) {
|
||||
if self.whiteAt(pEdge) {
|
||||
// if we are not making any progress, we still have another endless loop bug
|
||||
if self.p == RXingResultPoint::centered(&pEdge) {
|
||||
if self.p == pEdge.centered() {
|
||||
return Err(Exceptions::illegalState);
|
||||
}
|
||||
self.p = RXingResultPoint::centered(&pEdge);
|
||||
self.p = pEdge.centered();
|
||||
|
||||
// if (self.history && maxStepSize == 1) {
|
||||
if let Some(history) = &self.history {
|
||||
@@ -226,12 +226,12 @@ impl<'a> EdgeTracer<'_> {
|
||||
return Ok(StepResult::Found);
|
||||
}
|
||||
pEdge = pEdge - dEdge;
|
||||
if self.blackAt(&(pEdge - self.d)) {
|
||||
if self.blackAt(pEdge - self.d) {
|
||||
pEdge = pEdge - self.d;
|
||||
}
|
||||
// dbg!(pEdge);
|
||||
|
||||
if !self.isIn(&pEdge) {
|
||||
if !self.isIn(pEdge) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -243,45 +243,38 @@ impl<'a> EdgeTracer<'_> {
|
||||
Ok(StepResult::OpenEnd)
|
||||
}
|
||||
|
||||
pub fn updateDirectionFromOrigin(&mut self, origin: &RXingResultPoint) -> bool {
|
||||
pub fn updateDirectionFromOrigin(&mut self, origin: Point) -> bool {
|
||||
let old_d = self.d;
|
||||
self.setDirection(&(self.p - origin));
|
||||
self.setDirection(self.p - origin);
|
||||
// if the new direction is pointing "backward", i.e. angle(new, old) > 90 deg -> break
|
||||
if RXingResultPoint::dot(self.d, old_d) < 0.0 {
|
||||
if Point::dot(self.d, old_d) < 0.0 {
|
||||
return false;
|
||||
}
|
||||
// make sure d stays in the same quadrant to prevent an infinite loop
|
||||
if (self.d.x).abs() == (self.d.y).abs() {
|
||||
self.d = RXingResultPoint::mainDirection(old_d)
|
||||
+ 0.99 * (self.d - RXingResultPoint::mainDirection(old_d));
|
||||
} else if RXingResultPoint::mainDirection(self.d) != RXingResultPoint::mainDirection(old_d)
|
||||
{
|
||||
self.d = RXingResultPoint::mainDirection(old_d)
|
||||
+ 0.99 * RXingResultPoint::mainDirection(self.d);
|
||||
self.d = Point::mainDirection(old_d) + 0.99 * (self.d - Point::mainDirection(old_d));
|
||||
} else if Point::mainDirection(self.d) != Point::mainDirection(old_d) {
|
||||
self.d = Point::mainDirection(old_d) + 0.99 * Point::mainDirection(self.d);
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn traceLine<T: RegressionLine>(
|
||||
&mut self,
|
||||
dEdge: &RXingResultPoint,
|
||||
line: &mut T,
|
||||
) -> Result<bool> {
|
||||
pub fn traceLine<T: RegressionLine>(&mut self, dEdge: Point, line: &mut T) -> Result<bool> {
|
||||
line.setDirectionInward(dEdge);
|
||||
loop {
|
||||
// log(self.p);
|
||||
line.add(&self.p)?;
|
||||
line.add(self.p)?;
|
||||
if line.points().len() % 50 == 10 {
|
||||
if !line.evaluate_max_distance(None, None) {
|
||||
return Ok(false);
|
||||
}
|
||||
if !self.updateDirectionFromOrigin(
|
||||
&(self.p - line.project(&self.p)
|
||||
self.p - line.project(self.p)
|
||||
+ **line
|
||||
.points()
|
||||
.first()
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::indexOutOfBounds)?),
|
||||
.ok_or(Exceptions::indexOutOfBounds)?,
|
||||
) {
|
||||
return Ok(false);
|
||||
}
|
||||
@@ -295,7 +288,7 @@ impl<'a> EdgeTracer<'_> {
|
||||
|
||||
pub fn traceGaps<T: RegressionLine>(
|
||||
&mut self,
|
||||
dEdge: &RXingResultPoint,
|
||||
dEdge: Point,
|
||||
line: &mut T,
|
||||
maxStepSize: i32,
|
||||
finishLine: &mut T,
|
||||
@@ -329,21 +322,19 @@ impl<'a> EdgeTracer<'_> {
|
||||
|
||||
// if we drifted too far outside of the code, break
|
||||
if line.isValid()
|
||||
&& line.signedDistance(&self.p) < -5.0
|
||||
&& (!line.evaluate_max_distance(None, None) || line.signedDistance(&self.p) < -5.0)
|
||||
&& line.signedDistance(self.p) < -5.0
|
||||
&& (!line.evaluate_max_distance(None, None) || line.signedDistance(self.p) < -5.0)
|
||||
{
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
// if we are drifting towards the inside of the code, pull the current position back out onto the line
|
||||
if line.isValid() && line.signedDistance(&self.p) > 3.0 {
|
||||
if line.isValid() && line.signedDistance(self.p) > 3.0 {
|
||||
// The current direction d and the line we are tracing are supposed to be roughly parallel.
|
||||
// In case the 'go outward' step in traceStep lead us astray, we might end up with a line
|
||||
// that is almost perpendicular to d. Then the back-projection below can result in an
|
||||
// endless loop. Break if the angle between d and line is greater than 45 deg.
|
||||
if (RXingResultPoint::dot(RXingResultPoint::normalized(self.d), line.normal()))
|
||||
.abs()
|
||||
> 0.7
|
||||
if (Point::dot(Point::normalized(self.d), line.normal())).abs() > 0.7
|
||||
// thresh is approx. sin(45 deg)
|
||||
{
|
||||
return Ok(false);
|
||||
@@ -354,36 +345,41 @@ impl<'a> EdgeTracer<'_> {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let mut np = line.project(&self.p);
|
||||
let mut np = line.project(self.p);
|
||||
// make sure we are making progress even when back-projecting:
|
||||
// consider a 90deg corner, rotated 45deg. we step away perpendicular from the line and get
|
||||
// back projected where we left off the line.
|
||||
// The 'while' instead of 'if' was introduced to fix the issue with #245. It turns out that
|
||||
// np can actually be behind the projection of the last line point and we need 2 steps in d
|
||||
// to prevent a dead lock. see #245.png
|
||||
while RXingResultPoint::distance(
|
||||
while Point::distance(
|
||||
np,
|
||||
line.project(
|
||||
line.points()
|
||||
.last()
|
||||
.as_ref()
|
||||
.copied()
|
||||
.ok_or(Exceptions::indexOutOfBounds)?,
|
||||
),
|
||||
) < 1.0
|
||||
{
|
||||
np += self.d;
|
||||
}
|
||||
self.p = RXingResultPoint::centered(&np);
|
||||
self.p = Point::centered(np);
|
||||
} else {
|
||||
let stepLengthInMainDir = if line.points().is_empty() {
|
||||
0.0
|
||||
} else {
|
||||
RXingResultPoint::dot(
|
||||
RXingResultPoint::mainDirection(self.d),
|
||||
self.p - line.points().last().ok_or(Exceptions::indexOutOfBounds)?,
|
||||
Point::dot(
|
||||
Point::mainDirection(self.d),
|
||||
self.p
|
||||
- line
|
||||
.points()
|
||||
.last()
|
||||
.copied()
|
||||
.ok_or(Exceptions::indexOutOfBounds)?,
|
||||
)
|
||||
};
|
||||
line.add(&self.p)?;
|
||||
line.add(self.p)?;
|
||||
|
||||
if stepLengthInMainDir > 1.0 {
|
||||
gaps += 1;
|
||||
@@ -392,8 +388,12 @@ impl<'a> EdgeTracer<'_> {
|
||||
return Ok(false);
|
||||
}
|
||||
if !self.updateDirectionFromOrigin(
|
||||
&(self.p - line.project(&self.p)
|
||||
+ *line.points().first().ok_or(Exceptions::indexOutOfBounds)?),
|
||||
self.p - line.project(self.p)
|
||||
+ line
|
||||
.points()
|
||||
.first()
|
||||
.copied()
|
||||
.ok_or(Exceptions::indexOutOfBounds)?,
|
||||
) {
|
||||
return Ok(false);
|
||||
}
|
||||
@@ -415,7 +415,7 @@ impl<'a> EdgeTracer<'_> {
|
||||
|
||||
if finishLine.isValid() {
|
||||
maxStepSize =
|
||||
std::cmp::min(maxStepSize, (finishLine.signedDistance(&self.p)) as i32);
|
||||
std::cmp::min(maxStepSize, (finishLine.signedDistance(self.p)) as i32);
|
||||
}
|
||||
|
||||
let stepResult = self.traceStep(dEdge, maxStepSize, line.isValid())?;
|
||||
@@ -425,24 +425,20 @@ impl<'a> EdgeTracer<'_> {
|
||||
{
|
||||
return Ok(stepResult == StepResult::OpenEnd
|
||||
&& finishLine.isValid()
|
||||
&& (finishLine.signedDistance(&self.p)) as i32 <= maxStepSize + 1);
|
||||
&& (finishLine.signedDistance(self.p)) as i32 <= maxStepSize + 1);
|
||||
}
|
||||
} //while (true);
|
||||
}
|
||||
|
||||
pub fn traceCorner(
|
||||
&mut self,
|
||||
dir: &mut RXingResultPoint,
|
||||
corner: &mut RXingResultPoint,
|
||||
) -> Result<bool> {
|
||||
pub fn traceCorner(&mut self, dir: &mut Point, corner: &mut Point) -> Result<bool> {
|
||||
self.step(None);
|
||||
// log(p);
|
||||
*corner = self.p;
|
||||
std::mem::swap(&mut self.d, dir);
|
||||
self.traceStep(&(-1.0 * dir), 2, false)?;
|
||||
self.traceStep(-1.0 * (*dir), 2, false)?;
|
||||
// #ifdef PRINT_DEBUG
|
||||
// printf("turn: %.0f x %.0f -> %.2f, %.2f\n", p.x, p.y, d.x, d.y);
|
||||
// #endif
|
||||
Ok(self.isIn(corner) && self.isIn(&self.p))
|
||||
Ok(self.isIn(*corner) && self.isIn(self.p))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::RXingResultPoint;
|
||||
use crate::Point;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Quadrilateral([RXingResultPoint; 4]);
|
||||
pub struct Quadrilateral([Point; 4]);
|
||||
|
||||
impl Quadrilateral {
|
||||
// using Base = std::array<T, 4>;
|
||||
@@ -11,31 +11,26 @@ impl Quadrilateral {
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new() -> Self {
|
||||
Self([RXingResultPoint { x: 0.0, y: 0.0 }; 4])
|
||||
Self([Point { x: 0.0, y: 0.0 }; 4])
|
||||
}
|
||||
// pub fn with_f32( tl:f32, tr:f32, br:f32, bl:f32) -> Self {
|
||||
// Self([tl, tr,br, bl ])
|
||||
// }
|
||||
|
||||
pub fn with_points(
|
||||
tl: RXingResultPoint,
|
||||
tr: RXingResultPoint,
|
||||
br: RXingResultPoint,
|
||||
bl: RXingResultPoint,
|
||||
) -> Self {
|
||||
pub fn with_points(tl: Point, tr: Point, br: Point, bl: Point) -> Self {
|
||||
Self([tl, tr, br, bl])
|
||||
}
|
||||
|
||||
pub fn topLeft(&self) -> &RXingResultPoint {
|
||||
pub fn topLeft(&self) -> &Point {
|
||||
&self.0[0]
|
||||
} //const noexcept { return at(0); }
|
||||
pub fn topRight(&self) -> &RXingResultPoint {
|
||||
pub fn topRight(&self) -> &Point {
|
||||
&self.0[1]
|
||||
} //const noexcept { return at(1); }
|
||||
pub fn bottomRight(&self) -> &RXingResultPoint {
|
||||
pub fn bottomRight(&self) -> &Point {
|
||||
&self.0[2]
|
||||
} //const noexcept { return at(2); }
|
||||
pub fn bottomLeft(&self) -> &RXingResultPoint {
|
||||
pub fn bottomLeft(&self) -> &Point {
|
||||
&self.0[3]
|
||||
} //const noexcept { return at(3); }
|
||||
|
||||
@@ -43,13 +38,13 @@ impl Quadrilateral {
|
||||
pub fn orientation(&self) -> f64 {
|
||||
let centerLine =
|
||||
(*self.topRight() + *self.bottomRight()) - (*self.topLeft() + *self.bottomLeft());
|
||||
if (centerLine == RXingResultPoint { x: 0.0, y: 0.0 }) {
|
||||
if (centerLine == Point { x: 0.0, y: 0.0 }) {
|
||||
return 0.0;
|
||||
}
|
||||
let centerLineF = RXingResultPoint::normalized(centerLine);
|
||||
let centerLineF = Point::normalized(centerLine);
|
||||
f32::atan2(centerLineF.y, centerLineF.x).into()
|
||||
}
|
||||
pub fn points(&self) -> &[RXingResultPoint] {
|
||||
pub fn points(&self) -> &[Point] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
@@ -59,19 +54,19 @@ pub fn Rectangle(width: i32, height: i32, margin: Option<i32>) -> Quadrilateral
|
||||
let margin = if let Some(m) = margin { m } else { 0 };
|
||||
|
||||
Quadrilateral([
|
||||
RXingResultPoint {
|
||||
Point {
|
||||
x: margin as f32,
|
||||
y: margin as f32,
|
||||
},
|
||||
RXingResultPoint {
|
||||
Point {
|
||||
x: width as f32 - margin as f32,
|
||||
y: margin as f32,
|
||||
},
|
||||
RXingResultPoint {
|
||||
Point {
|
||||
x: width as f32 - margin as f32,
|
||||
y: height as f32 - margin as f32,
|
||||
},
|
||||
RXingResultPoint {
|
||||
Point {
|
||||
x: margin as f32,
|
||||
y: height as f32 - margin as f32,
|
||||
},
|
||||
@@ -82,10 +77,10 @@ pub fn Rectangle(width: i32, height: i32, margin: Option<i32>) -> Quadrilateral
|
||||
pub fn CenteredSquare(size: i32) -> Quadrilateral {
|
||||
Scale(
|
||||
&Quadrilateral([
|
||||
RXingResultPoint { x: -1.0, y: -1.0 },
|
||||
RXingResultPoint { x: 1.0, y: -1.0 },
|
||||
RXingResultPoint { x: 1.0, y: 1.0 },
|
||||
RXingResultPoint { x: -1.0, y: 1.0 },
|
||||
Point { x: -1.0, y: -1.0 },
|
||||
Point { x: 1.0, y: -1.0 },
|
||||
Point { x: 1.0, y: 1.0 },
|
||||
Point { x: -1.0, y: 1.0 },
|
||||
]),
|
||||
size / 2,
|
||||
)
|
||||
@@ -94,19 +89,19 @@ pub fn CenteredSquare(size: i32) -> Quadrilateral {
|
||||
#[allow(dead_code)]
|
||||
pub fn Line(y: i32, xStart: i32, xStop: i32) -> Quadrilateral {
|
||||
Quadrilateral([
|
||||
RXingResultPoint {
|
||||
Point {
|
||||
x: xStart as f32,
|
||||
y: y as f32,
|
||||
},
|
||||
RXingResultPoint {
|
||||
Point {
|
||||
x: xStop as f32,
|
||||
y: y as f32,
|
||||
},
|
||||
RXingResultPoint {
|
||||
Point {
|
||||
x: xStop as f32,
|
||||
y: y as f32,
|
||||
},
|
||||
RXingResultPoint {
|
||||
Point {
|
||||
x: xStart as f32,
|
||||
y: y as f32,
|
||||
},
|
||||
@@ -126,7 +121,7 @@ pub fn IsConvex(poly: &Quadrilateral) -> bool {
|
||||
{
|
||||
let d1 = poly.0[(i + 2) % N] - poly.0[(i + 1) % N];
|
||||
let d2 = poly.0[i] - poly.0[(i + 1) % N];
|
||||
let cp = RXingResultPoint::cross(&d1, &d2);
|
||||
let cp = d1.cross(d2);
|
||||
|
||||
m = if m.abs() > cp { cp } else { m.abs() };
|
||||
|
||||
@@ -162,8 +157,8 @@ pub fn Scale(q: &Quadrilateral, factor: i32) -> Quadrilateral {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn Center(q: &Quadrilateral) -> RXingResultPoint {
|
||||
let reduced: RXingResultPoint = q.0.iter().sum();
|
||||
pub fn Center(q: &Quadrilateral) -> Point {
|
||||
let reduced: Point = q.0.iter().sum();
|
||||
let size = q.0.len() as f32;
|
||||
reduced / size
|
||||
// return Reduce(q) / Size(q);
|
||||
@@ -186,14 +181,14 @@ pub fn RotatedCorners(q: &Quadrilateral, n: Option<i32>, mirror: Option<bool>) -
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn IsInside(p: &RXingResultPoint, q: &Quadrilateral) -> bool {
|
||||
pub fn IsInside(p: Point, q: &Quadrilateral) -> bool {
|
||||
// Test if p is on the same side (right or left) of all polygon segments
|
||||
let mut pos = 0;
|
||||
let mut neg = 0;
|
||||
for i in 0..q.0.len()
|
||||
// for (int i = 0; i < Size(q); ++i)
|
||||
{
|
||||
if RXingResultPoint::cross(&(*p - q.0[i]), &(q.0[(i + 1) % q.0.len()] - q.0[i])) < 0.0 {
|
||||
if Point::cross(p - q.0[i], q.0[(i + 1) % q.0.len()] - q.0[i]) < 0.0 {
|
||||
neg += 1;
|
||||
} else {
|
||||
pos += 1;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use crate::common::Result;
|
||||
use crate::RXingResultPoint;
|
||||
use crate::Point;
|
||||
|
||||
pub trait RegressionLine {
|
||||
// points: Vec<RXingResultPoint>,
|
||||
// direction_inward: RXingResultPoint,
|
||||
// points: Vec<Point>,
|
||||
// direction_inward: Point,
|
||||
|
||||
// }
|
||||
// impl RegressionLine {
|
||||
@@ -12,9 +12,9 @@ pub trait RegressionLine {
|
||||
// PointF::value_t a = NAN, b = NAN, c = NAN;
|
||||
|
||||
// fn intersect<T: RegressionLine, T2: RegressionLine>(&self, l1: &T, l2: &T2)
|
||||
// -> RXingResultPoint;
|
||||
// -> Point;
|
||||
|
||||
// fn evaluate_begin_end(&self, begin:&RXingResultPoint, end:&RXingResultPoint) -> bool;// {
|
||||
// fn evaluate_begin_end(&self, begin: Point, end: Point) -> bool;// {
|
||||
// {
|
||||
// let mean = std::accumulate(begin, end, PointF()) / std::distance(begin, end);
|
||||
// PointF::value_t sumXX = 0, sumYY = 0, sumXY = 0;
|
||||
@@ -41,13 +41,9 @@ pub trait RegressionLine {
|
||||
// return dot(_directionInward, normal()) > 0.5f; // angle between original and new direction is at most 60 degree
|
||||
// }
|
||||
|
||||
fn evaluate(&mut self, points: &[RXingResultPoint]) -> bool; // { return self.evaluate_begin_end(&points.front(), &points.back() + 1); }
|
||||
fn evaluate(&mut self, points: &[Point]) -> bool; // { return self.evaluate_begin_end(&points.front(), &points.back() + 1); }
|
||||
fn evaluateSelf(&mut self) -> bool;
|
||||
|
||||
fn distance(&self, a: &RXingResultPoint, b: &RXingResultPoint) -> f32 {
|
||||
crate::result_point_utils::distance(a, b)
|
||||
}
|
||||
|
||||
// RegressionLine() { _points.reserve(16); } // arbitrary but plausible start size (tiny performance improvement)
|
||||
|
||||
// template<typename T> RegressionLine(PointT<T> a, PointT<T> b)
|
||||
@@ -60,14 +56,14 @@ pub trait RegressionLine {
|
||||
// evaluate(b, e);
|
||||
// }
|
||||
|
||||
fn points(&self) -> &[RXingResultPoint]; //const { return _points; }
|
||||
fn points(&self) -> &[Point]; //const { return _points; }
|
||||
fn length(&self) -> u32; //const { return _points.size() >= 2 ? int(distance(_points.front(), _points.back())) : 0; }
|
||||
fn isValid(&self) -> bool; //const { return !std::isnan(a); }
|
||||
fn normal(&self) -> RXingResultPoint; //const { return isValid() ? PointF(a, b) : _directionInward; }
|
||||
fn signedDistance(&self, p: &RXingResultPoint) -> f32; //const { return dot(normal(), p) - c; }
|
||||
fn distance_single(&self, p: &RXingResultPoint) -> f32; //const { return std::abs(signedDistance(PointF(p))); }
|
||||
fn project(&self, p: &RXingResultPoint) -> RXingResultPoint {
|
||||
*p - self.normal() * self.signedDistance(p)
|
||||
fn normal(&self) -> Point; //const { return isValid() ? PointF(a, b) : _directionInward; }
|
||||
fn signedDistance(&self, p: Point) -> f32; //const { return dot(normal(), p) - c; }
|
||||
fn distance_single(&self, p: Point) -> f32; //const { return std::abs(signedDistance(PointF(p))); }
|
||||
fn project(&self, p: Point) -> Point {
|
||||
p - self.normal() * self.signedDistance(p)
|
||||
}
|
||||
|
||||
fn reset(&mut self);
|
||||
@@ -77,16 +73,16 @@ pub trait RegressionLine {
|
||||
// a = b = c = NAN;
|
||||
// }
|
||||
|
||||
fn add(&mut self, p: &RXingResultPoint) -> Result<()>; //{
|
||||
// assert(_directionInward != PointF());
|
||||
// _points.push_back(p);
|
||||
// if (_points.size() == 1)
|
||||
// c = dot(normal(), p);
|
||||
// }
|
||||
fn add(&mut self, p: Point) -> Result<()>; //{
|
||||
// assert(_directionInward != PointF());
|
||||
// _points.push_back(p);
|
||||
// if (_points.size() == 1)
|
||||
// c = dot(normal(), p);
|
||||
// }
|
||||
|
||||
fn pop_back(&mut self); // { _points.pop_back(); }
|
||||
|
||||
fn setDirectionInward(&mut self, d: &RXingResultPoint); //{ _directionInward = normalized(d); }
|
||||
fn setDirectionInward(&mut self, d: Point); //{ _directionInward = normalized(d); }
|
||||
|
||||
// fn evaluate(&self, double maxSignedDist = -1, bool updatePoints = false) -> bool
|
||||
fn evaluate_max_distance(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::common::Result;
|
||||
use crate::{Exceptions, RXingResultPoint};
|
||||
use crate::{Exceptions, Point};
|
||||
|
||||
use super::{DMRegressionLine, Direction, RegressionLine};
|
||||
|
||||
@@ -22,14 +22,14 @@ pub fn float_max<T: PartialOrd>(a: T, b: T) -> T {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn intersect(l1: &DMRegressionLine, l2: &DMRegressionLine) -> Result<RXingResultPoint> {
|
||||
pub fn intersect(l1: &DMRegressionLine, l2: &DMRegressionLine) -> Result<Point> {
|
||||
if !(l1.isValid() && l2.isValid()) {
|
||||
return Err(Exceptions::illegalState);
|
||||
}
|
||||
let d = l1.a * l2.b - l1.b * l2.a;
|
||||
let x = (l1.c * l2.b - l1.b * l2.c) / d;
|
||||
let y = (l1.a * l2.c - l1.c * l2.a) / d;
|
||||
Ok(RXingResultPoint { x, y })
|
||||
Ok(Point { x, y })
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::{BarcodeFormat, RXingResultPointCallback};
|
||||
use crate::{BarcodeFormat, PointCallback};
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -89,8 +89,8 @@ pub enum DecodeHintType {
|
||||
RETURN_CODABAR_START_END,
|
||||
|
||||
/**
|
||||
* The caller needs to be notified via callback when a possible {@link RXingResultPoint}
|
||||
* is found. Maps to a {@link RXingResultPointCallback}.
|
||||
* The caller needs to be notified via callback when a possible {@link Point}
|
||||
* is found. Maps to a {@link PointCallback}.
|
||||
*/
|
||||
NEED_RESULT_POINT_CALLBACK,
|
||||
|
||||
@@ -198,11 +198,11 @@ pub enum DecodeHintValue {
|
||||
ReturnCodabarStartEnd(bool),
|
||||
|
||||
/**
|
||||
* The caller needs to be notified via callback when a possible {@link RXingResultPoint}
|
||||
* is found. Maps to a {@link RXingResultPointCallback}.
|
||||
* The caller needs to be notified via callback when a possible {@link Point}
|
||||
* is found. Maps to a {@link PointCallback}.
|
||||
*/
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing, skip_deserializing))]
|
||||
NeedResultPointCallback(RXingResultPointCallback),
|
||||
NeedResultPointCallback(PointCallback),
|
||||
|
||||
/**
|
||||
* Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this.
|
||||
|
||||
@@ -36,7 +36,10 @@ pub use encode_hints::*;
|
||||
|
||||
/// Callback which is invoked when a possible result point (significant
|
||||
/// point in the barcode image such as a corner) is found.
|
||||
pub type RXingResultPointCallback = Rc<dyn Fn(&dyn ResultPoint)>;
|
||||
pub type PointCallback = Rc<dyn Fn(Point)>;
|
||||
|
||||
/** Temporary type to ease refactoring and keep backwards-compatibility */
|
||||
pub type RXingResultPointCallback = PointCallback;
|
||||
|
||||
mod decode_hints;
|
||||
pub use decode_hints::*;
|
||||
|
||||
@@ -2,11 +2,8 @@
|
||||
use num::integer::Roots;
|
||||
|
||||
use crate::{
|
||||
common::{
|
||||
detector::MathUtils, BitMatrix, DefaultGridSampler, DetectorRXingResult, GridSampler,
|
||||
Result,
|
||||
},
|
||||
Exceptions, RXingResultPoint,
|
||||
common::{BitMatrix, DefaultGridSampler, DetectorRXingResult, GridSampler, Result},
|
||||
point, Exceptions, Point,
|
||||
};
|
||||
|
||||
use super::MaxiCodeReader;
|
||||
@@ -16,7 +13,7 @@ const ROW_SCAN_SKIP: u32 = 2;
|
||||
#[derive(Debug)]
|
||||
pub struct MaxicodeDetectionResult {
|
||||
bits: BitMatrix,
|
||||
points: Vec<RXingResultPoint>,
|
||||
points: Vec<Point>,
|
||||
rotation: f32,
|
||||
}
|
||||
|
||||
@@ -31,7 +28,7 @@ impl DetectorRXingResult for MaxicodeDetectionResult {
|
||||
&self.bits
|
||||
}
|
||||
|
||||
fn getPoints(&self) -> &[RXingResultPoint] {
|
||||
fn getPoints(&self) -> &[Point] {
|
||||
&self.points
|
||||
}
|
||||
}
|
||||
@@ -349,8 +346,8 @@ pub fn detect(image: &BitMatrix, try_harder: bool) -> Result<MaxicodeDetectionRe
|
||||
|
||||
let [tl, bl, tr, br] = &symbol_box.0;
|
||||
|
||||
let target_width = MathUtils::distance(tl.0, tl.1, tr.0, tr.1);
|
||||
let target_height = MathUtils::distance(br.0, br.1, tr.0, tr.1);
|
||||
let target_width = Point::distance(tl.into(), tr.into());
|
||||
let target_height = Point::distance(br.into(), tr.into());
|
||||
|
||||
// let target_width = (tr.0 - tl.0).round().abs() as u32;
|
||||
// let target_height = (br.1 - tr.1).round().abs() as u32;
|
||||
@@ -387,7 +384,7 @@ pub fn detect(image: &BitMatrix, try_harder: bool) -> Result<MaxicodeDetectionRe
|
||||
points: symbol_box
|
||||
.0
|
||||
.iter()
|
||||
.map(|p| RXingResultPoint { x: p.0, y: p.1 })
|
||||
.map(|p| Point { x: p.0, y: p.1 })
|
||||
.collect(),
|
||||
rotation: symbol_box.1,
|
||||
});
|
||||
@@ -717,10 +714,10 @@ fn box_symbol(image: &BitMatrix, circle: &mut Circle) -> Result<([(f32, f32); 4]
|
||||
calculate_simple_boundary(circle, Some(image), None, false);
|
||||
|
||||
let naive_box = [
|
||||
RXingResultPoint::new(left_boundary as f32, bottom_boundary as f32),
|
||||
RXingResultPoint::new(left_boundary as f32, top_boundary as f32),
|
||||
RXingResultPoint::new(right_boundary as f32, bottom_boundary as f32),
|
||||
RXingResultPoint::new(right_boundary as f32, top_boundary as f32),
|
||||
point(left_boundary as f32, bottom_boundary as f32),
|
||||
point(left_boundary as f32, top_boundary as f32),
|
||||
point(right_boundary as f32, bottom_boundary as f32),
|
||||
point(right_boundary as f32, top_boundary as f32),
|
||||
];
|
||||
|
||||
#[allow(unused_mut)]
|
||||
@@ -807,9 +804,9 @@ const BOTTOM_RIGHT_ORIENTATION_POS: ((u32, u32), (u32, u32), (u32, u32)) =
|
||||
fn attempt_rotation_box(
|
||||
image: &BitMatrix,
|
||||
circle: &mut Circle,
|
||||
naive_box: &[RXingResultPoint; 4],
|
||||
naive_box: &[Point; 4],
|
||||
center_scale: f64,
|
||||
) -> Option<([RXingResultPoint; 4], f32)> {
|
||||
) -> Option<([Point; 4], f32)> {
|
||||
// update our circle with a more accurate center point
|
||||
circle.calculate_high_accuracy_center();
|
||||
|
||||
@@ -955,10 +952,10 @@ fn attempt_rotation_box(
|
||||
|
||||
Some((
|
||||
[
|
||||
RXingResultPoint::new(new_1.0, new_1.1),
|
||||
RXingResultPoint::new(new_2.0, new_2.1),
|
||||
RXingResultPoint::new(new_3.0, new_3.1),
|
||||
RXingResultPoint::new(new_4.0, new_4.1),
|
||||
point(new_1.0, new_1.1),
|
||||
point(new_2.0, new_2.1),
|
||||
point(new_3.0, new_3.1),
|
||||
point(new_4.0, new_4.1),
|
||||
],
|
||||
final_rotation,
|
||||
))
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::common::Result;
|
||||
use crate::{Exceptions, RXingResult, RXingResultPoint, Reader, ResultPoint};
|
||||
use crate::{point, Exceptions, Point, RXingResult, Reader};
|
||||
|
||||
/**
|
||||
* This class attempts to decode a barcode from an image, not by scanning the whole image,
|
||||
@@ -61,7 +61,7 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
||||
// This is a match because only NotFoundExceptions should be ignored
|
||||
match result {
|
||||
Ok(res) => {
|
||||
let points = Self::makeAbsolute(res.getRXingResultPoints(), halfWidth as f32, 0.0);
|
||||
let points = Self::makeAbsolute(res.getPoints(), halfWidth as f32, 0.0);
|
||||
return Ok(RXingResult::new_from_existing_result(res, points));
|
||||
}
|
||||
Err(Exceptions::NotFoundException(_)) => {}
|
||||
@@ -74,7 +74,7 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
||||
// This is a match because only NotFoundExceptions should be ignored
|
||||
match result {
|
||||
Ok(res) => {
|
||||
let points = Self::makeAbsolute(res.getRXingResultPoints(), 0.0, halfHeight as f32);
|
||||
let points = Self::makeAbsolute(res.getPoints(), 0.0, halfHeight as f32);
|
||||
return Ok(RXingResult::new_from_existing_result(res, points));
|
||||
}
|
||||
Err(Exceptions::NotFoundException(_)) => {}
|
||||
@@ -88,11 +88,8 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
||||
// This is a match because only NotFoundExceptions should be ignored
|
||||
match result {
|
||||
Ok(res) => {
|
||||
let points = Self::makeAbsolute(
|
||||
res.getRXingResultPoints(),
|
||||
halfWidth as f32,
|
||||
halfHeight as f32,
|
||||
);
|
||||
let points =
|
||||
Self::makeAbsolute(res.getPoints(), halfWidth as f32, halfHeight as f32);
|
||||
return Ok(RXingResult::new_from_existing_result(res, points));
|
||||
}
|
||||
Err(Exceptions::NotFoundException(_)) => {}
|
||||
@@ -105,7 +102,7 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
||||
let result = self.0.decode_with_hints(&mut center, hints)?;
|
||||
|
||||
let points = Self::makeAbsolute(
|
||||
result.getRXingResultPoints(),
|
||||
result.getPoints(),
|
||||
quarterWidth as f32,
|
||||
quarterHeight as f32,
|
||||
);
|
||||
@@ -122,16 +119,12 @@ impl<T: Reader> ByQuadrantReader<T> {
|
||||
Self(delegate)
|
||||
}
|
||||
|
||||
fn makeAbsolute(
|
||||
points: &[RXingResultPoint],
|
||||
leftOffset: f32,
|
||||
topOffset: f32,
|
||||
) -> Vec<RXingResultPoint> {
|
||||
fn makeAbsolute(points: &[Point], leftOffset: f32, topOffset: f32) -> Vec<Point> {
|
||||
// let mut result = Vec::new();
|
||||
// if !points.is_empty() {
|
||||
|
||||
// // for relative in points {
|
||||
// // result.push(RXingResultPoint::new(
|
||||
// // result.push(point(
|
||||
// // relative.getX() + leftOffset,
|
||||
// // relative.getY() + topOffset,
|
||||
// // ));
|
||||
@@ -140,9 +133,7 @@ impl<T: Reader> ByQuadrantReader<T> {
|
||||
// result
|
||||
points
|
||||
.iter()
|
||||
.map(|relative| {
|
||||
RXingResultPoint::new(relative.getX() + leftOffset, relative.getY() + topOffset)
|
||||
})
|
||||
.map(|relative| point(relative.x + leftOffset, relative.y + topOffset))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
common::Result, BinaryBitmap, DecodingHintDictionary, Exceptions, RXingResult,
|
||||
RXingResultPoint, Reader, ResultPoint,
|
||||
common::Result, point, BinaryBitmap, DecodingHintDictionary, Exceptions, Point, RXingResult,
|
||||
Reader,
|
||||
};
|
||||
|
||||
use super::MultipleBarcodeReader;
|
||||
@@ -26,7 +26,7 @@ use super::MultipleBarcodeReader;
|
||||
/**
|
||||
* <p>Attempts to locate multiple barcodes in an image by repeatedly decoding portion of the image.
|
||||
* After one barcode is found, the areas left, above, right and below the barcode's
|
||||
* {@link RXingResultPoint}s are scanned, recursively.</p>
|
||||
* {@link Point}s are scanned, recursively.</p>
|
||||
*
|
||||
* <p>A caller may want to also employ {@link ByQuadrantReader} when attempting to find multiple
|
||||
* 2D barcodes, like QR Codes, in an image, where the presence of multiple barcodes might prevent
|
||||
@@ -95,10 +95,10 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
|
||||
}
|
||||
}
|
||||
|
||||
let resultPoints = result.getRXingResultPoints().clone();
|
||||
let resultPoints = result.getPoints().clone();
|
||||
|
||||
if !alreadyFound {
|
||||
results.push(Self::translateRXingResultPoints(result, xOffset, yOffset));
|
||||
results.push(Self::translatePoints(result, xOffset, yOffset));
|
||||
}
|
||||
|
||||
if resultPoints.is_empty() {
|
||||
@@ -115,8 +115,8 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
|
||||
// if (point == null) {
|
||||
// continue;
|
||||
// }
|
||||
let x = point.getX();
|
||||
let y = point.getY();
|
||||
let x = point.x;
|
||||
let y = point.y;
|
||||
if x < minX {
|
||||
minX = x;
|
||||
}
|
||||
@@ -177,25 +177,20 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn translateRXingResultPoints(result: RXingResult, xOffset: u32, yOffset: u32) -> RXingResult {
|
||||
let oldRXingResultPoints = result.getRXingResultPoints();
|
||||
if oldRXingResultPoints.is_empty() {
|
||||
fn translatePoints(result: RXingResult, xOffset: u32, yOffset: u32) -> RXingResult {
|
||||
let oldPoints = result.getPoints();
|
||||
if oldPoints.is_empty() {
|
||||
return result;
|
||||
}
|
||||
|
||||
let newRXingResultPoints: Vec<RXingResultPoint> = oldRXingResultPoints
|
||||
let newPoints: Vec<Point> = oldPoints
|
||||
.iter()
|
||||
.map(|oldPoint| {
|
||||
RXingResultPoint::new(
|
||||
oldPoint.getX() + xOffset as f32,
|
||||
oldPoint.getY() + yOffset as f32,
|
||||
)
|
||||
})
|
||||
.map(|oldPoint| point(oldPoint.x + xOffset as f32, oldPoint.y + yOffset as f32))
|
||||
.collect();
|
||||
|
||||
// let mut newRXingResultPoints = Vec::with_capacity(oldRXingResultPoints.len());
|
||||
// for oldPoint in oldRXingResultPoints {
|
||||
// newRXingResultPoints.push(RXingResultPoint::new(
|
||||
// let mut newPoints = Vec::with_capacity(oldPoints.len());
|
||||
// for oldPoint in oldPoints {
|
||||
// newPoints.push(point(
|
||||
// oldPoint.getX() + xOffset as f32,
|
||||
// oldPoint.getY() + yOffset as f32,
|
||||
// ));
|
||||
@@ -204,7 +199,7 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
|
||||
result.getText(),
|
||||
result.getRawBytes().clone(),
|
||||
result.getNumBits(),
|
||||
newRXingResultPoints,
|
||||
newPoints,
|
||||
*result.getBarcodeFormat(),
|
||||
result.getTimestamp(),
|
||||
);
|
||||
|
||||
@@ -19,8 +19,7 @@ use std::cmp::Ordering;
|
||||
use crate::{
|
||||
common::{BitMatrix, Result},
|
||||
qrcode::detector::{FinderPattern, FinderPatternFinder, FinderPatternInfo},
|
||||
result_point_utils, DecodeHintType, DecodingHintDictionary, Exceptions,
|
||||
RXingResultPointCallback,
|
||||
result_point_utils, DecodeHintType, DecodingHintDictionary, Exceptions, Point, PointCallback,
|
||||
};
|
||||
|
||||
// max. legal count of modules per QR code edge (177)
|
||||
@@ -68,7 +67,7 @@ impl<'a> MultiFinderPatternFinder<'_> {
|
||||
|
||||
pub fn new(
|
||||
image: &'a BitMatrix,
|
||||
resultPointCallback: Option<RXingResultPointCallback>,
|
||||
resultPointCallback: Option<PointCallback>,
|
||||
) -> MultiFinderPatternFinder<'a> {
|
||||
MultiFinderPatternFinder(FinderPatternFinder::with_callback(
|
||||
image,
|
||||
@@ -175,9 +174,10 @@ impl<'a> MultiFinderPatternFinder<'_> {
|
||||
|
||||
// Calculate the distances: a = topleft-bottomleft, b=topleft-topright, c = diagonal
|
||||
let info = FinderPatternInfo::new(test);
|
||||
let dA = result_point_utils::distance(info.getTopLeft(), info.getBottomLeft());
|
||||
let dC = result_point_utils::distance(info.getTopRight(), info.getBottomLeft());
|
||||
let dB = result_point_utils::distance(info.getTopLeft(), info.getTopRight());
|
||||
let dA = Point::distance(info.getTopLeft().into(), info.getBottomLeft().into());
|
||||
let dC =
|
||||
Point::distance(info.getTopRight().into(), info.getBottomLeft().into());
|
||||
let dB = Point::distance(info.getTopLeft().into(), info.getTopRight().into());
|
||||
|
||||
// Check the sizes
|
||||
let estimatedModuleCount = (dA + dB) / (p1.getEstimatedModuleSize() * 2.0);
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
use rxing_one_d_proc_derive::OneDReader;
|
||||
|
||||
use crate::common::{BitArray, Result};
|
||||
use crate::BarcodeFormat;
|
||||
use crate::DecodeHintValue;
|
||||
use crate::Exceptions;
|
||||
use crate::RXingResult;
|
||||
use crate::{point, BarcodeFormat};
|
||||
|
||||
use super::OneDReader;
|
||||
|
||||
@@ -170,8 +170,8 @@ impl OneDReader for CodaBarReader {
|
||||
&self.decodeRowRXingResult,
|
||||
Vec::new(),
|
||||
vec![
|
||||
RXingResultPoint::new(left, rowNumber as f32),
|
||||
RXingResultPoint::new(right, rowNumber as f32),
|
||||
point(left, rowNumber as f32),
|
||||
point(right, rowNumber as f32),
|
||||
],
|
||||
BarcodeFormat::CODABAR,
|
||||
);
|
||||
|
||||
@@ -18,7 +18,7 @@ use rxing_one_d_proc_derive::OneDReader;
|
||||
|
||||
use crate::{
|
||||
common::{BitArray, Result},
|
||||
BarcodeFormat, Exceptions, RXingResult,
|
||||
point, BarcodeFormat, Exceptions, RXingResult,
|
||||
};
|
||||
|
||||
use super::{one_d_reader, OneDReader};
|
||||
@@ -338,8 +338,8 @@ impl OneDReader for Code128Reader {
|
||||
&result,
|
||||
rawBytes,
|
||||
vec![
|
||||
RXingResultPoint::new(left, rowNumber as f32),
|
||||
RXingResultPoint::new(right, rowNumber as f32),
|
||||
point(left, rowNumber as f32),
|
||||
point(right, rowNumber as f32),
|
||||
],
|
||||
BarcodeFormat::CODE_128,
|
||||
);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
use rxing_one_d_proc_derive::OneDReader;
|
||||
|
||||
use crate::common::{BitArray, Result};
|
||||
use crate::{BarcodeFormat, Exceptions, RXingResult};
|
||||
use crate::{point, BarcodeFormat, Exceptions, RXingResult};
|
||||
|
||||
use super::{one_d_reader, OneDReader};
|
||||
|
||||
@@ -134,8 +134,8 @@ impl OneDReader for Code39Reader {
|
||||
&resultString,
|
||||
Vec::new(),
|
||||
vec![
|
||||
RXingResultPoint::new(left, rowNumber as f32),
|
||||
RXingResultPoint::new(right, rowNumber as f32),
|
||||
point(left, rowNumber as f32),
|
||||
point(right, rowNumber as f32),
|
||||
],
|
||||
BarcodeFormat::CODE_39,
|
||||
);
|
||||
|
||||
@@ -18,7 +18,7 @@ use rxing_one_d_proc_derive::OneDReader;
|
||||
|
||||
use crate::{
|
||||
common::{BitArray, Result},
|
||||
BarcodeFormat, Exceptions, RXingResult,
|
||||
point, BarcodeFormat, Exceptions, RXingResult,
|
||||
};
|
||||
|
||||
use super::{one_d_reader, OneDReader};
|
||||
@@ -117,8 +117,8 @@ impl OneDReader for Code93Reader {
|
||||
&resultString,
|
||||
Vec::new(),
|
||||
vec![
|
||||
RXingResultPoint::new(left, rowNumber as f32),
|
||||
RXingResultPoint::new(right, rowNumber as f32),
|
||||
point(left, rowNumber as f32),
|
||||
point(right, rowNumber as f32),
|
||||
],
|
||||
BarcodeFormat::CODE_93,
|
||||
);
|
||||
|
||||
@@ -18,7 +18,7 @@ use rxing_one_d_proc_derive::OneDReader;
|
||||
|
||||
use crate::{
|
||||
common::{BitArray, Result},
|
||||
BarcodeFormat, DecodeHintValue, Exceptions, RXingResult,
|
||||
point, BarcodeFormat, DecodeHintValue, Exceptions, RXingResult,
|
||||
};
|
||||
|
||||
use super::{one_d_reader, OneDReader};
|
||||
@@ -150,8 +150,8 @@ impl OneDReader for ITFReader {
|
||||
&resultString,
|
||||
Vec::new(), // no natural byte representation for these barcodes
|
||||
vec![
|
||||
RXingResultPoint::new(startRange[1] as f32, rowNumber as f32),
|
||||
RXingResultPoint::new(endRange[0] as f32, rowNumber as f32),
|
||||
point(startRange[1] as f32, rowNumber as f32),
|
||||
point(endRange[0] as f32, rowNumber as f32),
|
||||
],
|
||||
BarcodeFormat::ITF,
|
||||
);
|
||||
|
||||
@@ -157,8 +157,8 @@ impl Reader for MultiFormatOneDReader {
|
||||
);
|
||||
// Update result points
|
||||
let height = rotatedImage.getHeight();
|
||||
let total_points = result.getRXingResultPoints().len();
|
||||
let points = result.getRXingResultPointsMut();
|
||||
let total_points = result.getPoints().len();
|
||||
let points = result.getPointsMut();
|
||||
for point in points.iter_mut().take(total_points) {
|
||||
std::mem::swap(&mut point.x, &mut point.y);
|
||||
point.x = height as f32 - point.x - 1.0;
|
||||
|
||||
@@ -105,7 +105,7 @@ impl MultiFormatUPCEANReader {
|
||||
let mut resultUPCA = RXingResult::new(
|
||||
&result.getText()[1..],
|
||||
result.getRawBytes().clone(),
|
||||
result.getRXingResultPoints().clone(),
|
||||
result.getPoints().clone(),
|
||||
BarcodeFormat::UPC_A,
|
||||
);
|
||||
resultUPCA.putAllMetadata(result.getRXingResultMetadata().clone());
|
||||
@@ -189,8 +189,8 @@ impl Reader for MultiFormatUPCEANReader {
|
||||
);
|
||||
// Update result points
|
||||
let height = rotatedImage.getHeight();
|
||||
let total_points = result.getRXingResultPoints().len();
|
||||
let points = result.getRXingResultPointsMut();
|
||||
let total_points = result.getPoints().len();
|
||||
let points = result.getPointsMut();
|
||||
for point in points.iter_mut().take(total_points) {
|
||||
std::mem::swap(&mut point.x, &mut point.y);
|
||||
point.x = height as f32 - point.x - 1.0;
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
use crate::{
|
||||
common::{BitArray, Result},
|
||||
BinaryBitmap, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions, RXingResult,
|
||||
RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader, ResultPoint,
|
||||
point, BinaryBitmap, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions,
|
||||
RXingResult, RXingResultMetadataType, RXingResultMetadataValue, Reader,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -115,16 +115,10 @@ pub trait OneDReader: Reader {
|
||||
RXingResultMetadataValue::Orientation(180),
|
||||
);
|
||||
// And remember to flip the result points horizontally.
|
||||
let points = result.getRXingResultPointsMut();
|
||||
let points = result.getPointsMut();
|
||||
if !points.is_empty() && points.len() >= 2 {
|
||||
points[0] = RXingResultPoint::new(
|
||||
width as f32 - points[0].getX() - 1.0,
|
||||
points[0].getY(),
|
||||
);
|
||||
points[1] = RXingResultPoint::new(
|
||||
width as f32 - points[1].getX() - 1.0,
|
||||
points[1].getY(),
|
||||
);
|
||||
points[0] = point(width as f32 - points[0].x - 1.0, points[0].y);
|
||||
points[1] = point(width as f32 - points[1].x - 1.0, points[1].y);
|
||||
}
|
||||
}
|
||||
return Ok(result);
|
||||
|
||||
@@ -215,8 +215,8 @@ impl Reader for RSSExpandedReader {
|
||||
// Update result points
|
||||
let height = rotatedImage.getHeight();
|
||||
|
||||
let total_points = result.getRXingResultPoints().len();
|
||||
let points = result.getRXingResultPointsMut();
|
||||
let total_points = result.getPoints().len();
|
||||
let points = result.getPointsMut();
|
||||
for point in points.iter_mut().take(total_points) {
|
||||
std::mem::swap(&mut point.x, &mut point.y);
|
||||
point.x = height as f32 - point.x - 1.0;
|
||||
@@ -540,14 +540,14 @@ impl RSSExpandedReader {
|
||||
.getFinderPattern()
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::illegalState)?
|
||||
.getRXingResultPoints();
|
||||
.getPoints();
|
||||
let lastPoints = pairs
|
||||
.last()
|
||||
.ok_or(Exceptions::indexOutOfBounds)?
|
||||
.getFinderPattern()
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::illegalState)?
|
||||
.getRXingResultPoints();
|
||||
.getPoints();
|
||||
|
||||
let mut result = RXingResult::new(
|
||||
&resultingString,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
use crate::RXingResultPoint;
|
||||
use crate::{point, Point};
|
||||
|
||||
/**
|
||||
* Encapsulates an RSS barcode finder pattern, including its start/end position and row.
|
||||
@@ -25,7 +25,7 @@ use crate::RXingResultPoint;
|
||||
pub struct FinderPattern {
|
||||
value: u32,
|
||||
startEnd: [usize; 2],
|
||||
resultPoints: Vec<RXingResultPoint>,
|
||||
resultPoints: Vec<Point>,
|
||||
}
|
||||
|
||||
impl FinderPattern {
|
||||
@@ -34,8 +34,8 @@ impl FinderPattern {
|
||||
value,
|
||||
startEnd,
|
||||
resultPoints: vec![
|
||||
RXingResultPoint::new(start as f32, rowNumber as f32),
|
||||
RXingResultPoint::new(end as f32, rowNumber as f32),
|
||||
point(start as f32, rowNumber as f32),
|
||||
point(end as f32, rowNumber as f32),
|
||||
],
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ impl FinderPattern {
|
||||
&mut self.startEnd
|
||||
}
|
||||
|
||||
pub fn getRXingResultPoints(&self) -> &[RXingResultPoint] {
|
||||
pub fn getPoints(&self) -> &[Point] {
|
||||
&self.resultPoints
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ use std::collections::HashMap;
|
||||
use crate::{
|
||||
common::{BitArray, Result},
|
||||
oned::{one_d_reader, OneDReader},
|
||||
BarcodeFormat, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions,
|
||||
RXingResult, RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader,
|
||||
point, BarcodeFormat, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions,
|
||||
RXingResult, RXingResultMetadataType, RXingResultMetadataValue, Reader,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -114,8 +114,8 @@ impl Reader for RSS14Reader {
|
||||
);
|
||||
// Update result points
|
||||
let height = rotatedImage.getHeight();
|
||||
let total_points = result.getRXingResultPoints().len();
|
||||
let points = result.getRXingResultPointsMut();
|
||||
let total_points = result.getPoints().len();
|
||||
let points = result.getPointsMut();
|
||||
for point in points.iter_mut().take(total_points) {
|
||||
std::mem::swap(&mut point.x, &mut point.y);
|
||||
point.x = height as f32 - point.x - 1.0
|
||||
@@ -209,8 +209,8 @@ impl RSS14Reader {
|
||||
}
|
||||
buffer.push_str(&checkDigit.to_string());
|
||||
|
||||
let leftPoints = leftPair.getFinderPattern().getRXingResultPoints();
|
||||
let rightPoints = rightPair.getFinderPattern().getRXingResultPoints();
|
||||
let leftPoints = leftPair.getFinderPattern().getPoints();
|
||||
let rightPoints = rightPair.getFinderPattern().getPoints();
|
||||
let mut result = RXingResult::new(
|
||||
&buffer,
|
||||
Vec::new(),
|
||||
@@ -259,7 +259,7 @@ impl RSS14Reader {
|
||||
// row is actually reversed
|
||||
center = row.getSize() as f32 - 1.0 - center;
|
||||
}
|
||||
cb(&RXingResultPoint::new(center, rowNumber as f32));
|
||||
cb(point(center, rowNumber as f32));
|
||||
}
|
||||
|
||||
let outside = self.decodeDataCharacter(row, &pattern, true)?;
|
||||
|
||||
@@ -94,7 +94,7 @@ impl UPCAReader {
|
||||
let mut upcaRXingResult = RXingResult::new(
|
||||
stripped_text,
|
||||
Vec::new(),
|
||||
result.getRXingResultPoints().to_vec(),
|
||||
result.getPoints().to_vec(),
|
||||
BarcodeFormat::UPC_A,
|
||||
);
|
||||
upcaRXingResult.putAllMetadata(result.getRXingResultMetadata().clone());
|
||||
|
||||
@@ -18,8 +18,8 @@ use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
common::{BitArray, Result},
|
||||
BarcodeFormat, Exceptions, RXingResult, RXingResultMetadataType, RXingResultMetadataValue,
|
||||
RXingResultPoint,
|
||||
point, BarcodeFormat, Exceptions, RXingResult, RXingResultMetadataType,
|
||||
RXingResultMetadataValue,
|
||||
};
|
||||
|
||||
use super::{upc_ean_reader, UPCEANReader, STAND_IN};
|
||||
@@ -49,11 +49,11 @@ impl UPCEANExtension2Support {
|
||||
&resultString,
|
||||
Vec::new(),
|
||||
vec![
|
||||
RXingResultPoint::new(
|
||||
point(
|
||||
(extensionStartRange[0] + extensionStartRange[1]) as f32 / 2.0,
|
||||
rowNumber as f32,
|
||||
),
|
||||
RXingResultPoint::new(end as f32, rowNumber as f32),
|
||||
point(end as f32, rowNumber as f32),
|
||||
],
|
||||
BarcodeFormat::UPC_EAN_EXTENSION,
|
||||
);
|
||||
|
||||
@@ -18,8 +18,8 @@ use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
common::{BitArray, Result},
|
||||
BarcodeFormat, Exceptions, RXingResult, RXingResultMetadataType, RXingResultMetadataValue,
|
||||
RXingResultPoint,
|
||||
point, BarcodeFormat, Exceptions, RXingResult, RXingResultMetadataType,
|
||||
RXingResultMetadataValue,
|
||||
};
|
||||
|
||||
use super::{upc_ean_reader, UPCEANReader, STAND_IN};
|
||||
@@ -51,11 +51,11 @@ impl UPCEANExtension5Support {
|
||||
&resultString,
|
||||
Vec::new(),
|
||||
vec![
|
||||
RXingResultPoint::new(
|
||||
point(
|
||||
(extensionStartRange[0] + extensionStartRange[1]) as f32 / 2.0,
|
||||
rowNumber as f32,
|
||||
),
|
||||
RXingResultPoint::new(end as f32, rowNumber as f32),
|
||||
point(end as f32, rowNumber as f32),
|
||||
],
|
||||
BarcodeFormat::UPC_EAN_EXTENSION,
|
||||
);
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
use crate::{
|
||||
common::{BitArray, Result},
|
||||
BarcodeFormat, DecodeHintType, DecodeHintValue, Exceptions, RXingResult,
|
||||
RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader,
|
||||
point, BarcodeFormat, DecodeHintType, DecodeHintValue, Exceptions, RXingResult,
|
||||
RXingResultMetadataType, RXingResultMetadataValue, Reader,
|
||||
};
|
||||
|
||||
use super::{one_d_reader, EANManufacturerOrgSupport, OneDReader, UPCEANExtensionSupport};
|
||||
@@ -156,7 +156,7 @@ pub trait UPCEANReader: OneDReader {
|
||||
let mut symbologyIdentifier = 0;
|
||||
|
||||
if let Some(DecodeHintValue::NeedResultPointCallback(cb)) = resultPointCallback {
|
||||
cb(&RXingResultPoint::new(
|
||||
cb(point(
|
||||
(startGuardRange[0] + startGuardRange[1]) as f32 / 2.0,
|
||||
rowNumber as f32,
|
||||
));
|
||||
@@ -166,13 +166,13 @@ pub trait UPCEANReader: OneDReader {
|
||||
let endStart = self.decodeMiddle(row, startGuardRange, &mut result)?;
|
||||
|
||||
if let Some(DecodeHintValue::NeedResultPointCallback(cb)) = resultPointCallback {
|
||||
cb(&RXingResultPoint::new(endStart as f32, rowNumber as f32));
|
||||
cb(point(endStart as f32, rowNumber as f32));
|
||||
}
|
||||
|
||||
let endRange = self.decodeEnd(row, endStart)?;
|
||||
|
||||
if let Some(DecodeHintValue::NeedResultPointCallback(cb)) = resultPointCallback {
|
||||
cb(&RXingResultPoint::new(
|
||||
cb(point(
|
||||
(endRange[0] + endRange[1]) as f32 / 2.0,
|
||||
rowNumber as f32,
|
||||
));
|
||||
@@ -204,8 +204,8 @@ pub trait UPCEANReader: OneDReader {
|
||||
&resultString,
|
||||
Vec::new(), // no natural byte representation for these barcodes
|
||||
vec![
|
||||
RXingResultPoint::new(left, rowNumber as f32),
|
||||
RXingResultPoint::new(right, rowNumber as f32),
|
||||
point(left, rowNumber as f32),
|
||||
point(right, rowNumber as f32),
|
||||
],
|
||||
format,
|
||||
);
|
||||
@@ -223,8 +223,7 @@ pub trait UPCEANReader: OneDReader {
|
||||
),
|
||||
);
|
||||
decodeRXingResult.putAllMetadata(extensionRXingResult.getRXingResultMetadata().clone());
|
||||
decodeRXingResult
|
||||
.addRXingResultPoints(&mut extensionRXingResult.getRXingResultPoints().clone());
|
||||
decodeRXingResult.addPoints(&mut extensionRXingResult.getPoints().clone());
|
||||
extensionLength = extensionRXingResult.getText().chars().count();
|
||||
Ok(())
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@ use std::rc::Rc;
|
||||
|
||||
use crate::{
|
||||
common::{BitMatrix, Result},
|
||||
Exceptions, RXingResultPoint, ResultPoint,
|
||||
point, Exceptions, Point,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -27,10 +27,10 @@ use crate::{
|
||||
#[derive(Clone)]
|
||||
pub struct BoundingBox {
|
||||
image: Rc<BitMatrix>,
|
||||
topLeft: RXingResultPoint,
|
||||
bottomLeft: RXingResultPoint,
|
||||
topRight: RXingResultPoint,
|
||||
bottomRight: RXingResultPoint,
|
||||
topLeft: Point,
|
||||
bottomLeft: Point,
|
||||
topRight: Point,
|
||||
bottomRight: Point,
|
||||
minX: u32,
|
||||
maxX: u32,
|
||||
minY: u32,
|
||||
@@ -39,10 +39,10 @@ pub struct BoundingBox {
|
||||
impl BoundingBox {
|
||||
pub fn new(
|
||||
image: Rc<BitMatrix>,
|
||||
topLeft: Option<RXingResultPoint>,
|
||||
bottomLeft: Option<RXingResultPoint>,
|
||||
topRight: Option<RXingResultPoint>,
|
||||
bottomRight: Option<RXingResultPoint>,
|
||||
topLeft: Option<Point>,
|
||||
bottomLeft: Option<Point>,
|
||||
topRight: Option<Point>,
|
||||
bottomRight: Option<Point>,
|
||||
) -> Result<BoundingBox> {
|
||||
let leftUnspecified = topLeft.is_none() || bottomLeft.is_none();
|
||||
let rightUnspecified = topRight.is_none() || bottomRight.is_none();
|
||||
@@ -58,14 +58,13 @@ impl BoundingBox {
|
||||
if leftUnspecified {
|
||||
newTopRight = topRight.ok_or(Exceptions::illegalState)?;
|
||||
newBottomRight = bottomRight.ok_or(Exceptions::illegalState)?;
|
||||
newTopLeft = RXingResultPoint::new(0.0, newTopRight.getY());
|
||||
newBottomLeft = RXingResultPoint::new(0.0, newBottomRight.getY());
|
||||
newTopLeft = point(0.0, newTopRight.y);
|
||||
newBottomLeft = point(0.0, newBottomRight.y);
|
||||
} else if rightUnspecified {
|
||||
newTopLeft = topLeft.ok_or(Exceptions::illegalState)?;
|
||||
newBottomLeft = bottomLeft.ok_or(Exceptions::illegalState)?;
|
||||
newTopRight = RXingResultPoint::new(image.getWidth() as f32 - 1.0, newTopLeft.getY());
|
||||
newBottomRight =
|
||||
RXingResultPoint::new(image.getWidth() as f32 - 1.0, newBottomLeft.getY());
|
||||
newTopRight = point(image.getWidth() as f32 - 1.0, newTopLeft.y);
|
||||
newBottomRight = point(image.getWidth() as f32 - 1.0, newBottomLeft.y);
|
||||
} else {
|
||||
newTopLeft = topLeft.ok_or(Exceptions::illegalState)?;
|
||||
newTopRight = topRight.ok_or(Exceptions::illegalState)?;
|
||||
@@ -75,10 +74,10 @@ impl BoundingBox {
|
||||
|
||||
Ok(BoundingBox {
|
||||
image,
|
||||
minX: newTopLeft.getX().min(newBottomLeft.getX()) as u32,
|
||||
maxX: newTopRight.getX().max(newBottomRight.getX()) as u32,
|
||||
minY: newTopLeft.getY().min(newTopRight.getY()) as u32,
|
||||
maxY: newBottomLeft.getY().max(newBottomRight.getY()) as u32,
|
||||
minX: newTopLeft.x.min(newBottomLeft.x) as u32,
|
||||
maxX: newTopRight.x.max(newBottomRight.x) as u32,
|
||||
minY: newTopLeft.y.min(newTopRight.y) as u32,
|
||||
maxY: newBottomLeft.y.max(newBottomRight.y) as u32,
|
||||
topLeft: newTopLeft,
|
||||
bottomLeft: newBottomLeft,
|
||||
topRight: newTopRight,
|
||||
@@ -135,11 +134,11 @@ impl BoundingBox {
|
||||
|
||||
if missingStartRows > 0 {
|
||||
let top = if isLeft { self.topLeft } else { self.topRight };
|
||||
let mut newMinY = top.getY() - missingStartRows as f32;
|
||||
let mut newMinY = top.y - missingStartRows as f32;
|
||||
if newMinY < 0.0 {
|
||||
newMinY = 0.0;
|
||||
}
|
||||
let newTop = RXingResultPoint::new(top.getX(), newMinY);
|
||||
let newTop = point(top.x, newMinY);
|
||||
if isLeft {
|
||||
newTopLeft = newTop;
|
||||
} else {
|
||||
@@ -153,11 +152,11 @@ impl BoundingBox {
|
||||
} else {
|
||||
self.bottomRight
|
||||
};
|
||||
let mut newMaxY = bottom.getY() as u32 + missingEndRows;
|
||||
let mut newMaxY = bottom.y as u32 + missingEndRows;
|
||||
if newMaxY >= self.image.getHeight() {
|
||||
newMaxY = self.image.getHeight() - 1;
|
||||
}
|
||||
let newBottom = RXingResultPoint::new(bottom.getX(), newMaxY as f32);
|
||||
let newBottom = point(bottom.x, newMaxY as f32);
|
||||
if isLeft {
|
||||
newBottomLeft = newBottom;
|
||||
} else {
|
||||
@@ -190,19 +189,19 @@ impl BoundingBox {
|
||||
self.maxY
|
||||
}
|
||||
|
||||
pub fn getTopLeft(&self) -> &RXingResultPoint {
|
||||
pub fn getTopLeft(&self) -> &Point {
|
||||
&self.topLeft
|
||||
}
|
||||
|
||||
pub fn getTopRight(&self) -> &RXingResultPoint {
|
||||
pub fn getTopRight(&self) -> &Point {
|
||||
&self.topRight
|
||||
}
|
||||
|
||||
pub fn getBottomLeft(&self) -> &RXingResultPoint {
|
||||
pub fn getBottomLeft(&self) -> &Point {
|
||||
&self.bottomLeft
|
||||
}
|
||||
|
||||
pub fn getBottomRight(&self) -> &RXingResultPoint {
|
||||
pub fn getBottomRight(&self) -> &Point {
|
||||
&self.bottomRight
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::{pdf417::pdf_417_common, ResultPoint};
|
||||
use crate::pdf417::pdf_417_common;
|
||||
|
||||
use super::{
|
||||
BarcodeMetadata, BarcodeValue, Codeword, DetectionRXingResultColumn,
|
||||
@@ -63,8 +63,8 @@ impl DetectionRXingResultRowIndicatorColumn for DetectionRXingResultColumn {
|
||||
boundingBox.getBottomRight()
|
||||
};
|
||||
|
||||
let firstRow = self.imageRowToCodewordIndex(top.getY() as u32);
|
||||
let lastRow = self.imageRowToCodewordIndex(bottom.getY() as u32);
|
||||
let firstRow = self.imageRowToCodewordIndex(top.y as u32);
|
||||
let lastRow = self.imageRowToCodewordIndex(bottom.y as u32);
|
||||
// We need to be careful using the average row height. Barcode could be skewed so that we have smaller and
|
||||
// taller rows
|
||||
let averageRowHeight: f64 =
|
||||
@@ -263,8 +263,8 @@ fn adjustIncompleteIndicatorColumnRowNumbers(
|
||||
} else {
|
||||
boundingBox.getBottomRight()
|
||||
};
|
||||
let firstRow = col.imageRowToCodewordIndex(top.getY() as u32);
|
||||
let lastRow = col.imageRowToCodewordIndex(bottom.getY() as u32);
|
||||
let firstRow = col.imageRowToCodewordIndex(top.y as u32);
|
||||
let lastRow = col.imageRowToCodewordIndex(bottom.y as u32);
|
||||
let averageRowHeight: f64 =
|
||||
(lastRow as f64 - firstRow as f64) / barcodeMetadata.getRowCount() as f64;
|
||||
let codewords = col.getCodewordsMut();
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::rc::Rc;
|
||||
use crate::{
|
||||
common::{BitMatrix, DecoderRXingResult, Result},
|
||||
pdf417::pdf_417_common,
|
||||
Exceptions, RXingResultPoint, ResultPoint,
|
||||
Exceptions, Point,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -44,10 +44,10 @@ const MAX_EC_CODEWORDS: u32 = 512;
|
||||
// than it should be. This can happen if the scanner used a bad blackpoint.
|
||||
pub fn decode(
|
||||
image: &BitMatrix,
|
||||
imageTopLeft: Option<RXingResultPoint>,
|
||||
imageBottomLeft: Option<RXingResultPoint>,
|
||||
imageTopRight: Option<RXingResultPoint>,
|
||||
imageBottomRight: Option<RXingResultPoint>,
|
||||
imageTopLeft: Option<Point>,
|
||||
imageBottomLeft: Option<Point>,
|
||||
imageTopRight: Option<Point>,
|
||||
imageBottomRight: Option<Point>,
|
||||
minCodewordWidth: u32,
|
||||
maxCodewordWidth: u32,
|
||||
) -> Result<DecoderRXingResult> {
|
||||
@@ -68,7 +68,7 @@ pub fn decode(
|
||||
leftRowIndicatorColumn = Some(getRowIndicatorColumn(
|
||||
image,
|
||||
boundingBox.clone(),
|
||||
imageTopLeft.as_ref().unwrap(),
|
||||
imageTopLeft.unwrap(),
|
||||
true,
|
||||
minCodewordWidth,
|
||||
maxCodewordWidth,
|
||||
@@ -78,7 +78,7 @@ pub fn decode(
|
||||
rightRowIndicatorColumn = Some(getRowIndicatorColumn(
|
||||
image,
|
||||
boundingBox.clone(),
|
||||
imageTopRight.as_ref().unwrap(),
|
||||
imageTopRight.unwrap(),
|
||||
false,
|
||||
minCodewordWidth,
|
||||
maxCodewordWidth,
|
||||
@@ -358,7 +358,7 @@ fn getBarcodeMetadata<T: DetectionRXingResultRowIndicatorColumn>(
|
||||
fn getRowIndicatorColumn<'a>(
|
||||
image: &BitMatrix,
|
||||
boundingBox: Rc<BoundingBox>,
|
||||
startPoint: &RXingResultPoint,
|
||||
startPoint: Point,
|
||||
leftToRight: bool,
|
||||
minCodewordWidth: u32,
|
||||
maxCodewordWidth: u32,
|
||||
@@ -368,8 +368,8 @@ fn getRowIndicatorColumn<'a>(
|
||||
for i in 0..2 {
|
||||
// for (int i = 0; i < 2; i++) {
|
||||
let increment: i32 = if i == 0 { 1 } else { -1 };
|
||||
let mut startColumn: u32 = startPoint.getX() as u32;
|
||||
let mut imageRow: i32 = startPoint.getY() as i32;
|
||||
let mut startColumn: u32 = startPoint.x as u32;
|
||||
let mut imageRow: i32 = startPoint.y as i32;
|
||||
while imageRow <= boundingBox.getMaxY() as i32 && imageRow >= boundingBox.getMinY() as i32 {
|
||||
// for (int imageRow = (int) startPoint.getY(); imageRow <= boundingBox.getMaxY() &&
|
||||
// imageRow >= boundingBox.getMinY(); imageRow += increment) {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use crate::{
|
||||
common::{BitMatrix, Result},
|
||||
BinaryBitmap, DecodingHintDictionary, Exceptions, RXingResultPoint, ResultPoint,
|
||||
point, BinaryBitmap, DecodingHintDictionary, Exceptions, Point,
|
||||
};
|
||||
|
||||
use std::borrow::Cow;
|
||||
@@ -115,10 +115,10 @@ fn applyRotation(matrix: &BitMatrix, rotation: u32) -> Result<Cow<BitMatrix>> {
|
||||
* @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will
|
||||
* be found and returned
|
||||
* @param bitMatrix bit matrix to detect barcodes in
|
||||
* @return List of RXingResultPoint arrays containing the coordinates of found barcodes
|
||||
* @return List of Point arrays containing the coordinates of found barcodes
|
||||
*/
|
||||
pub fn detect(multiple: bool, bitMatrix: &BitMatrix) -> Option<Vec<[Option<RXingResultPoint>; 8]>> {
|
||||
let mut barcodeCoordinates: Vec<[Option<RXingResultPoint>; 8]> = Vec::new();
|
||||
pub fn detect(multiple: bool, bitMatrix: &BitMatrix) -> Option<Vec<[Option<Point>; 8]>> {
|
||||
let mut barcodeCoordinates: Vec<[Option<Point>; 8]> = Vec::new();
|
||||
let mut row = 0;
|
||||
let mut column = 0;
|
||||
let mut foundBarcodeInRow = false;
|
||||
@@ -136,10 +136,10 @@ pub fn detect(multiple: bool, bitMatrix: &BitMatrix) -> Option<Vec<[Option<RXing
|
||||
column = 0;
|
||||
for barcodeCoordinate in &barcodeCoordinates {
|
||||
if let Some(coord_1) = barcodeCoordinate[1] {
|
||||
row = row.max(coord_1.getY() as u32);
|
||||
row = row.max(coord_1.y as u32);
|
||||
}
|
||||
if let Some(coord_3) = barcodeCoordinate[3] {
|
||||
row = row.max(coord_3.getY() as u32);
|
||||
row = row.max(coord_3.y as u32);
|
||||
}
|
||||
}
|
||||
row += ROW_STEP;
|
||||
@@ -153,11 +153,11 @@ pub fn detect(multiple: bool, bitMatrix: &BitMatrix) -> Option<Vec<[Option<RXing
|
||||
// if we didn't find a right row indicator column, then continue the search for the next barcode after the
|
||||
// start pattern of the barcode just found.
|
||||
if let Some(vert_2) = vertices[2] {
|
||||
column = vert_2.getX() as u32;
|
||||
row = vert_2.getY() as u32;
|
||||
column = vert_2.x as u32;
|
||||
row = vert_2.y as u32;
|
||||
} else {
|
||||
column = vertices[4].as_ref().unwrap().getX() as u32;
|
||||
row = vertices[4].as_ref().unwrap().getY() as u32;
|
||||
column = vertices[4].as_ref().unwrap().x as u32;
|
||||
row = vertices[4].as_ref().unwrap().y as u32;
|
||||
}
|
||||
}
|
||||
Some(barcodeCoordinates)
|
||||
@@ -178,17 +178,13 @@ pub fn detect(multiple: bool, bitMatrix: &BitMatrix) -> Option<Vec<[Option<RXing
|
||||
* vertices[6] x, y top right codeword area
|
||||
* vertices[7] x, y bottom right codeword area
|
||||
*/
|
||||
fn findVertices(
|
||||
matrix: &BitMatrix,
|
||||
startRow: u32,
|
||||
startColumn: u32,
|
||||
) -> Option<[Option<RXingResultPoint>; 8]> {
|
||||
fn findVertices(matrix: &BitMatrix, startRow: u32, startColumn: u32) -> Option<[Option<Point>; 8]> {
|
||||
let height = matrix.getHeight();
|
||||
let width = matrix.getWidth();
|
||||
let mut startRow = startRow;
|
||||
let mut startColumn = startColumn;
|
||||
|
||||
let mut result = [None::<RXingResultPoint>; 8]; //RXingResultPoint[8];
|
||||
let mut result = [None::<Point>; 8]; //Point[8];
|
||||
copyToRXingResult(
|
||||
&mut result,
|
||||
&findRowsWithPattern(matrix, height, width, startRow, startColumn, &START_PATTERN)?,
|
||||
@@ -196,8 +192,8 @@ fn findVertices(
|
||||
);
|
||||
|
||||
if let Some(result_4) = result[4] {
|
||||
startColumn = result_4.getX() as u32;
|
||||
startRow = result_4.getY() as u32;
|
||||
startColumn = result_4.x as u32;
|
||||
startRow = result_4.y as u32;
|
||||
}
|
||||
copyToRXingResult(
|
||||
&mut result,
|
||||
@@ -209,8 +205,8 @@ fn findVertices(
|
||||
}
|
||||
|
||||
fn copyToRXingResult(
|
||||
result: &mut [Option<RXingResultPoint>],
|
||||
tmpRXingResult: &[Option<RXingResultPoint>],
|
||||
result: &mut [Option<Point>],
|
||||
tmpRXingResult: &[Option<Point>],
|
||||
destinationIndexes: &[u32],
|
||||
) {
|
||||
for i in 0..destinationIndexes.len() {
|
||||
@@ -225,7 +221,7 @@ fn findRowsWithPattern(
|
||||
startRow: u32,
|
||||
startColumn: u32,
|
||||
pattern: &[u32],
|
||||
) -> Option<[Option<RXingResultPoint>; 4]> {
|
||||
) -> Option<[Option<Point>; 4]> {
|
||||
let mut startRow = startRow;
|
||||
let mut result = [None; 4];
|
||||
let mut found = false;
|
||||
@@ -248,14 +244,8 @@ fn findRowsWithPattern(
|
||||
break;
|
||||
}
|
||||
}
|
||||
result[0] = Some(RXingResultPoint::new(
|
||||
loc_store.as_ref()?[0] as f32,
|
||||
startRow as f32,
|
||||
));
|
||||
result[1] = Some(RXingResultPoint::new(
|
||||
loc_store.as_ref()?[1] as f32,
|
||||
startRow as f32,
|
||||
));
|
||||
result[0] = Some(point(loc_store.as_ref()?[0] as f32, startRow as f32));
|
||||
result[1] = Some(point(loc_store.as_ref()?[1] as f32, startRow as f32));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -267,10 +257,7 @@ fn findRowsWithPattern(
|
||||
// Last row of the current symbol that contains pattern
|
||||
if found {
|
||||
let mut skippedRowCount = 0;
|
||||
let mut previousRowLoc = [
|
||||
result[0].as_ref()?.getX() as u32,
|
||||
result[1].as_ref()?.getX() as u32,
|
||||
];
|
||||
let mut previousRowLoc = [result[0].as_ref()?.x as u32, result[1].as_ref()?.x as u32];
|
||||
while stopRow < height {
|
||||
if let Some(loc) = findGuardPattern(
|
||||
matrix,
|
||||
@@ -303,14 +290,8 @@ fn findRowsWithPattern(
|
||||
stopRow += 1;
|
||||
}
|
||||
stopRow -= skippedRowCount + 1;
|
||||
result[2] = Some(RXingResultPoint::new(
|
||||
previousRowLoc[0] as f32,
|
||||
stopRow as f32,
|
||||
));
|
||||
result[3] = Some(RXingResultPoint::new(
|
||||
previousRowLoc[1] as f32,
|
||||
stopRow as f32,
|
||||
));
|
||||
result[2] = Some(point(previousRowLoc[0] as f32, stopRow as f32));
|
||||
result[3] = Some(point(previousRowLoc[1] as f32, stopRow as f32));
|
||||
}
|
||||
if stopRow - startRow < BARCODE_MIN_HEIGHT {
|
||||
result.fill(None);
|
||||
|
||||
@@ -14,23 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::{common::BitMatrix, RXingResultPoint};
|
||||
use crate::{common::BitMatrix, Point};
|
||||
|
||||
/**
|
||||
* @author Guenther Grau
|
||||
*/
|
||||
pub struct PDF417DetectorRXingResult {
|
||||
bits: BitMatrix,
|
||||
points: Vec<[Option<RXingResultPoint>; 8]>,
|
||||
points: Vec<[Option<Point>; 8]>,
|
||||
rotation: u32,
|
||||
}
|
||||
|
||||
impl PDF417DetectorRXingResult {
|
||||
pub fn with_rotation(
|
||||
bits: BitMatrix,
|
||||
points: Vec<[Option<RXingResultPoint>; 8]>,
|
||||
rotation: u32,
|
||||
) -> Self {
|
||||
pub fn with_rotation(bits: BitMatrix, points: Vec<[Option<Point>; 8]>, rotation: u32) -> Self {
|
||||
Self {
|
||||
bits,
|
||||
points,
|
||||
@@ -38,7 +34,7 @@ impl PDF417DetectorRXingResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(bits: BitMatrix, points: Vec<[Option<RXingResultPoint>; 8]>) -> Self {
|
||||
pub fn new(bits: BitMatrix, points: Vec<[Option<Point>; 8]>) -> Self {
|
||||
Self::with_rotation(bits, points, 0)
|
||||
}
|
||||
|
||||
@@ -46,7 +42,7 @@ impl PDF417DetectorRXingResult {
|
||||
&self.bits
|
||||
}
|
||||
|
||||
pub fn getPoints(&self) -> &Vec<[Option<RXingResultPoint>; 8]> {
|
||||
pub fn getPoints(&self) -> &Vec<[Option<Point>; 8]> {
|
||||
&self.points
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
common::Result, multi::MultipleBarcodeReader, BarcodeFormat, BinaryBitmap,
|
||||
DecodingHintDictionary, Exceptions, RXingResult, RXingResultMetadataType,
|
||||
RXingResultMetadataValue, RXingResultPoint, Reader, ResultPoint,
|
||||
DecodingHintDictionary, Exceptions, Point, RXingResult, RXingResultMetadataType,
|
||||
RXingResultMetadataValue, Reader,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -151,23 +151,23 @@ impl PDF417Reader {
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
fn getMaxWidth(p1: &Option<RXingResultPoint>, p2: &Option<RXingResultPoint>) -> u64 {
|
||||
fn getMaxWidth(p1: &Option<Point>, p2: &Option<Point>) -> u64 {
|
||||
if let (Some(p1), Some(p2)) = (p1, p2) {
|
||||
(p1.getX() - p2.getX()).abs() as u64
|
||||
(p1.x - p2.x).abs() as u64
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn getMinWidth(p1: &Option<RXingResultPoint>, p2: &Option<RXingResultPoint>) -> u64 {
|
||||
fn getMinWidth(p1: &Option<Point>, p2: &Option<Point>) -> u64 {
|
||||
if let (Some(p1), Some(p2)) = (p1, p2) {
|
||||
(p1.getX() - p2.getX()).abs() as u64
|
||||
(p1.x - p2.x).abs() as u64
|
||||
} else {
|
||||
u32::MAX as u64
|
||||
}
|
||||
}
|
||||
|
||||
fn getMaxCodewordWidth(p: &[Option<RXingResultPoint>]) -> u32 {
|
||||
fn getMaxCodewordWidth(p: &[Option<Point>]) -> u32 {
|
||||
Self::getMaxWidth(&p[0], &p[4])
|
||||
.max(
|
||||
Self::getMaxWidth(&p[6], &p[2]) * pdf_417_common::MODULES_IN_CODEWORD as u64
|
||||
@@ -179,7 +179,7 @@ impl PDF417Reader {
|
||||
)) as u32
|
||||
}
|
||||
|
||||
fn getMinCodewordWidth(p: &[Option<RXingResultPoint>]) -> u32 {
|
||||
fn getMinCodewordWidth(p: &[Option<Point>]) -> u32 {
|
||||
Self::getMinWidth(&p[0], &p[4])
|
||||
.min(
|
||||
Self::getMinWidth(&p[6], &p[2]) * pdf_417_common::MODULES_IN_CODEWORD as u64
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::RXingResultPoint;
|
||||
use crate::Point;
|
||||
|
||||
/**
|
||||
* Meta-data container for QR Code decoding. Instances of this class may be used to convey information back to the
|
||||
@@ -41,7 +41,7 @@ impl QRCodeDecoderMetaData {
|
||||
*
|
||||
* @param points Array of points to apply mirror correction to.
|
||||
*/
|
||||
pub fn applyMirroredCorrection(&self, points: &mut [RXingResultPoint]) {
|
||||
pub fn applyMirroredCorrection(&self, points: &mut [Point]) {
|
||||
if !self.0 || points.is_empty() || points.len() < 3 {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//RXingResultPoint
|
||||
//Point
|
||||
|
||||
use crate::{RXingResultPoint, ResultPoint};
|
||||
use crate::{point, Point};
|
||||
|
||||
/**
|
||||
* <p>Encapsulates an alignment pattern, which are the smaller square patterns found in
|
||||
@@ -27,23 +27,18 @@ use crate::{RXingResultPoint, ResultPoint};
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct AlignmentPattern {
|
||||
estimatedModuleSize: f32,
|
||||
point: (f32, f32),
|
||||
point: Point,
|
||||
}
|
||||
|
||||
impl ResultPoint for AlignmentPattern {
|
||||
fn getX(&self) -> f32 {
|
||||
self.point.0
|
||||
impl From<&AlignmentPattern> for Point {
|
||||
fn from(value: &AlignmentPattern) -> Self {
|
||||
value.point
|
||||
}
|
||||
}
|
||||
|
||||
fn getY(&self) -> f32 {
|
||||
self.point.1
|
||||
}
|
||||
|
||||
fn into_rxing_result_point(self) -> RXingResultPoint {
|
||||
RXingResultPoint {
|
||||
x: self.point.0,
|
||||
y: self.point.1,
|
||||
}
|
||||
impl From<AlignmentPattern> for Point {
|
||||
fn from(value: AlignmentPattern) -> Self {
|
||||
value.point
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +46,7 @@ impl AlignmentPattern {
|
||||
pub fn new(posX: f32, posY: f32, estimatedModuleSize: f32) -> Self {
|
||||
Self {
|
||||
estimatedModuleSize,
|
||||
point: (posX, posY),
|
||||
point: point(posX, posY),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +55,7 @@ impl AlignmentPattern {
|
||||
* position and size -- meaning, it is at nearly the same center with nearly the same size.</p>
|
||||
*/
|
||||
pub fn aboutEquals(&self, moduleSize: f32, i: f32, j: f32) -> bool {
|
||||
if (i - self.getY()).abs() <= moduleSize && (j - self.getX()).abs() <= moduleSize {
|
||||
if (i - self.point.y).abs() <= moduleSize && (j - self.point.x).abs() <= moduleSize {
|
||||
let moduleSizeDiff = (moduleSize - self.estimatedModuleSize).abs();
|
||||
return moduleSizeDiff <= 1.0 || moduleSizeDiff <= self.estimatedModuleSize;
|
||||
}
|
||||
@@ -72,8 +67,8 @@ impl AlignmentPattern {
|
||||
* with a new estimate. It returns a new {@code FinderPattern} containing an average of the two.
|
||||
*/
|
||||
pub fn combineEstimate(&self, i: f32, j: f32, newModuleSize: f32) -> AlignmentPattern {
|
||||
let combinedX = (self.getX() + j) / 2.0;
|
||||
let combinedY = (self.getY() + i) / 2.0;
|
||||
let combinedX = (self.point.x + j) / 2.0;
|
||||
let combinedY = (self.point.y + i) / 2.0;
|
||||
let combinedModuleSize = (self.estimatedModuleSize + newModuleSize) / 2.0;
|
||||
AlignmentPattern::new(combinedX, combinedY, combinedModuleSize)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use crate::{
|
||||
common::{BitMatrix, Result},
|
||||
Exceptions, RXingResultPointCallback,
|
||||
Exceptions, PointCallback,
|
||||
};
|
||||
|
||||
use super::AlignmentPattern;
|
||||
@@ -44,7 +44,7 @@ pub struct AlignmentPatternFinder {
|
||||
height: u32,
|
||||
moduleSize: f32,
|
||||
crossCheckStateCount: [u32; 3],
|
||||
resultPointCallback: Option<RXingResultPointCallback>,
|
||||
resultPointCallback: Option<PointCallback>,
|
||||
}
|
||||
|
||||
impl AlignmentPatternFinder {
|
||||
@@ -65,7 +65,7 @@ impl AlignmentPatternFinder {
|
||||
width: u32,
|
||||
height: u32,
|
||||
moduleSize: f32,
|
||||
resultPointCallback: Option<RXingResultPointCallback>,
|
||||
resultPointCallback: Option<PointCallback>,
|
||||
) -> Self {
|
||||
Self {
|
||||
image,
|
||||
@@ -311,7 +311,7 @@ impl AlignmentPatternFinder {
|
||||
// Hadn't found this before; save it
|
||||
let point = AlignmentPattern::new(centerJ, centerI, estimatedModuleSize);
|
||||
if let Some(rpc) = self.resultPointCallback.clone() {
|
||||
rpc(&point);
|
||||
rpc((&point).into());
|
||||
}
|
||||
|
||||
self.possibleCenters.push(point);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::{RXingResultPoint, ResultPoint};
|
||||
use crate::{point, Point};
|
||||
|
||||
/**
|
||||
* <p>Encapsulates a finder pattern, which are the three square patterns found in
|
||||
@@ -27,23 +27,18 @@ use crate::{RXingResultPoint, ResultPoint};
|
||||
pub struct FinderPattern {
|
||||
estimatedModuleSize: f32,
|
||||
count: usize,
|
||||
point: (f32, f32),
|
||||
pub(crate) point: Point,
|
||||
}
|
||||
|
||||
impl ResultPoint for FinderPattern {
|
||||
fn getX(&self) -> f32 {
|
||||
self.point.0
|
||||
impl From<&FinderPattern> for Point {
|
||||
fn from(value: &FinderPattern) -> Self {
|
||||
value.point
|
||||
}
|
||||
}
|
||||
|
||||
fn getY(&self) -> f32 {
|
||||
self.point.1
|
||||
}
|
||||
|
||||
fn into_rxing_result_point(self) -> RXingResultPoint {
|
||||
RXingResultPoint {
|
||||
x: self.point.0,
|
||||
y: self.point.1,
|
||||
}
|
||||
impl From<FinderPattern> for Point {
|
||||
fn from(value: FinderPattern) -> Self {
|
||||
value.point
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +51,7 @@ impl FinderPattern {
|
||||
Self {
|
||||
estimatedModuleSize,
|
||||
count,
|
||||
point: (posX, posY),
|
||||
point: point(posX, posY),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +68,7 @@ impl FinderPattern {
|
||||
* position and size -- meaning, it is at nearly the same center with nearly the same size.</p>
|
||||
*/
|
||||
pub fn aboutEquals(&self, moduleSize: f32, i: f32, j: f32) -> bool {
|
||||
if (i - self.getY()).abs() <= moduleSize && (j - self.getX()).abs() <= moduleSize {
|
||||
if (i - self.point.y).abs() <= moduleSize && (j - self.point.x).abs() <= moduleSize {
|
||||
let moduleSizeDiff = (moduleSize - self.estimatedModuleSize).abs();
|
||||
moduleSizeDiff <= 1.0 || moduleSizeDiff <= self.estimatedModuleSize
|
||||
} else {
|
||||
@@ -88,8 +83,8 @@ impl FinderPattern {
|
||||
*/
|
||||
pub fn combineEstimate(&self, i: f32, j: f32, newModuleSize: f32) -> FinderPattern {
|
||||
let combinedCount = self.count as f32 + 1.0;
|
||||
let combinedX = (self.count as f32 * self.getX() + j) / combinedCount;
|
||||
let combinedY = (self.count as f32 * self.getY() + i) / combinedCount;
|
||||
let combinedX = (self.count as f32 * self.point.x + j) / combinedCount;
|
||||
let combinedY = (self.count as f32 * self.point.y + i) / combinedCount;
|
||||
let combinedModuleSize =
|
||||
(self.count as f32 * self.estimatedModuleSize + newModuleSize) / combinedCount;
|
||||
FinderPattern::private_new(
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use std::ops::Div;
|
||||
|
||||
use crate::{
|
||||
common::{BitMatrix, Result},
|
||||
result_point_utils, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions,
|
||||
RXingResultPointCallback, ResultPoint,
|
||||
result_point_utils, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions, Point,
|
||||
PointCallback,
|
||||
};
|
||||
|
||||
use super::{FinderPattern, FinderPatternInfo};
|
||||
@@ -35,7 +37,7 @@ pub struct FinderPatternFinder<'a> {
|
||||
possibleCenters: Vec<FinderPattern>,
|
||||
hasSkipped: bool,
|
||||
crossCheckStateCount: [u32; 5],
|
||||
resultPointCallback: Option<RXingResultPointCallback>,
|
||||
resultPointCallback: Option<PointCallback>,
|
||||
}
|
||||
impl<'a> FinderPatternFinder<'_> {
|
||||
pub const CENTER_QUORUM: usize = 2;
|
||||
@@ -53,7 +55,7 @@ impl<'a> FinderPatternFinder<'_> {
|
||||
|
||||
pub fn with_callback(
|
||||
image: &'a BitMatrix,
|
||||
resultPointCallback: Option<RXingResultPointCallback>,
|
||||
resultPointCallback: Option<PointCallback>,
|
||||
) -> FinderPatternFinder<'a> {
|
||||
FinderPatternFinder {
|
||||
image,
|
||||
@@ -603,7 +605,7 @@ impl<'a> FinderPatternFinder<'_> {
|
||||
let point = FinderPattern::new(centerJ, centerI, estimatedModuleSize);
|
||||
self.possibleCenters.push(point);
|
||||
if let Some(rpc) = self.resultPointCallback.clone() {
|
||||
rpc(&point);
|
||||
rpc((&point).into());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -633,9 +635,11 @@ impl<'a> FinderPatternFinder<'_> {
|
||||
// difference in the x / y coordinates of the two centers.
|
||||
// This is the case where you find top left last.
|
||||
self.hasSkipped = true;
|
||||
return (((fnp.getX() - center.getX()).abs()
|
||||
- (fnp.getY() - center.getY()).abs())
|
||||
/ 2.0)
|
||||
|
||||
return (Point::from(fnp) - Point::from(center))
|
||||
.abs()
|
||||
.fold(|x, y| x - y)
|
||||
.div(2.0)
|
||||
.floor() as u32;
|
||||
} else {
|
||||
firstConfirmedCenter.replace(center);
|
||||
@@ -679,10 +683,7 @@ impl<'a> FinderPatternFinder<'_> {
|
||||
* Get square of distance between a and b.
|
||||
*/
|
||||
fn squaredDistance(a: &FinderPattern, b: &FinderPattern) -> f64 {
|
||||
let x = a.getX() as f64 - b.getX() as f64;
|
||||
let y = a.getY() as f64 - b.getY() as f64;
|
||||
|
||||
x * x + y * y
|
||||
Point::from(a).squaredDistance(Point::from(b)) as f64
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,13 +17,10 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
common::{
|
||||
detector::MathUtils, BitMatrix, DefaultGridSampler, GridSampler, PerspectiveTransform,
|
||||
Result,
|
||||
},
|
||||
common::{BitMatrix, DefaultGridSampler, GridSampler, PerspectiveTransform, Result},
|
||||
point,
|
||||
qrcode::decoder::Version,
|
||||
result_point_utils, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions,
|
||||
RXingResultPointCallback, ResultPoint,
|
||||
DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions, Point, PointCallback,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -39,7 +36,7 @@ use super::{
|
||||
*/
|
||||
pub struct Detector<'a> {
|
||||
image: &'a BitMatrix,
|
||||
resultPointCallback: Option<RXingResultPointCallback>,
|
||||
resultPointCallback: Option<PointCallback>,
|
||||
}
|
||||
|
||||
impl<'a> Detector<'_> {
|
||||
@@ -54,7 +51,7 @@ impl<'a> Detector<'_> {
|
||||
self.image
|
||||
}
|
||||
|
||||
pub fn getRXingResultPointCallback(&self) -> &Option<RXingResultPointCallback> {
|
||||
pub fn getPointCallback(&self) -> &Option<PointCallback> {
|
||||
&self.resultPointCallback
|
||||
}
|
||||
|
||||
@@ -116,16 +113,16 @@ impl<'a> Detector<'_> {
|
||||
// Anything above version 1 has an alignment pattern
|
||||
if !provisionalVersion.getAlignmentPatternCenters().is_empty() {
|
||||
// Guess where a "bottom right" finder pattern would have been
|
||||
let bottomRightX = topRight.getX() - topLeft.getX() + bottomLeft.getX();
|
||||
let bottomRightY = topRight.getY() - topLeft.getY() + bottomLeft.getY();
|
||||
let bottomRightX = topRight.point.x - topLeft.point.x + bottomLeft.point.x;
|
||||
let bottomRightY = topRight.point.y - topLeft.point.y + bottomLeft.point.y;
|
||||
|
||||
// Estimate that alignment pattern is closer by 3 modules
|
||||
// from "bottom right" to known top left location
|
||||
let correctionToTopLeft = 1.0 - (3.0 / modulesBetweenFPCenters as f32);
|
||||
let estAlignmentX =
|
||||
(topLeft.getX() + correctionToTopLeft * (bottomRightX - topLeft.getX())) as u32;
|
||||
(topLeft.point.x + correctionToTopLeft * (bottomRightX - topLeft.point.x)) as u32;
|
||||
let estAlignmentY =
|
||||
(topLeft.getY() + correctionToTopLeft * (bottomRightY - topLeft.getY())) as u32;
|
||||
(topLeft.point.y + correctionToTopLeft * (bottomRightY - topLeft.point.y)) as u32;
|
||||
|
||||
// Kind of arbitrary -- expand search radius before giving up
|
||||
let mut i = 4;
|
||||
@@ -153,29 +150,30 @@ impl<'a> Detector<'_> {
|
||||
let bits = Detector::sampleGrid(self.image, &transform, dimension)?;
|
||||
|
||||
let mut points = vec![
|
||||
bottomLeft.into_rxing_result_point(),
|
||||
topLeft.into_rxing_result_point(),
|
||||
topRight.into_rxing_result_point(),
|
||||
Point::from(bottomLeft),
|
||||
Point::from(topLeft),
|
||||
Point::from(topRight),
|
||||
];
|
||||
|
||||
if alignmentPattern.is_some() {
|
||||
points.push(
|
||||
alignmentPattern
|
||||
.ok_or(Exceptions::notFound)?
|
||||
.into_rxing_result_point(),
|
||||
)
|
||||
points.push(alignmentPattern.ok_or(Exceptions::notFound)?.into())
|
||||
}
|
||||
|
||||
Ok(QRCodeDetectorResult::new(bits, points))
|
||||
}
|
||||
|
||||
fn createTransform<T: ResultPoint, X: ResultPoint>(
|
||||
topLeft: &T,
|
||||
topRight: &T,
|
||||
bottomLeft: &T,
|
||||
alignmentPattern: Option<&X>,
|
||||
fn createTransform<T: Into<Point>, X: Into<Point>>(
|
||||
topLeft: T,
|
||||
topRight: T,
|
||||
bottomLeft: T,
|
||||
alignmentPattern: Option<X>,
|
||||
dimension: u32,
|
||||
) -> Option<PerspectiveTransform> {
|
||||
let topLeft: Point = topLeft.into();
|
||||
let topRight: Point = topRight.into();
|
||||
let bottomLeft: Point = bottomLeft.into();
|
||||
let alignmentPattern: Option<Point> = alignmentPattern.map(Into::into);
|
||||
|
||||
let dimMinusThree = dimension as f32 - 3.5;
|
||||
let bottomRightX: f32;
|
||||
let bottomRightY: f32;
|
||||
@@ -183,14 +181,14 @@ impl<'a> Detector<'_> {
|
||||
let sourceBottomRightY: f32;
|
||||
if alignmentPattern.is_some() {
|
||||
let alignmentPattern = alignmentPattern?;
|
||||
bottomRightX = alignmentPattern.getX();
|
||||
bottomRightY = alignmentPattern.getY();
|
||||
bottomRightX = alignmentPattern.x;
|
||||
bottomRightY = alignmentPattern.y;
|
||||
sourceBottomRightX = dimMinusThree - 3.0;
|
||||
sourceBottomRightY = sourceBottomRightX;
|
||||
} else {
|
||||
// Don't have an alignment pattern, just make up the bottom-right point
|
||||
bottomRightX = (topRight.getX() - topLeft.getX()) + bottomLeft.getX();
|
||||
bottomRightY = (topRight.getY() - topLeft.getY()) + bottomLeft.getY();
|
||||
bottomRightX = (topRight.x - topLeft.x) + bottomLeft.x;
|
||||
bottomRightY = (topRight.y - topLeft.y) + bottomLeft.y;
|
||||
sourceBottomRightX = dimMinusThree;
|
||||
sourceBottomRightY = dimMinusThree;
|
||||
}
|
||||
@@ -204,14 +202,14 @@ impl<'a> Detector<'_> {
|
||||
sourceBottomRightY,
|
||||
3.5,
|
||||
dimMinusThree,
|
||||
topLeft.getX(),
|
||||
topLeft.getY(),
|
||||
topRight.getX(),
|
||||
topRight.getY(),
|
||||
topLeft.x,
|
||||
topLeft.y,
|
||||
topRight.x,
|
||||
topRight.y,
|
||||
bottomRightX,
|
||||
bottomRightY,
|
||||
bottomLeft.getX(),
|
||||
bottomLeft.getY(),
|
||||
bottomLeft.x,
|
||||
bottomLeft.y,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -228,16 +226,16 @@ impl<'a> Detector<'_> {
|
||||
* <p>Computes the dimension (number of modules on a size) of the QR Code based on the position
|
||||
* of the finder patterns and estimated module size.</p>
|
||||
*/
|
||||
fn computeDimension<T: ResultPoint>(
|
||||
topLeft: &T,
|
||||
topRight: &T,
|
||||
bottomLeft: &T,
|
||||
fn computeDimension<T: Into<Point> + Copy>(
|
||||
topLeft: T,
|
||||
topRight: T,
|
||||
bottomLeft: T,
|
||||
moduleSize: f32,
|
||||
) -> Result<u32> {
|
||||
let tltrCentersDimension =
|
||||
MathUtils::round(result_point_utils::distance(topLeft, topRight) / moduleSize);
|
||||
(Point::distance(topLeft.into(), topRight.into()) / moduleSize).round() as i32;
|
||||
let tlblCentersDimension =
|
||||
MathUtils::round(result_point_utils::distance(topLeft, bottomLeft) / moduleSize);
|
||||
(Point::distance(topLeft.into(), bottomLeft.into()) / moduleSize).round() as i32;
|
||||
let mut dimension = ((tltrCentersDimension + tlblCentersDimension) / 2) + 7;
|
||||
match dimension & 0x03 {
|
||||
0 => dimension += 1,
|
||||
@@ -257,11 +255,11 @@ impl<'a> Detector<'_> {
|
||||
* @param bottomLeft detected bottom-left finder pattern center
|
||||
* @return estimated module size
|
||||
*/
|
||||
pub fn calculateModuleSize<T: ResultPoint>(
|
||||
pub fn calculateModuleSize<T: Into<Point> + Copy>(
|
||||
&self,
|
||||
topLeft: &T,
|
||||
topRight: &T,
|
||||
bottomLeft: &T,
|
||||
topLeft: T,
|
||||
topRight: T,
|
||||
bottomLeft: T,
|
||||
) -> f32 {
|
||||
// Take the average
|
||||
(self.calculateModuleSizeOneWay(topLeft, topRight)
|
||||
@@ -274,18 +272,21 @@ impl<'a> Detector<'_> {
|
||||
* {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the
|
||||
* width of each, measuring along the axis between their centers.</p>
|
||||
*/
|
||||
fn calculateModuleSizeOneWay<T: ResultPoint>(&self, pattern: &T, otherPattern: &T) -> f32 {
|
||||
fn calculateModuleSizeOneWay<T: Into<Point>>(&self, pattern: T, otherPattern: T) -> f32 {
|
||||
let pattern: Point = pattern.into();
|
||||
let otherPattern: Point = otherPattern.into();
|
||||
|
||||
let moduleSizeEst1 = self.sizeOfBlackWhiteBlackRunBothWays(
|
||||
pattern.getX().floor() as u32,
|
||||
pattern.getY().floor() as u32,
|
||||
otherPattern.getX().floor() as u32,
|
||||
otherPattern.getY().floor() as u32,
|
||||
pattern.x.floor() as u32,
|
||||
pattern.y.floor() as u32,
|
||||
otherPattern.x.floor() as u32,
|
||||
otherPattern.y.floor() as u32,
|
||||
);
|
||||
let moduleSizeEst2 = self.sizeOfBlackWhiteBlackRunBothWays(
|
||||
otherPattern.getX().floor() as u32,
|
||||
otherPattern.getY().floor() as u32,
|
||||
pattern.getX().floor() as u32,
|
||||
pattern.getY().floor() as u32,
|
||||
otherPattern.x.floor() as u32,
|
||||
otherPattern.y.floor() as u32,
|
||||
pattern.x.floor() as u32,
|
||||
pattern.y.floor() as u32,
|
||||
);
|
||||
if moduleSizeEst1.is_nan() {
|
||||
return moduleSizeEst2 / 7.0;
|
||||
@@ -379,7 +380,10 @@ impl<'a> Detector<'_> {
|
||||
// color, advance to next state or end if we are in state 2 already
|
||||
if (state == 1) == self.image.get(realX as u32, realY as u32) {
|
||||
if state == 2 {
|
||||
return MathUtils::distance(x, y, fromX as i32, fromY as i32);
|
||||
return Point::distance(
|
||||
point(x as f32, y as f32),
|
||||
point(fromX as f32, fromY as f32),
|
||||
);
|
||||
}
|
||||
state += 1;
|
||||
}
|
||||
@@ -399,7 +403,10 @@ impl<'a> Detector<'_> {
|
||||
// is "white" so this last point at (toX+xStep,toY) is the right ending. This is really a
|
||||
// small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this.
|
||||
if state == 2 {
|
||||
return MathUtils::distance(toX as i32 + xstep, toY as i32, fromX as i32, fromY as i32);
|
||||
return Point::distance(
|
||||
point((toX as i32 + xstep) as f32, toY as f32),
|
||||
point(fromX as f32, fromY as f32),
|
||||
);
|
||||
}
|
||||
// else we didn't find even black-white-black; no estimate is really possible
|
||||
f32::NAN
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use crate::{
|
||||
common::{BitMatrix, DetectorRXingResult},
|
||||
RXingResultPoint,
|
||||
Point,
|
||||
};
|
||||
|
||||
pub struct QRCodeDetectorResult {
|
||||
bit_source: BitMatrix,
|
||||
result_points: Vec<RXingResultPoint>,
|
||||
result_points: Vec<Point>,
|
||||
}
|
||||
|
||||
impl QRCodeDetectorResult {
|
||||
pub fn new(bit_source: BitMatrix, result_points: Vec<RXingResultPoint>) -> Self {
|
||||
pub fn new(bit_source: BitMatrix, result_points: Vec<Point>) -> Self {
|
||||
Self {
|
||||
bit_source,
|
||||
result_points,
|
||||
@@ -22,7 +22,7 @@ impl DetectorRXingResult for QRCodeDetectorResult {
|
||||
&self.bit_source
|
||||
}
|
||||
|
||||
fn getPoints(&self) -> &[crate::RXingResultPoint] {
|
||||
fn getPoints(&self) -> &[crate::Point] {
|
||||
&self.result_points
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
common::{BitMatrix, DecoderRXingResult, DetectorRXingResult, Result},
|
||||
BarcodeFormat, DecodeHintType, DecodeHintValue, Exceptions, RXingResult,
|
||||
RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader,
|
||||
BarcodeFormat, DecodeHintType, DecodeHintValue, Exceptions, Point, RXingResult,
|
||||
RXingResultMetadataType, RXingResultMetadataValue, Reader,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -36,7 +36,7 @@ use super::{
|
||||
pub struct QRCodeReader;
|
||||
// pub struct QRCodeReader; {
|
||||
|
||||
// // private static final RXingResultPoint[] NO_POINTS = new RXingResultPoint[0];
|
||||
// // private static final Point[] NO_POINTS = new Point[0];
|
||||
// }
|
||||
|
||||
impl Reader for QRCodeReader {
|
||||
@@ -58,7 +58,7 @@ impl Reader for QRCodeReader {
|
||||
hints: &crate::DecodingHintDictionary,
|
||||
) -> Result<crate::RXingResult> {
|
||||
let decoderRXingResult: DecoderRXingResult;
|
||||
let mut points: Vec<RXingResultPoint>;
|
||||
let mut points: Vec<Point>;
|
||||
if matches!(
|
||||
hints.get(&DecodeHintType::PURE_BARCODE),
|
||||
Some(DecodeHintValue::PureBarcode(true))
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
use crate::RXingResultPoint;
|
||||
use crate::Point;
|
||||
|
||||
pub trait ResultPoint {
|
||||
fn getX(&self) -> f32;
|
||||
fn getY(&self) -> f32;
|
||||
fn into_rxing_result_point(self) -> RXingResultPoint;
|
||||
fn to_rxing_result_point(&self) -> Point;
|
||||
}
|
||||
|
||||
@@ -1,87 +1,43 @@
|
||||
use crate::{common::detector::MathUtils, ResultPoint};
|
||||
use crate::Point;
|
||||
|
||||
/**
|
||||
* Orders an array of three RXingResultPoints in an order [A,B,C] such that AB is less than AC
|
||||
* Orders an array of three Points in an order [A,B,C] such that AB is less than AC
|
||||
* and BC is less than AC, and the angle between BC and BA is less than 180 degrees.
|
||||
*
|
||||
* @param patterns array of three {@code RXingResultPoint} to order
|
||||
* @param patterns array of three {@code Point} to order
|
||||
*/
|
||||
pub fn orderBestPatterns<T: ResultPoint + Copy + Clone>(patterns: &mut [T; 3]) {
|
||||
pub fn orderBestPatterns<T: Into<Point> + Copy>(patterns: &mut [T; 3]) {
|
||||
// Find distances between pattern centers
|
||||
let zeroOneDistance = MathUtils::distance(
|
||||
patterns[0].getX(),
|
||||
patterns[0].getY(),
|
||||
patterns[1].getX(),
|
||||
patterns[1].getY(),
|
||||
);
|
||||
let oneTwoDistance = MathUtils::distance(
|
||||
patterns[1].getX(),
|
||||
patterns[1].getY(),
|
||||
patterns[2].getX(),
|
||||
patterns[2].getY(),
|
||||
);
|
||||
let zeroTwoDistance = MathUtils::distance(
|
||||
patterns[0].getX(),
|
||||
patterns[0].getY(),
|
||||
patterns[2].getX(),
|
||||
patterns[2].getY(),
|
||||
);
|
||||
|
||||
let mut pointA;
|
||||
let pointB;
|
||||
let mut pointC;
|
||||
let zeroOneDistance = Point::distance(patterns[0].into(), patterns[1].into());
|
||||
let oneTwoDistance = Point::distance(patterns[1].into(), patterns[2].into());
|
||||
let zeroTwoDistance = Point::distance(patterns[0].into(), patterns[2].into());
|
||||
|
||||
// Assume one closest to other two is B; A and C will just be guesses at first
|
||||
if oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance {
|
||||
pointB = patterns[0];
|
||||
pointA = patterns[1];
|
||||
pointC = patterns[2];
|
||||
} else if zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance {
|
||||
pointB = patterns[1];
|
||||
pointA = patterns[0];
|
||||
pointC = patterns[2];
|
||||
} else {
|
||||
pointB = patterns[2];
|
||||
pointA = patterns[0];
|
||||
pointC = patterns[1];
|
||||
}
|
||||
let (mut pointA, pointB, mut pointC) =
|
||||
if oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance {
|
||||
(patterns[1], patterns[0], patterns[2])
|
||||
} else if zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance {
|
||||
(patterns[0], patterns[1], patterns[2])
|
||||
} else {
|
||||
(patterns[0], patterns[2], patterns[1])
|
||||
};
|
||||
|
||||
// Use cross product to figure out whether A and C are correct or flipped.
|
||||
// This asks whether BC x BA has a positive z component, which is the arrangement
|
||||
// we want for A, B, C. If it's negative, then we've got it flipped around and
|
||||
// should swap A and C.
|
||||
if crossProductZ(pointA, pointB, pointC) < 0.0 {
|
||||
if crossProductZ(pointA.into(), pointB.into(), pointC.into()) < 0.0 {
|
||||
std::mem::swap(&mut pointA, &mut pointC);
|
||||
}
|
||||
|
||||
let pa = pointA;
|
||||
let pb = pointB;
|
||||
let pc = pointC;
|
||||
|
||||
patterns[0] = pa;
|
||||
patterns[1] = pb;
|
||||
patterns[2] = pc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pattern1 first pattern
|
||||
* @param pattern2 second pattern
|
||||
* @return distance between two points
|
||||
*/
|
||||
pub fn distance<T: ResultPoint>(pattern1: &T, pattern2: &T) -> f32 {
|
||||
MathUtils::distance(
|
||||
pattern1.getX(),
|
||||
pattern1.getY(),
|
||||
pattern2.getX(),
|
||||
pattern2.getY(),
|
||||
)
|
||||
patterns[0] = pointA;
|
||||
patterns[1] = pointB;
|
||||
patterns[2] = pointC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the z component of the cross product between vectors BC and BA.
|
||||
*/
|
||||
pub fn crossProductZ<T: ResultPoint>(pointA: T, pointB: T, pointC: T) -> f32 {
|
||||
let bX = pointB.getX();
|
||||
let bY = pointB.getY();
|
||||
((pointC.getX() - bX) * (pointA.getY() - bY)) - ((pointC.getY() - bY) * (pointA.getX() - bX))
|
||||
fn crossProductZ(a: Point, b: Point, c: Point) -> f32 {
|
||||
((c.x - b.x) * (a.y - b.y)) - ((c.y - b.y) * (a.x - b.x))
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use std::{collections::HashMap, fmt};
|
||||
|
||||
use crate::{BarcodeFormat, RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint};
|
||||
use crate::{BarcodeFormat, Point, RXingResultMetadataType, RXingResultMetadataValue};
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -32,7 +32,7 @@ pub struct RXingResult {
|
||||
text: String,
|
||||
rawBytes: Vec<u8>,
|
||||
numBits: usize,
|
||||
resultPoints: Vec<RXingResultPoint>,
|
||||
resultPoints: Vec<Point>,
|
||||
format: BarcodeFormat,
|
||||
resultMetadata: HashMap<RXingResultMetadataType, RXingResultMetadataValue>,
|
||||
timestamp: u128,
|
||||
@@ -41,7 +41,7 @@ impl RXingResult {
|
||||
pub fn new(
|
||||
text: &str,
|
||||
rawBytes: Vec<u8>,
|
||||
resultPoints: Vec<RXingResultPoint>,
|
||||
resultPoints: Vec<Point>,
|
||||
format: BarcodeFormat,
|
||||
) -> Self {
|
||||
Self::new_timestamp(
|
||||
@@ -56,7 +56,7 @@ impl RXingResult {
|
||||
pub fn new_timestamp(
|
||||
text: &str,
|
||||
rawBytes: Vec<u8>,
|
||||
resultPoints: Vec<RXingResultPoint>,
|
||||
resultPoints: Vec<Point>,
|
||||
format: BarcodeFormat,
|
||||
timestamp: u128,
|
||||
) -> Self {
|
||||
@@ -68,7 +68,7 @@ impl RXingResult {
|
||||
text: &str,
|
||||
rawBytes: Vec<u8>,
|
||||
numBits: usize,
|
||||
resultPoints: Vec<RXingResultPoint>,
|
||||
resultPoints: Vec<Point>,
|
||||
format: BarcodeFormat,
|
||||
timestamp: u128,
|
||||
) -> Self {
|
||||
@@ -83,7 +83,7 @@ impl RXingResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_existing_result(prev: Self, points: Vec<RXingResultPoint>) -> Self {
|
||||
pub fn new_from_existing_result(prev: Self, points: Vec<Point>) -> Self {
|
||||
Self {
|
||||
text: prev.text,
|
||||
rawBytes: prev.rawBytes,
|
||||
@@ -122,11 +122,21 @@ impl RXingResult {
|
||||
* identifying finder patterns or the corners of the barcode. The exact meaning is
|
||||
* specific to the type of barcode that was decoded.
|
||||
*/
|
||||
pub fn getRXingResultPoints(&self) -> &Vec<RXingResultPoint> {
|
||||
pub fn getPoints(&self) -> &Vec<Point> {
|
||||
&self.resultPoints
|
||||
}
|
||||
|
||||
pub fn getRXingResultPointsMut(&mut self) -> &mut Vec<RXingResultPoint> {
|
||||
pub fn getPointsMut(&mut self) -> &mut Vec<Point> {
|
||||
&mut self.resultPoints
|
||||
}
|
||||
|
||||
/** Currently necessary because the external OneDReader proc macro uses it. */
|
||||
pub fn getRXingResultPoints(&self) -> &Vec<Point> {
|
||||
&&self.resultPoints
|
||||
}
|
||||
|
||||
/** Currently necessary because the external OneDReader proc macro uses it. */
|
||||
pub fn getRXingResultPointsMut(&mut self) -> &mut Vec<Point> {
|
||||
&mut self.resultPoints
|
||||
}
|
||||
|
||||
@@ -169,7 +179,7 @@ impl RXingResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addRXingResultPoints(&mut self, newPoints: &mut Vec<RXingResultPoint>) {
|
||||
pub fn addPoints(&mut self, newPoints: &mut Vec<Point>) {
|
||||
if !newPoints.is_empty() {
|
||||
self.resultPoints.append(newPoints);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use std::{fmt, iter::Sum};
|
||||
|
||||
use crate::ResultPoint;
|
||||
use std::hash::Hash;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::ResultPoint;
|
||||
|
||||
/**
|
||||
* <p>Encapsulates a point of interest in an image containing a barcode. Typically, this
|
||||
* would be the location of a finder pattern or the corner of the barcode, for example.</p>
|
||||
@@ -14,49 +15,58 @@ use serde::{Deserialize, Serialize};
|
||||
*/
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct RXingResultPoint {
|
||||
pub struct Point {
|
||||
pub(crate) x: f32,
|
||||
pub(crate) y: f32,
|
||||
}
|
||||
impl Hash for RXingResultPoint {
|
||||
|
||||
/** An alias for `Point::new`. */
|
||||
pub fn point(x: f32, y: f32) -> Point {
|
||||
Point::new(x, y)
|
||||
}
|
||||
|
||||
/** Currently necessary because the external OneDReader proc macro uses it. */
|
||||
pub type RXingResultPoint = Point;
|
||||
|
||||
impl Hash for Point {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.x.to_string().hash(state);
|
||||
self.y.to_string().hash(state);
|
||||
}
|
||||
}
|
||||
impl PartialEq for RXingResultPoint {
|
||||
|
||||
impl PartialEq for Point {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.x == other.x && self.y == other.y
|
||||
}
|
||||
}
|
||||
impl Eq for RXingResultPoint {}
|
||||
impl RXingResultPoint {
|
||||
impl Eq for Point {}
|
||||
|
||||
impl Point {
|
||||
pub const fn new(x: f32, y: f32) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
pub const fn with_single(x: f32) -> Self {
|
||||
Self { x, y: x }
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::AddAssign for RXingResultPoint {
|
||||
impl std::ops::AddAssign for Point {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.x = self.x + rhs.x;
|
||||
self.y = self.y + rhs.y;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Sum<&'a RXingResultPoint> for RXingResultPoint {
|
||||
fn sum<I: Iterator<Item = &'a RXingResultPoint>>(iter: I) -> Self {
|
||||
let mut add = RXingResultPoint { x: 0.0, y: 0.0 };
|
||||
for n in iter {
|
||||
add += *n;
|
||||
}
|
||||
add
|
||||
impl<'a> Sum<&'a Point> for Point {
|
||||
fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::default(), |acc, &p| acc + p)
|
||||
}
|
||||
}
|
||||
|
||||
impl ResultPoint for RXingResultPoint {
|
||||
/** This impl is temporary and is there to ease refactoring. */
|
||||
impl ResultPoint for Point {
|
||||
fn getX(&self) -> f32 {
|
||||
self.x
|
||||
}
|
||||
@@ -65,210 +75,187 @@ impl ResultPoint for RXingResultPoint {
|
||||
self.y
|
||||
}
|
||||
|
||||
fn into_rxing_result_point(self) -> RXingResultPoint {
|
||||
self
|
||||
fn to_rxing_result_point(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RXingResultPoint {
|
||||
impl fmt::Display for Point {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "({},{})", self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Sub<RXingResultPoint> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
impl std::ops::Sub for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
x: self.x - rhs.x,
|
||||
y: self.y - rhs.y,
|
||||
}
|
||||
Self::new(self.x - rhs.x, self.y - rhs.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Sub<&RXingResultPoint> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
|
||||
fn sub(self, rhs: &Self) -> Self::Output {
|
||||
Self {
|
||||
x: self.x - rhs.x,
|
||||
y: self.y - rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Neg for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
impl std::ops::Neg for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
Self {
|
||||
x: -self.x,
|
||||
y: -self.y,
|
||||
}
|
||||
Self::new(-self.x, -self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Add<RXingResultPoint> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
impl std::ops::Add for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: RXingResultPoint) -> Self::Output {
|
||||
Self {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
}
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self::new(self.x + rhs.x, self.y + rhs.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<RXingResultPoint> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
impl std::ops::Mul for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: RXingResultPoint) -> Self::Output {
|
||||
Self {
|
||||
x: self.x * rhs.x,
|
||||
y: self.y * rhs.y,
|
||||
}
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
Self::new(self.x * rhs.x, self.y * rhs.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<f32> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
impl std::ops::Mul<f32> for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x * rhs,
|
||||
y: self.y * rhs,
|
||||
}
|
||||
Self::new(self.x * rhs, self.y * rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<i32> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
impl std::ops::Mul<i32> for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: i32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x * rhs as f32,
|
||||
y: self.y * rhs as f32,
|
||||
}
|
||||
Self::new(self.x * rhs as f32, self.y * rhs as f32)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<RXingResultPoint> for i32 {
|
||||
type Output = RXingResultPoint;
|
||||
impl std::ops::Mul<Point> for i32 {
|
||||
type Output = Point;
|
||||
|
||||
fn mul(self, rhs: RXingResultPoint) -> Self::Output {
|
||||
RXingResultPoint {
|
||||
x: rhs.x * self as f32,
|
||||
y: rhs.y * self as f32,
|
||||
}
|
||||
fn mul(self, rhs: Point) -> Self::Output {
|
||||
Self::Output::new(rhs.x * self as f32, rhs.y * self as f32)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<RXingResultPoint> for f32 {
|
||||
type Output = RXingResultPoint;
|
||||
impl std::ops::Mul<Point> for f32 {
|
||||
type Output = Point;
|
||||
|
||||
fn mul(self, rhs: RXingResultPoint) -> Self::Output {
|
||||
RXingResultPoint {
|
||||
x: rhs.x * self,
|
||||
y: rhs.y * self,
|
||||
}
|
||||
fn mul(self, rhs: Point) -> Self::Output {
|
||||
Self::Output::new(rhs.x * self, rhs.y * self)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<&RXingResultPoint> for f32 {
|
||||
type Output = RXingResultPoint;
|
||||
|
||||
fn mul(self, rhs: &RXingResultPoint) -> Self::Output {
|
||||
RXingResultPoint {
|
||||
x: rhs.x * self,
|
||||
y: rhs.y * self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<&mut RXingResultPoint> for f32 {
|
||||
type Output = RXingResultPoint;
|
||||
|
||||
fn mul(self, rhs: &mut RXingResultPoint) -> Self::Output {
|
||||
RXingResultPoint {
|
||||
x: rhs.x * self,
|
||||
y: rhs.y * self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Div<f32> for RXingResultPoint {
|
||||
type Output = RXingResultPoint;
|
||||
impl std::ops::Div<f32> for Point {
|
||||
type Output = Point;
|
||||
|
||||
fn div(self, rhs: f32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x / rhs,
|
||||
y: self.y / rhs,
|
||||
}
|
||||
Self::Output::new(self.x / rhs, self.y / rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl RXingResultPoint {
|
||||
pub fn dot(a: RXingResultPoint, b: RXingResultPoint) -> f32 {
|
||||
a.x * b.x + a.y * b.y
|
||||
impl Point {
|
||||
pub fn dot(self, p: Self) -> f32 {
|
||||
self.x * p.x + self.y * p.y
|
||||
}
|
||||
|
||||
pub fn cross(a: &RXingResultPoint, b: &RXingResultPoint) -> f32 {
|
||||
a.x * b.y - b.x * a.y
|
||||
pub fn cross(self, p: Self) -> f32 {
|
||||
self.x * p.y - p.x * self.y
|
||||
}
|
||||
|
||||
/// L1 norm
|
||||
pub fn sumAbsComponent(p: &RXingResultPoint) -> f32 {
|
||||
(p.x).abs() + (p.y).abs()
|
||||
pub fn sumAbsComponent(self) -> f32 {
|
||||
self.x.abs() + self.y.abs()
|
||||
}
|
||||
|
||||
/// L2 norm
|
||||
pub fn length(p: RXingResultPoint) -> f32 {
|
||||
(Self::dot(p, p)).sqrt()
|
||||
pub fn length(self) -> f32 {
|
||||
self.x.hypot(self.y)
|
||||
}
|
||||
|
||||
/// L-inf norm
|
||||
pub fn maxAbsComponent(p: &RXingResultPoint) -> f32 {
|
||||
let a = (p.x).abs();
|
||||
let b = (p.y).abs();
|
||||
|
||||
if a > b {
|
||||
a
|
||||
} else {
|
||||
b
|
||||
}
|
||||
|
||||
// return std::cmp::max((p.x).abs(), (p.y).abs());
|
||||
pub fn maxAbsComponent(self) -> f32 {
|
||||
f32::max(self.x.abs(), self.y.abs())
|
||||
}
|
||||
|
||||
pub fn distance(a: RXingResultPoint, b: RXingResultPoint) -> f32 {
|
||||
Self::length(a - b)
|
||||
pub fn squaredDistance(self, p: Self) -> f32 {
|
||||
let diff = self - p;
|
||||
diff.x * diff.x + diff.y * diff.y
|
||||
}
|
||||
|
||||
pub fn distance(self, p: Self) -> f32 {
|
||||
(self - p).length()
|
||||
}
|
||||
|
||||
pub fn abs(self) -> Self {
|
||||
Self::new(self.x.abs(), self.y.abs())
|
||||
}
|
||||
|
||||
pub fn fold<U, F: Fn(f32, f32) -> U>(self, f: F) -> U {
|
||||
f(self.x, self.y)
|
||||
}
|
||||
|
||||
/// Calculate a floating point pixel coordinate representing the 'center' of the pixel.
|
||||
/// This is sort of the inverse operation of the PointI(PointF) conversion constructor.
|
||||
/// See also the documentation of the GridSampler API.
|
||||
#[inline(always)]
|
||||
pub fn centered(p: &RXingResultPoint) -> RXingResultPoint {
|
||||
RXingResultPoint {
|
||||
x: (p.x).floor() + 0.5,
|
||||
y: (p.y).floor() + 0.5,
|
||||
}
|
||||
pub fn centered(self) -> Self {
|
||||
Self::new(self.x.floor() + 0.5, self.y.floor() + 0.5)
|
||||
}
|
||||
|
||||
pub fn normalized(d: RXingResultPoint) -> RXingResultPoint {
|
||||
d / Self::length(d)
|
||||
pub fn middle(self, p: Self) -> Self {
|
||||
(self + p) / 2.0
|
||||
}
|
||||
|
||||
pub fn bresenhamDirection(d: &RXingResultPoint) -> RXingResultPoint {
|
||||
*d / Self::maxAbsComponent(d)
|
||||
pub fn normalized(self) -> Self {
|
||||
self / Self::length(self)
|
||||
}
|
||||
|
||||
pub fn mainDirection(d: RXingResultPoint) -> RXingResultPoint {
|
||||
if (d.x).abs() > (d.y).abs() {
|
||||
Self::new(d.x, 0.0)
|
||||
pub fn bresenhamDirection(self) -> Self {
|
||||
self / Self::maxAbsComponent(self)
|
||||
}
|
||||
|
||||
pub fn mainDirection(self) -> Self {
|
||||
if self.x.abs() > self.y.abs() {
|
||||
Self::new(self.x, 0.0)
|
||||
} else {
|
||||
Self::new(0.0, d.y)
|
||||
Self::new(0.0, self.y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&(f32, f32)> for Point {
|
||||
fn from(&(x, y): &(f32, f32)) -> Self {
|
||||
Self::new(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, f32)> for Point {
|
||||
fn from((x, y): (f32, f32)) -> Self {
|
||||
Self::new(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Point;
|
||||
|
||||
#[test]
|
||||
fn testDistance() {
|
||||
assert_eq!(
|
||||
(8.0f32).sqrt(),
|
||||
Point::new(1.0, 2.0).distance(Point::new(3.0, 4.0))
|
||||
);
|
||||
assert_eq!(0.0, Point::new(1.0, 2.0).distance(Point::new(1.0, 2.0)));
|
||||
|
||||
assert_eq!(
|
||||
(8.0f32).sqrt(),
|
||||
Point::new(1.0, 2.0).distance(Point::new(3.0, 4.0))
|
||||
);
|
||||
assert_eq!(0.0, Point::new(1.0, 2.0).distance(Point::new(1.0, 2.0)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user