mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
port: QRCode: restructure Format and Version code after rRMQ addition
f27106c78c
This commit is contained in:
@@ -102,23 +102,23 @@ impl FormatInformation {
|
|||||||
*/
|
*/
|
||||||
pub fn DecodeRMQR(formatInfoBits1: u32, formatInfoBits2: u32) -> Self {
|
pub fn DecodeRMQR(formatInfoBits1: u32, formatInfoBits2: u32) -> Self {
|
||||||
//FormatInformation fi;
|
//FormatInformation fi;
|
||||||
let mirror18Bits = |bits: u32| bits.reverse_bits() >> 14;
|
|
||||||
let mut fi = if formatInfoBits2 != 0 {
|
let mut fi = if formatInfoBits2 != 0 {
|
||||||
Self::FindBestFormatInfoRMQR(
|
Self::FindBestFormatInfoRMQR(
|
||||||
&[formatInfoBits1, mirror18Bits(formatInfoBits1)],
|
&[formatInfoBits1],
|
||||||
&[formatInfoBits2, mirror18Bits(formatInfoBits2)],
|
&[formatInfoBits2],
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// TODO probably remove if `sampleRMQR()` done properly
|
// TODO probably remove if `sampleRMQR()` done properly
|
||||||
Self::FindBestFormatInfoRMQR(&[formatInfoBits1, mirror18Bits(formatInfoBits1)], &[])
|
Self::FindBestFormatInfoRMQR(&[formatInfoBits1], &[])
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bit 6 is error correction (M/H), and bits 0-5 version.
|
// Bit 6 is error correction (M/H), and bits 0-5 version.
|
||||||
fi.error_correction_level =
|
fi.error_correction_level =
|
||||||
ErrorCorrectionLevel::ECLevelFromBits(((fi.data >> 5) as u8 & 1) << 1, false); // Shift to match QRCode M/H
|
ErrorCorrectionLevel::ECLevelFromBits(((fi.data >> 5) as u8 & 1) << 1, false); // Shift to match QRCode M/H
|
||||||
fi.data_mask = 4; // ((y / 2) + (x / 3)) % 2 == 0
|
fi.data_mask = 4; // ((y / 2) + (x / 3)) % 2 == 0
|
||||||
fi.rMQRVersion = fi.data as u8 & 0x1F;
|
fi.microVersion = (fi.data & 0x1F) + 1;
|
||||||
fi.isMirrored = fi.bitsIndex > 1;
|
fi.isMirrored = false; // TODO: implement mirrored format bit reading
|
||||||
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use crate::qrcode::decoder::{
|
|||||||
};
|
};
|
||||||
use crate::{point, Exceptions, PointI};
|
use crate::{point, Exceptions, PointI};
|
||||||
|
|
||||||
const dimsVersionRMQR: [PointI; 32] = [
|
const RMQR_SIZES: [PointI; 32] = [
|
||||||
point(43, 7),
|
point(43, 7),
|
||||||
point(59, 7),
|
point(59, 7),
|
||||||
point(77, 7),
|
point(77, 7),
|
||||||
@@ -144,59 +144,96 @@ impl Version {
|
|||||||
Type::const_eq(self.qr_type, Type::RectMicro)
|
Type::const_eq(self.qr_type, Type::RectMicro)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn HasMicroSize(bitMatrix: &BitMatrix) -> bool {
|
pub fn SymbolSize(version: u32, qr_type: Type) -> PointI {
|
||||||
let size = bitMatrix.height();
|
let version = version as i32;
|
||||||
size == bitMatrix.width() && (11..=17).contains(&size) && (size % 2) == 1
|
|
||||||
|
let square = |s: i32| point(s, s);
|
||||||
|
let valid = |v: i32, max: i32| v >= 1 && v <= max;
|
||||||
|
|
||||||
|
match (qr_type) {
|
||||||
|
Type::Model1 => {
|
||||||
|
if valid(version, 32) {
|
||||||
|
square(17 + 4 * version)
|
||||||
|
} else {
|
||||||
|
PointI::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type::Model2 => {
|
||||||
|
if valid(version, 40) {
|
||||||
|
square(17 + 4 * version)
|
||||||
|
} else {
|
||||||
|
PointI::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type::Micro => {
|
||||||
|
if valid(version, 4) {
|
||||||
|
square(9 + 2 * version)
|
||||||
|
} else {
|
||||||
|
PointI::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type::RectMicro => {
|
||||||
|
if valid(version, 32) {
|
||||||
|
RMQR_SIZES[(version - 1) as usize]
|
||||||
|
} else {
|
||||||
|
PointI::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn HasRMQRSize(bitMatrix: &BitMatrix) -> bool {
|
pub fn IsValidSize(size: PointI, qr_type: Type) -> bool {
|
||||||
Self::getVersionRMQR(bitMatrix) != -1
|
match (qr_type) {
|
||||||
|
Type::Model1 => size.x == size.y && size.x >= 21 && size.x <= 145 && (size.x % 4 == 1),
|
||||||
|
Type::Model2 => size.x == size.y && size.x >= 21 && size.x <= 177 && (size.x % 4 == 1),
|
||||||
|
Type::Micro => size.x == size.y && size.x >= 11 && size.x <= 17 && (size.x % 2 == 1),
|
||||||
|
Type::RectMicro => {
|
||||||
|
size.x != size.y
|
||||||
|
&& size.x.is_odd()
|
||||||
|
&& size.y.is_odd()
|
||||||
|
&& size.x >= 27
|
||||||
|
&& size.x <= 139
|
||||||
|
&& size.y >= 7
|
||||||
|
&& size.y <= 17
|
||||||
|
&& Self::IndexOf(&RMQR_SIZES, size) != -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn HasValidSizeType(bitMatrix: &BitMatrix, qr_type: Type) -> bool {
|
||||||
|
return Self::IsValidSize(
|
||||||
|
point(bitMatrix.width() as i32, bitMatrix.height() as i32),
|
||||||
|
qr_type,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn HasValidSize(bitMatrix: &BitMatrix) -> bool {
|
pub fn HasValidSize(matrix: &BitMatrix) -> bool {
|
||||||
let size = bitMatrix.height();
|
return Self::HasValidSizeType(matrix, Type::Model1)
|
||||||
if bitMatrix.width() != size {
|
|| Self::HasValidSizeType(matrix, Type::Model2)
|
||||||
Self::HasRMQRSize(bitMatrix)
|
|| Self::HasValidSizeType(matrix, Type::Micro)
|
||||||
|
|| Self::HasValidSizeType(matrix, Type::RectMicro);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn IndexOf(points: &[PointI], search: PointI) -> i32 {
|
||||||
|
RMQR_SIZES
|
||||||
|
.iter()
|
||||||
|
.position(|p| *p == search)
|
||||||
|
.and_then(|x| Some(x as i32))
|
||||||
|
.unwrap_or(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn NumberPoint(size: PointI) -> u32 {
|
||||||
|
if (size.x != size.y) {
|
||||||
|
return (Self::IndexOf(&RMQR_SIZES, size) + 1) as u32;
|
||||||
|
} else if (Self::IsValidSize(size, Type::Model2)) {
|
||||||
|
return ((size.x as i32 - 17) / 4) as u32;
|
||||||
|
} else if (Self::IsValidSize(size, Type::Micro)) {
|
||||||
|
return ((size.x as i32 - 9) / 2) as u32;
|
||||||
} else {
|
} else {
|
||||||
Self::HasMicroSize(bitMatrix) || ((21..=177).contains(&size) && (size % 4) == 1)
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Number(bitMatrix: &BitMatrix) -> u32 {
|
pub fn Number(bitMatrix: &BitMatrix) -> u32 {
|
||||||
if bitMatrix.width() != bitMatrix.height() {
|
return Self::NumberPoint(point(bitMatrix.width() as i32, bitMatrix.height() as i32));
|
||||||
Self::getVersionRMQR(bitMatrix) as u32 + 1
|
|
||||||
} else if !Self::HasValidSize(bitMatrix) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
let isMicro = Self::HasMicroSize(bitMatrix);
|
|
||||||
(bitMatrix.height() - Self::DimensionOffset(isMicro)) / Self::DimensionStep(isMicro)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn DimensionOfVersionRMQR(version_number: u32) -> PointI {
|
|
||||||
if version_number < 1 || version_number as usize > dimsVersionRMQR.len() {
|
|
||||||
point(0, 0)
|
|
||||||
} else {
|
|
||||||
dimsVersionRMQR[version_number as usize - 1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getVersionRMQR(bitMatrix: &BitMatrix) -> i32 {
|
|
||||||
let width = bitMatrix.width() as i32;
|
|
||||||
let height = bitMatrix.height() as i32;
|
|
||||||
if width != height
|
|
||||||
&& width.is_odd()
|
|
||||||
&& height.is_odd()
|
|
||||||
&& (27..=139).contains(&width)
|
|
||||||
&& (7..=17).contains(&height)
|
|
||||||
{
|
|
||||||
for i in 0..dimsVersionRMQR.len() {
|
|
||||||
// for (int i = 0; i < Size(dimsVersionRMQR); i++){
|
|
||||||
if width == dimsVersionRMQR[i].x && height == dimsVersionRMQR[i].y {
|
|
||||||
return i as i32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ pub fn ReadVersion(bitMatrix: &BitMatrix, qr_type: Type) -> Result<VersionRef> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn ReadFormatInformation(bitMatrix: &BitMatrix) -> Result<FormatInformation> {
|
pub fn ReadFormatInformation(bitMatrix: &BitMatrix) -> Result<FormatInformation> {
|
||||||
if Version::HasMicroSize(bitMatrix) {
|
if Version::HasValidSizeType(bitMatrix, Type::Micro) {
|
||||||
// Read top-left format info bits
|
// Read top-left format info bits
|
||||||
let mut formatInfoBits = 0;
|
let mut formatInfoBits = 0;
|
||||||
for x in 1..9 {
|
for x in 1..9 {
|
||||||
@@ -52,7 +52,7 @@ pub fn ReadFormatInformation(bitMatrix: &BitMatrix) -> Result<FormatInformation>
|
|||||||
return Ok(FormatInformation::DecodeMQR(formatInfoBits as u32));
|
return Ok(FormatInformation::DecodeMQR(formatInfoBits as u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
if Version::HasRMQRSize(bitMatrix) {
|
if Version::HasValidSizeType(bitMatrix, Type::RectMicro) {
|
||||||
// Read top-left format info bits
|
// Read top-left format info bits
|
||||||
let mut formatInfoBits1 = 0;
|
let mut formatInfoBits1 = 0;
|
||||||
for y in (1..=3).rev() {
|
for y in (1..=3).rev() {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use crate::{
|
|||||||
decoder::{FormatInformation, Version, VersionRef},
|
decoder::{FormatInformation, Version, VersionRef},
|
||||||
detector::QRCodeDetectorResult,
|
detector::QRCodeDetectorResult,
|
||||||
},
|
},
|
||||||
Exceptions,
|
Exceptions, point,
|
||||||
};
|
};
|
||||||
use multimap::MultiMap;
|
use multimap::MultiMap;
|
||||||
use num::Integer;
|
use num::Integer;
|
||||||
@@ -27,6 +27,8 @@ use crate::{
|
|||||||
point_f, Point,
|
point_f, Point,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::Type;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
|
||||||
pub struct FinderPatternSet {
|
pub struct FinderPatternSet {
|
||||||
pub bl: ConcentricPattern,
|
pub bl: ConcentricPattern,
|
||||||
@@ -40,8 +42,6 @@ pub type FinderPatternSets = Vec<FinderPatternSet>;
|
|||||||
const LEN: usize = 5;
|
const LEN: usize = 5;
|
||||||
const SUM: usize = 7;
|
const SUM: usize = 7;
|
||||||
const PATTERN: FixedPattern<LEN, SUM, false> = FixedPattern::new([1, 1, 3, 1, 1]);
|
const PATTERN: FixedPattern<LEN, SUM, false> = FixedPattern::new([1, 1, 3, 1, 1]);
|
||||||
const SUBPATTERN_RMQR: FixedPattern<5, 5, false> = FixedPattern::new([1, 1, 1, 1, 1]);
|
|
||||||
const CORNER_EDGE_RMQR: FixedPattern<2, 4, false> = FixedPattern::new([3, 1]);
|
|
||||||
const E2E: bool = true;
|
const E2E: bool = true;
|
||||||
|
|
||||||
fn FindPattern(view: PatternView<'_>) -> Result<PatternView<'_>> {
|
fn FindPattern(view: PatternView<'_>) -> Result<PatternView<'_>> {
|
||||||
@@ -570,7 +570,7 @@ pub fn SampleQR(image: &BitMatrix, fp: &FinderPatternSet) -> Result<QRCodeDetect
|
|||||||
Quadrilateral::from([fp.tl.p, fp.tr.p, br.p, fp.bl.p]),
|
Quadrilateral::from([fp.tl.p, fp.tr.p, br.p, fp.bl.p]),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if dimension >= Version::DimensionOfVersion(7, false) as i32 {
|
if dimension >= Version::SymbolSize(7, Type::Model2).x as i32 {
|
||||||
let version = ReadVersion(image, dimension as u32, mod2Pix);
|
let version = ReadVersion(image, dimension as u32, mod2Pix);
|
||||||
|
|
||||||
// if the version bits are garbage -> discard the detection
|
// if the version bits are garbage -> discard the detection
|
||||||
@@ -799,10 +799,9 @@ pub fn DetectPureQR(image: &BitMatrix) -> Result<QRCodeDetectorResult> {
|
|||||||
// SaveAsPBM(image, "weg.pbm");
|
// SaveAsPBM(image, "weg.pbm");
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
let MIN_MODULES: u32 = Version::DimensionOfVersion(1, false);
|
let MIN_MODULES : i32 = Version::SymbolSize(1, Type::Model2).x;
|
||||||
let MAX_MODULES: u32 = Version::DimensionOfVersion(40, false);
|
|
||||||
|
|
||||||
let (found, left, top, width, height) = image.findBoundingBox(0, 0, 0, 0, MIN_MODULES);
|
let (found, left, top, width, height) = image.findBoundingBox(0, 0, 0, 0, MIN_MODULES as u32);
|
||||||
|
|
||||||
if !found || (width as i32 - height as i32).abs() > 1 {
|
if !found || (width as i32 - height as i32).abs() > 1 {
|
||||||
return Err(Exceptions::NOT_FOUND);
|
return Err(Exceptions::NOT_FOUND);
|
||||||
@@ -846,8 +845,7 @@ pub fn DetectPureQR(image: &BitMatrix) -> Result<QRCodeDetectorResult> {
|
|||||||
.dim;
|
.dim;
|
||||||
|
|
||||||
let moduleSize: f32 = ((width) as f32) / dimension as f32;
|
let moduleSize: f32 = ((width) as f32) / dimension as f32;
|
||||||
if dimension < MIN_MODULES as i32
|
if !Version::IsValidSize(point(dimension, dimension), Type::Model2)
|
||||||
|| dimension > MAX_MODULES as i32
|
|
||||||
|| !image.is_in(point_f(
|
|| !image.is_in(point_f(
|
||||||
left as f32 + moduleSize / 2.0 + (dimension - 1) as f32 * moduleSize,
|
left as f32 + moduleSize / 2.0 + (dimension - 1) as f32 * moduleSize,
|
||||||
top as f32 + moduleSize / 2.0 + (dimension - 1) as f32 * moduleSize,
|
top as f32 + moduleSize / 2.0 + (dimension - 1) as f32 * moduleSize,
|
||||||
@@ -888,10 +886,9 @@ pub fn DetectPureQR(image: &BitMatrix) -> Result<QRCodeDetectorResult> {
|
|||||||
pub fn DetectPureMQR(image: &BitMatrix) -> Result<QRCodeDetectorResult> {
|
pub fn DetectPureMQR(image: &BitMatrix) -> Result<QRCodeDetectorResult> {
|
||||||
type Pattern = [PatternType; 5];
|
type Pattern = [PatternType; 5];
|
||||||
|
|
||||||
const MIN_MODULES: u32 = Version::DimensionOfVersion(1, true);
|
let MIN_MODULES : i32= Version::SymbolSize(1, Type::Micro).x;
|
||||||
const MAX_MODULES: u32 = Version::DimensionOfVersion(4, true);
|
|
||||||
|
|
||||||
let (found, left, top, width, height) = image.findBoundingBox(0, 0, 0, 0, MIN_MODULES);
|
let (found, left, top, width, height) = image.findBoundingBox(0, 0, 0, 0, MIN_MODULES as u32);
|
||||||
|
|
||||||
// int left, top, width, height;
|
// int left, top, width, height;
|
||||||
if !found || (width as i32 - height as i32).abs() > 1 {
|
if !found || (width as i32 - height as i32).abs() > 1 {
|
||||||
@@ -914,7 +911,7 @@ pub fn DetectPureMQR(image: &BitMatrix) -> Result<QRCodeDetectorResult> {
|
|||||||
let moduleSize: f32 = (fpWidth as f32) / 7.0;
|
let moduleSize: f32 = (fpWidth as f32) / 7.0;
|
||||||
let dimension = (width as f32 / moduleSize).floor() as u32;
|
let dimension = (width as f32 / moduleSize).floor() as u32;
|
||||||
|
|
||||||
if !(MIN_MODULES..=MAX_MODULES).contains(&dimension)
|
if !Version::IsValidSize(point(dimension as i32, dimension as i32), Type::Micro)
|
||||||
|| !image.is_in(point_f(
|
|| !image.is_in(point_f(
|
||||||
left as f32 + moduleSize / 2.0 + (dimension - 1) as f32 * moduleSize,
|
left as f32 + moduleSize / 2.0 + (dimension - 1) as f32 * moduleSize,
|
||||||
top as f32 + moduleSize / 2.0 + (dimension - 1) as f32 * moduleSize,
|
top as f32 + moduleSize / 2.0 + (dimension - 1) as f32 * moduleSize,
|
||||||
@@ -952,23 +949,25 @@ pub fn DetectPureMQR(image: &BitMatrix) -> Result<QRCodeDetectorResult> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn DetectPureRMQR(image: &BitMatrix) -> Result<QRCodeDetectorResult> {
|
pub fn DetectPureRMQR(image: &BitMatrix) -> Result<QRCodeDetectorResult> {
|
||||||
|
const SUBPATTERN : FixedPattern<4,4> = FixedPattern::new([1, 1, 1, 1]);
|
||||||
|
const TIMINGPATTERN : FixedPattern<10,10>= FixedPattern::new([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
|
||||||
|
|
||||||
type Pattern = [PatternType; 5]; //std::array<PatternView::value_type, PATTERN.size()>;
|
type Pattern = [PatternType; 5]; //std::array<PatternView::value_type, PATTERN.size()>;
|
||||||
type SubPattern = [PatternType; 5]; //std::array<PatternView::value_type, SUBPATTERN_RMQR.size()>;
|
// type SubPattern = [PatternType; 5]; //std::array<PatternView::value_type, SUBPATTERN_RMQR.size()>;
|
||||||
type CornerEdgePattern = [PatternType; 2]; //std::array<PatternView::value_type, CORNER_EDGE_RMQR.size()>;
|
// type CornerEdgePattern = [PatternType; 2]; //std::array<PatternView::value_type, CORNER_EDGE_RMQR.size()>;
|
||||||
|
|
||||||
|
type SubPattern = [PatternType;4];
|
||||||
|
type TimingPattern = [PatternType;10];
|
||||||
|
|
||||||
// #ifdef PRINT_DEBUG
|
// #ifdef PRINT_DEBUG
|
||||||
// SaveAsPBM(image, "weg.pbm");
|
// SaveAsPBM(image, "weg.pbm");
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
const MIN_MODULES: u32 = 7;
|
let MIN_MODULES : i32 = Version::SymbolSize(1, Type::RectMicro).y;
|
||||||
const MIN_MODULES_W: u32 = 27;
|
|
||||||
const MIN_MODULES_H: u32 = 7;
|
|
||||||
const MAX_MODULES_W: u32 = 139;
|
|
||||||
const MAX_MODULES_H: u32 = 17;
|
|
||||||
|
|
||||||
let (found, left, top, width, height) = image.findBoundingBox(0, 0, 0, 0, MIN_MODULES);
|
let (found, left, top, width, height) = image.findBoundingBox(0, 0, 0, 0, MIN_MODULES as u32);
|
||||||
|
|
||||||
if !found {
|
if !found || height >= width{
|
||||||
return Err(Exceptions::NOT_FOUND);
|
return Err(Exceptions::NOT_FOUND);
|
||||||
}
|
}
|
||||||
let right = left + width - 1;
|
let right = left + width - 1;
|
||||||
@@ -989,76 +988,37 @@ pub fn DetectPureRMQR(image: &BitMatrix) -> Result<QRCodeDetectorResult> {
|
|||||||
return Err(Exceptions::NOT_FOUND);
|
return Err(Exceptions::NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finder sub pattern
|
|
||||||
let mut subdiagonal: SubPattern = EdgeTracer::new(image, br, point_i(-1, -1))
|
|
||||||
.readPatternFromBlack(1, None)
|
|
||||||
.ok_or(Exceptions::ILLEGAL_STATE)?;
|
|
||||||
if subdiagonal.len() == 5 && subdiagonal[4] > subdiagonal[3] {
|
|
||||||
// Sub pattern has no separator so can run off along the diagonal
|
|
||||||
subdiagonal[4] = subdiagonal[3]; // Hack it back to previous
|
|
||||||
}
|
|
||||||
let subdiagonal_hld = subdiagonal.to_vec().into();
|
|
||||||
let view = PatternView::new(&subdiagonal_hld);
|
|
||||||
if !(IsPattern::<E2E, 5, 5, false>(&view, &SUBPATTERN_RMQR, None, 0.0, 0.0) != 0.0) {
|
|
||||||
return Err(Exceptions::NOT_FOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Horizontal corner finder patterns (for vertical ones see below)
|
|
||||||
for (p, d) in [(tr, point_i(-1, 0)), (bl, point_i(1, 0))] {
|
|
||||||
// for (auto [p, d] : {std::pair(tr, PointI{-1, 0}), {bl, {1, 0}}}) {
|
|
||||||
let corner: CornerEdgePattern = EdgeTracer::new(image, p, d)
|
|
||||||
.readPatternFromBlack(1, None)
|
|
||||||
.ok_or(Exceptions::ILLEGAL_STATE)?;
|
|
||||||
let corner_hld = corner.to_vec().into();
|
|
||||||
let view = PatternView::new(&corner_hld);
|
|
||||||
if !(IsPattern::<E2E, 2, 4, false>(&view, &CORNER_EDGE_RMQR, None, 0.0, 0.0) != 0.0) {
|
|
||||||
{
|
|
||||||
return Err(Exceptions::NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let fpWidth = (diagonal).into_iter().sum::<u16>();
|
let fpWidth = (diagonal).into_iter().sum::<u16>();
|
||||||
let moduleSize = (fpWidth as f32) / 7.0;
|
let moduleSize = (fpWidth as f32) / 7.0;
|
||||||
let dimW = (width as f32 / moduleSize as f32).floor() as u32;
|
let dimW = (width as f32 / moduleSize as f32).floor() as u32;
|
||||||
let dimH = (height as f32 / moduleSize as f32).floor() as u32;
|
let dimH = (height as f32 / moduleSize as f32).floor() as u32;
|
||||||
|
|
||||||
if dimW == dimH
|
if (!Version::IsValidSize(point(dimW as i32, dimH as i32), Type::RectMicro))
|
||||||
|| dimW.is_even()
|
{return Err(Exceptions::NOT_FOUND);}
|
||||||
|| dimH.is_even()
|
|
||||||
|| !(MIN_MODULES_W..=MAX_MODULES_W).contains(&dimW)
|
// Finder sub pattern
|
||||||
|| !(MIN_MODULES_H..=MAX_MODULES_H).contains(&dimH)
|
let subdiagonal : SubPattern = EdgeTracer::new(image, br, point_i(-1, -1)).readPatternFromBlack(1,None).ok_or(Exceptions::ILLEGAL_STATE)?;
|
||||||
|| !image.is_in(point_f(
|
let subdiagonal_hld = diagonal.to_vec().into();
|
||||||
left as f32 + moduleSize / 2.0 + (dimW as f32 - 1.0) * moduleSize,
|
let view = PatternView::new(&subdiagonal_hld);
|
||||||
top as f32 + moduleSize / 2.0 + (dimH as f32 - 1.0) * moduleSize,
|
if IsPattern::<E2E, 4, 4, false>(&view, &SUBPATTERN, None, 0.0, 0.0) != 0.0
|
||||||
))
|
{return Err(Exceptions::NOT_FOUND);}
|
||||||
{
|
|
||||||
return Err(Exceptions::NOT_FOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vertical corner finder patterns
|
// Vertical corner finder patterns
|
||||||
if dimH > 7 {
|
// Horizontal timing patterns
|
||||||
// None for R7
|
for (p, d) in [(tr, point(-1, 0)), (bl, point(1, 0)), (tl, point(1, 0)), (br, point(-1, 0))] {
|
||||||
let corner: CornerEdgePattern = EdgeTracer::new(image, tr, point_i(0, 1))
|
let mut cur = EdgeTracer::new(image, p, d.into());
|
||||||
.readPatternFromBlack(1, None)
|
// skip corner / finder / sub pattern edge
|
||||||
.ok_or(Exceptions::ILLEGAL_STATE)?;
|
cur.stepToEdge(Some(2 + i32::from(cur.isWhite())), None, None);
|
||||||
let corner_hld = corner.to_vec().into();
|
let timing : TimingPattern = cur.readPattern(None).ok_or(Exceptions::ILLEGAL_STATE)?;
|
||||||
let view = PatternView::new(&corner_hld);
|
let timing_hld = diagonal.to_vec().into();
|
||||||
if !(IsPattern::<E2E, 2, 4, false>(&view, &CORNER_EDGE_RMQR, None, 0.0, 0.0) != 0.0) {
|
let view = PatternView::new(&timing_hld);
|
||||||
return Err(Exceptions::NOT_FOUND);
|
if !(IsPattern::<E2E, 10,10, false>(&view, &TIMINGPATTERN, None, 0.0, 0.0) != 0.0)
|
||||||
|
{return Err(Exceptions::NOT_FOUND);}
|
||||||
}
|
}
|
||||||
if dimH > 9 {
|
|
||||||
// No bottom left for R9
|
|
||||||
let corner: CornerEdgePattern = EdgeTracer::new(image, bl, point_i(0, -1))
|
|
||||||
.readPatternFromBlack(1, None)
|
|
||||||
.ok_or(Exceptions::ILLEGAL_STATE)?;
|
|
||||||
let corner_hld = corner.to_vec().into();
|
|
||||||
let view = PatternView::new(&corner_hld);
|
|
||||||
if !(IsPattern::<E2E, 2, 4, false>(&view, &CORNER_EDGE_RMQR, None, 0.0, 0.0) != 0.0) {
|
|
||||||
return Err(Exceptions::NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// #ifdef PRINT_DEBUG
|
// #ifdef PRINT_DEBUG
|
||||||
// LogMatrix log;
|
// LogMatrix log;
|
||||||
@@ -1159,7 +1119,7 @@ pub fn SampleMQR(image: &BitMatrix, fp: ConcentricPattern) -> Result<QRCodeDetec
|
|||||||
return Err(Exceptions::NOT_FOUND);
|
return Err(Exceptions::NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dim: u32 = Version::DimensionOfVersion(bestFI.microVersion, true);
|
let dim: u32 = Version::SymbolSize(bestFI.microVersion, Type::Micro).x as u32;
|
||||||
|
|
||||||
// check that we are in fact not looking at a corner of a non-micro QRCode symbol
|
// check that we are in fact not looking at a corner of a non-micro QRCode symbol
|
||||||
// we accept at most 1/3rd black pixels in the quite zone (in a QRCode symbol we expect about 1/2).
|
// we accept at most 1/3rd black pixels in the quite zone (in a QRCode symbol we expect about 1/2).
|
||||||
@@ -1202,24 +1162,10 @@ pub fn SampleRMQR(image: &BitMatrix, fp: ConcentricPattern) -> Result<QRCodeDete
|
|||||||
let FORMAT_INFO_EDGE_COORDS: [Point; 4] =
|
let FORMAT_INFO_EDGE_COORDS: [Point; 4] =
|
||||||
[point_i(8, 0), point_i(9, 0), point_i(10, 0), point_i(11, 0)];
|
[point_i(8, 0), point_i(9, 0), point_i(10, 0), point_i(11, 0)];
|
||||||
let FORMAT_INFO_COORDS: [Point; 18] = [
|
let FORMAT_INFO_COORDS: [Point; 18] = [
|
||||||
point_i(8, 1),
|
point_i(11, 3), point_i(11, 2), point_i(11, 1),
|
||||||
point_i(8, 2),
|
point_i(10, 5), point_i(10, 4), point_i(10, 3), point_i(10, 2), point_i(10, 1),
|
||||||
point_i(8, 3),
|
point_i( 9, 5), point_i( 9, 4), point_i( 9, 3), point_i( 9, 2), point_i( 9, 1),
|
||||||
point_i(8, 4),
|
point_i( 8, 5), point_i( 8, 4), point_i( 8, 3), point_i( 8, 2), point_i( 8, 1),
|
||||||
point_i(8, 5),
|
|
||||||
point_i(9, 1),
|
|
||||||
point_i(9, 2),
|
|
||||||
point_i(9, 3),
|
|
||||||
point_i(9, 4),
|
|
||||||
point_i(9, 5),
|
|
||||||
point_i(10, 1),
|
|
||||||
point_i(10, 2),
|
|
||||||
point_i(10, 3),
|
|
||||||
point_i(10, 4),
|
|
||||||
point_i(10, 5),
|
|
||||||
point_i(11, 1),
|
|
||||||
point_i(11, 2),
|
|
||||||
point_i(11, 3),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut bestFI: FormatInformation = FormatInformation::default();
|
let mut bestFI: FormatInformation = FormatInformation::default();
|
||||||
@@ -1262,7 +1208,7 @@ pub fn SampleRMQR(image: &BitMatrix, fp: ConcentricPattern) -> Result<QRCodeDete
|
|||||||
return Err(Exceptions::NOT_FOUND);
|
return Err(Exceptions::NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dim = Version::DimensionOfVersionRMQR(bestFI.rMQRVersion as u32 + 1);
|
let dim = Version::SymbolSize(bestFI.microVersion, Type::RectMicro);
|
||||||
|
|
||||||
let grid_sampler = DefaultGridSampler;
|
let grid_sampler = DefaultGridSampler;
|
||||||
let (sample, rps) = grid_sampler.sample_grid(
|
let (sample, rps) = grid_sampler.sample_grid(
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::BitMatrix,
|
common::BitMatrix,
|
||||||
qrcode::decoder::{Version, VersionRef},
|
qrcode::{decoder::{Version, VersionRef}, cpp_port::Type},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn CheckVersion(version: VersionRef, number: u32, dimension: u32) {
|
fn CheckVersion(version: VersionRef, number: u32, dimension: u32) {
|
||||||
@@ -129,7 +129,7 @@ fn FunctionPattern() {
|
|||||||
fn CheckRMQRVersion(version: VersionRef, number: u32) {
|
fn CheckRMQRVersion(version: VersionRef, number: u32) {
|
||||||
assert_eq!(number, version.getVersionNumber());
|
assert_eq!(number, version.getVersionNumber());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Version::DimensionOfVersionRMQR(number).x == 27,
|
Version::SymbolSize(number, Type::RectMicro).x == 27,
|
||||||
version.getAlignmentPatternCenters().is_empty()
|
version.getAlignmentPatternCenters().is_empty()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ pub struct FormatInformation {
|
|||||||
pub mask: u32, // = 0
|
pub mask: u32, // = 0
|
||||||
pub data: u32, // = 255
|
pub data: u32, // = 255
|
||||||
pub bitsIndex: u8, // = 255;
|
pub bitsIndex: u8, // = 255;
|
||||||
pub rMQRVersion: u8, //= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FormatInformation {
|
impl Default for FormatInformation {
|
||||||
@@ -92,7 +91,6 @@ impl Default for FormatInformation {
|
|||||||
mask: 0,
|
mask: 0,
|
||||||
data: 255,
|
data: 255,
|
||||||
bitsIndex: 255,
|
bitsIndex: 255,
|
||||||
rMQRVersion: 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +110,6 @@ impl FormatInformation {
|
|||||||
mask: 0,
|
mask: 0,
|
||||||
bitsIndex: 255,
|
bitsIndex: 255,
|
||||||
data: 255,
|
data: 255,
|
||||||
rMQRVersion: 0,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -202,14 +202,14 @@ impl Version {
|
|||||||
*/
|
*/
|
||||||
pub fn buildFunctionPattern(&self) -> Result<BitMatrix> {
|
pub fn buildFunctionPattern(&self) -> Result<BitMatrix> {
|
||||||
if self.isRMQR() {
|
if self.isRMQR() {
|
||||||
let dimension = Version::DimensionOfVersionRMQR(self.versionNumber);
|
let size = Version::SymbolSize(self.versionNumber, Type::RectMicro);
|
||||||
let mut bitMatrix = BitMatrix::new(dimension.x as u32, dimension.y as u32)?;
|
let mut bitMatrix = BitMatrix::new(size.x as u32, size.y as u32)?;
|
||||||
|
|
||||||
// Set edge timing patterns
|
// Set edge timing patterns
|
||||||
bitMatrix.setRegion(0, 0, dimension.x as u32, 1)?; // Top
|
bitMatrix.setRegion(0, 0, size.x as u32, 1)?; // Top
|
||||||
bitMatrix.setRegion(0, (dimension.y - 1) as u32, dimension.x as u32, 1)?; // Bottom
|
bitMatrix.setRegion(0, (size.y - 1) as u32, size.x as u32, 1)?; // Bottom
|
||||||
bitMatrix.setRegion(0, 1, 1, (dimension.y - 2) as u32)?; // Left
|
bitMatrix.setRegion(0, 1, 1, (size.y - 2) as u32)?; // Left
|
||||||
bitMatrix.setRegion((dimension.x - 1) as u32, 1, 1, (dimension.y - 2) as u32)?; // Right
|
bitMatrix.setRegion((size.x - 1) as u32, 1, 1, (size.y - 2) as u32)?; // Right
|
||||||
|
|
||||||
// Set vertical timing and alignment patterns
|
// Set vertical timing and alignment patterns
|
||||||
let max = self.alignmentPatternCenters.len(); // Same as vertical timing column
|
let max = self.alignmentPatternCenters.len(); // Same as vertical timing column
|
||||||
@@ -217,32 +217,32 @@ impl Version {
|
|||||||
// for (size_t x = 0; x < max; ++x) {
|
// for (size_t x = 0; x < max; ++x) {
|
||||||
let cx = self.alignmentPatternCenters[x];
|
let cx = self.alignmentPatternCenters[x];
|
||||||
bitMatrix.setRegion(cx - 1, 1, 3, 2)?; // Top alignment pattern
|
bitMatrix.setRegion(cx - 1, 1, 3, 2)?; // Top alignment pattern
|
||||||
bitMatrix.setRegion(cx - 1, (dimension.y - 3) as u32, 3, 2)?; // Bottom alignment pattern
|
bitMatrix.setRegion(cx - 1, (size.y - 3) as u32, 3, 2)?; // Bottom alignment pattern
|
||||||
bitMatrix.setRegion(cx, 3, 1, (dimension.y - 6) as u32)?; // Vertical timing pattern
|
bitMatrix.setRegion(cx, 3, 1, (size.y - 6) as u32)?; // Vertical timing pattern
|
||||||
}
|
}
|
||||||
|
|
||||||
// Top left finder pattern + separator
|
// Top left finder pattern + separator
|
||||||
bitMatrix.setRegion(1, 1, 8 - 1, 8 - 1 - u32::from(dimension.y == 7))?; // R7 finder bottom flush with edge
|
bitMatrix.setRegion(1, 1, 8 - 1, 8 - 1 - u32::from(size.y == 7))?; // R7 finder bottom flush with edge
|
||||||
// Top left format
|
// Top left format
|
||||||
bitMatrix.setRegion(8, 1, 3, 5)?;
|
bitMatrix.setRegion(8, 1, 3, 5)?;
|
||||||
bitMatrix.setRegion(11, 1, 1, 3)?;
|
bitMatrix.setRegion(11, 1, 1, 3)?;
|
||||||
|
|
||||||
// Bottom right finder subpattern
|
// Bottom right finder subpattern
|
||||||
bitMatrix.setRegion(
|
bitMatrix.setRegion(
|
||||||
(dimension.x - 5) as u32,
|
(size.x - 5) as u32,
|
||||||
(dimension.y - 5) as u32,
|
(size.y - 5) as u32,
|
||||||
5 - 1,
|
5 - 1,
|
||||||
5 - 1,
|
5 - 1,
|
||||||
)?;
|
)?;
|
||||||
// Bottom right format
|
// Bottom right format
|
||||||
bitMatrix.setRegion((dimension.x - 8) as u32, (dimension.y - 6) as u32, 3, 5)?;
|
bitMatrix.setRegion((size.x - 8) as u32, (size.y - 6) as u32, 3, 5)?;
|
||||||
bitMatrix.setRegion((dimension.x - 5) as u32, (dimension.y - 6) as u32, 3, 1)?;
|
bitMatrix.setRegion((size.x - 5) as u32, (size.y - 6) as u32, 3, 1)?;
|
||||||
|
|
||||||
// Top right corner finder
|
// Top right corner finder
|
||||||
bitMatrix.set((dimension.x - 2) as u32, 1);
|
bitMatrix.set((size.x - 2) as u32, 1);
|
||||||
if dimension.y > 9 {
|
if size.y > 9 {
|
||||||
// Bottom left corner finder
|
// Bottom left corner finder
|
||||||
bitMatrix.set(1, (dimension.y - 2) as u32);
|
bitMatrix.set(1, (size.y - 2) as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(bitMatrix);
|
return Ok(bitMatrix);
|
||||||
|
|||||||
@@ -90,12 +90,22 @@ impl Hash for Point {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Point {
|
// impl PartialEq for Point {
|
||||||
|
// fn eq(&self, other: &Self) -> bool {
|
||||||
|
// self.x == other.x && self.y == other.y
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl Eq for Point {}
|
||||||
|
|
||||||
|
impl<T> PartialEq for PointT<T>
|
||||||
|
where
|
||||||
|
T: PartialEq,
|
||||||
|
{
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.x == other.x && self.y == other.y
|
self.x == other.x && self.y == other.y
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Eq for Point {}
|
impl<T> Eq for PointT<T> where T: PartialEq {}
|
||||||
|
|
||||||
impl<T> PointT<T>
|
impl<T> PointT<T>
|
||||||
where
|
where
|
||||||
|
|||||||
Reference in New Issue
Block a user