partially passing encoder

This commit is contained in:
Henry Schimke
2022-09-25 16:52:12 -05:00
parent fb08ee0e34
commit b2a460a226
10 changed files with 769 additions and 512 deletions

View File

@@ -34,6 +34,8 @@
// import java.util.Random; // import java.util.Random;
// import java.util.TreeSet; // import java.util.TreeSet;
use rand::Rng;
use crate::{aztec::decoder, common::BitMatrix, exceptions::Exceptions}; use crate::{aztec::decoder, common::BitMatrix, exceptions::Exceptions};
use super::{ use super::{
@@ -69,7 +71,7 @@ fn testErrorInParameterLocatorNotCompact() {
fn testErrorInParameterLocator(data: &str) { fn testErrorInParameterLocator(data: &str) {
let aztec = encoder::encoder::encode(data, 25, encoder::encoder::DEFAULT_AZTEC_LAYERS) let aztec = encoder::encoder::encode(data, 25, encoder::encoder::DEFAULT_AZTEC_LAYERS)
.expect("encode should create"); .expect("encode should create");
let random = rand::thread_rng(); //Random(aztec.getMatrix().hashCode()); // pseudo-random, but deterministic let mut random = rand::thread_rng(); //Random(aztec.getMatrix().hashCode()); // pseudo-random, but deterministic
let layers = aztec.getLayers(); let layers = aztec.getLayers();
let compact = aztec.isCompact(); let compact = aztec.isCompact();
let orientationPoints = getOrientationPoints(&aztec); let orientationPoints = getOrientationPoints(&aztec);
@@ -78,24 +80,24 @@ fn testErrorInParameterLocator(data: &str) {
for matrix in getRotations(aztec.getMatrix()) { for matrix in getRotations(aztec.getMatrix()) {
// for (BitMatrix matrix : getRotations(aztec.getMatrix())) { // for (BitMatrix matrix : getRotations(aztec.getMatrix())) {
// Systematically try every possible 1- and 2-bit error. // Systematically try every possible 1- and 2-bit error.
for error1 in 0..orientationPoints.size() { for error1 in 0..orientationPoints.len() {
// for (int error1 = 0; error1 < orientationPoints.size(); error1++) { // for (int error1 = 0; error1 < orientationPoints.size(); error1++) {
for error2 in error1..orientationPoints.size() { for error2 in error1..orientationPoints.len() {
// for (int error2 = error1; error2 < orientationPoints.size(); error2++) { // for (int error2 = error1; error2 < orientationPoints.size(); error2++) {
let copy = if isMirror { let mut copy = if isMirror {
transpose(&matrix) transpose(&matrix)
} else { } else {
clone(&matrix) clone(&matrix)
}; };
copy.flip( copy.flip_coords(
orientationPoints.get(error1).getX(), orientationPoints.get(error1).unwrap().getX() as u32,
orientationPoints.get(error1).getY(), orientationPoints.get(error1).unwrap().getY() as u32,
); );
if error2 > error1 { if error2 > error1 {
// if error2 == error1, we only test a single error // if error2 == error1, we only test a single error
copy.flip( copy.flip_coords(
orientationPoints.get(error2).getX(), orientationPoints.get(error2).unwrap().getX() as u32,
orientationPoints.get(error2).getY(), orientationPoints.get(error2).unwrap().getY() as u32,
); );
} }
// The detector doesn't seem to work when matrix bits are only 1x1. So magnify. // The detector doesn't seem to work when matrix bits are only 1x1. So magnify.
@@ -111,17 +113,17 @@ fn testErrorInParameterLocator(data: &str) {
// Try a few random three-bit errors; // Try a few random three-bit errors;
for i in 0..5 { for i in 0..5 {
// for (int i = 0; i < 5; i++) { // for (int i = 0; i < 5; i++) {
let copy = clone(&matrix); let mut copy = clone(&matrix);
let errors = Vec::new(); let mut errors = Vec::new();
while errors.size() < 3 { while errors.len() < 3 {
// Quick and dirty way of getting three distinct integers between 1 and n. // Quick and dirty way of getting three distinct integers between 1 and n.
errors.push(random.nextInt(orientationPoints.size())); errors.push(random.gen_range(0..=orientationPoints.len()));
} }
for error in errors { for error in errors {
// for (int error : errors) { // for (int error : errors) {
copy.flip( copy.flip_coords(
orientationPoints.get(error).getX(), orientationPoints.get(error).unwrap().getX() as u32,
orientationPoints.get(error).getY(), orientationPoints.get(error).unwrap().getY() as u32,
); );
} }
// try { // try {
@@ -147,7 +149,7 @@ fn testErrorInParameterLocator(data: &str) {
// Zooms a bit matrix so that each bit is factor x factor // Zooms a bit matrix so that each bit is factor x factor
fn makeLarger(input: &BitMatrix, factor: u32) -> BitMatrix { fn makeLarger(input: &BitMatrix, factor: u32) -> BitMatrix {
let width = input.getWidth(); let width = input.getWidth();
let output = BitMatrix::with_single_dimension(width * factor); let mut output = BitMatrix::with_single_dimension(width * factor);
for inputY in 0..width { for inputY in 0..width {
// for (int inputY = 0; inputY < width; inputY++) { // for (int inputY = 0; inputY < width; inputY++) {
for inputX in 0..width { for inputX in 0..width {
@@ -165,13 +167,13 @@ fn getRotations(matrix0: &BitMatrix) -> Vec<BitMatrix> {
let matrix90 = rotateRight(matrix0); let matrix90 = rotateRight(matrix0);
let matrix180 = rotateRight(&matrix90); let matrix180 = rotateRight(&matrix90);
let matrix270 = rotateRight(&matrix180); let matrix270 = rotateRight(&matrix180);
vec![*matrix0, matrix90, matrix180, matrix270] vec![matrix0.clone(), matrix90, matrix180, matrix270]
} }
// Rotates a square BitMatrix to the right by 90 degrees // Rotates a square BitMatrix to the right by 90 degrees
fn rotateRight(input: &BitMatrix) -> BitMatrix { fn rotateRight(input: &BitMatrix) -> BitMatrix {
let width = input.getWidth(); let width = input.getWidth();
let result = BitMatrix::with_single_dimension(width); let mut result = BitMatrix::with_single_dimension(width);
for x in 0..width { for x in 0..width {
// for (int x = 0; x < width; x++) { // for (int x = 0; x < width; x++) {
for y in 0..width { for y in 0..width {
@@ -188,7 +190,7 @@ fn rotateRight(input: &BitMatrix) -> BitMatrix {
// matrix to the right, and then flipping it left-to-right // matrix to the right, and then flipping it left-to-right
fn transpose(input: &BitMatrix) -> BitMatrix { fn transpose(input: &BitMatrix) -> BitMatrix {
let width = input.getWidth(); let width = input.getWidth();
let result = BitMatrix::with_single_dimension(width); let mut result = BitMatrix::with_single_dimension(width);
for x in 0..width { for x in 0..width {
// for (int x = 0; x < width; x++) { // for (int x = 0; x < width; x++) {
for y in 0..width { for y in 0..width {
@@ -203,7 +205,7 @@ fn transpose(input: &BitMatrix) -> BitMatrix {
fn clone(input: &BitMatrix) -> BitMatrix { fn clone(input: &BitMatrix) -> BitMatrix {
let width = input.getWidth(); let width = input.getWidth();
let result = BitMatrix::with_single_dimension(width); let mut result = BitMatrix::with_single_dimension(width);
for x in 0..width { for x in 0..width {
// for (int x = 0; x < width; x++) { // for (int x = 0; x < width; x++) {
for y in 0..width { for y in 0..width {
@@ -217,21 +219,21 @@ fn clone(input: &BitMatrix) -> BitMatrix {
} }
fn getOrientationPoints(code: &AztecCode) -> Vec<Point> { fn getOrientationPoints(code: &AztecCode) -> Vec<Point> {
let center = code.getMatrix().getWidth() / 2; let center = code.getMatrix().getWidth() as i32 / 2;
let offset = if code.isCompact() { 5 } else { 7 }; let offset = if code.isCompact() { 5 } else { 7 };
let result = Vec::new(); let mut result = Vec::new();
let mut xSign = -1; let mut xSign: i32 = -1;
while xSign <= 1 { while xSign <= 1 {
// for (int xSign = -1; xSign <= 1; xSign += 2) { // for (int xSign = -1; xSign <= 1; xSign += 2) {
let mut ySign = -1; let mut ySign: i32 = -1;
while ySign <= 1 { while ySign <= 1 {
// for (int ySign = -1; ySign <= 1; ySign += 2) { // for (int ySign = -1; ySign <= 1; ySign += 2) {
result.add(Point::new(center + xSign * offset, center + ySign * offset)); result.push(Point::new(center + xSign * offset, center + ySign * offset));
result.add(Point::new( result.push(Point::new(
center + xSign * (offset - 1), center + xSign * (offset - 1),
center + ySign * offset, center + ySign * offset,
)); ));
result.add(Point::new( result.push(Point::new(
center + xSign * offset, center + xSign * offset,
center + ySign * (offset - 1), center + ySign * (offset - 1),
)); ));

File diff suppressed because it is too large Load Diff

View File

@@ -20,37 +20,37 @@ use crate::common::BitArray;
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct BinaryShiftToken { pub struct BinaryShiftToken {
binaryShiftStart: u32, binary_shift_start: u32,
binaryShiftByteCount: u32, binary_shift_byte_count: u32,
} }
impl BinaryShiftToken { impl BinaryShiftToken {
pub fn new(binaryShiftStart: u32, binaryShiftByteCount: u32) -> Self { pub fn new(binary_shift_start: u32, binary_shift_byte_count: u32) -> Self {
Self { Self {
binaryShiftStart, binary_shift_start,
binaryShiftByteCount, binary_shift_byte_count,
} }
} }
pub fn appendTo(&self, bitArray: &mut BitArray, text: &[u8]) { pub fn appendTo(&self, bit_array: &mut BitArray, text: &[u8]) {
let bsbc = self.binaryShiftByteCount as usize; let bsbc = self.binary_shift_byte_count as usize;
for i in 0..bsbc { for i in 0..bsbc {
// for (int i = 0; i < bsbc; i++) { // for (int i = 0; i < bsbc; i++) {
if (i == 0 || (i == 31 && bsbc <= 62)) { if i == 0 || (i == 31 && bsbc <= 62) {
// We need a header before the first character, and before // We need a header before the first character, and before
// character 31 when the total byte code is <= 62 // character 31 when the total byte code is <= 62
bitArray.appendBits(31, 5); // BINARY_SHIFT bit_array.appendBits(31, 5).unwrap(); // BINARY_SHIFT
if (bsbc > 62) { if bsbc > 62 {
bitArray.appendBits(bsbc as u32 - 31, 16); bit_array.appendBits(bsbc as u32 - 31, 16).unwrap();
} else if (i == 0) { } else if i == 0 {
// 1 <= binaryShiftByteCode <= 62 // 1 <= binaryShiftByteCode <= 62
bitArray.appendBits(bsbc.min(31) as u32, 5); bit_array.appendBits(bsbc.min(31) as u32, 5).unwrap();
} else { } else {
// 32 <= binaryShiftCount <= 62 and i == 31 // 32 <= binaryShiftCount <= 62 and i == 31
bitArray.appendBits(bsbc as u32 - 31, 5); bit_array.appendBits(bsbc as u32 - 31, 5).unwrap();
} }
} }
bitArray.appendBits(text[self.binaryShiftStart as usize + i].into(), 8); bit_array.appendBits(text[self.binary_shift_start as usize + i].into(), 8).expect("should never fail to append");
} }
} }
@@ -65,8 +65,8 @@ impl fmt::Display for BinaryShiftToken {
write!( write!(
f, f,
"<{}::{}>", "<{}::{}>",
self.binaryShiftStart, self.binary_shift_start,
(self.binaryShiftStart + self.binaryShiftByteCount - 1) (self.binary_shift_start + self.binary_shift_byte_count - 1)
) )
} }
} }

View File

@@ -72,8 +72,8 @@ pub fn encode(
userSpecifiedLayers: u32, userSpecifiedLayers: u32,
) -> Result<AztecCode, Exceptions> { ) -> Result<AztecCode, Exceptions> {
let bytes = encoding::all::ISO_8859_1 let bytes = encoding::all::ISO_8859_1
.encode(data, encoding::EncoderTrap::Replace) .encode(data, encoding::EncoderTrap::Strict)
.unwrap(); .expect("must encode cleanly in ISO_8859_1");
encode_bytes(&bytes, minECCPercent, userSpecifiedLayers) encode_bytes(&bytes, minECCPercent, userSpecifiedLayers)
} }
@@ -209,6 +209,7 @@ pub fn encode_bytes_with_charset(
layers = if compact { i + 1 } else { i }; layers = if compact { i + 1 } else { i };
totalBitsInLayerVar = totalBitsInLayer(layers, compact); totalBitsInLayerVar = totalBitsInLayer(layers, compact);
if totalSizeBits > totalBitsInLayerVar as u32 { if totalSizeBits > totalBitsInLayerVar as u32 {
i += 1;
continue; continue;
} }
// [Re]stuff the bits if this is the first opportunity, or if the // [Re]stuff the bits if this is the first opportunity, or if the
@@ -220,6 +221,7 @@ pub fn encode_bytes_with_charset(
let usableBitsInLayers = totalBitsInLayerVar - (totalBitsInLayerVar % wordSize); let usableBitsInLayers = totalBitsInLayerVar - (totalBitsInLayerVar % wordSize);
if compact && stuffedBits.getSize() as u32 > wordSize * 64 { if compact && stuffedBits.getSize() as u32 > wordSize * 64 {
// Compact format only allows 64 data words, though C4 can hold more words than that // Compact format only allows 64 data words, though C4 can hold more words than that
i += 1;
continue; continue;
} }
if stuffedBits.getSize()as u32 + eccBits<= usableBitsInLayers { if stuffedBits.getSize()as u32 + eccBits<= usableBitsInLayers {
@@ -487,32 +489,32 @@ fn getGF(wordSize: usize) -> Result<GenericGF, Exceptions> {
// } // }
} }
pub fn stuffBits(bits: &BitArray, wordSize: usize) -> BitArray { pub fn stuffBits(bits: &BitArray, word_size: usize) -> BitArray {
let mut out = BitArray::new(); let mut out = BitArray::new();
let n = bits.getSize(); let n = bits.getSize() as isize;
let mask = (1 << wordSize) - 2; let mask = (1 << word_size) - 2;
let mut i = 0; let mut i:isize = 0;
while i < n { while i < n {
// for (int i = 0; i < n; i += wordSize) { // for (int i = 0; i < n; i += wordSize) {
let mut word = 0; let mut word = 0;
for j in 0..wordSize { for j in 0..word_size as isize {
// for (int j = 0; j < wordSize; j++) { // for (int j = 0; j < wordSize; j++) {
if i + j >= n || bits.get(i + j) { if i + j >= n || bits.get((i + j) as usize) {
word |= 1 << (wordSize - 1 - j); word |= 1 << (word_size as isize - 1 - j);
} }
} }
if (word & mask) == mask { if (word & mask) == mask {
out.appendBits(word & mask, wordSize); out.appendBits(word & mask, word_size).unwrap();
i -= 1; i -= 1;
} else if (word & mask) == 0 { } else if (word & mask) == 0 {
out.appendBits(word | 1, wordSize); out.appendBits(word | 1, word_size).unwrap();
i -= 1; i -= 1;
} else { } else {
out.appendBits(word, wordSize); out.appendBits(word, word_size).unwrap();
} }
i += wordSize; i += word_size as isize;
} }
return out; return out;
} }

View File

@@ -125,27 +125,28 @@ impl HighLevelEncoder {
// } // }
char_map[Self::MODE_DIGIT][b',' as usize] = 12; char_map[Self::MODE_DIGIT][b',' as usize] = 12;
char_map[Self::MODE_DIGIT][b'.' as usize] = 13; char_map[Self::MODE_DIGIT][b'.' as usize] = 13;
let mixedTable = [ let mixed_table = [
'\0', ' ', '\u{1}', '\u{2}', '\u{3}', '\u{4}', '\u{5}', '\u{6}', '\u{7}', '\u{8}', '\0', ' ', '\u{1}', '\u{2}', '\u{3}', '\u{4}', '\u{5}', '\u{6}', '\u{7}', '\u{8}',
'\t', '\n', '\u{13}', '\u{f}', '\r', '\u{33}', '\u{34}', '\u{35}', '\u{36}', '\u{37}', '\t', '\n', '\u{13}', '\u{f}', '\r', '\u{33}', '\u{34}', '\u{35}', '\u{36}', '\u{37}',
'@', '\\', '^', '_', '`', '|', '~', '\u{177}', '@', '\\', '^', '_', '`', '|', '~', '\u{177}',
]; ];
let mut i = 0; let mut i = 0;
while i < mixedTable.len() { while i < mixed_table.len() {
char_map[Self::MODE_MIXED][mixedTable[i] as u8 as usize] = i as u8; char_map[Self::MODE_MIXED][mixed_table[i] as u8 as usize] = i as u8;
i += 1; i += 1;
} }
// for (int i = 0; i < mixedTable.length; i++) { // for (int i = 0; i < mixedTable.length; i++) {
// CHAR_MAP[MODE_MIXED][mixedTable[i]] = i; // CHAR_MAP[MODE_MIXED][mixedTable[i]] = i;
// } // }
let punctTable = [ let punctTable = [
'\0', '\r', '\0', '\0', '\0', '\0', '!', '\'', '#', '$', '%', '&', '\'', '(', ')', '*', b'\0', b'\r', b'\0', b'\0', b'\0', b'\0', b'!', b'\'', b'#', b'$', b'%', b'&', b'\'',
'+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '{', '}', b'(', b')', b'*', b'+', b',', b'-', b'.', b'/', b':', b';', b'<', b'=', b'>', b'?',
b'[', b']', b'{', b'}',
]; ];
let mut i = 0; let mut i = 0;
while i < punctTable.len() { while i < punctTable.len() {
if punctTable[i] as u8 > 0u8 { if punctTable[i] > 0u8 {
char_map[Self::MODE_PUNCT][punctTable[i] as u8 as usize] = i as u8; char_map[Self::MODE_PUNCT][punctTable[i] as usize] = i as u8;
} }
i += 1; i += 1;
} }
@@ -230,7 +231,7 @@ impl HighLevelEncoder {
pub fn new(text: Vec<u8>) -> Self { pub fn new(text: Vec<u8>) -> Self {
Self { Self {
text, text,
charset: encoding::all::UTF_8, charset: encoding::all::ISO_8859_1,
} }
} }
@@ -242,9 +243,11 @@ impl HighLevelEncoder {
* @return text represented by this encoder encoded as a {@link BitArray} * @return text represented by this encoder encoded as a {@link BitArray}
*/ */
pub fn encode(&self) -> Result<BitArray, Exceptions> { pub fn encode(&self) -> Result<BitArray, Exceptions> {
let mut initialState = State::new(Token::new(), Self::MODE_UPPER as u32, 0, 0); let mut initial_state = State::new(Token::new(), Self::MODE_UPPER as u32, 0, 0);
if let Some(eci) = CharacterSetECI::getCharacterSetECI(self.charset) { if let Some(eci) = CharacterSetECI::getCharacterSetECI(self.charset) {
initialState = initialState.appendFLGn(CharacterSetECI::getValue(&eci))?; if eci != CharacterSetECI::ISO8859_1 {
initial_state = initial_state.appendFLGn(CharacterSetECI::getValue(&eci))?;
}
} else { } else {
return Err(Exceptions::IllegalArgumentException( return Err(Exceptions::IllegalArgumentException(
"No ECI code for character set".to_owned(), "No ECI code for character set".to_owned(),
@@ -257,22 +260,22 @@ impl HighLevelEncoder {
// } // }
// initialState = initialState.appendFLGn(eci.getValue()); // initialState = initialState.appendFLGn(eci.getValue());
// } // }
let mut states = vec![initialState]; let mut states = vec![initial_state];
let mut index = 0; let mut index = 0;
while index < self.text.len() { while index < self.text.len() {
// for index in 0..self.text.len() { // for index in 0..self.text.len() {
// for (int index = 0; index < text.length; index++) { // for (int index = 0; index < text.length; index++) {
let pairCode; let pair_code;
let nextChar = if index + 1 < self.text.len() { let next_char = if index + 1 < self.text.len() {
self.text[index + 1] self.text[index + 1]
} else { } else {
0 0
}; };
pairCode = match self.text[index] { pair_code = match self.text[index] {
b'\r' if nextChar == b'\n' => 2, b'\r' if next_char == b'\n' => 2,
b'.' if nextChar == b' ' => 3, b'.' if next_char == b' ' => 3,
b',' if nextChar == b' ' => 4, b',' if next_char == b' ' => 4,
b':' if nextChar == b' ' => 5, b':' if next_char == b' ' => 5,
_ => 0, _ => 0,
}; };
// switch (text[index]) { // switch (text[index]) {
@@ -291,19 +294,24 @@ impl HighLevelEncoder {
// default: // default:
// pairCode = 0; // pairCode = 0;
// } // }
if pairCode > 0 { if pair_code > 0 {
// We have one of the four special PUNCT pairs. Treat them specially. // We have one of the four special PUNCT pairs. Treat them specially.
// Get a new set of states for the two new characters. // Get a new set of states for the two new characters.
states = Self::updateStateListForPair(states, index as u32, pairCode); states = Self::update_state_list_for_pair(states, index as u32, pair_code);
index += 1; index += 1;
} else { } else {
// Get a new set of states for the new character. // Get a new set of states for the new character.
states = self.updateStateListForChar(states, index as u32); states = self.update_state_list_for_char(states, index as u32);
} }
index += 1; index += 1;
} }
// for state in &states {
// dbg!(state.clone().toBitArray(&self.text).to_string());
// }
// We are left with a set of states. Find the shortest one. // We are left with a set of states. Find the shortest one.
let minState = states let min_state = states
.into_iter() .into_iter()
.min_by(|a, b| { .min_by(|a, b| {
let diff: i64 = a.getBitCount() as i64 - b.getBitCount() as i64; let diff: i64 = a.getBitCount() as i64 - b.getBitCount() as i64;
@@ -324,58 +332,61 @@ impl HighLevelEncoder {
// } // }
// }); // });
// Convert it to a bit array, and return. // Convert it to a bit array, and return.
Ok(minState.toBitArray(&self.text)) Ok(min_state.toBitArray(&self.text))
} }
// We update a set of states for a new character by updating each state // We update a set of states for a new character by updating each state
// for the new character, merging the results, and then removing the // for the new character, merging the results, and then removing the
// non-optimal states. // non-optimal states.
fn updateStateListForChar(&self, states: Vec<State>, index: u32) -> Vec<State> { fn update_state_list_for_char(&self, states: Vec<State>, index: u32) -> Vec<State> {
let mut result = Vec::new(); let mut result = Vec::new();
for state in states { for state in states {
// for (State state : states) { // for (State state : states) {
self.updateStateForChar(state, index, &mut result); self.update_state_for_char(state, index, &mut result);
} }
Self::simplifyStates(result) Self::simplify_states(result)
} }
// Return a set of states that represent the possible ways of updating this // Return a set of states that represent the possible ways of updating this
// state for the next character. The resulting set of states are added to // state for the next character. The resulting set of states are added to
// the "result" list. // the "result" list.
fn updateStateForChar(&self, state: State, index: u32, result: &mut Vec<State>) { fn update_state_for_char(&self, state: State, index: u32, result: &mut Vec<State>) {
let ch = self.text[index as usize]; let ch = self.text[index as usize];
let charInCurrentTable = Self::CHAR_MAP[state.getMode() as usize][ch as usize] > 0; let char_in_current_table = Self::CHAR_MAP[state.getMode() as usize][ch as usize] > 0;
let mut stateNoBinary = None; let mut state_no_binary = None;
for mode in 0..Self::MODE_PUNCT { for mode in 0..=Self::MODE_PUNCT {
// for (int mode = 0; mode <= MODE_PUNCT; mode++) { // for (int mode = 0; mode <= MODE_PUNCT; mode++) {
let charInMode = Self::CHAR_MAP[mode as usize][ch as usize]; let char_in_mode = Self::CHAR_MAP[mode as usize][ch as usize];
if charInMode > 0 { if char_in_mode > 0 {
if stateNoBinary.is_none() { if state_no_binary.is_none() {
// Only create stateNoBinary the first time it's required. // Only create stateNoBinary the first time it's required.
stateNoBinary = Some(state.clone().endBinaryShift(index)); state_no_binary = Some(state.clone().endBinaryShift(index));
} }
// Try generating the character by latching to its mode // Try generating the character by latching to its mode
if !charInCurrentTable || mode as u32 == state.getMode() || mode == Self::MODE_DIGIT if !char_in_current_table
|| mode as u32 == state.getMode()
|| mode == Self::MODE_DIGIT
{ {
// If the character is in the current table, we don't want to latch to // If the character is in the current table, we don't want to latch to
// any other mode except possibly digit (which uses only 4 bits). Any // any other mode except possibly digit (which uses only 4 bits). Any
// other latch would be equally successful *after* this character, and // other latch would be equally successful *after* this character, and
// so wouldn't save any bits. // so wouldn't save any bits.
let latchState = stateNoBinary let latch_state = state_no_binary
.clone() .clone()
.unwrap() .unwrap()
.latchAndAppend(mode as u32, charInMode as u32); .latchAndAppend(mode as u32, char_in_mode as u32);
result.push(latchState); result.push(latch_state);
} }
// Try generating the character by switching to its mode. // Try generating the character by switching to its mode.
if !charInCurrentTable && Self::SHIFT_TABLE[state.getMode() as usize][mode] >= 0 { if !char_in_current_table && Self::SHIFT_TABLE[state.getMode() as usize][mode] >= 0
{
// It never makes sense to temporarily shift to another mode if the // It never makes sense to temporarily shift to another mode if the
// character exists in the current mode. That can never save bits. // character exists in the current mode. That can never save bits.
let shiftState = stateNoBinary let shift_state = state_no_binary
.clone() .clone()
.unwrap() .unwrap()
.shiftAndAppend(mode as u32, charInMode as u32); .shiftAndAppend(mode as u32, char_in_mode as u32);
result.push(shiftState); result.push(shift_state);
} }
} }
} }
@@ -385,56 +396,56 @@ impl HighLevelEncoder {
// It's never worthwhile to go into binary shift mode if you're not already // It's never worthwhile to go into binary shift mode if you're not already
// in binary shift mode, and the character exists in your current mode. // in binary shift mode, and the character exists in your current mode.
// That can never save bits over just outputting the char in the current mode. // That can never save bits over just outputting the char in the current mode.
let binaryState = state.addBinaryShiftChar(index); let binary_state = state.addBinaryShiftChar(index);
result.push(binaryState); result.push(binary_state);
} }
} }
fn updateStateListForPair(states: Vec<State>, index: u32, pairCode: u32) -> Vec<State> { fn update_state_list_for_pair(states: Vec<State>, index: u32, pairCode: u32) -> Vec<State> {
let mut result = Vec::new(); let mut result = Vec::new();
for state in states { for state in states {
// for (State state : states) { // for (State state : states) {
Self::updateStateForPair(state, index, pairCode, &mut result); Self::update_state_for_pair(state, index, pairCode, &mut result);
} }
Self::simplifyStates(result) Self::simplify_states(result)
} }
fn updateStateForPair(state: State, index: u32, pairCode: u32, result: &mut Vec<State>) { fn update_state_for_pair(state: State, index: u32, pair_code: u32, result: &mut Vec<State>) {
let stateNoBinary = state.clone().endBinaryShift(index); let state_no_binary = state.clone().endBinaryShift(index);
// Possibility 1. Latch to MODE_PUNCT, and then append this code // Possibility 1. Latch to MODE_PUNCT, and then append this code
result.push( result.push(
stateNoBinary state_no_binary
.clone() .clone()
.latchAndAppend(Self::MODE_PUNCT as u32, pairCode), .latchAndAppend(Self::MODE_PUNCT as u32, pair_code),
); );
if state.getMode() != Self::MODE_PUNCT as u32 { if state.getMode() != Self::MODE_PUNCT as u32 {
// Possibility 2. Shift to MODE_PUNCT, and then append this code. // Possibility 2. Shift to MODE_PUNCT, and then append this code.
// Every state except MODE_PUNCT (handled above) can shift // Every state except MODE_PUNCT (handled above) can shift
result.push( result.push(
stateNoBinary state_no_binary
.clone() .clone()
.shiftAndAppend(Self::MODE_PUNCT as u32, pairCode), .shiftAndAppend(Self::MODE_PUNCT as u32, pair_code),
); );
} }
if pairCode == 3 || pairCode == 4 { if pair_code == 3 || pair_code == 4 {
// both characters are in DIGITS. Sometimes better to just add two digits // both characters are in DIGITS. Sometimes better to just add two digits
let digitState = stateNoBinary let digit_state = state_no_binary
.latchAndAppend(Self::MODE_DIGIT as u32, 16 - pairCode) // period or comma in DIGIT .latchAndAppend(Self::MODE_DIGIT as u32, 16 - pair_code) // period or comma in DIGIT
.latchAndAppend(Self::MODE_DIGIT as u32, 1); // space in DIGIT .latchAndAppend(Self::MODE_DIGIT as u32, 1); // space in DIGIT
result.push(digitState); result.push(digit_state);
} }
if state.getBinaryShiftByteCount() > 0 { if state.getBinaryShiftByteCount() > 0 {
// It only makes sense to do the characters as binary if we're already // It only makes sense to do the characters as binary if we're already
// in binary mode. // in binary mode.
let binaryState = state let binary_state = state
.addBinaryShiftChar(index) .addBinaryShiftChar(index)
.addBinaryShiftChar(index + 1); .addBinaryShiftChar(index + 1);
result.push(binaryState); result.push(binary_state);
} }
} }
fn simplifyStates(states: Vec<State>) -> Vec<State> { fn simplify_states(states: Vec<State>) -> Vec<State> {
let mut result: Vec<State> = Vec::new(); let mut result: Vec<State> = Vec::new();
for newState in states { for newState in states {
// for (State newState : states) { // for (State newState : states) {
@@ -442,13 +453,14 @@ impl HighLevelEncoder {
for i in 0..result.len() { for i in 0..result.len() {
// for st in result { // for st in result {
// for (Iterator<State> iterator = result.iterator(); iterator.hasNext();) { // for (Iterator<State> iterator = result.iterator(); iterator.hasNext();) {
let oldState = result.get(i).unwrap(); if let Some(oldState) = result.get(i) {
if oldState.isBetterThanOrEqualTo(&newState) { if oldState.isBetterThanOrEqualTo(&newState) {
add = false; add = false;
break; break;
} }
if newState.isBetterThanOrEqualTo(&oldState) { if newState.isBetterThanOrEqualTo(&oldState) {
result.remove(i); result.remove(i);
}
} }
} }
if add { if add {

View File

@@ -22,20 +22,20 @@ use crate::common::BitArray;
pub struct SimpleToken { pub struct SimpleToken {
// For normal words, indicates value and bitCount // For normal words, indicates value and bitCount
value: u16, value: u16,
bitCount: u16, bit_count: u16,
} }
impl SimpleToken { impl SimpleToken {
pub fn new(value: i32, bitCount: u32) -> Self { pub fn new(value: i32, bitCount: u32) -> Self {
Self { Self {
value: value as u16, value: value as u16,
bitCount: bitCount as u16, bit_count: bitCount as u16,
} }
} }
pub fn appendTo(&self, bitArray: &mut BitArray, text: &[u8]) { pub fn appendTo(&self, bit_array: &mut BitArray, text: &[u8]) {
bitArray bit_array
.appendBits(self.value as u32, self.bitCount as usize) .appendBits(self.value as u32, self.bit_count as usize)
.expect("append should never fail"); .expect("append should never fail");
} }
@@ -49,8 +49,8 @@ impl SimpleToken {
impl fmt::Display for SimpleToken { impl fmt::Display for SimpleToken {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut value = self.value & ((1 << self.bitCount) - 1); let mut value = self.value & ((1 << self.bit_count) - 1);
value |= 1 << self.bitCount; value |= 1 << self.bit_count;
write!(f, "<{:#016b}>", value | (1 << self.bitCount)) write!(f, "<{:#016b}>", value | (1 << self.bit_count))
} }
} }

View File

@@ -38,19 +38,19 @@ pub struct State {
token: Token, token: Token,
// If non-zero, the number of most recent bytes that should be output // If non-zero, the number of most recent bytes that should be output
// in Binary Shift mode. // in Binary Shift mode.
binaryShiftByteCount: u32, binary_shift_byte_count: u32,
// The total number of bits generated (including Binary Shift). // The total number of bits generated (including Binary Shift).
bitCount: u32, bit_count: u32,
binaryShiftCost: u32, binary_shift_cost: u32,
} }
impl State { impl State {
pub fn new(token: Token, mode: u32, binaryBytes: u32, bitCount: u32) -> Self { pub fn new(token: Token, mode: u32, binary_bytes: u32, bit_count: u32) -> Self {
Self { Self {
mode, mode,
token, token,
binaryShiftByteCount: binaryBytes, binary_shift_byte_count: binary_bytes,
bitCount, bit_count,
binaryShiftCost: Self::calculateBinaryShiftCost(binaryBytes), binary_shift_cost: Self::calculate_binary_shift_cost(binary_bytes),
} }
} }
@@ -63,19 +63,19 @@ impl State {
} }
pub fn getBinaryShiftByteCount(&self) -> u32 { pub fn getBinaryShiftByteCount(&self) -> u32 {
self.binaryShiftByteCount self.binary_shift_byte_count
} }
pub fn getBitCount(&self) -> u32 { pub fn getBitCount(&self) -> u32 {
self.bitCount self.bit_count
} }
pub fn appendFLGn(self, eci: u32) -> Result<Self, Exceptions> { pub fn appendFLGn(self, eci: u32) -> Result<Self, Exceptions> {
let bit_count = self.bitCount; let bit_count = self.bit_count;
let mode = self.mode; let mode = self.mode;
let result = self.shiftAndAppend(HighLevelEncoder::MODE_PUNCT as u32, 0); // 0: FLG(n) let result = self.shiftAndAppend(HighLevelEncoder::MODE_PUNCT as u32, 0); // 0: FLG(n)
let mut token = result.token; let mut token = result.token;
let mut bitsAdded = 3; let mut bits_added = 3;
if eci < 0 { if eci < 0 {
token.add(0, 3); // 0: FNC1 token.add(0, 3); // 0: FNC1
} else if eci > 999999 { } else if eci > 999999 {
@@ -84,25 +84,25 @@ impl State {
)); ));
// throw new IllegalArgumentException("ECI code must be between 0 and 999999"); // throw new IllegalArgumentException("ECI code must be between 0 and 999999");
} else { } else {
let eciDigits = encoding::all::ISO_8859_1 let eci_digits = encoding::all::ISO_8859_1
.encode(&format!("{}", eci), encoding::EncoderTrap::Replace) .encode(&format!("{}", eci), encoding::EncoderTrap::Replace)
.unwrap(); .unwrap();
// let eciDigits = Integer.toString(eci).getBytes(StandardCharsets.ISO_8859_1); // let eciDigits = Integer.toString(eci).getBytes(StandardCharsets.ISO_8859_1);
token.add(eciDigits.len() as i32, 3); // 1-6: number of ECI digits token.add(eci_digits.len() as i32, 3); // 1-6: number of ECI digits
for eciDigit in &eciDigits { for eci_digit in &eci_digits {
// for (byte eciDigit : eciDigits) { // for (byte eciDigit : eciDigits) {
token.add((eciDigit - b'0' + 2) as i32, 4); token.add((eci_digit - b'0' + 2) as i32, 4);
} }
bitsAdded += eciDigits.len() * 4; bits_added += eci_digits.len() * 4;
} }
Ok(State::new(token, mode, 0, bit_count + bitsAdded as u32)) Ok(State::new(token, mode, 0, bit_count + bits_added as u32))
// return new State(token, mode, 0, bitCount + bitsAdded); // return new State(token, mode, 0, bitCount + bitsAdded);
} }
// Create a new state representing this state with a latch to a (not // Create a new state representing this state with a latch to a (not
// necessary different) mode, and then a code. // necessary different) mode, and then a code.
pub fn latchAndAppend(self, mode: u32, value: u32) -> State { pub fn latchAndAppend(self, mode: u32, value: u32) -> State {
let mut bitCount = self.bitCount; let mut bitCount = self.bit_count;
let mut token = self.token; let mut token = self.token;
if mode != self.mode { if mode != self.mode {
let latch = HighLevelEncoder::LATCH_TABLE[self.mode as usize][mode as usize]; let latch = HighLevelEncoder::LATCH_TABLE[self.mode as usize][mode as usize];
@@ -134,7 +134,7 @@ impl State {
thisModeBitCount, thisModeBitCount,
); );
token.add(value as i32, 5); token.add(value as i32, 5);
State::new(token, self.mode, 0, self.bitCount + thisModeBitCount + 5) State::new(token, self.mode, 0, self.bit_count + thisModeBitCount + 5)
} }
// Create a new state representing this state, but an additional character // Create a new state representing this state, but an additional character
@@ -142,7 +142,7 @@ impl State {
pub fn addBinaryShiftChar(self, index: u32) -> State { pub fn addBinaryShiftChar(self, index: u32) -> State {
let mut token = self.token; let mut token = self.token;
let mut mode = self.mode; let mut mode = self.mode;
let mut bitCount = self.bitCount; let mut bitCount = self.bit_count;
if self.mode == HighLevelEncoder::MODE_PUNCT as u32 if self.mode == HighLevelEncoder::MODE_PUNCT as u32
|| self.mode == HighLevelEncoder::MODE_DIGIT as u32 || self.mode == HighLevelEncoder::MODE_DIGIT as u32
{ {
@@ -151,10 +151,10 @@ impl State {
bitCount += latch >> 16; bitCount += latch >> 16;
mode = HighLevelEncoder::MODE_UPPER as u32; mode = HighLevelEncoder::MODE_UPPER as u32;
} }
let deltaBitCount = if self.binaryShiftByteCount == 0 || self.binaryShiftByteCount == 31 { let deltaBitCount = if self.binary_shift_byte_count == 0 || self.binary_shift_byte_count == 31 {
18 18
} else { } else {
if self.binaryShiftByteCount == 62 { if self.binary_shift_byte_count == 62 {
9 9
} else { } else {
8 8
@@ -163,10 +163,10 @@ impl State {
let mut result = State::new( let mut result = State::new(
token, token,
mode, mode,
self.binaryShiftByteCount + 1, self.binary_shift_byte_count + 1,
bitCount + deltaBitCount, bitCount + deltaBitCount,
); );
if result.binaryShiftByteCount == 2047 + 31 { if result.binary_shift_byte_count == 2047 + 31 {
// The string is as long as it's allowed to be. We should end it. // The string is as long as it's allowed to be. We should end it.
result = result.endBinaryShift(index + 1); result = result.endBinaryShift(index + 1);
} }
@@ -176,30 +176,30 @@ impl State {
// Create the state identical to this one, but we are no longer in // Create the state identical to this one, but we are no longer in
// Binary Shift mode. // Binary Shift mode.
pub fn endBinaryShift(self, index: u32) -> State { pub fn endBinaryShift(self, index: u32) -> State {
if self.binaryShiftByteCount == 0 { if self.binary_shift_byte_count == 0 {
return self; return self;
} }
let mut token = self.token; let mut token = self.token;
token.addBinaryShift(index - self.binaryShiftByteCount, self.binaryShiftByteCount); token.addBinaryShift(index - self.binary_shift_byte_count, self.binary_shift_byte_count);
State::new(token, self.mode, 0, self.bitCount) State::new(token, self.mode, 0, self.bit_count)
} }
// Returns true if "this" state is better (or equal) to be in than "that" // Returns true if "this" state is better (or equal) to be in than "that"
// state under all possible circumstances. // state under all possible circumstances.
pub fn isBetterThanOrEqualTo(&self, other: &State) -> bool { pub fn isBetterThanOrEqualTo(&self, other: &State) -> bool {
let mut newModeBitCount = self.bitCount let mut new_mode_bit_count = self.bit_count
+ (HighLevelEncoder::LATCH_TABLE[self.mode as usize][other.mode as usize] >> 16); + (HighLevelEncoder::LATCH_TABLE[self.mode as usize][other.mode as usize] >> 16);
if self.binaryShiftByteCount < other.binaryShiftByteCount { if self.binary_shift_byte_count < other.binary_shift_byte_count {
// add additional B/S encoding cost of other, if any // add additional B/S encoding cost of other, if any
newModeBitCount += other.binaryShiftCost - self.binaryShiftCost; new_mode_bit_count += other.binary_shift_cost - self.binary_shift_cost;
} else if self.binaryShiftByteCount > other.binaryShiftByteCount } else if self.binary_shift_byte_count > other.binary_shift_byte_count
&& other.binaryShiftByteCount > 0 && other.binary_shift_byte_count > 0
{ {
// maximum possible additional cost (we end up exceeding the 31 byte boundary and other state can stay beneath it) // maximum possible additional cost (we end up exceeding the 31 byte boundary and other state can stay beneath it)
newModeBitCount += 10; new_mode_bit_count += 10;
} }
newModeBitCount <= other.bitCount new_mode_bit_count <= other.bit_count
} }
pub fn toBitArray(self, text: &[u8]) -> BitArray { pub fn toBitArray(self, text: &[u8]) -> BitArray {
@@ -215,28 +215,24 @@ impl State {
// symbols.push(tkn); // symbols.push(tkn);
// tkn = tok.getPrevious(); // tkn = tok.getPrevious();
// } // }
let mut bitArray = BitArray::new(); let mut bit_array = BitArray::new();
// Add each token to the result in forward order // Add each token to the result in forward order
for i in (0..symbols.len() - 1).rev() { for symbol in symbols.into_iter().rev() {
// for i in (0..symbols.len()).rev() {
// for (int i = symbols.size() - 1; i >= 0; i--) { // for (int i = symbols.size() - 1; i >= 0; i--) {
symbols.get(i).unwrap().appendTo(&mut bitArray, text); symbol.appendTo(&mut bit_array, text);
} }
bitArray bit_array
} }
// @Override fn calculate_binary_shift_cost(binary_shift_byte_count: u32) -> u32 {
// public String toString() { if binary_shift_byte_count > 62 {
// return String.format("%s bits=%d bytes=%d", HighLevelEncoder.MODE_NAMES[mode], bitCount, binaryShiftByteCount);
// }
fn calculateBinaryShiftCost(binaryShiftByteCount: u32) -> u32 {
if binaryShiftByteCount > 62 {
return 21; // B/S with extended length return 21; // B/S with extended length
} }
if binaryShiftByteCount > 31 { if binary_shift_byte_count > 31 {
return 20; // two B/S return 20; // two B/S
} }
if binaryShiftByteCount > 0 { if binary_shift_byte_count > 0 {
return 10; // one B/S return 10; // one B/S
} }
return 0; return 0;
@@ -249,8 +245,8 @@ impl fmt::Display for State {
f, f,
"{} bits={} bytes={}", "{} bits={} bytes={}",
HighLevelEncoder::MODE_NAMES[self.mode as usize], HighLevelEncoder::MODE_NAMES[self.mode as usize],
self.bitCount, self.bit_count,
self.binaryShiftByteCount self.binary_shift_byte_count
) )
} }
} }

View File

@@ -9,9 +9,9 @@ pub fn toBitArray( bits:&str) -> BitArray{
let mut ba_in = BitArray::new(); let mut ba_in = BitArray::new();
let replacer_regex = Regex::new(DOTX).unwrap(); let replacer_regex = Regex::new(DOTX).unwrap();
let str = replacer_regex.replace_all(bits, ""); let str = replacer_regex.replace_all(bits, "");
for aStr in str.chars() { for a_str in str.chars() {
// for (char aStr : str) { // for (char aStr : str) {
ba_in.appendBit(aStr == 'X'); ba_in.appendBit(a_str == 'X');
} }
ba_in ba_in

View File

@@ -148,6 +148,21 @@ use rand::Rng;
} }
} }
#[test]
fn test_append_bit(){
let mut array = BitArray::new();
array.appendBits(0x000001E, 6);
let mut array_2 = BitArray::new();
array_2.appendBit(false);
array_2.appendBit(true);
array_2.appendBit(true);
array_2.appendBit(true);
array_2.appendBit(true);
array_2.appendBit(false);
assert_eq!(array, array_2)
}
#[test] #[test]
fn test_set_range() { fn test_set_range() {
let mut array = BitArray::with_size(64); let mut array = BitArray::with_size(64);

View File

@@ -552,14 +552,19 @@ impl BitArray {
* @param numBits bits from value to append * @param numBits bits from value to append
*/ */
pub fn appendBits(&mut self, value: u32, numBits: usize) -> Result<(), Exceptions> { pub fn appendBits(&mut self, value: u32, numBits: usize) -> Result<(), Exceptions> {
if numBits < 0 || numBits > 32 { if numBits > 32 {
return Err(Exceptions::IllegalArgumentException( return Err(Exceptions::IllegalArgumentException(
"Num bits must be between 0 and 32".to_owned(), "Num bits must be between 0 and 32".to_owned(),
)); ));
} }
if numBits == 0 {
return Ok(());
}
let mut 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)).rev() {
//for (int numBitsLeft = numBits - 1; numBitsLeft >= 0; numBitsLeft--) { //for (int numBitsLeft = numBits - 1; numBitsLeft >= 0; numBitsLeft--) {
if (value & (1 << numBitsLeft)) != 0 { if (value & (1 << numBitsLeft)) != 0 {
self.bits[nextSize / 32] |= 1 << (nextSize & 0x1F); self.bits[nextSize / 32] |= 1 << (nextSize & 0x1F);
@@ -720,10 +725,9 @@ impl fmt::Display for BitArray {
* @author Sean Owen * @author Sean Owen
*/ */
pub trait DetectorRXingResult { pub trait DetectorRXingResult {
fn getBits(&self) -> &BitMatrix;
fn getBits(&self) -> &BitMatrix; fn getPoints(&self) -> &Vec<RXingResultPoint>;
fn getPoints(&self) -> &Vec<RXingResultPoint>;
} }
// pub struct DetectorRXingResult { // pub struct DetectorRXingResult {
@@ -841,25 +845,25 @@ impl BitMatrix {
} }
pub fn parse_strings( pub fn parse_strings(
stringRepresentation: &str, string_representation: &str,
setString: &str, set_string: &str,
unsetString: &str, unset_string: &str,
) -> Result<Self, Exceptions> { ) -> Result<Self, Exceptions> {
// cannot pass nulls in rust // cannot pass nulls in rust
// if (stringRepresentation == null) { // if (stringRepresentation == null) {
// throw new IllegalArgumentException(); // throw new IllegalArgumentException();
// } // }
let mut bits = vec![false; stringRepresentation.len()]; let mut bits = vec![false; string_representation.len()];
let mut bitsPos = 0; let mut bitsPos = 0;
let mut rowStartPos = 0; let mut rowStartPos = 0;
let mut rowLength = 0; //-1; let mut rowLength = 0; //-1;
let mut first_run = true; let mut first_run = true;
let mut nRows = 0; let mut nRows = 0;
let mut pos = 0; let mut pos = 0;
while pos < stringRepresentation.len() { while pos < string_representation.len() {
if stringRepresentation.chars().nth(pos).unwrap() == '\n' if string_representation.chars().nth(pos).unwrap() == '\n'
|| stringRepresentation.chars().nth(pos).unwrap() == '\r' || string_representation.chars().nth(pos).unwrap() == '\r'
{ {
if bitsPos > rowStartPos { if bitsPos > rowStartPos {
//if rowLength == -1 { //if rowLength == -1 {
@@ -875,18 +879,18 @@ impl BitMatrix {
nRows += 1; nRows += 1;
} }
pos += 1; pos += 1;
} else if stringRepresentation[pos..].starts_with(setString) { } else if string_representation[pos..].starts_with(set_string) {
pos += setString.len(); pos += set_string.len();
bits[bitsPos] = true; bits[bitsPos] = true;
bitsPos += 1; bitsPos += 1;
} else if stringRepresentation[pos..].starts_with(unsetString) { } else if string_representation[pos..].starts_with(unset_string) {
pos += unsetString.len(); pos += unset_string.len();
bits[bitsPos] = false; bits[bitsPos] = false;
bitsPos += 1; bitsPos += 1;
} else { } else {
return Err(Exceptions::IllegalArgumentException(format!( return Err(Exceptions::IllegalArgumentException(format!(
"illegal character encountered: {}", "illegal character encountered: {}",
stringRepresentation[pos..].to_owned() string_representation[pos..].to_owned()
))); )));
} }
} }
@@ -975,7 +979,8 @@ impl BitMatrix {
* @param mask XOR mask * @param mask XOR mask
*/ */
pub fn xor(&mut self, mask: &BitMatrix) -> Result<(), Exceptions> { pub fn xor(&mut self, mask: &BitMatrix) -> Result<(), Exceptions> {
if self.width != mask.width || self.height != mask.height || self.row_size != mask.row_size { if self.width != mask.width || self.height != mask.height || self.row_size != mask.row_size
{
return Err(Exceptions::IllegalArgumentException( return Err(Exceptions::IllegalArgumentException(
"input matrix dimensions do not match".to_owned(), "input matrix dimensions do not match".to_owned(),
)); ));
@@ -2398,6 +2403,7 @@ impl GridSampler for DefaultGridSampler {
* *
* @author Sean Owen * @author Sean Owen
*/ */
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CharacterSetECI { pub enum CharacterSetECI {
// Enum name is a Java encoding valid for java.lang and java.io // Enum name is a Java encoding valid for java.lang and java.io
Cp437, //(new int[]{0,2}), Cp437, //(new int[]{0,2}),
@@ -2531,34 +2537,34 @@ impl CharacterSetECI {
* but unsupported * but unsupported
*/ */
pub fn getCharacterSetECI(charset: &'static dyn Encoding) -> Option<CharacterSetECI> { pub fn getCharacterSetECI(charset: &'static dyn Encoding) -> Option<CharacterSetECI> {
match charset.whatwg_name().unwrap() { match charset.name() {
"CP437" => Some(CharacterSetECI::Cp437), "CP437" => Some(CharacterSetECI::Cp437),
"ISO-8859-1" => Some(CharacterSetECI::ISO8859_1), "iso-8859-1" => Some(CharacterSetECI::ISO8859_1),
"ISO-8859-2" => Some(CharacterSetECI::ISO8859_2), "iso-8859-2" => Some(CharacterSetECI::ISO8859_2),
"ISO-8859-3" => Some(CharacterSetECI::ISO8859_3), "iso-8859-3" => Some(CharacterSetECI::ISO8859_3),
"ISO-8859-4" => Some(CharacterSetECI::ISO8859_4), "iso-8859-4" => Some(CharacterSetECI::ISO8859_4),
"ISO-8859-5" => Some(CharacterSetECI::ISO8859_5), "iso-8859-5" => Some(CharacterSetECI::ISO8859_5),
"ISO-8859-6" => Some(CharacterSetECI::ISO8859_6), "iso-8859-6" => Some(CharacterSetECI::ISO8859_6),
"ISO-8859-7" => Some(CharacterSetECI::ISO8859_7), "iso-8859-7" => Some(CharacterSetECI::ISO8859_7),
"ISO-8859-8" => Some(CharacterSetECI::ISO8859_8), "iso-8859-8" => Some(CharacterSetECI::ISO8859_8),
"ISO-8859-9" => Some(CharacterSetECI::ISO8859_9), "iso-8859-9" => Some(CharacterSetECI::ISO8859_9),
"ISO-8859-10" => Some(CharacterSetECI::ISO8859_10), "iso-8859-10" => Some(CharacterSetECI::ISO8859_10),
"ISO-8859-11" => Some(CharacterSetECI::ISO8859_11), "iso-8859-11" => Some(CharacterSetECI::ISO8859_11),
"ISO-8859-13" => Some(CharacterSetECI::ISO8859_13), "iso-8859-13" => Some(CharacterSetECI::ISO8859_13),
"ISO-8859-14" => Some(CharacterSetECI::ISO8859_14), "iso-8859-14" => Some(CharacterSetECI::ISO8859_14),
"ISO-8859-15" => Some(CharacterSetECI::ISO8859_15), "iso-8859-15" => Some(CharacterSetECI::ISO8859_15),
"ISO-8859-16" => Some(CharacterSetECI::ISO8859_16), "iso-8859-16" => Some(CharacterSetECI::ISO8859_16),
"Shift_JIS" => Some(CharacterSetECI::SJIS), "shift_jis" => Some(CharacterSetECI::SJIS),
"windows-1250" => Some(CharacterSetECI::Cp1250), "windows-1250" => Some(CharacterSetECI::Cp1250),
"windows-1251" => Some(CharacterSetECI::Cp1251), "windows-1251" => Some(CharacterSetECI::Cp1251),
"windows-1252" => Some(CharacterSetECI::Cp1252), "windows-1252" => Some(CharacterSetECI::Cp1252),
"windows-1256" => Some(CharacterSetECI::Cp1256), "windows-1256" => Some(CharacterSetECI::Cp1256),
"UTF-16BE" => Some(CharacterSetECI::UnicodeBigUnmarked), "utf-16be" => Some(CharacterSetECI::UnicodeBigUnmarked),
"UTF-8" => Some(CharacterSetECI::UTF8), "utf-8" => Some(CharacterSetECI::UTF8),
"US-ASCII" => Some(CharacterSetECI::ASCII), "us-ascii" => Some(CharacterSetECI::ASCII),
"Big5" => Some(CharacterSetECI::Big5), "big5" => Some(CharacterSetECI::Big5),
"GB2312" => Some(CharacterSetECI::GB18030), "gb2312" => Some(CharacterSetECI::GB18030),
"EUC-KR" => Some(CharacterSetECI::EUC_KR), "euc-kr" => Some(CharacterSetECI::EUC_KR),
_ => None, _ => None,
} }
} }
@@ -4052,6 +4058,9 @@ impl HybridBinarizer {
blackPoints[y as usize][x as usize] = average; blackPoints[y as usize][x as usize] = average;
} }
} }
return blackPoints.into_iter().map(|x| x.iter().map(|y| *y as u32).collect()).collect(); return blackPoints
.into_iter()
.map(|x| x.iter().map(|y| *y as u32).collect())
.collect();
} }
} }