mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-27 21:02:35 +00:00
consider removing inverted
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
pub mod detector;
|
pub mod detector;
|
||||||
pub mod reedsolomon;
|
pub mod reedsolomon;
|
||||||
|
|
||||||
|
use core::num;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@@ -52,12 +53,12 @@ pub struct StringUtils {
|
|||||||
// public static final String GB2312 = "GB2312";
|
// public static final String GB2312 = "GB2312";
|
||||||
}
|
}
|
||||||
|
|
||||||
const PLATFORM_DEFAULT_ENCODING: &dyn Encoding = encoding::all::UTF_8;
|
// const PLATFORM_DEFAULT_ENCODING: &dyn Encoding = encoding::all::UTF_8;
|
||||||
const SHIFT_JIS_CHARSET: &dyn Encoding =
|
// const SHIFT_JIS_CHARSET: &dyn Encoding =
|
||||||
encoding::label::encoding_from_whatwg_label("SJIS").unwrap();
|
// encoding::label::encoding_from_whatwg_label("SJIS").unwrap();
|
||||||
const GB2312_CHARSET: &dyn Encoding =
|
// const GB2312_CHARSET: &dyn Encoding =
|
||||||
encoding::label::encoding_from_whatwg_label("GB2312").unwrap();
|
// encoding::label::encoding_from_whatwg_label("GB2312").unwrap();
|
||||||
const EUC_JP: &dyn Encoding = encoding::label::encoding_from_whatwg_label("EUC_JP").unwrap();
|
// const EUC_JP: &dyn Encoding = encoding::label::encoding_from_whatwg_label("EUC_JP").unwrap();
|
||||||
const ASSUME_SHIFT_JIS: bool = false;
|
const ASSUME_SHIFT_JIS: bool = false;
|
||||||
static SHIFT_JIS: &'static str = "SJIS";
|
static SHIFT_JIS: &'static str = "SJIS";
|
||||||
static GB2312: &'static str = "GB2312";
|
static GB2312: &'static str = "GB2312";
|
||||||
@@ -76,7 +77,11 @@ impl StringUtils {
|
|||||||
*/
|
*/
|
||||||
pub fn guessEncoding(bytes: &[u8], hints: HashMap<DecodeHintType, String>) -> String {
|
pub fn guessEncoding(bytes: &[u8], hints: HashMap<DecodeHintType, String>) -> String {
|
||||||
let c = StringUtils::guessCharset(bytes, hints);
|
let c = StringUtils::guessCharset(bytes, hints);
|
||||||
if c.name() == SHIFT_JIS_CHARSET.name() {
|
if c.name()
|
||||||
|
== encoding::label::encoding_from_whatwg_label("SJIS")
|
||||||
|
.unwrap()
|
||||||
|
.name()
|
||||||
|
{
|
||||||
return "SJIS".to_owned();
|
return "SJIS".to_owned();
|
||||||
} else if c.name() == encoding::all::UTF_8.name() {
|
} else if c.name() == encoding::all::UTF_8.name() {
|
||||||
return "UTF8".to_owned();
|
return "UTF8".to_owned();
|
||||||
@@ -119,20 +124,20 @@ impl StringUtils {
|
|||||||
// For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS,
|
// For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS,
|
||||||
// which should be by far the most common encodings.
|
// which should be by far the most common encodings.
|
||||||
let length = bytes.len();
|
let length = bytes.len();
|
||||||
let canBeISO88591 = true;
|
let mut canBeISO88591 = true;
|
||||||
let canBeShiftJIS = true;
|
let mut canBeShiftJIS = true;
|
||||||
let canBeUTF8 = true;
|
let mut canBeUTF8 = true;
|
||||||
let utf8BytesLeft = 0;
|
let mut utf8BytesLeft = 0;
|
||||||
let utf2BytesChars = 0;
|
let mut utf2BytesChars = 0;
|
||||||
let utf3BytesChars = 0;
|
let mut utf3BytesChars = 0;
|
||||||
let utf4BytesChars = 0;
|
let mut utf4BytesChars = 0;
|
||||||
let sjisBytesLeft = 0;
|
let mut sjisBytesLeft = 0;
|
||||||
let sjisKatakanaChars = 0;
|
let mut sjisKatakanaChars = 0;
|
||||||
let sjisCurKatakanaWordLength = 0;
|
let mut sjisCurKatakanaWordLength = 0;
|
||||||
let sjisCurDoubleBytesWordLength = 0;
|
let mut sjisCurDoubleBytesWordLength = 0;
|
||||||
let sjisMaxKatakanaWordLength = 0;
|
let mut sjisMaxKatakanaWordLength = 0;
|
||||||
let sjisMaxDoubleBytesWordLength = 0;
|
let mut sjisMaxDoubleBytesWordLength = 0;
|
||||||
let isoHighOther = 0;
|
let mut isoHighOther = 0;
|
||||||
|
|
||||||
let utf8bom = bytes.len() > 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF;
|
let utf8bom = bytes.len() > 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF;
|
||||||
|
|
||||||
@@ -237,7 +242,7 @@ impl StringUtils {
|
|||||||
|| sjisMaxKatakanaWordLength >= 3
|
|| sjisMaxKatakanaWordLength >= 3
|
||||||
|| sjisMaxDoubleBytesWordLength >= 3)
|
|| sjisMaxDoubleBytesWordLength >= 3)
|
||||||
{
|
{
|
||||||
return SHIFT_JIS_CHARSET;
|
return encoding::label::encoding_from_whatwg_label("SJIS").unwrap();
|
||||||
}
|
}
|
||||||
// Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is:
|
// Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is:
|
||||||
// - If we saw
|
// - If we saw
|
||||||
@@ -248,7 +253,7 @@ impl StringUtils {
|
|||||||
return if (sjisMaxKatakanaWordLength == 2 && sjisKatakanaChars == 2)
|
return if (sjisMaxKatakanaWordLength == 2 && sjisKatakanaChars == 2)
|
||||||
|| isoHighOther * 10 >= length
|
|| isoHighOther * 10 >= length
|
||||||
{
|
{
|
||||||
SHIFT_JIS_CHARSET
|
encoding::label::encoding_from_whatwg_label("SJIS").unwrap()
|
||||||
} else {
|
} else {
|
||||||
encoding::all::ISO_8859_1
|
encoding::all::ISO_8859_1
|
||||||
};
|
};
|
||||||
@@ -259,13 +264,13 @@ impl StringUtils {
|
|||||||
return encoding::all::ISO_8859_1;
|
return encoding::all::ISO_8859_1;
|
||||||
}
|
}
|
||||||
if canBeShiftJIS {
|
if canBeShiftJIS {
|
||||||
return SHIFT_JIS_CHARSET;
|
return encoding::label::encoding_from_whatwg_label("SJIS").unwrap();
|
||||||
}
|
}
|
||||||
if canBeUTF8 {
|
if canBeUTF8 {
|
||||||
return encoding::all::UTF_8;
|
return encoding::all::UTF_8;
|
||||||
}
|
}
|
||||||
// Otherwise, we take a wild guess with platform encoding
|
// Otherwise, we take a wild guess with platform encoding
|
||||||
return PLATFORM_DEFAULT_ENCODING;
|
return encoding::all::UTF_8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,9 +339,9 @@ impl BitArray {
|
|||||||
return (self.size + 7) / 8;
|
return (self.size + 7) / 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensureCapacity(&self, newSize: usize) {
|
fn ensureCapacity(&mut self, newSize: usize) {
|
||||||
if newSize > self.bits.len() * 32 {
|
if newSize > self.bits.len() * 32 {
|
||||||
let newBits = BitArray::makeArray((newSize as f32 / LOAD_FACTOR).ceil() as usize);
|
let mut newBits = BitArray::makeArray((newSize as f32 / LOAD_FACTOR).ceil() as usize);
|
||||||
//System.arraycopy(bits, 0, newBits, 0, bits.length);
|
//System.arraycopy(bits, 0, newBits, 0, bits.length);
|
||||||
newBits[0..self.bits.len()].clone_from_slice(&self.bits[0..self.bits.len()]);
|
newBits[0..self.bits.len()].clone_from_slice(&self.bits[0..self.bits.len()]);
|
||||||
self.bits = newBits;
|
self.bits = newBits;
|
||||||
@@ -356,7 +361,7 @@ impl BitArray {
|
|||||||
*
|
*
|
||||||
* @param i bit to set
|
* @param i bit to set
|
||||||
*/
|
*/
|
||||||
pub fn set(&self, i: usize) {
|
pub fn set(&mut self, i: usize) {
|
||||||
self.bits[i / 32] |= 1 << (i & 0x1F);
|
self.bits[i / 32] |= 1 << (i & 0x1F);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +370,7 @@ impl BitArray {
|
|||||||
*
|
*
|
||||||
* @param i bit to set
|
* @param i bit to set
|
||||||
*/
|
*/
|
||||||
pub fn flip(&self, i: usize) {
|
pub fn flip(&mut self, i: usize) {
|
||||||
self.bits[i / 32] ^= 1 << (i & 0x1F);
|
self.bits[i / 32] ^= 1 << (i & 0x1F);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,7 +384,7 @@ impl BitArray {
|
|||||||
if from >= self.size {
|
if from >= self.size {
|
||||||
return self.size;
|
return self.size;
|
||||||
}
|
}
|
||||||
let bitsOffset = from / 32;
|
let mut bitsOffset = from / 32;
|
||||||
let mut currentBits = self.bits[bitsOffset] as i32;
|
let mut currentBits = self.bits[bitsOffset] as i32;
|
||||||
// mask off lesser bits first
|
// mask off lesser bits first
|
||||||
currentBits &= -(1 << (from & 0x1F));
|
currentBits &= -(1 << (from & 0x1F));
|
||||||
@@ -403,8 +408,8 @@ impl BitArray {
|
|||||||
if from >= self.size {
|
if from >= self.size {
|
||||||
return self.size;
|
return self.size;
|
||||||
}
|
}
|
||||||
let bitsOffset = from / 32;
|
let mut bitsOffset = from / 32;
|
||||||
let currentBits = !self.bits[bitsOffset] as i32;
|
let mut currentBits = !self.bits[bitsOffset] as i32;
|
||||||
// mask off lesser bits first
|
// mask off lesser bits first
|
||||||
currentBits &= -(1 << (from & 0x1F));
|
currentBits &= -(1 << (from & 0x1F));
|
||||||
while currentBits == 0 {
|
while currentBits == 0 {
|
||||||
@@ -425,7 +430,7 @@ impl BitArray {
|
|||||||
* @param newBits the new value of the next 32 bits. Note again that the least-significant bit
|
* @param newBits the new value of the next 32 bits. Note again that the least-significant bit
|
||||||
* corresponds to bit i, the next-least-significant to i+1, and so on.
|
* corresponds to bit i, the next-least-significant to i+1, and so on.
|
||||||
*/
|
*/
|
||||||
pub fn setBulk(&self, i: usize, newBits: u32) {
|
pub fn setBulk(&mut self, i: usize, newBits: u32) {
|
||||||
self.bits[i / 32] = newBits;
|
self.bits[i / 32] = newBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,7 +440,8 @@ impl BitArray {
|
|||||||
* @param start start of range, inclusive.
|
* @param start start of range, inclusive.
|
||||||
* @param end end of range, exclusive
|
* @param end end of range, exclusive
|
||||||
*/
|
*/
|
||||||
pub fn setRange(&self, start: usize, end: usize) -> Result<(), IllegalArgumentException> {
|
pub fn setRange(&mut self, start: usize, end: usize) -> Result<(), IllegalArgumentException> {
|
||||||
|
let mut end = end;
|
||||||
if end < start || start < 0 || end > self.size {
|
if end < start || start < 0 || end > self.size {
|
||||||
return Err(IllegalArgumentException::new(
|
return Err(IllegalArgumentException::new(
|
||||||
"end < start || start < 0 || end > self.size",
|
"end < start || start < 0 || end > self.size",
|
||||||
@@ -461,7 +467,7 @@ impl BitArray {
|
|||||||
/**
|
/**
|
||||||
* Clears all bits (sets to false).
|
* Clears all bits (sets to false).
|
||||||
*/
|
*/
|
||||||
pub fn clear(&self) {
|
pub fn clear(&mut self) {
|
||||||
let max = self.bits.len();
|
let max = self.bits.len();
|
||||||
for i in 0..max {
|
for i in 0..max {
|
||||||
//for (int i = 0; i < max; i++) {
|
//for (int i = 0; i < max; i++) {
|
||||||
@@ -484,6 +490,7 @@ impl BitArray {
|
|||||||
end: usize,
|
end: usize,
|
||||||
value: bool,
|
value: bool,
|
||||||
) -> Result<bool, IllegalArgumentException> {
|
) -> Result<bool, IllegalArgumentException> {
|
||||||
|
let mut end = end;
|
||||||
if end < start || start < 0 || end > self.size {
|
if end < start || start < 0 || end > self.size {
|
||||||
return Err(IllegalArgumentException::new(
|
return Err(IllegalArgumentException::new(
|
||||||
"end < start || start < 0 || end > self.size",
|
"end < start || start < 0 || end > self.size",
|
||||||
@@ -511,7 +518,7 @@ impl BitArray {
|
|||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn appendBit(&self, bit: bool) {
|
pub fn appendBit(&mut self, bit: bool) {
|
||||||
self.ensureCapacity(self.size + 1);
|
self.ensureCapacity(self.size + 1);
|
||||||
if bit {
|
if bit {
|
||||||
self.bits[self.size / 32] |= 1 << (self.size & 0x1F);
|
self.bits[self.size / 32] |= 1 << (self.size & 0x1F);
|
||||||
@@ -527,13 +534,17 @@ impl BitArray {
|
|||||||
* @param value {@code int} containing bits to append
|
* @param value {@code int} containing bits to append
|
||||||
* @param numBits bits from value to append
|
* @param numBits bits from value to append
|
||||||
*/
|
*/
|
||||||
pub fn appendBits(&self, value: u32, numBits: usize) -> Result<(), IllegalArgumentException> {
|
pub fn appendBits(
|
||||||
|
&mut self,
|
||||||
|
value: u32,
|
||||||
|
numBits: usize,
|
||||||
|
) -> Result<(), IllegalArgumentException> {
|
||||||
if numBits < 0 || numBits > 32 {
|
if numBits < 0 || numBits > 32 {
|
||||||
return Err(IllegalArgumentException::new(
|
return Err(IllegalArgumentException::new(
|
||||||
"Num bits must be between 0 and 32",
|
"Num bits must be between 0 and 32",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let nextSize = self.size;
|
let mut nextSize = self.size;
|
||||||
self.ensureCapacity(nextSize + numBits);
|
self.ensureCapacity(nextSize + numBits);
|
||||||
for numBitsLeft in (0..(numBits - 1)).rev() {
|
for numBitsLeft in (0..(numBits - 1)).rev() {
|
||||||
//for (int numBitsLeft = numBits - 1; numBitsLeft >= 0; numBitsLeft--) {
|
//for (int numBitsLeft = numBits - 1; numBitsLeft >= 0; numBitsLeft--) {
|
||||||
@@ -546,7 +557,7 @@ impl BitArray {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn appendBitArray(&self, other: BitArray) {
|
pub fn appendBitArray(&mut self, other: BitArray) {
|
||||||
let otherSize = other.size;
|
let otherSize = other.size;
|
||||||
self.ensureCapacity(self.size + otherSize);
|
self.ensureCapacity(self.size + otherSize);
|
||||||
for i in 0..otherSize {
|
for i in 0..otherSize {
|
||||||
@@ -555,7 +566,7 @@ impl BitArray {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn xor(&self, other: &BitArray) -> Result<(), IllegalArgumentException> {
|
pub fn xor(&mut self, other: &BitArray) -> Result<(), IllegalArgumentException> {
|
||||||
if self.size != other.size {
|
if self.size != other.size {
|
||||||
return Err(IllegalArgumentException::new("Sizes don't match"));
|
return Err(IllegalArgumentException::new("Sizes don't match"));
|
||||||
}
|
}
|
||||||
@@ -577,9 +588,10 @@ impl BitArray {
|
|||||||
* @param numBytes how many bytes to write
|
* @param numBytes how many bytes to write
|
||||||
*/
|
*/
|
||||||
pub fn toBytes(&self, bitOffset: usize, array: &mut [u8], offset: usize, numBytes: usize) {
|
pub fn toBytes(&self, bitOffset: usize, array: &mut [u8], offset: usize, numBytes: usize) {
|
||||||
|
let mut bitOffset = bitOffset;
|
||||||
for i in 0..numBytes {
|
for i in 0..numBytes {
|
||||||
//for (int i = 0; i < numBytes; i++) {
|
//for (int i = 0; i < numBytes; i++) {
|
||||||
let theByte = 0;
|
let mut theByte = 0;
|
||||||
for j in 0..8 {
|
for j in 0..8 {
|
||||||
//for (int j = 0; j < 8; j++) {
|
//for (int j = 0; j < 8; j++) {
|
||||||
if self.get(bitOffset) {
|
if self.get(bitOffset) {
|
||||||
@@ -595,15 +607,15 @@ impl BitArray {
|
|||||||
* @return underlying array of ints. The first element holds the first 32 bits, and the least
|
* @return underlying array of ints. The first element holds the first 32 bits, and the least
|
||||||
* significant bit is bit 0.
|
* significant bit is bit 0.
|
||||||
*/
|
*/
|
||||||
pub fn getBitArray(&self) -> Vec<u32> {
|
pub fn getBitArray(&self) -> &Vec<u32> {
|
||||||
return self.bits;
|
return &self.bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverses all bits in the array.
|
* Reverses all bits in the array.
|
||||||
*/
|
*/
|
||||||
pub fn reverse(&self) {
|
pub fn reverse(&mut self) {
|
||||||
let newBits = Vec::with_capacity(self.bits.len());
|
let mut newBits = Vec::with_capacity(self.bits.len());
|
||||||
// reverse all int's first
|
// reverse all int's first
|
||||||
let len = (self.size - 1) / 32;
|
let len = (self.size - 1) / 32;
|
||||||
let oldBitsLen = len + 1;
|
let oldBitsLen = len + 1;
|
||||||
@@ -614,7 +626,7 @@ impl BitArray {
|
|||||||
// now correct the int's if the bit size isn't a multiple of 32
|
// now correct the int's if the bit size isn't a multiple of 32
|
||||||
if self.size != oldBitsLen * 32 {
|
if self.size != oldBitsLen * 32 {
|
||||||
let leftOffset = oldBitsLen * 32 - self.size;
|
let leftOffset = oldBitsLen * 32 - self.size;
|
||||||
let currentInt = newBits[0] >> leftOffset;
|
let mut currentInt = newBits[0] >> leftOffset;
|
||||||
for i in 1..oldBitsLen {
|
for i in 1..oldBitsLen {
|
||||||
//for (int i = 1; i < oldBitsLen; i++) {
|
//for (int i = 1; i < oldBitsLen; i++) {
|
||||||
let nextInt = newBits[i];
|
let nextInt = newBits[i];
|
||||||
@@ -653,7 +665,7 @@ impl BitArray {
|
|||||||
|
|
||||||
impl fmt::Display for BitArray {
|
impl fmt::Display for BitArray {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let _str = String::with_capacity(self.size + (self.size / 8) + 1);
|
let mut _str = String::with_capacity(self.size + (self.size / 8) + 1);
|
||||||
for i in 0..self.size {
|
for i in 0..self.size {
|
||||||
//for (int i = 0; i < size; i++) {
|
//for (int i = 0; i < size; i++) {
|
||||||
if (i & 0x07) == 0 {
|
if (i & 0x07) == 0 {
|
||||||
@@ -705,12 +717,12 @@ impl DetectorRXingResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getBits(&self) -> BitMatrix {
|
pub fn getBits(&self) -> &BitMatrix {
|
||||||
return self.bits;
|
return &self.bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getPoints(&self) -> Vec<RXingResultPoint> {
|
pub fn getPoints(&self) -> &Vec<RXingResultPoint> {
|
||||||
return self.points;
|
return &self.points;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,10 +821,10 @@ impl BitMatrix {
|
|||||||
pub fn parse_bools(image: &Vec<Vec<bool>>) -> Self {
|
pub fn parse_bools(image: &Vec<Vec<bool>>) -> Self {
|
||||||
let height: u32 = image.len().try_into().unwrap();
|
let height: u32 = image.len().try_into().unwrap();
|
||||||
let width: u32 = image[0].len().try_into().unwrap();
|
let width: u32 = image[0].len().try_into().unwrap();
|
||||||
let bits = BitMatrix::new(width, height).unwrap();
|
let mut bits = BitMatrix::new(width, height).unwrap();
|
||||||
for i in 0..height as usize {
|
for i in 0..height as usize {
|
||||||
//for (int i = 0; i < height; i++) {
|
//for (int i = 0; i < height; i++) {
|
||||||
let imageI = image[i];
|
let imageI = &image[i];
|
||||||
for j in 0..width as usize {
|
for j in 0..width as usize {
|
||||||
//for (int j = 0; j < width; j++) {
|
//for (int j = 0; j < width; j++) {
|
||||||
if imageI[j] {
|
if imageI[j] {
|
||||||
@@ -833,15 +845,16 @@ impl BitMatrix {
|
|||||||
// throw new IllegalArgumentException();
|
// throw new IllegalArgumentException();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
let bits = Vec::with_capacity(stringRepresentation.len());
|
let mut bits = Vec::with_capacity(stringRepresentation.len());
|
||||||
let bitsPos = 0;
|
let mut bitsPos = 0;
|
||||||
let rowStartPos = 0;
|
let mut rowStartPos = 0;
|
||||||
let rowLength = 0;//-1;
|
let mut rowLength = 0; //-1;
|
||||||
let mut first_run = true;
|
let mut first_run = true;
|
||||||
let nRows = 0;
|
let mut nRows = 0;
|
||||||
let pos = 0;
|
let mut pos = 0;
|
||||||
while pos < stringRepresentation.len() {
|
while pos < stringRepresentation.len() {
|
||||||
if stringRepresentation.chars().nth(pos).unwrap() == '\n' || stringRepresentation.chars().nth(pos).unwrap() == '\r'
|
if stringRepresentation.chars().nth(pos).unwrap() == '\n'
|
||||||
|
|| stringRepresentation.chars().nth(pos).unwrap() == '\r'
|
||||||
{
|
{
|
||||||
if bitsPos > rowStartPos {
|
if bitsPos > rowStartPos {
|
||||||
//if rowLength == -1 {
|
//if rowLength == -1 {
|
||||||
@@ -883,11 +896,14 @@ impl BitMatrix {
|
|||||||
nRows += 1;
|
nRows += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let matrix = BitMatrix::new(rowLength.try_into().unwrap(), nRows)?;
|
let mut matrix = BitMatrix::new(rowLength.try_into().unwrap(), nRows)?;
|
||||||
for i in 0..bitsPos {
|
for i in 0..bitsPos {
|
||||||
//for (int i = 0; i < bitsPos; i++) {
|
//for (int i = 0; i < bitsPos; i++) {
|
||||||
if bits[i] {
|
if bits[i] {
|
||||||
matrix.set((i % rowLength).try_into().unwrap(), (i / rowLength).try_into().unwrap());
|
matrix.set(
|
||||||
|
(i % rowLength).try_into().unwrap(),
|
||||||
|
(i / rowLength).try_into().unwrap(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(matrix);
|
return Ok(matrix);
|
||||||
@@ -911,12 +927,12 @@ impl BitMatrix {
|
|||||||
* @param x The horizontal component (i.e. which column)
|
* @param x The horizontal component (i.e. which column)
|
||||||
* @param y The vertical component (i.e. which row)
|
* @param y The vertical component (i.e. which row)
|
||||||
*/
|
*/
|
||||||
pub fn set(&self, x: u32, y: u32) {
|
pub fn set(&mut self, x: u32, y: u32) {
|
||||||
let offset = y as usize * self.rowSize + (x as usize / 32);
|
let offset = y as usize * self.rowSize + (x as usize / 32);
|
||||||
self.bits[offset] |= 1 << (x & 0x1f);
|
self.bits[offset] |= 1 << (x & 0x1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unset(&self, x: u32, y: u32) {
|
pub fn unset(&mut self, x: u32, y: u32) {
|
||||||
let offset = y as usize * self.rowSize + (x as usize / 32);
|
let offset = y as usize * self.rowSize + (x as usize / 32);
|
||||||
self.bits[offset] &= !(1 << (x & 0x1f));
|
self.bits[offset] &= !(1 << (x & 0x1f));
|
||||||
}
|
}
|
||||||
@@ -927,7 +943,7 @@ impl BitMatrix {
|
|||||||
* @param x The horizontal component (i.e. which column)
|
* @param x The horizontal component (i.e. which column)
|
||||||
* @param y The vertical component (i.e. which row)
|
* @param y The vertical component (i.e. which row)
|
||||||
*/
|
*/
|
||||||
pub fn flip_coords(&self, x: u32, y: u32) {
|
pub fn flip_coords(&mut self, x: u32, y: u32) {
|
||||||
let offset = y as usize * self.rowSize + (x as usize / 32);
|
let offset = y as usize * self.rowSize + (x as usize / 32);
|
||||||
self.bits[offset] ^= 1 << (x & 0x1f);
|
self.bits[offset] ^= 1 << (x & 0x1f);
|
||||||
}
|
}
|
||||||
@@ -935,7 +951,7 @@ impl BitMatrix {
|
|||||||
/**
|
/**
|
||||||
* <p>Flips every bit in the matrix.</p>
|
* <p>Flips every bit in the matrix.</p>
|
||||||
*/
|
*/
|
||||||
pub fn flip_self(&self) {
|
pub fn flip_self(&mut self) {
|
||||||
let max = self.bits.len();
|
let max = self.bits.len();
|
||||||
for i in 0..max {
|
for i in 0..max {
|
||||||
//for (int i = 0; i < max; i++) {
|
//for (int i = 0; i < max; i++) {
|
||||||
@@ -949,7 +965,7 @@ impl BitMatrix {
|
|||||||
*
|
*
|
||||||
* @param mask XOR mask
|
* @param mask XOR mask
|
||||||
*/
|
*/
|
||||||
pub fn xor(&self, mask: &BitMatrix) -> Result<(), IllegalArgumentException> {
|
pub fn xor(&mut self, mask: &BitMatrix) -> Result<(), IllegalArgumentException> {
|
||||||
if self.width != mask.width || self.height != mask.height || self.rowSize != mask.rowSize {
|
if self.width != mask.width || self.height != mask.height || self.rowSize != mask.rowSize {
|
||||||
return Err(IllegalArgumentException::new(
|
return Err(IllegalArgumentException::new(
|
||||||
"input matrix dimensions do not match",
|
"input matrix dimensions do not match",
|
||||||
@@ -959,7 +975,8 @@ impl BitMatrix {
|
|||||||
for y in 0..self.height {
|
for y in 0..self.height {
|
||||||
//for (int y = 0; y < height; y++) {
|
//for (int y = 0; y < height; y++) {
|
||||||
let offset = y as usize * self.rowSize;
|
let offset = y as usize * self.rowSize;
|
||||||
let row = mask.getRow(y, &rowArray).getBitArray();
|
let tmp = mask.getRow(y, &rowArray);
|
||||||
|
let row = tmp.getBitArray();
|
||||||
for x in 0..self.rowSize {
|
for x in 0..self.rowSize {
|
||||||
//for (int x = 0; x < rowSize; x++) {
|
//for (int x = 0; x < rowSize; x++) {
|
||||||
self.bits[offset + x] ^= row[x];
|
self.bits[offset + x] ^= row[x];
|
||||||
@@ -971,7 +988,7 @@ impl BitMatrix {
|
|||||||
/**
|
/**
|
||||||
* Clears all bits (sets to false).
|
* Clears all bits (sets to false).
|
||||||
*/
|
*/
|
||||||
pub fn clear(&self) {
|
pub fn clear(&mut self) {
|
||||||
let max = self.bits.len();
|
let max = self.bits.len();
|
||||||
for i in 0..max {
|
for i in 0..max {
|
||||||
//for (int i = 0; i < max; i++) {
|
//for (int i = 0; i < max; i++) {
|
||||||
@@ -988,7 +1005,7 @@ impl BitMatrix {
|
|||||||
* @param height The height of the region
|
* @param height The height of the region
|
||||||
*/
|
*/
|
||||||
pub fn setRegion(
|
pub fn setRegion(
|
||||||
&self,
|
&mut self,
|
||||||
left: u32,
|
left: u32,
|
||||||
top: u32,
|
top: u32,
|
||||||
width: u32,
|
width: u32,
|
||||||
@@ -1031,11 +1048,14 @@ impl BitMatrix {
|
|||||||
* your own row
|
* your own row
|
||||||
*/
|
*/
|
||||||
pub fn getRow(&self, y: u32, row: &BitArray) -> BitArray {
|
pub fn getRow(&self, y: u32, row: &BitArray) -> BitArray {
|
||||||
let rw: BitArray = if row.getSize() < self.width as usize {
|
let mut rw: BitArray = if row.getSize() < self.width as usize {
|
||||||
BitArray::with_size(self.width as usize)
|
BitArray::with_size(self.width as usize)
|
||||||
} else {
|
} else {
|
||||||
row.clear();
|
let mut z = row.clone();
|
||||||
*row
|
z.clear();
|
||||||
|
z
|
||||||
|
// row.clear();
|
||||||
|
// row.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let offset = y as usize * self.rowSize;
|
let offset = y as usize * self.rowSize;
|
||||||
@@ -1050,7 +1070,7 @@ impl BitMatrix {
|
|||||||
* @param y row to set
|
* @param y row to set
|
||||||
* @param row {@link BitArray} to copy from
|
* @param row {@link BitArray} to copy from
|
||||||
*/
|
*/
|
||||||
pub fn setRow(&self, y: u32, row: &BitArray) {
|
pub fn setRow(&mut self, y: u32, row: &BitArray) {
|
||||||
return self.bits[y as usize * self.rowSize..self.rowSize]
|
return self.bits[y as usize * self.rowSize..self.rowSize]
|
||||||
.clone_from_slice(&row.getBitArray()[0..self.rowSize]);
|
.clone_from_slice(&row.getBitArray()[0..self.rowSize]);
|
||||||
//System.arraycopy(row.getBitArray(), 0, self.bits, y * self.rowSize, self.rowSize);
|
//System.arraycopy(row.getBitArray(), 0, self.bits, y * self.rowSize, self.rowSize);
|
||||||
@@ -1061,7 +1081,7 @@ impl BitMatrix {
|
|||||||
*
|
*
|
||||||
* @param degrees number of degrees to rotate through counter-clockwise (0, 90, 180, 270)
|
* @param degrees number of degrees to rotate through counter-clockwise (0, 90, 180, 270)
|
||||||
*/
|
*/
|
||||||
pub fn rotate(&self, degrees: u32) -> Result<(), IllegalArgumentException> {
|
pub fn rotate(&mut self, degrees: u32) -> Result<(), IllegalArgumentException> {
|
||||||
match degrees % 360 {
|
match degrees % 360 {
|
||||||
0 => Ok(()),
|
0 => Ok(()),
|
||||||
90 => {
|
90 => {
|
||||||
@@ -1086,7 +1106,7 @@ impl BitMatrix {
|
|||||||
/**
|
/**
|
||||||
* Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees
|
* Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees
|
||||||
*/
|
*/
|
||||||
pub fn rotate180(&self) {
|
pub fn rotate180(&mut self) {
|
||||||
let mut topRow = BitArray::with_size(self.width as usize);
|
let mut topRow = BitArray::with_size(self.width as usize);
|
||||||
let mut bottomRow = BitArray::with_size(self.width as usize);
|
let mut bottomRow = BitArray::with_size(self.width as usize);
|
||||||
let mut maxHeight = (self.height + 1) / 2;
|
let mut maxHeight = (self.height + 1) / 2;
|
||||||
@@ -1105,7 +1125,7 @@ impl BitMatrix {
|
|||||||
/**
|
/**
|
||||||
* Modifies this {@code BitMatrix} to represent the same but rotated 90 degrees counterclockwise
|
* Modifies this {@code BitMatrix} to represent the same but rotated 90 degrees counterclockwise
|
||||||
*/
|
*/
|
||||||
pub fn rotate90(&self) {
|
pub fn rotate90(&mut self) {
|
||||||
let mut newWidth = self.height;
|
let mut newWidth = self.height;
|
||||||
let mut newHeight = self.width;
|
let mut newHeight = self.width;
|
||||||
let mut newRowSize = (newWidth + 31) / 32;
|
let mut newRowSize = (newWidth + 31) / 32;
|
||||||
@@ -1117,7 +1137,9 @@ impl BitMatrix {
|
|||||||
//for (int x = 0; x < width; x++) {
|
//for (int x = 0; x < width; x++) {
|
||||||
let offset = y as usize * self.rowSize + (x as usize / 32);
|
let offset = y as usize * self.rowSize + (x as usize / 32);
|
||||||
if ((self.bits[offset] >> (x & 0x1f)) & 1) != 0 {
|
if ((self.bits[offset] >> (x & 0x1f)) & 1) != 0 {
|
||||||
let newOffset:usize = ((newHeight - 1 - x) * newRowSize + (y / 32)).try_into().unwrap();
|
let newOffset: usize = ((newHeight - 1 - x) * newRowSize + (y / 32))
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
newBits[newOffset] |= 1 << (y & 0x1f);
|
newBits[newOffset] |= 1 << (y & 0x1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1134,12 +1156,12 @@ impl BitMatrix {
|
|||||||
* @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white
|
* @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white
|
||||||
*/
|
*/
|
||||||
pub fn getEnclosingRectangle(&self) -> Option<Vec<u32>> {
|
pub fn getEnclosingRectangle(&self) -> Option<Vec<u32>> {
|
||||||
let left = self.width;
|
let mut left = self.width;
|
||||||
let top = self.height;
|
let mut top = self.height;
|
||||||
// let right = -1;
|
// let right = -1;
|
||||||
// let bottom = -1;
|
// let bottom = -1;
|
||||||
let right:u32 = 0;
|
let mut right: u32 = 0;
|
||||||
let bottom = 0;
|
let mut bottom = 0;
|
||||||
|
|
||||||
for y in 0..self.height {
|
for y in 0..self.height {
|
||||||
//for (int y = 0; y < height; y++) {
|
//for (int y = 0; y < height; y++) {
|
||||||
@@ -1154,7 +1176,7 @@ impl BitMatrix {
|
|||||||
bottom = y;
|
bottom = y;
|
||||||
}
|
}
|
||||||
if x32 * 32 < left.try_into().unwrap() {
|
if x32 * 32 < left.try_into().unwrap() {
|
||||||
let bit = 0;
|
let mut bit = 0;
|
||||||
while (theBits << (31 - bit)) == 0 {
|
while (theBits << (31 - bit)) == 0 {
|
||||||
bit += 1;
|
bit += 1;
|
||||||
}
|
}
|
||||||
@@ -1163,7 +1185,7 @@ impl BitMatrix {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if x32 * 32 + 31 > right.try_into().unwrap() {
|
if x32 * 32 + 31 > right.try_into().unwrap() {
|
||||||
let bit = 31;
|
let mut bit = 31;
|
||||||
while (theBits >> bit) == 0 {
|
while (theBits >> bit) == 0 {
|
||||||
bit -= 1;
|
bit -= 1;
|
||||||
}
|
}
|
||||||
@@ -1188,7 +1210,7 @@ impl BitMatrix {
|
|||||||
* @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white
|
* @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white
|
||||||
*/
|
*/
|
||||||
pub fn getTopLeftOnBit(&self) -> Option<Vec<u32>> {
|
pub fn getTopLeftOnBit(&self) -> Option<Vec<u32>> {
|
||||||
let bitsOffset = 0;
|
let mut bitsOffset = 0;
|
||||||
while bitsOffset < self.bits.len() && self.bits[bitsOffset] == 0 {
|
while bitsOffset < self.bits.len() && self.bits[bitsOffset] == 0 {
|
||||||
bitsOffset += 1;
|
bitsOffset += 1;
|
||||||
}
|
}
|
||||||
@@ -1196,10 +1218,10 @@ impl BitMatrix {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let y = bitsOffset / self.rowSize;
|
let y = bitsOffset / self.rowSize;
|
||||||
let x = (bitsOffset % self.rowSize) * 32;
|
let mut x = (bitsOffset % self.rowSize) * 32;
|
||||||
|
|
||||||
let theBits = self.bits[bitsOffset];
|
let theBits = self.bits[bitsOffset];
|
||||||
let bit = 0;
|
let mut bit = 0;
|
||||||
while (theBits << (31 - bit)) == 0 {
|
while (theBits << (31 - bit)) == 0 {
|
||||||
bit += 1;
|
bit += 1;
|
||||||
}
|
}
|
||||||
@@ -1208,7 +1230,7 @@ impl BitMatrix {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn getBottomRightOnBit(&self) -> Option<Vec<u32>> {
|
pub fn getBottomRightOnBit(&self) -> Option<Vec<u32>> {
|
||||||
let bitsOffset = self.bits.len() - 1;
|
let mut bitsOffset = self.bits.len() - 1;
|
||||||
while bitsOffset >= 0 && self.bits[bitsOffset] == 0 {
|
while bitsOffset >= 0 && self.bits[bitsOffset] == 0 {
|
||||||
bitsOffset -= 1;
|
bitsOffset -= 1;
|
||||||
}
|
}
|
||||||
@@ -1217,10 +1239,10 @@ impl BitMatrix {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let y = bitsOffset / self.rowSize;
|
let y = bitsOffset / self.rowSize;
|
||||||
let x = (bitsOffset % self.rowSize) * 32;
|
let mut x = (bitsOffset % self.rowSize) * 32;
|
||||||
|
|
||||||
let theBits = self.bits[bitsOffset];
|
let theBits = self.bits[bitsOffset];
|
||||||
let bit = 31;
|
let mut bit = 31;
|
||||||
while (theBits >> bit) == 0 {
|
while (theBits >> bit) == 0 {
|
||||||
bit -= 1;
|
bit -= 1;
|
||||||
}
|
}
|
||||||
@@ -1292,7 +1314,8 @@ impl BitMatrix {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
fn buildToString(&self, setString: &str, unsetString: &str, lineSeparator: &str) -> String {
|
fn buildToString(&self, setString: &str, unsetString: &str, lineSeparator: &str) -> String {
|
||||||
let result = String::with_capacity((self.height * (self.width + 1)).try_into().unwrap());
|
let mut result =
|
||||||
|
String::with_capacity((self.height * (self.width + 1)).try_into().unwrap());
|
||||||
for y in 0..self.height {
|
for y in 0..self.height {
|
||||||
//for (int y = 0; y < height; y++) {
|
//for (int y = 0; y < height; y++) {
|
||||||
for x in 0..self.width {
|
for x in 0..self.width {
|
||||||
@@ -1493,12 +1516,14 @@ impl BitSource {
|
|||||||
* bits of the int
|
* bits of the int
|
||||||
* @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available
|
* @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available
|
||||||
*/
|
*/
|
||||||
pub fn readBits(&self, numBits: usize) -> Result<u32, IllegalArgumentException> {
|
pub fn readBits(&mut self, numBits: usize) -> Result<u32, IllegalArgumentException> {
|
||||||
if numBits < 1 || numBits > 32 || numBits > self.available() {
|
if numBits < 1 || numBits > 32 || numBits > self.available() {
|
||||||
return Err(IllegalArgumentException::new(&numBits.to_string()));
|
return Err(IllegalArgumentException::new(&numBits.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = 0;
|
let mut result = 0;
|
||||||
|
|
||||||
|
let mut numBits = numBits;
|
||||||
|
|
||||||
// First, read remainder from current byte
|
// First, read remainder from current byte
|
||||||
if self.bitOffset > 0 {
|
if self.bitOffset > 0 {
|
||||||
|
|||||||
@@ -25,28 +25,36 @@ use super::{GenericGF, GenericGFPoly};
|
|||||||
* Tests {@link GenericGFPoly}.
|
* Tests {@link GenericGFPoly}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const FIELD: GenericGF = super::QR_CODE_FIELD_256;
|
//const FIELD: GenericGF = super::QR_CODE_FIELD_256;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testPolynomialString() {
|
fn testPolynomialString() {
|
||||||
assert_eq!("0", FIELD.getZero().to_string());
|
let FIELD = super::get_predefined_genericgf(super::PredefinedGenericGF::QrCodeField256);
|
||||||
|
let fz = super::GenericGFPoly::new(FIELD.clone(), &vec![0;0]).unwrap();
|
||||||
|
|
||||||
|
assert_eq!("0", fz.getZero().to_string());
|
||||||
assert_eq!("-1", FIELD.buildMonomial(0, -1).to_string());
|
assert_eq!("-1", FIELD.buildMonomial(0, -1).to_string());
|
||||||
let p = GenericGFPoly::new(Box::new(FIELD), &vec![3, 0, -2, 1, 1]).unwrap();
|
let p = GenericGFPoly::new(FIELD.clone(), &vec![3, 0, -2, 1, 1]).unwrap();
|
||||||
assert_eq!("a^25x^4 - ax^2 + x + 1", p.to_string());
|
assert_eq!("a^25x^4 - ax^2 + x + 1", p.to_string());
|
||||||
let p = GenericGFPoly::new(Box::new(FIELD), &vec![3]).unwrap();
|
let p = GenericGFPoly::new(FIELD.clone(), &vec![3]).unwrap();
|
||||||
assert_eq!("a^25", p.to_string());
|
assert_eq!("a^25", p.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testZero() {
|
fn testZero() {
|
||||||
assert_eq!(*FIELD.getZero(), *FIELD.buildMonomial(1, 0));
|
let FIELD = super::get_predefined_genericgf(super::PredefinedGenericGF::QrCodeField256);
|
||||||
|
let fz = super::GenericGFPoly::new(FIELD.clone(), &vec![0;0]).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(fz.getZero(), FIELD.buildMonomial(1, 0));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*FIELD.getZero(),
|
fz.getZero(),
|
||||||
*FIELD.buildMonomial(1, 2).multiply_with_scalar(0)
|
FIELD.buildMonomial(1, 2).multiply_with_scalar(0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testEvaluate() {
|
fn testEvaluate() {
|
||||||
|
let FIELD = super::get_predefined_genericgf(super::PredefinedGenericGF::QrCodeField256);
|
||||||
|
|
||||||
assert_eq!(3, FIELD.buildMonomial(0, 3).evaluateAt(0));
|
assert_eq!(3, FIELD.buildMonomial(0, 3).evaluateAt(0));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,14 +36,15 @@ const DECODER_TEST_ITERATIONS: i32 = 10;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testDataMatrix() {
|
fn testDataMatrix() {
|
||||||
|
let dm256 = super::get_predefined_genericgf(super::PredefinedGenericGF::DataMatrixField256);
|
||||||
// real life test cases
|
// real life test cases
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&super::DATA_MATRIX_FIELD_256,
|
&dm256,
|
||||||
&vec![142, 164, 186],
|
&vec![142, 164, 186],
|
||||||
&vec![114, 25, 5, 88, 102],
|
&vec![114, 25, 5, 88, 102],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&super::DATA_MATRIX_FIELD_256,
|
&dm256,
|
||||||
&vec![
|
&vec![
|
||||||
0x69, 0x75, 0x75, 0x71, 0x3B, 0x30, 0x30, 0x64, 0x70, 0x65, 0x66, 0x2F, 0x68, 0x70,
|
0x69, 0x75, 0x75, 0x71, 0x3B, 0x30, 0x30, 0x64, 0x70, 0x65, 0x66, 0x2F, 0x68, 0x70,
|
||||||
0x70, 0x68, 0x6D, 0x66, 0x2F, 0x64, 0x70, 0x6E, 0x30, 0x71, 0x30, 0x7B, 0x79, 0x6A,
|
0x70, 0x68, 0x6D, 0x66, 0x2F, 0x64, 0x70, 0x6E, 0x30, 0x71, 0x30, 0x7B, 0x79, 0x6A,
|
||||||
@@ -55,16 +56,17 @@ fn testDataMatrix() {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
// synthetic test cases
|
// synthetic test cases
|
||||||
testEncodeDecodeRandom(super::DATA_MATRIX_FIELD_256, 10, 240);
|
testEncodeDecodeRandom(dm256.clone(), 10, 240);
|
||||||
testEncodeDecodeRandom(super::DATA_MATRIX_FIELD_256, 128, 127);
|
testEncodeDecodeRandom(dm256.clone(), 128, 127);
|
||||||
testEncodeDecodeRandom(super::DATA_MATRIX_FIELD_256, 220, 35);
|
testEncodeDecodeRandom(dm256.clone(), 220, 35);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testQRCode() {
|
fn testQRCode() {
|
||||||
|
let qrcf256 = super::get_predefined_genericgf(super::PredefinedGenericGF::QrCodeField256);
|
||||||
// Test case from example given in ISO 18004, Annex I
|
// Test case from example given in ISO 18004, Annex I
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&super::QR_CODE_FIELD_256,
|
&qrcf256,
|
||||||
&vec![
|
&vec![
|
||||||
0x10, 0x20, 0x0C, 0x56, 0x61, 0x80, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11,
|
0x10, 0x20, 0x0C, 0x56, 0x61, 0x80, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11,
|
||||||
0xEC, 0x11,
|
0xEC, 0x11,
|
||||||
@@ -72,7 +74,7 @@ fn testQRCode() {
|
|||||||
&vec![0xA5, 0x24, 0xD4, 0xC1, 0xED, 0x36, 0xC7, 0x87, 0x2C, 0x55],
|
&vec![0xA5, 0x24, 0xD4, 0xC1, 0xED, 0x36, 0xC7, 0x87, 0x2C, 0x55],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&super::QR_CODE_FIELD_256,
|
&qrcf256,
|
||||||
&vec![
|
&vec![
|
||||||
0x72, 0x67, 0x2F, 0x77, 0x69, 0x6B, 0x69, 0x2F, 0x4D, 0x61, 0x69, 0x6E, 0x5F, 0x50,
|
0x72, 0x67, 0x2F, 0x77, 0x69, 0x6B, 0x69, 0x2F, 0x4D, 0x61, 0x69, 0x6E, 0x5F, 0x50,
|
||||||
0x61, 0x67, 0x65, 0x3B, 0x3B, 0x00, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11,
|
0x61, 0x67, 0x65, 0x3B, 0x3B, 0x00, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11,
|
||||||
@@ -85,36 +87,37 @@ fn testQRCode() {
|
|||||||
);
|
);
|
||||||
// real life test cases
|
// real life test cases
|
||||||
// synthetic test cases
|
// synthetic test cases
|
||||||
testEncodeDecodeRandom(super::QR_CODE_FIELD_256, 10, 240);
|
testEncodeDecodeRandom(qrcf256.clone(), 10, 240);
|
||||||
testEncodeDecodeRandom(super::QR_CODE_FIELD_256, 128, 127);
|
testEncodeDecodeRandom(qrcf256.clone(), 128, 127);
|
||||||
testEncodeDecodeRandom(super::QR_CODE_FIELD_256, 220, 35);
|
testEncodeDecodeRandom(qrcf256.clone(), 220, 35);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testAztec() {
|
fn testAztec() {
|
||||||
// real life test cases
|
// real life test cases
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&super::AZTEC_PARAM,
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecParam),
|
||||||
&vec![0x5, 0x6],
|
&vec![0x5, 0x6],
|
||||||
&vec![0x3, 0x2, 0xB, 0xB, 0x7],
|
&vec![0x3, 0x2, 0xB, 0xB, 0x7],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&super::AZTEC_PARAM,
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecParam),
|
||||||
&vec![0x0, 0x0, 0x0, 0x9],
|
&vec![0x0, 0x0, 0x0, 0x9],
|
||||||
&vec![0xA, 0xD, 0x8, 0x6, 0x5, 0x6],
|
&vec![0xA, 0xD, 0x8, 0x6, 0x5, 0x6],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&super::AZTEC_PARAM,
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecParam),
|
||||||
&vec![0x2, 0x8, 0x8, 0x7],
|
&vec![0x2, 0x8, 0x8, 0x7],
|
||||||
&vec![0xE, 0xC, 0xA, 0x9, 0x6, 0x8],
|
&vec![0xE, 0xC, 0xA, 0x9, 0x6, 0x8],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&super::AZTEC_DATA_6,
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData6),
|
||||||
&vec![0x9, 0x32, 0x1, 0x29, 0x2F, 0x2, 0x27, 0x25, 0x1, 0x1B],
|
&vec![0x9, 0x32, 0x1, 0x29, 0x2F, 0x2, 0x27, 0x25, 0x1, 0x1B],
|
||||||
&vec![0x2C, 0x2, 0xD, 0xD, 0xA, 0x16, 0x28, 0x9, 0x22, 0xA, 0x14],
|
&vec![0x2C, 0x2, 0xD, 0xD, 0xA, 0x16, 0x28, 0x9, 0x22, 0xA, 0x14],
|
||||||
);
|
);
|
||||||
|
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&super::AZTEC_DATA_8,
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData8),
|
||||||
&vec![
|
&vec![
|
||||||
0xE0, 0x86, 0x42, 0x98, 0xE8, 0x4A, 0x96, 0xC6, 0xB9, 0xF0, 0x8C, 0xA7, 0x4A, 0xDA,
|
0xE0, 0x86, 0x42, 0x98, 0xE8, 0x4A, 0x96, 0xC6, 0xB9, 0xF0, 0x8C, 0xA7, 0x4A, 0xDA,
|
||||||
0xF8, 0xCE, 0xB7, 0xDE, 0x88, 0x64, 0x29, 0x8E, 0x84, 0xA9, 0x6C, 0x6B, 0x9F, 0x08,
|
0xF8, 0xCE, 0xB7, 0xDE, 0x88, 0x64, 0x29, 0x8E, 0x84, 0xA9, 0x6C, 0x6B, 0x9F, 0x08,
|
||||||
@@ -130,7 +133,7 @@ fn testAztec() {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&super::AZTEC_DATA_10,
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData10),
|
||||||
&vec![
|
&vec![
|
||||||
0x15C, 0x1E1, 0x2D5, 0x02E, 0x048, 0x1E2, 0x037, 0x0CD, 0x02E, 0x056, 0x26A, 0x281,
|
0x15C, 0x1E1, 0x2D5, 0x02E, 0x048, 0x1E2, 0x037, 0x0CD, 0x02E, 0x056, 0x26A, 0x281,
|
||||||
0x1C2, 0x1A6, 0x296, 0x045, 0x041, 0x0AA, 0x095, 0x2CE, 0x003, 0x38F, 0x2CD, 0x1A2,
|
0x1C2, 0x1A6, 0x296, 0x045, 0x041, 0x0AA, 0x095, 0x2CE, 0x003, 0x38F, 0x2CD, 0x1A2,
|
||||||
@@ -177,7 +180,7 @@ fn testAztec() {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
testEncodeDecode(
|
||||||
&super::AZTEC_DATA_12,
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData12),
|
||||||
&vec![
|
&vec![
|
||||||
0x571, 0xE1B, 0x542, 0xE12, 0x1E2, 0x0DC, 0xCD0, 0xB85, 0x69A, 0xA81, 0x709, 0xA6A,
|
0x571, 0xE1B, 0x542, 0xE12, 0x1E2, 0x0DC, 0xCD0, 0xB85, 0x69A, 0xA81, 0x709, 0xA6A,
|
||||||
0x584, 0x510, 0x4AA, 0x256, 0xCE0, 0x0F8, 0xFB3, 0x5A2, 0x0D9, 0xAD1, 0x389, 0x09C,
|
0x584, 0x510, 0x4AA, 0x256, 0xCE0, 0x0F8, 0xFB3, 0x5A2, 0x0D9, 0xAD1, 0x389, 0x09C,
|
||||||
@@ -324,15 +327,21 @@ fn testAztec() {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
// synthetic test cases
|
// synthetic test cases
|
||||||
testEncodeDecodeRandom(super::AZTEC_PARAM, 2, 5); // compact mode message
|
let azp = super::get_predefined_genericgf(super::PredefinedGenericGF::AztecParam);
|
||||||
testEncodeDecodeRandom(super::AZTEC_PARAM, 4, 6); // full mode message
|
let azd6 = super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData6);
|
||||||
testEncodeDecodeRandom(super::AZTEC_DATA_6, 10, 7);
|
let azd8 = super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData8);
|
||||||
testEncodeDecodeRandom(super::AZTEC_DATA_6, 20, 12);
|
let azd10 = super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData10);
|
||||||
testEncodeDecodeRandom(super::AZTEC_DATA_8, 20, 11);
|
let azd12 = super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData12);
|
||||||
testEncodeDecodeRandom(super::AZTEC_DATA_8, 128, 127);
|
|
||||||
testEncodeDecodeRandom(super::AZTEC_DATA_10, 128, 128);
|
testEncodeDecodeRandom(azp.clone(), 2, 5); // compact mode message
|
||||||
testEncodeDecodeRandom(super::AZTEC_DATA_10, 768, 255);
|
testEncodeDecodeRandom(azp.clone(), 4, 6); // full mode message
|
||||||
testEncodeDecodeRandom(super::AZTEC_DATA_12, 3072, 1023);
|
testEncodeDecodeRandom(azd6.clone(), 10, 7);
|
||||||
|
testEncodeDecodeRandom(azd6.clone(), 20, 12);
|
||||||
|
testEncodeDecodeRandom(azd8.clone(), 20, 11);
|
||||||
|
testEncodeDecodeRandom(azd8.clone(), 128, 127);
|
||||||
|
testEncodeDecodeRandom(azd10.clone(), 128, 128);
|
||||||
|
testEncodeDecodeRandom(azd10.clone(), 768, 255);
|
||||||
|
testEncodeDecodeRandom(azd12.clone(), 3072, 1023);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn corrupt(received: &mut Vec<i32>, howMany: i32, random: &mut rand::rngs::ThreadRng, max: i32) {
|
fn corrupt(received: &mut Vec<i32>, howMany: i32, random: &mut rand::rngs::ThreadRng, max: i32) {
|
||||||
@@ -367,7 +376,7 @@ fn testEncodeDecodeRandom(field: GenericGF, dataSize: usize, ecSize: usize) {
|
|||||||
"Invalid ECC size for {}",
|
"Invalid ECC size for {}",
|
||||||
field
|
field
|
||||||
);
|
);
|
||||||
let encoder = ReedSolomonEncoder::new(Box::new(field.clone()));
|
let mut encoder = ReedSolomonEncoder::new(field.clone());
|
||||||
let mut message = Vec::with_capacity(dataSize + ecSize);
|
let mut message = Vec::with_capacity(dataSize + ecSize);
|
||||||
let mut dataWords: Vec<i32> = Vec::with_capacity(dataSize);
|
let mut dataWords: Vec<i32> = Vec::with_capacity(dataSize);
|
||||||
let mut ecWords = Vec::with_capacity(ecSize);
|
let mut ecWords = Vec::with_capacity(ecSize);
|
||||||
@@ -401,7 +410,7 @@ fn testEncodeDecode(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn testEncoder(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
fn testEncoder(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
||||||
let encoder = ReedSolomonEncoder::new(Box::new(field.clone()));
|
let mut encoder = ReedSolomonEncoder::new(field.clone());
|
||||||
let mut messageExpected = Vec::with_capacity(dataWords.len() + ecWords.len());
|
let mut messageExpected = Vec::with_capacity(dataWords.len() + ecWords.len());
|
||||||
let mut message = Vec::with_capacity(dataWords.len() + ecWords.len());
|
let mut message = Vec::with_capacity(dataWords.len() + ecWords.len());
|
||||||
messageExpected[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]);
|
messageExpected[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]);
|
||||||
|
|||||||
@@ -69,14 +69,37 @@ impl fmt::Display for ReedSolomonException {
|
|||||||
|
|
||||||
//package com.google.zxing.common.reedsolomon;
|
//package com.google.zxing.common.reedsolomon;
|
||||||
|
|
||||||
pub const AZTEC_DATA_12: GenericGF = GenericGF::new(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1
|
// pub const AZTEC_DATA_12: GenericGF = GenericGF::new(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1
|
||||||
pub const AZTEC_DATA_10: GenericGF = GenericGF::new(0x409, 1024, 1); // x^10 + x^3 + 1
|
// pub const AZTEC_DATA_10: GenericGF = GenericGF::new(0x409, 1024, 1); // x^10 + x^3 + 1
|
||||||
pub const AZTEC_DATA_6: GenericGF = GenericGF::new(0x43, 64, 1); // x^6 + x + 1
|
// pub const AZTEC_DATA_6: GenericGF = GenericGF::new(0x43, 64, 1); // x^6 + x + 1
|
||||||
pub const AZTEC_PARAM: GenericGF = GenericGF::new(0x13, 16, 1); // x^4 + x + 1
|
// pub const AZTEC_PARAM: GenericGF = GenericGF::new(0x13, 16, 1); // x^4 + x + 1
|
||||||
pub const QR_CODE_FIELD_256: GenericGF = GenericGF::new(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1
|
// pub const QR_CODE_FIELD_256: GenericGF = GenericGF::new(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1
|
||||||
pub const DATA_MATRIX_FIELD_256: GenericGF = GenericGF::new(0x012D, 256, 1); // x^8 + x^5 + x^3 + x^2 + 1
|
// pub const DATA_MATRIX_FIELD_256: GenericGF = GenericGF::new(0x012D, 256, 1); // x^8 + x^5 + x^3 + x^2 + 1
|
||||||
pub const AZTEC_DATA_8: GenericGF = DATA_MATRIX_FIELD_256;
|
// pub const AZTEC_DATA_8: GenericGF = DATA_MATRIX_FIELD_256;
|
||||||
pub const MAXICODE_FIELD_64: GenericGF = AZTEC_DATA_6;
|
// pub const MAXICODE_FIELD_64: GenericGF = AZTEC_DATA_6;
|
||||||
|
|
||||||
|
pub enum PredefinedGenericGF {
|
||||||
|
AztecData12,
|
||||||
|
AztecData10,
|
||||||
|
AztecData6,
|
||||||
|
AztecParam,
|
||||||
|
QrCodeField256,
|
||||||
|
DataMatrixField256,
|
||||||
|
AztecData8,
|
||||||
|
MaxicodeField64
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replacement for old const options, has the downside of generating new versions whenever one is requested.
|
||||||
|
pub fn get_predefined_genericgf(request:PredefinedGenericGF) -> GenericGF {
|
||||||
|
match request {
|
||||||
|
PredefinedGenericGF::AztecData12 => GenericGF::new(0x1069, 4096, 1), // x^12 + x^6 + x^5 + x^3 + 1,
|
||||||
|
PredefinedGenericGF::AztecData10 => GenericGF::new(0x409, 1024, 1), // x^10 + x^3 + 1
|
||||||
|
PredefinedGenericGF::AztecData6 | PredefinedGenericGF::MaxicodeField64 => GenericGF::new(0x43, 64, 1), // x^6 + x + 1
|
||||||
|
PredefinedGenericGF::AztecParam => GenericGF::new(0x13, 16, 1), // x^4 + x + 1
|
||||||
|
PredefinedGenericGF::QrCodeField256 => GenericGF::new(0x011D, 256, 0), // x^8 + x^4 + x^3 + x^2 + 1
|
||||||
|
PredefinedGenericGF::DataMatrixField256 | PredefinedGenericGF::AztecData8 => GenericGF::new(0x012D, 256, 1), // x^8 + x^5 + x^3 + x^2 + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>This class contains utility methods for performing mathematical operations over
|
* <p>This class contains utility methods for performing mathematical operations over
|
||||||
@@ -324,8 +347,7 @@ impl GenericGFPoly {
|
|||||||
let mut new_coefficients =
|
let mut new_coefficients =
|
||||||
Vec::with_capacity(coefficientsLength - firstNonZero);
|
Vec::with_capacity(coefficientsLength - firstNonZero);
|
||||||
let l = new_coefficients.len();
|
let l = new_coefficients.len();
|
||||||
new_coefficients[0..l]
|
new_coefficients[0..l].clone_from_slice(&coefficients[firstNonZero..l]);
|
||||||
.clone_from_slice(&coefficients[firstNonZero..l]);
|
|
||||||
// System.arraycopy(coefficients,
|
// System.arraycopy(coefficients,
|
||||||
// firstNonZero,
|
// firstNonZero,
|
||||||
// this.coefficients,
|
// this.coefficients,
|
||||||
@@ -594,7 +616,8 @@ impl fmt::Display for GenericGFPoly {
|
|||||||
} else {
|
} else {
|
||||||
result.push_str("a^");
|
result.push_str("a^");
|
||||||
result.push_str(&format!("{}", alphaPower));
|
result.push_str(&format!("{}", alphaPower));
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if degree != 0 {
|
if degree != 0 {
|
||||||
if degree == 1 {
|
if degree == 1 {
|
||||||
@@ -655,9 +678,7 @@ pub struct ReedSolomonDecoder {
|
|||||||
|
|
||||||
impl ReedSolomonDecoder {
|
impl ReedSolomonDecoder {
|
||||||
pub fn new(field: GenericGF) -> Self {
|
pub fn new(field: GenericGF) -> Self {
|
||||||
Self {
|
Self { field: field }
|
||||||
field: field,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -726,8 +747,8 @@ impl ReedSolomonDecoder {
|
|||||||
R: usize,
|
R: usize,
|
||||||
) -> Result<Vec<GenericGFPoly>, ReedSolomonException> {
|
) -> Result<Vec<GenericGFPoly>, ReedSolomonException> {
|
||||||
// Assume a's degree is >= b's
|
// Assume a's degree is >= b's
|
||||||
let mut a = a;
|
let mut a = a.clone();
|
||||||
let mut b = b;
|
let mut b = b.clone();
|
||||||
if a.getDegree() < b.getDegree() {
|
if a.getDegree() < b.getDegree() {
|
||||||
let temp = a;
|
let temp = a;
|
||||||
a = b;
|
a = b;
|
||||||
@@ -738,8 +759,8 @@ impl ReedSolomonDecoder {
|
|||||||
let mut r = b;
|
let mut r = b;
|
||||||
// let tLast = self.field.getZero();
|
// let tLast = self.field.getZero();
|
||||||
// let t = self.field.getOne();
|
// let t = self.field.getOne();
|
||||||
let mut tLast = a.getZero();
|
let mut tLast = rLast.getZero();
|
||||||
let mut t = a.getOne();
|
let mut t = rLast.getOne();
|
||||||
|
|
||||||
// Run Euclidean algorithm until r's degree is less than R/2
|
// Run Euclidean algorithm until r's degree is less than R/2
|
||||||
while 2 * r.getDegree() >= R {
|
while 2 * r.getDegree() >= R {
|
||||||
@@ -754,7 +775,7 @@ impl ReedSolomonDecoder {
|
|||||||
return Err(ReedSolomonException::new("r_{i-1} was zero"));
|
return Err(ReedSolomonException::new("r_{i-1} was zero"));
|
||||||
}
|
}
|
||||||
r = rLastLast;
|
r = rLastLast;
|
||||||
let q = a.getZero();
|
let mut q = r.getZero();
|
||||||
let denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());
|
let denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());
|
||||||
let dltInverse = match self.field.inverse(denominatorLeadingTerm) {
|
let dltInverse = match self.field.inverse(denominatorLeadingTerm) {
|
||||||
Ok(inv) => inv,
|
Ok(inv) => inv,
|
||||||
@@ -769,11 +790,11 @@ impl ReedSolomonDecoder {
|
|||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(err) => return Err(ReedSolomonException::new("IllegalArgumentException")),
|
Err(err) => return Err(ReedSolomonException::new("IllegalArgumentException")),
|
||||||
};
|
};
|
||||||
r = match r.addOrSubtract(match rLast.multiplyByMonomial(degreeDiff, scale) {
|
r = match r.addOrSubtract(&match rLast.multiplyByMonomial(degreeDiff, scale) {
|
||||||
Ok(res) => &res,
|
Ok(res) => res,
|
||||||
Err(err) => return Err(ReedSolomonException::new("IllegalArgumentException")),
|
Err(err) => return Err(ReedSolomonException::new("IllegalArgumentException")),
|
||||||
}) {
|
}) {
|
||||||
Ok(res) =>&res,
|
Ok(res) => res,
|
||||||
Err(err) => return Err(ReedSolomonException::new("IllegalArgumentException")),
|
Err(err) => return Err(ReedSolomonException::new("IllegalArgumentException")),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -821,7 +842,7 @@ impl ReedSolomonDecoder {
|
|||||||
return Ok(vec![errorLocator.getCoefficient(1).try_into().unwrap()]);
|
return Ok(vec![errorLocator.getCoefficient(1).try_into().unwrap()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let result: Vec<usize> = Vec::with_capacity(numErrors);
|
let mut result: Vec<usize> = Vec::with_capacity(numErrors);
|
||||||
let mut e = 0;
|
let mut e = 0;
|
||||||
for i in 1..self.field.getSize() {
|
for i in 1..self.field.getSize() {
|
||||||
//for (int i = 1; i < field.getSize() && e < numErrors; i++) {
|
//for (int i = 1; i < field.getSize() && e < numErrors; i++) {
|
||||||
@@ -851,11 +872,14 @@ impl ReedSolomonDecoder {
|
|||||||
) -> Vec<i32> {
|
) -> Vec<i32> {
|
||||||
// This is directly applying Forney's Formula
|
// This is directly applying Forney's Formula
|
||||||
let s = errorLocations.len();
|
let s = errorLocations.len();
|
||||||
let result = Vec::with_capacity(s);
|
let mut result = Vec::with_capacity(s);
|
||||||
for i in 0..s {
|
for i in 0..s {
|
||||||
//for (int i = 0; i < s; i++) {
|
//for (int i = 0; i < s; i++) {
|
||||||
let xiInverse = self.field.inverse(errorLocations[i].try_into().unwrap());
|
let xiInverse = self
|
||||||
let denominator = 1;
|
.field
|
||||||
|
.inverse(errorLocations[i].try_into().unwrap())
|
||||||
|
.unwrap();
|
||||||
|
let mut denominator = 1;
|
||||||
for j in 0..s {
|
for j in 0..s {
|
||||||
//for (int j = 0; j < s; j++) {
|
//for (int j = 0; j < s; j++) {
|
||||||
if i != j {
|
if i != j {
|
||||||
@@ -865,7 +889,7 @@ impl ReedSolomonDecoder {
|
|||||||
// Below is a funny-looking workaround from Steven Parkes
|
// Below is a funny-looking workaround from Steven Parkes
|
||||||
let term = self
|
let term = self
|
||||||
.field
|
.field
|
||||||
.multiply(errorLocations[j].try_into().unwrap(), xiInverse.unwrap());
|
.multiply(errorLocations[j].try_into().unwrap(), xiInverse);
|
||||||
let termPlus1 = if (term & 0x1) == 0 {
|
let termPlus1 = if (term & 0x1) == 0 {
|
||||||
term | 1
|
term | 1
|
||||||
} else {
|
} else {
|
||||||
@@ -875,11 +899,11 @@ impl ReedSolomonDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
result[i] = self.field.multiply(
|
result[i] = self.field.multiply(
|
||||||
errorEvaluator.evaluateAt(xiInverse.unwrap().try_into().unwrap()),
|
errorEvaluator.evaluateAt(xiInverse.try_into().unwrap()),
|
||||||
self.field.inverse(denominator).unwrap(),
|
self.field.inverse(denominator).unwrap(),
|
||||||
);
|
);
|
||||||
if self.field.getGeneratorBase() != 0 {
|
if self.field.getGeneratorBase() != 0 {
|
||||||
result[i] = self.field.multiply(result[i], xiInverse.unwrap());
|
result[i] = self.field.multiply(result[i], xiInverse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -921,23 +945,25 @@ pub struct ReedSolomonEncoder {
|
|||||||
impl ReedSolomonEncoder {
|
impl ReedSolomonEncoder {
|
||||||
pub fn new(field: GenericGF) -> Self {
|
pub fn new(field: GenericGF) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
cachedGenerators: vec![GenericGFPoly::new(field.clone(), &vec![1]).unwrap()],
|
||||||
field: field,
|
field: field,
|
||||||
cachedGenerators: vec![GenericGFPoly::new(field, &vec![1]).unwrap()],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildGenerator(&self, degree: usize) -> GenericGFPoly {
|
fn buildGenerator(&mut self, degree: usize) -> &GenericGFPoly {
|
||||||
if degree >= self.cachedGenerators.len() {
|
if degree >= self.cachedGenerators.len() {
|
||||||
let mut lastGenerator = self
|
let mut lastGenerator = self
|
||||||
.cachedGenerators
|
.cachedGenerators
|
||||||
.get(self.cachedGenerators.len() - 1)
|
.get(self.cachedGenerators.len() - 1)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for d in self.cachedGenerators.len()..=degree {
|
let cg_len = self.cachedGenerators.len();
|
||||||
|
let mut nextGenerator;
|
||||||
|
for d in cg_len..=degree {
|
||||||
//for (int d = cachedGenerators.size(); d <= degree; d++) {
|
//for (int d = cachedGenerators.size(); d <= degree; d++) {
|
||||||
let nextGenerator = lastGenerator
|
nextGenerator = lastGenerator
|
||||||
.multiply(
|
.multiply(
|
||||||
&GenericGFPoly::new(
|
&GenericGFPoly::new(
|
||||||
self.field,
|
self.field.clone(),
|
||||||
&vec![
|
&vec![
|
||||||
1,
|
1,
|
||||||
self.field.exp(d as i32 - 1 + self.field.getGeneratorBase()),
|
self.field.exp(d as i32 - 1 + self.field.getGeneratorBase()),
|
||||||
@@ -947,14 +973,16 @@ impl ReedSolomonEncoder {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.cachedGenerators.push(nextGenerator);
|
self.cachedGenerators.push(nextGenerator);
|
||||||
lastGenerator = &nextGenerator;
|
lastGenerator = self.cachedGenerators.get(d).unwrap();
|
||||||
|
//lastGenerator = &nextGenerator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *self.cachedGenerators.get(degree).unwrap();
|
let rv = self.cachedGenerators.get(degree).unwrap();
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode(
|
pub fn encode(
|
||||||
&self,
|
&mut self,
|
||||||
toEncode: &mut Vec<i32>,
|
toEncode: &mut Vec<i32>,
|
||||||
ecBytes: usize,
|
ecBytes: usize,
|
||||||
) -> Result<(), IllegalArgumentException> {
|
) -> Result<(), IllegalArgumentException> {
|
||||||
@@ -965,13 +993,14 @@ impl ReedSolomonEncoder {
|
|||||||
if dataBytes <= 0 {
|
if dataBytes <= 0 {
|
||||||
return Err(IllegalArgumentException::new("No data bytes provided"));
|
return Err(IllegalArgumentException::new("No data bytes provided"));
|
||||||
}
|
}
|
||||||
|
let fld = self.field.clone();
|
||||||
let generator = self.buildGenerator(ecBytes);
|
let generator = self.buildGenerator(ecBytes);
|
||||||
let mut infoCoefficients: Vec<i32> = Vec::with_capacity(dataBytes);
|
let mut infoCoefficients: Vec<i32> = Vec::with_capacity(dataBytes);
|
||||||
infoCoefficients[0..dataBytes].clone_from_slice(&toEncode[0..dataBytes]);
|
infoCoefficients[0..dataBytes].clone_from_slice(&toEncode[0..dataBytes]);
|
||||||
//System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);
|
//System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);
|
||||||
let mut info = GenericGFPoly::new(self.field.clone(), &infoCoefficients)?;
|
let mut info = GenericGFPoly::new(fld, &infoCoefficients)?;
|
||||||
info = info.multiplyByMonomial(ecBytes.try_into().unwrap(), 1)?;
|
info = info.multiplyByMonomial(ecBytes.try_into().unwrap(), 1)?;
|
||||||
let remainder = info.divide(&generator)?[1];
|
let remainder = &info.divide(&generator)?[1];
|
||||||
let coefficients = remainder.getCoefficients();
|
let coefficients = remainder.getCoefficients();
|
||||||
let numZeroCoefficients = ecBytes - coefficients.len();
|
let numZeroCoefficients = ecBytes - coefficients.len();
|
||||||
for i in 0..numZeroCoefficients {
|
for i in 0..numZeroCoefficients {
|
||||||
|
|||||||
192
src/lib.rs
192
src/lib.rs
@@ -489,7 +489,7 @@ pub trait Reader {
|
|||||||
* @throws ChecksumException if a potential barcode is found but does not pass its checksum
|
* @throws ChecksumException if a potential barcode is found but does not pass its checksum
|
||||||
* @throws FormatException if a potential barcode is found but format is invalid
|
* @throws FormatException if a potential barcode is found but format is invalid
|
||||||
*/
|
*/
|
||||||
fn decode(image: BinaryBitmap) -> Result<RXingResult<'static>, ReaderDecodeException>;
|
fn decode(image: BinaryBitmap) -> Result<RXingResult, ReaderDecodeException>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locates and decodes a barcode in some format within an image. This method also accepts
|
* Locates and decodes a barcode in some format within an image. This method also accepts
|
||||||
@@ -508,7 +508,7 @@ pub trait Reader {
|
|||||||
fn decode_with_hints<T>(
|
fn decode_with_hints<T>(
|
||||||
image: BinaryBitmap,
|
image: BinaryBitmap,
|
||||||
hints: HashMap<DecodeHintType, T>,
|
hints: HashMap<DecodeHintType, T>,
|
||||||
) -> Result<RXingResult<'static>, ReaderDecodeException>;
|
) -> Result<RXingResult, ReaderDecodeException>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets any internal state the implementation has after a decode, to prepare it
|
* Resets any internal state the implementation has after a decode, to prepare it
|
||||||
@@ -647,16 +647,16 @@ pub enum RXingResultMetadataType {
|
|||||||
*
|
*
|
||||||
* @author Sean Owen
|
* @author Sean Owen
|
||||||
*/
|
*/
|
||||||
pub struct RXingResult<'a> {
|
pub struct RXingResult {
|
||||||
text: String,
|
text: String,
|
||||||
rawBytes: Vec<u8>,
|
rawBytes: Vec<u8>,
|
||||||
numBits: usize,
|
numBits: usize,
|
||||||
resultPoints: Vec<RXingResultPoint>,
|
resultPoints: Vec<RXingResultPoint>,
|
||||||
format: BarcodeFormat,
|
format: BarcodeFormat,
|
||||||
resultMetadata: Option<HashMap<RXingResultMetadataType, &'a dyn Any>>,
|
resultMetadata: HashMap<RXingResultMetadataType, String>,
|
||||||
timestamp: u128,
|
timestamp: u128,
|
||||||
}
|
}
|
||||||
impl RXingResult<'_> {
|
impl RXingResult {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
text: &str,
|
text: &str,
|
||||||
rawBytes: Vec<u8>,
|
rawBytes: Vec<u8>,
|
||||||
@@ -682,10 +682,11 @@ impl RXingResult<'_> {
|
|||||||
format: BarcodeFormat,
|
format: BarcodeFormat,
|
||||||
timestamp: u128,
|
timestamp: u128,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let l = rawBytes.len();
|
||||||
Self::new_complex(
|
Self::new_complex(
|
||||||
text,
|
text,
|
||||||
rawBytes,
|
rawBytes,
|
||||||
8 * rawBytes.len(),
|
8 * l,
|
||||||
resultPoints,
|
resultPoints,
|
||||||
format,
|
format,
|
||||||
timestamp,
|
timestamp,
|
||||||
@@ -706,7 +707,7 @@ impl RXingResult<'_> {
|
|||||||
numBits,
|
numBits,
|
||||||
resultPoints,
|
resultPoints,
|
||||||
format,
|
format,
|
||||||
resultMetadata: None,
|
resultMetadata: HashMap::new(),
|
||||||
timestamp,
|
timestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -714,15 +715,15 @@ impl RXingResult<'_> {
|
|||||||
/**
|
/**
|
||||||
* @return raw text encoded by the barcode
|
* @return raw text encoded by the barcode
|
||||||
*/
|
*/
|
||||||
pub fn getText(&self) -> String {
|
pub fn getText(&self) -> &String {
|
||||||
return self.text;
|
return &self.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return raw bytes encoded by the barcode, if applicable, otherwise {@code null}
|
* @return raw bytes encoded by the barcode, if applicable, otherwise {@code null}
|
||||||
*/
|
*/
|
||||||
pub fn getRawBytes(&self) -> Vec<u8> {
|
pub fn getRawBytes(&self) -> &Vec<u8> {
|
||||||
return self.rawBytes;
|
return &self.rawBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -738,15 +739,15 @@ impl RXingResult<'_> {
|
|||||||
* identifying finder patterns or the corners of the barcode. The exact meaning is
|
* identifying finder patterns or the corners of the barcode. The exact meaning is
|
||||||
* specific to the type of barcode that was decoded.
|
* specific to the type of barcode that was decoded.
|
||||||
*/
|
*/
|
||||||
pub fn getRXingResultPoints(&self) -> Vec<RXingResultPoint> {
|
pub fn getRXingResultPoints(&self) -> &Vec<RXingResultPoint> {
|
||||||
return self.resultPoints;
|
return &self.resultPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {@link BarcodeFormat} representing the format of the barcode that was decoded
|
* @return {@link BarcodeFormat} representing the format of the barcode that was decoded
|
||||||
*/
|
*/
|
||||||
pub fn getBarcodeFormat(&self) -> BarcodeFormat {
|
pub fn getBarcodeFormat(&self) -> &BarcodeFormat {
|
||||||
return self.format;
|
return &self.format;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -754,35 +755,32 @@ impl RXingResult<'_> {
|
|||||||
* {@code null}. This contains optional metadata about what was detected about the barcode,
|
* {@code null}. This contains optional metadata about what was detected about the barcode,
|
||||||
* like orientation.
|
* like orientation.
|
||||||
*/
|
*/
|
||||||
pub fn getRXingResultMetadata(&self) -> HashMap<RXingResultMetadataType, &dyn Any> {
|
pub fn getRXingResultMetadata(&self) -> &HashMap<RXingResultMetadataType, String> {
|
||||||
return self.resultMetadata.unwrap();
|
return &self.resultMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn putMetadata(&self, md_type: RXingResultMetadataType, value: &dyn Any) {
|
pub fn putMetadata(&mut self, md_type: RXingResultMetadataType, value:String) {
|
||||||
if (self.resultMetadata.is_none()) {
|
self.resultMetadata.insert(md_type, value);
|
||||||
self.resultMetadata = Some(HashMap::new());
|
|
||||||
}
|
|
||||||
self.resultMetadata.unwrap().insert(md_type, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn putAllMetadata(&self, metadata: HashMap<RXingResultMetadataType, &dyn Any>) {
|
pub fn putAllMetadata(&mut self, metadata: HashMap<RXingResultMetadataType, String>) {
|
||||||
if (self.resultMetadata.is_none()) {
|
if self.resultMetadata.is_empty() {
|
||||||
self.resultMetadata = Some(metadata);
|
self.resultMetadata = metadata;
|
||||||
} else {
|
} else {
|
||||||
for (key, value) in metadata.into_iter() {
|
for (key, value) in metadata.into_iter() {
|
||||||
self.resultMetadata.unwrap().insert(key, value);
|
self.resultMetadata.insert(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addRXingResultPoints(&self, newPoints: Vec<RXingResultPoint>) {
|
pub fn addRXingResultPoints(&mut self, newPoints: &mut Vec<RXingResultPoint>) {
|
||||||
//RXingResultPoint[] oldPoints = resultPoints;
|
//RXingResultPoint[] oldPoints = resultPoints;
|
||||||
if !newPoints.is_empty() {
|
if !newPoints.is_empty() {
|
||||||
// let allPoints:Vec<RXingResultPoint>= Vec::with_capacity(oldPoints.len() + newPoints.len());
|
// let allPoints:Vec<RXingResultPoint>= Vec::with_capacity(oldPoints.len() + newPoints.len());
|
||||||
//System.arraycopy(oldPoints, 0, allPoints, 0, oldPoints.length);
|
//System.arraycopy(oldPoints, 0, allPoints, 0, oldPoints.length);
|
||||||
//System.arraycopy(newPoints, 0, allPoints, oldPoints.length, newPoints.length);
|
//System.arraycopy(newPoints, 0, allPoints, oldPoints.length, newPoints.length);
|
||||||
//resultPoints = allPoints;
|
//resultPoints = allPoints;
|
||||||
self.resultPoints.append(&mut newPoints);
|
self.resultPoints.append(newPoints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -791,7 +789,7 @@ impl RXingResult<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for RXingResult<'_> {
|
impl fmt::Display for RXingResult {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}", self.text)
|
write!(f, "{}", self.text)
|
||||||
}
|
}
|
||||||
@@ -822,6 +820,7 @@ use crate::common::detector::MathUtils;
|
|||||||
*
|
*
|
||||||
* @author Sean Owen
|
* @author Sean Owen
|
||||||
*/
|
*/
|
||||||
|
#[derive(Debug,Clone)]
|
||||||
pub struct RXingResultPoint {
|
pub struct RXingResultPoint {
|
||||||
x: f32,
|
x: f32,
|
||||||
y: f32,
|
y: f32,
|
||||||
@@ -857,7 +856,7 @@ impl RXingResultPoint {
|
|||||||
*
|
*
|
||||||
* @param patterns array of three {@code RXingResultPoint} to order
|
* @param patterns array of three {@code RXingResultPoint} to order
|
||||||
*/
|
*/
|
||||||
pub fn orderBestPatterns(patterns: &Vec<RXingResultPoint>) {
|
pub fn orderBestPatterns(patterns: &mut Vec<RXingResultPoint>) {
|
||||||
// Find distances between pattern centers
|
// Find distances between pattern centers
|
||||||
let zeroOneDistance = MathUtils::distance_float(
|
let zeroOneDistance = MathUtils::distance_float(
|
||||||
patterns[0].getX(),
|
patterns[0].getX(),
|
||||||
@@ -878,37 +877,41 @@ impl RXingResultPoint {
|
|||||||
patterns[2].getY(),
|
patterns[2].getY(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let pointA: RXingResultPoint;
|
let mut pointA: &RXingResultPoint;
|
||||||
let pointB: RXingResultPoint;
|
let mut pointB: &RXingResultPoint;
|
||||||
let pointC: RXingResultPoint;
|
let mut pointC: &RXingResultPoint;
|
||||||
// Assume one closest to other two is B; A and C will just be guesses at first
|
// Assume one closest to other two is B; A and C will just be guesses at first
|
||||||
if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {
|
if oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance {
|
||||||
pointB = patterns[0];
|
pointB = &patterns[0];
|
||||||
pointA = patterns[1];
|
pointA = &patterns[1];
|
||||||
pointC = patterns[2];
|
pointC = &patterns[2];
|
||||||
} else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {
|
} else if zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance {
|
||||||
pointB = patterns[1];
|
pointB = &patterns[1];
|
||||||
pointA = patterns[0];
|
pointA = &patterns[0];
|
||||||
pointC = patterns[2];
|
pointC = &patterns[2];
|
||||||
} else {
|
} else {
|
||||||
pointB = patterns[2];
|
pointB = &patterns[2];
|
||||||
pointA = patterns[0];
|
pointA = &patterns[0];
|
||||||
pointC = patterns[1];
|
pointC = &patterns[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use cross product to figure out whether A and C are correct or flipped.
|
// 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
|
// 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
|
// we want for A, B, C. If it's negative, then we've got it flipped around and
|
||||||
// should swap A and C.
|
// should swap A and C.
|
||||||
if (RXingResultPoint::crossProductZ(&pointA, &pointB, &pointC) < 0.0f32) {
|
if RXingResultPoint::crossProductZ(&pointA, &pointB, &pointC) < 0.0f32 {
|
||||||
let temp = pointA;
|
let temp = pointA;
|
||||||
pointA = pointC;
|
pointA = pointC;
|
||||||
pointC = temp;
|
pointC = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
patterns[0] = pointA;
|
let pa = (*pointA).clone();
|
||||||
patterns[1] = pointB;
|
let pb = (*pointB).clone();
|
||||||
patterns[2] = pointC;
|
let pc = (*pointC).clone();
|
||||||
|
|
||||||
|
patterns[0] = pa;
|
||||||
|
patterns[1] = pb;
|
||||||
|
patterns[2] = pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -969,7 +972,7 @@ pub struct Dimension {
|
|||||||
|
|
||||||
impl Dimension {
|
impl Dimension {
|
||||||
pub fn new(width: usize, height: usize) -> Result<Self, IllegalArgumentException> {
|
pub fn new(width: usize, height: usize) -> Result<Self, IllegalArgumentException> {
|
||||||
if (width < 0 || height < 0) {
|
if width < 0 || height < 0 {
|
||||||
return Err(IllegalArgumentException::new(""));
|
return Err(IllegalArgumentException::new(""));
|
||||||
}
|
}
|
||||||
Ok(Self { width, height })
|
Ok(Self { width, height })
|
||||||
@@ -1020,7 +1023,7 @@ pub trait Binarizer {
|
|||||||
//private final LuminanceSource source;
|
//private final LuminanceSource source;
|
||||||
//fn new(source:dyn LuminanceSource) -> Self;
|
//fn new(source:dyn LuminanceSource) -> Self;
|
||||||
|
|
||||||
fn getLuminanceSource(&self) -> dyn LuminanceSource;
|
fn getLuminanceSource(&self) -> &dyn LuminanceSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts one row of luminance data to 1 bit data. May actually do the conversion, or return
|
* Converts one row of luminance data to 1 bit data. May actually do the conversion, or return
|
||||||
@@ -1096,8 +1099,8 @@ pub struct BinaryBitmap {
|
|||||||
impl BinaryBitmap {
|
impl BinaryBitmap {
|
||||||
pub fn new(binarizer: Box<dyn Binarizer>) -> Self {
|
pub fn new(binarizer: Box<dyn Binarizer>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
binarizer: binarizer,
|
|
||||||
matrix: binarizer.getBlackMatrix().unwrap(),
|
matrix: binarizer.getBlackMatrix().unwrap(),
|
||||||
|
binarizer: binarizer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1139,20 +1142,23 @@ impl BinaryBitmap {
|
|||||||
* @return The 2D array of bits for the image (true means black).
|
* @return The 2D array of bits for the image (true means black).
|
||||||
* @throws NotFoundException if image can't be binarized to make a matrix
|
* @throws NotFoundException if image can't be binarized to make a matrix
|
||||||
*/
|
*/
|
||||||
pub fn getBlackMatrix(&self) -> Result<BitMatrix, NotFoundException> {
|
pub fn getBlackMatrix(&self) -> Result<&BitMatrix, NotFoundException> {
|
||||||
// The matrix is created on demand the first time it is requested, then cached. There are two
|
// The matrix is created on demand the first time it is requested, then cached. There are two
|
||||||
// reasons for this:
|
// reasons for this:
|
||||||
// 1. This work will never be done if the caller only installs 1D Reader objects, or if a
|
// 1. This work will never be done if the caller only installs 1D Reader objects, or if a
|
||||||
// 1D Reader finds a barcode before the 2D Readers run.
|
// 1D Reader finds a barcode before the 2D Readers run.
|
||||||
// 2. This work will only be done once even if the caller installs multiple 2D Readers.
|
// 2. This work will only be done once even if the caller installs multiple 2D Readers.
|
||||||
return Ok(self.matrix);
|
return Ok(&self.matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Whether this bitmap can be cropped.
|
* @return Whether this bitmap can be cropped.
|
||||||
*/
|
*/
|
||||||
pub fn isCropSupported(&self) -> bool {
|
pub fn isCropSupported(&self) -> bool {
|
||||||
return self.binarizer.getLuminanceSource().isCropSupported();
|
let b = &self.binarizer;
|
||||||
|
let r = &b.getLuminanceSource();
|
||||||
|
let isCropOk = r.isCropSupported();
|
||||||
|
return isCropOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1453,19 +1459,11 @@ impl InvertedLuminanceSource {
|
|||||||
delegate,
|
delegate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(width: usize, height: usize) -> Self {
|
|
||||||
let new_ils: Self;
|
|
||||||
new_ils.width = width;
|
|
||||||
new_ils.height = height;
|
|
||||||
|
|
||||||
new_ils
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LuminanceSource for InvertedLuminanceSource {
|
impl LuminanceSource for InvertedLuminanceSource {
|
||||||
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
|
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
|
||||||
let new_row = self.delegate.getRow(y, row);
|
let mut new_row = self.delegate.getRow(y, row);
|
||||||
let width = self.getWidth();
|
let width = self.getWidth();
|
||||||
for i in 0..width {
|
for i in 0..width {
|
||||||
//for (int i = 0; i < width; i++) {
|
//for (int i = 0; i < width; i++) {
|
||||||
@@ -1477,7 +1475,7 @@ impl LuminanceSource for InvertedLuminanceSource {
|
|||||||
fn getMatrix(&self) -> Vec<u8> {
|
fn getMatrix(&self) -> Vec<u8> {
|
||||||
let matrix = self.delegate.getMatrix();
|
let matrix = self.delegate.getMatrix();
|
||||||
let length = self.getWidth() * self.getHeight();
|
let length = self.getWidth() * self.getHeight();
|
||||||
let invertedMatrix = Vec::with_capacity(length);
|
let mut invertedMatrix = Vec::with_capacity(length);
|
||||||
for i in 0..length {
|
for i in 0..length {
|
||||||
//for (int i = 0; i < length; i++) {
|
//for (int i = 0; i < length; i++) {
|
||||||
invertedMatrix[i] = (255 - (matrix[i] & 0xFF));
|
invertedMatrix[i] = (255 - (matrix[i] & 0xFF));
|
||||||
@@ -1515,7 +1513,7 @@ impl LuminanceSource for InvertedLuminanceSource {
|
|||||||
/**
|
/**
|
||||||
* @return original delegate {@link LuminanceSource} since invert undoes itself
|
* @return original delegate {@link LuminanceSource} since invert undoes itself
|
||||||
*/
|
*/
|
||||||
fn invert(&self) -> Box<(dyn LuminanceSource)> {
|
fn invert(&self) -> Box<dyn LuminanceSource> {
|
||||||
return self.delegate;
|
return self.delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1564,6 +1562,7 @@ const THUMBNAIL_SCALE_FACTOR: usize = 2;
|
|||||||
*
|
*
|
||||||
* @author dswitkin@google.com (Daniel Switkin)
|
* @author dswitkin@google.com (Daniel Switkin)
|
||||||
*/
|
*/
|
||||||
|
#[derive(Debug,Clone)]
|
||||||
pub struct PlanarYUVLuminanceSource {
|
pub struct PlanarYUVLuminanceSource {
|
||||||
yuvData: Vec<u8>,
|
yuvData: Vec<u8>,
|
||||||
dataWidth: usize,
|
dataWidth: usize,
|
||||||
@@ -1585,13 +1584,13 @@ impl PlanarYUVLuminanceSource {
|
|||||||
height: usize,
|
height: usize,
|
||||||
reverseHorizontal: bool,
|
reverseHorizontal: bool,
|
||||||
) -> Result<Self, IllegalArgumentException> {
|
) -> Result<Self, IllegalArgumentException> {
|
||||||
if (left + width > dataWidth || top + height > dataHeight) {
|
if left + width > dataWidth || top + height > dataHeight {
|
||||||
return Err(IllegalArgumentException::new(
|
return Err(IllegalArgumentException::new(
|
||||||
"Crop rectangle does not fit within image data.",
|
"Crop rectangle does not fit within image data.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_s: Self = Self {
|
let mut new_s: Self = Self {
|
||||||
yuvData,
|
yuvData,
|
||||||
dataWidth,
|
dataWidth,
|
||||||
dataHeight,
|
dataHeight,
|
||||||
@@ -1611,9 +1610,9 @@ impl PlanarYUVLuminanceSource {
|
|||||||
pub fn renderThumbnail(&self) -> Vec<u8> {
|
pub fn renderThumbnail(&self) -> Vec<u8> {
|
||||||
let width = self.getWidth() / THUMBNAIL_SCALE_FACTOR;
|
let width = self.getWidth() / THUMBNAIL_SCALE_FACTOR;
|
||||||
let height = self.getHeight() / THUMBNAIL_SCALE_FACTOR;
|
let height = self.getHeight() / THUMBNAIL_SCALE_FACTOR;
|
||||||
let pixels = Vec::with_capacity(width * height);
|
let mut pixels = Vec::with_capacity(width * height);
|
||||||
let yuv: Vec<u8> = Vec::new();
|
let yuv: Vec<u8> = Vec::new();
|
||||||
let inputOffset = self.top * self.dataWidth + self.left;
|
let mut inputOffset = self.top * self.dataWidth + self.left;
|
||||||
|
|
||||||
for y in 0..height {
|
for y in 0..height {
|
||||||
//for (int y = 0; y < height; y++) {
|
//for (int y = 0; y < height; y++) {
|
||||||
@@ -1642,22 +1641,22 @@ impl PlanarYUVLuminanceSource {
|
|||||||
return self.getHeight() / THUMBNAIL_SCALE_FACTOR;
|
return self.getHeight() / THUMBNAIL_SCALE_FACTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reverseHorizontal(&self, width: usize, height: usize) {
|
fn reverseHorizontal(&mut self, width: usize, height: usize) {
|
||||||
let yuvData = self.yuvData;
|
//let mut yuvData = self.yuvData;
|
||||||
let mut rowStart = self.top * self.dataWidth + self.left;
|
let mut rowStart = self.top * self.dataWidth + self.left;
|
||||||
for y in 0..height {
|
for y in 0..height {
|
||||||
let middle = rowStart + width / 2;
|
let middle = rowStart + width / 2;
|
||||||
let mut x2 = rowStart + width - 1;
|
let mut x2 = rowStart + width - 1;
|
||||||
for x1 in rowStart..middle {
|
for x1 in rowStart..middle {
|
||||||
//for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) {
|
//for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) {
|
||||||
let temp = yuvData[x1];
|
let temp = self.yuvData[x1];
|
||||||
yuvData[x1] = yuvData[x2];
|
self.yuvData[x1] = self.yuvData[x2];
|
||||||
yuvData[x2] = temp;
|
self.yuvData[x2] = temp;
|
||||||
x2 -= 1;
|
x2 -= 1;
|
||||||
}
|
}
|
||||||
rowStart += self.dataWidth;
|
rowStart += self.dataWidth;
|
||||||
}
|
}
|
||||||
self.yuvData = yuvData;
|
//self.yuvData = yuvData;
|
||||||
/*for (int y = 0, rowStart = top * dataWidth + left; y < height; y++, rowStart += dataWidth) {
|
/*for (int y = 0, rowStart = top * dataWidth + left; y < height; y++, rowStart += dataWidth) {
|
||||||
let middle = rowStart + width / 2;
|
let middle = rowStart + width / 2;
|
||||||
for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) {
|
for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) {
|
||||||
@@ -1667,20 +1666,12 @@ impl PlanarYUVLuminanceSource {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(width: usize, height: usize) -> Self {
|
|
||||||
let new_ils: Self;
|
|
||||||
new_ils.width = width;
|
|
||||||
new_ils.height = height;
|
|
||||||
|
|
||||||
new_ils
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LuminanceSource for PlanarYUVLuminanceSource {
|
impl LuminanceSource for PlanarYUVLuminanceSource {
|
||||||
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
|
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
|
||||||
let mut row = row.to_vec();
|
let mut row = row.to_vec();
|
||||||
if (y < 0 || y >= self.getHeight()) {
|
if y < 0 || y >= self.getHeight() {
|
||||||
//throw new IllegalArgumentException("Requested row is outside the image: " + y);
|
//throw new IllegalArgumentException("Requested row is outside the image: " + y);
|
||||||
panic!("Requested row is outside the image: {}", y);
|
panic!("Requested row is outside the image: {}", y);
|
||||||
}
|
}
|
||||||
@@ -1699,16 +1690,16 @@ impl LuminanceSource for PlanarYUVLuminanceSource {
|
|||||||
|
|
||||||
// If the caller asks for the entire underlying image, save the copy and give them the
|
// If the caller asks for the entire underlying image, save the copy and give them the
|
||||||
// original data. The docs specifically warn that result.length must be ignored.
|
// original data. The docs specifically warn that result.length must be ignored.
|
||||||
if (width == self.dataWidth && height == self.dataHeight) {
|
if width == self.dataWidth && height == self.dataHeight {
|
||||||
return self.yuvData;
|
return self.yuvData.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
let area = width * height;
|
let area = width * height;
|
||||||
let matrix = Vec::with_capacity(area);
|
let mut matrix = Vec::with_capacity(area);
|
||||||
let inputOffset = self.top * self.dataWidth + self.left;
|
let mut inputOffset = self.top * self.dataWidth + self.left;
|
||||||
|
|
||||||
// If the width matches the full width of the underlying data, perform a single copy.
|
// If the width matches the full width of the underlying data, perform a single copy.
|
||||||
if (width == self.dataWidth) {
|
if width == self.dataWidth {
|
||||||
matrix[0..area].clone_from_slice(&self.yuvData[inputOffset..area]);
|
matrix[0..area].clone_from_slice(&self.yuvData[inputOffset..area]);
|
||||||
//System.arraycopy(yuvData, inputOffset, matrix, 0, area);
|
//System.arraycopy(yuvData, inputOffset, matrix, 0, area);
|
||||||
return matrix;
|
return matrix;
|
||||||
@@ -1745,7 +1736,7 @@ impl LuminanceSource for PlanarYUVLuminanceSource {
|
|||||||
height: usize,
|
height: usize,
|
||||||
) -> Result<Box<dyn LuminanceSource>, UnsupportedOperationException> {
|
) -> Result<Box<dyn LuminanceSource>, UnsupportedOperationException> {
|
||||||
match PlanarYUVLuminanceSource::new_with_all(
|
match PlanarYUVLuminanceSource::new_with_all(
|
||||||
self.yuvData,
|
self.yuvData.clone(),
|
||||||
self.dataWidth,
|
self.dataWidth,
|
||||||
self.dataHeight,
|
self.dataHeight,
|
||||||
self.left + left,
|
self.left + left,
|
||||||
@@ -1764,7 +1755,7 @@ impl LuminanceSource for PlanarYUVLuminanceSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn invert(&self) -> Box<dyn LuminanceSource> {
|
fn invert(&self) -> Box<dyn LuminanceSource> {
|
||||||
let new_i = InvertedLuminanceSource::new_with_delegate(Box::new(*self));
|
let new_i = InvertedLuminanceSource::new_with_delegate(Box::new(self.clone()));
|
||||||
|
|
||||||
Box::new(new_i)
|
Box::new(new_i)
|
||||||
}
|
}
|
||||||
@@ -1795,6 +1786,7 @@ impl LuminanceSource for PlanarYUVLuminanceSource {
|
|||||||
* @author dswitkin@google.com (Daniel Switkin)
|
* @author dswitkin@google.com (Daniel Switkin)
|
||||||
* @author Betaminos
|
* @author Betaminos
|
||||||
*/
|
*/
|
||||||
|
#[derive(Debug,Clone)]
|
||||||
pub struct RGBLuminanceSource {
|
pub struct RGBLuminanceSource {
|
||||||
luminances: Vec<u8>,
|
luminances: Vec<u8>,
|
||||||
dataWidth: usize,
|
dataWidth: usize,
|
||||||
@@ -1807,7 +1799,7 @@ pub struct RGBLuminanceSource {
|
|||||||
|
|
||||||
impl LuminanceSource for RGBLuminanceSource {
|
impl LuminanceSource for RGBLuminanceSource {
|
||||||
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
|
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
|
||||||
let row = row.to_vec();
|
let mut row = row.to_vec();
|
||||||
if y < 0 || y >= self.getHeight() {
|
if y < 0 || y >= self.getHeight() {
|
||||||
panic!("Requested row is outside the image: {}", y);
|
panic!("Requested row is outside the image: {}", y);
|
||||||
}
|
}
|
||||||
@@ -1825,8 +1817,8 @@ impl LuminanceSource for RGBLuminanceSource {
|
|||||||
|
|
||||||
// If the caller asks for the entire underlying image, save the copy and give them the
|
// If the caller asks for the entire underlying image, save the copy and give them the
|
||||||
// original data. The docs specifically warn that result.length must be ignored.
|
// original data. The docs specifically warn that result.length must be ignored.
|
||||||
if (width == self.dataWidth && height == self.dataHeight) {
|
if width == self.dataWidth && height == self.dataHeight {
|
||||||
return self.luminances;
|
return self.luminances.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
let area = width * height;
|
let area = width * height;
|
||||||
@@ -1834,7 +1826,7 @@ impl LuminanceSource for RGBLuminanceSource {
|
|||||||
let mut inputOffset = self.top * self.dataWidth + self.left;
|
let mut inputOffset = self.top * self.dataWidth + self.left;
|
||||||
|
|
||||||
// If the width matches the full width of the underlying data, perform a single copy.
|
// If the width matches the full width of the underlying data, perform a single copy.
|
||||||
if (width == self.dataWidth) {
|
if width == self.dataWidth {
|
||||||
matrix[0..area].clone_from_slice(&self.luminances[inputOffset..area]);
|
matrix[0..area].clone_from_slice(&self.luminances[inputOffset..area]);
|
||||||
//System.arraycopy(self.luminances, inputOffset, matrix, 0, area);
|
//System.arraycopy(self.luminances, inputOffset, matrix, 0, area);
|
||||||
return matrix;
|
return matrix;
|
||||||
@@ -1885,21 +1877,13 @@ impl LuminanceSource for RGBLuminanceSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn invert(&self) -> Box<dyn LuminanceSource> {
|
fn invert(&self) -> Box<dyn LuminanceSource> {
|
||||||
let new_i = InvertedLuminanceSource::new_with_delegate(Box::new(*self));
|
let new_i = InvertedLuminanceSource::new_with_delegate(Box::new(self.clone()));
|
||||||
|
|
||||||
Box::new(new_i)
|
Box::new(new_i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RGBLuminanceSource {
|
impl RGBLuminanceSource {
|
||||||
fn new(width: usize, height: usize) -> Self {
|
|
||||||
let new_ils: Self;
|
|
||||||
new_ils.width = width;
|
|
||||||
new_ils.height = height;
|
|
||||||
|
|
||||||
new_ils
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_with_width_height_pixels(width: usize, height: usize, pixels: &Vec<u8>) -> Self {
|
pub fn new_with_width_height_pixels(width: usize, height: usize, pixels: &Vec<u8>) -> Self {
|
||||||
//super(width, height);
|
//super(width, height);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user