From 328e691288430e93fcfbb893376c9e7b8a914d4a Mon Sep 17 00:00:00 2001 From: Henry Date: Fri, 12 Aug 2022 22:18:58 -0500 Subject: [PATCH] Migrate common errors all over --- .../zxing => DONE}/common/BitArray.java | 0 .../zxing => DONE}/common/BitMatrix.java | 0 .../zxing => DONE}/common/BitSource.java | 0 .../common/CharacterSetECI.java | 0 .../zxing => DONE}/common/DecoderResult.java | 0 .../common/DefaultGridSampler.java | 0 .../zxing => DONE}/common/DetectorResult.java | 0 .../zxing => DONE}/common/ECIEncoderSet.java | 0 .../zxing => DONE}/common/ECIInput.java | 0 .../common/ECIStringBuilder.java | 0 .../common/GlobalHistogramBinarizer.java | 0 .../zxing => DONE}/common/GridSampler.java | 0 .../common/HybridBinarizer.java | 0 .../common/MinimalECIInput.java | 0 .../common/PerspectiveTransform.java | 0 .../zxing => DONE}/common/StringUtils.java | 0 .../common/detector/MathUtils.java | 0 .../detector/MonochromeRectangleDetector.java | 0 .../detector/WhiteRectangleDetector.java | 0 .../common/reedsolomon/GenericGF.java | 0 .../common/reedsolomon/GenericGFPoly.java | 0 .../reedsolomon/ReedSolomonDecoder.java | 0 .../reedsolomon/ReedSolomonEncoder.java | 0 .../reedsolomon/ReedSolomonException.java | 0 port_src/output/zxing/common/bit_array.rs | 436 --- port_src/output/zxing/common/bit_matrix.rs | 652 ---- port_src/output/zxing/common/bit_source.rs | 110 - .../zxing/common/character_set_e_c_i.rs | 110 - .../output/zxing/common/decoder_result.rs | 168 - .../zxing/common/default_grid_sampler.rs | 92 - .../zxing/common/detector/math_utils.rs | 80 - .../detector/monochrome_rectangle_detector.rs | 200 - .../detector/white_rectangle_detector.rs | 341 -- .../output/zxing/common/detector_result.rs | 47 - .../output/zxing/common/e_c_i_encoder_set.rs | 194 - port_src/output/zxing/common/e_c_i_input.rs | 108 - .../zxing/common/e_c_i_string_builder.rs | 146 - .../common/global_histogram_binarizer.rs | 269 -- port_src/output/zxing/common/grid_sampler.rs | 175 - .../output/zxing/common/hybrid_binarizer.rs | 301 -- .../zxing/common/minimal_e_c_i_input.rs | 422 --- .../zxing/common/perspective_transform.rs | 144 - .../zxing/common/reedsolomon/generic_g_f.rs | 202 - .../common/reedsolomon/generic_g_f_poly.rs | 312 -- .../reedsolomon/reed_solomon_decoder.rs | 220 -- .../reedsolomon/reed_solomon_encoder.rs | 89 - .../reedsolomon/reed_solomon_exception.rs | 34 - port_src/output/zxing/common/string_utils.rs | 213 -- src/common.rs | 3359 +++++++++++++++++ src/common/detector.rs | 577 +++ src/common/readsolomon.rs | 776 ++++ 51 files changed, 4712 insertions(+), 5065 deletions(-) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/BitArray.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/BitMatrix.java (100%) mode change 100755 => 100644 rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/BitSource.java (100%) mode change 100755 => 100644 rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/CharacterSetECI.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/DecoderResult.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/DefaultGridSampler.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/DetectorResult.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/ECIEncoderSet.java (100%) mode change 100755 => 100644 rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/ECIInput.java (100%) mode change 100755 => 100644 rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/ECIStringBuilder.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/GlobalHistogramBinarizer.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/GridSampler.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/HybridBinarizer.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/MinimalECIInput.java (100%) mode change 100755 => 100644 rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/PerspectiveTransform.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/StringUtils.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/detector/MathUtils.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/detector/MonochromeRectangleDetector.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/detector/WhiteRectangleDetector.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/reedsolomon/GenericGF.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/reedsolomon/GenericGFPoly.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/reedsolomon/ReedSolomonDecoder.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/reedsolomon/ReedSolomonEncoder.java (100%) rename port_src/core/{src/main/java/com/google/zxing => DONE}/common/reedsolomon/ReedSolomonException.java (100%) delete mode 100644 port_src/output/zxing/common/bit_array.rs delete mode 100644 port_src/output/zxing/common/bit_matrix.rs delete mode 100644 port_src/output/zxing/common/bit_source.rs delete mode 100644 port_src/output/zxing/common/character_set_e_c_i.rs delete mode 100644 port_src/output/zxing/common/decoder_result.rs delete mode 100644 port_src/output/zxing/common/default_grid_sampler.rs delete mode 100644 port_src/output/zxing/common/detector/math_utils.rs delete mode 100644 port_src/output/zxing/common/detector/monochrome_rectangle_detector.rs delete mode 100644 port_src/output/zxing/common/detector/white_rectangle_detector.rs delete mode 100644 port_src/output/zxing/common/detector_result.rs delete mode 100644 port_src/output/zxing/common/e_c_i_encoder_set.rs delete mode 100644 port_src/output/zxing/common/e_c_i_input.rs delete mode 100644 port_src/output/zxing/common/e_c_i_string_builder.rs delete mode 100644 port_src/output/zxing/common/global_histogram_binarizer.rs delete mode 100644 port_src/output/zxing/common/grid_sampler.rs delete mode 100644 port_src/output/zxing/common/hybrid_binarizer.rs delete mode 100644 port_src/output/zxing/common/minimal_e_c_i_input.rs delete mode 100644 port_src/output/zxing/common/perspective_transform.rs delete mode 100644 port_src/output/zxing/common/reedsolomon/generic_g_f.rs delete mode 100644 port_src/output/zxing/common/reedsolomon/generic_g_f_poly.rs delete mode 100644 port_src/output/zxing/common/reedsolomon/reed_solomon_decoder.rs delete mode 100644 port_src/output/zxing/common/reedsolomon/reed_solomon_encoder.rs delete mode 100644 port_src/output/zxing/common/reedsolomon/reed_solomon_exception.rs delete mode 100644 port_src/output/zxing/common/string_utils.rs 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