qr_code partially working

This commit is contained in:
Henry Schimke
2022-10-09 22:01:36 -05:00
parent 50a675c693
commit 79aafa200d
26 changed files with 839 additions and 604 deletions

View File

@@ -0,0 +1,62 @@
use std::collections::HashMap;
use crate::{qrcode::{
decoder::decoder, decoder::ErrorCorrectionLevel, detector::Detector, encoder::encoder,
}, common::BitMatrix};
#[test]
fn test_simple() {
test_encode_decode("value");
}
#[test]
fn test_uri() {
test_encode_decode("https://google.com");
}
#[test]
fn test_unicode() {
test_encode_decode("\u{3484}\u{f8a7}\u{a1e7}");
}
fn test_encode_decode(value: &str) {
for ec_level_v in 0..4 {
let ec_level: ErrorCorrectionLevel =
ErrorCorrectionLevel::forBits(ec_level_v).expect("must get level");
let qr_code =
encoder::encode_with_hints(value, ec_level, &HashMap::new()).expect("must encode");
// dbg!(&qr_code.to_string());
let byt_matrix = qr_code.getMatrix().as_ref().unwrap().clone();
// dbg!(BitMatrix::from(byt_matrix.clone()).to_string());
// let mut detector = Detector::new(make_larger(&byt_matrix.into(),5));
let mut detector = Detector::new(byt_matrix.into());
let _detected_points = detector.detect().expect("must detect");
let decoded = decoder::decode_bitmatrix(
&qr_code
.getMatrix()
.clone()
.expect("matrix must exist")
.into(),
)
.expect("must decode");
assert_eq!(decoded.getText(), value);
}
}
// Zooms a bit matrix so that each bit is factor x factor
fn make_larger(input: &BitMatrix, factor: u32) -> BitMatrix {
let width = input.getWidth();
let mut output = BitMatrix::with_single_dimension(width * factor);
for inputY in 0..width {
// for (int inputY = 0; inputY < width; inputY++) {
for inputX in 0..width {
// for (int inputX = 0; inputX < width; inputX++) {
if input.get(inputX, inputY) {
output
.setRegion(inputX * factor, inputY * factor, factor, factor)
.expect("region set should be ok");
}
}
}
return output;
}

View File

@@ -95,12 +95,12 @@ impl AlignmentPatternFinder {
for iGen in 0..height {
// for (int iGen = 0; iGen < height; iGen++) {
// Search from middle outwards
let i = middleI
let i = (middleI as i32
+ (if (iGen & 0x01) == 0 {
(iGen + 1) / 2
(iGen as i32 + 1) / 2
} else {
-((iGen as i32 + 1) / 2) as u32
});
-((iGen as i32 + 1) / 2)
})) as u32;
stateCount[0] = 0;
stateCount[1] = 0;
stateCount[2] = 0;

View File

