diff --git a/port_src/core/src/main/java/com/google/zxing/common/BitArray.java b/port_src/core/DONE/common/BitArray.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/BitArray.java
rename to port_src/core/DONE/common/BitArray.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/BitMatrix.java b/port_src/core/DONE/common/BitMatrix.java
old mode 100755
new mode 100644
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/BitMatrix.java
rename to port_src/core/DONE/common/BitMatrix.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/BitSource.java b/port_src/core/DONE/common/BitSource.java
old mode 100755
new mode 100644
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/BitSource.java
rename to port_src/core/DONE/common/BitSource.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/CharacterSetECI.java b/port_src/core/DONE/common/CharacterSetECI.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/CharacterSetECI.java
rename to port_src/core/DONE/common/CharacterSetECI.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/DecoderResult.java b/port_src/core/DONE/common/DecoderResult.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/DecoderResult.java
rename to port_src/core/DONE/common/DecoderResult.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/DefaultGridSampler.java b/port_src/core/DONE/common/DefaultGridSampler.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/DefaultGridSampler.java
rename to port_src/core/DONE/common/DefaultGridSampler.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/DetectorResult.java b/port_src/core/DONE/common/DetectorResult.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/DetectorResult.java
rename to port_src/core/DONE/common/DetectorResult.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/ECIEncoderSet.java b/port_src/core/DONE/common/ECIEncoderSet.java
old mode 100755
new mode 100644
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/ECIEncoderSet.java
rename to port_src/core/DONE/common/ECIEncoderSet.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/ECIInput.java b/port_src/core/DONE/common/ECIInput.java
old mode 100755
new mode 100644
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/ECIInput.java
rename to port_src/core/DONE/common/ECIInput.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/ECIStringBuilder.java b/port_src/core/DONE/common/ECIStringBuilder.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/ECIStringBuilder.java
rename to port_src/core/DONE/common/ECIStringBuilder.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/GlobalHistogramBinarizer.java b/port_src/core/DONE/common/GlobalHistogramBinarizer.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/GlobalHistogramBinarizer.java
rename to port_src/core/DONE/common/GlobalHistogramBinarizer.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/GridSampler.java b/port_src/core/DONE/common/GridSampler.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/GridSampler.java
rename to port_src/core/DONE/common/GridSampler.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/HybridBinarizer.java b/port_src/core/DONE/common/HybridBinarizer.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/HybridBinarizer.java
rename to port_src/core/DONE/common/HybridBinarizer.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/MinimalECIInput.java b/port_src/core/DONE/common/MinimalECIInput.java
old mode 100755
new mode 100644
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/MinimalECIInput.java
rename to port_src/core/DONE/common/MinimalECIInput.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/PerspectiveTransform.java b/port_src/core/DONE/common/PerspectiveTransform.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/PerspectiveTransform.java
rename to port_src/core/DONE/common/PerspectiveTransform.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/StringUtils.java b/port_src/core/DONE/common/StringUtils.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/StringUtils.java
rename to port_src/core/DONE/common/StringUtils.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/detector/MathUtils.java b/port_src/core/DONE/common/detector/MathUtils.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/detector/MathUtils.java
rename to port_src/core/DONE/common/detector/MathUtils.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/detector/MonochromeRectangleDetector.java b/port_src/core/DONE/common/detector/MonochromeRectangleDetector.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/detector/MonochromeRectangleDetector.java
rename to port_src/core/DONE/common/detector/MonochromeRectangleDetector.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/detector/WhiteRectangleDetector.java b/port_src/core/DONE/common/detector/WhiteRectangleDetector.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/detector/WhiteRectangleDetector.java
rename to port_src/core/DONE/common/detector/WhiteRectangleDetector.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/reedsolomon/GenericGF.java b/port_src/core/DONE/common/reedsolomon/GenericGF.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/reedsolomon/GenericGF.java
rename to port_src/core/DONE/common/reedsolomon/GenericGF.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/reedsolomon/GenericGFPoly.java b/port_src/core/DONE/common/reedsolomon/GenericGFPoly.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/reedsolomon/GenericGFPoly.java
rename to port_src/core/DONE/common/reedsolomon/GenericGFPoly.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonDecoder.java b/port_src/core/DONE/common/reedsolomon/ReedSolomonDecoder.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonDecoder.java
rename to port_src/core/DONE/common/reedsolomon/ReedSolomonDecoder.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java b/port_src/core/DONE/common/reedsolomon/ReedSolomonEncoder.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java
rename to port_src/core/DONE/common/reedsolomon/ReedSolomonEncoder.java
diff --git a/port_src/core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonException.java b/port_src/core/DONE/common/reedsolomon/ReedSolomonException.java
similarity index 100%
rename from port_src/core/src/main/java/com/google/zxing/common/reedsolomon/ReedSolomonException.java
rename to port_src/core/DONE/common/reedsolomon/ReedSolomonException.java
diff --git a/port_src/output/zxing/common/bit_array.rs b/port_src/output/zxing/common/bit_array.rs
deleted file mode 100644
index 2ec9762..0000000
--- a/port_src/output/zxing/common/bit_array.rs
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- *
A simple, fast array of bits, represented compactly by an array of ints internally.
- *
- * @author Sean Owen
- */
-
- const EMPTY_BITS;
-
- const LOAD_FACTOR: f32 = 0.75f;
-#[derive(Cloneable)]
-pub struct BitArray {
-
- let mut bits: Vec;
-
- let mut size: i32;
-}
-
-impl BitArray {
-
- pub fn new() -> BitArray {
- let .size = 0;
- let .bits = EMPTY_BITS;
- }
-
- pub fn new( size: i32) -> BitArray {
- let .size = size;
- let .bits = ::make_array(size);
- }
-
- // For testing only
- fn new( bits: &Vec, size: i32) -> BitArray {
- let .bits = bits;
- let .size = size;
- }
-
- pub fn get_size(&self) -> i32 {
- return self.size;
- }
-
- pub fn get_size_in_bytes(&self) -> i32 {
- return (self.size + 7) / 8;
- }
-
- fn ensure_capacity(&self, new_size: i32) {
- if new_size > self.bits.len() * 32 {
- let new_bits: Vec = ::make_array(Math::ceil(new_size / LOAD_FACTOR) as i32);
- System::arraycopy(&self.bits, 0, &new_bits, 0, self.bits.len());
- self.bits = new_bits;
- }
- }
-
- /**
- * @param i bit to get
- * @return true iff bit i is set
- */
- pub fn get(&self, i: i32) -> bool {
- return (self.bits[i / 32] & (1 << (i & 0x1F))) != 0;
- }
-
- /**
- * Sets bit i.
- *
- * @param i bit to set
- */
- pub fn set(&self, i: i32) {
- self.bits[i / 32] |= 1 << (i & 0x1F);
- }
-
- /**
- * Flips bit i.
- *
- * @param i bit to set
- */
- pub fn flip(&self, i: i32) {
- self.bits[i / 32] ^= 1 << (i & 0x1F);
- }
-
- /**
- * @param from first bit to check
- * @return index of first bit that is set, starting from the given index, or size if none are set
- * at or beyond this given index
- * @see #getNextUnset(int)
- */
- pub fn get_next_set(&self, from: i32) -> i32 {
- if from >= self.size {
- return self.size;
- }
- let bits_offset: i32 = from / 32;
- let current_bits: i32 = self.bits[bits_offset];
- // mask off lesser bits first
- current_bits &= -(1 << (from & 0x1F));
- while current_bits == 0 {
- if bits_offset += 1 == self.bits.len() {
- return self.size;
- }
- current_bits = self.bits[bits_offset];
- }
- let result: i32 = (bits_offset * 32) + Integer::number_of_trailing_zeros(current_bits);
- return Math::min(result, self.size);
- }
-
- /**
- * @param from index to start looking for unset bit
- * @return index of next unset bit, or {@code size} if none are unset until the end
- * @see #getNextSet(int)
- */
- pub fn get_next_unset(&self, from: i32) -> i32 {
- if from >= self.size {
- return self.size;
- }
- let bits_offset: i32 = from / 32;
- let current_bits: i32 = ~self.bits[bits_offset];
- // mask off lesser bits first
- current_bits &= -(1 << (from & 0x1F));
- while current_bits == 0 {
- if bits_offset += 1 == self.bits.len() {
- return self.size;
- }
- current_bits = ~self.bits[bits_offset];
- }
- let result: i32 = (bits_offset * 32) + Integer::number_of_trailing_zeros(current_bits);
- return Math::min(result, self.size);
- }
-
- /**
- * Sets a block of 32 bits, starting at bit i.
- *
- * @param i first bit to set
- * @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.
- */
- pub fn set_bulk(&self, i: i32, new_bits: i32) {
- self.bits[i / 32] = new_bits;
- }
-
- /**
- * Sets a range of bits.
- *
- * @param start start of range, inclusive.
- * @param end end of range, exclusive
- */
- pub fn set_range(&self, start: i32, end: i32) {
- if end < start || start < 0 || end > self.size {
- throw IllegalArgumentException::new();
- }
- if end == start {
- return;
- }
- // will be easier to treat this as the last actually set bit -- inclusive
- end -= 1;
- let first_int: i32 = start / 32;
- let last_int: i32 = end / 32;
- {
- let mut i: i32 = first_int;
- while i <= last_int {
- {
- let first_bit: i32 = if i > first_int { 0 } else { start & 0x1F };
- let last_bit: i32 = if i < last_int { 31 } else { end & 0x1F };
- // Ones from firstBit to lastBit, inclusive
- let mask: i32 = (2 << last_bit) - (1 << first_bit);
- self.bits[i] |= mask;
- }
- i += 1;
- }
- }
-
- }
-
- /**
- * Clears all bits (sets to false).
- */
- pub fn clear(&self) {
- let max: i32 = self.bits.len();
- {
- let mut i: i32 = 0;
- while i < max {
- {
- self.bits[i] = 0;
- }
- i += 1;
- }
- }
-
- }
-
- /**
- * Efficient method to check if a range of bits is set, or not set.
- *
- * @param start start of range, inclusive.
- * @param end end of range, exclusive
- * @param value if true, checks that bits in range are set, otherwise checks that they are not set
- * @return true iff all bits are set or not set in range, according to value argument
- * @throws IllegalArgumentException if end is less than start or the range is not contained in the array
- */
- pub fn is_range(&self, start: i32, end: i32, value: bool) -> bool {
- if end < start || start < 0 || end > self.size {
- throw IllegalArgumentException::new();
- }
- if end == start {
- // empty range matches
- return true;
- }
- // will be easier to treat this as the last actually set bit -- inclusive
- end -= 1;
- let first_int: i32 = start / 32;
- let last_int: i32 = end / 32;
- {
- let mut i: i32 = first_int;
- while i <= last_int {
- {
- let first_bit: i32 = if i > first_int { 0 } else { start & 0x1F };
- let last_bit: i32 = if i < last_int { 31 } else { end & 0x1F };
- // Ones from firstBit to lastBit, inclusive
- let mask: i32 = (2 << last_bit) - (1 << first_bit);
- // equals the mask, or we're looking for 0s and the masked portion is not all 0s
- if (self.bits[i] & mask) != ( if value { mask } else { 0 }) {
- return false;
- }
- }
- i += 1;
- }
- }
-
- return true;
- }
-
- pub fn append_bit(&self, bit: bool) {
- self.ensure_capacity(self.size + 1);
- if bit {
- self.bits[self.size / 32] |= 1 << (self.size & 0x1F);
- }
- self.size += 1;
- }
-
- /**
- * Appends the least-significant bits, from value, in order from most-significant to
- * least-significant. For example, appending 6 bits from 0x000001E will append the bits
- * 0, 1, 1, 1, 1, 0 in that order.
- *
- * @param value {@code int} containing bits to append
- * @param numBits bits from value to append
- */
- pub fn append_bits(&self, value: i32, num_bits: i32) {
- if num_bits < 0 || num_bits > 32 {
- throw IllegalArgumentException::new("Num bits must be between 0 and 32");
- }
- let next_size: i32 = self.size;
- self.ensure_capacity(next_size + num_bits);
- {
- let num_bits_left: i32 = num_bits - 1;
- while num_bits_left >= 0 {
- {
- if (value & (1 << num_bits_left)) != 0 {
- self.bits[next_size / 32] |= 1 << (next_size & 0x1F);
- }
- next_size += 1;
- }
- num_bits_left -= 1;
- }
- }
-
- self.size = next_size;
- }
-
- pub fn append_bit_array(&self, other: &BitArray) {
- let other_size: i32 = other.size;
- self.ensure_capacity(self.size + other_size);
- {
- let mut i: i32 = 0;
- while i < other_size {
- {
- self.append_bit(&other.get(i));
- }
- i += 1;
- }
- }
-
- }
-
- pub fn xor(&self, other: &BitArray) {
- if self.size != other.size {
- throw IllegalArgumentException::new("Sizes don't match");
- }
- {
- let mut i: i32 = 0;
- while i < self.bits.len() {
- {
- // The last int could be incomplete (i.e. not have 32 bits in
- // it) but there is no problem since 0 XOR 0 == 0.
- self.bits[i] ^= other.bits[i];
- }
- i += 1;
- }
- }
-
- }
-
- /**
- *
- * @param bitOffset first bit to start writing
- * @param array array to write into. Bytes are written most-significant byte first. This is the opposite
- * of the internal representation, which is exposed by {@link #getBitArray()}
- * @param offset position in array to start writing
- * @param numBytes how many bytes to write
- */
- pub fn to_bytes(&self, bit_offset: i32, array: &Vec, offset: i32, num_bytes: i32) {
- {
- let mut i: i32 = 0;
- while i < num_bytes {
- {
- let the_byte: i32 = 0;
- {
- let mut j: i32 = 0;
- while j < 8 {
- {
- if self.get(bit_offset) {
- the_byte |= 1 << (7 - j);
- }
- bit_offset += 1;
- }
- j += 1;
- }
- }
-
- array[offset + i] = the_byte as i8;
- }
- i += 1;
- }
- }
-
- }
-
- /**
- * @return underlying array of ints. The first element holds the first 32 bits, and the least
- * significant bit is bit 0.
- */
- pub fn get_bit_array(&self) -> Vec {
- return self.bits;
- }
-
- /**
- * Reverses all bits in the array.
- */
- pub fn reverse(&self) {
- let new_bits: [i32; self.bits.len()] = [0; self.bits.len()];
- // reverse all int's first
- let mut len: i32 = (self.size - 1) / 32;
- let old_bits_len: i32 = len + 1;
- {
- let mut i: i32 = 0;
- while i < old_bits_len {
- {
- new_bits[len - i] = Integer::reverse(self.bits[i]);
- }
- i += 1;
- }
- }
-
- // now correct the int's if the bit size isn't a multiple of 32
- if self.size != old_bits_len * 32 {
- let left_offset: i32 = old_bits_len * 32 - self.size;
- let current_int: i32 = new_bits[0] >> /* >>> */ left_offset;
- {
- let mut i: i32 = 1;
- while i < old_bits_len {
- {
- let next_int: i32 = new_bits[i];
- current_int |= next_int << (32 - left_offset);
- new_bits[i - 1] = current_int;
- current_int = next_int >> /* >>> */ left_offset;
- }
- i += 1;
- }
- }
-
- new_bits[old_bits_len - 1] = current_int;
- }
- self.bits = new_bits;
- }
-
- fn make_array( size: i32) -> Vec {
- return : [i32; (size + 31) / 32] = [0; (size + 31) / 32];
- }
-
- pub fn equals(&self, o: &Object) -> bool {
- if !(o instanceof BitArray) {
- return false;
- }
- let other: BitArray = o as BitArray;
- return self.size == other.size && Arrays::equals(&self.bits, other.bits);
- }
-
- pub fn hash_code(&self) -> i32 {
- return 31 * self.size + Arrays::hash_code(&self.bits);
- }
-
- pub fn to_string(&self) -> String {
- let result: StringBuilder = StringBuilder::new(self.size + (self.size / 8) + 1);
- {
- let mut i: i32 = 0;
- while i < self.size {
- {
- if (i & 0x07) == 0 {
- result.append(' ');
- }
- result.append( if self.get(i) { 'X' } else { '.' });
- }
- i += 1;
- }
- }
-
- return result.to_string();
- }
-
- pub fn clone(&self) -> BitArray {
- return BitArray::new(&self.bits.clone(), self.size);
- }
-}
-
diff --git a/port_src/output/zxing/common/bit_matrix.rs b/port_src/output/zxing/common/bit_matrix.rs
deleted file mode 100644
index 80ce885..0000000
--- a/port_src/output/zxing/common/bit_matrix.rs
+++ /dev/null
@@ -1,652 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * Represents a 2D matrix of bits. In function arguments below, and throughout the common
- * module, x is the column position, and y is the row position. The ordering is always x, y.
- * The origin is at the top-left.
- *
- * Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins
- * with a new int. This is done intentionally so that we can copy out a row into a BitArray very
- * efficiently.
- *
- * The ordering of bits is row-major. Within each int, the least significant bits are used first,
- * meaning they represent lower x values. This is compatible with BitArray's implementation.
- *
- * @author Sean Owen
- * @author dswitkin@google.com (Daniel Switkin)
- */
-#[derive(Cloneable)]
-pub struct BitMatrix {
-
- let mut width: i32;
-
- let mut height: i32;
-
- let row_size: i32;
-
- let mut bits: Vec;
-}
-
-impl BitMatrix {
-
- /**
- * Creates an empty square {@code BitMatrix}.
- *
- * @param dimension height and width
- */
- pub fn new( dimension: i32) -> BitMatrix {
- this(dimension, dimension);
- }
-
- /**
- * Creates an empty {@code BitMatrix}.
- *
- * @param width bit matrix width
- * @param height bit matrix height
- */
- pub fn new( width: i32, height: i32) -> BitMatrix {
- if width < 1 || height < 1 {
- throw IllegalArgumentException::new("Both dimensions must be greater than 0");
- }
- let .width = width;
- let .height = height;
- let .rowSize = (width + 31) / 32;
- bits = : [i32; row_size * height] = [0; row_size * height];
- }
-
- fn new( width: i32, height: i32, row_size: i32, bits: &Vec) -> BitMatrix {
- let .width = width;
- let .height = height;
- let .rowSize = row_size;
- let .bits = bits;
- }
-
- /**
- * Interprets a 2D array of booleans as a {@code BitMatrix}, where "true" means an "on" bit.
- *
- * @param image bits of the image, as a row-major 2D array. Elements are arrays representing rows
- * @return {@code BitMatrix} representation of image
- */
- pub fn parse( image: &Vec>) -> BitMatrix {
- let height: i32 = image.len();
- let width: i32 = image[0].len();
- let bits: BitMatrix = BitMatrix::new(width, height);
- {
- let mut i: i32 = 0;
- while i < height {
- {
- let image_i: Vec = image[i];
- {
- let mut j: i32 = 0;
- while j < width {
- {
- if image_i[j] {
- bits.set(j, i);
- }
- }
- j += 1;
- }
- }
-
- }
- i += 1;
- }
- }
-
- return bits;
- }
-
- pub fn parse( string_representation: &String, set_string: &String, unset_string: &String) -> BitMatrix {
- if string_representation == null {
- throw IllegalArgumentException::new();
- }
- let mut bits: [bool; string_representation.length()] = [false; string_representation.length()];
- let bits_pos: i32 = 0;
- let row_start_pos: i32 = 0;
- let row_length: i32 = -1;
- let n_rows: i32 = 0;
- let mut pos: i32 = 0;
- while pos < string_representation.length() {
- if string_representation.char_at(pos) == '\n' || string_representation.char_at(pos) == '\r' {
- if bits_pos > row_start_pos {
- if row_length == -1 {
- row_length = bits_pos - row_start_pos;
- } else if bits_pos - row_start_pos != row_length {
- throw IllegalArgumentException::new("row lengths do not match");
- }
- row_start_pos = bits_pos;
- n_rows += 1;
- }
- pos += 1;
- } else if string_representation.starts_with(&set_string, pos) {
- pos += set_string.length();
- bits[bits_pos] = true;
- bits_pos += 1;
- } else if string_representation.starts_with(&unset_string, pos) {
- pos += unset_string.length();
- bits[bits_pos] = false;
- bits_pos += 1;
- } else {
- throw IllegalArgumentException::new(format!("illegal character encountered: {}", string_representation.substring(pos)));
- }
- }
- // no EOL at end?
- if bits_pos > row_start_pos {
- if row_length == -1 {
- row_length = bits_pos - row_start_pos;
- } else if bits_pos - row_start_pos != row_length {
- throw IllegalArgumentException::new("row lengths do not match");
- }
- n_rows += 1;
- }
- let matrix: BitMatrix = BitMatrix::new(row_length, n_rows);
- {
- let mut i: i32 = 0;
- while i < bits_pos {
- {
- if bits[i] {
- matrix.set(i % row_length, i / row_length);
- }
- }
- i += 1;
- }
- }
-
- return matrix;
- }
-
- /**
- * Gets the requested bit, where true means black.
- *
- * @param x The horizontal component (i.e. which column)
- * @param y The vertical component (i.e. which row)
- * @return value of given bit in matrix
- */
- pub fn get(&self, x: i32, y: i32) -> bool {
- let offset: i32 = y * self.row_size + (x / 32);
- return ((self.bits[offset] >> /* >>> */ (x & 0x1f)) & 1) != 0;
- }
-
- /**
- * Sets the given bit to true.
- *
- * @param x The horizontal component (i.e. which column)
- * @param y The vertical component (i.e. which row)
- */
- pub fn set(&self, x: i32, y: i32) {
- let mut offset: i32 = y * self.row_size + (x / 32);
- self.bits[offset] |= 1 << (x & 0x1f);
- }
-
- pub fn unset(&self, x: i32, y: i32) {
- let mut offset: i32 = y * self.row_size + (x / 32);
- self.bits[offset] &= ~(1 << (x & 0x1f));
- }
-
- /**
- * Flips the given bit.
- *
- * @param x The horizontal component (i.e. which column)
- * @param y The vertical component (i.e. which row)
- */
- pub fn flip(&self, x: i32, y: i32) {
- let mut offset: i32 = y * self.row_size + (x / 32);
- self.bits[offset] ^= 1 << (x & 0x1f);
- }
-
- /**
- * Flips every bit in the matrix.
- */
- pub fn flip(&self) {
- let max: i32 = self.bits.len();
- {
- let mut i: i32 = 0;
- while i < max {
- {
- self.bits[i] = ~self.bits[i];
- }
- i += 1;
- }
- }
-
- }
-
- /**
- * Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding
- * mask bit is set.
- *
- * @param mask XOR mask
- */
- pub fn xor(&self, mask: &BitMatrix) {
- if self.width != mask.width || self.height != mask.height || self.row_size != mask.rowSize {
- throw IllegalArgumentException::new("input matrix dimensions do not match");
- }
- let row_array: BitArray = BitArray::new(self.width);
- {
- let mut y: i32 = 0;
- while y < self.height {
- {
- let mut offset: i32 = y * self.row_size;
- let row: Vec = mask.get_row(y, row_array).get_bit_array();
- {
- let mut x: i32 = 0;
- while x < self.row_size {
- {
- self.bits[offset + x] ^= row[x];
- }
- x += 1;
- }
- }
-
- }
- y += 1;
- }
- }
-
- }
-
- /**
- * Clears all bits (sets to false).
- */
- pub fn clear(&self) {
- let max: i32 = self.bits.len();
- {
- let mut i: i32 = 0;
- while i < max {
- {
- self.bits[i] = 0;
- }
- i += 1;
- }
- }
-
- }
-
- /**
- * Sets a square region of the bit matrix to true.
- *
- * @param left The horizontal position to begin at (inclusive)
- * @param top The vertical position to begin at (inclusive)
- * @param width The width of the region
- * @param height The height of the region
- */
- pub fn set_region(&self, left: i32, top: i32, width: i32, height: i32) {
- if top < 0 || left < 0 {
- throw IllegalArgumentException::new("Left and top must be nonnegative");
- }
- if height < 1 || width < 1 {
- throw IllegalArgumentException::new("Height and width must be at least 1");
- }
- let right: i32 = left + width;
- let bottom: i32 = top + height;
- if bottom > self.height || right > self.width {
- throw IllegalArgumentException::new("The region must fit inside the matrix");
- }
- {
- let mut y: i32 = top;
- while y < bottom {
- {
- let mut offset: i32 = y * self.row_size;
- {
- let mut x: i32 = left;
- while x < right {
- {
- self.bits[offset + (x / 32)] |= 1 << (x & 0x1f);
- }
- x += 1;
- }
- }
-
- }
- y += 1;
- }
- }
-
- }
-
- /**
- * A fast method to retrieve one row of data from the matrix as a BitArray.
- *
- * @param y The row to retrieve
- * @param row An optional caller-allocated BitArray, will be allocated if null or too small
- * @return The resulting BitArray - this reference should always be used even when passing
- * your own row
- */
- pub fn get_row(&self, y: i32, row: &BitArray) -> BitArray {
- if row == null || row.get_size() < self.width {
- row = BitArray::new(self.width);
- } else {
- row.clear();
- }
- let offset: i32 = y * self.row_size;
- {
- let mut x: i32 = 0;
- while x < self.row_size {
- {
- row.set_bulk(x * 32, self.bits[offset + x]);
- }
- x += 1;
- }
- }
-
- return row;
- }
-
- /**
- * @param y row to set
- * @param row {@link BitArray} to copy from
- */
- pub fn set_row(&self, y: i32, row: &BitArray) {
- System::arraycopy(&row.get_bit_array(), 0, &self.bits, y * self.row_size, self.row_size);
- }
-
- /**
- * Modifies this {@code BitMatrix} to represent the same but rotated the given degrees (0, 90, 180, 270)
- *
- * @param degrees number of degrees to rotate through counter-clockwise (0, 90, 180, 270)
- */
- pub fn rotate(&self, degrees: i32) {
- match degrees % 360 {
- 0 =>
- {
- return;
- }
- 90 =>
- {
- self.rotate90();
- return;
- }
- 180 =>
- {
- self.rotate180();
- return;
- }
- 270 =>
- {
- self.rotate90();
- self.rotate180();
- return;
- }
- }
- throw IllegalArgumentException::new("degrees must be a multiple of 0, 90, 180, or 270");
- }
-
- /**
- * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees
- */
- pub fn rotate180(&self) {
- let top_row: BitArray = BitArray::new(self.width);
- let bottom_row: BitArray = BitArray::new(self.width);
- let max_height: i32 = (self.height + 1) / 2;
- {
- let mut i: i32 = 0;
- while i < max_height {
- {
- top_row = self.get_row(i, top_row);
- let bottom_row_index: i32 = self.height - 1 - i;
- bottom_row = self.get_row(bottom_row_index, bottom_row);
- top_row.reverse();
- bottom_row.reverse();
- self.set_row(i, bottom_row);
- self.set_row(bottom_row_index, top_row);
- }
- i += 1;
- }
- }
-
- }
-
- /**
- * Modifies this {@code BitMatrix} to represent the same but rotated 90 degrees counterclockwise
- */
- pub fn rotate90(&self) {
- let new_width: i32 = self.height;
- let new_height: i32 = self.width;
- let new_row_size: i32 = (new_width + 31) / 32;
- let new_bits: [i32; new_row_size * new_height] = [0; new_row_size * new_height];
- {
- let mut y: i32 = 0;
- while y < self.height {
- {
- {
- let mut x: i32 = 0;
- while x < self.width {
- {
- let offset: i32 = y * self.row_size + (x / 32);
- if ((self.bits[offset] >> /* >>> */ (x & 0x1f)) & 1) != 0 {
- let new_offset: i32 = (new_height - 1 - x) * new_row_size + (y / 32);
- new_bits[new_offset] |= 1 << (y & 0x1f);
- }
- }
- x += 1;
- }
- }
-
- }
- y += 1;
- }
- }
-
- self.width = new_width;
- self.height = new_height;
- self.row_size = new_row_size;
- self.bits = new_bits;
- }
-
- /**
- * This is useful in detecting the enclosing rectangle of a 'pure' barcode.
- *
- * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white
- */
- pub fn get_enclosing_rectangle(&self) -> Vec {
- let mut left: i32 = self.width;
- let mut top: i32 = self.height;
- let mut right: i32 = -1;
- let mut bottom: i32 = -1;
- {
- let mut y: i32 = 0;
- while y < self.height {
- {
- {
- let mut x32: i32 = 0;
- while x32 < self.row_size {
- {
- let the_bits: i32 = self.bits[y * self.row_size + x32];
- if the_bits != 0 {
- if y < top {
- top = y;
- }
- if y > bottom {
- bottom = y;
- }
- if x32 * 32 < left {
- let mut bit: i32 = 0;
- while (the_bits << (31 - bit)) == 0 {
- bit += 1;
- }
- if (x32 * 32 + bit) < left {
- left = x32 * 32 + bit;
- }
- }
- if x32 * 32 + 31 > right {
- let mut bit: i32 = 31;
- while (the_bits >> /* >>> */ bit) == 0 {
- bit -= 1;
- }
- if (x32 * 32 + bit) > right {
- right = x32 * 32 + bit;
- }
- }
- }
- }
- x32 += 1;
- }
- }
-
- }
- y += 1;
- }
- }
-
- if right < left || bottom < top {
- return null;
- }
- return : vec![i32; 4] = vec![left, top, right - left + 1, bottom - top + 1, ]
- ;
- }
-
- /**
- * This is useful in detecting a corner of a 'pure' barcode.
- *
- * @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white
- */
- pub fn get_top_left_on_bit(&self) -> Vec {
- let bits_offset: i32 = 0;
- while bits_offset < self.bits.len() && self.bits[bits_offset] == 0 {
- bits_offset += 1;
- }
- if bits_offset == self.bits.len() {
- return null;
- }
- let y: i32 = bits_offset / self.row_size;
- let mut x: i32 = (bits_offset % self.row_size) * 32;
- let the_bits: i32 = self.bits[bits_offset];
- let mut bit: i32 = 0;
- while (the_bits << (31 - bit)) == 0 {
- bit += 1;
- }
- x += bit;
- return : vec![i32; 2] = vec![x, y, ]
- ;
- }
-
- pub fn get_bottom_right_on_bit(&self) -> Vec {
- let bits_offset: i32 = self.bits.len() - 1;
- while bits_offset >= 0 && self.bits[bits_offset] == 0 {
- bits_offset -= 1;
- }
- if bits_offset < 0 {
- return null;
- }
- let y: i32 = bits_offset / self.row_size;
- let mut x: i32 = (bits_offset % self.row_size) * 32;
- let the_bits: i32 = self.bits[bits_offset];
- let mut bit: i32 = 31;
- while (the_bits >> /* >>> */ bit) == 0 {
- bit -= 1;
- }
- x += bit;
- return : vec![i32; 2] = vec![x, y, ]
- ;
- }
-
- /**
- * @return The width of the matrix
- */
- pub fn get_width(&self) -> i32 {
- return self.width;
- }
-
- /**
- * @return The height of the matrix
- */
- pub fn get_height(&self) -> i32 {
- return self.height;
- }
-
- /**
- * @return The row size of the matrix
- */
- pub fn get_row_size(&self) -> i32 {
- return self.row_size;
- }
-
- pub fn equals(&self, o: &Object) -> bool {
- if !(o instanceof BitMatrix) {
- return false;
- }
- let other: BitMatrix = o as BitMatrix;
- return self.width == other.width && self.height == other.height && self.row_size == other.rowSize && Arrays::equals(&self.bits, other.bits);
- }
-
- pub fn hash_code(&self) -> i32 {
- let mut hash: i32 = self.width;
- hash = 31 * hash + self.width;
- hash = 31 * hash + self.height;
- hash = 31 * hash + self.row_size;
- hash = 31 * hash + Arrays::hash_code(&self.bits);
- return hash;
- }
-
- /**
- * @return string representation using "X" for set and " " for unset bits
- */
- pub fn to_string(&self) -> String {
- return self.to_string("X ", " ");
- }
-
- /**
- * @param setString representation of a set bit
- * @param unsetString representation of an unset bit
- * @return string representation of entire matrix utilizing given strings
- */
- pub fn to_string(&self, set_string: &String, unset_string: &String) -> String {
- return self.build_to_string(&set_string, &unset_string, "\n");
- }
-
- /**
- * @param setString representation of a set bit
- * @param unsetString representation of an unset bit
- * @param lineSeparator newline character in string representation
- * @return string representation of entire matrix utilizing given strings and line separator
- * @deprecated call {@link #toString(String,String)} only, which uses \n line separator always
- */
- pub fn to_string(&self, set_string: &String, unset_string: &String, line_separator: &String) -> String {
- return self.build_to_string(&set_string, &unset_string, &line_separator);
- }
-
- fn build_to_string(&self, set_string: &String, unset_string: &String, line_separator: &String) -> String {
- let result: StringBuilder = StringBuilder::new(self.height * (self.width + 1));
- {
- let mut y: i32 = 0;
- while y < self.height {
- {
- {
- let mut x: i32 = 0;
- while x < self.width {
- {
- result.append( if self.get(x, y) { set_string } else { unset_string });
- }
- x += 1;
- }
- }
-
- result.append(&line_separator);
- }
- y += 1;
- }
- }
-
- return result.to_string();
- }
-
- pub fn clone(&self) -> BitMatrix {
- return BitMatrix::new(self.width, self.height, self.row_size, &self.bits.clone());
- }
-}
-
diff --git a/port_src/output/zxing/common/bit_source.rs b/port_src/output/zxing/common/bit_source.rs
deleted file mode 100644
index a5b50f5..0000000
--- a/port_src/output/zxing/common/bit_source.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * This provides an easy abstraction to read bits at a time from a sequence of bytes, where the
- * number of bits read is not often a multiple of 8.
- *
- * This class is thread-safe but not reentrant -- unless the caller modifies the bytes array
- * it passed in, in which case all bets are off.
- *
- * @author Sean Owen
- */
-pub struct BitSource {
-
- let bytes: Vec;
-
- let byte_offset: i32;
-
- let bit_offset: i32;
-}
-
-impl BitSource {
-
- /**
- * @param bytes bytes from which this will read bits. Bits will be read from the first byte first.
- * Bits are read within a byte from most-significant to least-significant bit.
- */
- pub fn new( bytes: &Vec) -> BitSource {
- let .bytes = bytes;
- }
-
- /**
- * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}.
- */
- pub fn get_bit_offset(&self) -> i32 {
- return self.bit_offset;
- }
-
- /**
- * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}.
- */
- pub fn get_byte_offset(&self) -> i32 {
- return self.byte_offset;
- }
-
- /**
- * @param numBits number of bits to read
- * @return int representing the bits read. The bits will appear as the least-significant
- * bits of the int
- * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available
- */
- pub fn read_bits(&self, num_bits: i32) -> i32 {
- if num_bits < 1 || num_bits > 32 || num_bits > self.available() {
- throw IllegalArgumentException::new(&String::value_of(num_bits));
- }
- let mut result: i32 = 0;
- // First, read remainder from current byte
- if self.bit_offset > 0 {
- let bits_left: i32 = 8 - self.bit_offset;
- let to_read: i32 = Math::min(num_bits, bits_left);
- let bits_to_not_read: i32 = bits_left - to_read;
- let mask: i32 = (0xFF >> (8 - to_read)) << bits_to_not_read;
- result = (self.bytes[self.byte_offset] & mask) >> bits_to_not_read;
- num_bits -= to_read;
- self.bit_offset += to_read;
- if self.bit_offset == 8 {
- self.bit_offset = 0;
- self.byte_offset += 1;
- }
- }
- // Next read whole bytes
- if num_bits > 0 {
- while num_bits >= 8 {
- result = (result << 8) | (self.bytes[self.byte_offset] & 0xFF);
- self.byte_offset += 1;
- num_bits -= 8;
- }
- // Finally read a partial byte
- if num_bits > 0 {
- let bits_to_not_read: i32 = 8 - num_bits;
- let mask: i32 = (0xFF >> bits_to_not_read) << bits_to_not_read;
- result = (result << num_bits) | ((self.bytes[self.byte_offset] & mask) >> bits_to_not_read);
- self.bit_offset += num_bits;
- }
- }
- return result;
- }
-
- /**
- * @return number of bits that can be read successfully
- */
- pub fn available(&self) -> i32 {
- return 8 * (self.bytes.len() - self.byte_offset) - self.bit_offset;
- }
-}
-
diff --git a/port_src/output/zxing/common/character_set_e_c_i.rs b/port_src/output/zxing/common/character_set_e_c_i.rs
deleted file mode 100644
index 41ad1f7..0000000
--- a/port_src/output/zxing/common/character_set_e_c_i.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * Encapsulates a Character Set ECI, according to "Extended Channel Interpretations" 5.3.1.1
- * of ISO 18004.
- *
- * @author Sean Owen
- */
-pub enum CharacterSetECI {
-
- // Enum name is a Java encoding valid for java.lang and java.io
- Cp437( : vec![i32; 2] = vec![0, 2, ]
- ), ISO8859_1( : vec![i32; 2] = vec![1, 3, ]
- , "ISO-8859-1"), ISO8859_2(4, "ISO-8859-2"), ISO8859_3(5, "ISO-8859-3"), ISO8859_4(6, "ISO-8859-4"), ISO8859_5(7, "ISO-8859-5"), // ISO8859_6(8, "ISO-8859-6"),
- ISO8859_7(9, "ISO-8859-7"), // ISO8859_8(10, "ISO-8859-8"),
- ISO8859_9(11, "ISO-8859-9"), // ISO8859_11(13, "ISO-8859-11"),
- ISO8859_13(15, "ISO-8859-13"), // ISO8859_14(16, "ISO-8859-14"),
- ISO8859_15(17, "ISO-8859-15"), ISO8859_16(18, "ISO-8859-16"), SJIS(20, "Shift_JIS"), Cp1250(21, "windows-1250"), Cp1251(22, "windows-1251"), Cp1252(23, "windows-1252"), Cp1256(24, "windows-1256"), UnicodeBigUnmarked(25, "UTF-16BE", "UnicodeBig"), UTF8(26, "UTF-8"), ASCII( : vec![i32; 2] = vec![27, 170, ]
- , "US-ASCII"), Big5(28), GB18030(29, "GB2312", "EUC_CN", "GBK"), EUC_KR(30, "EUC-KR");
-
- const VALUE_TO_ECI: Map = HashMap<>::new();
-
- const NAME_TO_ECI: Map = HashMap<>::new();
-
- static {
- for let eci: CharacterSetECI in self.values() {
- for let value: i32 in eci.values {
- VALUE_TO_ECI::put(value, eci);
- }
- NAME_TO_ECI::put(&eci.name(), eci);
- for let name: String in eci.otherEncodingNames {
- NAME_TO_ECI::put(&name, eci);
- }
- }
- }
-
- let mut values: Vec;
-
- let other_encoding_names: Vec;
-
- fn new( value: i32) -> CharacterSetECI {
- this( : vec![i32; 1] = vec![value, ]
- );
- }
-
- fn new( value: i32, other_encoding_names: &String) -> CharacterSetECI {
- let .values = : vec![i32; 1] = vec![value, ]
- ;
- let .otherEncodingNames = other_encoding_names;
- }
-
- fn new( values: &Vec, other_encoding_names: &String) -> CharacterSetECI {
- let .values = values;
- let .otherEncodingNames = other_encoding_names;
- }
-
- pub fn get_value(&self) -> i32 {
- return self.values[0];
- }
-
- pub fn get_charset(&self) -> Charset {
- return Charset::for_name(&name());
- }
-
- /**
- * @param charset Java character set object
- * @return CharacterSetECI representing ECI for character encoding, or null if it is legal
- * but unsupported
- */
- pub fn get_character_set_e_c_i( charset: &Charset) -> CharacterSetECI {
- return NAME_TO_ECI::get(&charset.name());
- }
-
- /**
- * @param value character set ECI value
- * @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but
- * unsupported
- * @throws FormatException if ECI value is invalid
- */
- pub fn get_character_set_e_c_i_by_value( value: i32) -> /* throws FormatException */Result> {
- if value < 0 || value >= 900 {
- throw FormatException::get_format_instance();
- }
- return Ok(VALUE_TO_ECI::get(value));
- }
-
- /**
- * @param name character set ECI encoding name
- * @return CharacterSetECI representing ECI for character encoding, or null if it is legal
- * but unsupported
- */
- pub fn get_character_set_e_c_i_by_name( name: &String) -> CharacterSetECI {
- return NAME_TO_ECI::get(&name);
- }
-}
diff --git a/port_src/output/zxing/common/decoder_result.rs b/port_src/output/zxing/common/decoder_result.rs
deleted file mode 100644
index 466f09e..0000000
--- a/port_src/output/zxing/common/decoder_result.rs
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * Encapsulates the result of decoding a matrix of bits. This typically
- * applies to 2D barcode formats. For now it contains the raw bytes obtained,
- * as well as a String interpretation of those bytes, if applicable.
- *
- * @author Sean Owen
- */
-pub struct DecoderResult {
-
- let raw_bytes: Vec;
-
- let num_bits: i32;
-
- let text: String;
-
- let byte_segments: List>;
-
- let ec_level: String;
-
- let errors_corrected: Integer;
-
- let erasures: Integer;
-
- let other: Object;
-
- let structured_append_parity: i32;
-
- let structured_append_sequence_number: i32;
-
- let symbology_modifier: i32;
-}
-
-impl DecoderResult {
-
- pub fn new( raw_bytes: &Vec, text: &String, byte_segments: &List>, ec_level: &String) -> DecoderResult {
- this(&raw_bytes, &text, &byte_segments, &ec_level, -1, -1, 0);
- }
-
- pub fn new( raw_bytes: &Vec, text: &String, byte_segments: &List>, ec_level: &String, symbology_modifier: i32) -> DecoderResult {
- this(&raw_bytes, &text, &byte_segments, &ec_level, -1, -1, symbology_modifier);
- }
-
- pub fn new( raw_bytes: &Vec, text: &String, byte_segments: &List>, ec_level: &String, sa_sequence: i32, sa_parity: i32) -> DecoderResult {
- this(&raw_bytes, &text, &byte_segments, &ec_level, sa_sequence, sa_parity, 0);
- }
-
- pub fn new( raw_bytes: &Vec, text: &String, byte_segments: &List>, ec_level: &String, sa_sequence: i32, sa_parity: i32, symbology_modifier: i32) -> DecoderResult {
- let .rawBytes = raw_bytes;
- let .numBits = if raw_bytes == null { 0 } else { 8 * raw_bytes.len() };
- let .text = text;
- let .byteSegments = byte_segments;
- let .ecLevel = ec_level;
- let .structuredAppendParity = sa_parity;
- let .structuredAppendSequenceNumber = sa_sequence;
- let .symbologyModifier = symbology_modifier;
- }
-
- /**
- * @return raw bytes representing the result, or {@code null} if not applicable
- */
- pub fn get_raw_bytes(&self) -> Vec {
- return self.raw_bytes;
- }
-
- /**
- * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length
- * @since 3.3.0
- */
- pub fn get_num_bits(&self) -> i32 {
- return self.num_bits;
- }
-
- /**
- * @param numBits overrides the number of bits that are valid in {@link #getRawBytes()}
- * @since 3.3.0
- */
- pub fn set_num_bits(&self, num_bits: i32) {
- self.numBits = num_bits;
- }
-
- /**
- * @return text representation of the result
- */
- pub fn get_text(&self) -> String {
- return self.text;
- }
-
- /**
- * @return list of byte segments in the result, or {@code null} if not applicable
- */
- pub fn get_byte_segments(&self) -> List> {
- return self.byte_segments;
- }
-
- /**
- * @return name of error correction level used, or {@code null} if not applicable
- */
- pub fn get_e_c_level(&self) -> String {
- return self.ec_level;
- }
-
- /**
- * @return number of errors corrected, or {@code null} if not applicable
- */
- pub fn get_errors_corrected(&self) -> Integer {
- return self.errors_corrected;
- }
-
- pub fn set_errors_corrected(&self, errors_corrected: &Integer) {
- self.errorsCorrected = errors_corrected;
- }
-
- /**
- * @return number of erasures corrected, or {@code null} if not applicable
- */
- pub fn get_erasures(&self) -> Integer {
- return self.erasures;
- }
-
- pub fn set_erasures(&self, erasures: &Integer) {
- self.erasures = erasures;
- }
-
- /**
- * @return arbitrary additional metadata
- */
- pub fn get_other(&self) -> Object {
- return self.other;
- }
-
- pub fn set_other(&self, other: &Object) {
- self.other = other;
- }
-
- pub fn has_structured_append(&self) -> bool {
- return self.structured_append_parity >= 0 && self.structured_append_sequence_number >= 0;
- }
-
- pub fn get_structured_append_parity(&self) -> i32 {
- return self.structured_append_parity;
- }
-
- pub fn get_structured_append_sequence_number(&self) -> i32 {
- return self.structured_append_sequence_number;
- }
-
- pub fn get_symbology_modifier(&self) -> i32 {
- return self.symbology_modifier;
- }
-}
-
diff --git a/port_src/output/zxing/common/default_grid_sampler.rs b/port_src/output/zxing/common/default_grid_sampler.rs
deleted file mode 100644
index a4096e4..0000000
--- a/port_src/output/zxing/common/default_grid_sampler.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * @author Sean Owen
- */
-pub struct DefaultGridSampler {
- super: GridSampler;
-}
-
-impl DefaultGridSampler {
-
- pub fn sample_grid(&self, image: &BitMatrix, dimension_x: i32, dimension_y: i32, p1_to_x: f32, p1_to_y: f32, p2_to_x: f32, p2_to_y: f32, p3_to_x: f32, p3_to_y: f32, p4_to_x: f32, p4_to_y: f32, p1_from_x: f32, p1_from_y: f32, p2_from_x: f32, p2_from_y: f32, p3_from_x: f32, p3_from_y: f32, p4_from_x: f32, p4_from_y: f32) -> /* throws NotFoundException */Result> {
- let transform: PerspectiveTransform = PerspectiveTransform::quadrilateral_to_quadrilateral(p1_to_x, p1_to_y, p2_to_x, p2_to_y, p3_to_x, p3_to_y, p4_to_x, p4_to_y, p1_from_x, p1_from_y, p2_from_x, p2_from_y, p3_from_x, p3_from_y, p4_from_x, p4_from_y);
- return Ok(self.sample_grid(image, dimension_x, dimension_y, transform));
- }
-
- pub fn sample_grid(&self, image: &BitMatrix, dimension_x: i32, dimension_y: i32, transform: &PerspectiveTransform) -> /* throws NotFoundException */Result> {
- if dimension_x <= 0 || dimension_y <= 0 {
- throw NotFoundException::get_not_found_instance();
- }
- let bits: BitMatrix = BitMatrix::new(dimension_x, dimension_y);
- let mut points: [f32; 2.0 * dimension_x] = [0.0; 2.0 * dimension_x];
- {
- let mut y: i32 = 0;
- while y < dimension_y {
- {
- let max: i32 = points.len();
- let i_value: f32 = y + 0.5f;
- {
- let mut x: i32 = 0;
- while x < max {
- {
- points[x] = (x / 2.0) as f32 + 0.5f;
- points[x + 1] = i_value;
- }
- x += 2;
- }
- }
-
- transform.transform_points(&points);
- // Quick check to see if points transformed to something inside the image;
- // sufficient to check the endpoints
- check_and_nudge_points(image, &points);
- let tryResult1 = 0;
- 'try1: loop {
- {
- {
- let mut x: i32 = 0;
- while x < max {
- {
- if image.get(points[x] as i32, points[x + 1] as i32) {
- // Black(-ish) pixel
- bits.set(x / 2, y);
- }
- }
- x += 2;
- }
- }
-
- }
- break 'try1
- }
- match tryResult1 {
- catch ( aioobe: &ArrayIndexOutOfBoundsException) {
- throw NotFoundException::get_not_found_instance();
- } 0 => break
- }
-
- }
- y += 1;
- }
- }
-
- return Ok(bits);
- }
-}
-
diff --git a/port_src/output/zxing/common/detector/math_utils.rs b/port_src/output/zxing/common/detector/math_utils.rs
deleted file mode 100644
index 60c849e..0000000
--- a/port_src/output/zxing/common/detector/math_utils.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2012 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common::detector;
-
-/**
- * General math-related and numeric utility functions.
- */
-pub struct MathUtils {
-}
-
-impl MathUtils {
-
- fn new() -> MathUtils {
- }
-
- /**
- * Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its
- * argument to the nearest int, where x.5 rounds up to x+1. Semantics of this shortcut
- * differ slightly from {@link Math#round(float)} in that half rounds down for negative
- * values. -2.5 rounds to -3, not -2. For purposes here it makes no difference.
- *
- * @param d real value to round
- * @return nearest {@code int}
- */
- pub fn round( d: f32) -> i32 {
- return (d + ( if d < 0.0f { -0.5f } else { 0.5f })) as i32;
- }
-
- /**
- * @param aX point A x coordinate
- * @param aY point A y coordinate
- * @param bX point B x coordinate
- * @param bY point B y coordinate
- * @return Euclidean distance between points A and B
- */
- pub fn distance( a_x: f32, a_y: f32, b_x: f32, b_y: f32) -> f32 {
- let x_diff: f64 = a_x - b_x;
- let y_diff: f64 = a_y - b_y;
- return Math::sqrt(x_diff * x_diff + y_diff * y_diff) as f32;
- }
-
- /**
- * @param aX point A x coordinate
- * @param aY point A y coordinate
- * @param bX point B x coordinate
- * @param bY point B y coordinate
- * @return Euclidean distance between points A and B
- */
- pub fn distance( a_x: i32, a_y: i32, b_x: i32, b_y: i32) -> f32 {
- let x_diff: f64 = a_x - b_x;
- let y_diff: f64 = a_y - b_y;
- return Math::sqrt(x_diff * x_diff + y_diff * y_diff) as f32;
- }
-
- /**
- * @param array values to sum
- * @return sum of values in array
- */
- pub fn sum( array: &Vec) -> i32 {
- let mut count: i32 = 0;
- for let a: i32 in array {
- count += a;
- }
- return count;
- }
-}
-
diff --git a/port_src/output/zxing/common/detector/monochrome_rectangle_detector.rs b/port_src/output/zxing/common/detector/monochrome_rectangle_detector.rs
deleted file mode 100644
index d7d649f..0000000
--- a/port_src/output/zxing/common/detector/monochrome_rectangle_detector.rs
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common::detector;
-
-/**
- * A somewhat generic detector that looks for a barcode-like rectangular region within an image.
- * It looks within a mostly white region of an image for a region of black and white, but mostly
- * black. It returns the four corners of the region, as best it can determine.
- *
- * @author Sean Owen
- * @deprecated without replacement since 3.3.0
- */
-
- const MAX_MODULES: i32 = 32;
-pub struct MonochromeRectangleDetector {
-
- let image: BitMatrix;
-}
-
-impl MonochromeRectangleDetector {
-
- pub fn new( image: &BitMatrix) -> MonochromeRectangleDetector {
- let .image = image;
- }
-
- /**
- * Detects a rectangular region of black and white -- mostly black -- with a region of mostly
- * white, in an image.
- *
- * @return {@link ResultPoint}[] describing the corners of the rectangular region. The first and
- * last points are opposed on the diagonal, as are the second and third. The first point will be
- * the topmost point and the last, the bottommost. The second point will be leftmost and the
- * third, the rightmost
- * @throws NotFoundException if no Data Matrix Code can be found
- */
- pub fn detect(&self) -> /* throws NotFoundException */Result, Rc> {
- let height: i32 = self.image.get_height();
- let width: i32 = self.image.get_width();
- let half_height: i32 = height / 2;
- let half_width: i32 = width / 2;
- let delta_y: i32 = Math::max(1, height / (MAX_MODULES * 8));
- let delta_x: i32 = Math::max(1, width / (MAX_MODULES * 8));
- let mut top: i32 = 0;
- let mut bottom: i32 = height;
- let mut left: i32 = 0;
- let mut right: i32 = width;
- let point_a: ResultPoint = self.find_corner_from_center(half_width, 0, left, right, half_height, -delta_y, top, bottom, half_width / 2);
- top = point_a.get_y() as i32 - 1;
- let point_b: ResultPoint = self.find_corner_from_center(half_width, -delta_x, left, right, half_height, 0, top, bottom, half_height / 2);
- left = point_b.get_x() as i32 - 1;
- let point_c: ResultPoint = self.find_corner_from_center(half_width, delta_x, left, right, half_height, 0, top, bottom, half_height / 2);
- right = point_c.get_x() as i32 + 1;
- let point_d: ResultPoint = self.find_corner_from_center(half_width, 0, left, right, half_height, delta_y, top, bottom, half_width / 2);
- bottom = point_d.get_y() as i32 + 1;
- // Go try to find point A again with better information -- might have been off at first.
- point_a = self.find_corner_from_center(half_width, 0, left, right, half_height, -delta_y, top, bottom, half_width / 4);
- return Ok( : vec![ResultPoint; 4] = vec![point_a, point_b, point_c, point_d, ]
- );
- }
-
- /**
- * Attempts to locate a corner of the barcode by scanning up, down, left or right from a center
- * point which should be within the barcode.
- *
- * @param centerX center's x component (horizontal)
- * @param deltaX same as deltaY but change in x per step instead
- * @param left minimum value of x
- * @param right maximum value of x
- * @param centerY center's y component (vertical)
- * @param deltaY change in y per step. If scanning up this is negative; down, positive;
- * left or right, 0
- * @param top minimum value of y to search through (meaningless when di == 0)
- * @param bottom maximum value of y
- * @param maxWhiteRun maximum run of white pixels that can still be considered to be within
- * the barcode
- * @return a {@link ResultPoint} encapsulating the corner that was found
- * @throws NotFoundException if such a point cannot be found
- */
- fn find_corner_from_center(&self, center_x: i32, delta_x: i32, left: i32, right: i32, center_y: i32, delta_y: i32, top: i32, bottom: i32, max_white_run: i32) -> /* throws NotFoundException */Result> {
- let last_range: Vec = null;
- {
- let mut y: i32 = center_y, let mut x: i32 = center_x;
- while y < bottom && y >= top && x < right && x >= left {
- {
- let mut range: Vec;
- if delta_x == 0 {
- // horizontal slices, up and down
- range = self.black_white_range(y, max_white_run, left, right, true);
- } else {
- // vertical slices, left and right
- range = self.black_white_range(x, max_white_run, top, bottom, false);
- }
- if range == null {
- if last_range == null {
- throw NotFoundException::get_not_found_instance();
- }
- // lastRange was found
- if delta_x == 0 {
- let last_y: i32 = y - delta_y;
- if last_range[0] < center_x {
- if last_range[1] > center_x {
- // straddle, choose one or the other based on direction
- return Ok(ResultPoint::new(last_range[ if delta_y > 0 { 0 } else { 1 }], last_y));
- }
- return Ok(ResultPoint::new(last_range[0], last_y));
- } else {
- return Ok(ResultPoint::new(last_range[1], last_y));
- }
- } else {
- let last_x: i32 = x - delta_x;
- if last_range[0] < center_y {
- if last_range[1] > center_y {
- return Ok(ResultPoint::new(last_x, last_range[ if delta_x < 0 { 0 } else { 1 }]));
- }
- return Ok(ResultPoint::new(last_x, last_range[0]));
- } else {
- return Ok(ResultPoint::new(last_x, last_range[1]));
- }
- }
- }
- last_range = range;
- }
- y += delta_y;
- x += delta_x;
- }
- }
-
- throw NotFoundException::get_not_found_instance();
- }
-
- /**
- * Computes the start and end of a region of pixels, either horizontally or vertically, that could
- * be part of a Data Matrix barcode.
- *
- * @param fixedDimension if scanning horizontally, this is the row (the fixed vertical location)
- * where we are scanning. If scanning vertically it's the column, the fixed horizontal location
- * @param maxWhiteRun largest run of white pixels that can still be considered part of the
- * barcode region
- * @param minDim minimum pixel location, horizontally or vertically, to consider
- * @param maxDim maximum pixel location, horizontally or vertically, to consider
- * @param horizontal if true, we're scanning left-right, instead of up-down
- * @return int[] with start and end of found range, or null if no such range is found
- * (e.g. only white was found)
- */
- fn black_white_range(&self, fixed_dimension: i32, max_white_run: i32, min_dim: i32, max_dim: i32, horizontal: bool) -> Vec {
- let center: i32 = (min_dim + max_dim) / 2;
- // Scan left/up first
- let mut start: i32 = center;
- while start >= min_dim {
- if if horizontal { self.image.get(start, fixed_dimension) } else { self.image.get(fixed_dimension, start) } {
- start -= 1;
- } else {
- let white_run_start: i32 = start;
- loop { {
- start -= 1;
- }if !(start >= min_dim && !( if horizontal { self.image.get(start, fixed_dimension) } else { self.image.get(fixed_dimension, start) })) break;}
- let white_run_size: i32 = white_run_start - start;
- if start < min_dim || white_run_size > max_white_run {
- start = white_run_start;
- break;
- }
- }
- }
- start += 1;
- // Then try right/down
- let mut end: i32 = center;
- while end < max_dim {
- if if horizontal { self.image.get(end, fixed_dimension) } else { self.image.get(fixed_dimension, end) } {
- end += 1;
- } else {
- let white_run_start: i32 = end;
- loop { {
- end += 1;
- }if !(end < max_dim && !( if horizontal { self.image.get(end, fixed_dimension) } else { self.image.get(fixed_dimension, end) })) break;}
- let white_run_size: i32 = end - white_run_start;
- if end >= max_dim || white_run_size > max_white_run {
- end = white_run_start;
- break;
- }
- }
- }
- end -= 1;
- return if end > start { : vec![i32; 2] = vec![start, end, ]
- } else { null };
- }
-}
-
diff --git a/port_src/output/zxing/common/detector/white_rectangle_detector.rs b/port_src/output/zxing/common/detector/white_rectangle_detector.rs
deleted file mode 100644
index d3d6d27..0000000
--- a/port_src/output/zxing/common/detector/white_rectangle_detector.rs
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright 2010 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common::detector;
-
-/**
- *
- * Detects a candidate barcode-like rectangular region within an image. It
- * starts around the center of the image, increases the size of the candidate
- * region until it finds a white rectangular region. By keeping track of the
- * last black points it encountered, it determines the corners of the barcode.
- *
- *
- * @author David Olivier
- */
-
- const INIT_SIZE: i32 = 10;
-
- const CORR: i32 = 1;
-pub struct WhiteRectangleDetector {
-
- let image: BitMatrix;
-
- let mut height: i32;
-
- let mut width: i32;
-
- let left_init: i32;
-
- let right_init: i32;
-
- let down_init: i32;
-
- let up_init: i32;
-}
-
-impl WhiteRectangleDetector {
-
- pub fn new( image: &BitMatrix) -> WhiteRectangleDetector throws NotFoundException {
- this(image, INIT_SIZE, image.get_width() / 2, image.get_height() / 2);
- }
-
- /**
- * @param image barcode image to find a rectangle in
- * @param initSize initial size of search area around center
- * @param x x position of search center
- * @param y y position of search center
- * @throws NotFoundException if image is too small to accommodate {@code initSize}
- */
- pub fn new( image: &BitMatrix, init_size: i32, x: i32, y: i32) -> WhiteRectangleDetector throws NotFoundException {
- let .image = image;
- height = image.get_height();
- width = image.get_width();
- let halfsize: i32 = init_size / 2;
- left_init = x - halfsize;
- right_init = x + halfsize;
- up_init = y - halfsize;
- down_init = y + halfsize;
- if up_init < 0 || left_init < 0 || down_init >= height || right_init >= width {
- throw NotFoundException::get_not_found_instance();
- }
- }
-
- /**
- *
- * Detects a candidate barcode-like rectangular region within an image. It
- * starts around the center of the image, increases the size of the candidate
- * region until it finds a white rectangular region.
- *
- *
- * @return {@link ResultPoint}[] describing the corners of the rectangular
- * region. The first and last points are opposed on the diagonal, as
- * are the second and third. The first point will be the topmost
- * point and the last, the bottommost. The second point will be
- * leftmost and the third, the rightmost
- * @throws NotFoundException if no Data Matrix Code can be found
- */
- pub fn detect(&self) -> /* throws NotFoundException */Result, Rc> {
- let mut left: i32 = self.left_init;
- let mut right: i32 = self.right_init;
- let mut up: i32 = self.up_init;
- let mut down: i32 = self.down_init;
- let size_exceeded: bool = false;
- let a_black_point_found_on_border: bool = true;
- let at_least_one_black_point_found_on_right: bool = false;
- let at_least_one_black_point_found_on_bottom: bool = false;
- let at_least_one_black_point_found_on_left: bool = false;
- let at_least_one_black_point_found_on_top: bool = false;
- while a_black_point_found_on_border {
- a_black_point_found_on_border = false;
- // .....
- // . |
- // .....
- let right_border_not_white: bool = true;
- while (right_border_not_white || !at_least_one_black_point_found_on_right) && right < self.width {
- right_border_not_white = self.contains_black_point(up, down, right, false);
- if right_border_not_white {
- right += 1;
- a_black_point_found_on_border = true;
- at_least_one_black_point_found_on_right = true;
- } else if !at_least_one_black_point_found_on_right {
- right += 1;
- }
- }
- if right >= self.width {
- size_exceeded = true;
- break;
- }
- // .....
- // . .
- // .___.
- let bottom_border_not_white: bool = true;
- while (bottom_border_not_white || !at_least_one_black_point_found_on_bottom) && down < self.height {
- bottom_border_not_white = self.contains_black_point(left, right, down, true);
- if bottom_border_not_white {
- down += 1;
- a_black_point_found_on_border = true;
- at_least_one_black_point_found_on_bottom = true;
- } else if !at_least_one_black_point_found_on_bottom {
- down += 1;
- }
- }
- if down >= self.height {
- size_exceeded = true;
- break;
- }
- // .....
- // | .
- // .....
- let left_border_not_white: bool = true;
- while (left_border_not_white || !at_least_one_black_point_found_on_left) && left >= 0 {
- left_border_not_white = self.contains_black_point(up, down, left, false);
- if left_border_not_white {
- left -= 1;
- a_black_point_found_on_border = true;
- at_least_one_black_point_found_on_left = true;
- } else if !at_least_one_black_point_found_on_left {
- left -= 1;
- }
- }
- if left < 0 {
- size_exceeded = true;
- break;
- }
- // .___.
- // . .
- // .....
- let top_border_not_white: bool = true;
- while (top_border_not_white || !at_least_one_black_point_found_on_top) && up >= 0 {
- top_border_not_white = self.contains_black_point(left, right, up, true);
- if top_border_not_white {
- up -= 1;
- a_black_point_found_on_border = true;
- at_least_one_black_point_found_on_top = true;
- } else if !at_least_one_black_point_found_on_top {
- up -= 1;
- }
- }
- if up < 0 {
- size_exceeded = true;
- break;
- }
- }
- if !size_exceeded {
- let max_size: i32 = right - left;
- let mut z: ResultPoint = null;
- {
- let mut i: i32 = 1;
- while z == null && i < max_size {
- {
- z = self.get_black_point_on_segment(left, down - i, left + i, down);
- }
- i += 1;
- }
- }
-
- if z == null {
- throw NotFoundException::get_not_found_instance();
- }
- let mut t: ResultPoint = null;
- //go down right
- {
- let mut i: i32 = 1;
- while t == null && i < max_size {
- {
- t = self.get_black_point_on_segment(left, up + i, left + i, up);
- }
- i += 1;
- }
- }
-
- if t == null {
- throw NotFoundException::get_not_found_instance();
- }
- let mut x: ResultPoint = null;
- //go down left
- {
- let mut i: i32 = 1;
- while x == null && i < max_size {
- {
- x = self.get_black_point_on_segment(right, up + i, right - i, up);
- }
- i += 1;
- }
- }
-
- if x == null {
- throw NotFoundException::get_not_found_instance();
- }
- let mut y: ResultPoint = null;
- //go up left
- {
- let mut i: i32 = 1;
- while y == null && i < max_size {
- {
- y = self.get_black_point_on_segment(right, down - i, right - i, down);
- }
- i += 1;
- }
- }
-
- if y == null {
- throw NotFoundException::get_not_found_instance();
- }
- return Ok(self.center_edges(y, z, x, t));
- } else {
- throw NotFoundException::get_not_found_instance();
- }
- }
-
- fn get_black_point_on_segment(&self, a_x: f32, a_y: f32, b_x: f32, b_y: f32) -> ResultPoint {
- let dist: i32 = MathUtils::round(&MathUtils::distance(a_x, a_y, b_x, b_y));
- let x_step: f32 = (b_x - a_x) / dist;
- let y_step: f32 = (b_y - a_y) / dist;
- {
- let mut i: i32 = 0;
- while i < dist {
- {
- let x: i32 = MathUtils::round(a_x + i * x_step);
- let y: i32 = MathUtils::round(a_y + i * y_step);
- if self.image.get(x, y) {
- return ResultPoint::new(x, y);
- }
- }
- i += 1;
- }
- }
-
- return null;
- }
-
- /**
- * recenters the points of a constant distance towards the center
- *
- * @param y bottom most point
- * @param z left most point
- * @param x right most point
- * @param t top most point
- * @return {@link ResultPoint}[] describing the corners of the rectangular
- * region. The first and last points are opposed on the diagonal, as
- * are the second and third. The first point will be the topmost
- * point and the last, the bottommost. The second point will be
- * leftmost and the third, the rightmost
- */
- fn center_edges(&self, y: &ResultPoint, z: &ResultPoint, x: &ResultPoint, t: &ResultPoint) -> Vec {
- //
- // t t
- // z x
- // x OR z
- // y y
- //
- let yi: f32 = y.get_x();
- let yj: f32 = y.get_y();
- let zi: f32 = z.get_x();
- let zj: f32 = z.get_y();
- let xi: f32 = x.get_x();
- let xj: f32 = x.get_y();
- let ti: f32 = t.get_x();
- let tj: f32 = t.get_y();
- if yi < self.width / 2.0f {
- return : vec![ResultPoint; 4] = vec![ResultPoint::new(ti - CORR, tj + CORR), ResultPoint::new(zi + CORR, zj + CORR), ResultPoint::new(xi - CORR, xj - CORR), ResultPoint::new(yi + CORR, yj - CORR), ]
- ;
- } else {
- return : vec![ResultPoint; 4] = vec![ResultPoint::new(ti + CORR, tj + CORR), ResultPoint::new(zi + CORR, zj - CORR), ResultPoint::new(xi - CORR, xj + CORR), ResultPoint::new(yi - CORR, yj - CORR), ]
- ;
- }
- }
-
- /**
- * Determines whether a segment contains a black point
- *
- * @param a min value of the scanned coordinate
- * @param b max value of the scanned coordinate
- * @param fixed value of fixed coordinate
- * @param horizontal set to true if scan must be horizontal, false if vertical
- * @return true if a black point has been found, else false.
- */
- fn contains_black_point(&self, a: i32, b: i32, fixed: i32, horizontal: bool) -> bool {
- if horizontal {
- {
- let mut x: i32 = a;
- while x <= b {
- {
- if self.image.get(x, fixed) {
- return true;
- }
- }
- x += 1;
- }
- }
-
- } else {
- {
- let mut y: i32 = a;
- while y <= b {
- {
- if self.image.get(fixed, y) {
- return true;
- }
- }
- y += 1;
- }
- }
-
- }
- return false;
- }
-}
-
diff --git a/port_src/output/zxing/common/detector_result.rs b/port_src/output/zxing/common/detector_result.rs
deleted file mode 100644
index 47713b1..0000000
--- a/port_src/output/zxing/common/detector_result.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * Encapsulates the result of detecting a barcode in an image. This includes the raw
- * matrix of black/white pixels corresponding to the barcode, and possibly points of interest
- * in the image, like the location of finder patterns or corners of the barcode in the image.
- *
- * @author Sean Owen
- */
-pub struct DetectorResult {
-
- let bits: BitMatrix;
-
- let points: Vec;
-}
-
-impl DetectorResult {
-
- pub fn new( bits: &BitMatrix, points: &Vec) -> DetectorResult {
- let .bits = bits;
- let .points = points;
- }
-
- pub fn get_bits(&self) -> BitMatrix {
- return self.bits;
- }
-
- pub fn get_points(&self) -> Vec {
- return self.points;
- }
-}
-
diff --git a/port_src/output/zxing/common/e_c_i_encoder_set.rs b/port_src/output/zxing/common/e_c_i_encoder_set.rs
deleted file mode 100644
index 1001df4..0000000
--- a/port_src/output/zxing/common/e_c_i_encoder_set.rs
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright 2021 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * Set of CharsetEncoders for a given input string
- *
- * Invariants:
- * - The list contains only encoders from CharacterSetECI (list is shorter then the list of encoders available on
- * the platform for which ECI values are defined).
- * - The list contains encoders at least one encoder for every character in the input.
- * - The first encoder in the list is always the ISO-8859-1 encoder even of no character in the input can be encoded
- * by it.
- * - If the input contains a character that is not in ISO-8859-1 then the last two entries in the list will be the
- * UTF-8 encoder and the UTF-16BE encoder.
- *
- * @author Alex Geller
- */
-
-// List of encoders that potentially encode characters not in ISO-8859-1 in one byte.
- const ENCODERS: List = ArrayList<>::new();
-pub struct ECIEncoderSet {
-
- let mut encoders: Vec;
-
- let priority_encoder_index: i32;
-}
-
-impl ECIEncoderSet {
-
- static {
- let names: vec![Vec; 20] = vec!["IBM437", "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", "ISO-8859-10", "ISO-8859-11", "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "ISO-8859-16", "windows-1250", "windows-1251", "windows-1252", "windows-1256", "Shift_JIS", ]
- ;
- for let name: String in names {
- if CharacterSetECI::get_character_set_e_c_i_by_name(&name) != null {
- let tryResult1 = 0;
- 'try1: loop {
- {
- ENCODERS::add(&Charset::for_name(&name)::new_encoder());
- }
- break 'try1
- }
- match tryResult1 {
- catch ( e: &UnsupportedCharsetException) {
- } 0 => break
- }
-
- }
- }
- }
-
- /**
- * Constructs an encoder set
- *
- * @param stringToEncode the string that needs to be encoded
- * @param priorityCharset The preferred {@link Charset} or null.
- * @param fnc1 fnc1 denotes the character in the input that represents the FNC1 character or -1 for a non-GS1 bar
- * code. When specified, it is considered an error to pass it as argument to the methods canEncode() or encode().
- */
- pub fn new( string_to_encode: &String, priority_charset: &Charset, fnc1: i32) -> ECIEncoderSet {
- let needed_encoders: List = ArrayList<>::new();
- //we always need the ISO-8859-1 encoder. It is the default encoding
- needed_encoders.add(&StandardCharsets::ISO_8859_1::new_encoder());
- let need_unicode_encoder: bool = priority_charset != null && priority_charset.name().starts_with("UTF");
- //Walk over the input string and see if all characters can be encoded with the list of encoders
- {
- let mut i: i32 = 0;
- while i < string_to_encode.length() {
- {
- let can_encode: bool = false;
- for let encoder: CharsetEncoder in needed_encoders {
- let c: char = string_to_encode.char_at(i);
- if c == fnc1 || encoder.can_encode(c) {
- can_encode = true;
- break;
- }
- }
- if !can_encode {
- //for the character at position i we don't yet have an encoder in the list
- for let encoder: CharsetEncoder in ENCODERS {
- if encoder.can_encode(&string_to_encode.char_at(i)) {
- //Good, we found an encoder that can encode the character. We add him to the list and continue scanning
- //the input
- needed_encoders.add(&encoder);
- can_encode = true;
- break;
- }
- }
- }
- if !can_encode {
- //The character is not encodeable by any of the single byte encoders so we remember that we will need a
- //Unicode encoder.
- need_unicode_encoder = true;
- }
- }
- i += 1;
- }
- }
-
- if needed_encoders.size() == 1 && !need_unicode_encoder {
- //the entire input can be encoded by the ISO-8859-1 encoder
- encoders = : vec![CharsetEncoder; 1] = vec![needed_encoders.get(0), ]
- ;
- } else {
- // we need more than one single byte encoder or we need a Unicode encoder.
- // In this case we append a UTF-8 and UTF-16 encoder to the list
- encoders = : [Option; needed_encoders.size() + 2] = [None; needed_encoders.size() + 2];
- let mut index: i32 = 0;
- for let encoder: CharsetEncoder in needed_encoders {
- encoders[index += 1 !!!check!!! post increment] = encoder;
- }
- encoders[index] = StandardCharsets::UTF_8::new_encoder();
- encoders[index + 1] = StandardCharsets::UTF_16BE::new_encoder();
- }
- //Compute priorityEncoderIndex by looking up priorityCharset in encoders
- let priority_encoder_index_value: i32 = -1;
- if priority_charset != null {
- {
- let mut i: i32 = 0;
- while i < encoders.len() {
- {
- if encoders[i] != null && priority_charset.name().equals(&encoders[i].charset().name()) {
- priority_encoder_index_value = i;
- break;
- }
- }
- i += 1;
- }
- }
-
- }
- priority_encoder_index = priority_encoder_index_value;
- //invariants
- assert!( encoders[0].charset().equals(StandardCharsets::ISO_8859_1));
- }
-
- pub fn length(&self) -> i32 {
- return self.encoders.len();
- }
-
- pub fn get_charset_name(&self, index: i32) -> String {
- assert!( index < self.length());
- return self.encoders[index].charset().name();
- }
-
- pub fn get_charset(&self, index: i32) -> Charset {
- assert!( index < self.length());
- return self.encoders[index].charset();
- }
-
- pub fn get_e_c_i_value(&self, encoder_index: i32) -> i32 {
- return CharacterSetECI::get_character_set_e_c_i(&self.encoders[encoder_index].charset())::get_value();
- }
-
- /*
- * returns -1 if no priority charset was defined
- */
- pub fn get_priority_encoder_index(&self) -> i32 {
- return self.priority_encoder_index;
- }
-
- pub fn can_encode(&self, c: char, encoder_index: i32) -> bool {
- assert!( encoder_index < self.length());
- let encoder: CharsetEncoder = self.encoders[encoder_index];
- return encoder.can_encode(format!("{}", c));
- }
-
- pub fn encode(&self, c: char, encoder_index: i32) -> Vec {
- assert!( encoder_index < self.length());
- let encoder: CharsetEncoder = self.encoders[encoder_index];
- assert!( encoder.can_encode(format!("{}", c)));
- return (format!("{}", c)).get_bytes(&encoder.charset());
- }
-
- pub fn encode(&self, s: &String, encoder_index: i32) -> Vec {
- assert!( encoder_index < self.length());
- let encoder: CharsetEncoder = self.encoders[encoder_index];
- return s.get_bytes(&encoder.charset());
- }
-}
-
diff --git a/port_src/output/zxing/common/e_c_i_input.rs b/port_src/output/zxing/common/e_c_i_input.rs
deleted file mode 100644
index 64bec0f..0000000
--- a/port_src/output/zxing/common/e_c_i_input.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2021 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * Interface to navigate a sequence of ECIs and bytes.
- *
- * @author Alex Geller
- */
-pub trait ECIInput {
-
- /**
- * Returns the length of this input. The length is the number
- * of {@code byte}s in or ECIs in the sequence.
- *
- * @return the number of {@code char}s in this sequence
- */
- fn length(&self) -> i32 ;
-
- /**
- * Returns the {@code byte} value at the specified index. An index ranges from zero
- * to {@code length() - 1}. The first {@code byte} value of the sequence is at
- * index zero, the next at index one, and so on, as for array
- * indexing.
- *
- * @param index the index of the {@code byte} value to be returned
- *
- * @return the specified {@code byte} value as character or the FNC1 character
- *
- * @throws IndexOutOfBoundsException
- * if the {@code index} argument is negative or not less than
- * {@code length()}
- * @throws IllegalArgumentException
- * if the value at the {@code index} argument is an ECI (@see #isECI)
- */
- fn char_at(&self, index: i32) -> char ;
-
- /**
- * Returns a {@code CharSequence} that is a subsequence of this sequence.
- * The subsequence starts with the {@code char} value at the specified index and
- * ends with the {@code char} value at index {@code end - 1}. The length
- * (in {@code char}s) of the
- * returned sequence is {@code end - start}, so if {@code start == end}
- * then an empty sequence is returned.
- *
- * @param start the start index, inclusive
- * @param end the end index, exclusive
- *
- * @return the specified subsequence
- *
- * @throws IndexOutOfBoundsException
- * if {@code start} or {@code end} are negative,
- * if {@code end} is greater than {@code length()},
- * or if {@code start} is greater than {@code end}
- * @throws IllegalArgumentException
- * if a value in the range {@code start}-{@code end} is an ECI (@see #isECI)
- */
- fn sub_sequence(&self, start: i32, end: i32) -> CharSequence ;
-
- /**
- * Determines if a value is an ECI
- *
- * @param index the index of the value
- *
- * @return true if the value at position {@code index} is an ECI
- *
- * @throws IndexOutOfBoundsException
- * if the {@code index} argument is negative or not less than
- * {@code length()}
- */
- fn is_e_c_i(&self, index: i32) -> bool ;
-
- /**
- * Returns the {@code int} ECI value at the specified index. An index ranges from zero
- * to {@code length() - 1}. The first {@code byte} value of the sequence is at
- * index zero, the next at index one, and so on, as for array
- * indexing.
- *
- * @param index the index of the {@code int} value to be returned
- *
- * @return the specified {@code int} ECI value.
- * The ECI specified the encoding of all bytes with a higher index until the
- * next ECI or until the end of the input if no other ECI follows.
- *
- * @throws IndexOutOfBoundsException
- * if the {@code index} argument is negative or not less than
- * {@code length()}
- * @throws IllegalArgumentException
- * if the value at the {@code index} argument is not an ECI (@see #isECI)
- */
- fn get_e_c_i_value(&self, index: i32) -> i32 ;
-
- fn have_n_characters(&self, index: i32, n: i32) -> bool ;
-}
-
diff --git a/port_src/output/zxing/common/e_c_i_string_builder.rs b/port_src/output/zxing/common/e_c_i_string_builder.rs
deleted file mode 100644
index e6b3e97..0000000
--- a/port_src/output/zxing/common/e_c_i_string_builder.rs
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2022 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * Class that converts a sequence of ECIs and bytes into a string
- *
- * @author Alex Geller
- */
-pub struct ECIStringBuilder {
-
- let current_bytes: StringBuilder;
-
- let mut result: StringBuilder;
-
- let current_charset: Charset = StandardCharsets::ISO_8859_1;
-}
-
-impl ECIStringBuilder {
-
- pub fn new() -> ECIStringBuilder {
- current_bytes = StringBuilder::new();
- }
-
- pub fn new( initial_capacity: i32) -> ECIStringBuilder {
- current_bytes = StringBuilder::new(initial_capacity);
- }
-
- /**
- * Appends {@code value} as a byte value
- *
- * @param value character whose lowest byte is to be appended
- */
- pub fn append(&self, value: char) {
- self.current_bytes.append((value & 0xff) as char);
- }
-
- /**
- * Appends {@code value} as a byte value
- *
- * @param value byte to append
- */
- pub fn append(&self, value: i8) {
- self.current_bytes.append((value & 0xff) as char);
- }
-
- /**
- * Appends the characters in {@code value} as bytes values
- *
- * @param value string to append
- */
- pub fn append(&self, value: &String) {
- self.current_bytes.append(&value);
- }
-
- /**
- * Append the string repesentation of {@code value} (short for {@code append(String.valueOf(value))})
- *
- * @param value int to append as a string
- */
- pub fn append(&self, value: i32) {
- self.append(&String::value_of(value));
- }
-
- /**
- * Appends ECI value to output.
- *
- * @param value ECI value to append, as an int
- * @throws FormatException on invalid ECI value
- */
- pub fn append_e_c_i(&self, value: i32) -> /* throws FormatException */Result> {
- self.encode_current_bytes_if_any();
- let character_set_e_c_i: CharacterSetECI = CharacterSetECI::get_character_set_e_c_i_by_value(value);
- if character_set_e_c_i == null {
- throw FormatException::get_format_instance();
- }
- self.current_charset = character_set_e_c_i.get_charset();
- }
-
- fn encode_current_bytes_if_any(&self) {
- if self.current_charset.equals(StandardCharsets::ISO_8859_1) {
- if self.current_bytes.length() > 0 {
- if self.result == null {
- self.result = self.current_bytes;
- self.current_bytes = StringBuilder::new();
- } else {
- self.result.append(&self.current_bytes);
- self.current_bytes = StringBuilder::new();
- }
- }
- } else if self.current_bytes.length() > 0 {
- let bytes: Vec = self.current_bytes.to_string().get_bytes(StandardCharsets::ISO_8859_1);
- self.current_bytes = StringBuilder::new();
- if self.result == null {
- self.result = StringBuilder::new(String::new(&bytes, &self.current_charset));
- } else {
- self.result.append(String::new(&bytes, &self.current_charset));
- }
- }
- }
-
- /**
- * Appends the characters from {@code value} (unlike all other append methods of this class who append bytes)
- *
- * @param value characters to append
- */
- pub fn append_characters(&self, value: &StringBuilder) {
- self.encode_current_bytes_if_any();
- self.result.append(&value);
- }
-
- /**
- * Short for {@code toString().length()} (if possible, use {@link #isEmpty()} instead)
- *
- * @return length of string representation in characters
- */
- pub fn length(&self) -> i32 {
- return self.to_string().length();
- }
-
- /**
- * @return true iff nothing has been appended
- */
- pub fn is_empty(&self) -> bool {
- return self.current_bytes.length() == 0 && (self.result == null || self.result.length() == 0);
- }
-
- pub fn to_string(&self) -> String {
- self.encode_current_bytes_if_any();
- return if self.result == null { "" } else { self.result.to_string() };
- }
-}
-
diff --git a/port_src/output/zxing/common/global_histogram_binarizer.rs b/port_src/output/zxing/common/global_histogram_binarizer.rs
deleted file mode 100644
index fc2b7ee..0000000
--- a/port_src/output/zxing/common/global_histogram_binarizer.rs
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * This Binarizer implementation uses the old ZXing global histogram approach. It is suitable
- * for low-end mobile devices which don't have enough CPU or memory to use a local thresholding
- * algorithm. However, because it picks a global black point, it cannot handle difficult shadows
- * and gradients.
- *
- * Faster mobile devices and all desktop applications should probably use HybridBinarizer instead.
- *
- * @author dswitkin@google.com (Daniel Switkin)
- * @author Sean Owen
- */
-
- const LUMINANCE_BITS: i32 = 5;
-
- const LUMINANCE_SHIFT: i32 = 8 - LUMINANCE_BITS;
-
- const LUMINANCE_BUCKETS: i32 = 1 << LUMINANCE_BITS;
-
- const EMPTY: [i8; 0] = [0; 0];
-pub struct GlobalHistogramBinarizer {
- super: Binarizer;
-
- let mut luminances: Vec;
-
- let mut buckets: Vec;
-}
-
-impl GlobalHistogramBinarizer {
-
- pub fn new( source: &LuminanceSource) -> GlobalHistogramBinarizer {
- super(source);
- luminances = EMPTY;
- buckets = : [i32; LUMINANCE_BUCKETS] = [0; LUMINANCE_BUCKETS];
- }
-
- // Applies simple sharpening to the row data to improve performance of the 1D Readers.
- pub fn get_black_row(&self, y: i32, row: &BitArray) -> /* throws NotFoundException */Result> {
- let source: LuminanceSource = get_luminance_source();
- let width: i32 = source.get_width();
- if row == null || row.get_size() < width {
- row = BitArray::new(width);
- } else {
- row.clear();
- }
- self.init_arrays(width);
- let local_luminances: Vec = source.get_row(y, &self.luminances);
- let local_buckets: Vec = self.buckets;
- {
- let mut x: i32 = 0;
- while x < width {
- {
- local_buckets[(local_luminances[x] & 0xff) >> LUMINANCE_SHIFT] += 1;
- }
- x += 1;
- }
- }
-
- let black_point: i32 = ::estimate_black_point(&local_buckets);
- if width < 3 {
- // Special case for very small images
- {
- let mut x: i32 = 0;
- while x < width {
- {
- if (local_luminances[x] & 0xff) < black_point {
- row.set(x);
- }
- }
- x += 1;
- }
- }
-
- } else {
- let mut left: i32 = local_luminances[0] & 0xff;
- let mut center: i32 = local_luminances[1] & 0xff;
- {
- let mut x: i32 = 1;
- while x < width - 1 {
- {
- let right: i32 = local_luminances[x + 1] & 0xff;
- // A simple -1 4 -1 box filter with a weight of 2.
- if ((center * 4) - left - right) / 2 < black_point {
- row.set(x);
- }
- left = center;
- center = right;
- }
- x += 1;
- }
- }
-
- }
- return Ok(row);
- }
-
- // Does not sharpen the data, as this call is intended to only be used by 2D Readers.
- pub fn get_black_matrix(&self) -> /* throws NotFoundException */Result> {
- let source: LuminanceSource = get_luminance_source();
- let width: i32 = source.get_width();
- let height: i32 = source.get_height();
- let matrix: BitMatrix = BitMatrix::new(width, height);
- // Quickly calculates the histogram by sampling four rows from the image. This proved to be
- // more robust on the blackbox tests than sampling a diagonal as we used to do.
- self.init_arrays(width);
- let local_buckets: Vec = self.buckets;
- {
- let mut y: i32 = 1;
- while y < 5 {
- {
- let row: i32 = height * y / 5;
- let local_luminances: Vec = source.get_row(row, &self.luminances);
- let right: i32 = (width * 4) / 5;
- {
- let mut x: i32 = width / 5;
- while x < right {
- {
- let mut pixel: i32 = local_luminances[x] & 0xff;
- local_buckets[pixel >> LUMINANCE_SHIFT] += 1;
- }
- x += 1;
- }
- }
-
- }
- y += 1;
- }
- }
-
- let black_point: i32 = ::estimate_black_point(&local_buckets);
- // We delay reading the entire image luminance until the black point estimation succeeds.
- // Although we end up reading four rows twice, it is consistent with our motto of
- // "fail quickly" which is necessary for continuous scanning.
- let local_luminances: Vec = source.get_matrix();
- {
- let mut y: i32 = 0;
- while y < height {
- {
- let offset: i32 = y * width;
- {
- let mut x: i32 = 0;
- while x < width {
- {
- let pixel: i32 = local_luminances[offset + x] & 0xff;
- if pixel < black_point {
- matrix.set(x, y);
- }
- }
- x += 1;
- }
- }
-
- }
- y += 1;
- }
- }
-
- return Ok(matrix);
- }
-
- pub fn create_binarizer(&self, source: &LuminanceSource) -> Binarizer {
- return GlobalHistogramBinarizer::new(source);
- }
-
- fn init_arrays(&self, luminance_size: i32) {
- if self.luminances.len() < luminance_size {
- self.luminances = : [i8; luminance_size] = [0; luminance_size];
- }
- {
- let mut x: i32 = 0;
- while x < LUMINANCE_BUCKETS {
- {
- self.buckets[x] = 0;
- }
- x += 1;
- }
- }
-
- }
-
- fn estimate_black_point( buckets: &Vec) -> /* throws NotFoundException */Result> {
- // Find the tallest peak in the histogram.
- let num_buckets: i32 = buckets.len();
- let max_bucket_count: i32 = 0;
- let first_peak: i32 = 0;
- let first_peak_size: i32 = 0;
- {
- let mut x: i32 = 0;
- while x < num_buckets {
- {
- if buckets[x] > first_peak_size {
- first_peak = x;
- first_peak_size = buckets[x];
- }
- if buckets[x] > max_bucket_count {
- max_bucket_count = buckets[x];
- }
- }
- x += 1;
- }
- }
-
- // Find the second-tallest peak which is somewhat far from the tallest peak.
- let second_peak: i32 = 0;
- let second_peak_score: i32 = 0;
- {
- let mut x: i32 = 0;
- while x < num_buckets {
- {
- let distance_to_biggest: i32 = x - first_peak;
- // Encourage more distant second peaks by multiplying by square of distance.
- let score: i32 = buckets[x] * distance_to_biggest * distance_to_biggest;
- if score > second_peak_score {
- second_peak = x;
- second_peak_score = score;
- }
- }
- x += 1;
- }
- }
-
- // Make sure firstPeak corresponds to the black peak.
- if first_peak > second_peak {
- let temp: i32 = first_peak;
- first_peak = second_peak;
- second_peak = temp;
- }
- // than waste time trying to decode the image, and risk false positives.
- if second_peak - first_peak <= num_buckets / 16 {
- throw NotFoundException::get_not_found_instance();
- }
- // Find a valley between them that is low and closer to the white peak.
- let best_valley: i32 = second_peak - 1;
- let best_valley_score: i32 = -1;
- {
- let mut x: i32 = second_peak - 1;
- while x > first_peak {
- {
- let from_first: i32 = x - first_peak;
- let score: i32 = from_first * from_first * (second_peak - x) * (max_bucket_count - buckets[x]);
- if score > best_valley_score {
- best_valley = x;
- best_valley_score = score;
- }
- }
- x -= 1;
- }
- }
-
- return Ok(best_valley << LUMINANCE_SHIFT);
- }
-}
-
diff --git a/port_src/output/zxing/common/grid_sampler.rs b/port_src/output/zxing/common/grid_sampler.rs
deleted file mode 100644
index f38912b..0000000
--- a/port_src/output/zxing/common/grid_sampler.rs
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * Implementations of this class can, given locations of finder patterns for a QR code in an
- * image, sample the right points in the image to reconstruct the QR code, accounting for
- * perspective distortion. It is abstracted since it is relatively expensive and should be allowed
- * to take advantage of platform-specific optimized implementations, like Sun's Java Advanced
- * Imaging library, but which may not be available in other environments such as J2ME, and vice
- * versa.
- *
- * The implementation used can be controlled by calling {@link #setGridSampler(GridSampler)}
- * with an instance of a class which implements this interface.
- *
- * @author Sean Owen
- */
-
- let grid_sampler: GridSampler = DefaultGridSampler::new();
-pub struct GridSampler {
-}
-
-impl GridSampler {
-
- /**
- * Sets the implementation of GridSampler used by the library. One global
- * instance is stored, which may sound problematic. But, the implementation provided
- * ought to be appropriate for the entire platform, and all uses of this library
- * in the whole lifetime of the JVM. For instance, an Android activity can swap in
- * an implementation that takes advantage of native platform libraries.
- *
- * @param newGridSampler The platform-specific object to install.
- */
- pub fn set_grid_sampler( new_grid_sampler: &GridSampler) {
- grid_sampler = new_grid_sampler;
- }
-
- /**
- * @return the current implementation of GridSampler
- */
- pub fn get_instance() -> GridSampler {
- return grid_sampler;
- }
-
- /**
- * Samples an image for a rectangular matrix of bits of the given dimension. The sampling
- * transformation is determined by the coordinates of 4 points, in the original and transformed
- * image space.
- *
- * @param image image to sample
- * @param dimensionX width of {@link BitMatrix} to sample from image
- * @param dimensionY height of {@link BitMatrix} to sample from image
- * @param p1ToX point 1 preimage X
- * @param p1ToY point 1 preimage Y
- * @param p2ToX point 2 preimage X
- * @param p2ToY point 2 preimage Y
- * @param p3ToX point 3 preimage X
- * @param p3ToY point 3 preimage Y
- * @param p4ToX point 4 preimage X
- * @param p4ToY point 4 preimage Y
- * @param p1FromX point 1 image X
- * @param p1FromY point 1 image Y
- * @param p2FromX point 2 image X
- * @param p2FromY point 2 image Y
- * @param p3FromX point 3 image X
- * @param p3FromY point 3 image Y
- * @param p4FromX point 4 image X
- * @param p4FromY point 4 image Y
- * @return {@link BitMatrix} representing a grid of points sampled from the image within a region
- * defined by the "from" parameters
- * @throws NotFoundException if image can't be sampled, for example, if the transformation defined
- * by the given points is invalid or results in sampling outside the image boundaries
- */
- pub fn sample_grid(&self, image: &BitMatrix, dimension_x: i32, dimension_y: i32, p1_to_x: f32, p1_to_y: f32, p2_to_x: f32, p2_to_y: f32, p3_to_x: f32, p3_to_y: f32, p4_to_x: f32, p4_to_y: f32, p1_from_x: f32, p1_from_y: f32, p2_from_x: f32, p2_from_y: f32, p3_from_x: f32, p3_from_y: f32, p4_from_x: f32, p4_from_y: f32) -> /* throws NotFoundException */Result> ;
-
- pub fn sample_grid(&self, image: &BitMatrix, dimension_x: i32, dimension_y: i32, transform: &PerspectiveTransform) -> /* throws NotFoundException */Result> ;
-
- /**
- * Checks a set of points that have been transformed to sample points on an image against
- * the image's dimensions to see if the point are even within the image.
- *
- * This method will actually "nudge" the endpoints back onto the image if they are found to be
- * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder
- * patterns in an image where the QR Code runs all the way to the image border.
- *
- * For efficiency, the method will check points from either end of the line until one is found
- * to be within the image. Because the set of points are assumed to be linear, this is valid.
- *
- * @param image image into which the points should map
- * @param points actual points in x1,y1,...,xn,yn form
- * @throws NotFoundException if an endpoint is lies outside the image boundaries
- */
- pub fn check_and_nudge_points( image: &BitMatrix, points: &Vec) -> /* throws NotFoundException */Result> {
- let width: i32 = image.get_width();
- let height: i32 = image.get_height();
- // Check and nudge points from start until we see some that are OK:
- let mut nudged: bool = true;
- // points.length must be even
- let max_offset: i32 = points.len() - 1;
- {
- let mut offset: i32 = 0;
- while offset < max_offset && nudged {
- {
- let x: i32 = points[offset] as i32;
- let y: i32 = points[offset + 1] as i32;
- if x < -1 || x > width || y < -1 || y > height {
- throw NotFoundException::get_not_found_instance();
- }
- nudged = false;
- if x == -1 {
- points[offset] = 0.0f;
- nudged = true;
- } else if x == width {
- points[offset] = width - 1.0;
- nudged = true;
- }
- if y == -1 {
- points[offset + 1] = 0.0f;
- nudged = true;
- } else if y == height {
- points[offset + 1] = height - 1.0;
- nudged = true;
- }
- }
- offset += 2;
- }
- }
-
- // Check and nudge points from end:
- nudged = true;
- {
- let mut offset: i32 = points.len() - 2;
- while offset >= 0 && nudged {
- {
- let x: i32 = points[offset] as i32;
- let y: i32 = points[offset + 1] as i32;
- if x < -1 || x > width || y < -1 || y > height {
- throw NotFoundException::get_not_found_instance();
- }
- nudged = false;
- if x == -1 {
- points[offset] = 0.0f;
- nudged = true;
- } else if x == width {
- points[offset] = width - 1.0;
- nudged = true;
- }
- if y == -1 {
- points[offset + 1] = 0.0f;
- nudged = true;
- } else if y == height {
- points[offset + 1] = height - 1.0;
- nudged = true;
- }
- }
- offset -= 2;
- }
- }
-
- }
-}
-
diff --git a/port_src/output/zxing/common/hybrid_binarizer.rs b/port_src/output/zxing/common/hybrid_binarizer.rs
deleted file mode 100644
index 7533abf..0000000
--- a/port_src/output/zxing/common/hybrid_binarizer.rs
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * This class implements a local thresholding algorithm, which while slower than the
- * GlobalHistogramBinarizer, is fairly efficient for what it does. It is designed for
- * high frequency images of barcodes with black data on white backgrounds. For this application,
- * it does a much better job than a global blackpoint with severe shadows and gradients.
- * However it tends to produce artifacts on lower frequency images and is therefore not
- * a good general purpose binarizer for uses outside ZXing.
- *
- * This class extends GlobalHistogramBinarizer, using the older histogram approach for 1D readers,
- * and the newer local approach for 2D readers. 1D decoding using a per-row histogram is already
- * inherently local, and only fails for horizontal gradients. We can revisit that problem later,
- * but for now it was not a win to use local blocks for 1D.
- *
- * This Binarizer is the default for the unit tests and the recommended class for library users.
- *
- * @author dswitkin@google.com (Daniel Switkin)
- */
-
-// This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels.
-// So this is the smallest dimension in each axis we can accept.
- const BLOCK_SIZE_POWER: i32 = 3;
-
-// ...0100...00
- const BLOCK_SIZE: i32 = 1 << BLOCK_SIZE_POWER;
-
-// ...0011...11
- const BLOCK_SIZE_MASK: i32 = BLOCK_SIZE - 1;
-
- const MINIMUM_DIMENSION: i32 = BLOCK_SIZE * 5;
-
- const MIN_DYNAMIC_RANGE: i32 = 24;
-pub struct HybridBinarizer {
- super: GlobalHistogramBinarizer;
-
- let mut matrix: BitMatrix;
-}
-
-impl HybridBinarizer {
-
- pub fn new( source: &LuminanceSource) -> HybridBinarizer {
- super(source);
- }
-
- /**
- * Calculates the final BitMatrix once for all requests. This could be called once from the
- * constructor instead, but there are some advantages to doing it lazily, such as making
- * profiling easier, and not doing heavy lifting when callers don't expect it.
- */
- pub fn get_black_matrix(&self) -> /* throws NotFoundException */Result> {
- if self.matrix != null {
- return Ok(self.matrix);
- }
- let source: LuminanceSource = get_luminance_source();
- let width: i32 = source.get_width();
- let height: i32 = source.get_height();
- if width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION {
- let luminances: Vec = source.get_matrix();
- let sub_width: i32 = width >> BLOCK_SIZE_POWER;
- if (width & BLOCK_SIZE_MASK) != 0 {
- sub_width += 1;
- }
- let sub_height: i32 = height >> BLOCK_SIZE_POWER;
- if (height & BLOCK_SIZE_MASK) != 0 {
- sub_height += 1;
- }
- let black_points: Vec> = ::calculate_black_points(&luminances, sub_width, sub_height, width, height);
- let new_matrix: BitMatrix = BitMatrix::new(width, height);
- ::calculate_threshold_for_block(&luminances, sub_width, sub_height, width, height, &black_points, new_matrix);
- self.matrix = new_matrix;
- } else {
- // If the image is too small, fall back to the global histogram approach.
- self.matrix = super.get_black_matrix();
- }
- return Ok(self.matrix);
- }
-
- pub fn create_binarizer(&self, source: &LuminanceSource) -> Binarizer {
- return HybridBinarizer::new(source);
- }
-
- /**
- * For each block in the image, calculate the average black point using a 5x5 grid
- * of the blocks around it. Also handles the corner cases (fractional blocks are computed based
- * on the last pixels in the row/column which are also used in the previous block).
- */
- fn calculate_threshold_for_block( luminances: &Vec, sub_width: i32, sub_height: i32, width: i32, height: i32, black_points: &Vec>, matrix: &BitMatrix) {
- let max_y_offset: i32 = height - BLOCK_SIZE;
- let max_x_offset: i32 = width - BLOCK_SIZE;
- {
- let mut y: i32 = 0;
- while y < sub_height {
- {
- let mut yoffset: i32 = y << BLOCK_SIZE_POWER;
- if yoffset > max_y_offset {
- yoffset = max_y_offset;
- }
- let top: i32 = ::cap(y, sub_height - 3);
- {
- let mut x: i32 = 0;
- while x < sub_width {
- {
- let mut xoffset: i32 = x << BLOCK_SIZE_POWER;
- if xoffset > max_x_offset {
- xoffset = max_x_offset;
- }
- let left: i32 = ::cap(x, sub_width - 3);
- let mut sum: i32 = 0;
- {
- let mut z: i32 = -2;
- while z <= 2 {
- {
- let black_row: Vec = black_points[top + z];
- sum += black_row[left - 2] + black_row[left - 1] + black_row[left] + black_row[left + 1] + black_row[left + 2];
- }
- z += 1;
- }
- }
-
- let average: i32 = sum / 25;
- ::threshold_block(&luminances, xoffset, yoffset, average, width, matrix);
- }
- x += 1;
- }
- }
-
- }
- y += 1;
- }
- }
-
- }
-
- fn cap( value: i32, max: i32) -> i32 {
- return if value < 2 { 2 } else { Math::min(value, max) };
- }
-
- /**
- * Applies a single threshold to a block of pixels.
- */
- fn threshold_block( luminances: &Vec, xoffset: i32, yoffset: i32, threshold: i32, stride: i32, matrix: &BitMatrix) {
- {
- let mut y: i32 = 0, let mut offset: i32 = yoffset * stride + xoffset;
- while y < BLOCK_SIZE {
- {
- {
- let mut x: i32 = 0;
- while x < BLOCK_SIZE {
- {
- // Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0.
- if (luminances[offset + x] & 0xFF) <= threshold {
- matrix.set(xoffset + x, yoffset + y);
- }
- }
- x += 1;
- }
- }
-
- }
- y += 1;
- offset += stride;
- }
- }
-
- }
-
- /**
- * Calculates a single black point for each block of pixels and saves it away.
- * See the following thread for a discussion of this algorithm:
- * http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0
- */
- fn calculate_black_points( luminances: &Vec, sub_width: i32, sub_height: i32, width: i32, height: i32) -> Vec> {
- let max_y_offset: i32 = height - BLOCK_SIZE;
- let max_x_offset: i32 = width - BLOCK_SIZE;
- let black_points: [[i32; sub_width]; sub_height] = [[0; sub_width]; sub_height];
- {
- let mut y: i32 = 0;
- while y < sub_height {
- {
- let mut yoffset: i32 = y << BLOCK_SIZE_POWER;
- if yoffset > max_y_offset {
- yoffset = max_y_offset;
- }
- {
- let mut x: i32 = 0;
- while x < sub_width {
- {
- let mut xoffset: i32 = x << BLOCK_SIZE_POWER;
- if xoffset > max_x_offset {
- xoffset = max_x_offset;
- }
- let mut sum: i32 = 0;
- let mut min: i32 = 0xFF;
- let mut max: i32 = 0;
- {
- let mut yy: i32 = 0, let mut offset: i32 = yoffset * width + xoffset;
- while yy < BLOCK_SIZE {
- {
- {
- let mut xx: i32 = 0;
- while xx < BLOCK_SIZE {
- {
- let pixel: i32 = luminances[offset + xx] & 0xFF;
- sum += pixel;
- // still looking for good contrast
- if pixel < min {
- min = pixel;
- }
- if pixel > max {
- max = pixel;
- }
- }
- xx += 1;
- }
- }
-
- // short-circuit min/max tests once dynamic range is met
- if max - min > MIN_DYNAMIC_RANGE {
- // finish the rest of the rows quickly
- {
- yy += 1;
- offset += width;
- while yy < BLOCK_SIZE {
- {
- {
- let mut xx: i32 = 0;
- while xx < BLOCK_SIZE {
- {
- sum += luminances[offset + xx] & 0xFF;
- }
- xx += 1;
- }
- }
-
- }
- yy += 1;
- offset += width;
- }
- }
-
- }
- }
- yy += 1;
- offset += width;
- }
- }
-
- // The default estimate is the average of the values in the block.
- let mut average: i32 = sum >> (BLOCK_SIZE_POWER * 2);
- if max - min <= MIN_DYNAMIC_RANGE {
- // If variation within the block is low, assume this is a block with only light or only
- // dark pixels. In that case we do not want to use the average, as it would divide this
- // low contrast area into black and white pixels, essentially creating data out of noise.
- //
- // The default assumption is that the block is light/background. Since no estimate for
- // the level of dark pixels exists locally, use half the min for the block.
- average = min / 2;
- if y > 0 && x > 0 {
- // Correct the "white background" assumption for blocks that have neighbors by comparing
- // the pixels in this block to the previously calculated black points. This is based on
- // the fact that dark barcode symbology is always surrounded by some amount of light
- // background for which reasonable black point estimates were made. The bp estimated at
- // the boundaries is used for the interior.
- // The (min < bp) is arbitrary but works better than other heuristics that were tried.
- let average_neighbor_black_point: i32 = (black_points[y - 1][x] + (2 * black_points[y][x - 1]) + black_points[y - 1][x - 1]) / 4;
- if min < average_neighbor_black_point {
- average = average_neighbor_black_point;
- }
- }
- }
- black_points[y][x] = average;
- }
- x += 1;
- }
- }
-
- }
- y += 1;
- }
- }
-
- return black_points;
- }
-}
-
diff --git a/port_src/output/zxing/common/minimal_e_c_i_input.rs b/port_src/output/zxing/common/minimal_e_c_i_input.rs
deleted file mode 100644
index 89e393c..0000000
--- a/port_src/output/zxing/common/minimal_e_c_i_input.rs
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright 2021 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * Class that converts a character string into a sequence of ECIs and bytes
- *
- * The implementation uses the Dijkstra algorithm to produce minimal encodings
- *
- * @author Alex Geller
- */
-
-// approximated (latch + 2 codewords)
- const COST_PER_ECI: i32 = 3;
-#[derive(ECIInput)]
-pub struct MinimalECIInput {
-
- let mut bytes: Vec;
-
- let fnc1: i32;
-}
-
-impl MinimalECIInput {
-
- /**
- * Constructs a minimal input
- *
- * @param stringToEncode the character string to encode
- * @param priorityCharset The preferred {@link Charset}. When the value of the argument is null, the algorithm
- * chooses charsets that leads to a minimal representation. Otherwise the algorithm will use the priority
- * charset to encode any character in the input that can be encoded by it if the charset is among the
- * supported charsets.
- * @param fnc1 denotes the character in the input that represents the FNC1 character or -1 if this is not GS1
- * input.
- */
- pub fn new( string_to_encode: &String, priority_charset: &Charset, fnc1: i32) -> MinimalECIInput {
- let .fnc1 = fnc1;
- let encoder_set: ECIEncoderSet = ECIEncoderSet::new(&string_to_encode, &priority_charset, fnc1);
- if encoder_set.length() == 1 {
- //optimization for the case when all can be encoded without ECI in ISO-8859-1
- bytes = : [i32; string_to_encode.length()] = [0; string_to_encode.length()];
- {
- let mut i: i32 = 0;
- while i < bytes.len() {
- {
- let c: char = string_to_encode.char_at(i);
- bytes[i] = if c == fnc1 { 1000 } else { c as i32 };
- }
- i += 1;
- }
- }
-
- } else {
- bytes = ::encode_minimally(&string_to_encode, encoder_set, fnc1);
- }
- }
-
- pub fn get_f_n_c1_character(&self) -> i32 {
- return self.fnc1;
- }
-
- /**
- * Returns the length of this input. The length is the number
- * of {@code byte}s, FNC1 characters or ECIs in the sequence.
- *
- * @return the number of {@code char}s in this sequence
- */
- pub fn length(&self) -> i32 {
- return self.bytes.len();
- }
-
- pub fn have_n_characters(&self, index: i32, n: i32) -> bool {
- if index + n - 1 >= self.bytes.len() {
- return false;
- }
- {
- let mut i: i32 = 0;
- while i < n {
- {
- if self.is_e_c_i(index + i) {
- return false;
- }
- }
- i += 1;
- }
- }
-
- return true;
- }
-
- /**
- * Returns the {@code byte} value at the specified index. An index ranges from zero
- * to {@code length() - 1}. The first {@code byte} value of the sequence is at
- * index zero, the next at index one, and so on, as for array
- * indexing.
- *
- * @param index the index of the {@code byte} value to be returned
- *
- * @return the specified {@code byte} value as character or the FNC1 character
- *
- * @throws IndexOutOfBoundsException
- * if the {@code index} argument is negative or not less than
- * {@code length()}
- * @throws IllegalArgumentException
- * if the value at the {@code index} argument is an ECI (@see #isECI)
- */
- pub fn char_at(&self, index: i32) -> char {
- if index < 0 || index >= self.length() {
- throw IndexOutOfBoundsException::new(format!("{}", index));
- }
- if self.is_e_c_i(index) {
- throw IllegalArgumentException::new(format!("value at {} is not a character but an ECI", index));
- }
- return if self.is_f_n_c1(index) { self.fnc1 as char } else { self.bytes[index] as char };
- }
-
- /**
- * Returns a {@code CharSequence} that is a subsequence of this sequence.
- * The subsequence starts with the {@code char} value at the specified index and
- * ends with the {@code char} value at index {@code end - 1}. The length
- * (in {@code char}s) of the
- * returned sequence is {@code end - start}, so if {@code start == end}
- * then an empty sequence is returned.
- *
- * @param start the start index, inclusive
- * @param end the end index, exclusive
- *
- * @return the specified subsequence
- *
- * @throws IndexOutOfBoundsException
- * if {@code start} or {@code end} are negative,
- * if {@code end} is greater than {@code length()},
- * or if {@code start} is greater than {@code end}
- * @throws IllegalArgumentException
- * if a value in the range {@code start}-{@code end} is an ECI (@see #isECI)
- */
- pub fn sub_sequence(&self, start: i32, end: i32) -> CharSequence {
- if start < 0 || start > end || end > self.length() {
- throw IndexOutOfBoundsException::new(format!("{}", start));
- }
- let result: StringBuilder = StringBuilder::new();
- {
- let mut i: i32 = start;
- while i < end {
- {
- if self.is_e_c_i(i) {
- throw IllegalArgumentException::new(format!("value at {} is not a character but an ECI", i));
- }
- result.append(&self.char_at(i));
- }
- i += 1;
- }
- }
-
- return result;
- }
-
- /**
- * Determines if a value is an ECI
- *
- * @param index the index of the value
- *
- * @return true if the value at position {@code index} is an ECI
- *
- * @throws IndexOutOfBoundsException
- * if the {@code index} argument is negative or not less than
- * {@code length()}
- */
- pub fn is_e_c_i(&self, index: i32) -> bool {
- if index < 0 || index >= self.length() {
- throw IndexOutOfBoundsException::new(format!("{}", index));
- }
- return self.bytes[index] > 255 && self.bytes[index] <= 999;
- }
-
- /**
- * Determines if a value is the FNC1 character
- *
- * @param index the index of the value
- *
- * @return true if the value at position {@code index} is the FNC1 character
- *
- * @throws IndexOutOfBoundsException
- * if the {@code index} argument is negative or not less than
- * {@code length()}
- */
- pub fn is_f_n_c1(&self, index: i32) -> bool {
- if index < 0 || index >= self.length() {
- throw IndexOutOfBoundsException::new(format!("{}", index));
- }
- return self.bytes[index] == 1000;
- }
-
- /**
- * Returns the {@code int} ECI value at the specified index. An index ranges from zero
- * to {@code length() - 1}. The first {@code byte} value of the sequence is at
- * index zero, the next at index one, and so on, as for array
- * indexing.
- *
- * @param index the index of the {@code int} value to be returned
- *
- * @return the specified {@code int} ECI value.
- * The ECI specified the encoding of all bytes with a higher index until the
- * next ECI or until the end of the input if no other ECI follows.
- *
- * @throws IndexOutOfBoundsException
- * if the {@code index} argument is negative or not less than
- * {@code length()}
- * @throws IllegalArgumentException
- * if the value at the {@code index} argument is not an ECI (@see #isECI)
- */
- pub fn get_e_c_i_value(&self, index: i32) -> i32 {
- if index < 0 || index >= self.length() {
- throw IndexOutOfBoundsException::new(format!("{}", index));
- }
- if !self.is_e_c_i(index) {
- throw IllegalArgumentException::new(format!("value at {} is not an ECI but a character", index));
- }
- return self.bytes[index] - 256;
- }
-
- pub fn to_string(&self) -> String {
- let result: StringBuilder = StringBuilder::new();
- {
- let mut i: i32 = 0;
- while i < self.length() {
- {
- if i > 0 {
- result.append(", ");
- }
- if self.is_e_c_i(i) {
- result.append("ECI(");
- result.append(&self.get_e_c_i_value(i));
- result.append(')');
- } else if self.char_at(i) < 128 {
- result.append('\'');
- result.append(&self.char_at(i));
- result.append('\'');
- } else {
- result.append(self.char_at(i) as i32);
- }
- }
- i += 1;
- }
- }
-
- return result.to_string();
- }
-
- fn add_edge( edges: &Vec>, to: i32, edge: &InputEdge) {
- if edges[to][edge.encoderIndex] == null || edges[to][edge.encoderIndex].cachedTotalSize > edge.cachedTotalSize {
- edges[to][edge.encoderIndex] = edge;
- }
- }
-
- fn add_edges( string_to_encode: &String, encoder_set: &ECIEncoderSet, edges: &Vec>, from: i32, previous: &InputEdge, fnc1: i32) {
- let ch: char = string_to_encode.char_at(from);
- let mut start: i32 = 0;
- let mut end: i32 = encoder_set.length();
- if encoder_set.get_priority_encoder_index() >= 0 && (ch == fnc1 || encoder_set.can_encode(ch, &encoder_set.get_priority_encoder_index())) {
- start = encoder_set.get_priority_encoder_index();
- end = start + 1;
- }
- {
- let mut i: i32 = start;
- while i < end {
- {
- if ch == fnc1 || encoder_set.can_encode(ch, i) {
- ::add_edge(edges, from + 1, InputEdge::new(ch, encoder_set, i, previous, fnc1));
- }
- }
- i += 1;
- }
- }
-
- }
-
- fn encode_minimally( string_to_encode: &String, encoder_set: &ECIEncoderSet, fnc1: i32) -> Vec {
- let input_length: i32 = string_to_encode.length();
- // Array that represents vertices. There is a vertex for every character and encoding.
- let mut edges: [[Option; encoder_set.length()]; input_length + 1] = [[None; encoder_set.length()]; input_length + 1];
- ::add_edges(&string_to_encode, encoder_set, edges, 0, null, fnc1);
- {
- let mut i: i32 = 1;
- while i <= input_length {
- {
- {
- let mut j: i32 = 0;
- while j < encoder_set.length() {
- {
- if edges[i][j] != null && i < input_length {
- ::add_edges(&string_to_encode, encoder_set, edges, i, edges[i][j], fnc1);
- }
- }
- j += 1;
- }
- }
-
- //optimize memory by removing edges that have been passed.
- {
- let mut j: i32 = 0;
- while j < encoder_set.length() {
- {
- edges[i - 1][j] = null;
- }
- j += 1;
- }
- }
-
- }
- i += 1;
- }
- }
-
- let minimal_j: i32 = -1;
- let minimal_size: i32 = Integer::MAX_VALUE;
- {
- let mut j: i32 = 0;
- while j < encoder_set.length() {
- {
- if edges[input_length][j] != null {
- let edge: InputEdge = edges[input_length][j];
- if edge.cachedTotalSize < minimal_size {
- minimal_size = edge.cachedTotalSize;
- minimal_j = j;
- }
- }
- }
- j += 1;
- }
- }
-
- if minimal_j < 0 {
- throw RuntimeException::new(format!("Internal error: failed to encode \"{}\"", string_to_encode));
- }
- let ints_a_l: List = ArrayList<>::new();
- let mut current: InputEdge = edges[input_length][minimal_j];
- while current != null {
- if current.is_f_n_c1() {
- ints_a_l.add(0, 1000);
- } else {
- let bytes: Vec = encoder_set.encode(current.c, current.encoderIndex);
- {
- let mut i: i32 = bytes.len() - 1;
- while i >= 0 {
- {
- ints_a_l.add(0, (bytes[i] & 0xFF));
- }
- i -= 1;
- }
- }
-
- }
- let previous_encoder_index: i32 = if current.previous == null { 0 } else { current.previous.encoderIndex };
- if previous_encoder_index != current.encoderIndex {
- ints_a_l.add(0, 256 + encoder_set.get_e_c_i_value(current.encoderIndex));
- }
- current = current.previous;
- }
- let mut ints: [i32; ints_a_l.size()] = [0; ints_a_l.size()];
- {
- let mut i: i32 = 0;
- while i < ints.len() {
- {
- ints[i] = ints_a_l.get(i);
- }
- i += 1;
- }
- }
-
- return ints;
- }
-
- struct InputEdge {
-
- let c: char;
-
- //the encoding of this edge
- let encoder_index: i32;
-
- let previous: InputEdge;
-
- let cached_total_size: i32;
- }
-
- impl InputEdge {
-
- fn new( c: char, encoder_set: &ECIEncoderSet, encoder_index: i32, previous: &InputEdge, fnc1: i32) -> InputEdge {
- let .c = if c == fnc1 { 1000 } else { c };
- let .encoderIndex = encoder_index;
- let .previous = previous;
- let mut size: i32 = if let .c == 1000 { 1 } else { encoder_set.encode(c, encoder_index).len() };
- let previous_encoder_index: i32 = if previous == null { 0 } else { previous.encoderIndex };
- if previous_encoder_index != encoder_index {
- size += COST_PER_ECI;
- }
- if previous != null {
- size += previous.cachedTotalSize;
- }
- let .cachedTotalSize = size;
- }
-
- fn is_f_n_c1(&self) -> bool {
- return self.c == 1000;
- }
- }
-
-}
-
diff --git a/port_src/output/zxing/common/perspective_transform.rs b/port_src/output/zxing/common/perspective_transform.rs
deleted file mode 100644
index dd1f5e5..0000000
--- a/port_src/output/zxing/common/perspective_transform.rs
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * This class implements a perspective transform in two dimensions. Given four source and four
- * destination points, it will compute the transformation implied between them. The code is based
- * directly upon section 3.4.2 of George Wolberg's "Digital Image Warping"; see pages 54-56.
- *
- * @author Sean Owen
- */
-pub struct PerspectiveTransform {
-
- let a11: f32;
-
- let a12: f32;
-
- let a13: f32;
-
- let a21: f32;
-
- let a22: f32;
-
- let a23: f32;
-
- let a31: f32;
-
- let a32: f32;
-
- let a33: f32;
-}
-
-impl PerspectiveTransform {
-
- fn new( a11: f32, a21: f32, a31: f32, a12: f32, a22: f32, a32: f32, a13: f32, a23: f32, a33: f32) -> PerspectiveTransform {
- let .a11 = a11;
- let .a12 = a12;
- let .a13 = a13;
- let .a21 = a21;
- let .a22 = a22;
- let .a23 = a23;
- let .a31 = a31;
- let .a32 = a32;
- let .a33 = a33;
- }
-
- pub fn quadrilateral_to_quadrilateral( x0: f32, y0: f32, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32, x0p: f32, y0p: f32, x1p: f32, y1p: f32, x2p: f32, y2p: f32, x3p: f32, y3p: f32) -> PerspectiveTransform {
- let q_to_s: PerspectiveTransform = ::quadrilateral_to_square(x0, y0, x1, y1, x2, y2, x3, y3);
- let s_to_q: PerspectiveTransform = ::square_to_quadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
- return s_to_q.times(q_to_s);
- }
-
- pub fn transform_points(&self, points: &Vec) {
- let a11: f32 = self.a11;
- let a12: f32 = self.a12;
- let a13: f32 = self.a13;
- let a21: f32 = self.a21;
- let a22: f32 = self.a22;
- let a23: f32 = self.a23;
- let a31: f32 = self.a31;
- let a32: f32 = self.a32;
- let a33: f32 = self.a33;
- // points.length must be even
- let max_i: i32 = points.len() - 1;
- {
- let mut i: i32 = 0;
- while i < max_i {
- {
- let x: f32 = points[i];
- let y: f32 = points[i + 1];
- let denominator: f32 = a13 * x + a23 * y + a33;
- points[i] = (a11 * x + a21 * y + a31) / denominator;
- points[i + 1] = (a12 * x + a22 * y + a32) / denominator;
- }
- i += 2;
- }
- }
-
- }
-
- pub fn transform_points(&self, x_values: &Vec, y_values: &Vec) {
- let n: i32 = x_values.len();
- {
- let mut i: i32 = 0;
- while i < n {
- {
- let x: f32 = x_values[i];
- let y: f32 = y_values[i];
- let denominator: f32 = self.a13 * x + self.a23 * y + self.a33;
- x_values[i] = (self.a11 * x + self.a21 * y + self.a31) / denominator;
- y_values[i] = (self.a12 * x + self.a22 * y + self.a32) / denominator;
- }
- i += 1;
- }
- }
-
- }
-
- pub fn square_to_quadrilateral( x0: f32, y0: f32, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) -> PerspectiveTransform {
- let dx3: f32 = x0 - x1 + x2 - x3;
- let dy3: f32 = y0 - y1 + y2 - y3;
- if dx3 == 0.0f && dy3 == 0.0f {
- // Affine
- return PerspectiveTransform::new(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0f, 0.0f, 1.0f);
- } else {
- let dx1: f32 = x1 - x2;
- let dx2: f32 = x3 - x2;
- let dy1: f32 = y1 - y2;
- let dy2: f32 = y3 - y2;
- let denominator: f32 = dx1 * dy2 - dx2 * dy1;
- let a13: f32 = (dx3 * dy2 - dx2 * dy3) / denominator;
- let a23: f32 = (dx1 * dy3 - dx3 * dy1) / denominator;
- return PerspectiveTransform::new(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0f);
- }
- }
-
- pub fn quadrilateral_to_square( x0: f32, y0: f32, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) -> PerspectiveTransform {
- // Here, the adjoint serves as the inverse:
- return ::square_to_quadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).build_adjoint();
- }
-
- fn build_adjoint(&self) -> PerspectiveTransform {
- // Adjoint is the transpose of the cofactor matrix:
- return PerspectiveTransform::new(self.a22 * self.a33 - self.a23 * self.a32, self.a23 * self.a31 - self.a21 * self.a33, self.a21 * self.a32 - self.a22 * self.a31, self.a13 * self.a32 - self.a12 * self.a33, self.a11 * self.a33 - self.a13 * self.a31, self.a12 * self.a31 - self.a11 * self.a32, self.a12 * self.a23 - self.a13 * self.a22, self.a13 * self.a21 - self.a11 * self.a23, self.a11 * self.a22 - self.a12 * self.a21);
- }
-
- fn times(&self, other: &PerspectiveTransform) -> PerspectiveTransform {
- return PerspectiveTransform::new(self.a11 * other.a11 + self.a21 * other.a12 + self.a31 * other.a13, self.a11 * other.a21 + self.a21 * other.a22 + self.a31 * other.a23, self.a11 * other.a31 + self.a21 * other.a32 + self.a31 * other.a33, self.a12 * other.a11 + self.a22 * other.a12 + self.a32 * other.a13, self.a12 * other.a21 + self.a22 * other.a22 + self.a32 * other.a23, self.a12 * other.a31 + self.a22 * other.a32 + self.a32 * other.a33, self.a13 * other.a11 + self.a23 * other.a12 + self.a33 * other.a13, self.a13 * other.a21 + self.a23 * other.a22 + self.a33 * other.a23, self.a13 * other.a31 + self.a23 * other.a32 + self.a33 * other.a33);
- }
-}
-
diff --git a/port_src/output/zxing/common/reedsolomon/generic_g_f.rs b/port_src/output/zxing/common/reedsolomon/generic_g_f.rs
deleted file mode 100644
index 28ff8d8..0000000
--- a/port_src/output/zxing/common/reedsolomon/generic_g_f.rs
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common::reedsolomon;
-
-/**
- * This class contains utility methods for performing mathematical operations over
- * the Galois Fields. Operations use a given primitive polynomial in calculations.
- *
- * Throughout this package, elements of the GF are represented as an {@code int}
- * for convenience and speed (but at the cost of memory).
- *
- *
- * @author Sean Owen
- * @author David Olivier
- */
-
-// x^12 + x^6 + x^5 + x^3 + 1
- const AZTEC_DATA_12: GenericGF = GenericGF::new(0x1069, 4096, 1);
-
-// x^10 + x^3 + 1
- const AZTEC_DATA_10: GenericGF = GenericGF::new(0x409, 1024, 1);
-
-// x^6 + x + 1
- const AZTEC_DATA_6: GenericGF = GenericGF::new(0x43, 64, 1);
-
-// x^4 + x + 1
- const AZTEC_PARAM: GenericGF = GenericGF::new(0x13, 16, 1);
-
-// x^8 + x^4 + x^3 + x^2 + 1
- const QR_CODE_FIELD_256: GenericGF = GenericGF::new(0x011D, 256, 0);
-
-// x^8 + x^5 + x^3 + x^2 + 1
- const DATA_MATRIX_FIELD_256: GenericGF = GenericGF::new(0x012D, 256, 1);
-
- const AZTEC_DATA_8: GenericGF = DATA_MATRIX_FIELD_256;
-
- const MAXICODE_FIELD_64: GenericGF = AZTEC_DATA_6;
-pub struct GenericGF {
-
- let exp_table: Vec;
-
- let log_table: Vec;
-
- let mut zero: GenericGFPoly;
-
- let mut one: GenericGFPoly;
-
- let size: i32;
-
- let primitive: i32;
-
- let generator_base: i32;
-}
-
-impl GenericGF {
-
- /**
- * Create a representation of GF(size) using the given primitive polynomial.
- *
- * @param primitive irreducible polynomial whose coefficients are represented by
- * the bits of an int, where the least-significant bit represents the constant
- * coefficient
- * @param size the size of the field
- * @param b the factor b in the generator polynomial can be 0- or 1-based
- * (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).
- * In most cases it should be 1, but for QR code it is 0.
- */
- pub fn new( primitive: i32, size: i32, b: i32) -> GenericGF {
- let .primitive = primitive;
- let .size = size;
- let .generatorBase = b;
- exp_table = : [i32; size] = [0; size];
- log_table = : [i32; size] = [0; size];
- let mut x: i32 = 1;
- {
- let mut i: i32 = 0;
- while i < size {
- {
- exp_table[i] = x;
- // we're assuming the generator alpha is 2
- x *= 2;
- if x >= size {
- x ^= primitive;
- x &= size - 1;
- }
- }
- i += 1;
- }
- }
-
- {
- let mut i: i32 = 0;
- while i < size - 1 {
- {
- log_table[exp_table[i]] = i;
- }
- i += 1;
- }
- }
-
- // logTable[0] == 0 but this should never be used
- zero = GenericGFPoly::new(let , : vec![i32; 1] = vec![0, ]
- );
- one = GenericGFPoly::new(let , : vec![i32; 1] = vec![1, ]
- );
- }
-
- fn get_zero(&self) -> GenericGFPoly {
- return self.zero;
- }
-
- fn get_one(&self) -> GenericGFPoly {
- return self.one;
- }
-
- /**
- * @return the monomial representing coefficient * x^degree
- */
- fn build_monomial(&self, degree: i32, coefficient: i32) -> GenericGFPoly {
- if degree < 0 {
- throw IllegalArgumentException::new();
- }
- if coefficient == 0 {
- return self.zero;
- }
- let mut coefficients: [i32; degree + 1] = [0; degree + 1];
- coefficients[0] = coefficient;
- return GenericGFPoly::new(self, &coefficients);
- }
-
- /**
- * Implements both addition and subtraction -- they are the same in GF(size).
- *
- * @return sum/difference of a and b
- */
- fn add_or_subtract( a: i32, b: i32) -> i32 {
- return a ^ b;
- }
-
- /**
- * @return 2 to the power of a in GF(size)
- */
- fn exp(&self, a: i32) -> i32 {
- return self.exp_table[a];
- }
-
- /**
- * @return base 2 log of a in GF(size)
- */
- fn log(&self, a: i32) -> i32 {
- if a == 0 {
- throw IllegalArgumentException::new();
- }
- return self.log_table[a];
- }
-
- /**
- * @return multiplicative inverse of a
- */
- fn inverse(&self, a: i32) -> i32 {
- if a == 0 {
- throw ArithmeticException::new();
- }
- return self.exp_table[self.size - self.log_table[a] - 1];
- }
-
- /**
- * @return product of a and b in GF(size)
- */
- fn multiply(&self, a: i32, b: i32) -> i32 {
- if a == 0 || b == 0 {
- return 0;
- }
- return self.exp_table[(self.log_table[a] + self.log_table[b]) % (self.size - 1)];
- }
-
- pub fn get_size(&self) -> i32 {
- return self.size;
- }
-
- pub fn get_generator_base(&self) -> i32 {
- return self.generator_base;
- }
-
- pub fn to_string(&self) -> String {
- return format!("GF(0x{},{})", Integer::to_hex_string(self.primitive), self.size);
- }
-}
-
diff --git a/port_src/output/zxing/common/reedsolomon/generic_g_f_poly.rs b/port_src/output/zxing/common/reedsolomon/generic_g_f_poly.rs
deleted file mode 100644
index 7a7f76d..0000000
--- a/port_src/output/zxing/common/reedsolomon/generic_g_f_poly.rs
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common::reedsolomon;
-
-/**
- * Represents a polynomial whose coefficients are elements of a GF.
- * Instances of this class are immutable.
- *
- * Much credit is due to William Rucklidge since portions of this code are an indirect
- * port of his C++ Reed-Solomon implementation.
- *
- * @author Sean Owen
- */
-struct GenericGFPoly {
-
- let field: GenericGF;
-
- let coefficients: Vec;
-}
-
-impl GenericGFPoly {
-
- /**
- * @param field the {@link GenericGF} instance representing the field to use
- * to perform computations
- * @param coefficients coefficients as ints representing elements of GF(size), arranged
- * from most significant (highest-power term) coefficient to least significant
- * @throws IllegalArgumentException if argument is null or empty,
- * or if leading coefficient is 0 and this is not a
- * constant polynomial (that is, it is not the monomial "0")
- */
- fn new( field: &GenericGF, coefficients: &Vec) -> GenericGFPoly {
- if coefficients.len() == 0 {
- throw IllegalArgumentException::new();
- }
- let .field = field;
- let coefficients_length: i32 = coefficients.len();
- if coefficients_length > 1 && coefficients[0] == 0 {
- // Leading term must be non-zero for anything except the constant polynomial "0"
- let first_non_zero: i32 = 1;
- while first_non_zero < coefficients_length && coefficients[first_non_zero] == 0 {
- first_non_zero += 1;
- }
- if first_non_zero == coefficients_length {
- let .coefficients = : vec![i32; 1] = vec![0, ]
- ;
- } else {
- let .coefficients = : [i32; coefficients_length - first_non_zero] = [0; coefficients_length - first_non_zero];
- System::arraycopy(&coefficients, first_non_zero, let .coefficients, 0, let .coefficients.len());
- }
- } else {
- let .coefficients = coefficients;
- }
- }
-
- fn get_coefficients(&self) -> Vec {
- return self.coefficients;
- }
-
- /**
- * @return degree of this polynomial
- */
- fn get_degree(&self) -> i32 {
- return self.coefficients.len() - 1;
- }
-
- /**
- * @return true iff this polynomial is the monomial "0"
- */
- fn is_zero(&self) -> bool {
- return self.coefficients[0] == 0;
- }
-
- /**
- * @return coefficient of x^degree term in this polynomial
- */
- fn get_coefficient(&self, degree: i32) -> i32 {
- return self.coefficients[self.coefficients.len() - 1 - degree];
- }
-
- /**
- * @return evaluation of this polynomial at a given point
- */
- fn evaluate_at(&self, a: i32) -> i32 {
- if a == 0 {
- // Just return the x^0 coefficient
- return self.get_coefficient(0);
- }
- if a == 1 {
- // Just the sum of the coefficients
- let mut result: i32 = 0;
- for let coefficient: i32 in self.coefficients {
- result = GenericGF::add_or_subtract(result, coefficient);
- }
- return result;
- }
- let mut result: i32 = self.coefficients[0];
- let size: i32 = self.coefficients.len();
- {
- let mut i: i32 = 1;
- while i < size {
- {
- result = GenericGF::add_or_subtract(&self.field.multiply(a, result), self.coefficients[i]);
- }
- i += 1;
- }
- }
-
- return result;
- }
-
- fn add_or_subtract(&self, other: &GenericGFPoly) -> GenericGFPoly {
- if !self.field.equals(other.field) {
- throw IllegalArgumentException::new("GenericGFPolys do not have same GenericGF field");
- }
- if self.is_zero() {
- return other;
- }
- if other.is_zero() {
- return self;
- }
- let smaller_coefficients: Vec = self.coefficients;
- let larger_coefficients: Vec = other.coefficients;
- if smaller_coefficients.len() > larger_coefficients.len() {
- let temp: Vec = smaller_coefficients;
- smaller_coefficients = larger_coefficients;
- larger_coefficients = temp;
- }
- let sum_diff: [i32; larger_coefficients.len()] = [0; larger_coefficients.len()];
- let length_diff: i32 = larger_coefficients.len() - smaller_coefficients.len();
- // Copy high-order terms only found in higher-degree polynomial's coefficients
- System::arraycopy(&larger_coefficients, 0, &sum_diff, 0, length_diff);
- {
- let mut i: i32 = length_diff;
- while i < larger_coefficients.len() {
- {
- sum_diff[i] = GenericGF::add_or_subtract(smaller_coefficients[i - length_diff], larger_coefficients[i]);
- }
- i += 1;
- }
- }
-
- return GenericGFPoly::new(self.field, &sum_diff);
- }
-
- fn multiply(&self, other: &GenericGFPoly) -> GenericGFPoly {
- if !self.field.equals(other.field) {
- throw IllegalArgumentException::new("GenericGFPolys do not have same GenericGF field");
- }
- if self.is_zero() || other.is_zero() {
- return self.field.get_zero();
- }
- let a_coefficients: Vec = self.coefficients;
- let a_length: i32 = a_coefficients.len();
- let b_coefficients: Vec = other.coefficients;
- let b_length: i32 = b_coefficients.len();
- let mut product: [i32; a_length + b_length - 1] = [0; a_length + b_length - 1];
- {
- let mut i: i32 = 0;
- while i < a_length {
- {
- let a_coeff: i32 = a_coefficients[i];
- {
- let mut j: i32 = 0;
- while j < b_length {
- {
- product[i + j] = GenericGF::add_or_subtract(product[i + j], &self.field.multiply(a_coeff, b_coefficients[j]));
- }
- j += 1;
- }
- }
-
- }
- i += 1;
- }
- }
-
- return GenericGFPoly::new(self.field, &product);
- }
-
- fn multiply(&self, scalar: i32) -> GenericGFPoly {
- if scalar == 0 {
- return self.field.get_zero();
- }
- if scalar == 1 {
- return self;
- }
- let size: i32 = self.coefficients.len();
- let mut product: [i32; size] = [0; size];
- {
- let mut i: i32 = 0;
- while i < size {
- {
- product[i] = self.field.multiply(self.coefficients[i], scalar);
- }
- i += 1;
- }
- }
-
- return GenericGFPoly::new(self.field, &product);
- }
-
- fn multiply_by_monomial(&self, degree: i32, coefficient: i32) -> GenericGFPoly {
- if degree < 0 {
- throw IllegalArgumentException::new();
- }
- if coefficient == 0 {
- return self.field.get_zero();
- }
- let size: i32 = self.coefficients.len();
- let mut product: [i32; size + degree] = [0; size + degree];
- {
- let mut i: i32 = 0;
- while i < size {
- {
- product[i] = self.field.multiply(self.coefficients[i], coefficient);
- }
- i += 1;
- }
- }
-
- return GenericGFPoly::new(self.field, &product);
- }
-
- fn divide(&self, other: &GenericGFPoly) -> Vec {
- if !self.field.equals(other.field) {
- throw IllegalArgumentException::new("GenericGFPolys do not have same GenericGF field");
- }
- if other.is_zero() {
- throw IllegalArgumentException::new("Divide by 0");
- }
- let mut quotient: GenericGFPoly = self.field.get_zero();
- let mut remainder: GenericGFPoly = self;
- let denominator_leading_term: i32 = other.get_coefficient(&other.get_degree());
- let inverse_denominator_leading_term: i32 = self.field.inverse(denominator_leading_term);
- while remainder.get_degree() >= other.get_degree() && !remainder.is_zero() {
- let degree_difference: i32 = remainder.get_degree() - other.get_degree();
- let scale: i32 = self.field.multiply(&remainder.get_coefficient(&remainder.get_degree()), inverse_denominator_leading_term);
- let term: GenericGFPoly = other.multiply_by_monomial(degree_difference, scale);
- let iteration_quotient: GenericGFPoly = self.field.build_monomial(degree_difference, scale);
- quotient = quotient.add_or_subtract(iteration_quotient);
- remainder = remainder.add_or_subtract(term);
- }
- return : vec![GenericGFPoly; 2] = vec![quotient, remainder, ]
- ;
- }
-
- pub fn to_string(&self) -> String {
- if self.is_zero() {
- return "0";
- }
- let result: StringBuilder = StringBuilder::new(8 * self.get_degree());
- {
- let mut degree: i32 = self.get_degree();
- while degree >= 0 {
- {
- let mut coefficient: i32 = self.get_coefficient(degree);
- if coefficient != 0 {
- if coefficient < 0 {
- if degree == self.get_degree() {
- result.append("-");
- } else {
- result.append(" - ");
- }
- coefficient = -coefficient;
- } else {
- if result.length() > 0 {
- result.append(" + ");
- }
- }
- if degree == 0 || coefficient != 1 {
- let alpha_power: i32 = self.field.log(coefficient);
- if alpha_power == 0 {
- result.append('1');
- } else if alpha_power == 1 {
- result.append('a');
- } else {
- result.append("a^");
- result.append(alpha_power);
- }
- }
- if degree != 0 {
- if degree == 1 {
- result.append('x');
- } else {
- result.append("x^");
- result.append(degree);
- }
- }
- }
- }
- degree -= 1;
- }
- }
-
- return result.to_string();
- }
-}
-
diff --git a/port_src/output/zxing/common/reedsolomon/reed_solomon_decoder.rs b/port_src/output/zxing/common/reedsolomon/reed_solomon_decoder.rs
deleted file mode 100644
index e8152ce..0000000
--- a/port_src/output/zxing/common/reedsolomon/reed_solomon_decoder.rs
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common::reedsolomon;
-
-/**
- * Implements Reed-Solomon decoding, as the name implies.
- *
- * The algorithm will not be explained here, but the following references were helpful
- * in creating this implementation:
- *
- *
- *
- * Much credit is due to William Rucklidge since portions of this code are an indirect
- * port of his C++ Reed-Solomon implementation.
- *
- * @author Sean Owen
- * @author William Rucklidge
- * @author sanfordsquires
- */
-pub struct ReedSolomonDecoder {
-
- let field: GenericGF;
-}
-
-impl ReedSolomonDecoder {
-
- pub fn new( field: &GenericGF) -> ReedSolomonDecoder {
- let .field = field;
- }
-
- /**
- * Decodes given set of received codewords, which include both data and error-correction
- * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,
- * in the input.
- *
- * @param received data and error-correction codewords
- * @param twoS number of error-correction codewords available
- * @throws ReedSolomonException if decoding fails for any reason
- */
- pub fn decode(&self, received: &Vec, two_s: i32) -> /* throws ReedSolomonException */Result> {
- let poly: GenericGFPoly = GenericGFPoly::new(self.field, &received);
- let syndrome_coefficients: [i32; two_s] = [0; two_s];
- let no_error: bool = true;
- {
- let mut i: i32 = 0;
- while i < two_s {
- {
- let eval: i32 = poly.evaluate_at(&self.field.exp(i + self.field.get_generator_base()));
- syndrome_coefficients[syndrome_coefficients.len() - 1 - i] = eval;
- if eval != 0 {
- no_error = false;
- }
- }
- i += 1;
- }
- }
-
- if no_error {
- return;
- }
- let syndrome: GenericGFPoly = GenericGFPoly::new(self.field, &syndrome_coefficients);
- let sigma_omega: Vec = self.run_euclidean_algorithm(&self.field.build_monomial(two_s, 1), syndrome, two_s);
- let sigma: GenericGFPoly = sigma_omega[0];
- let omega: GenericGFPoly = sigma_omega[1];
- let error_locations: Vec = self.find_error_locations(sigma);
- let error_magnitudes: Vec = self.find_error_magnitudes(omega, &error_locations);
- {
- let mut i: i32 = 0;
- while i < error_locations.len() {
- {
- let mut position: i32 = received.len() - 1 - self.field.log(error_locations[i]);
- if position < 0 {
- throw ReedSolomonException::new("Bad error location");
- }
- received[position] = GenericGF::add_or_subtract(received[position], error_magnitudes[i]);
- }
- i += 1;
- }
- }
-
- }
-
- fn run_euclidean_algorithm(&self, a: &GenericGFPoly, b: &GenericGFPoly, R: i32) -> /* throws ReedSolomonException */Result, Rc> {
- // Assume a's degree is >= b's
- if a.get_degree() < b.get_degree() {
- let temp: GenericGFPoly = a;
- a = b;
- b = temp;
- }
- let r_last: GenericGFPoly = a;
- let mut r: GenericGFPoly = b;
- let t_last: GenericGFPoly = self.field.get_zero();
- let mut t: GenericGFPoly = self.field.get_one();
- // Run Euclidean algorithm until r's degree is less than R/2
- while 2 * r.get_degree() >= R {
- let r_last_last: GenericGFPoly = r_last;
- let t_last_last: GenericGFPoly = t_last;
- r_last = r;
- t_last = t;
- // Divide rLastLast by rLast, with quotient in q and remainder in r
- if r_last.is_zero() {
- // Oops, Euclidean algorithm already terminated?
- throw ReedSolomonException::new("r_{i-1} was zero");
- }
- r = r_last_last;
- let mut q: GenericGFPoly = self.field.get_zero();
- let denominator_leading_term: i32 = r_last.get_coefficient(&r_last.get_degree());
- let dlt_inverse: i32 = self.field.inverse(denominator_leading_term);
- while r.get_degree() >= r_last.get_degree() && !r.is_zero() {
- let degree_diff: i32 = r.get_degree() - r_last.get_degree();
- let scale: i32 = self.field.multiply(&r.get_coefficient(&r.get_degree()), dlt_inverse);
- q = q.add_or_subtract(&self.field.build_monomial(degree_diff, scale));
- r = r.add_or_subtract(&r_last.multiply_by_monomial(degree_diff, scale));
- }
- t = q.multiply(t_last).add_or_subtract(t_last_last);
- if r.get_degree() >= r_last.get_degree() {
- throw IllegalStateException::new(format!("Division algorithm failed to reduce polynomial? r: {}, rLast: {}", r, r_last));
- }
- }
- let sigma_tilde_at_zero: i32 = t.get_coefficient(0);
- if sigma_tilde_at_zero == 0 {
- throw ReedSolomonException::new("sigmaTilde(0) was zero");
- }
- let inverse: i32 = self.field.inverse(sigma_tilde_at_zero);
- let sigma: GenericGFPoly = t.multiply(inverse);
- let omega: GenericGFPoly = r.multiply(inverse);
- return Ok( : vec![GenericGFPoly; 2] = vec![sigma, omega, ]
- );
- }
-
- fn find_error_locations(&self, error_locator: &GenericGFPoly) -> /* throws ReedSolomonException */Result, Rc> {
- // This is a direct application of Chien's search
- let num_errors: i32 = error_locator.get_degree();
- if num_errors == 1 {
- // shortcut
- return Ok( : vec![i32; 1] = vec![error_locator.get_coefficient(1), ]
- );
- }
- let mut result: [i32; num_errors] = [0; num_errors];
- let mut e: i32 = 0;
- {
- let mut i: i32 = 1;
- while i < self.field.get_size() && e < num_errors {
- {
- if error_locator.evaluate_at(i) == 0 {
- result[e] = self.field.inverse(i);
- e += 1;
- }
- }
- i += 1;
- }
- }
-
- if e != num_errors {
- throw ReedSolomonException::new("Error locator degree does not match number of roots");
- }
- return Ok(result);
- }
-
- fn find_error_magnitudes(&self, error_evaluator: &GenericGFPoly, error_locations: &Vec) -> Vec {
- // This is directly applying Forney's Formula
- let s: i32 = error_locations.len();
- let mut result: [i32; s] = [0; s];
- {
- let mut i: i32 = 0;
- while i < s {
- {
- let xi_inverse: i32 = self.field.inverse(error_locations[i]);
- let mut denominator: i32 = 1;
- {
- let mut j: i32 = 0;
- while j < s {
- {
- if i != j {
- //denominator = field.multiply(denominator,
- // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)));
- // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.
- // Below is a funny-looking workaround from Steven Parkes
- let term: i32 = self.field.multiply(error_locations[j], xi_inverse);
- let term_plus1: i32 = if (term & 0x1) == 0 { term | 1 } else { term & ~1 };
- denominator = self.field.multiply(denominator, term_plus1);
- }
- }
- j += 1;
- }
- }
-
- result[i] = self.field.multiply(&error_evaluator.evaluate_at(xi_inverse), &self.field.inverse(denominator));
- if self.field.get_generator_base() != 0 {
- result[i] = self.field.multiply(result[i], xi_inverse);
- }
- }
- i += 1;
- }
- }
-
- return result;
- }
-}
-
diff --git a/port_src/output/zxing/common/reedsolomon/reed_solomon_encoder.rs b/port_src/output/zxing/common/reedsolomon/reed_solomon_encoder.rs
deleted file mode 100644
index c24096a..0000000
--- a/port_src/output/zxing/common/reedsolomon/reed_solomon_encoder.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common::reedsolomon;
-
-/**
- * Implements Reed-Solomon encoding, as the name implies.
- *
- * @author Sean Owen
- * @author William Rucklidge
- */
-pub struct ReedSolomonEncoder {
-
- let field: GenericGF;
-
- let cached_generators: List;
-}
-
-impl ReedSolomonEncoder {
-
- pub fn new( field: &GenericGF) -> ReedSolomonEncoder {
- let .field = field;
- let .cachedGenerators = ArrayList<>::new();
- cached_generators.add(GenericGFPoly::new(field, : vec![i32; 1] = vec![1, ]
- ));
- }
-
- fn build_generator(&self, degree: i32) -> GenericGFPoly {
- if degree >= self.cached_generators.size() {
- let last_generator: GenericGFPoly = self.cached_generators.get(self.cached_generators.size() - 1);
- {
- let mut d: i32 = self.cached_generators.size();
- while d <= degree {
- {
- let next_generator: GenericGFPoly = last_generator.multiply(GenericGFPoly::new(self.field, : vec![i32; 2] = vec![1, self.field.exp(d - 1 + self.field.get_generator_base()), ]
- ));
- self.cached_generators.add(next_generator);
- last_generator = next_generator;
- }
- d += 1;
- }
- }
-
- }
- return self.cached_generators.get(degree);
- }
-
- pub fn encode(&self, to_encode: &Vec, ec_bytes: i32) {
- if ec_bytes == 0 {
- throw IllegalArgumentException::new("No error correction bytes");
- }
- let data_bytes: i32 = to_encode.len() - ec_bytes;
- if data_bytes <= 0 {
- throw IllegalArgumentException::new("No data bytes provided");
- }
- let generator: GenericGFPoly = self.build_generator(ec_bytes);
- let info_coefficients: [i32; data_bytes] = [0; data_bytes];
- System::arraycopy(&to_encode, 0, &info_coefficients, 0, data_bytes);
- let mut info: GenericGFPoly = GenericGFPoly::new(self.field, &info_coefficients);
- info = info.multiply_by_monomial(ec_bytes, 1);
- let remainder: GenericGFPoly = info.divide(generator)[1];
- let coefficients: Vec = remainder.get_coefficients();
- let num_zero_coefficients: i32 = ec_bytes - coefficients.len();
- {
- let mut i: i32 = 0;
- while i < num_zero_coefficients {
- {
- to_encode[data_bytes + i] = 0;
- }
- i += 1;
- }
- }
-
- System::arraycopy(&coefficients, 0, &to_encode, data_bytes + num_zero_coefficients, coefficients.len());
- }
-}
-
diff --git a/port_src/output/zxing/common/reedsolomon/reed_solomon_exception.rs b/port_src/output/zxing/common/reedsolomon/reed_solomon_exception.rs
deleted file mode 100644
index c2f56b8..0000000
--- a/port_src/output/zxing/common/reedsolomon/reed_solomon_exception.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common::reedsolomon;
-
-/**
- * Thrown when an exception occurs during Reed-Solomon decoding, such as when
- * there are too many errors to correct.
- *
- * @author Sean Owen
- */
-pub struct ReedSolomonException {
- super: Exception;
-}
-
-impl ReedSolomonException {
-
- pub fn new( message: &String) -> ReedSolomonException {
- super(&message);
- }
-}
-
diff --git a/port_src/output/zxing/common/string_utils.rs b/port_src/output/zxing/common/string_utils.rs
deleted file mode 100644
index 7a1f1cf..0000000
--- a/port_src/output/zxing/common/string_utils.rs
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2010 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// package com::google::zxing::common;
-
-/**
- * Common string-related functions.
- *
- * @author Sean Owen
- * @author Alex Dupre
- */
-
- const PLATFORM_DEFAULT_ENCODING: Charset = Charset::default_charset();
-
- const SHIFT_JIS_CHARSET: Charset = Charset::for_name("SJIS");
-
- const GB2312_CHARSET: Charset = Charset::for_name("GB2312");
-
- const EUC_JP: Charset = Charset::for_name("EUC_JP");
-
- const ASSUME_SHIFT_JIS: bool = SHIFT_JIS_CHARSET::equals(&PLATFORM_DEFAULT_ENCODING) || EUC_JP::equals(&PLATFORM_DEFAULT_ENCODING);
-
-// Retained for ABI compatibility with earlier versions
- const SHIFT_JIS: &'static str = "SJIS";
-
- const GB2312: &'static str = "GB2312";
-pub struct StringUtils {
-}
-
-impl StringUtils {
-
- fn new() -> StringUtils {
- }
-
- /**
- * @param bytes bytes encoding a string, whose encoding should be guessed
- * @param hints decode hints if applicable
- * @return name of guessed encoding; at the moment will only guess one of:
- * "SJIS", "UTF8", "ISO8859_1", or the platform default encoding if none
- * of these can possibly be correct
- */
- pub fn guess_encoding( bytes: &Vec, hints: &Map) -> String {
- let c: Charset = ::guess_charset(&bytes, &hints);
- if c == SHIFT_JIS_CHARSET {
- return "SJIS";
- } else if c == StandardCharsets::UTF_8 {
- return "UTF8";
- } else if c == StandardCharsets::ISO_8859_1 {
- return "ISO8859_1";
- }
- return c.name();
- }
-
- /**
- * @param bytes bytes encoding a string, whose encoding should be guessed
- * @param hints decode hints if applicable
- * @return Charset of guessed encoding; at the moment will only guess one of:
- * {@link #SHIFT_JIS_CHARSET}, {@link StandardCharsets#UTF_8},
- * {@link StandardCharsets#ISO_8859_1}, {@link StandardCharsets#UTF_16},
- * or the platform default encoding if
- * none of these can possibly be correct
- */
- pub fn guess_charset( bytes: &Vec, hints: &Map) -> Charset {
- if hints != null && hints.contains_key(DecodeHintType::CHARACTER_SET) {
- return Charset::for_name(&hints.get(DecodeHintType::CHARACTER_SET).to_string());
- }
- // First try UTF-16, assuming anything with its BOM is UTF-16
- if bytes.len() > 2 && ((bytes[0] == 0xFE as i8 && bytes[1] == 0xFF as i8) || (bytes[0] == 0xFF as i8 && bytes[1] == 0xFE as i8)) {
- return StandardCharsets::UTF_16;
- }
- // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS,
- // which should be by far the most common encodings.
- let length: i32 = bytes.len();
- let can_be_i_s_o88591: bool = true;
- let can_be_shift_j_i_s: bool = true;
- let can_be_u_t_f8: bool = true;
- let utf8_bytes_left: i32 = 0;
- let utf2_bytes_chars: i32 = 0;
- let utf3_bytes_chars: i32 = 0;
- let utf4_bytes_chars: i32 = 0;
- let sjis_bytes_left: i32 = 0;
- let sjis_katakana_chars: i32 = 0;
- let sjis_cur_katakana_word_length: i32 = 0;
- let sjis_cur_double_bytes_word_length: i32 = 0;
- let sjis_max_katakana_word_length: i32 = 0;
- let sjis_max_double_bytes_word_length: i32 = 0;
- let iso_high_other: i32 = 0;
- let utf8bom: bool = bytes.len() > 3 && bytes[0] == 0xEF as i8 && bytes[1] == 0xBB as i8 && bytes[2] == 0xBF as i8;
- {
- let mut i: i32 = 0;
- while i < length && (can_be_i_s_o88591 || can_be_shift_j_i_s || can_be_u_t_f8) {
- {
- let value: i32 = bytes[i] & 0xFF;
- // UTF-8 stuff
- if can_be_u_t_f8 {
- if utf8_bytes_left > 0 {
- if (value & 0x80) == 0 {
- can_be_u_t_f8 = false;
- } else {
- utf8_bytes_left -= 1;
- }
- } else if (value & 0x80) != 0 {
- if (value & 0x40) == 0 {
- can_be_u_t_f8 = false;
- } else {
- utf8_bytes_left += 1;
- if (value & 0x20) == 0 {
- utf2_bytes_chars += 1;
- } else {
- utf8_bytes_left += 1;
- if (value & 0x10) == 0 {
- utf3_bytes_chars += 1;
- } else {
- utf8_bytes_left += 1;
- if (value & 0x08) == 0 {
- utf4_bytes_chars += 1;
- } else {
- can_be_u_t_f8 = false;
- }
- }
- }
- }
- }
- }
- // ISO-8859-1 stuff
- if can_be_i_s_o88591 {
- if value > 0x7F && value < 0xA0 {
- can_be_i_s_o88591 = false;
- } else if value > 0x9F && (value < 0xC0 || value == 0xD7 || value == 0xF7) {
- iso_high_other += 1;
- }
- }
- // Shift_JIS stuff
- if can_be_shift_j_i_s {
- if sjis_bytes_left > 0 {
- if value < 0x40 || value == 0x7F || value > 0xFC {
- can_be_shift_j_i_s = false;
- } else {
- sjis_bytes_left -= 1;
- }
- } else if value == 0x80 || value == 0xA0 || value > 0xEF {
- can_be_shift_j_i_s = false;
- } else if value > 0xA0 && value < 0xE0 {
- sjis_katakana_chars += 1;
- sjis_cur_double_bytes_word_length = 0;
- sjis_cur_katakana_word_length += 1;
- if sjis_cur_katakana_word_length > sjis_max_katakana_word_length {
- sjis_max_katakana_word_length = sjis_cur_katakana_word_length;
- }
- } else if value > 0x7F {
- sjis_bytes_left += 1;
- //sjisDoubleBytesChars++;
- sjis_cur_katakana_word_length = 0;
- sjis_cur_double_bytes_word_length += 1;
- if sjis_cur_double_bytes_word_length > sjis_max_double_bytes_word_length {
- sjis_max_double_bytes_word_length = sjis_cur_double_bytes_word_length;
- }
- } else {
- //sjisLowChars++;
- sjis_cur_katakana_word_length = 0;
- sjis_cur_double_bytes_word_length = 0;
- }
- }
- }
- i += 1;
- }
- }
-
- if can_be_u_t_f8 && utf8_bytes_left > 0 {
- can_be_u_t_f8 = false;
- }
- if can_be_shift_j_i_s && sjis_bytes_left > 0 {
- can_be_shift_j_i_s = false;
- }
- // Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done
- if can_be_u_t_f8 && (utf8bom || utf2_bytes_chars + utf3_bytes_chars + utf4_bytes_chars > 0) {
- return StandardCharsets::UTF_8;
- }
- // Easy -- if assuming Shift_JIS or >= 3 valid consecutive not-ascii characters (and no evidence it can't be), done
- if can_be_shift_j_i_s && (ASSUME_SHIFT_JIS || sjis_max_katakana_word_length >= 3 || sjis_max_double_bytes_word_length >= 3) {
- return SHIFT_JIS_CHARSET;
- }
- // - then we conclude Shift_JIS, else ISO-8859-1
- if can_be_i_s_o88591 && can_be_shift_j_i_s {
- return if (sjis_max_katakana_word_length == 2 && sjis_katakana_chars == 2) || iso_high_other * 10 >= length { SHIFT_JIS_CHARSET } else { StandardCharsets::ISO_8859_1 };
- }
- // Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding
- if can_be_i_s_o88591 {
- return StandardCharsets::ISO_8859_1;
- }
- if can_be_shift_j_i_s {
- return SHIFT_JIS_CHARSET;
- }
- if can_be_u_t_f8 {
- return StandardCharsets::UTF_8;
- }
- // Otherwise, we take a wild guess with platform encoding
- return PLATFORM_DEFAULT_ENCODING;
- }
-}
-
diff --git a/src/common.rs b/src/common.rs
index e69de29..61e745e 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -0,0 +1,3359 @@
+use crate::{Binarizer,LuminanceSource,NotFoundException,FormatException,NotFoundException,Binarizer,ResultPoint};
+
+// ECIInput.java
+/**
+ * Interface to navigate a sequence of ECIs and bytes.
+ *
+ * @author Alex Geller
+ */
+pub trait ECIInput {
+
+ /**
+ * Returns the length of this input. The length is the number
+ * of {@code byte}s in or ECIs in the sequence.
+ *
+ * @return the number of {@code char}s in this sequence
+ */
+ fn length(&self) -> i32 ;
+
+ /**
+ * Returns the {@code byte} value at the specified index. An index ranges from zero
+ * to {@code length() - 1}. The first {@code byte} value of the sequence is at
+ * index zero, the next at index one, and so on, as for array
+ * indexing.
+ *
+ * @param index the index of the {@code byte} value to be returned
+ *
+ * @return the specified {@code byte} value as character or the FNC1 character
+ *
+ * @throws IndexOutOfBoundsException
+ * if the {@code index} argument is negative or not less than
+ * {@code length()}
+ * @throws IllegalArgumentException
+ * if the value at the {@code index} argument is an ECI (@see #isECI)
+ */
+ fn char_at(&self, index: i32) -> char ;
+
+ /**
+ * Returns a {@code CharSequence} that is a subsequence of this sequence.
+ * The subsequence starts with the {@code char} value at the specified index and
+ * ends with the {@code char} value at index {@code end - 1}. The length
+ * (in {@code char}s) of the
+ * returned sequence is {@code end - start}, so if {@code start == end}
+ * then an empty sequence is returned.
+ *
+ * @param start the start index, inclusive
+ * @param end the end index, exclusive
+ *
+ * @return the specified subsequence
+ *
+ * @throws IndexOutOfBoundsException
+ * if {@code start} or {@code end} are negative,
+ * if {@code end} is greater than {@code length()},
+ * or if {@code start} is greater than {@code end}
+ * @throws IllegalArgumentException
+ * if a value in the range {@code start}-{@code end} is an ECI (@see #isECI)
+ */
+ fn sub_sequence(&self, start: i32, end: i32) -> CharSequence ;
+
+ /**
+ * Determines if a value is an ECI
+ *
+ * @param index the index of the value
+ *
+ * @return true if the value at position {@code index} is an ECI
+ *
+ * @throws IndexOutOfBoundsException
+ * if the {@code index} argument is negative or not less than
+ * {@code length()}
+ */
+ fn is_e_c_i(&self, index: i32) -> bool ;
+
+ /**
+ * Returns the {@code int} ECI value at the specified index. An index ranges from zero
+ * to {@code length() - 1}. The first {@code byte} value of the sequence is at
+ * index zero, the next at index one, and so on, as for array
+ * indexing.
+ *
+ * @param index the index of the {@code int} value to be returned
+ *
+ * @return the specified {@code int} ECI value.
+ * The ECI specified the encoding of all bytes with a higher index until the
+ * next ECI or until the end of the input if no other ECI follows.
+ *
+ * @throws IndexOutOfBoundsException
+ * if the {@code index} argument is negative or not less than
+ * {@code length()}
+ * @throws IllegalArgumentException
+ * if the value at the {@code index} argument is not an ECI (@see #isECI)
+ */
+ fn get_e_c_i_value(&self, index: i32) -> i32 ;
+
+ fn have_n_characters(&self, index: i32, n: i32) -> bool ;
+}
+
+// GridSampler.java
+
+/**
+ * Implementations of this class can, given locations of finder patterns for a QR code in an
+ * image, sample the right points in the image to reconstruct the QR code, accounting for
+ * perspective distortion. It is abstracted since it is relatively expensive and should be allowed
+ * to take advantage of platform-specific optimized implementations, like Sun's Java Advanced
+ * Imaging library, but which may not be available in other environments such as J2ME, and vice
+ * versa.
+ *
+ * The implementation used can be controlled by calling {@link #setGridSampler(GridSampler)}
+ * with an instance of a class which implements this interface.
+ *
+ * @author Sean Owen
+ */
+
+let grid_sampler: GridSampler = DefaultGridSampler::new();
+pub struct GridSampler {
+}
+
+impl GridSampler {
+
+ /**
+ * Sets the implementation of GridSampler used by the library. One global
+ * instance is stored, which may sound problematic. But, the implementation provided
+ * ought to be appropriate for the entire platform, and all uses of this library
+ * in the whole lifetime of the JVM. For instance, an Android activity can swap in
+ * an implementation that takes advantage of native platform libraries.
+ *
+ * @param newGridSampler The platform-specific object to install.
+ */
+ pub fn set_grid_sampler( new_grid_sampler: &GridSampler) {
+ grid_sampler = new_grid_sampler;
+ }
+
+ /**
+ * @return the current implementation of GridSampler
+ */
+ pub fn get_instance() -> GridSampler {
+ return grid_sampler;
+ }
+
+ /**
+ * Samples an image for a rectangular matrix of bits of the given dimension. The sampling
+ * transformation is determined by the coordinates of 4 points, in the original and transformed
+ * image space.
+ *
+ * @param image image to sample
+ * @param dimensionX width of {@link BitMatrix} to sample from image
+ * @param dimensionY height of {@link BitMatrix} to sample from image
+ * @param p1ToX point 1 preimage X
+ * @param p1ToY point 1 preimage Y
+ * @param p2ToX point 2 preimage X
+ * @param p2ToY point 2 preimage Y
+ * @param p3ToX point 3 preimage X
+ * @param p3ToY point 3 preimage Y
+ * @param p4ToX point 4 preimage X
+ * @param p4ToY point 4 preimage Y
+ * @param p1FromX point 1 image X
+ * @param p1FromY point 1 image Y
+ * @param p2FromX point 2 image X
+ * @param p2FromY point 2 image Y
+ * @param p3FromX point 3 image X
+ * @param p3FromY point 3 image Y
+ * @param p4FromX point 4 image X
+ * @param p4FromY point 4 image Y
+ * @return {@link BitMatrix} representing a grid of points sampled from the image within a region
+ * defined by the "from" parameters
+ * @throws NotFoundException if image can't be sampled, for example, if the transformation defined
+ * by the given points is invalid or results in sampling outside the image boundaries
+ */
+ pub fn sample_grid(&self, image: &BitMatrix, dimension_x: i32, dimension_y: i32, p1_to_x: f32, p1_to_y: f32, p2_to_x: f32, p2_to_y: f32, p3_to_x: f32, p3_to_y: f32, p4_to_x: f32, p4_to_y: f32, p1_from_x: f32, p1_from_y: f32, p2_from_x: f32, p2_from_y: f32, p3_from_x: f32, p3_from_y: f32, p4_from_x: f32, p4_from_y: f32) -> /* throws NotFoundException */Result> ;
+
+ pub fn sample_grid(&self, image: &BitMatrix, dimension_x: i32, dimension_y: i32, transform: &PerspectiveTransform) -> /* throws NotFoundException */Result> ;
+
+ /**
+ * Checks a set of points that have been transformed to sample points on an image against
+ * the image's dimensions to see if the point are even within the image.
+ *
+ * This method will actually "nudge" the endpoints back onto the image if they are found to be
+ * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder
+ * patterns in an image where the QR Code runs all the way to the image border.
+ *
+ * For efficiency, the method will check points from either end of the line until one is found
+ * to be within the image. Because the set of points are assumed to be linear, this is valid.
+ *
+ * @param image image into which the points should map
+ * @param points actual points in x1,y1,...,xn,yn form
+ * @throws NotFoundException if an endpoint is lies outside the image boundaries
+ */
+ pub fn check_and_nudge_points( image: &BitMatrix, points: &Vec) -> /* throws NotFoundException */Result> {
+ let width: i32 = image.get_width();
+ let height: i32 = image.get_height();
+ // Check and nudge points from start until we see some that are OK:
+ let mut nudged: bool = true;
+ // points.length must be even
+ let max_offset: i32 = points.len() - 1;
+ {
+ let mut offset: i32 = 0;
+ while offset < max_offset && nudged {
+ {
+ let x: i32 = points[offset] as i32;
+ let y: i32 = points[offset + 1] as i32;
+ if x < -1 || x > width || y < -1 || y > height {
+ throw NotFoundException::get_not_found_instance();
+ }
+ nudged = false;
+ if x == -1 {
+ points[offset] = 0.0f;
+ nudged = true;
+ } else if x == width {
+ points[offset] = width - 1.0;
+ nudged = true;
+ }
+ if y == -1 {
+ points[offset + 1] = 0.0f;
+ nudged = true;
+ } else if y == height {
+ points[offset + 1] = height - 1.0;
+ nudged = true;
+ }
+ }
+ offset += 2;
+ }
+ }
+
+ // Check and nudge points from end:
+ nudged = true;
+ {
+ let mut offset: i32 = points.len() - 2;
+ while offset >= 0 && nudged {
+ {
+ let x: i32 = points[offset] as i32;
+ let y: i32 = points[offset + 1] as i32;
+ if x < -1 || x > width || y < -1 || y > height {
+ throw NotFoundException::get_not_found_instance();
+ }
+ nudged = false;
+ if x == -1 {
+ points[offset] = 0.0f;
+ nudged = true;
+ } else if x == width {
+ points[offset] = width - 1.0;
+ nudged = true;
+ }
+ if y == -1 {
+ points[offset + 1] = 0.0f;
+ nudged = true;
+ } else if y == height {
+ points[offset + 1] = height - 1.0;
+ nudged = true;
+ }
+ }
+ offset -= 2;
+ }
+ }
+
+ }
+}
+
+// GlobalHistogramBinarizer.java
+/**
+ * This Binarizer implementation uses the old ZXing global histogram approach. It is suitable
+ * for low-end mobile devices which don't have enough CPU or memory to use a local thresholding
+ * algorithm. However, because it picks a global black point, it cannot handle difficult shadows
+ * and gradients.
+ *
+ * Faster mobile devices and all desktop applications should probably use HybridBinarizer instead.
+ *
+ * @author dswitkin@google.com (Daniel Switkin)
+ * @author Sean Owen
+ */
+
+const LUMINANCE_BITS: i32 = 5;
+
+const LUMINANCE_SHIFT: i32 = 8 - LUMINANCE_BITS;
+
+const LUMINANCE_BUCKETS: i32 = 1 << LUMINANCE_BITS;
+
+const EMPTY: [i8; 0] = [0; 0];
+pub struct GlobalHistogramBinarizer {
+ super: Binarizer;
+
+ let mut luminances: Vec;
+
+ let mut buckets: Vec;
+}
+
+impl Binarizer for GlobalHistogramBinarizer {
+ // Applies simple sharpening to the row data to improve performance of the 1D Readers.
+ pub fn get_black_row(&self, y: i32, row: &BitArray) -> /* throws NotFoundException */Result> {
+ let source: LuminanceSource = get_luminance_source();
+ let width: i32 = source.get_width();
+ if row == null || row.get_size() < width {
+ row = BitArray::new(width);
+ } else {
+ row.clear();
+ }
+ self.init_arrays(width);
+ let local_luminances: Vec = source.get_row(y, &self.luminances);
+ let local_buckets: Vec = self.buckets;
+ {
+ let mut x: i32 = 0;
+ while x < width {
+ {
+ local_buckets[(local_luminances[x] & 0xff) >> LUMINANCE_SHIFT] += 1;
+ }
+ x += 1;
+ }
+ }
+
+ let black_point: i32 = ::estimate_black_point(&local_buckets);
+ if width < 3 {
+ // Special case for very small images
+ {
+ let mut x: i32 = 0;
+ while x < width {
+ {
+ if (local_luminances[x] & 0xff) < black_point {
+ row.set(x);
+ }
+ }
+ x += 1;
+ }
+ }
+
+ } else {
+ let mut left: i32 = local_luminances[0] & 0xff;
+ let mut center: i32 = local_luminances[1] & 0xff;
+ {
+ let mut x: i32 = 1;
+ while x < width - 1 {
+ {
+ let right: i32 = local_luminances[x + 1] & 0xff;
+ // A simple -1 4 -1 box filter with a weight of 2.
+ if ((center * 4) - left - right) / 2 < black_point {
+ row.set(x);
+ }
+ left = center;
+ center = right;
+ }
+ x += 1;
+ }
+ }
+
+ }
+ return Ok(row);
+}
+
+// Does not sharpen the data, as this call is intended to only be used by 2D Readers.
+pub fn get_black_matrix(&self) -> /* throws NotFoundException */Result> {
+ let source: LuminanceSource = get_luminance_source();
+ let width: i32 = source.get_width();
+ let height: i32 = source.get_height();
+ let matrix: BitMatrix = BitMatrix::new(width, height);
+ // Quickly calculates the histogram by sampling four rows from the image. This proved to be
+ // more robust on the blackbox tests than sampling a diagonal as we used to do.
+ self.init_arrays(width);
+ let local_buckets: Vec = self.buckets;
+ {
+ let mut y: i32 = 1;
+ while y < 5 {
+ {
+ let row: i32 = height * y / 5;
+ let local_luminances: Vec = source.get_row(row, &self.luminances);
+ let right: i32 = (width * 4) / 5;
+ {
+ let mut x: i32 = width / 5;
+ while x < right {
+ {
+ let mut pixel: i32 = local_luminances[x] & 0xff;
+ local_buckets[pixel >> LUMINANCE_SHIFT] += 1;
+ }
+ x += 1;
+ }
+ }
+
+ }
+ y += 1;
+ }
+ }
+
+ let black_point: i32 = ::estimate_black_point(&local_buckets);
+ // We delay reading the entire image luminance until the black point estimation succeeds.
+ // Although we end up reading four rows twice, it is consistent with our motto of
+ // "fail quickly" which is necessary for continuous scanning.
+ let local_luminances: Vec = source.get_matrix();
+ {
+ let mut y: i32 = 0;
+ while y < height {
+ {
+ let offset: i32 = y * width;
+ {
+ let mut x: i32 = 0;
+ while x < width {
+ {
+ let pixel: i32 = local_luminances[offset + x] & 0xff;
+ if pixel < black_point {
+ matrix.set(x, y);
+ }
+ }
+ x += 1;
+ }
+ }
+
+ }
+ y += 1;
+ }
+ }
+
+ return Ok(matrix);
+}
+
+pub fn create_binarizer(&self, source: &LuminanceSource) -> Binarizer {
+ return GlobalHistogramBinarizer::new(source);
+}
+}
+
+impl GlobalHistogramBinarizer {
+
+ pub fn new( source: &LuminanceSource) -> GlobalHistogramBinarizer {
+ super(source);
+ luminances = EMPTY;
+ buckets = : [i32; LUMINANCE_BUCKETS] = [0; LUMINANCE_BUCKETS];
+ }
+
+ fn init_arrays(&self, luminance_size: i32) {
+ if self.luminances.len() < luminance_size {
+ self.luminances = : [i8; luminance_size] = [0; luminance_size];
+ }
+ {
+ let mut x: i32 = 0;
+ while x < LUMINANCE_BUCKETS {
+ {
+ self.buckets[x] = 0;
+ }
+ x += 1;
+ }
+ }
+
+ }
+
+ fn estimate_black_point( buckets: &Vec) -> /* throws NotFoundException */Result> {
+ // Find the tallest peak in the histogram.
+ let num_buckets: i32 = buckets.len();
+ let max_bucket_count: i32 = 0;
+ let first_peak: i32 = 0;
+ let first_peak_size: i32 = 0;
+ {
+ let mut x: i32 = 0;
+ while x < num_buckets {
+ {
+ if buckets[x] > first_peak_size {
+ first_peak = x;
+ first_peak_size = buckets[x];
+ }
+ if buckets[x] > max_bucket_count {
+ max_bucket_count = buckets[x];
+ }
+ }
+ x += 1;
+ }
+ }
+
+ // Find the second-tallest peak which is somewhat far from the tallest peak.
+ let second_peak: i32 = 0;
+ let second_peak_score: i32 = 0;
+ {
+ let mut x: i32 = 0;
+ while x < num_buckets {
+ {
+ let distance_to_biggest: i32 = x - first_peak;
+ // Encourage more distant second peaks by multiplying by square of distance.
+ let score: i32 = buckets[x] * distance_to_biggest * distance_to_biggest;
+ if score > second_peak_score {
+ second_peak = x;
+ second_peak_score = score;
+ }
+ }
+ x += 1;
+ }
+ }
+
+ // Make sure firstPeak corresponds to the black peak.
+ if first_peak > second_peak {
+ let temp: i32 = first_peak;
+ first_peak = second_peak;
+ second_peak = temp;
+ }
+ // than waste time trying to decode the image, and risk false positives.
+ if second_peak - first_peak <= num_buckets / 16 {
+ throw NotFoundException::get_not_found_instance();
+ }
+ // Find a valley between them that is low and closer to the white peak.
+ let best_valley: i32 = second_peak - 1;
+ let best_valley_score: i32 = -1;
+ {
+ let mut x: i32 = second_peak - 1;
+ while x > first_peak {
+ {
+ let from_first: i32 = x - first_peak;
+ let score: i32 = from_first * from_first * (second_peak - x) * (max_bucket_count - buckets[x]);
+ if score > best_valley_score {
+ best_valley = x;
+ best_valley_score = score;
+ }
+ }
+ x -= 1;
+ }
+ }
+
+ return Ok(best_valley << LUMINANCE_SHIFT);
+ }
+}
+
+// BitArray.java
+/**
+ * A simple, fast array of bits, represented compactly by an array of ints internally.
+ *
+ * @author Sean Owen
+ */
+
+const EMPTY_BITS;
+
+const LOAD_FACTOR: f32 = 0.75f;
+#[derive(Cloneable)]
+pub struct BitArray {
+
+ let mut bits: Vec;
+
+ let mut size: i32;
+}
+
+impl BitArray {
+
+ pub fn new() -> BitArray {
+ let .size = 0;
+ let .bits = EMPTY_BITS;
+ }
+
+ pub fn new( size: i32) -> BitArray {
+ let .size = size;
+ let .bits = ::make_array(size);
+ }
+
+ // For testing only
+ fn new( bits: &Vec, size: i32) -> BitArray {
+ let .bits = bits;
+ let .size = size;
+ }
+
+ pub fn get_size(&self) -> i32 {
+ return self.size;
+ }
+
+ pub fn get_size_in_bytes(&self) -> i32 {
+ return (self.size + 7) / 8;
+ }
+
+ fn ensure_capacity(&self, new_size: i32) {
+ if new_size > self.bits.len() * 32 {
+ let new_bits: Vec = ::make_array(Math::ceil(new_size / LOAD_FACTOR) as i32);
+ System::arraycopy(&self.bits, 0, &new_bits, 0, self.bits.len());
+ self.bits = new_bits;
+ }
+ }
+
+ /**
+ * @param i bit to get
+ * @return true iff bit i is set
+ */
+ pub fn get(&self, i: i32) -> bool {
+ return (self.bits[i / 32] & (1 << (i & 0x1F))) != 0;
+ }
+
+ /**
+ * Sets bit i.
+ *
+ * @param i bit to set
+ */
+ pub fn set(&self, i: i32) {
+ self.bits[i / 32] |= 1 << (i & 0x1F);
+ }
+
+ /**
+ * Flips bit i.
+ *
+ * @param i bit to set
+ */
+ pub fn flip(&self, i: i32) {
+ self.bits[i / 32] ^= 1 << (i & 0x1F);
+ }
+
+ /**
+ * @param from first bit to check
+ * @return index of first bit that is set, starting from the given index, or size if none are set
+ * at or beyond this given index
+ * @see #getNextUnset(int)
+ */
+ pub fn get_next_set(&self, from: i32) -> i32 {
+ if from >= self.size {
+ return self.size;
+ }
+ let bits_offset: i32 = from / 32;
+ let current_bits: i32 = self.bits[bits_offset];
+ // mask off lesser bits first
+ current_bits &= -(1 << (from & 0x1F));
+ while current_bits == 0 {
+ if bits_offset += 1 == self.bits.len() {
+ return self.size;
+ }
+ current_bits = self.bits[bits_offset];
+ }
+ let result: i32 = (bits_offset * 32) + Integer::number_of_trailing_zeros(current_bits);
+ return Math::min(result, self.size);
+ }
+
+ /**
+ * @param from index to start looking for unset bit
+ * @return index of next unset bit, or {@code size} if none are unset until the end
+ * @see #getNextSet(int)
+ */
+ pub fn get_next_unset(&self, from: i32) -> i32 {
+ if from >= self.size {
+ return self.size;
+ }
+ let bits_offset: i32 = from / 32;
+ let current_bits: i32 = ~self.bits[bits_offset];
+ // mask off lesser bits first
+ current_bits &= -(1 << (from & 0x1F));
+ while current_bits == 0 {
+ if bits_offset += 1 == self.bits.len() {
+ return self.size;
+ }
+ current_bits = ~self.bits[bits_offset];
+ }
+ let result: i32 = (bits_offset * 32) + Integer::number_of_trailing_zeros(current_bits);
+ return Math::min(result, self.size);
+ }
+
+ /**
+ * Sets a block of 32 bits, starting at bit i.
+ *
+ * @param i first bit to set
+ * @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.
+ */
+ pub fn set_bulk(&self, i: i32, new_bits: i32) {
+ self.bits[i / 32] = new_bits;
+ }
+
+ /**
+ * Sets a range of bits.
+ *
+ * @param start start of range, inclusive.
+ * @param end end of range, exclusive
+ */
+ pub fn set_range(&self, start: i32, end: i32) {
+ if end < start || start < 0 || end > self.size {
+ throw IllegalArgumentException::new();
+ }
+ if end == start {
+ return;
+ }
+ // will be easier to treat this as the last actually set bit -- inclusive
+ end -= 1;
+ let first_int: i32 = start / 32;
+ let last_int: i32 = end / 32;
+ {
+ let mut i: i32 = first_int;
+ while i <= last_int {
+ {
+ let first_bit: i32 = if i > first_int { 0 } else { start & 0x1F };
+ let last_bit: i32 = if i < last_int { 31 } else { end & 0x1F };
+ // Ones from firstBit to lastBit, inclusive
+ let mask: i32 = (2 << last_bit) - (1 << first_bit);
+ self.bits[i] |= mask;
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ /**
+ * Clears all bits (sets to false).
+ */
+ pub fn clear(&self) {
+ let max: i32 = self.bits.len();
+ {
+ let mut i: i32 = 0;
+ while i < max {
+ {
+ self.bits[i] = 0;
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ /**
+ * Efficient method to check if a range of bits is set, or not set.
+ *
+ * @param start start of range, inclusive.
+ * @param end end of range, exclusive
+ * @param value if true, checks that bits in range are set, otherwise checks that they are not set
+ * @return true iff all bits are set or not set in range, according to value argument
+ * @throws IllegalArgumentException if end is less than start or the range is not contained in the array
+ */
+ pub fn is_range(&self, start: i32, end: i32, value: bool) -> bool {
+ if end < start || start < 0 || end > self.size {
+ throw IllegalArgumentException::new();
+ }
+ if end == start {
+ // empty range matches
+ return true;
+ }
+ // will be easier to treat this as the last actually set bit -- inclusive
+ end -= 1;
+ let first_int: i32 = start / 32;
+ let last_int: i32 = end / 32;
+ {
+ let mut i: i32 = first_int;
+ while i <= last_int {
+ {
+ let first_bit: i32 = if i > first_int { 0 } else { start & 0x1F };
+ let last_bit: i32 = if i < last_int { 31 } else { end & 0x1F };
+ // Ones from firstBit to lastBit, inclusive
+ let mask: i32 = (2 << last_bit) - (1 << first_bit);
+ // equals the mask, or we're looking for 0s and the masked portion is not all 0s
+ if (self.bits[i] & mask) != ( if value { mask } else { 0 }) {
+ return false;
+ }
+ }
+ i += 1;
+ }
+ }
+
+ return true;
+ }
+
+ pub fn append_bit(&self, bit: bool) {
+ self.ensure_capacity(self.size + 1);
+ if bit {
+ self.bits[self.size / 32] |= 1 << (self.size & 0x1F);
+ }
+ self.size += 1;
+ }
+
+ /**
+ * Appends the least-significant bits, from value, in order from most-significant to
+ * least-significant. For example, appending 6 bits from 0x000001E will append the bits
+ * 0, 1, 1, 1, 1, 0 in that order.
+ *
+ * @param value {@code int} containing bits to append
+ * @param numBits bits from value to append
+ */
+ pub fn append_bits(&self, value: i32, num_bits: i32) {
+ if num_bits < 0 || num_bits > 32 {
+ throw IllegalArgumentException::new("Num bits must be between 0 and 32");
+ }
+ let next_size: i32 = self.size;
+ self.ensure_capacity(next_size + num_bits);
+ {
+ let num_bits_left: i32 = num_bits - 1;
+ while num_bits_left >= 0 {
+ {
+ if (value & (1 << num_bits_left)) != 0 {
+ self.bits[next_size / 32] |= 1 << (next_size & 0x1F);
+ }
+ next_size += 1;
+ }
+ num_bits_left -= 1;
+ }
+ }
+
+ self.size = next_size;
+ }
+
+ pub fn append_bit_array(&self, other: &BitArray) {
+ let other_size: i32 = other.size;
+ self.ensure_capacity(self.size + other_size);
+ {
+ let mut i: i32 = 0;
+ while i < other_size {
+ {
+ self.append_bit(&other.get(i));
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ pub fn xor(&self, other: &BitArray) {
+ if self.size != other.size {
+ throw IllegalArgumentException::new("Sizes don't match");
+ }
+ {
+ let mut i: i32 = 0;
+ while i < self.bits.len() {
+ {
+ // The last int could be incomplete (i.e. not have 32 bits in
+ // it) but there is no problem since 0 XOR 0 == 0.
+ self.bits[i] ^= other.bits[i];
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ /**
+ *
+ * @param bitOffset first bit to start writing
+ * @param array array to write into. Bytes are written most-significant byte first. This is the opposite
+ * of the internal representation, which is exposed by {@link #getBitArray()}
+ * @param offset position in array to start writing
+ * @param numBytes how many bytes to write
+ */
+ pub fn to_bytes(&self, bit_offset: i32, array: &Vec, offset: i32, num_bytes: i32) {
+ {
+ let mut i: i32 = 0;
+ while i < num_bytes {
+ {
+ let the_byte: i32 = 0;
+ {
+ let mut j: i32 = 0;
+ while j < 8 {
+ {
+ if self.get(bit_offset) {
+ the_byte |= 1 << (7 - j);
+ }
+ bit_offset += 1;
+ }
+ j += 1;
+ }
+ }
+
+ array[offset + i] = the_byte as i8;
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ /**
+ * @return underlying array of ints. The first element holds the first 32 bits, and the least
+ * significant bit is bit 0.
+ */
+ pub fn get_bit_array(&self) -> Vec {
+ return self.bits;
+ }
+
+ /**
+ * Reverses all bits in the array.
+ */
+ pub fn reverse(&self) {
+ let new_bits: [i32; self.bits.len()] = [0; self.bits.len()];
+ // reverse all int's first
+ let mut len: i32 = (self.size - 1) / 32;
+ let old_bits_len: i32 = len + 1;
+ {
+ let mut i: i32 = 0;
+ while i < old_bits_len {
+ {
+ new_bits[len - i] = Integer::reverse(self.bits[i]);
+ }
+ i += 1;
+ }
+ }
+
+ // now correct the int's if the bit size isn't a multiple of 32
+ if self.size != old_bits_len * 32 {
+ let left_offset: i32 = old_bits_len * 32 - self.size;
+ let current_int: i32 = new_bits[0] >> /* >>> */ left_offset;
+ {
+ let mut i: i32 = 1;
+ while i < old_bits_len {
+ {
+ let next_int: i32 = new_bits[i];
+ current_int |= next_int << (32 - left_offset);
+ new_bits[i - 1] = current_int;
+ current_int = next_int >> /* >>> */ left_offset;
+ }
+ i += 1;
+ }
+ }
+
+ new_bits[old_bits_len - 1] = current_int;
+ }
+ self.bits = new_bits;
+ }
+
+ fn make_array( size: i32) -> Vec {
+ return : [i32; (size + 31) / 32] = [0; (size + 31) / 32];
+ }
+
+ pub fn equals(&self, o: &Object) -> bool {
+ if !(o instanceof BitArray) {
+ return false;
+ }
+ let other: BitArray = o as BitArray;
+ return self.size == other.size && Arrays::equals(&self.bits, other.bits);
+ }
+
+ pub fn hash_code(&self) -> i32 {
+ return 31 * self.size + Arrays::hash_code(&self.bits);
+ }
+
+ pub fn to_string(&self) -> String {
+ let result: StringBuilder = StringBuilder::new(self.size + (self.size / 8) + 1);
+ {
+ let mut i: i32 = 0;
+ while i < self.size {
+ {
+ if (i & 0x07) == 0 {
+ result.append(' ');
+ }
+ result.append( if self.get(i) { 'X' } else { '.' });
+ }
+ i += 1;
+ }
+ }
+
+ return result.to_string();
+ }
+
+ pub fn clone(&self) -> BitArray {
+ return BitArray::new(&self.bits.clone(), self.size);
+ }
+}
+
+// BitMatrix.java
+/**
+ * Represents a 2D matrix of bits. In function arguments below, and throughout the common
+ * module, x is the column position, and y is the row position. The ordering is always x, y.
+ * The origin is at the top-left.
+ *
+ * Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins
+ * with a new int. This is done intentionally so that we can copy out a row into a BitArray very
+ * efficiently.
+ *
+ * The ordering of bits is row-major. Within each int, the least significant bits are used first,
+ * meaning they represent lower x values. This is compatible with BitArray's implementation.
+ *
+ * @author Sean Owen
+ * @author dswitkin@google.com (Daniel Switkin)
+ */
+#[derive(Cloneable)]
+pub struct BitMatrix {
+
+ let mut width: i32;
+
+ let mut height: i32;
+
+ let row_size: i32;
+
+ let mut bits: Vec;
+}
+
+impl BitMatrix {
+
+ /**
+ * Creates an empty square {@code BitMatrix}.
+ *
+ * @param dimension height and width
+ */
+ pub fn new( dimension: i32) -> BitMatrix {
+ this(dimension, dimension);
+ }
+
+ /**
+ * Creates an empty {@code BitMatrix}.
+ *
+ * @param width bit matrix width
+ * @param height bit matrix height
+ */
+ pub fn new( width: i32, height: i32) -> BitMatrix {
+ if width < 1 || height < 1 {
+ throw IllegalArgumentException::new("Both dimensions must be greater than 0");
+ }
+ let .width = width;
+ let .height = height;
+ let .rowSize = (width + 31) / 32;
+ bits = : [i32; row_size * height] = [0; row_size * height];
+ }
+
+ fn new( width: i32, height: i32, row_size: i32, bits: &Vec) -> BitMatrix {
+ let .width = width;
+ let .height = height;
+ let .rowSize = row_size;
+ let .bits = bits;
+ }
+
+ /**
+ * Interprets a 2D array of booleans as a {@code BitMatrix}, where "true" means an "on" bit.
+ *
+ * @param image bits of the image, as a row-major 2D array. Elements are arrays representing rows
+ * @return {@code BitMatrix} representation of image
+ */
+ pub fn parse( image: &Vec>) -> BitMatrix {
+ let height: i32 = image.len();
+ let width: i32 = image[0].len();
+ let bits: BitMatrix = BitMatrix::new(width, height);
+ {
+ let mut i: i32 = 0;
+ while i < height {
+ {
+ let image_i: Vec = image[i];
+ {
+ let mut j: i32 = 0;
+ while j < width {
+ {
+ if image_i[j] {
+ bits.set(j, i);
+ }
+ }
+ j += 1;
+ }
+ }
+
+ }
+ i += 1;
+ }
+ }
+
+ return bits;
+ }
+
+ pub fn parse( string_representation: &String, set_string: &String, unset_string: &String) -> BitMatrix {
+ if string_representation == null {
+ throw IllegalArgumentException::new();
+ }
+ let mut bits: [bool; string_representation.length()] = [false; string_representation.length()];
+ let bits_pos: i32 = 0;
+ let row_start_pos: i32 = 0;
+ let row_length: i32 = -1;
+ let n_rows: i32 = 0;
+ let mut pos: i32 = 0;
+ while pos < string_representation.length() {
+ if string_representation.char_at(pos) == '\n' || string_representation.char_at(pos) == '\r' {
+ if bits_pos > row_start_pos {
+ if row_length == -1 {
+ row_length = bits_pos - row_start_pos;
+ } else if bits_pos - row_start_pos != row_length {
+ throw IllegalArgumentException::new("row lengths do not match");
+ }
+ row_start_pos = bits_pos;
+ n_rows += 1;
+ }
+ pos += 1;
+ } else if string_representation.starts_with(&set_string, pos) {
+ pos += set_string.length();
+ bits[bits_pos] = true;
+ bits_pos += 1;
+ } else if string_representation.starts_with(&unset_string, pos) {
+ pos += unset_string.length();
+ bits[bits_pos] = false;
+ bits_pos += 1;
+ } else {
+ throw IllegalArgumentException::new(format!("illegal character encountered: {}", string_representation.substring(pos)));
+ }
+ }
+ // no EOL at end?
+ if bits_pos > row_start_pos {
+ if row_length == -1 {
+ row_length = bits_pos - row_start_pos;
+ } else if bits_pos - row_start_pos != row_length {
+ throw IllegalArgumentException::new("row lengths do not match");
+ }
+ n_rows += 1;
+ }
+ let matrix: BitMatrix = BitMatrix::new(row_length, n_rows);
+ {
+ let mut i: i32 = 0;
+ while i < bits_pos {
+ {
+ if bits[i] {
+ matrix.set(i % row_length, i / row_length);
+ }
+ }
+ i += 1;
+ }
+ }
+
+ return matrix;
+ }
+
+ /**
+ * Gets the requested bit, where true means black.
+ *
+ * @param x The horizontal component (i.e. which column)
+ * @param y The vertical component (i.e. which row)
+ * @return value of given bit in matrix
+ */
+ pub fn get(&self, x: i32, y: i32) -> bool {
+ let offset: i32 = y * self.row_size + (x / 32);
+ return ((self.bits[offset] >> /* >>> */ (x & 0x1f)) & 1) != 0;
+ }
+
+ /**
+ * Sets the given bit to true.
+ *
+ * @param x The horizontal component (i.e. which column)
+ * @param y The vertical component (i.e. which row)
+ */
+ pub fn set(&self, x: i32, y: i32) {
+ let mut offset: i32 = y * self.row_size + (x / 32);
+ self.bits[offset] |= 1 << (x & 0x1f);
+ }
+
+ pub fn unset(&self, x: i32, y: i32) {
+ let mut offset: i32 = y * self.row_size + (x / 32);
+ self.bits[offset] &= ~(1 << (x & 0x1f));
+ }
+
+ /**
+ * Flips the given bit.
+ *
+ * @param x The horizontal component (i.e. which column)
+ * @param y The vertical component (i.e. which row)
+ */
+ pub fn flip(&self, x: i32, y: i32) {
+ let mut offset: i32 = y * self.row_size + (x / 32);
+ self.bits[offset] ^= 1 << (x & 0x1f);
+ }
+
+ /**
+ * Flips every bit in the matrix.
+ */
+ pub fn flip(&self) {
+ let max: i32 = self.bits.len();
+ {
+ let mut i: i32 = 0;
+ while i < max {
+ {
+ self.bits[i] = ~self.bits[i];
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ /**
+ * Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding
+ * mask bit is set.
+ *
+ * @param mask XOR mask
+ */
+ pub fn xor(&self, mask: &BitMatrix) {
+ if self.width != mask.width || self.height != mask.height || self.row_size != mask.rowSize {
+ throw IllegalArgumentException::new("input matrix dimensions do not match");
+ }
+ let row_array: BitArray = BitArray::new(self.width);
+ {
+ let mut y: i32 = 0;
+ while y < self.height {
+ {
+ let mut offset: i32 = y * self.row_size;
+ let row: Vec = mask.get_row(y, row_array).get_bit_array();
+ {
+ let mut x: i32 = 0;
+ while x < self.row_size {
+ {
+ self.bits[offset + x] ^= row[x];
+ }
+ x += 1;
+ }
+ }
+
+ }
+ y += 1;
+ }
+ }
+
+ }
+
+ /**
+ * Clears all bits (sets to false).
+ */
+ pub fn clear(&self) {
+ let max: i32 = self.bits.len();
+ {
+ let mut i: i32 = 0;
+ while i < max {
+ {
+ self.bits[i] = 0;
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ /**
+ * Sets a square region of the bit matrix to true.
+ *
+ * @param left The horizontal position to begin at (inclusive)
+ * @param top The vertical position to begin at (inclusive)
+ * @param width The width of the region
+ * @param height The height of the region
+ */
+ pub fn set_region(&self, left: i32, top: i32, width: i32, height: i32) {
+ if top < 0 || left < 0 {
+ throw IllegalArgumentException::new("Left and top must be nonnegative");
+ }
+ if height < 1 || width < 1 {
+ throw IllegalArgumentException::new("Height and width must be at least 1");
+ }
+ let right: i32 = left + width;
+ let bottom: i32 = top + height;
+ if bottom > self.height || right > self.width {
+ throw IllegalArgumentException::new("The region must fit inside the matrix");
+ }
+ {
+ let mut y: i32 = top;
+ while y < bottom {
+ {
+ let mut offset: i32 = y * self.row_size;
+ {
+ let mut x: i32 = left;
+ while x < right {
+ {
+ self.bits[offset + (x / 32)] |= 1 << (x & 0x1f);
+ }
+ x += 1;
+ }
+ }
+
+ }
+ y += 1;
+ }
+ }
+
+ }
+
+ /**
+ * A fast method to retrieve one row of data from the matrix as a BitArray.
+ *
+ * @param y The row to retrieve
+ * @param row An optional caller-allocated BitArray, will be allocated if null or too small
+ * @return The resulting BitArray - this reference should always be used even when passing
+ * your own row
+ */
+ pub fn get_row(&self, y: i32, row: &BitArray) -> BitArray {
+ if row == null || row.get_size() < self.width {
+ row = BitArray::new(self.width);
+ } else {
+ row.clear();
+ }
+ let offset: i32 = y * self.row_size;
+ {
+ let mut x: i32 = 0;
+ while x < self.row_size {
+ {
+ row.set_bulk(x * 32, self.bits[offset + x]);
+ }
+ x += 1;
+ }
+ }
+
+ return row;
+ }
+
+ /**
+ * @param y row to set
+ * @param row {@link BitArray} to copy from
+ */
+ pub fn set_row(&self, y: i32, row: &BitArray) {
+ System::arraycopy(&row.get_bit_array(), 0, &self.bits, y * self.row_size, self.row_size);
+ }
+
+ /**
+ * Modifies this {@code BitMatrix} to represent the same but rotated the given degrees (0, 90, 180, 270)
+ *
+ * @param degrees number of degrees to rotate through counter-clockwise (0, 90, 180, 270)
+ */
+ pub fn rotate(&self, degrees: i32) {
+ match degrees % 360 {
+ 0 =>
+ {
+ return;
+ }
+ 90 =>
+ {
+ self.rotate90();
+ return;
+ }
+ 180 =>
+ {
+ self.rotate180();
+ return;
+ }
+ 270 =>
+ {
+ self.rotate90();
+ self.rotate180();
+ return;
+ }
+ }
+ throw IllegalArgumentException::new("degrees must be a multiple of 0, 90, 180, or 270");
+ }
+
+ /**
+ * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees
+ */
+ pub fn rotate180(&self) {
+ let top_row: BitArray = BitArray::new(self.width);
+ let bottom_row: BitArray = BitArray::new(self.width);
+ let max_height: i32 = (self.height + 1) / 2;
+ {
+ let mut i: i32 = 0;
+ while i < max_height {
+ {
+ top_row = self.get_row(i, top_row);
+ let bottom_row_index: i32 = self.height - 1 - i;
+ bottom_row = self.get_row(bottom_row_index, bottom_row);
+ top_row.reverse();
+ bottom_row.reverse();
+ self.set_row(i, bottom_row);
+ self.set_row(bottom_row_index, top_row);
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ /**
+ * Modifies this {@code BitMatrix} to represent the same but rotated 90 degrees counterclockwise
+ */
+ pub fn rotate90(&self) {
+ let new_width: i32 = self.height;
+ let new_height: i32 = self.width;
+ let new_row_size: i32 = (new_width + 31) / 32;
+ let new_bits: [i32; new_row_size * new_height] = [0; new_row_size * new_height];
+ {
+ let mut y: i32 = 0;
+ while y < self.height {
+ {
+ {
+ let mut x: i32 = 0;
+ while x < self.width {
+ {
+ let offset: i32 = y * self.row_size + (x / 32);
+ if ((self.bits[offset] >> /* >>> */ (x & 0x1f)) & 1) != 0 {
+ let new_offset: i32 = (new_height - 1 - x) * new_row_size + (y / 32);
+ new_bits[new_offset] |= 1 << (y & 0x1f);
+ }
+ }
+ x += 1;
+ }
+ }
+
+ }
+ y += 1;
+ }
+ }
+
+ self.width = new_width;
+ self.height = new_height;
+ self.row_size = new_row_size;
+ self.bits = new_bits;
+ }
+
+ /**
+ * This is useful in detecting the enclosing rectangle of a 'pure' barcode.
+ *
+ * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white
+ */
+ pub fn get_enclosing_rectangle(&self) -> Vec {
+ let mut left: i32 = self.width;
+ let mut top: i32 = self.height;
+ let mut right: i32 = -1;
+ let mut bottom: i32 = -1;
+ {
+ let mut y: i32 = 0;
+ while y < self.height {
+ {
+ {
+ let mut x32: i32 = 0;
+ while x32 < self.row_size {
+ {
+ let the_bits: i32 = self.bits[y * self.row_size + x32];
+ if the_bits != 0 {
+ if y < top {
+ top = y;
+ }
+ if y > bottom {
+ bottom = y;
+ }
+ if x32 * 32 < left {
+ let mut bit: i32 = 0;
+ while (the_bits << (31 - bit)) == 0 {
+ bit += 1;
+ }
+ if (x32 * 32 + bit) < left {
+ left = x32 * 32 + bit;
+ }
+ }
+ if x32 * 32 + 31 > right {
+ let mut bit: i32 = 31;
+ while (the_bits >> /* >>> */ bit) == 0 {
+ bit -= 1;
+ }
+ if (x32 * 32 + bit) > right {
+ right = x32 * 32 + bit;
+ }
+ }
+ }
+ }
+ x32 += 1;
+ }
+ }
+
+ }
+ y += 1;
+ }
+ }
+
+ if right < left || bottom < top {
+ return null;
+ }
+ return : vec![i32; 4] = vec![left, top, right - left + 1, bottom - top + 1, ]
+ ;
+ }
+
+ /**
+ * This is useful in detecting a corner of a 'pure' barcode.
+ *
+ * @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white
+ */
+ pub fn get_top_left_on_bit(&self) -> Vec {
+ let bits_offset: i32 = 0;
+ while bits_offset < self.bits.len() && self.bits[bits_offset] == 0 {
+ bits_offset += 1;
+ }
+ if bits_offset == self.bits.len() {
+ return null;
+ }
+ let y: i32 = bits_offset / self.row_size;
+ let mut x: i32 = (bits_offset % self.row_size) * 32;
+ let the_bits: i32 = self.bits[bits_offset];
+ let mut bit: i32 = 0;
+ while (the_bits << (31 - bit)) == 0 {
+ bit += 1;
+ }
+ x += bit;
+ return : vec![i32; 2] = vec![x, y, ]
+ ;
+ }
+
+ pub fn get_bottom_right_on_bit(&self) -> Vec {
+ let bits_offset: i32 = self.bits.len() - 1;
+ while bits_offset >= 0 && self.bits[bits_offset] == 0 {
+ bits_offset -= 1;
+ }
+ if bits_offset < 0 {
+ return null;
+ }
+ let y: i32 = bits_offset / self.row_size;
+ let mut x: i32 = (bits_offset % self.row_size) * 32;
+ let the_bits: i32 = self.bits[bits_offset];
+ let mut bit: i32 = 31;
+ while (the_bits >> /* >>> */ bit) == 0 {
+ bit -= 1;
+ }
+ x += bit;
+ return : vec![i32; 2] = vec![x, y, ]
+ ;
+ }
+
+ /**
+ * @return The width of the matrix
+ */
+ pub fn get_width(&self) -> i32 {
+ return self.width;
+ }
+
+ /**
+ * @return The height of the matrix
+ */
+ pub fn get_height(&self) -> i32 {
+ return self.height;
+ }
+
+ /**
+ * @return The row size of the matrix
+ */
+ pub fn get_row_size(&self) -> i32 {
+ return self.row_size;
+ }
+
+ pub fn equals(&self, o: &Object) -> bool {
+ if !(o instanceof BitMatrix) {
+ return false;
+ }
+ let other: BitMatrix = o as BitMatrix;
+ return self.width == other.width && self.height == other.height && self.row_size == other.rowSize && Arrays::equals(&self.bits, other.bits);
+ }
+
+ pub fn hash_code(&self) -> i32 {
+ let mut hash: i32 = self.width;
+ hash = 31 * hash + self.width;
+ hash = 31 * hash + self.height;
+ hash = 31 * hash + self.row_size;
+ hash = 31 * hash + Arrays::hash_code(&self.bits);
+ return hash;
+ }
+
+ /**
+ * @return string representation using "X" for set and " " for unset bits
+ */
+ pub fn to_string(&self) -> String {
+ return self.to_string("X ", " ");
+ }
+
+ /**
+ * @param setString representation of a set bit
+ * @param unsetString representation of an unset bit
+ * @return string representation of entire matrix utilizing given strings
+ */
+ pub fn to_string(&self, set_string: &String, unset_string: &String) -> String {
+ return self.build_to_string(&set_string, &unset_string, "\n");
+ }
+
+ /**
+ * @param setString representation of a set bit
+ * @param unsetString representation of an unset bit
+ * @param lineSeparator newline character in string representation
+ * @return string representation of entire matrix utilizing given strings and line separator
+ * @deprecated call {@link #toString(String,String)} only, which uses \n line separator always
+ */
+ pub fn to_string(&self, set_string: &String, unset_string: &String, line_separator: &String) -> String {
+ return self.build_to_string(&set_string, &unset_string, &line_separator);
+ }
+
+ fn build_to_string(&self, set_string: &String, unset_string: &String, line_separator: &String) -> String {
+ let result: StringBuilder = StringBuilder::new(self.height * (self.width + 1));
+ {
+ let mut y: i32 = 0;
+ while y < self.height {
+ {
+ {
+ let mut x: i32 = 0;
+ while x < self.width {
+ {
+ result.append( if self.get(x, y) { set_string } else { unset_string });
+ }
+ x += 1;
+ }
+ }
+
+ result.append(&line_separator);
+ }
+ y += 1;
+ }
+ }
+
+ return result.to_string();
+ }
+
+ pub fn clone(&self) -> BitMatrix {
+ return BitMatrix::new(self.width, self.height, self.row_size, &self.bits.clone());
+ }
+}
+
+// BitSource.java
+/**
+ * This provides an easy abstraction to read bits at a time from a sequence of bytes, where the
+ * number of bits read is not often a multiple of 8.
+ *
+ * This class is thread-safe but not reentrant -- unless the caller modifies the bytes array
+ * it passed in, in which case all bets are off.
+ *
+ * @author Sean Owen
+ */
+pub struct BitSource {
+
+ let bytes: Vec;
+
+ let byte_offset: i32;
+
+ let bit_offset: i32;
+}
+
+impl BitSource {
+
+ /**
+ * @param bytes bytes from which this will read bits. Bits will be read from the first byte first.
+ * Bits are read within a byte from most-significant to least-significant bit.
+ */
+ pub fn new( bytes: &Vec) -> BitSource {
+ let .bytes = bytes;
+ }
+
+ /**
+ * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}.
+ */
+ pub fn get_bit_offset(&self) -> i32 {
+ return self.bit_offset;
+ }
+
+ /**
+ * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}.
+ */
+ pub fn get_byte_offset(&self) -> i32 {
+ return self.byte_offset;
+ }
+
+ /**
+ * @param numBits number of bits to read
+ * @return int representing the bits read. The bits will appear as the least-significant
+ * bits of the int
+ * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available
+ */
+ pub fn read_bits(&self, num_bits: i32) -> i32 {
+ if num_bits < 1 || num_bits > 32 || num_bits > self.available() {
+ throw IllegalArgumentException::new(&String::value_of(num_bits));
+ }
+ let mut result: i32 = 0;
+ // First, read remainder from current byte
+ if self.bit_offset > 0 {
+ let bits_left: i32 = 8 - self.bit_offset;
+ let to_read: i32 = Math::min(num_bits, bits_left);
+ let bits_to_not_read: i32 = bits_left - to_read;
+ let mask: i32 = (0xFF >> (8 - to_read)) << bits_to_not_read;
+ result = (self.bytes[self.byte_offset] & mask) >> bits_to_not_read;
+ num_bits -= to_read;
+ self.bit_offset += to_read;
+ if self.bit_offset == 8 {
+ self.bit_offset = 0;
+ self.byte_offset += 1;
+ }
+ }
+ // Next read whole bytes
+ if num_bits > 0 {
+ while num_bits >= 8 {
+ result = (result << 8) | (self.bytes[self.byte_offset] & 0xFF);
+ self.byte_offset += 1;
+ num_bits -= 8;
+ }
+ // Finally read a partial byte
+ if num_bits > 0 {
+ let bits_to_not_read: i32 = 8 - num_bits;
+ let mask: i32 = (0xFF >> bits_to_not_read) << bits_to_not_read;
+ result = (result << num_bits) | ((self.bytes[self.byte_offset] & mask) >> bits_to_not_read);
+ self.bit_offset += num_bits;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * @return number of bits that can be read successfully
+ */
+ pub fn available(&self) -> i32 {
+ return 8 * (self.bytes.len() - self.byte_offset) - self.bit_offset;
+ }
+}
+
+
+// CharacterSetECI.java
+/**
+ * Encapsulates a Character Set ECI, according to "Extended Channel Interpretations" 5.3.1.1
+ * of ISO 18004.
+ *
+ * @author Sean Owen
+ */
+pub enum CharacterSetECI {
+
+ // Enum name is a Java encoding valid for java.lang and java.io
+ Cp437( : vec![i32; 2] = vec![0, 2, ]
+ ), ISO8859_1( : vec![i32; 2] = vec![1, 3, ]
+ , "ISO-8859-1"), ISO8859_2(4, "ISO-8859-2"), ISO8859_3(5, "ISO-8859-3"), ISO8859_4(6, "ISO-8859-4"), ISO8859_5(7, "ISO-8859-5"), // ISO8859_6(8, "ISO-8859-6"),
+ ISO8859_7(9, "ISO-8859-7"), // ISO8859_8(10, "ISO-8859-8"),
+ ISO8859_9(11, "ISO-8859-9"), // ISO8859_11(13, "ISO-8859-11"),
+ ISO8859_13(15, "ISO-8859-13"), // ISO8859_14(16, "ISO-8859-14"),
+ ISO8859_15(17, "ISO-8859-15"), ISO8859_16(18, "ISO-8859-16"), SJIS(20, "Shift_JIS"), Cp1250(21, "windows-1250"), Cp1251(22, "windows-1251"), Cp1252(23, "windows-1252"), Cp1256(24, "windows-1256"), UnicodeBigUnmarked(25, "UTF-16BE", "UnicodeBig"), UTF8(26, "UTF-8"), ASCII( : vec![i32; 2] = vec![27, 170, ]
+ , "US-ASCII"), Big5(28), GB18030(29, "GB2312", "EUC_CN", "GBK"), EUC_KR(30, "EUC-KR");
+
+ const VALUE_TO_ECI: Map = HashMap<>::new();
+
+ const NAME_TO_ECI: Map = HashMap<>::new();
+
+ static {
+ for let eci: CharacterSetECI in self.values() {
+ for let value: i32 in eci.values {
+ VALUE_TO_ECI::put(value, eci);
+ }
+ NAME_TO_ECI::put(&eci.name(), eci);
+ for let name: String in eci.otherEncodingNames {
+ NAME_TO_ECI::put(&name, eci);
+ }
+ }
+ }
+
+ let mut values: Vec;
+
+ let other_encoding_names: Vec;
+
+ fn new( value: i32) -> CharacterSetECI {
+ this( : vec![i32; 1] = vec![value, ]
+ );
+ }
+
+ fn new( value: i32, other_encoding_names: &String) -> CharacterSetECI {
+ let .values = : vec![i32; 1] = vec![value, ]
+ ;
+ let .otherEncodingNames = other_encoding_names;
+ }
+
+ fn new( values: &Vec, other_encoding_names: &String) -> CharacterSetECI {
+ let .values = values;
+ let .otherEncodingNames = other_encoding_names;
+ }
+
+ pub fn get_value(&self) -> i32 {
+ return self.values[0];
+ }
+
+ pub fn get_charset(&self) -> Charset {
+ return Charset::for_name(&name());
+ }
+
+ /**
+ * @param charset Java character set object
+ * @return CharacterSetECI representing ECI for character encoding, or null if it is legal
+ * but unsupported
+ */
+ pub fn get_character_set_e_c_i( charset: &Charset) -> CharacterSetECI {
+ return NAME_TO_ECI::get(&charset.name());
+ }
+
+ /**
+ * @param value character set ECI value
+ * @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but
+ * unsupported
+ * @throws FormatException if ECI value is invalid
+ */
+ pub fn get_character_set_e_c_i_by_value( value: i32) -> /* throws FormatException */Result> {
+ if value < 0 || value >= 900 {
+ throw FormatException::get_format_instance();
+ }
+ return Ok(VALUE_TO_ECI::get(value));
+ }
+
+ /**
+ * @param name character set ECI encoding name
+ * @return CharacterSetECI representing ECI for character encoding, or null if it is legal
+ * but unsupported
+ */
+ pub fn get_character_set_e_c_i_by_name( name: &String) -> CharacterSetECI {
+ return NAME_TO_ECI::get(&name);
+ }
+}
+
+// DecoderResult.java
+/**
+ * Encapsulates the result of decoding a matrix of bits. This typically
+ * applies to 2D barcode formats. For now it contains the raw bytes obtained,
+ * as well as a String interpretation of those bytes, if applicable.
+ *
+ * @author Sean Owen
+ */
+pub struct DecoderResult {
+
+ let raw_bytes: Vec;
+
+ let num_bits: i32;
+
+ let text: String;
+
+ let byte_segments: List>;
+
+ let ec_level: String;
+
+ let errors_corrected: Integer;
+
+ let erasures: Integer;
+
+ let other: Object;
+
+ let structured_append_parity: i32;
+
+ let structured_append_sequence_number: i32;
+
+ let symbology_modifier: i32;
+}
+
+impl DecoderResult {
+
+ pub fn new( raw_bytes: &Vec, text: &String, byte_segments: &List>, ec_level: &String) -> DecoderResult {
+ this(&raw_bytes, &text, &byte_segments, &ec_level, -1, -1, 0);
+ }
+
+ pub fn new( raw_bytes: &Vec, text: &String, byte_segments: &List>, ec_level: &String, symbology_modifier: i32) -> DecoderResult {
+ this(&raw_bytes, &text, &byte_segments, &ec_level, -1, -1, symbology_modifier);
+ }
+
+ pub fn new( raw_bytes: &Vec, text: &String, byte_segments: &List>, ec_level: &String, sa_sequence: i32, sa_parity: i32) -> DecoderResult {
+ this(&raw_bytes, &text, &byte_segments, &ec_level, sa_sequence, sa_parity, 0);
+ }
+
+ pub fn new( raw_bytes: &Vec, text: &String, byte_segments: &List>, ec_level: &String, sa_sequence: i32, sa_parity: i32, symbology_modifier: i32) -> DecoderResult {
+ let .rawBytes = raw_bytes;
+ let .numBits = if raw_bytes == null { 0 } else { 8 * raw_bytes.len() };
+ let .text = text;
+ let .byteSegments = byte_segments;
+ let .ecLevel = ec_level;
+ let .structuredAppendParity = sa_parity;
+ let .structuredAppendSequenceNumber = sa_sequence;
+ let .symbologyModifier = symbology_modifier;
+ }
+
+ /**
+ * @return raw bytes representing the result, or {@code null} if not applicable
+ */
+ pub fn get_raw_bytes(&self) -> Vec {
+ return self.raw_bytes;
+ }
+
+ /**
+ * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length
+ * @since 3.3.0
+ */
+ pub fn get_num_bits(&self) -> i32 {
+ return self.num_bits;
+ }
+
+ /**
+ * @param numBits overrides the number of bits that are valid in {@link #getRawBytes()}
+ * @since 3.3.0
+ */
+ pub fn set_num_bits(&self, num_bits: i32) {
+ self.numBits = num_bits;
+ }
+
+ /**
+ * @return text representation of the result
+ */
+ pub fn get_text(&self) -> String {
+ return self.text;
+ }
+
+ /**
+ * @return list of byte segments in the result, or {@code null} if not applicable
+ */
+ pub fn get_byte_segments(&self) -> List> {
+ return self.byte_segments;
+ }
+
+ /**
+ * @return name of error correction level used, or {@code null} if not applicable
+ */
+ pub fn get_e_c_level(&self) -> String {
+ return self.ec_level;
+ }
+
+ /**
+ * @return number of errors corrected, or {@code null} if not applicable
+ */
+ pub fn get_errors_corrected(&self) -> Integer {
+ return self.errors_corrected;
+ }
+
+ pub fn set_errors_corrected(&self, errors_corrected: &Integer) {
+ self.errorsCorrected = errors_corrected;
+ }
+
+ /**
+ * @return number of erasures corrected, or {@code null} if not applicable
+ */
+ pub fn get_erasures(&self) -> Integer {
+ return self.erasures;
+ }
+
+ pub fn set_erasures(&self, erasures: &Integer) {
+ self.erasures = erasures;
+ }
+
+ /**
+ * @return arbitrary additional metadata
+ */
+ pub fn get_other(&self) -> Object {
+ return self.other;
+ }
+
+ pub fn set_other(&self, other: &Object) {
+ self.other = other;
+ }
+
+ pub fn has_structured_append(&self) -> bool {
+ return self.structured_append_parity >= 0 && self.structured_append_sequence_number >= 0;
+ }
+
+ pub fn get_structured_append_parity(&self) -> i32 {
+ return self.structured_append_parity;
+ }
+
+ pub fn get_structured_append_sequence_number(&self) -> i32 {
+ return self.structured_append_sequence_number;
+ }
+
+ pub fn get_symbology_modifier(&self) -> i32 {
+ return self.symbology_modifier;
+ }
+}
+
+// DefaultGridSampler.java
+
+/**
+ * @author Sean Owen
+ */
+pub struct DefaultGridSampler {
+ super: GridSampler;
+}
+
+impl GridSampler for DefaultGridSampler {
+
+ pub fn sample_grid(&self, image: &BitMatrix, dimension_x: i32, dimension_y: i32, p1_to_x: f32, p1_to_y: f32, p2_to_x: f32, p2_to_y: f32, p3_to_x: f32, p3_to_y: f32, p4_to_x: f32, p4_to_y: f32, p1_from_x: f32, p1_from_y: f32, p2_from_x: f32, p2_from_y: f32, p3_from_x: f32, p3_from_y: f32, p4_from_x: f32, p4_from_y: f32) -> /* throws NotFoundException */Result> {
+ let transform: PerspectiveTransform = PerspectiveTransform::quadrilateral_to_quadrilateral(p1_to_x, p1_to_y, p2_to_x, p2_to_y, p3_to_x, p3_to_y, p4_to_x, p4_to_y, p1_from_x, p1_from_y, p2_from_x, p2_from_y, p3_from_x, p3_from_y, p4_from_x, p4_from_y);
+ return Ok(self.sample_grid(image, dimension_x, dimension_y, transform));
+ }
+
+ pub fn sample_grid(&self, image: &BitMatrix, dimension_x: i32, dimension_y: i32, transform: &PerspectiveTransform) -> /* throws NotFoundException */Result> {
+ if dimension_x <= 0 || dimension_y <= 0 {
+ throw NotFoundException::get_not_found_instance();
+ }
+ let bits: BitMatrix = BitMatrix::new(dimension_x, dimension_y);
+ let mut points: [f32; 2.0 * dimension_x] = [0.0; 2.0 * dimension_x];
+ {
+ let mut y: i32 = 0;
+ while y < dimension_y {
+ {
+ let max: i32 = points.len();
+ let i_value: f32 = y + 0.5f;
+ {
+ let mut x: i32 = 0;
+ while x < max {
+ {
+ points[x] = (x / 2.0) as f32 + 0.5f;
+ points[x + 1] = i_value;
+ }
+ x += 2;
+ }
+ }
+
+ transform.transform_points(&points);
+ // Quick check to see if points transformed to something inside the image;
+ // sufficient to check the endpoints
+ check_and_nudge_points(image, &points);
+ let tryResult1 = 0;
+ 'try1: loop {
+ {
+ {
+ let mut x: i32 = 0;
+ while x < max {
+ {
+ if image.get(points[x] as i32, points[x + 1] as i32) {
+ // Black(-ish) pixel
+ bits.set(x / 2, y);
+ }
+ }
+ x += 2;
+ }
+ }
+
+ }
+ break 'try1
+ }
+ match tryResult1 {
+ catch ( aioobe: &ArrayIndexOutOfBoundsException) {
+ throw NotFoundException::get_not_found_instance();
+ } 0 => break
+ }
+
+ }
+ y += 1;
+ }
+ }
+
+ return Ok(bits);
+ }
+}
+
+// DetectorResult.java
+/**
+ * Encapsulates the result of detecting a barcode in an image. This includes the raw
+ * matrix of black/white pixels corresponding to the barcode, and possibly points of interest
+ * in the image, like the location of finder patterns or corners of the barcode in the image.
+ *
+ * @author Sean Owen
+ */
+pub struct DetectorResult {
+
+ let bits: BitMatrix;
+
+ let points: Vec;
+}
+
+impl DetectorResult {
+
+ pub fn new( bits: &BitMatrix, points: &Vec) -> DetectorResult {
+ let .bits = bits;
+ let .points = points;
+ }
+
+ pub fn get_bits(&self) -> BitMatrix {
+ return self.bits;
+ }
+
+ pub fn get_points(&self) -> Vec {
+ return self.points;
+ }
+}
+
+
+// ECIEncoderSet.java
+/**
+ * Set of CharsetEncoders for a given input string
+ *
+ * Invariants:
+ * - The list contains only encoders from CharacterSetECI (list is shorter then the list of encoders available on
+ * the platform for which ECI values are defined).
+ * - The list contains encoders at least one encoder for every character in the input.
+ * - The first encoder in the list is always the ISO-8859-1 encoder even of no character in the input can be encoded
+ * by it.
+ * - If the input contains a character that is not in ISO-8859-1 then the last two entries in the list will be the
+ * UTF-8 encoder and the UTF-16BE encoder.
+ *
+ * @author Alex Geller
+ */
+
+// List of encoders that potentially encode characters not in ISO-8859-1 in one byte.
+const ENCODERS: List = ArrayList<>::new();
+pub struct ECIEncoderSet {
+
+ let mut encoders: Vec;
+
+ let priority_encoder_index: i32;
+}
+
+impl ECIEncoderSet {
+
+ static {
+ let names: vec![Vec; 20] = vec!["IBM437", "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", "ISO-8859-10", "ISO-8859-11", "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "ISO-8859-16", "windows-1250", "windows-1251", "windows-1252", "windows-1256", "Shift_JIS", ]
+ ;
+ for let name: String in names {
+ if CharacterSetECI::get_character_set_e_c_i_by_name(&name) != null {
+ let tryResult1 = 0;
+ 'try1: loop {
+ {
+ ENCODERS::add(&Charset::for_name(&name)::new_encoder());
+ }
+ break 'try1
+ }
+ match tryResult1 {
+ catch ( e: &UnsupportedCharsetException) {
+ } 0 => break
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Constructs an encoder set
+ *
+ * @param stringToEncode the string that needs to be encoded
+ * @param priorityCharset The preferred {@link Charset} or null.
+ * @param fnc1 fnc1 denotes the character in the input that represents the FNC1 character or -1 for a non-GS1 bar
+ * code. When specified, it is considered an error to pass it as argument to the methods canEncode() or encode().
+ */
+ pub fn new( string_to_encode: &String, priority_charset: &Charset, fnc1: i32) -> ECIEncoderSet {
+ let needed_encoders: List = ArrayList<>::new();
+ //we always need the ISO-8859-1 encoder. It is the default encoding
+ needed_encoders.add(&StandardCharsets::ISO_8859_1::new_encoder());
+ let need_unicode_encoder: bool = priority_charset != null && priority_charset.name().starts_with("UTF");
+ //Walk over the input string and see if all characters can be encoded with the list of encoders
+ {
+ let mut i: i32 = 0;
+ while i < string_to_encode.length() {
+ {
+ let can_encode: bool = false;
+ for let encoder: CharsetEncoder in needed_encoders {
+ let c: char = string_to_encode.char_at(i);
+ if c == fnc1 || encoder.can_encode(c) {
+ can_encode = true;
+ break;
+ }
+ }
+ if !can_encode {
+ //for the character at position i we don't yet have an encoder in the list
+ for let encoder: CharsetEncoder in ENCODERS {
+ if encoder.can_encode(&string_to_encode.char_at(i)) {
+ //Good, we found an encoder that can encode the character. We add him to the list and continue scanning
+ //the input
+ needed_encoders.add(&encoder);
+ can_encode = true;
+ break;
+ }
+ }
+ }
+ if !can_encode {
+ //The character is not encodeable by any of the single byte encoders so we remember that we will need a
+ //Unicode encoder.
+ need_unicode_encoder = true;
+ }
+ }
+ i += 1;
+ }
+ }
+
+ if needed_encoders.size() == 1 && !need_unicode_encoder {
+ //the entire input can be encoded by the ISO-8859-1 encoder
+ encoders = : vec![CharsetEncoder; 1] = vec![needed_encoders.get(0), ]
+ ;
+ } else {
+ // we need more than one single byte encoder or we need a Unicode encoder.
+ // In this case we append a UTF-8 and UTF-16 encoder to the list
+ encoders = : [Option; needed_encoders.size() + 2] = [None; needed_encoders.size() + 2];
+ let mut index: i32 = 0;
+ for let encoder: CharsetEncoder in needed_encoders {
+ encoders[index += 1 !!!check!!! post increment] = encoder;
+ }
+ encoders[index] = StandardCharsets::UTF_8::new_encoder();
+ encoders[index + 1] = StandardCharsets::UTF_16BE::new_encoder();
+ }
+ //Compute priorityEncoderIndex by looking up priorityCharset in encoders
+ let priority_encoder_index_value: i32 = -1;
+ if priority_charset != null {
+ {
+ let mut i: i32 = 0;
+ while i < encoders.len() {
+ {
+ if encoders[i] != null && priority_charset.name().equals(&encoders[i].charset().name()) {
+ priority_encoder_index_value = i;
+ break;
+ }
+ }
+ i += 1;
+ }
+ }
+
+ }
+ priority_encoder_index = priority_encoder_index_value;
+ //invariants
+ assert!( encoders[0].charset().equals(StandardCharsets::ISO_8859_1));
+ }
+
+ pub fn length(&self) -> i32 {
+ return self.encoders.len();
+ }
+
+ pub fn get_charset_name(&self, index: i32) -> String {
+ assert!( index < self.length());
+ return self.encoders[index].charset().name();
+ }
+
+ pub fn get_charset(&self, index: i32) -> Charset {
+ assert!( index < self.length());
+ return self.encoders[index].charset();
+ }
+
+ pub fn get_e_c_i_value(&self, encoder_index: i32) -> i32 {
+ return CharacterSetECI::get_character_set_e_c_i(&self.encoders[encoder_index].charset())::get_value();
+ }
+
+ /*
+ * returns -1 if no priority charset was defined
+ */
+ pub fn get_priority_encoder_index(&self) -> i32 {
+ return self.priority_encoder_index;
+ }
+
+ pub fn can_encode(&self, c: char, encoder_index: i32) -> bool {
+ assert!( encoder_index < self.length());
+ let encoder: CharsetEncoder = self.encoders[encoder_index];
+ return encoder.can_encode(format!("{}", c));
+ }
+
+ pub fn encode(&self, c: char, encoder_index: i32) -> Vec {
+ assert!( encoder_index < self.length());
+ let encoder: CharsetEncoder = self.encoders[encoder_index];
+ assert!( encoder.can_encode(format!("{}", c)));
+ return (format!("{}", c)).get_bytes(&encoder.charset());
+ }
+
+ pub fn encode(&self, s: &String, encoder_index: i32) -> Vec {
+ assert!( encoder_index < self.length());
+ let encoder: CharsetEncoder = self.encoders[encoder_index];
+ return s.get_bytes(&encoder.charset());
+ }
+}
+
+// ECIStringBuilder.java
+/**
+ * Class that converts a sequence of ECIs and bytes into a string
+ *
+ * @author Alex Geller
+ */
+pub struct ECIStringBuilder {
+
+ let current_bytes: StringBuilder;
+
+ let mut result: StringBuilder;
+
+ let current_charset: Charset = StandardCharsets::ISO_8859_1;
+}
+
+impl ECIStringBuilder {
+
+ pub fn new() -> ECIStringBuilder {
+ current_bytes = StringBuilder::new();
+ }
+
+ pub fn new( initial_capacity: i32) -> ECIStringBuilder {
+ current_bytes = StringBuilder::new(initial_capacity);
+ }
+
+ /**
+ * Appends {@code value} as a byte value
+ *
+ * @param value character whose lowest byte is to be appended
+ */
+ pub fn append(&self, value: char) {
+ self.current_bytes.append((value & 0xff) as char);
+ }
+
+ /**
+ * Appends {@code value} as a byte value
+ *
+ * @param value byte to append
+ */
+ pub fn append(&self, value: i8) {
+ self.current_bytes.append((value & 0xff) as char);
+ }
+
+ /**
+ * Appends the characters in {@code value} as bytes values
+ *
+ * @param value string to append
+ */
+ pub fn append(&self, value: &String) {
+ self.current_bytes.append(&value);
+ }
+
+ /**
+ * Append the string repesentation of {@code value} (short for {@code append(String.valueOf(value))})
+ *
+ * @param value int to append as a string
+ */
+ pub fn append(&self, value: i32) {
+ self.append(&String::value_of(value));
+ }
+
+ /**
+ * Appends ECI value to output.
+ *
+ * @param value ECI value to append, as an int
+ * @throws FormatException on invalid ECI value
+ */
+ pub fn append_e_c_i(&self, value: i32) -> /* throws FormatException */Result> {
+ self.encode_current_bytes_if_any();
+ let character_set_e_c_i: CharacterSetECI = CharacterSetECI::get_character_set_e_c_i_by_value(value);
+ if character_set_e_c_i == null {
+ throw FormatException::get_format_instance();
+ }
+ self.current_charset = character_set_e_c_i.get_charset();
+ }
+
+ fn encode_current_bytes_if_any(&self) {
+ if self.current_charset.equals(StandardCharsets::ISO_8859_1) {
+ if self.current_bytes.length() > 0 {
+ if self.result == null {
+ self.result = self.current_bytes;
+ self.current_bytes = StringBuilder::new();
+ } else {
+ self.result.append(&self.current_bytes);
+ self.current_bytes = StringBuilder::new();
+ }
+ }
+ } else if self.current_bytes.length() > 0 {
+ let bytes: Vec = self.current_bytes.to_string().get_bytes(StandardCharsets::ISO_8859_1);
+ self.current_bytes = StringBuilder::new();
+ if self.result == null {
+ self.result = StringBuilder::new(String::new(&bytes, &self.current_charset));
+ } else {
+ self.result.append(String::new(&bytes, &self.current_charset));
+ }
+ }
+ }
+
+ /**
+ * Appends the characters from {@code value} (unlike all other append methods of this class who append bytes)
+ *
+ * @param value characters to append
+ */
+ pub fn append_characters(&self, value: &StringBuilder) {
+ self.encode_current_bytes_if_any();
+ self.result.append(&value);
+ }
+
+ /**
+ * Short for {@code toString().length()} (if possible, use {@link #isEmpty()} instead)
+ *
+ * @return length of string representation in characters
+ */
+ pub fn length(&self) -> i32 {
+ return self.to_string().length();
+ }
+
+ /**
+ * @return true iff nothing has been appended
+ */
+ pub fn is_empty(&self) -> bool {
+ return self.current_bytes.length() == 0 && (self.result == null || self.result.length() == 0);
+ }
+
+ pub fn to_string(&self) -> String {
+ self.encode_current_bytes_if_any();
+ return if self.result == null { "" } else { self.result.to_string() };
+ }
+}
+
+
+// HybridBinarizer.java
+/**
+ * This class implements a local thresholding algorithm, which while slower than the
+ * GlobalHistogramBinarizer, is fairly efficient for what it does. It is designed for
+ * high frequency images of barcodes with black data on white backgrounds. For this application,
+ * it does a much better job than a global blackpoint with severe shadows and gradients.
+ * However it tends to produce artifacts on lower frequency images and is therefore not
+ * a good general purpose binarizer for uses outside ZXing.
+ *
+ * This class extends GlobalHistogramBinarizer, using the older histogram approach for 1D readers,
+ * and the newer local approach for 2D readers. 1D decoding using a per-row histogram is already
+ * inherently local, and only fails for horizontal gradients. We can revisit that problem later,
+ * but for now it was not a win to use local blocks for 1D.
+ *
+ * This Binarizer is the default for the unit tests and the recommended class for library users.
+ *
+ * @author dswitkin@google.com (Daniel Switkin)
+ */
+
+// This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels.
+// So this is the smallest dimension in each axis we can accept.
+const BLOCK_SIZE_POWER: i32 = 3;
+
+// ...0100...00
+ const BLOCK_SIZE: i32 = 1 << BLOCK_SIZE_POWER;
+
+// ...0011...11
+ const BLOCK_SIZE_MASK: i32 = BLOCK_SIZE - 1;
+
+ const MINIMUM_DIMENSION: i32 = BLOCK_SIZE * 5;
+
+ const MIN_DYNAMIC_RANGE: i32 = 24;
+pub struct HybridBinarizer {
+ super: GlobalHistogramBinarizer;
+
+ let mut matrix: BitMatrix;
+}
+
+impl GlobalHistogramBinarizer for HybridBinarizer{
+ /**
+ * Calculates the final BitMatrix once for all requests. This could be called once from the
+ * constructor instead, but there are some advantages to doing it lazily, such as making
+ * profiling easier, and not doing heavy lifting when callers don't expect it.
+ */
+ pub fn get_black_matrix(&self) -> /* throws NotFoundException */Result> {
+ if self.matrix != null {
+ return Ok(self.matrix);
+ }
+ let source: LuminanceSource = get_luminance_source();
+ let width: i32 = source.get_width();
+ let height: i32 = source.get_height();
+ if width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION {
+ let luminances: Vec = source.get_matrix();
+ let sub_width: i32 = width >> BLOCK_SIZE_POWER;
+ if (width & BLOCK_SIZE_MASK) != 0 {
+ sub_width += 1;
+ }
+ let sub_height: i32 = height >> BLOCK_SIZE_POWER;
+ if (height & BLOCK_SIZE_MASK) != 0 {
+ sub_height += 1;
+ }
+ let black_points: Vec> = ::calculate_black_points(&luminances, sub_width, sub_height, width, height);
+ let new_matrix: BitMatrix = BitMatrix::new(width, height);
+ ::calculate_threshold_for_block(&luminances, sub_width, sub_height, width, height, &black_points, new_matrix);
+ self.matrix = new_matrix;
+ } else {
+ // If the image is too small, fall back to the global histogram approach.
+ self.matrix = super.get_black_matrix();
+ }
+ return Ok(self.matrix);
+}
+
+pub fn create_binarizer(&self, source: &LuminanceSource) -> Binarizer {
+ return HybridBinarizer::new(source);
+}
+}
+
+impl HybridBinarizer {
+
+ pub fn new( source: &LuminanceSource) -> HybridBinarizer {
+ super(source);
+ }
+
+
+
+ /**
+ * For each block in the image, calculate the average black point using a 5x5 grid
+ * of the blocks around it. Also handles the corner cases (fractional blocks are computed based
+ * on the last pixels in the row/column which are also used in the previous block).
+ */
+ fn calculate_threshold_for_block( luminances: &Vec, sub_width: i32, sub_height: i32, width: i32, height: i32, black_points: &Vec>, matrix: &BitMatrix) {
+ let max_y_offset: i32 = height - BLOCK_SIZE;
+ let max_x_offset: i32 = width - BLOCK_SIZE;
+ {
+ let mut y: i32 = 0;
+ while y < sub_height {
+ {
+ let mut yoffset: i32 = y << BLOCK_SIZE_POWER;
+ if yoffset > max_y_offset {
+ yoffset = max_y_offset;
+ }
+ let top: i32 = ::cap(y, sub_height - 3);
+ {
+ let mut x: i32 = 0;
+ while x < sub_width {
+ {
+ let mut xoffset: i32 = x << BLOCK_SIZE_POWER;
+ if xoffset > max_x_offset {
+ xoffset = max_x_offset;
+ }
+ let left: i32 = ::cap(x, sub_width - 3);
+ let mut sum: i32 = 0;
+ {
+ let mut z: i32 = -2;
+ while z <= 2 {
+ {
+ let black_row: Vec = black_points[top + z];
+ sum += black_row[left - 2] + black_row[left - 1] + black_row[left] + black_row[left + 1] + black_row[left + 2];
+ }
+ z += 1;
+ }
+ }
+
+ let average: i32 = sum / 25;
+ ::threshold_block(&luminances, xoffset, yoffset, average, width, matrix);
+ }
+ x += 1;
+ }
+ }
+
+ }
+ y += 1;
+ }
+ }
+
+ }
+
+ fn cap( value: i32, max: i32) -> i32 {
+ return if value < 2 { 2 } else { Math::min(value, max) };
+ }
+
+ /**
+ * Applies a single threshold to a block of pixels.
+ */
+ fn threshold_block( luminances: &Vec, xoffset: i32, yoffset: i32, threshold: i32, stride: i32, matrix: &BitMatrix) {
+ {
+ let mut y: i32 = 0, let mut offset: i32 = yoffset * stride + xoffset;
+ while y < BLOCK_SIZE {
+ {
+ {
+ let mut x: i32 = 0;
+ while x < BLOCK_SIZE {
+ {
+ // Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0.
+ if (luminances[offset + x] & 0xFF) <= threshold {
+ matrix.set(xoffset + x, yoffset + y);
+ }
+ }
+ x += 1;
+ }
+ }
+
+ }
+ y += 1;
+ offset += stride;
+ }
+ }
+
+ }
+
+ /**
+ * Calculates a single black point for each block of pixels and saves it away.
+ * See the following thread for a discussion of this algorithm:
+ * http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0
+ */
+ fn calculate_black_points( luminances: &Vec, sub_width: i32, sub_height: i32, width: i32, height: i32) -> Vec> {
+ let max_y_offset: i32 = height - BLOCK_SIZE;
+ let max_x_offset: i32 = width - BLOCK_SIZE;
+ let black_points: [[i32; sub_width]; sub_height] = [[0; sub_width]; sub_height];
+ {
+ let mut y: i32 = 0;
+ while y < sub_height {
+ {
+ let mut yoffset: i32 = y << BLOCK_SIZE_POWER;
+ if yoffset > max_y_offset {
+ yoffset = max_y_offset;
+ }
+ {
+ let mut x: i32 = 0;
+ while x < sub_width {
+ {
+ let mut xoffset: i32 = x << BLOCK_SIZE_POWER;
+ if xoffset > max_x_offset {
+ xoffset = max_x_offset;
+ }
+ let mut sum: i32 = 0;
+ let mut min: i32 = 0xFF;
+ let mut max: i32 = 0;
+ {
+ let mut yy: i32 = 0, let mut offset: i32 = yoffset * width + xoffset;
+ while yy < BLOCK_SIZE {
+ {
+ {
+ let mut xx: i32 = 0;
+ while xx < BLOCK_SIZE {
+ {
+ let pixel: i32 = luminances[offset + xx] & 0xFF;
+ sum += pixel;
+ // still looking for good contrast
+ if pixel < min {
+ min = pixel;
+ }
+ if pixel > max {
+ max = pixel;
+ }
+ }
+ xx += 1;
+ }
+ }
+
+ // short-circuit min/max tests once dynamic range is met
+ if max - min > MIN_DYNAMIC_RANGE {
+ // finish the rest of the rows quickly
+ {
+ yy += 1;
+ offset += width;
+ while yy < BLOCK_SIZE {
+ {
+ {
+ let mut xx: i32 = 0;
+ while xx < BLOCK_SIZE {
+ {
+ sum += luminances[offset + xx] & 0xFF;
+ }
+ xx += 1;
+ }
+ }
+
+ }
+ yy += 1;
+ offset += width;
+ }
+ }
+
+ }
+ }
+ yy += 1;
+ offset += width;
+ }
+ }
+
+ // The default estimate is the average of the values in the block.
+ let mut average: i32 = sum >> (BLOCK_SIZE_POWER * 2);
+ if max - min <= MIN_DYNAMIC_RANGE {
+ // If variation within the block is low, assume this is a block with only light or only
+ // dark pixels. In that case we do not want to use the average, as it would divide this
+ // low contrast area into black and white pixels, essentially creating data out of noise.
+ //
+ // The default assumption is that the block is light/background. Since no estimate for
+ // the level of dark pixels exists locally, use half the min for the block.
+ average = min / 2;
+ if y > 0 && x > 0 {
+ // Correct the "white background" assumption for blocks that have neighbors by comparing
+ // the pixels in this block to the previously calculated black points. This is based on
+ // the fact that dark barcode symbology is always surrounded by some amount of light
+ // background for which reasonable black point estimates were made. The bp estimated at
+ // the boundaries is used for the interior.
+ // The (min < bp) is arbitrary but works better than other heuristics that were tried.
+ let average_neighbor_black_point: i32 = (black_points[y - 1][x] + (2 * black_points[y][x - 1]) + black_points[y - 1][x - 1]) / 4;
+ if min < average_neighbor_black_point {
+ average = average_neighbor_black_point;
+ }
+ }
+ }
+ black_points[y][x] = average;
+ }
+ x += 1;
+ }
+ }
+
+ }
+ y += 1;
+ }
+ }
+
+ return black_points;
+ }
+}
+
+// MinimalECIInput.java
+/**
+ * Class that converts a character string into a sequence of ECIs and bytes
+ *
+ * The implementation uses the Dijkstra algorithm to produce minimal encodings
+ *
+ * @author Alex Geller
+ */
+
+// approximated (latch + 2 codewords)
+const COST_PER_ECI: i32 = 3;
+pub struct MinimalECIInput {
+
+ let mut bytes: Vec;
+
+ let fnc1: i32;
+}
+
+impl ECIInput for MinimalECIInput{
+ pub fn have_n_characters(&self, index: i32, n: i32) -> bool {
+ if index + n - 1 >= self.bytes.len() {
+ return false;
+ }
+ {
+ let mut i: i32 = 0;
+ while i < n {
+ {
+ if self.is_e_c_i(index + i) {
+ return false;
+ }
+ }
+ i += 1;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the {@code int} ECI value at the specified index. An index ranges from zero
+ * to {@code length() - 1}. The first {@code byte} value of the sequence is at
+ * index zero, the next at index one, and so on, as for array
+ * indexing.
+ *
+ * @param index the index of the {@code int} value to be returned
+ *
+ * @return the specified {@code int} ECI value.
+ * The ECI specified the encoding of all bytes with a higher index until the
+ * next ECI or until the end of the input if no other ECI follows.
+ *
+ * @throws IndexOutOfBoundsException
+ * if the {@code index} argument is negative or not less than
+ * {@code length()}
+ * @throws IllegalArgumentException
+ * if the value at the {@code index} argument is not an ECI (@see #isECI)
+ */
+ pub fn get_e_c_i_value(&self, index: i32) -> i32 {
+ if index < 0 || index >= self.length() {
+ throw IndexOutOfBoundsException::new(format!("{}", index));
+ }
+ if !self.is_e_c_i(index) {
+ throw IllegalArgumentException::new(format!("value at {} is not an ECI but a character", index));
+ }
+ return self.bytes[index] - 256;
+}
+
+/**
+ * Determines if a value is an ECI
+ *
+ * @param index the index of the value
+ *
+ * @return true if the value at position {@code index} is an ECI
+ *
+ * @throws IndexOutOfBoundsException
+ * if the {@code index} argument is negative or not less than
+ * {@code length()}
+ */
+ pub fn is_e_c_i(&self, index: i32) -> bool {
+ if index < 0 || index >= self.length() {
+ throw IndexOutOfBoundsException::new(format!("{}", index));
+ }
+ return self.bytes[index] > 255 && self.bytes[index] <= 999;
+}
+
+/**
+ * Returns a {@code CharSequence} that is a subsequence of this sequence.
+ * The subsequence starts with the {@code char} value at the specified index and
+ * ends with the {@code char} value at index {@code end - 1}. The length
+ * (in {@code char}s) of the
+ * returned sequence is {@code end - start}, so if {@code start == end}
+ * then an empty sequence is returned.
+ *
+ * @param start the start index, inclusive
+ * @param end the end index, exclusive
+ *
+ * @return the specified subsequence
+ *
+ * @throws IndexOutOfBoundsException
+ * if {@code start} or {@code end} are negative,
+ * if {@code end} is greater than {@code length()},
+ * or if {@code start} is greater than {@code end}
+ * @throws IllegalArgumentException
+ * if a value in the range {@code start}-{@code end} is an ECI (@see #isECI)
+ */
+ pub fn sub_sequence(&self, start: i32, end: i32) -> CharSequence {
+ if start < 0 || start > end || end > self.length() {
+ throw IndexOutOfBoundsException::new(format!("{}", start));
+ }
+ let result: StringBuilder = StringBuilder::new();
+ {
+ let mut i: i32 = start;
+ while i < end {
+ {
+ if self.is_e_c_i(i) {
+ throw IllegalArgumentException::new(format!("value at {} is not a character but an ECI", i));
+ }
+ result.append(&self.char_at(i));
+ }
+ i += 1;
+ }
+ }
+
+ return result;
+}
+
+/**
+ * Returns the {@code byte} value at the specified index. An index ranges from zero
+ * to {@code length() - 1}. The first {@code byte} value of the sequence is at
+ * index zero, the next at index one, and so on, as for array
+ * indexing.
+ *
+ * @param index the index of the {@code byte} value to be returned
+ *
+ * @return the specified {@code byte} value as character or the FNC1 character
+ *
+ * @throws IndexOutOfBoundsException
+ * if the {@code index} argument is negative or not less than
+ * {@code length()}
+ * @throws IllegalArgumentException
+ * if the value at the {@code index} argument is an ECI (@see #isECI)
+ */
+ pub fn char_at(&self, index: i32) -> char {
+ if index < 0 || index >= self.length() {
+ throw IndexOutOfBoundsException::new(format!("{}", index));
+ }
+ if self.is_e_c_i(index) {
+ throw IllegalArgumentException::new(format!("value at {} is not a character but an ECI", index));
+ }
+ return if self.is_f_n_c1(index) { self.fnc1 as char } else { self.bytes[index] as char };
+}
+
+/**
+ * Returns the length of this input. The length is the number
+ * of {@code byte}s, FNC1 characters or ECIs in the sequence.
+ *
+ * @return the number of {@code char}s in this sequence
+ */
+ pub fn length(&self) -> i32 {
+ return self.bytes.len();
+}
+
+
+}
+
+impl MinimalECIInput {
+
+ /**
+ * Constructs a minimal input
+ *
+ * @param stringToEncode the character string to encode
+ * @param priorityCharset The preferred {@link Charset}. When the value of the argument is null, the algorithm
+ * chooses charsets that leads to a minimal representation. Otherwise the algorithm will use the priority
+ * charset to encode any character in the input that can be encoded by it if the charset is among the
+ * supported charsets.
+ * @param fnc1 denotes the character in the input that represents the FNC1 character or -1 if this is not GS1
+ * input.
+ */
+ pub fn new( string_to_encode: &String, priority_charset: &Charset, fnc1: i32) -> MinimalECIInput {
+ let .fnc1 = fnc1;
+ let encoder_set: ECIEncoderSet = ECIEncoderSet::new(&string_to_encode, &priority_charset, fnc1);
+ if encoder_set.length() == 1 {
+ //optimization for the case when all can be encoded without ECI in ISO-8859-1
+ bytes = : [i32; string_to_encode.length()] = [0; string_to_encode.length()];
+ {
+ let mut i: i32 = 0;
+ while i < bytes.len() {
+ {
+ let c: char = string_to_encode.char_at(i);
+ bytes[i] = if c == fnc1 { 1000 } else { c as i32 };
+ }
+ i += 1;
+ }
+ }
+
+ } else {
+ bytes = ::encode_minimally(&string_to_encode, encoder_set, fnc1);
+ }
+ }
+
+ pub fn get_f_n_c1_character(&self) -> i32 {
+ return self.fnc1;
+ }
+
+
+
+
+
+
+
+
+
+
+ /**
+ * Determines if a value is the FNC1 character
+ *
+ * @param index the index of the value
+ *
+ * @return true if the value at position {@code index} is the FNC1 character
+ *
+ * @throws IndexOutOfBoundsException
+ * if the {@code index} argument is negative or not less than
+ * {@code length()}
+ */
+ pub fn is_f_n_c1(&self, index: i32) -> bool {
+ if index < 0 || index >= self.length() {
+ throw IndexOutOfBoundsException::new(format!("{}", index));
+ }
+ return self.bytes[index] == 1000;
+ }
+
+
+
+ pub fn to_string(&self) -> String {
+ let result: StringBuilder = StringBuilder::new();
+ {
+ let mut i: i32 = 0;
+ while i < self.length() {
+ {
+ if i > 0 {
+ result.append(", ");
+ }
+ if self.is_e_c_i(i) {
+ result.append("ECI(");
+ result.append(&self.get_e_c_i_value(i));
+ result.append(')');
+ } else if self.char_at(i) < 128 {
+ result.append('\'');
+ result.append(&self.char_at(i));
+ result.append('\'');
+ } else {
+ result.append(self.char_at(i) as i32);
+ }
+ }
+ i += 1;
+ }
+ }
+
+ return result.to_string();
+ }
+
+ fn add_edge( edges: &Vec>, to: i32, edge: &InputEdge) {
+ if edges[to][edge.encoderIndex] == null || edges[to][edge.encoderIndex].cachedTotalSize > edge.cachedTotalSize {
+ edges[to][edge.encoderIndex] = edge;
+ }
+ }
+
+ fn add_edges( string_to_encode: &String, encoder_set: &ECIEncoderSet, edges: &Vec>, from: i32, previous: &InputEdge, fnc1: i32) {
+ let ch: char = string_to_encode.char_at(from);
+ let mut start: i32 = 0;
+ let mut end: i32 = encoder_set.length();
+ if encoder_set.get_priority_encoder_index() >= 0 && (ch == fnc1 || encoder_set.can_encode(ch, &encoder_set.get_priority_encoder_index())) {
+ start = encoder_set.get_priority_encoder_index();
+ end = start + 1;
+ }
+ {
+ let mut i: i32 = start;
+ while i < end {
+ {
+ if ch == fnc1 || encoder_set.can_encode(ch, i) {
+ ::add_edge(edges, from + 1, InputEdge::new(ch, encoder_set, i, previous, fnc1));
+ }
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ fn encode_minimally( string_to_encode: &String, encoder_set: &ECIEncoderSet, fnc1: i32) -> Vec {
+ let input_length: i32 = string_to_encode.length();
+ // Array that represents vertices. There is a vertex for every character and encoding.
+ let mut edges: [[Option; encoder_set.length()]; input_length + 1] = [[None; encoder_set.length()]; input_length + 1];
+ ::add_edges(&string_to_encode, encoder_set, edges, 0, null, fnc1);
+ {
+ let mut i: i32 = 1;
+ while i <= input_length {
+ {
+ {
+ let mut j: i32 = 0;
+ while j < encoder_set.length() {
+ {
+ if edges[i][j] != null && i < input_length {
+ ::add_edges(&string_to_encode, encoder_set, edges, i, edges[i][j], fnc1);
+ }
+ }
+ j += 1;
+ }
+ }
+
+ //optimize memory by removing edges that have been passed.
+ {
+ let mut j: i32 = 0;
+ while j < encoder_set.length() {
+ {
+ edges[i - 1][j] = null;
+ }
+ j += 1;
+ }
+ }
+
+ }
+ i += 1;
+ }
+ }
+
+ let minimal_j: i32 = -1;
+ let minimal_size: i32 = Integer::MAX_VALUE;
+ {
+ let mut j: i32 = 0;
+ while j < encoder_set.length() {
+ {
+ if edges[input_length][j] != null {
+ let edge: InputEdge = edges[input_length][j];
+ if edge.cachedTotalSize < minimal_size {
+ minimal_size = edge.cachedTotalSize;
+ minimal_j = j;
+ }
+ }
+ }
+ j += 1;
+ }
+ }
+
+ if minimal_j < 0 {
+ throw RuntimeException::new(format!("Internal error: failed to encode \"{}\"", string_to_encode));
+ }
+ let ints_a_l: List = ArrayList<>::new();
+ let mut current: InputEdge = edges[input_length][minimal_j];
+ while current != null {
+ if current.is_f_n_c1() {
+ ints_a_l.add(0, 1000);
+ } else {
+ let bytes: Vec = encoder_set.encode(current.c, current.encoderIndex);
+ {
+ let mut i: i32 = bytes.len() - 1;
+ while i >= 0 {
+ {
+ ints_a_l.add(0, (bytes[i] & 0xFF));
+ }
+ i -= 1;
+ }
+ }
+
+ }
+ let previous_encoder_index: i32 = if current.previous == null { 0 } else { current.previous.encoderIndex };
+ if previous_encoder_index != current.encoderIndex {
+ ints_a_l.add(0, 256 + encoder_set.get_e_c_i_value(current.encoderIndex));
+ }
+ current = current.previous;
+ }
+ let mut ints: [i32; ints_a_l.size()] = [0; ints_a_l.size()];
+ {
+ let mut i: i32 = 0;
+ while i < ints.len() {
+ {
+ ints[i] = ints_a_l.get(i);
+ }
+ i += 1;
+ }
+ }
+
+ return ints;
+ }
+
+ struct InputEdge {
+
+ let c: char;
+
+ //the encoding of this edge
+ let encoder_index: i32;
+
+ let previous: InputEdge;
+
+ let cached_total_size: i32;
+ }
+
+ impl InputEdge {
+
+ fn new( c: char, encoder_set: &ECIEncoderSet, encoder_index: i32, previous: &InputEdge, fnc1: i32) -> InputEdge {
+ let .c = if c == fnc1 { 1000 } else { c };
+ let .encoderIndex = encoder_index;
+ let .previous = previous;
+ let mut size: i32 = if let .c == 1000 { 1 } else { encoder_set.encode(c, encoder_index).len() };
+ let previous_encoder_index: i32 = if previous == null { 0 } else { previous.encoderIndex };
+ if previous_encoder_index != encoder_index {
+ size += COST_PER_ECI;
+ }
+ if previous != null {
+ size += previous.cachedTotalSize;
+ }
+ let .cachedTotalSize = size;
+ }
+
+ fn is_f_n_c1(&self) -> bool {
+ return self.c == 1000;
+ }
+ }
+
+}
+
+// PerspectiveTransform.java
+/**
+ * This class implements a perspective transform in two dimensions. Given four source and four
+ * destination points, it will compute the transformation implied between them. The code is based
+ * directly upon section 3.4.2 of George Wolberg's "Digital Image Warping"; see pages 54-56.
+ *
+ * @author Sean Owen
+ */
+pub struct PerspectiveTransform {
+
+ let a11: f32;
+
+ let a12: f32;
+
+ let a13: f32;
+
+ let a21: f32;
+
+ let a22: f32;
+
+ let a23: f32;
+
+ let a31: f32;
+
+ let a32: f32;
+
+ let a33: f32;
+}
+
+impl PerspectiveTransform {
+
+ fn new( a11: f32, a21: f32, a31: f32, a12: f32, a22: f32, a32: f32, a13: f32, a23: f32, a33: f32) -> PerspectiveTransform {
+ let .a11 = a11;
+ let .a12 = a12;
+ let .a13 = a13;
+ let .a21 = a21;
+ let .a22 = a22;
+ let .a23 = a23;
+ let .a31 = a31;
+ let .a32 = a32;
+ let .a33 = a33;
+ }
+
+ pub fn quadrilateral_to_quadrilateral( x0: f32, y0: f32, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32, x0p: f32, y0p: f32, x1p: f32, y1p: f32, x2p: f32, y2p: f32, x3p: f32, y3p: f32) -> PerspectiveTransform {
+ let q_to_s: PerspectiveTransform = ::quadrilateral_to_square(x0, y0, x1, y1, x2, y2, x3, y3);
+ let s_to_q: PerspectiveTransform = ::square_to_quadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
+ return s_to_q.times(q_to_s);
+ }
+
+ pub fn transform_points(&self, points: &Vec) {
+ let a11: f32 = self.a11;
+ let a12: f32 = self.a12;
+ let a13: f32 = self.a13;
+ let a21: f32 = self.a21;
+ let a22: f32 = self.a22;
+ let a23: f32 = self.a23;
+ let a31: f32 = self.a31;
+ let a32: f32 = self.a32;
+ let a33: f32 = self.a33;
+ // points.length must be even
+ let max_i: i32 = points.len() - 1;
+ {
+ let mut i: i32 = 0;
+ while i < max_i {
+ {
+ let x: f32 = points[i];
+ let y: f32 = points[i + 1];
+ let denominator: f32 = a13 * x + a23 * y + a33;
+ points[i] = (a11 * x + a21 * y + a31) / denominator;
+ points[i + 1] = (a12 * x + a22 * y + a32) / denominator;
+ }
+ i += 2;
+ }
+ }
+
+ }
+
+ pub fn transform_points(&self, x_values: &Vec, y_values: &Vec) {
+ let n: i32 = x_values.len();
+ {
+ let mut i: i32 = 0;
+ while i < n {
+ {
+ let x: f32 = x_values[i];
+ let y: f32 = y_values[i];
+ let denominator: f32 = self.a13 * x + self.a23 * y + self.a33;
+ x_values[i] = (self.a11 * x + self.a21 * y + self.a31) / denominator;
+ y_values[i] = (self.a12 * x + self.a22 * y + self.a32) / denominator;
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ pub fn square_to_quadrilateral( x0: f32, y0: f32, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) -> PerspectiveTransform {
+ let dx3: f32 = x0 - x1 + x2 - x3;
+ let dy3: f32 = y0 - y1 + y2 - y3;
+ if dx3 == 0.0f && dy3 == 0.0f {
+ // Affine
+ return PerspectiveTransform::new(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0f, 0.0f, 1.0f);
+ } else {
+ let dx1: f32 = x1 - x2;
+ let dx2: f32 = x3 - x2;
+ let dy1: f32 = y1 - y2;
+ let dy2: f32 = y3 - y2;
+ let denominator: f32 = dx1 * dy2 - dx2 * dy1;
+ let a13: f32 = (dx3 * dy2 - dx2 * dy3) / denominator;
+ let a23: f32 = (dx1 * dy3 - dx3 * dy1) / denominator;
+ return PerspectiveTransform::new(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0f);
+ }
+ }
+
+ pub fn quadrilateral_to_square( x0: f32, y0: f32, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) -> PerspectiveTransform {
+ // Here, the adjoint serves as the inverse:
+ return ::square_to_quadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).build_adjoint();
+ }
+
+ fn build_adjoint(&self) -> PerspectiveTransform {
+ // Adjoint is the transpose of the cofactor matrix:
+ return PerspectiveTransform::new(self.a22 * self.a33 - self.a23 * self.a32, self.a23 * self.a31 - self.a21 * self.a33, self.a21 * self.a32 - self.a22 * self.a31, self.a13 * self.a32 - self.a12 * self.a33, self.a11 * self.a33 - self.a13 * self.a31, self.a12 * self.a31 - self.a11 * self.a32, self.a12 * self.a23 - self.a13 * self.a22, self.a13 * self.a21 - self.a11 * self.a23, self.a11 * self.a22 - self.a12 * self.a21);
+ }
+
+ fn times(&self, other: &PerspectiveTransform) -> PerspectiveTransform {
+ return PerspectiveTransform::new(self.a11 * other.a11 + self.a21 * other.a12 + self.a31 * other.a13, self.a11 * other.a21 + self.a21 * other.a22 + self.a31 * other.a23, self.a11 * other.a31 + self.a21 * other.a32 + self.a31 * other.a33, self.a12 * other.a11 + self.a22 * other.a12 + self.a32 * other.a13, self.a12 * other.a21 + self.a22 * other.a22 + self.a32 * other.a23, self.a12 * other.a31 + self.a22 * other.a32 + self.a32 * other.a33, self.a13 * other.a11 + self.a23 * other.a12 + self.a33 * other.a13, self.a13 * other.a21 + self.a23 * other.a22 + self.a33 * other.a23, self.a13 * other.a31 + self.a23 * other.a32 + self.a33 * other.a33);
+ }
+}
+
+// StringUtils.java
+/**
+ * Common string-related functions.
+ *
+ * @author Sean Owen
+ * @author Alex Dupre
+ */
+
+const PLATFORM_DEFAULT_ENCODING: Charset = Charset::default_charset();
+
+const SHIFT_JIS_CHARSET: Charset = Charset::for_name("SJIS");
+
+const GB2312_CHARSET: Charset = Charset::for_name("GB2312");
+
+const EUC_JP: Charset = Charset::for_name("EUC_JP");
+
+const ASSUME_SHIFT_JIS: bool = SHIFT_JIS_CHARSET::equals(&PLATFORM_DEFAULT_ENCODING) || EUC_JP::equals(&PLATFORM_DEFAULT_ENCODING);
+
+// Retained for ABI compatibility with earlier versions
+const SHIFT_JIS: &'static str = "SJIS";
+
+const GB2312: &'static str = "GB2312";
+pub struct StringUtils {
+}
+
+impl StringUtils {
+
+ fn new() -> StringUtils {
+ }
+
+ /**
+ * @param bytes bytes encoding a string, whose encoding should be guessed
+ * @param hints decode hints if applicable
+ * @return name of guessed encoding; at the moment will only guess one of:
+ * "SJIS", "UTF8", "ISO8859_1", or the platform default encoding if none
+ * of these can possibly be correct
+ */
+ pub fn guess_encoding( bytes: &Vec, hints: &Map) -> String {
+ let c: Charset = ::guess_charset(&bytes, &hints);
+ if c == SHIFT_JIS_CHARSET {
+ return "SJIS";
+ } else if c == StandardCharsets::UTF_8 {
+ return "UTF8";
+ } else if c == StandardCharsets::ISO_8859_1 {
+ return "ISO8859_1";
+ }
+ return c.name();
+ }
+
+ /**
+ * @param bytes bytes encoding a string, whose encoding should be guessed
+ * @param hints decode hints if applicable
+ * @return Charset of guessed encoding; at the moment will only guess one of:
+ * {@link #SHIFT_JIS_CHARSET}, {@link StandardCharsets#UTF_8},
+ * {@link StandardCharsets#ISO_8859_1}, {@link StandardCharsets#UTF_16},
+ * or the platform default encoding if
+ * none of these can possibly be correct
+ */
+ pub fn guess_charset( bytes: &Vec, hints: &Map) -> Charset {
+ if hints != null && hints.contains_key(DecodeHintType::CHARACTER_SET) {
+ return Charset::for_name(&hints.get(DecodeHintType::CHARACTER_SET).to_string());
+ }
+ // First try UTF-16, assuming anything with its BOM is UTF-16
+ if bytes.len() > 2 && ((bytes[0] == 0xFE as i8 && bytes[1] == 0xFF as i8) || (bytes[0] == 0xFF as i8 && bytes[1] == 0xFE as i8)) {
+ return StandardCharsets::UTF_16;
+ }
+ // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS,
+ // which should be by far the most common encodings.
+ let length: i32 = bytes.len();
+ let can_be_i_s_o88591: bool = true;
+ let can_be_shift_j_i_s: bool = true;
+ let can_be_u_t_f8: bool = true;
+ let utf8_bytes_left: i32 = 0;
+ let utf2_bytes_chars: i32 = 0;
+ let utf3_bytes_chars: i32 = 0;
+ let utf4_bytes_chars: i32 = 0;
+ let sjis_bytes_left: i32 = 0;
+ let sjis_katakana_chars: i32 = 0;
+ let sjis_cur_katakana_word_length: i32 = 0;
+ let sjis_cur_double_bytes_word_length: i32 = 0;
+ let sjis_max_katakana_word_length: i32 = 0;
+ let sjis_max_double_bytes_word_length: i32 = 0;
+ let iso_high_other: i32 = 0;
+ let utf8bom: bool = bytes.len() > 3 && bytes[0] == 0xEF as i8 && bytes[1] == 0xBB as i8 && bytes[2] == 0xBF as i8;
+ {
+ let mut i: i32 = 0;
+ while i < length && (can_be_i_s_o88591 || can_be_shift_j_i_s || can_be_u_t_f8) {
+ {
+ let value: i32 = bytes[i] & 0xFF;
+ // UTF-8 stuff
+ if can_be_u_t_f8 {
+ if utf8_bytes_left > 0 {
+ if (value & 0x80) == 0 {
+ can_be_u_t_f8 = false;
+ } else {
+ utf8_bytes_left -= 1;
+ }
+ } else if (value & 0x80) != 0 {
+ if (value & 0x40) == 0 {
+ can_be_u_t_f8 = false;
+ } else {
+ utf8_bytes_left += 1;
+ if (value & 0x20) == 0 {
+ utf2_bytes_chars += 1;
+ } else {
+ utf8_bytes_left += 1;
+ if (value & 0x10) == 0 {
+ utf3_bytes_chars += 1;
+ } else {
+ utf8_bytes_left += 1;
+ if (value & 0x08) == 0 {
+ utf4_bytes_chars += 1;
+ } else {
+ can_be_u_t_f8 = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ // ISO-8859-1 stuff
+ if can_be_i_s_o88591 {
+ if value > 0x7F && value < 0xA0 {
+ can_be_i_s_o88591 = false;
+ } else if value > 0x9F && (value < 0xC0 || value == 0xD7 || value == 0xF7) {
+ iso_high_other += 1;
+ }
+ }
+ // Shift_JIS stuff
+ if can_be_shift_j_i_s {
+ if sjis_bytes_left > 0 {
+ if value < 0x40 || value == 0x7F || value > 0xFC {
+ can_be_shift_j_i_s = false;
+ } else {
+ sjis_bytes_left -= 1;
+ }
+ } else if value == 0x80 || value == 0xA0 || value > 0xEF {
+ can_be_shift_j_i_s = false;
+ } else if value > 0xA0 && value < 0xE0 {
+ sjis_katakana_chars += 1;
+ sjis_cur_double_bytes_word_length = 0;
+ sjis_cur_katakana_word_length += 1;
+ if sjis_cur_katakana_word_length > sjis_max_katakana_word_length {
+ sjis_max_katakana_word_length = sjis_cur_katakana_word_length;
+ }
+ } else if value > 0x7F {
+ sjis_bytes_left += 1;
+ //sjisDoubleBytesChars++;
+ sjis_cur_katakana_word_length = 0;
+ sjis_cur_double_bytes_word_length += 1;
+ if sjis_cur_double_bytes_word_length > sjis_max_double_bytes_word_length {
+ sjis_max_double_bytes_word_length = sjis_cur_double_bytes_word_length;
+ }
+ } else {
+ //sjisLowChars++;
+ sjis_cur_katakana_word_length = 0;
+ sjis_cur_double_bytes_word_length = 0;
+ }
+ }
+ }
+ i += 1;
+ }
+ }
+
+ if can_be_u_t_f8 && utf8_bytes_left > 0 {
+ can_be_u_t_f8 = false;
+ }
+ if can_be_shift_j_i_s && sjis_bytes_left > 0 {
+ can_be_shift_j_i_s = false;
+ }
+ // Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done
+ if can_be_u_t_f8 && (utf8bom || utf2_bytes_chars + utf3_bytes_chars + utf4_bytes_chars > 0) {
+ return StandardCharsets::UTF_8;
+ }
+ // Easy -- if assuming Shift_JIS or >= 3 valid consecutive not-ascii characters (and no evidence it can't be), done
+ if can_be_shift_j_i_s && (ASSUME_SHIFT_JIS || sjis_max_katakana_word_length >= 3 || sjis_max_double_bytes_word_length >= 3) {
+ return SHIFT_JIS_CHARSET;
+ }
+ // - then we conclude Shift_JIS, else ISO-8859-1
+ if can_be_i_s_o88591 && can_be_shift_j_i_s {
+ return if (sjis_max_katakana_word_length == 2 && sjis_katakana_chars == 2) || iso_high_other * 10 >= length { SHIFT_JIS_CHARSET } else { StandardCharsets::ISO_8859_1 };
+ }
+ // Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding
+ if can_be_i_s_o88591 {
+ return StandardCharsets::ISO_8859_1;
+ }
+ if can_be_shift_j_i_s {
+ return SHIFT_JIS_CHARSET;
+ }
+ if can_be_u_t_f8 {
+ return StandardCharsets::UTF_8;
+ }
+ // Otherwise, we take a wild guess with platform encoding
+ return PLATFORM_DEFAULT_ENCODING;
+ }
+}
+
diff --git a/src/common/detector.rs b/src/common/detector.rs
index e69de29..6e8d03f 100644
--- a/src/common/detector.rs
+++ b/src/common/detector.rs
@@ -0,0 +1,577 @@
+use crate::{NotFoundException,ResultPoint};
+use crate::common::{BitMatrix,BitMatrix};
+
+// MathUtils.java
+/**
+ * General math-related and numeric utility functions.
+ */
+pub struct MathUtils {
+}
+
+impl MathUtils {
+
+ fn new() -> MathUtils {
+ }
+
+ /**
+ * Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its
+ * argument to the nearest int, where x.5 rounds up to x+1. Semantics of this shortcut
+ * differ slightly from {@link Math#round(float)} in that half rounds down for negative
+ * values. -2.5 rounds to -3, not -2. For purposes here it makes no difference.
+ *
+ * @param d real value to round
+ * @return nearest {@code int}
+ */
+ pub fn round( d: f32) -> i32 {
+ return (d + ( if d < 0.0f { -0.5f } else { 0.5f })) as i32;
+ }
+
+ /**
+ * @param aX point A x coordinate
+ * @param aY point A y coordinate
+ * @param bX point B x coordinate
+ * @param bY point B y coordinate
+ * @return Euclidean distance between points A and B
+ */
+ pub fn distance( a_x: f32, a_y: f32, b_x: f32, b_y: f32) -> f32 {
+ let x_diff: f64 = a_x - b_x;
+ let y_diff: f64 = a_y - b_y;
+ return Math::sqrt(x_diff * x_diff + y_diff * y_diff) as f32;
+ }
+
+ /**
+ * @param aX point A x coordinate
+ * @param aY point A y coordinate
+ * @param bX point B x coordinate
+ * @param bY point B y coordinate
+ * @return Euclidean distance between points A and B
+ */
+ pub fn distance( a_x: i32, a_y: i32, b_x: i32, b_y: i32) -> f32 {
+ let x_diff: f64 = a_x - b_x;
+ let y_diff: f64 = a_y - b_y;
+ return Math::sqrt(x_diff * x_diff + y_diff * y_diff) as f32;
+ }
+
+ /**
+ * @param array values to sum
+ * @return sum of values in array
+ */
+ pub fn sum( array: &Vec) -> i32 {
+ let mut count: i32 = 0;
+ for let a: i32 in array {
+ count += a;
+ }
+ return count;
+ }
+}
+
+// MonochromeRectangleDetector.java
+/**
+ * A somewhat generic detector that looks for a barcode-like rectangular region within an image.
+ * It looks within a mostly white region of an image for a region of black and white, but mostly
+ * black. It returns the four corners of the region, as best it can determine.
+ *
+ * @author Sean Owen
+ * @deprecated without replacement since 3.3.0
+ */
+
+const MAX_MODULES: i32 = 32;
+#[deprecated]
+pub struct MonochromeRectangleDetector {
+
+ let image: BitMatrix;
+}
+
+impl MonochromeRectangleDetector {
+
+ pub fn new( image: &BitMatrix) -> MonochromeRectangleDetector {
+ let .image = image;
+ }
+
+ /**
+ * Detects a rectangular region of black and white -- mostly black -- with a region of mostly
+ * white, in an image.
+ *
+ * @return {@link ResultPoint}[] describing the corners of the rectangular region. The first and
+ * last points are opposed on the diagonal, as are the second and third. The first point will be
+ * the topmost point and the last, the bottommost. The second point will be leftmost and the
+ * third, the rightmost
+ * @throws NotFoundException if no Data Matrix Code can be found
+ */
+ pub fn detect(&self) -> /* throws NotFoundException */Result, Rc> {
+ let height: i32 = self.image.get_height();
+ let width: i32 = self.image.get_width();
+ let half_height: i32 = height / 2;
+ let half_width: i32 = width / 2;
+ let delta_y: i32 = Math::max(1, height / (MAX_MODULES * 8));
+ let delta_x: i32 = Math::max(1, width / (MAX_MODULES * 8));
+ let mut top: i32 = 0;
+ let mut bottom: i32 = height;
+ let mut left: i32 = 0;
+ let mut right: i32 = width;
+ let point_a: ResultPoint = self.find_corner_from_center(half_width, 0, left, right, half_height, -delta_y, top, bottom, half_width / 2);
+ top = point_a.get_y() as i32 - 1;
+ let point_b: ResultPoint = self.find_corner_from_center(half_width, -delta_x, left, right, half_height, 0, top, bottom, half_height / 2);
+ left = point_b.get_x() as i32 - 1;
+ let point_c: ResultPoint = self.find_corner_from_center(half_width, delta_x, left, right, half_height, 0, top, bottom, half_height / 2);
+ right = point_c.get_x() as i32 + 1;
+ let point_d: ResultPoint = self.find_corner_from_center(half_width, 0, left, right, half_height, delta_y, top, bottom, half_width / 2);
+ bottom = point_d.get_y() as i32 + 1;
+ // Go try to find point A again with better information -- might have been off at first.
+ point_a = self.find_corner_from_center(half_width, 0, left, right, half_height, -delta_y, top, bottom, half_width / 4);
+ return Ok( : vec![ResultPoint; 4] = vec![point_a, point_b, point_c, point_d, ]
+ );
+ }
+
+ /**
+ * Attempts to locate a corner of the barcode by scanning up, down, left or right from a center
+ * point which should be within the barcode.
+ *
+ * @param centerX center's x component (horizontal)
+ * @param deltaX same as deltaY but change in x per step instead
+ * @param left minimum value of x
+ * @param right maximum value of x
+ * @param centerY center's y component (vertical)
+ * @param deltaY change in y per step. If scanning up this is negative; down, positive;
+ * left or right, 0
+ * @param top minimum value of y to search through (meaningless when di == 0)
+ * @param bottom maximum value of y
+ * @param maxWhiteRun maximum run of white pixels that can still be considered to be within
+ * the barcode
+ * @return a {@link ResultPoint} encapsulating the corner that was found
+ * @throws NotFoundException if such a point cannot be found
+ */
+ fn find_corner_from_center(&self, center_x: i32, delta_x: i32, left: i32, right: i32, center_y: i32, delta_y: i32, top: i32, bottom: i32, max_white_run: i32) -> /* throws NotFoundException */Result> {
+ let last_range: Vec = null;
+ {
+ let mut y: i32 = center_y, let mut x: i32 = center_x;
+ while y < bottom && y >= top && x < right && x >= left {
+ {
+ let mut range: Vec;
+ if delta_x == 0 {
+ // horizontal slices, up and down
+ range = self.black_white_range(y, max_white_run, left, right, true);
+ } else {
+ // vertical slices, left and right
+ range = self.black_white_range(x, max_white_run, top, bottom, false);
+ }
+ if range == null {
+ if last_range == null {
+ throw NotFoundException::get_not_found_instance();
+ }
+ // lastRange was found
+ if delta_x == 0 {
+ let last_y: i32 = y - delta_y;
+ if last_range[0] < center_x {
+ if last_range[1] > center_x {
+ // straddle, choose one or the other based on direction
+ return Ok(ResultPoint::new(last_range[ if delta_y > 0 { 0 } else { 1 }], last_y));
+ }
+ return Ok(ResultPoint::new(last_range[0], last_y));
+ } else {
+ return Ok(ResultPoint::new(last_range[1], last_y));
+ }
+ } else {
+ let last_x: i32 = x - delta_x;
+ if last_range[0] < center_y {
+ if last_range[1] > center_y {
+ return Ok(ResultPoint::new(last_x, last_range[ if delta_x < 0 { 0 } else { 1 }]));
+ }
+ return Ok(ResultPoint::new(last_x, last_range[0]));
+ } else {
+ return Ok(ResultPoint::new(last_x, last_range[1]));
+ }
+ }
+ }
+ last_range = range;
+ }
+ y += delta_y;
+ x += delta_x;
+ }
+ }
+
+ throw NotFoundException::get_not_found_instance();
+ }
+
+ /**
+ * Computes the start and end of a region of pixels, either horizontally or vertically, that could
+ * be part of a Data Matrix barcode.
+ *
+ * @param fixedDimension if scanning horizontally, this is the row (the fixed vertical location)
+ * where we are scanning. If scanning vertically it's the column, the fixed horizontal location
+ * @param maxWhiteRun largest run of white pixels that can still be considered part of the
+ * barcode region
+ * @param minDim minimum pixel location, horizontally or vertically, to consider
+ * @param maxDim maximum pixel location, horizontally or vertically, to consider
+ * @param horizontal if true, we're scanning left-right, instead of up-down
+ * @return int[] with start and end of found range, or null if no such range is found
+ * (e.g. only white was found)
+ */
+ fn black_white_range(&self, fixed_dimension: i32, max_white_run: i32, min_dim: i32, max_dim: i32, horizontal: bool) -> Vec {
+ let center: i32 = (min_dim + max_dim) / 2;
+ // Scan left/up first
+ let mut start: i32 = center;
+ while start >= min_dim {
+ if if horizontal { self.image.get(start, fixed_dimension) } else { self.image.get(fixed_dimension, start) } {
+ start -= 1;
+ } else {
+ let white_run_start: i32 = start;
+ loop { {
+ start -= 1;
+ }if !(start >= min_dim && !( if horizontal { self.image.get(start, fixed_dimension) } else { self.image.get(fixed_dimension, start) })) break;}
+ let white_run_size: i32 = white_run_start - start;
+ if start < min_dim || white_run_size > max_white_run {
+ start = white_run_start;
+ break;
+ }
+ }
+ }
+ start += 1;
+ // Then try right/down
+ let mut end: i32 = center;
+ while end < max_dim {
+ if if horizontal { self.image.get(end, fixed_dimension) } else { self.image.get(fixed_dimension, end) } {
+ end += 1;
+ } else {
+ let white_run_start: i32 = end;
+ loop { {
+ end += 1;
+ }if !(end < max_dim && !( if horizontal { self.image.get(end, fixed_dimension) } else { self.image.get(fixed_dimension, end) })) break;}
+ let white_run_size: i32 = end - white_run_start;
+ if end >= max_dim || white_run_size > max_white_run {
+ end = white_run_start;
+ break;
+ }
+ }
+ }
+ end -= 1;
+ return if end > start { : vec![i32; 2] = vec![start, end, ]
+ } else { null };
+ }
+}
+
+// WhiteRectangleDetector.java
+/**
+ *
+ * Detects a candidate barcode-like rectangular region within an image. It
+ * starts around the center of the image, increases the size of the candidate
+ * region until it finds a white rectangular region. By keeping track of the
+ * last black points it encountered, it determines the corners of the barcode.
+ *
+ *
+ * @author David Olivier
+ */
+
+const INIT_SIZE: i32 = 10;
+
+const CORR: i32 = 1;
+pub struct WhiteRectangleDetector {
+
+ let image: BitMatrix;
+
+ let mut height: i32;
+
+ let mut width: i32;
+
+ let left_init: i32;
+
+ let right_init: i32;
+
+ let down_init: i32;
+
+ let up_init: i32;
+}
+
+impl WhiteRectangleDetector {
+
+ pub fn new( image: &BitMatrix) -> WhiteRectangleDetector throws NotFoundException {
+ this(image, INIT_SIZE, image.get_width() / 2, image.get_height() / 2);
+ }
+
+ /**
+ * @param image barcode image to find a rectangle in
+ * @param initSize initial size of search area around center
+ * @param x x position of search center
+ * @param y y position of search center
+ * @throws NotFoundException if image is too small to accommodate {@code initSize}
+ */
+ pub fn new( image: &BitMatrix, init_size: i32, x: i32, y: i32) -> WhiteRectangleDetector throws NotFoundException {
+ let .image = image;
+ height = image.get_height();
+ width = image.get_width();
+ let halfsize: i32 = init_size / 2;
+ left_init = x - halfsize;
+ right_init = x + halfsize;
+ up_init = y - halfsize;
+ down_init = y + halfsize;
+ if up_init < 0 || left_init < 0 || down_init >= height || right_init >= width {
+ throw NotFoundException::get_not_found_instance();
+ }
+ }
+
+ /**
+ *
+ * Detects a candidate barcode-like rectangular region within an image. It
+ * starts around the center of the image, increases the size of the candidate
+ * region until it finds a white rectangular region.
+ *
+ *
+ * @return {@link ResultPoint}[] describing the corners of the rectangular
+ * region. The first and last points are opposed on the diagonal, as
+ * are the second and third. The first point will be the topmost
+ * point and the last, the bottommost. The second point will be
+ * leftmost and the third, the rightmost
+ * @throws NotFoundException if no Data Matrix Code can be found
+ */
+ pub fn detect(&self) -> /* throws NotFoundException */Result, Rc> {
+ let mut left: i32 = self.left_init;
+ let mut right: i32 = self.right_init;
+ let mut up: i32 = self.up_init;
+ let mut down: i32 = self.down_init;
+ let size_exceeded: bool = false;
+ let a_black_point_found_on_border: bool = true;
+ let at_least_one_black_point_found_on_right: bool = false;
+ let at_least_one_black_point_found_on_bottom: bool = false;
+ let at_least_one_black_point_found_on_left: bool = false;
+ let at_least_one_black_point_found_on_top: bool = false;
+ while a_black_point_found_on_border {
+ a_black_point_found_on_border = false;
+ // .....
+ // . |
+ // .....
+ let right_border_not_white: bool = true;
+ while (right_border_not_white || !at_least_one_black_point_found_on_right) && right < self.width {
+ right_border_not_white = self.contains_black_point(up, down, right, false);
+ if right_border_not_white {
+ right += 1;
+ a_black_point_found_on_border = true;
+ at_least_one_black_point_found_on_right = true;
+ } else if !at_least_one_black_point_found_on_right {
+ right += 1;
+ }
+ }
+ if right >= self.width {
+ size_exceeded = true;
+ break;
+ }
+ // .....
+ // . .
+ // .___.
+ let bottom_border_not_white: bool = true;
+ while (bottom_border_not_white || !at_least_one_black_point_found_on_bottom) && down < self.height {
+ bottom_border_not_white = self.contains_black_point(left, right, down, true);
+ if bottom_border_not_white {
+ down += 1;
+ a_black_point_found_on_border = true;
+ at_least_one_black_point_found_on_bottom = true;
+ } else if !at_least_one_black_point_found_on_bottom {
+ down += 1;
+ }
+ }
+ if down >= self.height {
+ size_exceeded = true;
+ break;
+ }
+ // .....
+ // | .
+ // .....
+ let left_border_not_white: bool = true;
+ while (left_border_not_white || !at_least_one_black_point_found_on_left) && left >= 0 {
+ left_border_not_white = self.contains_black_point(up, down, left, false);
+ if left_border_not_white {
+ left -= 1;
+ a_black_point_found_on_border = true;
+ at_least_one_black_point_found_on_left = true;
+ } else if !at_least_one_black_point_found_on_left {
+ left -= 1;
+ }
+ }
+ if left < 0 {
+ size_exceeded = true;
+ break;
+ }
+ // .___.
+ // . .
+ // .....
+ let top_border_not_white: bool = true;
+ while (top_border_not_white || !at_least_one_black_point_found_on_top) && up >= 0 {
+ top_border_not_white = self.contains_black_point(left, right, up, true);
+ if top_border_not_white {
+ up -= 1;
+ a_black_point_found_on_border = true;
+ at_least_one_black_point_found_on_top = true;
+ } else if !at_least_one_black_point_found_on_top {
+ up -= 1;
+ }
+ }
+ if up < 0 {
+ size_exceeded = true;
+ break;
+ }
+ }
+ if !size_exceeded {
+ let max_size: i32 = right - left;
+ let mut z: ResultPoint = null;
+ {
+ let mut i: i32 = 1;
+ while z == null && i < max_size {
+ {
+ z = self.get_black_point_on_segment(left, down - i, left + i, down);
+ }
+ i += 1;
+ }
+ }
+
+ if z == null {
+ throw NotFoundException::get_not_found_instance();
+ }
+ let mut t: ResultPoint = null;
+ //go down right
+ {
+ let mut i: i32 = 1;
+ while t == null && i < max_size {
+ {
+ t = self.get_black_point_on_segment(left, up + i, left + i, up);
+ }
+ i += 1;
+ }
+ }
+
+ if t == null {
+ throw NotFoundException::get_not_found_instance();
+ }
+ let mut x: ResultPoint = null;
+ //go down left
+ {
+ let mut i: i32 = 1;
+ while x == null && i < max_size {
+ {
+ x = self.get_black_point_on_segment(right, up + i, right - i, up);
+ }
+ i += 1;
+ }
+ }
+
+ if x == null {
+ throw NotFoundException::get_not_found_instance();
+ }
+ let mut y: ResultPoint = null;
+ //go up left
+ {
+ let mut i: i32 = 1;
+ while y == null && i < max_size {
+ {
+ y = self.get_black_point_on_segment(right, down - i, right - i, down);
+ }
+ i += 1;
+ }
+ }
+
+ if y == null {
+ throw NotFoundException::get_not_found_instance();
+ }
+ return Ok(self.center_edges(y, z, x, t));
+ } else {
+ throw NotFoundException::get_not_found_instance();
+ }
+ }
+
+ fn get_black_point_on_segment(&self, a_x: f32, a_y: f32, b_x: f32, b_y: f32) -> ResultPoint {
+ let dist: i32 = MathUtils::round(&MathUtils::distance(a_x, a_y, b_x, b_y));
+ let x_step: f32 = (b_x - a_x) / dist;
+ let y_step: f32 = (b_y - a_y) / dist;
+ {
+ let mut i: i32 = 0;
+ while i < dist {
+ {
+ let x: i32 = MathUtils::round(a_x + i * x_step);
+ let y: i32 = MathUtils::round(a_y + i * y_step);
+ if self.image.get(x, y) {
+ return ResultPoint::new(x, y);
+ }
+ }
+ i += 1;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * recenters the points of a constant distance towards the center
+ *
+ * @param y bottom most point
+ * @param z left most point
+ * @param x right most point
+ * @param t top most point
+ * @return {@link ResultPoint}[] describing the corners of the rectangular
+ * region. The first and last points are opposed on the diagonal, as
+ * are the second and third. The first point will be the topmost
+ * point and the last, the bottommost. The second point will be
+ * leftmost and the third, the rightmost
+ */
+ fn center_edges(&self, y: &ResultPoint, z: &ResultPoint, x: &ResultPoint, t: &ResultPoint) -> Vec {
+ //
+ // t t
+ // z x
+ // x OR z
+ // y y
+ //
+ let yi: f32 = y.get_x();
+ let yj: f32 = y.get_y();
+ let zi: f32 = z.get_x();
+ let zj: f32 = z.get_y();
+ let xi: f32 = x.get_x();
+ let xj: f32 = x.get_y();
+ let ti: f32 = t.get_x();
+ let tj: f32 = t.get_y();
+ if yi < self.width / 2.0f {
+ return : vec![ResultPoint; 4] = vec![ResultPoint::new(ti - CORR, tj + CORR), ResultPoint::new(zi + CORR, zj + CORR), ResultPoint::new(xi - CORR, xj - CORR), ResultPoint::new(yi + CORR, yj - CORR), ]
+ ;
+ } else {
+ return : vec![ResultPoint; 4] = vec![ResultPoint::new(ti + CORR, tj + CORR), ResultPoint::new(zi + CORR, zj - CORR), ResultPoint::new(xi - CORR, xj + CORR), ResultPoint::new(yi - CORR, yj - CORR), ]
+ ;
+ }
+ }
+
+ /**
+ * Determines whether a segment contains a black point
+ *
+ * @param a min value of the scanned coordinate
+ * @param b max value of the scanned coordinate
+ * @param fixed value of fixed coordinate
+ * @param horizontal set to true if scan must be horizontal, false if vertical
+ * @return true if a black point has been found, else false.
+ */
+ fn contains_black_point(&self, a: i32, b: i32, fixed: i32, horizontal: bool) -> bool {
+ if horizontal {
+ {
+ let mut x: i32 = a;
+ while x <= b {
+ {
+ if self.image.get(x, fixed) {
+ return true;
+ }
+ }
+ x += 1;
+ }
+ }
+
+ } else {
+ {
+ let mut y: i32 = a;
+ while y <= b {
+ {
+ if self.image.get(fixed, y) {
+ return true;
+ }
+ }
+ y += 1;
+ }
+ }
+
+ }
+ return false;
+ }
+}
+
diff --git a/src/common/readsolomon.rs b/src/common/readsolomon.rs
index e69de29..bfb8190 100644
--- a/src/common/readsolomon.rs
+++ b/src/common/readsolomon.rs
@@ -0,0 +1,776 @@
+// GenericGFPoly.java
+/**
+ * Represents a polynomial whose coefficients are elements of a GF.
+ * Instances of this class are immutable.
+ *
+ * Much credit is due to William Rucklidge since portions of this code are an indirect
+ * port of his C++ Reed-Solomon implementation.
+ *
+ * @author Sean Owen
+ */
+struct GenericGFPoly {
+
+ let field: GenericGF;
+
+ let coefficients: Vec;
+}
+
+impl GenericGFPoly {
+
+ /**
+ * @param field the {@link GenericGF} instance representing the field to use
+ * to perform computations
+ * @param coefficients coefficients as ints representing elements of GF(size), arranged
+ * from most significant (highest-power term) coefficient to least significant
+ * @throws IllegalArgumentException if argument is null or empty,
+ * or if leading coefficient is 0 and this is not a
+ * constant polynomial (that is, it is not the monomial "0")
+ */
+ fn new( field: &GenericGF, coefficients: &Vec) -> GenericGFPoly {
+ if coefficients.len() == 0 {
+ throw IllegalArgumentException::new();
+ }
+ let .field = field;
+ let coefficients_length: i32 = coefficients.len();
+ if coefficients_length > 1 && coefficients[0] == 0 {
+ // Leading term must be non-zero for anything except the constant polynomial "0"
+ let first_non_zero: i32 = 1;
+ while first_non_zero < coefficients_length && coefficients[first_non_zero] == 0 {
+ first_non_zero += 1;
+ }
+ if first_non_zero == coefficients_length {
+ let .coefficients = : vec![i32; 1] = vec![0, ]
+ ;
+ } else {
+ let .coefficients = : [i32; coefficients_length - first_non_zero] = [0; coefficients_length - first_non_zero];
+ System::arraycopy(&coefficients, first_non_zero, let .coefficients, 0, let .coefficients.len());
+ }
+ } else {
+ let .coefficients = coefficients;
+ }
+ }
+
+ fn get_coefficients(&self) -> Vec {
+ return self.coefficients;
+ }
+
+ /**
+ * @return degree of this polynomial
+ */
+ fn get_degree(&self) -> i32 {
+ return self.coefficients.len() - 1;
+ }
+
+ /**
+ * @return true iff this polynomial is the monomial "0"
+ */
+ fn is_zero(&self) -> bool {
+ return self.coefficients[0] == 0;
+ }
+
+ /**
+ * @return coefficient of x^degree term in this polynomial
+ */
+ fn get_coefficient(&self, degree: i32) -> i32 {
+ return self.coefficients[self.coefficients.len() - 1 - degree];
+ }
+
+ /**
+ * @return evaluation of this polynomial at a given point
+ */
+ fn evaluate_at(&self, a: i32) -> i32 {
+ if a == 0 {
+ // Just return the x^0 coefficient
+ return self.get_coefficient(0);
+ }
+ if a == 1 {
+ // Just the sum of the coefficients
+ let mut result: i32 = 0;
+ for let coefficient: i32 in self.coefficients {
+ result = GenericGF::add_or_subtract(result, coefficient);
+ }
+ return result;
+ }
+ let mut result: i32 = self.coefficients[0];
+ let size: i32 = self.coefficients.len();
+ {
+ let mut i: i32 = 1;
+ while i < size {
+ {
+ result = GenericGF::add_or_subtract(&self.field.multiply(a, result), self.coefficients[i]);
+ }
+ i += 1;
+ }
+ }
+
+ return result;
+ }
+
+ fn add_or_subtract(&self, other: &GenericGFPoly) -> GenericGFPoly {
+ if !self.field.equals(other.field) {
+ throw IllegalArgumentException::new("GenericGFPolys do not have same GenericGF field");
+ }
+ if self.is_zero() {
+ return other;
+ }
+ if other.is_zero() {
+ return self;
+ }
+ let smaller_coefficients: Vec = self.coefficients;
+ let larger_coefficients: Vec = other.coefficients;
+ if smaller_coefficients.len() > larger_coefficients.len() {
+ let temp: Vec = smaller_coefficients;
+ smaller_coefficients = larger_coefficients;
+ larger_coefficients = temp;
+ }
+ let sum_diff: [i32; larger_coefficients.len()] = [0; larger_coefficients.len()];
+ let length_diff: i32 = larger_coefficients.len() - smaller_coefficients.len();
+ // Copy high-order terms only found in higher-degree polynomial's coefficients
+ System::arraycopy(&larger_coefficients, 0, &sum_diff, 0, length_diff);
+ {
+ let mut i: i32 = length_diff;
+ while i < larger_coefficients.len() {
+ {
+ sum_diff[i] = GenericGF::add_or_subtract(smaller_coefficients[i - length_diff], larger_coefficients[i]);
+ }
+ i += 1;
+ }
+ }
+
+ return GenericGFPoly::new(self.field, &sum_diff);
+ }
+
+ fn multiply(&self, other: &GenericGFPoly) -> GenericGFPoly {
+ if !self.field.equals(other.field) {
+ throw IllegalArgumentException::new("GenericGFPolys do not have same GenericGF field");
+ }
+ if self.is_zero() || other.is_zero() {
+ return self.field.get_zero();
+ }
+ let a_coefficients: Vec = self.coefficients;
+ let a_length: i32 = a_coefficients.len();
+ let b_coefficients: Vec = other.coefficients;
+ let b_length: i32 = b_coefficients.len();
+ let mut product: [i32; a_length + b_length - 1] = [0; a_length + b_length - 1];
+ {
+ let mut i: i32 = 0;
+ while i < a_length {
+ {
+ let a_coeff: i32 = a_coefficients[i];
+ {
+ let mut j: i32 = 0;
+ while j < b_length {
+ {
+ product[i + j] = GenericGF::add_or_subtract(product[i + j], &self.field.multiply(a_coeff, b_coefficients[j]));
+ }
+ j += 1;
+ }
+ }
+
+ }
+ i += 1;
+ }
+ }
+
+ return GenericGFPoly::new(self.field, &product);
+ }
+
+ fn multiply(&self, scalar: i32) -> GenericGFPoly {
+ if scalar == 0 {
+ return self.field.get_zero();
+ }
+ if scalar == 1 {
+ return self;
+ }
+ let size: i32 = self.coefficients.len();
+ let mut product: [i32; size] = [0; size];
+ {
+ let mut i: i32 = 0;
+ while i < size {
+ {
+ product[i] = self.field.multiply(self.coefficients[i], scalar);
+ }
+ i += 1;
+ }
+ }
+
+ return GenericGFPoly::new(self.field, &product);
+ }
+
+ fn multiply_by_monomial(&self, degree: i32, coefficient: i32) -> GenericGFPoly {
+ if degree < 0 {
+ throw IllegalArgumentException::new();
+ }
+ if coefficient == 0 {
+ return self.field.get_zero();
+ }
+ let size: i32 = self.coefficients.len();
+ let mut product: [i32; size + degree] = [0; size + degree];
+ {
+ let mut i: i32 = 0;
+ while i < size {
+ {
+ product[i] = self.field.multiply(self.coefficients[i], coefficient);
+ }
+ i += 1;
+ }
+ }
+
+ return GenericGFPoly::new(self.field, &product);
+ }
+
+ fn divide(&self, other: &GenericGFPoly) -> Vec {
+ if !self.field.equals(other.field) {
+ throw IllegalArgumentException::new("GenericGFPolys do not have same GenericGF field");
+ }
+ if other.is_zero() {
+ throw IllegalArgumentException::new("Divide by 0");
+ }
+ let mut quotient: GenericGFPoly = self.field.get_zero();
+ let mut remainder: GenericGFPoly = self;
+ let denominator_leading_term: i32 = other.get_coefficient(&other.get_degree());
+ let inverse_denominator_leading_term: i32 = self.field.inverse(denominator_leading_term);
+ while remainder.get_degree() >= other.get_degree() && !remainder.is_zero() {
+ let degree_difference: i32 = remainder.get_degree() - other.get_degree();
+ let scale: i32 = self.field.multiply(&remainder.get_coefficient(&remainder.get_degree()), inverse_denominator_leading_term);
+ let term: GenericGFPoly = other.multiply_by_monomial(degree_difference, scale);
+ let iteration_quotient: GenericGFPoly = self.field.build_monomial(degree_difference, scale);
+ quotient = quotient.add_or_subtract(iteration_quotient);
+ remainder = remainder.add_or_subtract(term);
+ }
+ return : vec![GenericGFPoly; 2] = vec![quotient, remainder, ]
+ ;
+ }
+
+ pub fn to_string(&self) -> String {
+ if self.is_zero() {
+ return "0";
+ }
+ let result: StringBuilder = StringBuilder::new(8 * self.get_degree());
+ {
+ let mut degree: i32 = self.get_degree();
+ while degree >= 0 {
+ {
+ let mut coefficient: i32 = self.get_coefficient(degree);
+ if coefficient != 0 {
+ if coefficient < 0 {
+ if degree == self.get_degree() {
+ result.append("-");
+ } else {
+ result.append(" - ");
+ }
+ coefficient = -coefficient;
+ } else {
+ if result.length() > 0 {
+ result.append(" + ");
+ }
+ }
+ if degree == 0 || coefficient != 1 {
+ let alpha_power: i32 = self.field.log(coefficient);
+ if alpha_power == 0 {
+ result.append('1');
+ } else if alpha_power == 1 {
+ result.append('a');
+ } else {
+ result.append("a^");
+ result.append(alpha_power);
+ }
+ }
+ if degree != 0 {
+ if degree == 1 {
+ result.append('x');
+ } else {
+ result.append("x^");
+ result.append(degree);
+ }
+ }
+ }
+ }
+ degree -= 1;
+ }
+ }
+
+ return result.to_string();
+ }
+}
+
+// GenericGF.java
+/**
+ * This class contains utility methods for performing mathematical operations over
+ * the Galois Fields. Operations use a given primitive polynomial in calculations.
+ *
+ * Throughout this package, elements of the GF are represented as an {@code int}
+ * for convenience and speed (but at the cost of memory).
+ *
+ *
+ * @author Sean Owen
+ * @author David Olivier
+ */
+
+// x^12 + x^6 + x^5 + x^3 + 1
+const AZTEC_DATA_12: GenericGF = GenericGF::new(0x1069, 4096, 1);
+
+// x^10 + x^3 + 1
+ const AZTEC_DATA_10: GenericGF = GenericGF::new(0x409, 1024, 1);
+
+// x^6 + x + 1
+ const AZTEC_DATA_6: GenericGF = GenericGF::new(0x43, 64, 1);
+
+// x^4 + x + 1
+ const AZTEC_PARAM: GenericGF = GenericGF::new(0x13, 16, 1);
+
+// x^8 + x^4 + x^3 + x^2 + 1
+ const QR_CODE_FIELD_256: GenericGF = GenericGF::new(0x011D, 256, 0);
+
+// x^8 + x^5 + x^3 + x^2 + 1
+ const DATA_MATRIX_FIELD_256: GenericGF = GenericGF::new(0x012D, 256, 1);
+
+ const AZTEC_DATA_8: GenericGF = DATA_MATRIX_FIELD_256;
+
+ const MAXICODE_FIELD_64: GenericGF = AZTEC_DATA_6;
+pub struct GenericGF {
+
+ let exp_table: Vec;
+
+ let log_table: Vec;
+
+ let mut zero: GenericGFPoly;
+
+ let mut one: GenericGFPoly;
+
+ let size: i32;
+
+ let primitive: i32;
+
+ let generator_base: i32;
+}
+
+impl GenericGF {
+
+ /**
+ * Create a representation of GF(size) using the given primitive polynomial.
+ *
+ * @param primitive irreducible polynomial whose coefficients are represented by
+ * the bits of an int, where the least-significant bit represents the constant
+ * coefficient
+ * @param size the size of the field
+ * @param b the factor b in the generator polynomial can be 0- or 1-based
+ * (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).
+ * In most cases it should be 1, but for QR code it is 0.
+ */
+ pub fn new( primitive: i32, size: i32, b: i32) -> GenericGF {
+ let .primitive = primitive;
+ let .size = size;
+ let .generatorBase = b;
+ exp_table = : [i32; size] = [0; size];
+ log_table = : [i32; size] = [0; size];
+ let mut x: i32 = 1;
+ {
+ let mut i: i32 = 0;
+ while i < size {
+ {
+ exp_table[i] = x;
+ // we're assuming the generator alpha is 2
+ x *= 2;
+ if x >= size {
+ x ^= primitive;
+ x &= size - 1;
+ }
+ }
+ i += 1;
+ }
+ }
+
+ {
+ let mut i: i32 = 0;
+ while i < size - 1 {
+ {
+ log_table[exp_table[i]] = i;
+ }
+ i += 1;
+ }
+ }
+
+ // logTable[0] == 0 but this should never be used
+ zero = GenericGFPoly::new(let , : vec![i32; 1] = vec![0, ]
+ );
+ one = GenericGFPoly::new(let , : vec![i32; 1] = vec![1, ]
+ );
+ }
+
+ fn get_zero(&self) -> GenericGFPoly {
+ return self.zero;
+ }
+
+ fn get_one(&self) -> GenericGFPoly {
+ return self.one;
+ }
+
+ /**
+ * @return the monomial representing coefficient * x^degree
+ */
+ fn build_monomial(&self, degree: i32, coefficient: i32) -> GenericGFPoly {
+ if degree < 0 {
+ throw IllegalArgumentException::new();
+ }
+ if coefficient == 0 {
+ return self.zero;
+ }
+ let mut coefficients: [i32; degree + 1] = [0; degree + 1];
+ coefficients[0] = coefficient;
+ return GenericGFPoly::new(self, &coefficients);
+ }
+
+ /**
+ * Implements both addition and subtraction -- they are the same in GF(size).
+ *
+ * @return sum/difference of a and b
+ */
+ fn add_or_subtract( a: i32, b: i32) -> i32 {
+ return a ^ b;
+ }
+
+ /**
+ * @return 2 to the power of a in GF(size)
+ */
+ fn exp(&self, a: i32) -> i32 {
+ return self.exp_table[a];
+ }
+
+ /**
+ * @return base 2 log of a in GF(size)
+ */
+ fn log(&self, a: i32) -> i32 {
+ if a == 0 {
+ throw IllegalArgumentException::new();
+ }
+ return self.log_table[a];
+ }
+
+ /**
+ * @return multiplicative inverse of a
+ */
+ fn inverse(&self, a: i32) -> i32 {
+ if a == 0 {
+ throw ArithmeticException::new();
+ }
+ return self.exp_table[self.size - self.log_table[a] - 1];
+ }
+
+ /**
+ * @return product of a and b in GF(size)
+ */
+ fn multiply(&self, a: i32, b: i32) -> i32 {
+ if a == 0 || b == 0 {
+ return 0;
+ }
+ return self.exp_table[(self.log_table[a] + self.log_table[b]) % (self.size - 1)];
+ }
+
+ pub fn get_size(&self) -> i32 {
+ return self.size;
+ }
+
+ pub fn get_generator_base(&self) -> i32 {
+ return self.generator_base;
+ }
+
+ pub fn to_string(&self) -> String {
+ return format!("GF(0x{},{})", Integer::to_hex_string(self.primitive), self.size);
+ }
+}
+
+// ReedSolomonDecoder.java
+/**
+ * Implements Reed-Solomon decoding, as the name implies.
+ *
+ * The algorithm will not be explained here, but the following references were helpful
+ * in creating this implementation:
+ *
+ *
+ *
+ * Much credit is due to William Rucklidge since portions of this code are an indirect
+ * port of his C++ Reed-Solomon implementation.
+ *
+ * @author Sean Owen
+ * @author William Rucklidge
+ * @author sanfordsquires
+ */
+pub struct ReedSolomonDecoder {
+
+ let field: GenericGF;
+}
+
+impl ReedSolomonDecoder {
+
+ pub fn new( field: &GenericGF) -> ReedSolomonDecoder {
+ let .field = field;
+ }
+
+ /**
+ * Decodes given set of received codewords, which include both data and error-correction
+ * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,
+ * in the input.
+ *
+ * @param received data and error-correction codewords
+ * @param twoS number of error-correction codewords available
+ * @throws ReedSolomonException if decoding fails for any reason
+ */
+ pub fn decode(&self, received: &Vec, two_s: i32) -> /* throws ReedSolomonException */Result> {
+ let poly: GenericGFPoly = GenericGFPoly::new(self.field, &received);
+ let syndrome_coefficients: [i32; two_s] = [0; two_s];
+ let no_error: bool = true;
+ {
+ let mut i: i32 = 0;
+ while i < two_s {
+ {
+ let eval: i32 = poly.evaluate_at(&self.field.exp(i + self.field.get_generator_base()));
+ syndrome_coefficients[syndrome_coefficients.len() - 1 - i] = eval;
+ if eval != 0 {
+ no_error = false;
+ }
+ }
+ i += 1;
+ }
+ }
+
+ if no_error {
+ return;
+ }
+ let syndrome: GenericGFPoly = GenericGFPoly::new(self.field, &syndrome_coefficients);
+ let sigma_omega: Vec = self.run_euclidean_algorithm(&self.field.build_monomial(two_s, 1), syndrome, two_s);
+ let sigma: GenericGFPoly = sigma_omega[0];
+ let omega: GenericGFPoly = sigma_omega[1];
+ let error_locations: Vec = self.find_error_locations(sigma);
+ let error_magnitudes: Vec = self.find_error_magnitudes(omega, &error_locations);
+ {
+ let mut i: i32 = 0;
+ while i < error_locations.len() {
+ {
+ let mut position: i32 = received.len() - 1 - self.field.log(error_locations[i]);
+ if position < 0 {
+ throw ReedSolomonException::new("Bad error location");
+ }
+ received[position] = GenericGF::add_or_subtract(received[position], error_magnitudes[i]);
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ fn run_euclidean_algorithm(&self, a: &GenericGFPoly, b: &GenericGFPoly, R: i32) -> /* throws ReedSolomonException */Result, Rc> {
+ // Assume a's degree is >= b's
+ if a.get_degree() < b.get_degree() {
+ let temp: GenericGFPoly = a;
+ a = b;
+ b = temp;
+ }
+ let r_last: GenericGFPoly = a;
+ let mut r: GenericGFPoly = b;
+ let t_last: GenericGFPoly = self.field.get_zero();
+ let mut t: GenericGFPoly = self.field.get_one();
+ // Run Euclidean algorithm until r's degree is less than R/2
+ while 2 * r.get_degree() >= R {
+ let r_last_last: GenericGFPoly = r_last;
+ let t_last_last: GenericGFPoly = t_last;
+ r_last = r;
+ t_last = t;
+ // Divide rLastLast by rLast, with quotient in q and remainder in r
+ if r_last.is_zero() {
+ // Oops, Euclidean algorithm already terminated?
+ throw ReedSolomonException::new("r_{i-1} was zero");
+ }
+ r = r_last_last;
+ let mut q: GenericGFPoly = self.field.get_zero();
+ let denominator_leading_term: i32 = r_last.get_coefficient(&r_last.get_degree());
+ let dlt_inverse: i32 = self.field.inverse(denominator_leading_term);
+ while r.get_degree() >= r_last.get_degree() && !r.is_zero() {
+ let degree_diff: i32 = r.get_degree() - r_last.get_degree();
+ let scale: i32 = self.field.multiply(&r.get_coefficient(&r.get_degree()), dlt_inverse);
+ q = q.add_or_subtract(&self.field.build_monomial(degree_diff, scale));
+ r = r.add_or_subtract(&r_last.multiply_by_monomial(degree_diff, scale));
+ }
+ t = q.multiply(t_last).add_or_subtract(t_last_last);
+ if r.get_degree() >= r_last.get_degree() {
+ throw IllegalStateException::new(format!("Division algorithm failed to reduce polynomial? r: {}, rLast: {}", r, r_last));
+ }
+ }
+ let sigma_tilde_at_zero: i32 = t.get_coefficient(0);
+ if sigma_tilde_at_zero == 0 {
+ throw ReedSolomonException::new("sigmaTilde(0) was zero");
+ }
+ let inverse: i32 = self.field.inverse(sigma_tilde_at_zero);
+ let sigma: GenericGFPoly = t.multiply(inverse);
+ let omega: GenericGFPoly = r.multiply(inverse);
+ return Ok( : vec![GenericGFPoly; 2] = vec![sigma, omega, ]
+ );
+ }
+
+ fn find_error_locations(&self, error_locator: &GenericGFPoly) -> /* throws ReedSolomonException */Result, Rc> {
+ // This is a direct application of Chien's search
+ let num_errors: i32 = error_locator.get_degree();
+ if num_errors == 1 {
+ // shortcut
+ return Ok( : vec![i32; 1] = vec![error_locator.get_coefficient(1), ]
+ );
+ }
+ let mut result: [i32; num_errors] = [0; num_errors];
+ let mut e: i32 = 0;
+ {
+ let mut i: i32 = 1;
+ while i < self.field.get_size() && e < num_errors {
+ {
+ if error_locator.evaluate_at(i) == 0 {
+ result[e] = self.field.inverse(i);
+ e += 1;
+ }
+ }
+ i += 1;
+ }
+ }
+
+ if e != num_errors {
+ throw ReedSolomonException::new("Error locator degree does not match number of roots");
+ }
+ return Ok(result);
+ }
+
+ fn find_error_magnitudes(&self, error_evaluator: &GenericGFPoly, error_locations: &Vec) -> Vec {
+ // This is directly applying Forney's Formula
+ let s: i32 = error_locations.len();
+ let mut result: [i32; s] = [0; s];
+ {
+ let mut i: i32 = 0;
+ while i < s {
+ {
+ let xi_inverse: i32 = self.field.inverse(error_locations[i]);
+ let mut denominator: i32 = 1;
+ {
+ let mut j: i32 = 0;
+ while j < s {
+ {
+ if i != j {
+ //denominator = field.multiply(denominator,
+ // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)));
+ // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.
+ // Below is a funny-looking workaround from Steven Parkes
+ let term: i32 = self.field.multiply(error_locations[j], xi_inverse);
+ let term_plus1: i32 = if (term & 0x1) == 0 { term | 1 } else { term & ~1 };
+ denominator = self.field.multiply(denominator, term_plus1);
+ }
+ }
+ j += 1;
+ }
+ }
+
+ result[i] = self.field.multiply(&error_evaluator.evaluate_at(xi_inverse), &self.field.inverse(denominator));
+ if self.field.get_generator_base() != 0 {
+ result[i] = self.field.multiply(result[i], xi_inverse);
+ }
+ }
+ i += 1;
+ }
+ }
+
+ return result;
+ }
+}
+
+// ReedSolomonEncoder.java
+/**
+ * Implements Reed-Solomon encoding, as the name implies.
+ *
+ * @author Sean Owen
+ * @author William Rucklidge
+ */
+pub struct ReedSolomonEncoder {
+
+ let field: GenericGF;
+
+ let cached_generators: List;
+}
+
+impl ReedSolomonEncoder {
+
+ pub fn new( field: &GenericGF) -> ReedSolomonEncoder {
+ let .field = field;
+ let .cachedGenerators = ArrayList<>::new();
+ cached_generators.add(GenericGFPoly::new(field, : vec![i32; 1] = vec![1, ]
+ ));
+ }
+
+ fn build_generator(&self, degree: i32) -> GenericGFPoly {
+ if degree >= self.cached_generators.size() {
+ let last_generator: GenericGFPoly = self.cached_generators.get(self.cached_generators.size() - 1);
+ {
+ let mut d: i32 = self.cached_generators.size();
+ while d <= degree {
+ {
+ let next_generator: GenericGFPoly = last_generator.multiply(GenericGFPoly::new(self.field, : vec![i32; 2] = vec![1, self.field.exp(d - 1 + self.field.get_generator_base()), ]
+ ));
+ self.cached_generators.add(next_generator);
+ last_generator = next_generator;
+ }
+ d += 1;
+ }
+ }
+
+ }
+ return self.cached_generators.get(degree);
+ }
+
+ pub fn encode(&self, to_encode: &Vec, ec_bytes: i32) {
+ if ec_bytes == 0 {
+ throw IllegalArgumentException::new("No error correction bytes");
+ }
+ let data_bytes: i32 = to_encode.len() - ec_bytes;
+ if data_bytes <= 0 {
+ throw IllegalArgumentException::new("No data bytes provided");
+ }
+ let generator: GenericGFPoly = self.build_generator(ec_bytes);
+ let info_coefficients: [i32; data_bytes] = [0; data_bytes];
+ System::arraycopy(&to_encode, 0, &info_coefficients, 0, data_bytes);
+ let mut info: GenericGFPoly = GenericGFPoly::new(self.field, &info_coefficients);
+ info = info.multiply_by_monomial(ec_bytes, 1);
+ let remainder: GenericGFPoly = info.divide(generator)[1];
+ let coefficients: Vec = remainder.get_coefficients();
+ let num_zero_coefficients: i32 = ec_bytes - coefficients.len();
+ {
+ let mut i: i32 = 0;
+ while i < num_zero_coefficients {
+ {
+ to_encode[data_bytes + i] = 0;
+ }
+ i += 1;
+ }
+ }
+
+ System::arraycopy(&coefficients, 0, &to_encode, data_bytes + num_zero_coefficients, coefficients.len());
+ }
+}
+
+// ReedSolomonException.java
+/**
+ * Thrown when an exception occurs during Reed-Solomon decoding, such as when
+ * there are too many errors to correct.
+ *
+ * @author Sean Owen
+ */
+pub struct ReedSolomonException {
+ super: Exception;
+}
+
+impl ReedSolomonException {
+
+ pub fn new( message: &String) -> ReedSolomonException {
+ super(&message);
+ }
+}
\ No newline at end of file