mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-27 04:42:35 +00:00
qr_code partially working
This commit is contained in:
62
src/qrcode/detector/DetectorTest.rs
Normal file
62
src/qrcode/detector/DetectorTest.rs
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user