@@ -336,27 +336,27 @@ impl Detector {
// Now count other way -- don't run off image though of course
let mut scale = 1.0;
let mut otherToX = fromX - (toX - fromX);
let mut otherToX = fromX as i32 - (toX as i32 - fromX as i32);
if (otherToX < 0) {
scale = fromX as f32 / (fromX - otherToX) as f32;
scale = fromX as f32 / (fromX as i32- otherToX) as f32;
otherToX = 0;
} else if (otherToX >= self.image.getWidth()) {
scale = (self.image.getWidth() - 1 - fromX) as f32 / (otherToX - fromX) as f32;
otherToX = self.image.getWidth() - 1;
} else if (otherToX as u32 >= self.image.getWidth() ) {
scale = (self.image.getWidth() as i32 - 1 - fromX as i32) as f32 / (otherToX - fromX as i32) as f32;
otherToX = self.image.getWidth() as i32 - 1;
}
let mut otherToY = (fromY - (toY - fromY) * scale as u32) as u32;
let mut otherToY = (fromY as i32 - (toY as i32 - fromY as i32) * scale as i32);
scale = 1.0;
if (otherToY < 0) {
scale = fromY as f32 / (fromY - otherToY) as f32;
scale = fromY as f32 / (fromY as i32 - otherToY) as f32;
otherToY = 0;
} else if (otherToY >= self.image.getHeight()) {
scale = (self.image.getHeight() - 1 - fromY) as f32 / (otherToY - fromY) as f32;
otherToY = self.image.getHeight() - 1;
} else if (otherToY as u32 >= self.image.getHeight()) {
scale = (self.image.getHeight() as i32 - 1 - fromY as i32) as f32 / (otherToY - fromY as i32) as f32;
otherToY = self.image.getHeight() as i32 - 1;
}
otherToX = (fromX + (otherToX - fromX) * scale as u32) as u32;
otherToX = (fromX as i32+ (otherToX - fromX as i32) * scale as i32);
result += self.sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);
result += self.sizeOfBlackWhiteBlackRun(fromX as u32, fromY as u32, otherToX as u32, otherToY as u32);
// Middle pixel is double-counted this way; subtract 1
return result - 1.0;
@@ -377,7 +377,7 @@ impl Detector {
let mut toY = toY;
// Mild variant of Bresenham's algorithm;
// see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
let steep = (toY - fromY) > (toX - fromX);
let steep = (toY as i64 - fromY as i64).abs() > (toX as i64 - fromX as i64).abs();
if (steep) {
let mut temp = fromX;
fromX = fromY;
@@ -387,8 +387,8 @@ impl Detector {
toY = temp;
}
let dx: i32 = (toX - fromX) as i32;
let dy: i32 = (toY - fromY) as i32;
let dx: i32 = (toX as i64 - fromX as i64).abs() as i32;
let dy: i32 = (toY as i64 - fromY as i64).abs() as i32;
let mut error = -dx / 2;
let xstep: i32 = if fromX < toX { 1 } else { -1 };
let ystep: i32 = if fromY < toY { 1 } else { -1 };

View File

@@ -161,6 +161,7 @@ impl FinderPatternFinder {
stateCount[currentState] += 1;
}
}
j+=1;
}
if FinderPatternFinder::foundPatternCross(&stateCount) {
let confirmed = self.handlePossibleCenter(&stateCount, i, maxJ);
@@ -187,7 +188,7 @@ impl FinderPatternFinder {
* figures the location of the center of this run.
*/
fn centerFromEnd(stateCount: &[u32], end: u32) -> f32 {
((end - stateCount[4] - stateCount[3]) - stateCount[2]) as f32 / 2.0
(end - stateCount[4] - stateCount[3]) as f32 - ((stateCount[2] as f32) / 2.0)
}
/**
@@ -363,19 +364,19 @@ impl FinderPatternFinder {
) -> f32 {
// let image = &self.image;
let maxI = self.image.getHeight();
let maxI = self.image.getHeight() as i32;
let _stateCount = self.getCrossCheckStateCount();
// Start counting up from center
let mut i = startI;
while i >= 0 && self.image.get(centerJ, i) {
let mut i = startI as i32;
while i >= 0 && self.image.get(centerJ, i as u32) {
self.crossCheckStateCount[2] += 1;
i -= 1;
}
if i < 0 {
return f32::NAN;
}
while i >= 0 && !self.image.get(centerJ, i) && self.crossCheckStateCount[1] <= maxCount {
while i >= 0 && !self.image.get(centerJ, i as u32) && self.crossCheckStateCount[1] <= maxCount {
self.crossCheckStateCount[1] += 1;
i -= 1;
}
@@ -383,7 +384,7 @@ impl FinderPatternFinder {
if i < 0 || self.crossCheckStateCount[1] > maxCount {
return f32::NAN;
}
while i >= 0 && self.image.get(centerJ, i) && self.crossCheckStateCount[0] <= maxCount {
while i >= 0 && self.image.get(centerJ, i as u32) && self.crossCheckStateCount[0] <= maxCount {
self.crossCheckStateCount[0] += 1;
i -= 1;
}
@@ -392,22 +393,22 @@ impl FinderPatternFinder {
}
// Now also count down from center
i = startI + 1;
while i < maxI && self.image.get(centerJ, i) {
i = startI as i32 + 1;
while i < maxI && self.image.get(centerJ, i as u32) {
self.crossCheckStateCount[2] += 1;
i += 1;
}
if i == maxI {
return f32::NAN;
}
while i < maxI && !self.image.get(centerJ, i) && self.crossCheckStateCount[3] < maxCount {
while i < maxI && !self.image.get(centerJ, i as u32) && self.crossCheckStateCount[3] < maxCount {
self.crossCheckStateCount[3] += 1;
i += 1;
}
if i == maxI || self.crossCheckStateCount[3] >= maxCount {
return f32::NAN;
}
while i < maxI && self.image.get(centerJ, i) && self.crossCheckStateCount[4] < maxCount {
while i < maxI && self.image.get(centerJ, i as u32) && self.crossCheckStateCount[4] < maxCount {
self.crossCheckStateCount[4] += 1;
i += 1;
}
@@ -422,12 +423,12 @@ impl FinderPatternFinder {
+ self.crossCheckStateCount[2]
+ self.crossCheckStateCount[3]
+ self.crossCheckStateCount[4];
if 5 * (stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal {
if 5 * (stateCountTotal as i64 - originalStateCountTotal as i64) >= 2 * originalStateCountTotal as i64 {
return f32::NAN;
}
if Self::foundPatternCross(&self.crossCheckStateCount) {
Self::centerFromEnd(&self.crossCheckStateCount, i)
Self::centerFromEnd(&self.crossCheckStateCount, i as u32)
} else {
f32::NAN
}
@@ -450,22 +451,22 @@ impl FinderPatternFinder {
let maxJ = self.image.getWidth();
let _stateCount = self.getCrossCheckStateCount();
let mut j = startJ;
while j >= 0 && self.image.get(j, centerI) {
let mut j = startJ as i32;
while j >= 0 && self.image.get(j as u32, centerI) {
self.crossCheckStateCount[2] += 1;
j -= 1;
}
if j < 0 {
return f32::NAN;
}
while j >= 0 && !self.image.get(j, centerI) && self.crossCheckStateCount[1] <= maxCount {
while j >= 0 && !self.image.get(j as u32, centerI) && self.crossCheckStateCount[1] <= maxCount {
self.crossCheckStateCount[1] += 1;
j -= 1;
}
if j < 0 || self.crossCheckStateCount[1] > maxCount {
return f32::NAN;
}
while j >= 0 && self.image.get(j, centerI) && self.crossCheckStateCount[0] <= maxCount {
while j >= 0 && self.image.get(j as u32 as u32, centerI) && self.crossCheckStateCount[0] <= maxCount {
self.crossCheckStateCount[0] += 1;
j -= 1;
}
@@ -473,22 +474,22 @@ impl FinderPatternFinder {
return f32::NAN;
}
j = startJ + 1;
while j < maxJ && self.image.get(j, centerI) {
j = startJ as i32 + 1;
while j < (maxJ as i32) && self.image.get(j as u32, centerI) {
self.crossCheckStateCount[2] += 1;
j += 1;
}
if j == maxJ {
if j == maxJ as i32 {
return f32::NAN;
}
while j < maxJ && !self.image.get(j, centerI) && self.crossCheckStateCount[3] < maxCount {
while j < maxJ as i32 && !self.image.get(j as u32, centerI) && self.crossCheckStateCount[3] < maxCount {
self.crossCheckStateCount[3] += 1;
j += 1;
}
if j == maxJ || self.crossCheckStateCount[3] >= maxCount {
if j == (maxJ as i32) || self.crossCheckStateCount[3] >= maxCount {
return f32::NAN;
}
while j < maxJ && self.image.get(j, centerI) && self.crossCheckStateCount[4] < maxCount {
while j < (maxJ as i32) && self.image.get(j as u32, centerI) && self.crossCheckStateCount[4] < maxCount {
self.crossCheckStateCount[4] += 1;
j += 1;
}
@@ -503,12 +504,12 @@ impl FinderPatternFinder {
+ self.crossCheckStateCount[2]
+ self.crossCheckStateCount[3]
+ self.crossCheckStateCount[4];
if 5 * (stateCountTotal - originalStateCountTotal) >= originalStateCountTotal {
if 5 * (stateCountTotal as i64 - originalStateCountTotal as i64) >= originalStateCountTotal as i64 {
return f32::NAN;
}
if Self::foundPatternCross(&self.crossCheckStateCount) {
Self::centerFromEnd(&self.crossCheckStateCount, j)
Self::centerFromEnd(&self.crossCheckStateCount, j as u32)
} else {
f32::NAN
}

View File

@@ -12,4 +12,7 @@ pub use alignment_pattern::*;
pub use alignment_pattern_finder::*;
pub use finder_pattern_finder::*;
pub use detector::*;
pub use qrcode_detector_result::*;
pub use qrcode_detector_result::*;
#[cfg(test)]
mod DetectorTest;