diff --git a/port_src/output/zxing/aztec/aztec_detector_result.rs b/port_src/output/zxing/aztec/aztec_detector_result.rs
deleted file mode 100644
index e1af8b5..0000000
--- a/port_src/output/zxing/aztec/aztec_detector_result.rs
+++ /dev/null
@@ -1,55 +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::aztec;
-
-/**
- *
Extends {@link DetectorResult} with more information specific to the Aztec format,
- * like the number of layers and whether it's compact.
- *
- * @author Sean Owen
- */
-pub struct AztecDetectorResult {
- super: DetectorResult;
-
- let compact: bool;
-
- let nb_datablocks: i32;
-
- let nb_layers: i32;
-}
-
-impl AztecDetectorResult {
-
- pub fn new( bits: &BitMatrix, points: &Vec, compact: bool, nb_datablocks: i32, nb_layers: i32) -> AztecDetectorResult {
- super(bits, points);
- let .compact = compact;
- let .nbDatablocks = nb_datablocks;
- let .nbLayers = nb_layers;
- }
-
- pub fn get_nb_layers(&self) -> i32 {
- return self.nb_layers;
- }
-
- pub fn get_nb_datablocks(&self) -> i32 {
- return self.nb_datablocks;
- }
-
- pub fn is_compact(&self) -> bool {
- return self.compact;
- }
-}
-
diff --git a/port_src/output/zxing/aztec/aztec_reader.rs b/port_src/output/zxing/aztec/aztec_reader.rs
deleted file mode 100644
index 3d71f14..0000000
--- a/port_src/output/zxing/aztec/aztec_reader.rs
+++ /dev/null
@@ -1,111 +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::aztec;
-
-/**
- * This implementation can detect and decode Aztec codes in an image.
- *
- * @author David Olivier
- */
-#[derive(Reader)]
-pub struct AztecReader {
-}
-
-impl AztecReader {
-
- /**
- * Locates and decodes a Data Matrix code in an image.
- *
- * @return a String representing the content encoded by the Data Matrix code
- * @throws NotFoundException if a Data Matrix code cannot be found
- * @throws FormatException if a Data Matrix code cannot be decoded
- */
- pub fn decode(&self, image: &BinaryBitmap) -> /* throws NotFoundException, FormatException */Result> {
- return Ok(self.decode(image, null));
- }
-
- pub fn decode(&self, image: &BinaryBitmap, hints: &Map) -> /* throws NotFoundException, FormatException */Result> {
- let not_found_exception: NotFoundException = null;
- let format_exception: FormatException = null;
- let detector: Detector = Detector::new(&image.get_black_matrix());
- let mut points: Vec = null;
- let decoder_result: DecoderResult = null;
- let tryResult1 = 0;
- 'try1: loop {
- {
- let detector_result: AztecDetectorResult = detector.detect(false);
- points = detector_result.get_points();
- decoder_result = Decoder::new().decode(detector_result);
- }
- break 'try1
- }
- match tryResult1 {
- catch ( e: &NotFoundException) {
- not_found_exception = e;
- } catch ( e: &FormatException) {
- format_exception = e;
- } 0 => break
- }
-
- if decoder_result == null {
- let tryResult1 = 0;
- 'try1: loop {
- {
- let detector_result: AztecDetectorResult = detector.detect(true);
- points = detector_result.get_points();
- decoder_result = Decoder::new().decode(detector_result);
- }
- break 'try1
- }
- match tryResult1 {
- catch ( e: &NotFoundExceptionFormatException | ) {
- if not_found_exception != null {
- throw not_found_exception;
- }
- if format_exception != null {
- throw format_exception;
- }
- throw e;
- } 0 => break
- }
-
- }
- if hints != null {
- let rpcb: ResultPointCallback = hints.get(DecodeHintType::NEED_RESULT_POINT_CALLBACK) as ResultPointCallback;
- if rpcb != null {
- for let point: ResultPoint in points {
- rpcb.found_possible_result_point(point);
- }
- }
- }
- let result: Result = Result::new(&decoder_result.get_text(), &decoder_result.get_raw_bytes(), &decoder_result.get_num_bits(), points, BarcodeFormat::AZTEC, &System::current_time_millis());
- let byte_segments: List> = decoder_result.get_byte_segments();
- if byte_segments != null {
- result.put_metadata(ResultMetadataType::BYTE_SEGMENTS, &byte_segments);
- }
- let ec_level: String = decoder_result.get_e_c_level();
- if ec_level != null {
- result.put_metadata(ResultMetadataType::ERROR_CORRECTION_LEVEL, &ec_level);
- }
- result.put_metadata(ResultMetadataType::SYMBOLOGY_IDENTIFIER, format!("]z{}", decoder_result.get_symbology_modifier()));
- return Ok(result);
- }
-
- pub fn reset(&self) {
- // do nothing
- }
-}
-
diff --git a/port_src/output/zxing/aztec/aztec_writer.rs b/port_src/output/zxing/aztec/aztec_writer.rs
deleted file mode 100644
index ecb1f78..0000000
--- a/port_src/output/zxing/aztec/aztec_writer.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2013 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::aztec;
-
-/**
- * Renders an Aztec code as a {@link BitMatrix}.
- */
-#[derive(Writer)]
-pub struct AztecWriter {
-}
-
-impl AztecWriter {
-
- pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32) -> BitMatrix {
- return ::encode(&contents, format, width, height, null);
- }
-
- pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32, hints: &Map) -> BitMatrix {
- // Do not add any ECI code by default
- let mut charset: Charset = null;
- let ecc_percent: i32 = Encoder::DEFAULT_EC_PERCENT;
- let mut layers: i32 = Encoder::DEFAULT_AZTEC_LAYERS;
- if hints != null {
- if hints.contains_key(EncodeHintType::CHARACTER_SET) {
- charset = Charset::for_name(&hints.get(EncodeHintType::CHARACTER_SET).to_string());
- }
- if hints.contains_key(EncodeHintType::ERROR_CORRECTION) {
- ecc_percent = Integer::parse_int(&hints.get(EncodeHintType::ERROR_CORRECTION).to_string());
- }
- if hints.contains_key(EncodeHintType::AZTEC_LAYERS) {
- layers = Integer::parse_int(&hints.get(EncodeHintType::AZTEC_LAYERS).to_string());
- }
- }
- return ::encode(&contents, format, width, height, &charset, ecc_percent, layers);
- }
-
- fn encode( contents: &String, format: &BarcodeFormat, width: i32, height: i32, charset: &Charset, ecc_percent: i32, layers: i32) -> BitMatrix {
- if format != BarcodeFormat::AZTEC {
- throw IllegalArgumentException::new(format!("Can only encode AZTEC, but got {}", format));
- }
- let aztec: AztecCode = Encoder::encode(&contents, ecc_percent, layers, &charset);
- return ::render_result(aztec, width, height);
- }
-
- fn render_result( code: &AztecCode, width: i32, height: i32) -> BitMatrix {
- let input: BitMatrix = code.get_matrix();
- if input == null {
- throw IllegalStateException::new();
- }
- let input_width: i32 = input.get_width();
- let input_height: i32 = input.get_height();
- let output_width: i32 = Math::max(width, input_width);
- let output_height: i32 = Math::max(height, input_height);
- let multiple: i32 = Math::min(output_width / input_width, output_height / input_height);
- let left_padding: i32 = (output_width - (input_width * multiple)) / 2;
- let top_padding: i32 = (output_height - (input_height * multiple)) / 2;
- let output: BitMatrix = BitMatrix::new(output_width, output_height);
- {
- let input_y: i32 = 0, let output_y: i32 = top_padding;
- while input_y < input_height {
- {
- // Write the contents of this row of the barcode
- {
- let input_x: i32 = 0, let output_x: i32 = left_padding;
- while input_x < input_width {
- {
- if input.get(input_x, input_y) {
- output.set_region(output_x, output_y, multiple, multiple);
- }
- }
- input_x += 1;
- output_x += multiple;
- }
- }
-
- }
- input_y += 1;
- output_y += multiple;
- }
- }
-
- return output;
- }
-}
-
diff --git a/port_src/output/zxing/aztec/decoder/decoder.rs b/port_src/output/zxing/aztec/decoder/decoder.rs
deleted file mode 100644
index 3c0446c..0000000
--- a/port_src/output/zxing/aztec/decoder/decoder.rs
+++ /dev/null
@@ -1,556 +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::aztec::decoder;
-
-/**
- * The main class which implements Aztec Code decoding -- as opposed to locating and extracting
- * the Aztec Code from an image.
- *
- * @author David Olivier
- */
-
- const UPPER_TABLE: vec![Vec; 32] = vec!["CTRL_PS", " ", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "CTRL_LL", "CTRL_ML", "CTRL_DL", "CTRL_BS", ]
-;
-
- const LOWER_TABLE: vec![Vec; 32] = vec!["CTRL_PS", " ", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "CTRL_US", "CTRL_ML", "CTRL_DL", "CTRL_BS", ]
-;
-
- const MIXED_TABLE: vec![Vec; 32] = vec!["CTRL_PS", " ", "\1", "\2", "\3", "\4", "\5", "\6", "\7", "\b", "\t", "\n", "\13", "\f", "\r", "\33", "\34", "\35", "\36", "\37", "@", "\\", "^", "_", "`", "|", "~", "\177", "CTRL_LL", "CTRL_UL", "CTRL_PL", "CTRL_BS", ]
-;
-
- const PUNCT_TABLE: vec![Vec; 32] = vec!["FLG(n)", "\r", "\r\n", ". ", ", ", ": ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", ":", ";", "<", "=", ">", "?", "[", "]", "{", "}", "CTRL_UL", ]
-;
-
- const DIGIT_TABLE: vec![Vec; 16] = vec!["CTRL_PS", " ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ",", ".", "CTRL_UL", "CTRL_US", ]
-;
-
- const DEFAULT_ENCODING: Charset = StandardCharsets::ISO_8859_1;
-pub struct Decoder {
-
- let mut ddata: AztecDetectorResult;
-}
-
-impl Decoder {
-
- enum Table {
-
- UPPER(), LOWER(), MIXED(), DIGIT(), PUNCT(), BINARY()
- }
-
- pub fn decode(&self, detector_result: &AztecDetectorResult) -> /* throws FormatException */Result> {
- self.ddata = detector_result;
- let matrix: BitMatrix = detector_result.get_bits();
- let rawbits: Vec = self.extract_bits(matrix);
- let corrected_bits: CorrectedBitsResult = self.correct_bits(&rawbits);
- let raw_bytes: Vec = ::convert_bool_array_to_byte_array(corrected_bits.correctBits);
- let result: String = ::get_encoded_data(corrected_bits.correctBits);
- let decoder_result: DecoderResult = DecoderResult::new(&raw_bytes, &result, null, &String::format("%d%%", corrected_bits.ecLevel));
- decoder_result.set_num_bits(corrected_bits.correctBits.len());
- return Ok(decoder_result);
- }
-
- // This method is used for testing the high-level encoder
- pub fn high_level_decode( corrected_bits: &Vec) -> /* throws FormatException */Result> {
- return Ok(::get_encoded_data(&corrected_bits));
- }
-
- /**
- * Gets the string encoded in the aztec code bits
- *
- * @return the decoded string
- */
- fn get_encoded_data( corrected_bits: &Vec) -> /* throws FormatException */Result> {
- let end_index: i32 = corrected_bits.len();
- // table most recently latched to
- let latch_table: Table = Table::UPPER;
- // table to use for the next read
- let shift_table: Table = Table::UPPER;
- // Final decoded string result
- // (correctedBits-5) / 4 is an upper bound on the size (all-digit result)
- let result: StringBuilder = StringBuilder::new((corrected_bits.len() - 5) / 4);
- // Intermediary buffer of decoded bytes, which is decoded into a string and flushed
- // when character encoding changes (ECI) or input ends.
- let decoded_bytes: ByteArrayOutputStream = ByteArrayOutputStream::new();
- let mut encoding: Charset = DEFAULT_ENCODING;
- let mut index: i32 = 0;
- while index < end_index {
- if shift_table == Table::BINARY {
- if end_index - index < 5 {
- break;
- }
- let mut length: i32 = ::read_code(&corrected_bits, index, 5);
- index += 5;
- if length == 0 {
- if end_index - index < 11 {
- break;
- }
- length = ::read_code(&corrected_bits, index, 11) + 31;
- index += 11;
- }
- {
- let char_count: i32 = 0;
- while char_count < length {
- {
- if end_index - index < 8 {
- // Force outer loop to exit
- index = end_index;
- break;
- }
- let code: i32 = ::read_code(&corrected_bits, index, 8);
- decoded_bytes.write(code as i8);
- index += 8;
- }
- char_count += 1;
- }
- }
-
- // Go back to whatever mode we had been in
- shift_table = latch_table;
- } else {
- let size: i32 = if shift_table == Table::DIGIT { 4 } else { 5 };
- if end_index - index < size {
- break;
- }
- let code: i32 = ::read_code(&corrected_bits, index, size);
- index += size;
- let str: String = ::get_character(shift_table, code);
- if "FLG(n)".equals(&str) {
- if end_index - index < 3 {
- break;
- }
- let mut n: i32 = ::read_code(&corrected_bits, index, 3);
- index += 3;
- // flush bytes, FLG changes state
- let tryResult1 = 0;
- 'try1: loop {
- {
- result.append(&decoded_bytes.to_string(&encoding.name()));
- }
- break 'try1
- }
- match tryResult1 {
- catch ( uee: &UnsupportedEncodingException) {
- throw IllegalStateException::new(&uee);
- } 0 => break
- }
-
- decoded_bytes.reset();
- match n {
- 0 =>
- {
- // translate FNC1 as ASCII 29
- result.append(29 as char);
- break;
- }
- 7 =>
- {
- // FLG(7) is reserved and illegal
- throw FormatException::get_format_instance();
- }
- _ =>
- {
- // ECI is decimal integer encoded as 1-6 codes in DIGIT mode
- let mut eci: i32 = 0;
- if end_index - index < 4 * n {
- break;
- }
- while n -= 1 !!!check!!! post decrement > 0 {
- let next_digit: i32 = ::read_code(&corrected_bits, index, 4);
- index += 4;
- if next_digit < 2 || next_digit > 11 {
- // Not a decimal digit
- throw FormatException::get_format_instance();
- }
- eci = eci * 10 + (next_digit - 2);
- }
- let charset_e_c_i: CharacterSetECI = CharacterSetECI::get_character_set_e_c_i_by_value(eci);
- if charset_e_c_i == null {
- throw FormatException::get_format_instance();
- }
- encoding = charset_e_c_i.get_charset();
- }
- }
- // Go back to whatever mode we had been in
- shift_table = latch_table;
- } else if str.starts_with("CTRL_") {
- // Table changes
- // ISO/IEC 24778:2008 prescribes ending a shift sequence in the mode from which it was invoked.
- // That's including when that mode is a shift.
- // Our test case dlusbs.png for issue #642 exercises that.
- // Latch the current mode, so as to return to Upper after U/S B/S
- latch_table = shift_table;
- shift_table = ::get_table(&str.char_at(5));
- if str.char_at(6) == 'L' {
- latch_table = shift_table;
- }
- } else {
- // Though stored as a table of strings for convenience, codes actually represent 1 or 2 *bytes*.
- let b: Vec = str.get_bytes(StandardCharsets::US_ASCII);
- decoded_bytes.write(&b, 0, b.len());
- // Go back to whatever mode we had been in
- shift_table = latch_table;
- }
- }
- }
- let tryResult1 = 0;
- 'try1: loop {
- {
- result.append(&decoded_bytes.to_string(&encoding.name()));
- }
- break 'try1
- }
- match tryResult1 {
- catch ( uee: &UnsupportedEncodingException) {
- throw IllegalStateException::new(&uee);
- } 0 => break
- }
-
- return Ok(result.to_string());
- }
-
- /**
- * gets the table corresponding to the char passed
- */
- fn get_table( t: char) -> Table {
- match t {
- 'L' =>
- {
- return Table::LOWER;
- }
- 'P' =>
- {
- return Table::PUNCT;
- }
- 'M' =>
- {
- return Table::MIXED;
- }
- 'D' =>
- {
- return Table::DIGIT;
- }
- 'B' =>
- {
- return Table::BINARY;
- }
- 'U' =>
- {
- }
- _ =>
- {
- return Table::UPPER;
- }
- }
- }
-
- /**
- * Gets the character (or string) corresponding to the passed code in the given table
- *
- * @param table the table used
- * @param code the code of the character
- */
- fn get_character( table: &Table, code: i32) -> String {
- match table {
- UPPER =>
- {
- return UPPER_TABLE[code];
- }
- LOWER =>
- {
- return LOWER_TABLE[code];
- }
- MIXED =>
- {
- return MIXED_TABLE[code];
- }
- PUNCT =>
- {
- return PUNCT_TABLE[code];
- }
- DIGIT =>
- {
- return DIGIT_TABLE[code];
- }
- _ =>
- {
- // Should not reach here.
- throw IllegalStateException::new("Bad table");
- }
- }
- }
-
- struct CorrectedBitsResult {
-
- let correct_bits: Vec;
-
- let ec_level: i32;
- }
-
- impl CorrectedBitsResult {
-
- fn new( correct_bits: &Vec, ec_level: i32) -> CorrectedBitsResult {
- let .correctBits = correct_bits;
- let .ecLevel = ec_level;
- }
- }
-
-
- /**
- * Performs RS error correction on an array of bits.
- *
- * @return the corrected array
- * @throws FormatException if the input contains too many errors
- */
- fn correct_bits(&self, rawbits: &Vec) -> /* throws FormatException */Result> {
- let mut gf: GenericGF;
- let codeword_size: i32;
- if self.ddata.get_nb_layers() <= 2 {
- codeword_size = 6;
- gf = GenericGF::AZTEC_DATA_6;
- } else if self.ddata.get_nb_layers() <= 8 {
- codeword_size = 8;
- gf = GenericGF::AZTEC_DATA_8;
- } else if self.ddata.get_nb_layers() <= 22 {
- codeword_size = 10;
- gf = GenericGF::AZTEC_DATA_10;
- } else {
- codeword_size = 12;
- gf = GenericGF::AZTEC_DATA_12;
- }
- let num_data_codewords: i32 = self.ddata.get_nb_datablocks();
- let num_codewords: i32 = rawbits.len() / codeword_size;
- if num_codewords < num_data_codewords {
- throw FormatException::get_format_instance();
- }
- let mut offset: i32 = rawbits.len() % codeword_size;
- let data_words: [i32; num_codewords] = [0; num_codewords];
- {
- let mut i: i32 = 0;
- while i < num_codewords {
- {
- data_words[i] = ::read_code(&rawbits, offset, codeword_size);
- }
- i += 1;
- offset += codeword_size;
- }
- }
-
- let tryResult1 = 0;
- 'try1: loop {
- {
- let rs_decoder: ReedSolomonDecoder = ReedSolomonDecoder::new(gf);
- rs_decoder.decode(&data_words, num_codewords - num_data_codewords);
- }
- break 'try1
- }
- match tryResult1 {
- catch ( ex: &ReedSolomonException) {
- throw FormatException::get_format_instance(ex);
- } 0 => break
- }
-
- // Now perform the unstuffing operation.
- // First, count how many bits are going to be thrown out as stuffing
- let mask: i32 = (1 << codeword_size) - 1;
- let stuffed_bits: i32 = 0;
- {
- let mut i: i32 = 0;
- while i < num_data_codewords {
- {
- let data_word: i32 = data_words[i];
- if data_word == 0 || data_word == mask {
- throw FormatException::get_format_instance();
- } else if data_word == 1 || data_word == mask - 1 {
- stuffed_bits += 1;
- }
- }
- i += 1;
- }
- }
-
- // Now, actually unpack the bits and remove the stuffing
- let corrected_bits: [bool; num_data_codewords * codeword_size - stuffed_bits] = [false; num_data_codewords * codeword_size - stuffed_bits];
- let mut index: i32 = 0;
- {
- let mut i: i32 = 0;
- while i < num_data_codewords {
- {
- let data_word: i32 = data_words[i];
- if data_word == 1 || data_word == mask - 1 {
- // next codewordSize-1 bits are all zeros or all ones
- Arrays::fill(&corrected_bits, index, index + codeword_size - 1, data_word > 1);
- index += codeword_size - 1;
- } else {
- {
- let mut bit: i32 = codeword_size - 1;
- while bit >= 0 {
- {
- corrected_bits[index += 1 !!!check!!! post increment] = (data_word & (1 << bit)) != 0;
- }
- bit -= 1;
- }
- }
-
- }
- }
- i += 1;
- }
- }
-
- return Ok(CorrectedBitsResult::new(&corrected_bits, 100 * (num_codewords - num_data_codewords) / num_codewords));
- }
-
- /**
- * Gets the array of bits from an Aztec Code matrix
- *
- * @return the array of bits
- */
- fn extract_bits(&self, matrix: &BitMatrix) -> Vec {
- let compact: bool = self.ddata.is_compact();
- let layers: i32 = self.ddata.get_nb_layers();
- // not including alignment lines
- let base_matrix_size: i32 = ( if compact { 11 } else { 14 }) + layers * 4;
- let alignment_map: [i32; base_matrix_size] = [0; base_matrix_size];
- let mut rawbits: [bool; ::total_bits_in_layer(layers, compact)] = [false; ::total_bits_in_layer(layers, compact)];
- if compact {
- {
- let mut i: i32 = 0;
- while i < alignment_map.len() {
- {
- alignment_map[i] = i;
- }
- i += 1;
- }
- }
-
- } else {
- let matrix_size: i32 = base_matrix_size + 1 + 2 * ((base_matrix_size / 2 - 1) / 15);
- let orig_center: i32 = base_matrix_size / 2;
- let center: i32 = matrix_size / 2;
- {
- let mut i: i32 = 0;
- while i < orig_center {
- {
- let new_offset: i32 = i + i / 15;
- alignment_map[orig_center - i - 1] = center - new_offset - 1;
- alignment_map[orig_center + i] = center + new_offset + 1;
- }
- i += 1;
- }
- }
-
- }
- {
- let mut i: i32 = 0, let row_offset: i32 = 0;
- while i < layers {
- {
- let row_size: i32 = (layers - i) * 4 + ( if compact { 9 } else { 12 });
- // The top-left most point of this layer is (not including alignment lines)
- let low: i32 = i * 2;
- // The bottom-right most point of this layer is (not including alignment lines)
- let high: i32 = base_matrix_size - 1 - low;
- // We pull bits from the two 2 x rowSize columns and two rowSize x 2 rows
- {
- let mut j: i32 = 0;
- while j < row_size {
- {
- let column_offset: i32 = j * 2;
- {
- let mut k: i32 = 0;
- while k < 2 {
- {
- // left column
- rawbits[row_offset + column_offset + k] = matrix.get(alignment_map[low + k], alignment_map[low + j]);
- // bottom row
- rawbits[row_offset + 2 * row_size + column_offset + k] = matrix.get(alignment_map[low + j], alignment_map[high - k]);
- // right column
- rawbits[row_offset + 4 * row_size + column_offset + k] = matrix.get(alignment_map[high - k], alignment_map[high - j]);
- // top row
- rawbits[row_offset + 6 * row_size + column_offset + k] = matrix.get(alignment_map[high - j], alignment_map[low + k]);
- }
- k += 1;
- }
- }
-
- }
- j += 1;
- }
- }
-
- row_offset += row_size * 8;
- }
- i += 1;
- }
- }
-
- return rawbits;
- }
-
- /**
- * Reads a code of given length and at given index in an array of bits
- */
- fn read_code( rawbits: &Vec, start_index: i32, length: i32) -> i32 {
- let mut res: i32 = 0;
- {
- let mut i: i32 = start_index;
- while i < start_index + length {
- {
- res <<= 1;
- if rawbits[i] {
- res |= 0x01;
- }
- }
- i += 1;
- }
- }
-
- return res;
- }
-
- /**
- * Reads a code of length 8 in an array of bits, padding with zeros
- */
- fn read_byte( rawbits: &Vec, start_index: i32) -> i8 {
- let n: i32 = rawbits.len() - start_index;
- if n >= 8 {
- return ::read_code(&rawbits, start_index, 8) as i8;
- }
- return (::read_code(&rawbits, start_index, n) << (8 - n)) as i8;
- }
-
- /**
- * Packs a bit array into bytes, most significant bit first
- */
- fn convert_bool_array_to_byte_array( bool_arr: &Vec) -> Vec {
- let byte_arr: [i8; (bool_arr.len() + 7) / 8] = [0; (bool_arr.len() + 7) / 8];
- {
- let mut i: i32 = 0;
- while i < byte_arr.len() {
- {
- byte_arr[i] = ::read_byte(&bool_arr, 8 * i);
- }
- i += 1;
- }
- }
-
- return byte_arr;
- }
-
- fn total_bits_in_layer( layers: i32, compact: bool) -> i32 {
- return (( if compact { 88 } else { 112 }) + 16 * layers) * layers;
- }
-}
-
diff --git a/port_src/output/zxing/aztec/detector/detector.rs b/port_src/output/zxing/aztec/detector/detector.rs
deleted file mode 100644
index 4fdadc1..0000000
--- a/port_src/output/zxing/aztec/detector/detector.rs
+++ /dev/null
@@ -1,586 +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::aztec::detector;
-
-/**
- * Encapsulates logic that can detect an Aztec Code in an image, even if the Aztec Code
- * is rotated or skewed, or partially obscured.
- *
- * @author David Olivier
- * @author Frank Yellin
- */
-
- const EXPECTED_CORNER_BITS: vec![Vec; 4] = vec![// 07340 XXX .XX X.. ...
-0xee0, // 00734 ... XXX .XX X..
-0x1dc, // 04073 X.. ... XXX .XX
-0x83b, // 03407 .XX X.. ... XXX
-0x707, ]
-;
-pub struct Detector {
-
- let image: BitMatrix;
-
- let mut compact: bool;
-
- let nb_layers: i32;
-
- let nb_data_blocks: i32;
-
- let nb_center_layers: i32;
-
- let mut shift: i32;
-}
-
-impl Detector {
-
- pub fn new( image: &BitMatrix) -> Detector {
- let .image = image;
- }
-
- pub fn detect(&self) -> /* throws NotFoundException */Result> {
- return Ok(self.detect(false));
- }
-
- /**
- * Detects an Aztec Code in an image.
- *
- * @param isMirror if true, image is a mirror-image of original
- * @return {@link AztecDetectorResult} encapsulating results of detecting an Aztec Code
- * @throws NotFoundException if no Aztec Code can be found
- */
- pub fn detect(&self, is_mirror: bool) -> /* throws NotFoundException */Result> {
- // 1. Get the center of the aztec matrix
- let p_center: Point = self.get_matrix_center();
- // 2. Get the center points of the four diagonal points just outside the bull's eye
- // [topRight, bottomRight, bottomLeft, topLeft]
- let bulls_eye_corners: Vec = self.get_bulls_eye_corners(p_center);
- if is_mirror {
- let temp: ResultPoint = bulls_eye_corners[0];
- bulls_eye_corners[0] = bulls_eye_corners[2];
- bulls_eye_corners[2] = temp;
- }
- // 3. Get the size of the matrix and other parameters from the bull's eye
- self.extract_parameters(bulls_eye_corners);
- // 4. Sample the grid
- let bits: BitMatrix = self.sample_grid(self.image, bulls_eye_corners[self.shift % 4], bulls_eye_corners[(self.shift + 1) % 4], bulls_eye_corners[(self.shift + 2) % 4], bulls_eye_corners[(self.shift + 3) % 4]);
- // 5. Get the corners of the matrix.
- let corners: Vec = self.get_matrix_corner_points(bulls_eye_corners);
- return Ok(AztecDetectorResult::new(bits, corners, self.compact, self.nb_data_blocks, self.nb_layers));
- }
-
- /**
- * Extracts the number of data layers and data blocks from the layer around the bull's eye.
- *
- * @param bullsEyeCorners the array of bull's eye corners
- * @throws NotFoundException in case of too many errors or invalid parameters
- */
- fn extract_parameters(&self, bulls_eye_corners: &Vec) -> /* throws NotFoundException */Result> {
- if !self.is_valid(bulls_eye_corners[0]) || !self.is_valid(bulls_eye_corners[1]) || !self.is_valid(bulls_eye_corners[2]) || !self.is_valid(bulls_eye_corners[3]) {
- throw NotFoundException::get_not_found_instance();
- }
- let length: i32 = 2 * self.nb_center_layers;
- // Get the bits around the bull's eye
- let sides: vec![Vec; 4] = vec![// Right side
- self.sample_line(bulls_eye_corners[0], bulls_eye_corners[1], length), // Bottom
- self.sample_line(bulls_eye_corners[1], bulls_eye_corners[2], length), // Left side
- self.sample_line(bulls_eye_corners[2], bulls_eye_corners[3], length), // Top
- self.sample_line(bulls_eye_corners[3], bulls_eye_corners[0], length), ]
- ;
- // bullsEyeCorners[shift] is the corner of the bulls'eye that has three
- // orientation marks.
- // sides[shift] is the row/column that goes from the corner with three
- // orientation marks to the corner with two.
- self.shift = ::get_rotation(&sides, length);
- // Flatten the parameter bits into a single 28- or 40-bit long
- let parameter_data: i64 = 0;
- {
- let mut i: i32 = 0;
- while i < 4 {
- {
- let side: i32 = sides[(self.shift + i) % 4];
- if self.compact {
- // Each side of the form ..XXXXXXX. where Xs are parameter data
- parameter_data <<= 7;
- parameter_data += (side >> 1) & 0x7F;
- } else {
- // Each side of the form ..XXXXX.XXXXX. where Xs are parameter data
- parameter_data <<= 10;
- parameter_data += ((side >> 2) & (0x1f << 5)) + ((side >> 1) & 0x1F);
- }
- }
- i += 1;
- }
- }
-
- // Corrects parameter data using RS. Returns just the data portion
- // without the error correction.
- let corrected_data: i32 = ::get_corrected_parameter_data(parameter_data, self.compact);
- if self.compact {
- // 8 bits: 2 bits layers and 6 bits data blocks
- self.nb_layers = (corrected_data >> 6) + 1;
- self.nb_data_blocks = (corrected_data & 0x3F) + 1;
- } else {
- // 16 bits: 5 bits layers and 11 bits data blocks
- self.nb_layers = (corrected_data >> 11) + 1;
- self.nb_data_blocks = (corrected_data & 0x7FF) + 1;
- }
- }
-
- fn get_rotation( sides: &Vec, length: i32) -> /* throws NotFoundException */Result> {
- // In a normal pattern, we expect to See
- // ** .* D A
- // * *
- //
- // . *
- // .. .. C B
- //
- // Grab the 3 bits from each of the sides the form the locator pattern and concatenate
- // into a 12-bit integer. Start with the bit at A
- let corner_bits: i32 = 0;
- for let side: i32 in sides {
- // XX......X where X's are orientation marks
- let t: i32 = ((side >> (length - 2)) << 1) + (side & 1);
- corner_bits = (corner_bits << 3) + t;
- }
- // Mov the bottom bit to the top, so that the three bits of the locator pattern at A are
- // together. cornerBits is now:
- // 3 orientation bits at A || 3 orientation bits at B || ... || 3 orientation bits at D
- corner_bits = ((corner_bits & 1) << 11) + (corner_bits >> 1);
- // can easily tolerate two errors.
- {
- let mut shift: i32 = 0;
- while shift < 4 {
- {
- if Integer::bit_count(corner_bits ^ EXPECTED_CORNER_BITS[shift]) <= 2 {
- return Ok(shift);
- }
- }
- shift += 1;
- }
- }
-
- throw NotFoundException::get_not_found_instance();
- }
-
- /**
- * Corrects the parameter bits using Reed-Solomon algorithm.
- *
- * @param parameterData parameter bits
- * @param compact true if this is a compact Aztec code
- * @throws NotFoundException if the array contains too many errors
- */
- fn get_corrected_parameter_data( parameter_data: i64, compact: bool) -> /* throws NotFoundException */Result> {
- let num_codewords: i32;
- let num_data_codewords: i32;
- if compact {
- num_codewords = 7;
- num_data_codewords = 2;
- } else {
- num_codewords = 10;
- num_data_codewords = 4;
- }
- let num_e_c_codewords: i32 = num_codewords - num_data_codewords;
- let parameter_words: [i32; num_codewords] = [0; num_codewords];
- {
- let mut i: i32 = num_codewords - 1;
- while i >= 0 {
- {
- parameter_words[i] = parameter_data as i32 & 0xF;
- parameter_data >>= 4;
- }
- i -= 1;
- }
- }
-
- let tryResult1 = 0;
- 'try1: loop {
- {
- let rs_decoder: ReedSolomonDecoder = ReedSolomonDecoder::new(GenericGF::AZTEC_PARAM);
- rs_decoder.decode(¶meter_words, num_e_c_codewords);
- }
- break 'try1
- }
- match tryResult1 {
- catch ( ignored: &ReedSolomonException) {
- throw NotFoundException::get_not_found_instance();
- } 0 => break
- }
-
- // Toss the error correction. Just return the data as an integer
- let mut result: i32 = 0;
- {
- let mut i: i32 = 0;
- while i < num_data_codewords {
- {
- result = (result << 4) + parameter_words[i];
- }
- i += 1;
- }
- }
-
- return Ok(result);
- }
-
- /**
- * Finds the corners of a bull-eye centered on the passed point.
- * This returns the centers of the diagonal points just outside the bull's eye
- * Returns [topRight, bottomRight, bottomLeft, topLeft]
- *
- * @param pCenter Center point
- * @return The corners of the bull-eye
- * @throws NotFoundException If no valid bull-eye can be found
- */
- fn get_bulls_eye_corners(&self, p_center: &Point) -> /* throws NotFoundException */Result, Rc> {
- let mut pina: Point = p_center;
- let mut pinb: Point = p_center;
- let mut pinc: Point = p_center;
- let mut pind: Point = p_center;
- let mut color: bool = true;
- {
- self.nb_center_layers = 1;
- while self.nb_center_layers < 9 {
- {
- let pouta: Point = self.get_first_different(pina, color, 1, -1);
- let poutb: Point = self.get_first_different(pinb, color, 1, 1);
- let poutc: Point = self.get_first_different(pinc, color, -1, 1);
- let poutd: Point = self.get_first_different(pind, color, -1, -1);
- if self.nb_center_layers > 2 {
- let q: f32 = ::distance(poutd, pouta) * self.nb_center_layers / (::distance(pind, pina) * (self.nb_center_layers + 2));
- if q < 0.75 || q > 1.25 || !self.is_white_or_black_rectangle(pouta, poutb, poutc, poutd) {
- break;
- }
- }
- pina = pouta;
- pinb = poutb;
- pinc = poutc;
- pind = poutd;
- color = !color;
- }
- self.nb_center_layers += 1;
- }
- }
-
- if self.nb_center_layers != 5 && self.nb_center_layers != 7 {
- throw NotFoundException::get_not_found_instance();
- }
- self.compact = self.nb_center_layers == 5;
- // Expand the square by .5 pixel in each direction so that we're on the border
- // between the white square and the black square
- let pinax: ResultPoint = ResultPoint::new(pina.get_x() + 0.5f, pina.get_y() - 0.5f);
- let pinbx: ResultPoint = ResultPoint::new(pinb.get_x() + 0.5f, pinb.get_y() + 0.5f);
- let pincx: ResultPoint = ResultPoint::new(pinc.get_x() - 0.5f, pinc.get_y() + 0.5f);
- let pindx: ResultPoint = ResultPoint::new(pind.get_x() - 0.5f, pind.get_y() - 0.5f);
- // just outside the bull's eye.
- return Ok(::expand_square( : vec![ResultPoint; 4] = vec![pinax, pinbx, pincx, pindx, ]
- , 2 * self.nb_center_layers - 3, 2 * self.nb_center_layers));
- }
-
- /**
- * Finds a candidate center point of an Aztec code from an image
- *
- * @return the center point
- */
- fn get_matrix_center(&self) -> Point {
- let point_a: ResultPoint;
- let point_b: ResultPoint;
- let point_c: ResultPoint;
- let point_d: ResultPoint;
- //Get a white rectangle that can be the border of the matrix in center bull's eye or
- let tryResult1 = 0;
- 'try1: loop {
- {
- let corner_points: Vec = WhiteRectangleDetector::new(self.image).detect();
- point_a = corner_points[0];
- point_b = corner_points[1];
- point_c = corner_points[2];
- point_d = corner_points[3];
- }
- break 'try1
- }
- match tryResult1 {
- catch ( e: &NotFoundException) {
- let cx: i32 = self.image.get_width() / 2;
- let cy: i32 = self.image.get_height() / 2;
- point_a = self.get_first_different(Point::new(cx + 7, cy - 7), false, 1, -1).to_result_point();
- point_b = self.get_first_different(Point::new(cx + 7, cy + 7), false, 1, 1).to_result_point();
- point_c = self.get_first_different(Point::new(cx - 7, cy + 7), false, -1, 1).to_result_point();
- point_d = self.get_first_different(Point::new(cx - 7, cy - 7), false, -1, -1).to_result_point();
- } 0 => break
- }
-
- //Compute the center of the rectangle
- let mut cx: i32 = MathUtils::round((point_a.get_x() + point_d.get_x() + point_b.get_x() + point_c.get_x()) / 4.0f);
- let mut cy: i32 = MathUtils::round((point_a.get_y() + point_d.get_y() + point_b.get_y() + point_c.get_y()) / 4.0f);
- // in order to compute a more accurate center.
- let tryResult1 = 0;
- 'try1: loop {
- {
- let corner_points: Vec = WhiteRectangleDetector::new(self.image, 15, cx, cy).detect();
- point_a = corner_points[0];
- point_b = corner_points[1];
- point_c = corner_points[2];
- point_d = corner_points[3];
- }
- break 'try1
- }
- match tryResult1 {
- catch ( e: &NotFoundException) {
- point_a = self.get_first_different(Point::new(cx + 7, cy - 7), false, 1, -1).to_result_point();
- point_b = self.get_first_different(Point::new(cx + 7, cy + 7), false, 1, 1).to_result_point();
- point_c = self.get_first_different(Point::new(cx - 7, cy + 7), false, -1, 1).to_result_point();
- point_d = self.get_first_different(Point::new(cx - 7, cy - 7), false, -1, -1).to_result_point();
- } 0 => break
- }
-
- // Recompute the center of the rectangle
- cx = MathUtils::round((point_a.get_x() + point_d.get_x() + point_b.get_x() + point_c.get_x()) / 4.0f);
- cy = MathUtils::round((point_a.get_y() + point_d.get_y() + point_b.get_y() + point_c.get_y()) / 4.0f);
- return Point::new(cx, cy);
- }
-
- /**
- * Gets the Aztec code corners from the bull's eye corners and the parameters.
- *
- * @param bullsEyeCorners the array of bull's eye corners
- * @return the array of aztec code corners
- */
- fn get_matrix_corner_points(&self, bulls_eye_corners: &Vec) -> Vec {
- return ::expand_square(bulls_eye_corners, 2 * self.nb_center_layers, &self.get_dimension());
- }
-
- /**
- * Creates a BitMatrix by sampling the provided image.
- * topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the
- * diagonal just outside the bull's eye.
- */
- fn sample_grid(&self, image: &BitMatrix, top_left: &ResultPoint, top_right: &ResultPoint, bottom_right: &ResultPoint, bottom_left: &ResultPoint) -> /* throws NotFoundException */Result> {
- let sampler: GridSampler = GridSampler::get_instance();
- let dimension: i32 = self.get_dimension();
- let low: f32 = dimension / 2.0f - self.nb_center_layers;
- let high: f32 = dimension / 2.0f + self.nb_center_layers;
- return Ok(sampler.sample_grid(image, dimension, dimension, // topleft
- low, // topleft
- low, // topright
- high, // topright
- low, // bottomright
- high, // bottomright
- high, // bottomleft
- low, // bottomleft
- high, &top_left.get_x(), &top_left.get_y(), &top_right.get_x(), &top_right.get_y(), &bottom_right.get_x(), &bottom_right.get_y(), &bottom_left.get_x(), &bottom_left.get_y()));
- }
-
- /**
- * Samples a line.
- *
- * @param p1 start point (inclusive)
- * @param p2 end point (exclusive)
- * @param size number of bits
- * @return the array of bits as an int (first bit is high-order bit of result)
- */
- fn sample_line(&self, p1: &ResultPoint, p2: &ResultPoint, size: i32) -> i32 {
- let mut result: i32 = 0;
- let d: f32 = ::distance(p1, p2);
- let module_size: f32 = d / size;
- let px: f32 = p1.get_x();
- let py: f32 = p1.get_y();
- let dx: f32 = module_size * (p2.get_x() - p1.get_x()) / d;
- let dy: f32 = module_size * (p2.get_y() - p1.get_y()) / d;
- {
- let mut i: i32 = 0;
- while i < size {
- {
- if self.image.get(&MathUtils::round(px + i * dx), &MathUtils::round(py + i * dy)) {
- result |= 1 << (size - i - 1);
- }
- }
- i += 1;
- }
- }
-
- return result;
- }
-
- /**
- * @return true if the border of the rectangle passed in parameter is compound of white points only
- * or black points only
- */
- fn is_white_or_black_rectangle(&self, p1: &Point, p2: &Point, p3: &Point, p4: &Point) -> bool {
- let corr: i32 = 3;
- p1 = Point::new(&Math::max(0, p1.get_x() - corr), &Math::min(self.image.get_height() - 1, p1.get_y() + corr));
- p2 = Point::new(&Math::max(0, p2.get_x() - corr), &Math::max(0, p2.get_y() - corr));
- p3 = Point::new(&Math::min(self.image.get_width() - 1, p3.get_x() + corr), &Math::max(0, &Math::min(self.image.get_height() - 1, p3.get_y() - corr)));
- p4 = Point::new(&Math::min(self.image.get_width() - 1, p4.get_x() + corr), &Math::min(self.image.get_height() - 1, p4.get_y() + corr));
- let c_init: i32 = self.get_color(p4, p1);
- if c_init == 0 {
- return false;
- }
- let mut c: i32 = self.get_color(p1, p2);
- if c != c_init {
- return false;
- }
- c = self.get_color(p2, p3);
- if c != c_init {
- return false;
- }
- c = self.get_color(p3, p4);
- return c == c_init;
- }
-
- /**
- * Gets the color of a segment
- *
- * @return 1 if segment more than 90% black, -1 if segment is more than 90% white, 0 else
- */
- fn get_color(&self, p1: &Point, p2: &Point) -> i32 {
- let d: f32 = ::distance(p1, p2);
- if d == 0.0f {
- return 0;
- }
- let dx: f32 = (p2.get_x() - p1.get_x()) / d;
- let dy: f32 = (p2.get_y() - p1.get_y()) / d;
- let mut error: i32 = 0;
- let mut px: f32 = p1.get_x();
- let mut py: f32 = p1.get_y();
- let color_model: bool = self.image.get(&p1.get_x(), &p1.get_y());
- let i_max: i32 = Math::floor(d) as i32;
- {
- let mut i: i32 = 0;
- while i < i_max {
- {
- if self.image.get(&MathUtils::round(px), &MathUtils::round(py)) != color_model {
- error += 1;
- }
- px += dx;
- py += dy;
- }
- i += 1;
- }
- }
-
- let err_ratio: f32 = error / d;
- if err_ratio > 0.1f && err_ratio < 0.9f {
- return 0;
- }
- return if (err_ratio <= 0.1f) == color_model { 1 } else { -1 };
- }
-
- /**
- * Gets the coordinate of the first point with a different color in the given direction
- */
- fn get_first_different(&self, init: &Point, color: bool, dx: i32, dy: i32) -> Point {
- let mut x: i32 = init.get_x() + dx;
- let mut y: i32 = init.get_y() + dy;
- while self.is_valid(x, y) && self.image.get(x, y) == color {
- x += dx;
- y += dy;
- }
- x -= dx;
- y -= dy;
- while self.is_valid(x, y) && self.image.get(x, y) == color {
- x += dx;
- }
- x -= dx;
- while self.is_valid(x, y) && self.image.get(x, y) == color {
- y += dy;
- }
- y -= dy;
- return Point::new(x, y);
- }
-
- /**
- * Expand the square represented by the corner points by pushing out equally in all directions
- *
- * @param cornerPoints the corners of the square, which has the bull's eye at its center
- * @param oldSide the original length of the side of the square in the target bit matrix
- * @param newSide the new length of the size of the square in the target bit matrix
- * @return the corners of the expanded square
- */
- fn expand_square( corner_points: &Vec, old_side: i32, new_side: i32) -> Vec {
- let ratio: f32 = new_side / (2.0f * old_side);
- let mut dx: f32 = corner_points[0].get_x() - corner_points[2].get_x();
- let mut dy: f32 = corner_points[0].get_y() - corner_points[2].get_y();
- let mut centerx: f32 = (corner_points[0].get_x() + corner_points[2].get_x()) / 2.0f;
- let mut centery: f32 = (corner_points[0].get_y() + corner_points[2].get_y()) / 2.0f;
- let result0: ResultPoint = ResultPoint::new(centerx + ratio * dx, centery + ratio * dy);
- let result2: ResultPoint = ResultPoint::new(centerx - ratio * dx, centery - ratio * dy);
- dx = corner_points[1].get_x() - corner_points[3].get_x();
- dy = corner_points[1].get_y() - corner_points[3].get_y();
- centerx = (corner_points[1].get_x() + corner_points[3].get_x()) / 2.0f;
- centery = (corner_points[1].get_y() + corner_points[3].get_y()) / 2.0f;
- let result1: ResultPoint = ResultPoint::new(centerx + ratio * dx, centery + ratio * dy);
- let result3: ResultPoint = ResultPoint::new(centerx - ratio * dx, centery - ratio * dy);
- return : vec![ResultPoint; 4] = vec![result0, result1, result2, result3, ]
- ;
- }
-
- fn is_valid(&self, x: i32, y: i32) -> bool {
- return x >= 0 && x < self.image.get_width() && y >= 0 && y < self.image.get_height();
- }
-
- fn is_valid(&self, point: &ResultPoint) -> bool {
- let x: i32 = MathUtils::round(&point.get_x());
- let y: i32 = MathUtils::round(&point.get_y());
- return self.is_valid(x, y);
- }
-
- fn distance( a: &Point, b: &Point) -> f32 {
- return MathUtils::distance(&a.get_x(), &a.get_y(), &b.get_x(), &b.get_y());
- }
-
- fn distance( a: &ResultPoint, b: &ResultPoint) -> f32 {
- return MathUtils::distance(&a.get_x(), &a.get_y(), &b.get_x(), &b.get_y());
- }
-
- fn get_dimension(&self) -> i32 {
- if self.compact {
- return 4 * self.nb_layers + 11;
- }
- return 4 * self.nb_layers + 2 * ((2 * self.nb_layers + 6) / 15) + 15;
- }
-
- struct Point {
-
- let x: i32;
-
- let y: i32;
- }
-
- impl Point {
-
- fn to_result_point(&self) -> ResultPoint {
- return ResultPoint::new(self.x, self.y);
- }
-
- fn new( x: i32, y: i32) -> Point {
- let .x = x;
- let .y = y;
- }
-
- fn get_x(&self) -> i32 {
- return self.x;
- }
-
- fn get_y(&self) -> i32 {
- return self.y;
- }
-
- pub fn to_string(&self) -> String {
- return format!("<{} {}>", self.x, self.y);
- }
- }
-
-}
-
diff --git a/port_src/output/zxing/aztec/encoder/aztec_code.rs b/port_src/output/zxing/aztec/encoder/aztec_code.rs
deleted file mode 100644
index 8aac172..0000000
--- a/port_src/output/zxing/aztec/encoder/aztec_code.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2013 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::aztec::encoder;
-
-/**
- * Aztec 2D code representation
- *
- * @author Rustam Abdullaev
- */
-pub struct AztecCode {
-
- let compact: bool;
-
- let size: i32;
-
- let layers: i32;
-
- let code_words: i32;
-
- let matrix: BitMatrix;
-}
-
-impl AztecCode {
-
- /**
- * @return {@code true} if compact instead of full mode
- */
- pub fn is_compact(&self) -> bool {
- return self.compact;
- }
-
- pub fn set_compact(&self, compact: bool) {
- self.compact = compact;
- }
-
- /**
- * @return size in pixels (width and height)
- */
- pub fn get_size(&self) -> i32 {
- return self.size;
- }
-
- pub fn set_size(&self, size: i32) {
- self.size = size;
- }
-
- /**
- * @return number of levels
- */
- pub fn get_layers(&self) -> i32 {
- return self.layers;
- }
-
- pub fn set_layers(&self, layers: i32) {
- self.layers = layers;
- }
-
- /**
- * @return number of data codewords
- */
- pub fn get_code_words(&self) -> i32 {
- return self.code_words;
- }
-
- pub fn set_code_words(&self, code_words: i32) {
- self.codeWords = code_words;
- }
-
- /**
- * @return the symbol image
- */
- pub fn get_matrix(&self) -> BitMatrix {
- return self.matrix;
- }
-
- pub fn set_matrix(&self, matrix: &BitMatrix) {
- self.matrix = matrix;
- }
-}
-
diff --git a/port_src/output/zxing/aztec/encoder/binary_shift_token.rs b/port_src/output/zxing/aztec/encoder/binary_shift_token.rs
deleted file mode 100644
index d9a3f3b..0000000
--- a/port_src/output/zxing/aztec/encoder/binary_shift_token.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2013 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::aztec::encoder;
-
-struct BinaryShiftToken {
- super: Token;
-
- let binary_shift_start: i32;
-
- let binary_shift_byte_count: i32;
-}
-
-impl BinaryShiftToken {
-
- fn new( previous: &Token, binary_shift_start: i32, binary_shift_byte_count: i32) -> BinaryShiftToken {
- super(previous);
- let .binaryShiftStart = binary_shift_start;
- let .binaryShiftByteCount = binary_shift_byte_count;
- }
-
- pub fn append_to(&self, bit_array: &BitArray, text: &Vec) {
- let bsbc: i32 = self.binary_shift_byte_count;
- {
- let mut i: i32 = 0;
- while i < bsbc {
- {
- if i == 0 || (i == 31 && bsbc <= 62) {
- // We need a header before the first character, and before
- // character 31 when the total byte code is <= 62
- // BINARY_SHIFT
- bit_array.append_bits(31, 5);
- if bsbc > 62 {
- bit_array.append_bits(bsbc - 31, 16);
- } else if i == 0 {
- // 1 <= binaryShiftByteCode <= 62
- bit_array.append_bits(&Math::min(bsbc, 31), 5);
- } else {
- // 32 <= binaryShiftCount <= 62 and i == 31
- bit_array.append_bits(bsbc - 31, 5);
- }
- }
- bit_array.append_bits(text[self.binary_shift_start + i], 8);
- }
- i += 1;
- }
- }
-
- }
-
- pub fn to_string(&self) -> String {
- return format!("<{}::{}>", self.binary_shift_start, (self.binary_shift_start + self.binary_shift_byte_count - 1));
- }
-}
-
diff --git a/port_src/output/zxing/aztec/encoder/encoder.rs b/port_src/output/zxing/aztec/encoder/encoder.rs
deleted file mode 100644
index 4bc61bc..0000000
--- a/port_src/output/zxing/aztec/encoder/encoder.rs
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * Copyright 2013 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::aztec::encoder;
-
-/**
- * Generates Aztec 2D barcodes.
- *
- * @author Rustam Abdullaev
- */
-
-// default minimal percentage of error check words
- const DEFAULT_EC_PERCENT: i32 = 33;
-
- const DEFAULT_AZTEC_LAYERS: i32 = 0;
-
- const MAX_NB_BITS: i32 = 32;
-
- const MAX_NB_BITS_COMPACT: i32 = 4;
-
- const WORD_SIZE: vec![Vec; 33] = vec![4, 6, 6, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, ]
-;
-pub struct Encoder {
-}
-
-impl Encoder {
-
- fn new() -> Encoder {
- }
-
- /**
- * Encodes the given string content as an Aztec symbol (without ECI code)
- *
- * @param data input data string; must be encodable as ISO/IEC 8859-1 (Latin-1)
- * @return Aztec symbol matrix with metadata
- */
- pub fn encode( data: &String) -> AztecCode {
- return ::encode(&data.get_bytes(StandardCharsets::ISO_8859_1));
- }
-
- /**
- * Encodes the given string content as an Aztec symbol (without ECI code)
- *
- * @param data input data string; must be encodable as ISO/IEC 8859-1 (Latin-1)
- * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008,
- * a minimum of 23% + 3 words is recommended)
- * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers
- * @return Aztec symbol matrix with metadata
- */
- pub fn encode( data: &String, min_e_c_c_percent: i32, user_specified_layers: i32) -> AztecCode {
- return ::encode(&data.get_bytes(StandardCharsets::ISO_8859_1), min_e_c_c_percent, user_specified_layers, null);
- }
-
- /**
- * Encodes the given string content as an Aztec symbol
- *
- * @param data input data string
- * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008,
- * a minimum of 23% + 3 words is recommended)
- * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers
- * @param charset character set in which to encode string using ECI; if null, no ECI code
- * will be inserted, and the string must be encodable as ISO/IEC 8859-1
- * (Latin-1), the default encoding of the symbol.
- * @return Aztec symbol matrix with metadata
- */
- pub fn encode( data: &String, min_e_c_c_percent: i32, user_specified_layers: i32, charset: &Charset) -> AztecCode {
- let bytes: Vec = data.get_bytes( if null != charset { charset } else { StandardCharsets::ISO_8859_1 });
- return ::encode(&bytes, min_e_c_c_percent, user_specified_layers, &charset);
- }
-
- /**
- * Encodes the given binary content as an Aztec symbol (without ECI code)
- *
- * @param data input data string
- * @return Aztec symbol matrix with metadata
- */
- pub fn encode( data: &Vec) -> AztecCode {
- return ::encode(&data, DEFAULT_EC_PERCENT, DEFAULT_AZTEC_LAYERS, null);
- }
-
- /**
- * Encodes the given binary content as an Aztec symbol (without ECI code)
- *
- * @param data input data string
- * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008,
- * a minimum of 23% + 3 words is recommended)
- * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers
- * @return Aztec symbol matrix with metadata
- */
- pub fn encode( data: &Vec, min_e_c_c_percent: i32, user_specified_layers: i32) -> AztecCode {
- return ::encode(&data, min_e_c_c_percent, user_specified_layers, null);
- }
-
- /**
- * Encodes the given binary content as an Aztec symbol
- *
- * @param data input data string
- * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008,
- * a minimum of 23% + 3 words is recommended)
- * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers
- * @param charset character set to mark using ECI; if null, no ECI code will be inserted, and the
- * default encoding of ISO/IEC 8859-1 will be assuming by readers.
- * @return Aztec symbol matrix with metadata
- */
- pub fn encode( data: &Vec, min_e_c_c_percent: i32, user_specified_layers: i32, charset: &Charset) -> AztecCode {
- // High-level encode
- let bits: BitArray = HighLevelEncoder::new(&data, &charset).encode();
- // stuff bits and choose symbol size
- let ecc_bits: i32 = bits.get_size() * min_e_c_c_percent / 100 + 11;
- let total_size_bits: i32 = bits.get_size() + ecc_bits;
- let mut compact: bool;
- let mut layers: i32;
- let total_bits_in_layer: i32;
- let word_size: i32;
- let stuffed_bits: BitArray;
- if user_specified_layers != DEFAULT_AZTEC_LAYERS {
- compact = user_specified_layers < 0;
- layers = Math::abs(user_specified_layers);
- if layers > ( if compact { MAX_NB_BITS_COMPACT } else { MAX_NB_BITS }) {
- throw IllegalArgumentException::new(&String::format("Illegal value %s for layers", user_specified_layers));
- }
- total_bits_in_layer = self.total_bits_in_layer(layers, compact);
- word_size = WORD_SIZE[layers];
- let usable_bits_in_layers: i32 = total_bits_in_layer - (total_bits_in_layer % word_size);
- stuffed_bits = ::stuff_bits(bits, word_size);
- if stuffed_bits.get_size() + ecc_bits > usable_bits_in_layers {
- throw IllegalArgumentException::new("Data to large for user specified layer");
- }
- if compact && stuffed_bits.get_size() > word_size * 64 {
- // Compact format only allows 64 data words, though C4 can hold more words than that
- throw IllegalArgumentException::new("Data to large for user specified layer");
- }
- } else {
- word_size = 0;
- stuffed_bits = null;
- // is the same size, but has more data.
- {
- let mut i: i32 = 0;
- loop {
- {
- if i > MAX_NB_BITS {
- throw IllegalArgumentException::new("Data too large for an Aztec code");
- }
- compact = i <= 3;
- layers = if compact { i + 1 } else { i };
- total_bits_in_layer = self.total_bits_in_layer(layers, compact);
- if total_size_bits > total_bits_in_layer {
- continue;
- }
- // wordSize has changed
- if stuffed_bits == null || word_size != WORD_SIZE[layers] {
- word_size = WORD_SIZE[layers];
- stuffed_bits = ::stuff_bits(bits, word_size);
- }
- let usable_bits_in_layers: i32 = total_bits_in_layer - (total_bits_in_layer % word_size);
- if compact && stuffed_bits.get_size() > word_size * 64 {
- // Compact format only allows 64 data words, though C4 can hold more words than that
- continue;
- }
- if stuffed_bits.get_size() + ecc_bits <= usable_bits_in_layers {
- break;
- }
- }
- i += 1;
- }
- }
-
- }
- let message_bits: BitArray = ::generate_check_words(stuffed_bits, total_bits_in_layer, word_size);
- // generate mode message
- let message_size_in_words: i32 = stuffed_bits.get_size() / word_size;
- let mode_message: BitArray = ::generate_mode_message(compact, layers, message_size_in_words);
- // allocate symbol
- // not including alignment lines
- let base_matrix_size: i32 = ( if compact { 11 } else { 14 }) + layers * 4;
- let alignment_map: [i32; base_matrix_size] = [0; base_matrix_size];
- let matrix_size: i32;
- if compact {
- // no alignment marks in compact mode, alignmentMap is a no-op
- matrix_size = base_matrix_size;
- {
- let mut i: i32 = 0;
- while i < alignment_map.len() {
- {
- alignment_map[i] = i;
- }
- i += 1;
- }
- }
-
- } else {
- matrix_size = base_matrix_size + 1 + 2 * ((base_matrix_size / 2 - 1) / 15);
- let orig_center: i32 = base_matrix_size / 2;
- let center: i32 = matrix_size / 2;
- {
- let mut i: i32 = 0;
- while i < orig_center {
- {
- let new_offset: i32 = i + i / 15;
- alignment_map[orig_center - i - 1] = center - new_offset - 1;
- alignment_map[orig_center + i] = center + new_offset + 1;
- }
- i += 1;
- }
- }
-
- }
- let matrix: BitMatrix = BitMatrix::new(matrix_size);
- // draw data bits
- {
- let mut i: i32 = 0, let row_offset: i32 = 0;
- while i < layers {
- {
- let row_size: i32 = (layers - i) * 4 + ( if compact { 9 } else { 12 });
- {
- let mut j: i32 = 0;
- while j < row_size {
- {
- let column_offset: i32 = j * 2;
- {
- let mut k: i32 = 0;
- while k < 2 {
- {
- if message_bits.get(row_offset + column_offset + k) {
- matrix.set(alignment_map[i * 2 + k], alignment_map[i * 2 + j]);
- }
- if message_bits.get(row_offset + row_size * 2 + column_offset + k) {
- matrix.set(alignment_map[i * 2 + j], alignment_map[base_matrix_size - 1 - i * 2 - k]);
- }
- if message_bits.get(row_offset + row_size * 4 + column_offset + k) {
- matrix.set(alignment_map[base_matrix_size - 1 - i * 2 - k], alignment_map[base_matrix_size - 1 - i * 2 - j]);
- }
- if message_bits.get(row_offset + row_size * 6 + column_offset + k) {
- matrix.set(alignment_map[base_matrix_size - 1 - i * 2 - j], alignment_map[i * 2 + k]);
- }
- }
- k += 1;
- }
- }
-
- }
- j += 1;
- }
- }
-
- row_offset += row_size * 8;
- }
- i += 1;
- }
- }
-
- // draw mode message
- ::draw_mode_message(matrix, compact, matrix_size, mode_message);
- // draw alignment marks
- if compact {
- ::draw_bulls_eye(matrix, matrix_size / 2, 5);
- } else {
- ::draw_bulls_eye(matrix, matrix_size / 2, 7);
- {
- let mut i: i32 = 0, let mut j: i32 = 0;
- while i < base_matrix_size / 2 - 1 {
- {
- {
- let mut k: i32 = (matrix_size / 2) & 1;
- while k < matrix_size {
- {
- matrix.set(matrix_size / 2 - j, k);
- matrix.set(matrix_size / 2 + j, k);
- matrix.set(k, matrix_size / 2 - j);
- matrix.set(k, matrix_size / 2 + j);
- }
- k += 2;
- }
- }
-
- }
- i += 15;
- j += 16;
- }
- }
-
- }
- let aztec: AztecCode = AztecCode::new();
- aztec.set_compact(compact);
- aztec.set_size(matrix_size);
- aztec.set_layers(layers);
- aztec.set_code_words(message_size_in_words);
- aztec.set_matrix(matrix);
- return aztec;
- }
-
- fn draw_bulls_eye( matrix: &BitMatrix, center: i32, size: i32) {
- {
- let mut i: i32 = 0;
- while i < size {
- {
- {
- let mut j: i32 = center - i;
- while j <= center + i {
- {
- matrix.set(j, center - i);
- matrix.set(j, center + i);
- matrix.set(center - i, j);
- matrix.set(center + i, j);
- }
- j += 1;
- }
- }
-
- }
- i += 2;
- }
- }
-
- matrix.set(center - size, center - size);
- matrix.set(center - size + 1, center - size);
- matrix.set(center - size, center - size + 1);
- matrix.set(center + size, center - size);
- matrix.set(center + size, center - size + 1);
- matrix.set(center + size, center + size - 1);
- }
-
- fn generate_mode_message( compact: bool, layers: i32, message_size_in_words: i32) -> BitArray {
- let mode_message: BitArray = BitArray::new();
- if compact {
- mode_message.append_bits(layers - 1, 2);
- mode_message.append_bits(message_size_in_words - 1, 6);
- mode_message = ::generate_check_words(mode_message, 28, 4);
- } else {
- mode_message.append_bits(layers - 1, 5);
- mode_message.append_bits(message_size_in_words - 1, 11);
- mode_message = ::generate_check_words(mode_message, 40, 4);
- }
- return mode_message;
- }
-
- fn draw_mode_message( matrix: &BitMatrix, compact: bool, matrix_size: i32, mode_message: &BitArray) {
- let center: i32 = matrix_size / 2;
- if compact {
- {
- let mut i: i32 = 0;
- while i < 7 {
- {
- let offset: i32 = center - 3 + i;
- if mode_message.get(i) {
- matrix.set(offset, center - 5);
- }
- if mode_message.get(i + 7) {
- matrix.set(center + 5, offset);
- }
- if mode_message.get(20 - i) {
- matrix.set(offset, center + 5);
- }
- if mode_message.get(27 - i) {
- matrix.set(center - 5, offset);
- }
- }
- i += 1;
- }
- }
-
- } else {
- {
- let mut i: i32 = 0;
- while i < 10 {
- {
- let offset: i32 = center - 5 + i + i / 5;
- if mode_message.get(i) {
- matrix.set(offset, center - 7);
- }
- if mode_message.get(i + 10) {
- matrix.set(center + 7, offset);
- }
- if mode_message.get(29 - i) {
- matrix.set(offset, center + 7);
- }
- if mode_message.get(39 - i) {
- matrix.set(center - 7, offset);
- }
- }
- i += 1;
- }
- }
-
- }
- }
-
- fn generate_check_words( bit_array: &BitArray, total_bits: i32, word_size: i32) -> BitArray {
- // bitArray is guaranteed to be a multiple of the wordSize, so no padding needed
- let message_size_in_words: i32 = bit_array.get_size() / word_size;
- let rs: ReedSolomonEncoder = ReedSolomonEncoder::new(&::get_g_f(word_size));
- let total_words: i32 = total_bits / word_size;
- let message_words: Vec = ::bits_to_words(bit_array, word_size, total_words);
- rs.encode(&message_words, total_words - message_size_in_words);
- let start_pad: i32 = total_bits % word_size;
- let message_bits: BitArray = BitArray::new();
- message_bits.append_bits(0, start_pad);
- for let message_word: i32 in message_words {
- message_bits.append_bits(message_word, word_size);
- }
- return message_bits;
- }
-
- fn bits_to_words( stuffed_bits: &BitArray, word_size: i32, total_words: i32) -> Vec {
- let mut message: [i32; total_words] = [0; total_words];
- let mut i: i32;
- let mut n: i32;
- {
- i = 0;
- n = stuffed_bits.get_size() / word_size;
- while i < n {
- {
- let mut value: i32 = 0;
- {
- let mut j: i32 = 0;
- while j < word_size {
- {
- value |= if stuffed_bits.get(i * word_size + j) { (1 << word_size - j - 1) } else { 0 };
- }
- j += 1;
- }
- }
-
- message[i] = value;
- }
- i += 1;
- }
- }
-
- return message;
- }
-
- fn get_g_f( word_size: i32) -> GenericGF {
- match word_size {
- 4 =>
- {
- return GenericGF::AZTEC_PARAM;
- }
- 6 =>
- {
- return GenericGF::AZTEC_DATA_6;
- }
- 8 =>
- {
- return GenericGF::AZTEC_DATA_8;
- }
- 10 =>
- {
- return GenericGF::AZTEC_DATA_10;
- }
- 12 =>
- {
- return GenericGF::AZTEC_DATA_12;
- }
- _ =>
- {
- throw IllegalArgumentException::new(format!("Unsupported word size {}", word_size));
- }
- }
- }
-
- fn stuff_bits( bits: &BitArray, word_size: i32) -> BitArray {
- let out: BitArray = BitArray::new();
- let n: i32 = bits.get_size();
- let mask: i32 = (1 << word_size) - 2;
- {
- let mut i: i32 = 0;
- while i < n {
- {
- let mut word: i32 = 0;
- {
- let mut j: i32 = 0;
- while j < word_size {
- {
- if i + j >= n || bits.get(i + j) {
- word |= 1 << (word_size - 1 - j);
- }
- }
- j += 1;
- }
- }
-
- if (word & mask) == mask {
- out.append_bits(word & mask, word_size);
- i -= 1;
- } else if (word & mask) == 0 {
- out.append_bits(word | 1, word_size);
- i -= 1;
- } else {
- out.append_bits(word, word_size);
- }
- }
- i += word_size;
- }
- }
-
- return out;
- }
-
- fn total_bits_in_layer( layers: i32, compact: bool) -> i32 {
- return (( if compact { 88 } else { 112 }) + 16 * layers) * layers;
- }
-}
-
diff --git a/port_src/output/zxing/aztec/encoder/high_level_encoder.rs b/port_src/output/zxing/aztec/encoder/high_level_encoder.rs
deleted file mode 100644
index e3de129..0000000
--- a/port_src/output/zxing/aztec/encoder/high_level_encoder.rs
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright 2013 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::aztec::encoder;
-
-/**
- * This produces nearly optimal encodings of text into the first-level of
- * encoding used by Aztec code.
- *
- * It uses a dynamic algorithm. For each prefix of the string, it determines
- * a set of encodings that could lead to this prefix. We repeatedly add a
- * character and generate a new set of optimal encodings until we have read
- * through the entire input.
- *
- * @author Frank Yellin
- * @author Rustam Abdullaev
- */
-
- const MODE_NAMES: vec![Vec; 5] = vec!["UPPER", "LOWER", "DIGIT", "MIXED", "PUNCT", ]
-;
-
-// 5 bits
- const MODE_UPPER: i32 = 0;
-
-// 5 bits
- const MODE_LOWER: i32 = 1;
-
-// 4 bits
- const MODE_DIGIT: i32 = 2;
-
-// 5 bits
- const MODE_MIXED: i32 = 3;
-
-// 5 bits
- const MODE_PUNCT: i32 = 4;
-
-// The Latch Table shows, for each pair of Modes, the optimal method for
-// getting from one mode to another. In the worst possible case, this can
-// be up to 14 bits. In the best possible case, we are already there!
-// The high half-word of each entry gives the number of bits.
-// The low half-word of each entry are the actual bits necessary to change
- const LATCH_TABLE: vec![vec![Vec>; 5]; 5] = vec![vec![0, // UPPER -> LOWER
-(5 << 16) + 28, // UPPER -> DIGIT
-(5 << 16) + 30, // UPPER -> MIXED
-(5 << 16) + 29, // UPPER -> MIXED -> PUNCT
-(10 << 16) + (29 << 5) + 30, ]
-, vec![// LOWER -> DIGIT -> UPPER
-(9 << 16) + (30 << 4) + 14, 0, // LOWER -> DIGIT
-(5 << 16) + 30, // LOWER -> MIXED
-(5 << 16) + 29, // LOWER -> MIXED -> PUNCT
-(10 << 16) + (29 << 5) + 30, ]
-, vec![// DIGIT -> UPPER
-(4 << 16) + 14, // DIGIT -> UPPER -> LOWER
-(9 << 16) + (14 << 5) + 28, 0, // DIGIT -> UPPER -> MIXED
-(9 << 16) + (14 << 5) + 29, (14 << 16) + (14 << 10) + (29 << 5) + 30, ]
-, vec![// MIXED -> UPPER
-(5 << 16) + 29, // MIXED -> LOWER
-(5 << 16) + 28, // MIXED -> UPPER -> DIGIT
-(10 << 16) + (29 << 5) + 30, 0, // MIXED -> PUNCT
-(5 << 16) + 30, ]
-, vec![// PUNCT -> UPPER
-(5 << 16) + 31, // PUNCT -> UPPER -> LOWER
-(10 << 16) + (31 << 5) + 28, // PUNCT -> UPPER -> DIGIT
-(10 << 16) + (31 << 5) + 30, // PUNCT -> UPPER -> MIXED
-(10 << 16) + (31 << 5) + 29, 0, ]
-, ]
-;
-
-// A reverse mapping from [mode][char] to the encoding for that character
-// in that mode. An entry of 0 indicates no mapping exists.
- const CHAR_MAP: [[i32; 256]; 5] = [[0; 256]; 5];
-
-// A map showing the available shift codes. (The shifts to BINARY are not
-// shown
-// mode shift codes, per table
- const SHIFT_TABLE: [[i32; 6]; 6] = [[0; 6]; 6];
-pub struct HighLevelEncoder {
-
- let text: Vec;
-
- let mut charset: Charset;
-}
-
-impl HighLevelEncoder {
-
- static {
- CHAR_MAP[MODE_UPPER][' '] = 1;
- {
- let mut c: i32 = 'A';
- while c <= 'Z' {
- {
- CHAR_MAP[MODE_UPPER][c] = c - 'A' + 2;
- }
- c += 1;
- }
- }
-
- CHAR_MAP[MODE_LOWER][' '] = 1;
- {
- let mut c: i32 = 'a';
- while c <= 'z' {
- {
- CHAR_MAP[MODE_LOWER][c] = c - 'a' + 2;
- }
- c += 1;
- }
- }
-
- CHAR_MAP[MODE_DIGIT][' '] = 1;
- {
- let mut c: i32 = '0';
- while c <= '9' {
- {
- CHAR_MAP[MODE_DIGIT][c] = c - '0' + 2;
- }
- c += 1;
- }
- }
-
- CHAR_MAP[MODE_DIGIT][','] = 12;
- CHAR_MAP[MODE_DIGIT]['.'] = 13;
- let mixed_table: vec![Vec; 28] = vec!['\0', ' ', '\1', '\2', '\3', '\4', '\5', '\6', '\7', '\b', '\t', '\n', '\13', '\f', '\r', '\33', '\34', '\35', '\36', '\37', '@', '\\', '^', '_', '`', '|', '~', '\177', ]
- ;
- {
- let mut i: i32 = 0;
- while i < mixed_table.len() {
- {
- CHAR_MAP[MODE_MIXED][mixed_table[i]] = i;
- }
- i += 1;
- }
- }
-
- let punct_table: vec![Vec; 31] = vec!['\0', '\r', '\0', '\0', '\0', '\0', '!', '\'', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '{', '}', ]
- ;
- {
- let mut i: i32 = 0;
- while i < punct_table.len() {
- {
- if punct_table[i] > 0 {
- CHAR_MAP[MODE_PUNCT][punct_table[i]] = i;
- }
- }
- i += 1;
- }
- }
-
- }
-
- static {
- for let table: Vec in SHIFT_TABLE {
- Arrays::fill(&table, -1);
- }
- SHIFT_TABLE[MODE_UPPER][MODE_PUNCT] = 0;
- SHIFT_TABLE[MODE_LOWER][MODE_PUNCT] = 0;
- SHIFT_TABLE[MODE_LOWER][MODE_UPPER] = 28;
- SHIFT_TABLE[MODE_MIXED][MODE_PUNCT] = 0;
- SHIFT_TABLE[MODE_DIGIT][MODE_PUNCT] = 0;
- SHIFT_TABLE[MODE_DIGIT][MODE_UPPER] = 15;
- }
-
- pub fn new( text: &Vec) -> HighLevelEncoder {
- let .text = text;
- let .charset = null;
- }
-
- pub fn new( text: &Vec, charset: &Charset) -> HighLevelEncoder {
- let .text = text;
- let .charset = charset;
- }
-
- /**
- * @return text represented by this encoder encoded as a {@link BitArray}
- */
- pub fn encode(&self) -> BitArray {
- let initial_state: State = State::INITIAL_STATE;
- if self.charset != null {
- let eci: CharacterSetECI = CharacterSetECI::get_character_set_e_c_i(&self.charset);
- if null == eci {
- throw IllegalArgumentException::new(format!("No ECI code for character set {}", self.charset));
- }
- initial_state = initial_state.append_f_l_gn(&eci.get_value());
- }
- let mut states: Collection = Collections::singleton_list(initial_state);
- {
- let mut index: i32 = 0;
- while index < self.text.len() {
- {
- let pair_code: i32;
- let next_char: i32 = if index + 1 < self.text.len() { self.text[index + 1] } else { 0 };
- match self.text[index] {
- '\r' =>
- {
- pair_code = if next_char == '\n' { 2 } else { 0 };
- break;
- }
- '.' =>
- {
- pair_code = if next_char == ' ' { 3 } else { 0 };
- break;
- }
- ',' =>
- {
- pair_code = if next_char == ' ' { 4 } else { 0 };
- break;
- }
- ':' =>
- {
- pair_code = if next_char == ' ' { 5 } else { 0 };
- break;
- }
- _ =>
- {
- pair_code = 0;
- }
- }
- if pair_code > 0 {
- // We have one of the four special PUNCT pairs. Treat them specially.
- // Get a new set of states for the two new characters.
- states = ::update_state_list_for_pair(&states, index, pair_code);
- index += 1;
- } else {
- // Get a new set of states for the new character.
- states = self.update_state_list_for_char(&states, index);
- }
- }
- index += 1;
- }
- }
-
- // We are left with a set of states. Find the shortest one.
- let min_state: State = Collections::min(&states, Comparator::new() {
-
- pub fn compare(&self, a: &State, b: &State) -> i32 {
- return a.get_bit_count() - b.get_bit_count();
- }
- });
- // Convert it to a bit array, and return.
- return min_state.to_bit_array(&self.text);
- }
-
- // We update a set of states for a new character by updating each state
- // for the new character, merging the results, and then removing the
- // non-optimal states.
- fn update_state_list_for_char(&self, states: &Iterable, index: i32) -> Collection {
- let result: Collection = LinkedList<>::new();
- for let state: State in states {
- self.update_state_for_char(state, index, &result);
- }
- return ::simplify_states(&result);
- }
-
- // Return a set of states that represent the possible ways of updating this
- // state for the next character. The resulting set of states are added to
- // the "result" list.
- fn update_state_for_char(&self, state: &State, index: i32, result: &Collection) {
- let ch: char = (self.text[index] & 0xFF) as char;
- let char_in_current_table: bool = CHAR_MAP[state.get_mode()][ch] > 0;
- let state_no_binary: State = null;
- {
- let mut mode: i32 = 0;
- while mode <= MODE_PUNCT {
- {
- let char_in_mode: i32 = CHAR_MAP[mode][ch];
- if char_in_mode > 0 {
- if state_no_binary == null {
- // Only create stateNoBinary the first time it's required.
- state_no_binary = state.end_binary_shift(index);
- }
- // Try generating the character by latching to its mode
- if !char_in_current_table || mode == state.get_mode() || mode == MODE_DIGIT {
- // If the character is in the current table, we don't want to latch to
- // any other mode except possibly digit (which uses only 4 bits). Any
- // other latch would be equally successful *after* this character, and
- // so wouldn't save any bits.
- let latch_state: State = state_no_binary.latch_and_append(mode, char_in_mode);
- result.add(latch_state);
- }
- // Try generating the character by switching to its mode.
- if !char_in_current_table && SHIFT_TABLE[state.get_mode()][mode] >= 0 {
- // It never makes sense to temporarily shift to another mode if the
- // character exists in the current mode. That can never save bits.
- let shift_state: State = state_no_binary.shift_and_append(mode, char_in_mode);
- result.add(shift_state);
- }
- }
- }
- mode += 1;
- }
- }
-
- if state.get_binary_shift_byte_count() > 0 || CHAR_MAP[state.get_mode()][ch] == 0 {
- // It's never worthwhile to go into binary shift mode if you're not already
- // in binary shift mode, and the character exists in your current mode.
- // That can never save bits over just outputting the char in the current mode.
- let binary_state: State = state.add_binary_shift_char(index);
- result.add(binary_state);
- }
- }
-
- fn update_state_list_for_pair( states: &Iterable, index: i32, pair_code: i32) -> Collection {
- let result: Collection = LinkedList<>::new();
- for let state: State in states {
- ::update_state_for_pair(state, index, pair_code, &result);
- }
- return ::simplify_states(&result);
- }
-
- fn update_state_for_pair( state: &State, index: i32, pair_code: i32, result: &Collection) {
- let state_no_binary: State = state.end_binary_shift(index);
- // Possibility 1. Latch to MODE_PUNCT, and then append this code
- result.add(&state_no_binary.latch_and_append(MODE_PUNCT, pair_code));
- if state.get_mode() != MODE_PUNCT {
- // Possibility 2. Shift to MODE_PUNCT, and then append this code.
- // Every state except MODE_PUNCT (handled above) can shift
- result.add(&state_no_binary.shift_and_append(MODE_PUNCT, pair_code));
- }
- if pair_code == 3 || pair_code == 4 {
- // both characters are in DIGITS. Sometimes better to just add two digits
- let digit_state: State = state_no_binary.latch_and_append(MODE_DIGIT, // period or comma in DIGIT
- 16 - pair_code).latch_and_append(MODE_DIGIT, // space in DIGIT
- 1);
- result.add(digit_state);
- }
- if state.get_binary_shift_byte_count() > 0 {
- // It only makes sense to do the characters as binary if we're already
- // in binary mode.
- let binary_state: State = state.add_binary_shift_char(index).add_binary_shift_char(index + 1);
- result.add(binary_state);
- }
- }
-
- fn simplify_states( states: &Iterable) -> Collection {
- let result: Deque = LinkedList<>::new();
- for let new_state: State in states {
- let mut add: bool = true;
- {
- let iterator: Iterator = result.iterator();
- while iterator.has_next(){
- let old_state: State = iterator.next();
- if old_state.is_better_than_or_equal_to(new_state) {
- add = false;
- break;
- }
- if new_state.is_better_than_or_equal_to(old_state) {
- iterator.remove();
- }
- }
- }
-
- if add {
- result.add_first(new_state);
- }
- }
- return result;
- }
-}
-
diff --git a/port_src/output/zxing/aztec/encoder/simple_token.rs b/port_src/output/zxing/aztec/encoder/simple_token.rs
deleted file mode 100644
index 2a332f6..0000000
--- a/port_src/output/zxing/aztec/encoder/simple_token.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2013 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::aztec::encoder;
-
-struct SimpleToken {
- super: Token;
-
- // For normal words, indicates value and bitCount
- let value: i16;
-
- let bit_count: i16;
-}
-
-impl SimpleToken {
-
- fn new( previous: &Token, value: i32, bit_count: i32) -> SimpleToken {
- super(previous);
- let .value = value as i16;
- let .bitCount = bit_count as i16;
- }
-
- fn append_to(&self, bit_array: &BitArray, text: &Vec) {
- bit_array.append_bits(self.value, self.bit_count);
- }
-
- pub fn to_string(&self) -> String {
- let mut value: i32 = self.value & ((1 << self.bit_count) - 1);
- value |= 1 << self.bit_count;
- return '<' + Integer::to_binary_string(value | (1 << self.bit_count))::substring(1) + '>';
- }
-}
-
diff --git a/port_src/output/zxing/aztec/encoder/state.rs b/port_src/output/zxing/aztec/encoder/state.rs
deleted file mode 100644
index fa4f17a..0000000
--- a/port_src/output/zxing/aztec/encoder/state.rs
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright 2013 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::aztec::encoder;
-
-/**
- * State represents all information about a sequence necessary to generate the current output.
- * Note that a state is immutable.
- */
-
- const INITIAL_STATE: State = State::new(Token::EMPTY, HighLevelEncoder::MODE_UPPER, 0, 0);
-struct State {
-
- // The current mode of the encoding (or the mode to which we'll return if
- // we're in Binary Shift mode.
- let mode: i32;
-
- // The list of tokens that we output. If we are in Binary Shift mode, this
- // token list does *not* yet included the token for those bytes
- let token: Token;
-
- // If non-zero, the number of most recent bytes that should be output
- // in Binary Shift mode.
- let binary_shift_byte_count: i32;
-
- // The total number of bits generated (including Binary Shift).
- let bit_count: i32;
-
- let binary_shift_cost: i32;
-}
-
-impl State {
-
- fn new( token: &Token, mode: i32, binary_bytes: i32, bit_count: i32) -> State {
- let .token = token;
- let .mode = mode;
- let .binaryShiftByteCount = binary_bytes;
- let .bitCount = bit_count;
- let .binaryShiftCost = ::calculate_binary_shift_cost(binary_bytes);
- }
-
- fn get_mode(&self) -> i32 {
- return self.mode;
- }
-
- fn get_token(&self) -> Token {
- return self.token;
- }
-
- fn get_binary_shift_byte_count(&self) -> i32 {
- return self.binary_shift_byte_count;
- }
-
- fn get_bit_count(&self) -> i32 {
- return self.bit_count;
- }
-
- fn append_f_l_gn(&self, eci: i32) -> State {
- // 0: FLG(n)
- let result: State = self.shift_and_append(HighLevelEncoder::MODE_PUNCT, 0);
- let mut token: Token = result.token;
- let bits_added: i32 = 3;
- if eci < 0 {
- // 0: FNC1
- token = token.add(0, 3);
- } else if eci > 999999 {
- throw IllegalArgumentException::new("ECI code must be between 0 and 999999");
- } else {
- let eci_digits: Vec = Integer::to_string(eci)::get_bytes(StandardCharsets::ISO_8859_1);
- // 1-6: number of ECI digits
- token = token.add(eci_digits.len(), 3);
- for let eci_digit: i8 in eci_digits {
- token = token.add(eci_digit - '0' + 2, 4);
- }
- bits_added += eci_digits.len() * 4;
- }
- return State::new(token, self.mode, 0, self.bit_count + bits_added);
- }
-
- // Create a new state representing this state with a latch to a (not
- // necessary different) mode, and then a code.
- fn latch_and_append(&self, mode: i32, value: i32) -> State {
- let bit_count: i32 = self.bitCount;
- let mut token: Token = self.token;
- if mode != self.mode {
- let latch: i32 = HighLevelEncoder::LATCH_TABLE[self.mode][mode];
- token = token.add(latch & 0xFFFF, latch >> 16);
- bit_count += latch >> 16;
- }
- let latch_mode_bit_count: i32 = if mode == HighLevelEncoder::MODE_DIGIT { 4 } else { 5 };
- token = token.add(value, latch_mode_bit_count);
- return State::new(token, mode, 0, bit_count + latch_mode_bit_count);
- }
-
- // Create a new state representing this state, with a temporary shift
- // to a different mode to output a single value.
- fn shift_and_append(&self, mode: i32, value: i32) -> State {
- let mut token: Token = self.token;
- let this_mode_bit_count: i32 = if self.mode == HighLevelEncoder::MODE_DIGIT { 4 } else { 5 };
- // Shifts exist only to UPPER and PUNCT, both with tokens size 5.
- token = token.add(HighLevelEncoder::SHIFT_TABLE[self.mode][mode], this_mode_bit_count);
- token = token.add(value, 5);
- return State::new(token, self.mode, 0, self.bitCount + this_mode_bit_count + 5);
- }
-
- // Create a new state representing this state, but an additional character
- // output in Binary Shift mode.
- fn add_binary_shift_char(&self, index: i32) -> State {
- let mut token: Token = self.token;
- let mut mode: i32 = self.mode;
- let bit_count: i32 = self.bitCount;
- if self.mode == HighLevelEncoder::MODE_PUNCT || self.mode == HighLevelEncoder::MODE_DIGIT {
- let latch: i32 = HighLevelEncoder::LATCH_TABLE[mode][HighLevelEncoder::MODE_UPPER];
- token = token.add(latch & 0xFFFF, latch >> 16);
- bit_count += latch >> 16;
- mode = HighLevelEncoder::MODE_UPPER;
- }
- let delta_bit_count: i32 = if (self.binary_shift_byte_count == 0 || self.binary_shift_byte_count == 31) { 18 } else { if (self.binary_shift_byte_count == 62) { 9 } else { 8 } };
- let mut result: State = State::new(token, mode, self.binary_shift_byte_count + 1, bit_count + delta_bit_count);
- if result.binaryShiftByteCount == 2047 + 31 {
- // The string is as long as it's allowed to be. We should end it.
- result = result.end_binary_shift(index + 1);
- }
- return result;
- }
-
- // Create the state identical to this one, but we are no longer in
- // Binary Shift mode.
- fn end_binary_shift(&self, index: i32) -> State {
- if self.binary_shift_byte_count == 0 {
- return self;
- }
- let mut token: Token = self.token;
- token = token.add_binary_shift(index - self.binary_shift_byte_count, self.binary_shift_byte_count);
- return State::new(token, self.mode, 0, self.bitCount);
- }
-
- // Returns true if "this" state is better (or equal) to be in than "that"
- // state under all possible circumstances.
- fn is_better_than_or_equal_to(&self, other: &State) -> bool {
- let new_mode_bit_count: i32 = self.bitCount + (HighLevelEncoder::LATCH_TABLE[self.mode][other.mode] >> 16);
- if self.binaryShiftByteCount < other.binaryShiftByteCount {
- // add additional B/S encoding cost of other, if any
- new_mode_bit_count += other.binaryShiftCost - self.binaryShiftCost;
- } else if self.binaryShiftByteCount > other.binaryShiftByteCount && other.binaryShiftByteCount > 0 {
- // maximum possible additional cost (we end up exceeding the 31 byte boundary and other state can stay beneath it)
- new_mode_bit_count += 10;
- }
- return new_mode_bit_count <= other.bitCount;
- }
-
- fn to_bit_array(&self, text: &Vec) -> BitArray {
- let symbols: List = ArrayList<>::new();
- {
- let mut token: Token = self.end_binary_shift(text.len()).token;
- while token != null {
- {
- symbols.add(token);
- }
- token = token.get_previous();
- }
- }
-
- let bit_array: BitArray = BitArray::new();
- // Add each token to the result in forward order
- {
- let mut i: i32 = symbols.size() - 1;
- while i >= 0 {
- {
- symbols.get(i).append_to(bit_array, &text);
- }
- i -= 1;
- }
- }
-
- return bit_array;
- }
-
- pub fn to_string(&self) -> String {
- return String::format("%s bits=%d bytes=%d", HighLevelEncoder::MODE_NAMES[self.mode], self.bit_count, self.binary_shift_byte_count);
- }
-
- fn calculate_binary_shift_cost( binary_shift_byte_count: i32) -> i32 {
- if binary_shift_byte_count > 62 {
- // B/S with extended length
- return 21;
- }
- if binary_shift_byte_count > 31 {
- // two B/S
- return 20;
- }
- if binary_shift_byte_count > 0 {
- // one B/S
- return 10;
- }
- return 0;
- }
-}
-
diff --git a/port_src/output/zxing/aztec/encoder/token.rs b/port_src/output/zxing/aztec/encoder/token.rs
deleted file mode 100644
index 04bd0f5..0000000
--- a/port_src/output/zxing/aztec/encoder/token.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2013 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::aztec::encoder;
-
-
- const EMPTY: Token = SimpleToken::new(null, 0, 0);
-struct Token {
-
- let previous: Token;
-}
-
-impl Token {
-
- fn new( previous: &Token) -> Token {
- let .previous = previous;
- }
-
- fn get_previous(&self) -> Token {
- return self.previous;
- }
-
- fn add(&self, value: i32, bit_count: i32) -> Token {
- return SimpleToken::new(self, value, bit_count);
- }
-
- fn add_binary_shift(&self, start: i32, byte_count: i32) -> Token {
- //int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);
- return BinaryShiftToken::new(self, start, byte_count);
- }
-
- fn append_to(&self, bit_array: &BitArray, text: &Vec) ;
-}
-
diff --git a/src/aztec.rs b/src/aztec.rs
index 9f06192..25fa82c 100644
--- a/src/aztec.rs
+++ b/src/aztec.rs
@@ -1,5 +1,232 @@
+pub mod decoder;
+pub mod detector;
+pub mod encoder;
+
+use crate::{ResultPoint,BarcodeFormat,EncodeHintType,Writer,Reader};
+use crate::common::{BitMatrix,DetectorResult,DecoderResult};
+use crate::{BarcodeFormat,BinaryBitmap,DecodeHintType,FormatException,NotFoundException,Reader,Result,ResultMetadataType,ResultPoint,ResultPointCallback};
+use crate::aztec::decoder::Decoder;
+use crate::aztec::detector::Detector;
+
+use crate::aztec::encoder{AztecCode,Encoder};
+
+
// AztecDetectorResult.java
+/**
+ * Extends {@link DetectorResult} with more information specific to the Aztec format,
+ * like the number of layers and whether it's compact.
+ *
+ * @author Sean Owen
+ */
+pub struct AztecDetectorResult {
+ super: DetectorResult;
+
+ let compact: bool;
+
+ let nb_datablocks: i32;
+
+ let nb_layers: i32;
+}
+
+impl DetectorResult for AztecDetectorResult {
+
+}
+
+impl AztecDetectorResult {
+
+ pub fn new( bits: &BitMatrix, points: &Vec, compact: bool, nb_datablocks: i32, nb_layers: i32) -> AztecDetectorResult {
+ super(bits, points);
+ let .compact = compact;
+ let .nbDatablocks = nb_datablocks;
+ let .nbLayers = nb_layers;
+ }
+
+ pub fn get_nb_layers(&self) -> i32 {
+ return self.nb_layers;
+ }
+
+ pub fn get_nb_datablocks(&self) -> i32 {
+ return self.nb_datablocks;
+ }
+
+ pub fn is_compact(&self) -> bool {
+ return self.compact;
+ }
+}
// AztecReader.java
-// AztecWriter.java
\ No newline at end of file
+/**
+ * This implementation can detect and decode Aztec codes in an image.
+ *
+ * @author David Olivier
+ */
+pub struct AztecReader {
+}
+
+impl Reader for AztecReader {
+
+ /**
+ * Locates and decodes a Data Matrix code in an image.
+ *
+ * @return a String representing the content encoded by the Data Matrix code
+ * @throws NotFoundException if a Data Matrix code cannot be found
+ * @throws FormatException if a Data Matrix code cannot be decoded
+ */
+ pub fn decode(&self, image: &BinaryBitmap) -> /* throws NotFoundException, FormatException */Result> {
+ return Ok(self.decode(image, null));
+ }
+
+ pub fn decode(&self, image: &BinaryBitmap, hints: &Map) -> /* throws NotFoundException, FormatException */Result> {
+ let not_found_exception: NotFoundException = null;
+ let format_exception: FormatException = null;
+ let detector: Detector = Detector::new(&image.get_black_matrix());
+ let mut points: Vec = null;
+ let decoder_result: DecoderResult = null;
+ let tryResult1 = 0;
+ 'try1: loop {
+ {
+ let detector_result: AztecDetectorResult = detector.detect(false);
+ points = detector_result.get_points();
+ decoder_result = Decoder::new().decode(detector_result);
+ }
+ break 'try1
+ }
+ match tryResult1 {
+ catch ( e: &NotFoundException) {
+ not_found_exception = e;
+ } catch ( e: &FormatException) {
+ format_exception = e;
+ } 0 => break
+ }
+
+ if decoder_result == null {
+ let tryResult1 = 0;
+ 'try1: loop {
+ {
+ let detector_result: AztecDetectorResult = detector.detect(true);
+ points = detector_result.get_points();
+ decoder_result = Decoder::new().decode(detector_result);
+ }
+ break 'try1
+ }
+ match tryResult1 {
+ catch ( e: &NotFoundExceptionFormatException | ) {
+ if not_found_exception != null {
+ throw not_found_exception;
+ }
+ if format_exception != null {
+ throw format_exception;
+ }
+ throw e;
+ } 0 => break
+ }
+
+ }
+ if hints != null {
+ let rpcb: ResultPointCallback = hints.get(DecodeHintType::NEED_RESULT_POINT_CALLBACK) as ResultPointCallback;
+ if rpcb != null {
+ for let point: ResultPoint in points {
+ rpcb.found_possible_result_point(point);
+ }
+ }
+ }
+ let result: Result = Result::new(&decoder_result.get_text(), &decoder_result.get_raw_bytes(), &decoder_result.get_num_bits(), points, BarcodeFormat::AZTEC, &System::current_time_millis());
+ let byte_segments: List> = decoder_result.get_byte_segments();
+ if byte_segments != null {
+ result.put_metadata(ResultMetadataType::BYTE_SEGMENTS, &byte_segments);
+ }
+ let ec_level: String = decoder_result.get_e_c_level();
+ if ec_level != null {
+ result.put_metadata(ResultMetadataType::ERROR_CORRECTION_LEVEL, &ec_level);
+ }
+ result.put_metadata(ResultMetadataType::SYMBOLOGY_IDENTIFIER, format!("]z{}", decoder_result.get_symbology_modifier()));
+ return Ok(result);
+ }
+
+ pub fn reset(&self) {
+ // do nothing
+ }
+}
+
+// AztecWriter.java
+
+/**
+ * Renders an Aztec code as a {@link BitMatrix}.
+ */
+pub struct AztecWriter {
+}
+
+impl Writer for AztecWriter {
+
+ pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32) -> BitMatrix {
+ return ::encode(&contents, format, width, height, null);
+ }
+
+ pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32, hints: &Map) -> BitMatrix {
+ // Do not add any ECI code by default
+ let mut charset: Charset = null;
+ let ecc_percent: i32 = Encoder::DEFAULT_EC_PERCENT;
+ let mut layers: i32 = Encoder::DEFAULT_AZTEC_LAYERS;
+ if hints != null {
+ if hints.contains_key(EncodeHintType::CHARACTER_SET) {
+ charset = Charset::for_name(&hints.get(EncodeHintType::CHARACTER_SET).to_string());
+ }
+ if hints.contains_key(EncodeHintType::ERROR_CORRECTION) {
+ ecc_percent = Integer::parse_int(&hints.get(EncodeHintType::ERROR_CORRECTION).to_string());
+ }
+ if hints.contains_key(EncodeHintType::AZTEC_LAYERS) {
+ layers = Integer::parse_int(&hints.get(EncodeHintType::AZTEC_LAYERS).to_string());
+ }
+ }
+ return ::encode(&contents, format, width, height, &charset, ecc_percent, layers);
+ }
+
+ fn encode( contents: &String, format: &BarcodeFormat, width: i32, height: i32, charset: &Charset, ecc_percent: i32, layers: i32) -> BitMatrix {
+ if format != BarcodeFormat::AZTEC {
+ throw IllegalArgumentException::new(format!("Can only encode AZTEC, but got {}", format));
+ }
+ let aztec: AztecCode = Encoder::encode(&contents, ecc_percent, layers, &charset);
+ return ::render_result(aztec, width, height);
+ }
+
+ fn render_result( code: &AztecCode, width: i32, height: i32) -> BitMatrix {
+ let input: BitMatrix = code.get_matrix();
+ if input == null {
+ throw IllegalStateException::new();
+ }
+ let input_width: i32 = input.get_width();
+ let input_height: i32 = input.get_height();
+ let output_width: i32 = Math::max(width, input_width);
+ let output_height: i32 = Math::max(height, input_height);
+ let multiple: i32 = Math::min(output_width / input_width, output_height / input_height);
+ let left_padding: i32 = (output_width - (input_width * multiple)) / 2;
+ let top_padding: i32 = (output_height - (input_height * multiple)) / 2;
+ let output: BitMatrix = BitMatrix::new(output_width, output_height);
+ {
+ let input_y: i32 = 0, let output_y: i32 = top_padding;
+ while input_y < input_height {
+ {
+ // Write the contents of this row of the barcode
+ {
+ let input_x: i32 = 0, let output_x: i32 = left_padding;
+ while input_x < input_width {
+ {
+ if input.get(input_x, input_y) {
+ output.set_region(output_x, output_y, multiple, multiple);
+ }
+ }
+ input_x += 1;
+ output_x += multiple;
+ }
+ }
+
+ }
+ input_y += 1;
+ output_y += multiple;
+ }
+ }
+
+ return output;
+ }
+}
\ No newline at end of file
diff --git a/src/aztec/decoder.rs b/src/aztec/decoder.rs
index e69de29..db3bc99 100644
--- a/src/aztec/decoder.rs
+++ b/src/aztec/decoder.rs
@@ -0,0 +1,548 @@
+import com.google.zxing.FormatException;
+import com.google.zxing.aztec.AztecDetectorResult;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.common.CharacterSetECI;
+import com.google.zxing.common.DecoderResult;
+import com.google.zxing.common.reedsolomon.GenericGF;
+import com.google.zxing.common.reedsolomon.ReedSolomonDecoder;
+import com.google.zxing.common.reedsolomon.ReedSolomonException;
+
+/**
+ * The main class which implements Aztec Code decoding -- as opposed to locating and extracting
+ * the Aztec Code from an image.
+ *
+ * @author David Olivier
+ */
+
+const UPPER_TABLE: vec![Vec; 32] = vec!["CTRL_PS", " ", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "CTRL_LL", "CTRL_ML", "CTRL_DL", "CTRL_BS", ]
+;
+
+ const LOWER_TABLE: vec![Vec; 32] = vec!["CTRL_PS", " ", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "CTRL_US", "CTRL_ML", "CTRL_DL", "CTRL_BS", ]
+;
+
+ const MIXED_TABLE: vec![Vec; 32] = vec!["CTRL_PS", " ", "\1", "\2", "\3", "\4", "\5", "\6", "\7", "\b", "\t", "\n", "\13", "\f", "\r", "\33", "\34", "\35", "\36", "\37", "@", "\\", "^", "_", "`", "|", "~", "\177", "CTRL_LL", "CTRL_UL", "CTRL_PL", "CTRL_BS", ]
+;
+
+ const PUNCT_TABLE: vec![Vec; 32] = vec!["FLG(n)", "\r", "\r\n", ". ", ", ", ": ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", ":", ";", "<", "=", ">", "?", "[", "]", "{", "}", "CTRL_UL", ]
+;
+
+ const DIGIT_TABLE: vec![Vec; 16] = vec!["CTRL_PS", " ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ",", ".", "CTRL_UL", "CTRL_US", ]
+;
+
+ const DEFAULT_ENCODING: Charset = StandardCharsets::ISO_8859_1;
+pub struct Decoder {
+
+ let mut ddata: AztecDetectorResult;
+}
+
+impl Decoder {
+
+ enum Table {
+
+ UPPER(), LOWER(), MIXED(), DIGIT(), PUNCT(), BINARY()
+ }
+
+ pub fn decode(&self, detector_result: &AztecDetectorResult) -> /* throws FormatException */Result> {
+ self.ddata = detector_result;
+ let matrix: BitMatrix = detector_result.get_bits();
+ let rawbits: Vec = self.extract_bits(matrix);
+ let corrected_bits: CorrectedBitsResult = self.correct_bits(&rawbits);
+ let raw_bytes: Vec = ::convert_bool_array_to_byte_array(corrected_bits.correctBits);
+ let result: String = ::get_encoded_data(corrected_bits.correctBits);
+ let decoder_result: DecoderResult = DecoderResult::new(&raw_bytes, &result, null, &String::format("%d%%", corrected_bits.ecLevel));
+ decoder_result.set_num_bits(corrected_bits.correctBits.len());
+ return Ok(decoder_result);
+ }
+
+ // This method is used for testing the high-level encoder
+ pub fn high_level_decode( corrected_bits: &Vec) -> /* throws FormatException */Result> {
+ return Ok(::get_encoded_data(&corrected_bits));
+ }
+
+ /**
+ * Gets the string encoded in the aztec code bits
+ *
+ * @return the decoded string
+ */
+ fn get_encoded_data( corrected_bits: &Vec) -> /* throws FormatException */Result> {
+ let end_index: i32 = corrected_bits.len();
+ // table most recently latched to
+ let latch_table: Table = Table::UPPER;
+ // table to use for the next read
+ let shift_table: Table = Table::UPPER;
+ // Final decoded string result
+ // (correctedBits-5) / 4 is an upper bound on the size (all-digit result)
+ let result: StringBuilder = StringBuilder::new((corrected_bits.len() - 5) / 4);
+ // Intermediary buffer of decoded bytes, which is decoded into a string and flushed
+ // when character encoding changes (ECI) or input ends.
+ let decoded_bytes: ByteArrayOutputStream = ByteArrayOutputStream::new();
+ let mut encoding: Charset = DEFAULT_ENCODING;
+ let mut index: i32 = 0;
+ while index < end_index {
+ if shift_table == Table::BINARY {
+ if end_index - index < 5 {
+ break;
+ }
+ let mut length: i32 = ::read_code(&corrected_bits, index, 5);
+ index += 5;
+ if length == 0 {
+ if end_index - index < 11 {
+ break;
+ }
+ length = ::read_code(&corrected_bits, index, 11) + 31;
+ index += 11;
+ }
+ {
+ let char_count: i32 = 0;
+ while char_count < length {
+ {
+ if end_index - index < 8 {
+ // Force outer loop to exit
+ index = end_index;
+ break;
+ }
+ let code: i32 = ::read_code(&corrected_bits, index, 8);
+ decoded_bytes.write(code as i8);
+ index += 8;
+ }
+ char_count += 1;
+ }
+ }
+
+ // Go back to whatever mode we had been in
+ shift_table = latch_table;
+ } else {
+ let size: i32 = if shift_table == Table::DIGIT { 4 } else { 5 };
+ if end_index - index < size {
+ break;
+ }
+ let code: i32 = ::read_code(&corrected_bits, index, size);
+ index += size;
+ let str: String = ::get_character(shift_table, code);
+ if "FLG(n)".equals(&str) {
+ if end_index - index < 3 {
+ break;
+ }
+ let mut n: i32 = ::read_code(&corrected_bits, index, 3);
+ index += 3;
+ // flush bytes, FLG changes state
+ let tryResult1 = 0;
+ 'try1: loop {
+ {
+ result.append(&decoded_bytes.to_string(&encoding.name()));
+ }
+ break 'try1
+ }
+ match tryResult1 {
+ catch ( uee: &UnsupportedEncodingException) {
+ throw IllegalStateException::new(&uee);
+ } 0 => break
+ }
+
+ decoded_bytes.reset();
+ match n {
+ 0 =>
+ {
+ // translate FNC1 as ASCII 29
+ result.append(29 as char);
+ break;
+ }
+ 7 =>
+ {
+ // FLG(7) is reserved and illegal
+ throw FormatException::get_format_instance();
+ }
+ _ =>
+ {
+ // ECI is decimal integer encoded as 1-6 codes in DIGIT mode
+ let mut eci: i32 = 0;
+ if end_index - index < 4 * n {
+ break;
+ }
+ while n -= 1 !!!check!!! post decrement > 0 {
+ let next_digit: i32 = ::read_code(&corrected_bits, index, 4);
+ index += 4;
+ if next_digit < 2 || next_digit > 11 {
+ // Not a decimal digit
+ throw FormatException::get_format_instance();
+ }
+ eci = eci * 10 + (next_digit - 2);
+ }
+ let charset_e_c_i: CharacterSetECI = CharacterSetECI::get_character_set_e_c_i_by_value(eci);
+ if charset_e_c_i == null {
+ throw FormatException::get_format_instance();
+ }
+ encoding = charset_e_c_i.get_charset();
+ }
+ }
+ // Go back to whatever mode we had been in
+ shift_table = latch_table;
+ } else if str.starts_with("CTRL_") {
+ // Table changes
+ // ISO/IEC 24778:2008 prescribes ending a shift sequence in the mode from which it was invoked.
+ // That's including when that mode is a shift.
+ // Our test case dlusbs.png for issue #642 exercises that.
+ // Latch the current mode, so as to return to Upper after U/S B/S
+ latch_table = shift_table;
+ shift_table = ::get_table(&str.char_at(5));
+ if str.char_at(6) == 'L' {
+ latch_table = shift_table;
+ }
+ } else {
+ // Though stored as a table of strings for convenience, codes actually represent 1 or 2 *bytes*.
+ let b: Vec = str.get_bytes(StandardCharsets::US_ASCII);
+ decoded_bytes.write(&b, 0, b.len());
+ // Go back to whatever mode we had been in
+ shift_table = latch_table;
+ }
+ }
+ }
+ let tryResult1 = 0;
+ 'try1: loop {
+ {
+ result.append(&decoded_bytes.to_string(&encoding.name()));
+ }
+ break 'try1
+ }
+ match tryResult1 {
+ catch ( uee: &UnsupportedEncodingException) {
+ throw IllegalStateException::new(&uee);
+ } 0 => break
+ }
+
+ return Ok(result.to_string());
+ }
+
+ /**
+ * gets the table corresponding to the char passed
+ */
+ fn get_table( t: char) -> Table {
+ match t {
+ 'L' =>
+ {
+ return Table::LOWER;
+ }
+ 'P' =>
+ {
+ return Table::PUNCT;
+ }
+ 'M' =>
+ {
+ return Table::MIXED;
+ }
+ 'D' =>
+ {
+ return Table::DIGIT;
+ }
+ 'B' =>
+ {
+ return Table::BINARY;
+ }
+ 'U' =>
+ {
+ }
+ _ =>
+ {
+ return Table::UPPER;
+ }
+ }
+ }
+
+ /**
+ * Gets the character (or string) corresponding to the passed code in the given table
+ *
+ * @param table the table used
+ * @param code the code of the character
+ */
+ fn get_character( table: &Table, code: i32) -> String {
+ match table {
+ UPPER =>
+ {
+ return UPPER_TABLE[code];
+ }
+ LOWER =>
+ {
+ return LOWER_TABLE[code];
+ }
+ MIXED =>
+ {
+ return MIXED_TABLE[code];
+ }
+ PUNCT =>
+ {
+ return PUNCT_TABLE[code];
+ }
+ DIGIT =>
+ {
+ return DIGIT_TABLE[code];
+ }
+ _ =>
+ {
+ // Should not reach here.
+ throw IllegalStateException::new("Bad table");
+ }
+ }
+ }
+
+ struct CorrectedBitsResult {
+
+ let correct_bits: Vec;
+
+ let ec_level: i32;
+ }
+
+ impl CorrectedBitsResult {
+
+ fn new( correct_bits: &Vec, ec_level: i32) -> CorrectedBitsResult {
+ let .correctBits = correct_bits;
+ let .ecLevel = ec_level;
+ }
+ }
+
+
+ /**
+ * Performs RS error correction on an array of bits.
+ *
+ * @return the corrected array
+ * @throws FormatException if the input contains too many errors
+ */
+ fn correct_bits(&self, rawbits: &Vec) -> /* throws FormatException */Result> {
+ let mut gf: GenericGF;
+ let codeword_size: i32;
+ if self.ddata.get_nb_layers() <= 2 {
+ codeword_size = 6;
+ gf = GenericGF::AZTEC_DATA_6;
+ } else if self.ddata.get_nb_layers() <= 8 {
+ codeword_size = 8;
+ gf = GenericGF::AZTEC_DATA_8;
+ } else if self.ddata.get_nb_layers() <= 22 {
+ codeword_size = 10;
+ gf = GenericGF::AZTEC_DATA_10;
+ } else {
+ codeword_size = 12;
+ gf = GenericGF::AZTEC_DATA_12;
+ }
+ let num_data_codewords: i32 = self.ddata.get_nb_datablocks();
+ let num_codewords: i32 = rawbits.len() / codeword_size;
+ if num_codewords < num_data_codewords {
+ throw FormatException::get_format_instance();
+ }
+ let mut offset: i32 = rawbits.len() % codeword_size;
+ let data_words: [i32; num_codewords] = [0; num_codewords];
+ {
+ let mut i: i32 = 0;
+ while i < num_codewords {
+ {
+ data_words[i] = ::read_code(&rawbits, offset, codeword_size);
+ }
+ i += 1;
+ offset += codeword_size;
+ }
+ }
+
+ let tryResult1 = 0;
+ 'try1: loop {
+ {
+ let rs_decoder: ReedSolomonDecoder = ReedSolomonDecoder::new(gf);
+ rs_decoder.decode(&data_words, num_codewords - num_data_codewords);
+ }
+ break 'try1
+ }
+ match tryResult1 {
+ catch ( ex: &ReedSolomonException) {
+ throw FormatException::get_format_instance(ex);
+ } 0 => break
+ }
+
+ // Now perform the unstuffing operation.
+ // First, count how many bits are going to be thrown out as stuffing
+ let mask: i32 = (1 << codeword_size) - 1;
+ let stuffed_bits: i32 = 0;
+ {
+ let mut i: i32 = 0;
+ while i < num_data_codewords {
+ {
+ let data_word: i32 = data_words[i];
+ if data_word == 0 || data_word == mask {
+ throw FormatException::get_format_instance();
+ } else if data_word == 1 || data_word == mask - 1 {
+ stuffed_bits += 1;
+ }
+ }
+ i += 1;
+ }
+ }
+
+ // Now, actually unpack the bits and remove the stuffing
+ let corrected_bits: [bool; num_data_codewords * codeword_size - stuffed_bits] = [false; num_data_codewords * codeword_size - stuffed_bits];
+ let mut index: i32 = 0;
+ {
+ let mut i: i32 = 0;
+ while i < num_data_codewords {
+ {
+ let data_word: i32 = data_words[i];
+ if data_word == 1 || data_word == mask - 1 {
+ // next codewordSize-1 bits are all zeros or all ones
+ Arrays::fill(&corrected_bits, index, index + codeword_size - 1, data_word > 1);
+ index += codeword_size - 1;
+ } else {
+ {
+ let mut bit: i32 = codeword_size - 1;
+ while bit >= 0 {
+ {
+ corrected_bits[index += 1 !!!check!!! post increment] = (data_word & (1 << bit)) != 0;
+ }
+ bit -= 1;
+ }
+ }
+
+ }
+ }
+ i += 1;
+ }
+ }
+
+ return Ok(CorrectedBitsResult::new(&corrected_bits, 100 * (num_codewords - num_data_codewords) / num_codewords));
+ }
+
+ /**
+ * Gets the array of bits from an Aztec Code matrix
+ *
+ * @return the array of bits
+ */
+ fn extract_bits(&self, matrix: &BitMatrix) -> Vec {
+ let compact: bool = self.ddata.is_compact();
+ let layers: i32 = self.ddata.get_nb_layers();
+ // not including alignment lines
+ let base_matrix_size: i32 = ( if compact { 11 } else { 14 }) + layers * 4;
+ let alignment_map: [i32; base_matrix_size] = [0; base_matrix_size];
+ let mut rawbits: [bool; ::total_bits_in_layer(layers, compact)] = [false; ::total_bits_in_layer(layers, compact)];
+ if compact {
+ {
+ let mut i: i32 = 0;
+ while i < alignment_map.len() {
+ {
+ alignment_map[i] = i;
+ }
+ i += 1;
+ }
+ }
+
+ } else {
+ let matrix_size: i32 = base_matrix_size + 1 + 2 * ((base_matrix_size / 2 - 1) / 15);
+ let orig_center: i32 = base_matrix_size / 2;
+ let center: i32 = matrix_size / 2;
+ {
+ let mut i: i32 = 0;
+ while i < orig_center {
+ {
+ let new_offset: i32 = i + i / 15;
+ alignment_map[orig_center - i - 1] = center - new_offset - 1;
+ alignment_map[orig_center + i] = center + new_offset + 1;
+ }
+ i += 1;
+ }
+ }
+
+ }
+ {
+ let mut i: i32 = 0, let row_offset: i32 = 0;
+ while i < layers {
+ {
+ let row_size: i32 = (layers - i) * 4 + ( if compact { 9 } else { 12 });
+ // The top-left most point of this layer is (not including alignment lines)
+ let low: i32 = i * 2;
+ // The bottom-right most point of this layer is (not including alignment lines)
+ let high: i32 = base_matrix_size - 1 - low;
+ // We pull bits from the two 2 x rowSize columns and two rowSize x 2 rows
+ {
+ let mut j: i32 = 0;
+ while j < row_size {
+ {
+ let column_offset: i32 = j * 2;
+ {
+ let mut k: i32 = 0;
+ while k < 2 {
+ {
+ // left column
+ rawbits[row_offset + column_offset + k] = matrix.get(alignment_map[low + k], alignment_map[low + j]);
+ // bottom row
+ rawbits[row_offset + 2 * row_size + column_offset + k] = matrix.get(alignment_map[low + j], alignment_map[high - k]);
+ // right column
+ rawbits[row_offset + 4 * row_size + column_offset + k] = matrix.get(alignment_map[high - k], alignment_map[high - j]);
+ // top row
+ rawbits[row_offset + 6 * row_size + column_offset + k] = matrix.get(alignment_map[high - j], alignment_map[low + k]);
+ }
+ k += 1;
+ }
+ }
+
+ }
+ j += 1;
+ }
+ }
+
+ row_offset += row_size * 8;
+ }
+ i += 1;
+ }
+ }
+
+ return rawbits;
+ }
+
+ /**
+ * Reads a code of given length and at given index in an array of bits
+ */
+ fn read_code( rawbits: &Vec, start_index: i32, length: i32) -> i32 {
+ let mut res: i32 = 0;
+ {
+ let mut i: i32 = start_index;
+ while i < start_index + length {
+ {
+ res <<= 1;
+ if rawbits[i] {
+ res |= 0x01;
+ }
+ }
+ i += 1;
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * Reads a code of length 8 in an array of bits, padding with zeros
+ */
+ fn read_byte( rawbits: &Vec, start_index: i32) -> i8 {
+ let n: i32 = rawbits.len() - start_index;
+ if n >= 8 {
+ return ::read_code(&rawbits, start_index, 8) as i8;
+ }
+ return (::read_code(&rawbits, start_index, n) << (8 - n)) as i8;
+ }
+
+ /**
+ * Packs a bit array into bytes, most significant bit first
+ */
+ fn convert_bool_array_to_byte_array( bool_arr: &Vec) -> Vec {
+ let byte_arr: [i8; (bool_arr.len() + 7) / 8] = [0; (bool_arr.len() + 7) / 8];
+ {
+ let mut i: i32 = 0;
+ while i < byte_arr.len() {
+ {
+ byte_arr[i] = ::read_byte(&bool_arr, 8 * i);
+ }
+ i += 1;
+ }
+ }
+
+ return byte_arr;
+ }
+
+ fn total_bits_in_layer( layers: i32, compact: bool) -> i32 {
+ return (( if compact { 88 } else { 112 }) + 16 * layers) * layers;
+ }
+}
+
diff --git a/src/aztec/detector.rs b/src/aztec/detector.rs
index e69de29..82941c4 100644
--- a/src/aztec/detector.rs
+++ b/src/aztec/detector.rs
@@ -0,0 +1,581 @@
+import com.google.zxing.NotFoundException;
+import com.google.zxing.ResultPoint;
+import com.google.zxing.aztec.AztecDetectorResult;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.common.GridSampler;
+import com.google.zxing.common.detector.MathUtils;
+import com.google.zxing.common.detector.WhiteRectangleDetector;
+import com.google.zxing.common.reedsolomon.GenericGF;
+import com.google.zxing.common.reedsolomon.ReedSolomonDecoder;
+import com.google.zxing.common.reedsolomon.ReedSolomonException;
+
+
+/**
+ * Encapsulates logic that can detect an Aztec Code in an image, even if the Aztec Code
+ * is rotated or skewed, or partially obscured.
+ *
+ * @author David Olivier
+ * @author Frank Yellin
+ */
+
+const EXPECTED_CORNER_BITS: vec![Vec; 4] = vec![// 07340 XXX .XX X.. ...
+0xee0, // 00734 ... XXX .XX X..
+0x1dc, // 04073 X.. ... XXX .XX
+0x83b, // 03407 .XX X.. ... XXX
+0x707, ]
+;
+pub struct Detector {
+
+ let image: BitMatrix;
+
+ let mut compact: bool;
+
+ let nb_layers: i32;
+
+ let nb_data_blocks: i32;
+
+ let nb_center_layers: i32;
+
+ let mut shift: i32;
+}
+
+impl Detector {
+
+ pub fn new( image: &BitMatrix) -> Detector {
+ let .image = image;
+ }
+
+ pub fn detect(&self) -> /* throws NotFoundException */Result> {
+ return Ok(self.detect(false));
+ }
+
+ /**
+ * Detects an Aztec Code in an image.
+ *
+ * @param isMirror if true, image is a mirror-image of original
+ * @return {@link AztecDetectorResult} encapsulating results of detecting an Aztec Code
+ * @throws NotFoundException if no Aztec Code can be found
+ */
+ pub fn detect(&self, is_mirror: bool) -> /* throws NotFoundException */Result> {
+ // 1. Get the center of the aztec matrix
+ let p_center: Point = self.get_matrix_center();
+ // 2. Get the center points of the four diagonal points just outside the bull's eye
+ // [topRight, bottomRight, bottomLeft, topLeft]
+ let bulls_eye_corners: Vec = self.get_bulls_eye_corners(p_center);
+ if is_mirror {
+ let temp: ResultPoint = bulls_eye_corners[0];
+ bulls_eye_corners[0] = bulls_eye_corners[2];
+ bulls_eye_corners[2] = temp;
+ }
+ // 3. Get the size of the matrix and other parameters from the bull's eye
+ self.extract_parameters(bulls_eye_corners);
+ // 4. Sample the grid
+ let bits: BitMatrix = self.sample_grid(self.image, bulls_eye_corners[self.shift % 4], bulls_eye_corners[(self.shift + 1) % 4], bulls_eye_corners[(self.shift + 2) % 4], bulls_eye_corners[(self.shift + 3) % 4]);
+ // 5. Get the corners of the matrix.
+ let corners: Vec = self.get_matrix_corner_points(bulls_eye_corners);
+ return Ok(AztecDetectorResult::new(bits, corners, self.compact, self.nb_data_blocks, self.nb_layers));
+ }
+
+ /**
+ * Extracts the number of data layers and data blocks from the layer around the bull's eye.
+ *
+ * @param bullsEyeCorners the array of bull's eye corners
+ * @throws NotFoundException in case of too many errors or invalid parameters
+ */
+ fn extract_parameters(&self, bulls_eye_corners: &Vec) -> /* throws NotFoundException */Result> {
+ if !self.is_valid(bulls_eye_corners[0]) || !self.is_valid(bulls_eye_corners[1]) || !self.is_valid(bulls_eye_corners[2]) || !self.is_valid(bulls_eye_corners[3]) {
+ throw NotFoundException::get_not_found_instance();
+ }
+ let length: i32 = 2 * self.nb_center_layers;
+ // Get the bits around the bull's eye
+ let sides: vec![Vec; 4] = vec![// Right side
+ self.sample_line(bulls_eye_corners[0], bulls_eye_corners[1], length), // Bottom
+ self.sample_line(bulls_eye_corners[1], bulls_eye_corners[2], length), // Left side
+ self.sample_line(bulls_eye_corners[2], bulls_eye_corners[3], length), // Top
+ self.sample_line(bulls_eye_corners[3], bulls_eye_corners[0], length), ]
+ ;
+ // bullsEyeCorners[shift] is the corner of the bulls'eye that has three
+ // orientation marks.
+ // sides[shift] is the row/column that goes from the corner with three
+ // orientation marks to the corner with two.
+ self.shift = ::get_rotation(&sides, length);
+ // Flatten the parameter bits into a single 28- or 40-bit long
+ let parameter_data: i64 = 0;
+ {
+ let mut i: i32 = 0;
+ while i < 4 {
+ {
+ let side: i32 = sides[(self.shift + i) % 4];
+ if self.compact {
+ // Each side of the form ..XXXXXXX. where Xs are parameter data
+ parameter_data <<= 7;
+ parameter_data += (side >> 1) & 0x7F;
+ } else {
+ // Each side of the form ..XXXXX.XXXXX. where Xs are parameter data
+ parameter_data <<= 10;
+ parameter_data += ((side >> 2) & (0x1f << 5)) + ((side >> 1) & 0x1F);
+ }
+ }
+ i += 1;
+ }
+ }
+
+ // Corrects parameter data using RS. Returns just the data portion
+ // without the error correction.
+ let corrected_data: i32 = ::get_corrected_parameter_data(parameter_data, self.compact);
+ if self.compact {
+ // 8 bits: 2 bits layers and 6 bits data blocks
+ self.nb_layers = (corrected_data >> 6) + 1;
+ self.nb_data_blocks = (corrected_data & 0x3F) + 1;
+ } else {
+ // 16 bits: 5 bits layers and 11 bits data blocks
+ self.nb_layers = (corrected_data >> 11) + 1;
+ self.nb_data_blocks = (corrected_data & 0x7FF) + 1;
+ }
+ }
+
+ fn get_rotation( sides: &Vec, length: i32) -> /* throws NotFoundException */Result> {
+ // In a normal pattern, we expect to See
+ // ** .* D A
+ // * *
+ //
+ // . *
+ // .. .. C B
+ //
+ // Grab the 3 bits from each of the sides the form the locator pattern and concatenate
+ // into a 12-bit integer. Start with the bit at A
+ let corner_bits: i32 = 0;
+ for let side: i32 in sides {
+ // XX......X where X's are orientation marks
+ let t: i32 = ((side >> (length - 2)) << 1) + (side & 1);
+ corner_bits = (corner_bits << 3) + t;
+ }
+ // Mov the bottom bit to the top, so that the three bits of the locator pattern at A are
+ // together. cornerBits is now:
+ // 3 orientation bits at A || 3 orientation bits at B || ... || 3 orientation bits at D
+ corner_bits = ((corner_bits & 1) << 11) + (corner_bits >> 1);
+ // can easily tolerate two errors.
+ {
+ let mut shift: i32 = 0;
+ while shift < 4 {
+ {
+ if Integer::bit_count(corner_bits ^ EXPECTED_CORNER_BITS[shift]) <= 2 {
+ return Ok(shift);
+ }
+ }
+ shift += 1;
+ }
+ }
+
+ throw NotFoundException::get_not_found_instance();
+ }
+
+ /**
+ * Corrects the parameter bits using Reed-Solomon algorithm.
+ *
+ * @param parameterData parameter bits
+ * @param compact true if this is a compact Aztec code
+ * @throws NotFoundException if the array contains too many errors
+ */
+ fn get_corrected_parameter_data( parameter_data: i64, compact: bool) -> /* throws NotFoundException */Result> {
+ let num_codewords: i32;
+ let num_data_codewords: i32;
+ if compact {
+ num_codewords = 7;
+ num_data_codewords = 2;
+ } else {
+ num_codewords = 10;
+ num_data_codewords = 4;
+ }
+ let num_e_c_codewords: i32 = num_codewords - num_data_codewords;
+ let parameter_words: [i32; num_codewords] = [0; num_codewords];
+ {
+ let mut i: i32 = num_codewords - 1;
+ while i >= 0 {
+ {
+ parameter_words[i] = parameter_data as i32 & 0xF;
+ parameter_data >>= 4;
+ }
+ i -= 1;
+ }
+ }
+
+ let tryResult1 = 0;
+ 'try1: loop {
+ {
+ let rs_decoder: ReedSolomonDecoder = ReedSolomonDecoder::new(GenericGF::AZTEC_PARAM);
+ rs_decoder.decode(¶meter_words, num_e_c_codewords);
+ }
+ break 'try1
+ }
+ match tryResult1 {
+ catch ( ignored: &ReedSolomonException) {
+ throw NotFoundException::get_not_found_instance();
+ } 0 => break
+ }
+
+ // Toss the error correction. Just return the data as an integer
+ let mut result: i32 = 0;
+ {
+ let mut i: i32 = 0;
+ while i < num_data_codewords {
+ {
+ result = (result << 4) + parameter_words[i];
+ }
+ i += 1;
+ }
+ }
+
+ return Ok(result);
+ }
+
+ /**
+ * Finds the corners of a bull-eye centered on the passed point.
+ * This returns the centers of the diagonal points just outside the bull's eye
+ * Returns [topRight, bottomRight, bottomLeft, topLeft]
+ *
+ * @param pCenter Center point
+ * @return The corners of the bull-eye
+ * @throws NotFoundException If no valid bull-eye can be found
+ */
+ fn get_bulls_eye_corners(&self, p_center: &Point) -> /* throws NotFoundException */Result, Rc> {
+ let mut pina: Point = p_center;
+ let mut pinb: Point = p_center;
+ let mut pinc: Point = p_center;
+ let mut pind: Point = p_center;
+ let mut color: bool = true;
+ {
+ self.nb_center_layers = 1;
+ while self.nb_center_layers < 9 {
+ {
+ let pouta: Point = self.get_first_different(pina, color, 1, -1);
+ let poutb: Point = self.get_first_different(pinb, color, 1, 1);
+ let poutc: Point = self.get_first_different(pinc, color, -1, 1);
+ let poutd: Point = self.get_first_different(pind, color, -1, -1);
+ if self.nb_center_layers > 2 {
+ let q: f32 = ::distance(poutd, pouta) * self.nb_center_layers / (::distance(pind, pina) * (self.nb_center_layers + 2));
+ if q < 0.75 || q > 1.25 || !self.is_white_or_black_rectangle(pouta, poutb, poutc, poutd) {
+ break;
+ }
+ }
+ pina = pouta;
+ pinb = poutb;
+ pinc = poutc;
+ pind = poutd;
+ color = !color;
+ }
+ self.nb_center_layers += 1;
+ }
+ }
+
+ if self.nb_center_layers != 5 && self.nb_center_layers != 7 {
+ throw NotFoundException::get_not_found_instance();
+ }
+ self.compact = self.nb_center_layers == 5;
+ // Expand the square by .5 pixel in each direction so that we're on the border
+ // between the white square and the black square
+ let pinax: ResultPoint = ResultPoint::new(pina.get_x() + 0.5f, pina.get_y() - 0.5f);
+ let pinbx: ResultPoint = ResultPoint::new(pinb.get_x() + 0.5f, pinb.get_y() + 0.5f);
+ let pincx: ResultPoint = ResultPoint::new(pinc.get_x() - 0.5f, pinc.get_y() + 0.5f);
+ let pindx: ResultPoint = ResultPoint::new(pind.get_x() - 0.5f, pind.get_y() - 0.5f);
+ // just outside the bull's eye.
+ return Ok(::expand_square( : vec![ResultPoint; 4] = vec![pinax, pinbx, pincx, pindx, ]
+ , 2 * self.nb_center_layers - 3, 2 * self.nb_center_layers));
+ }
+
+ /**
+ * Finds a candidate center point of an Aztec code from an image
+ *
+ * @return the center point
+ */
+ fn get_matrix_center(&self) -> Point {
+ let point_a: ResultPoint;
+ let point_b: ResultPoint;
+ let point_c: ResultPoint;
+ let point_d: ResultPoint;
+ //Get a white rectangle that can be the border of the matrix in center bull's eye or
+ let tryResult1 = 0;
+ 'try1: loop {
+ {
+ let corner_points: Vec = WhiteRectangleDetector::new(self.image).detect();
+ point_a = corner_points[0];
+ point_b = corner_points[1];
+ point_c = corner_points[2];
+ point_d = corner_points[3];
+ }
+ break 'try1
+ }
+ match tryResult1 {
+ catch ( e: &NotFoundException) {
+ let cx: i32 = self.image.get_width() / 2;
+ let cy: i32 = self.image.get_height() / 2;
+ point_a = self.get_first_different(Point::new(cx + 7, cy - 7), false, 1, -1).to_result_point();
+ point_b = self.get_first_different(Point::new(cx + 7, cy + 7), false, 1, 1).to_result_point();
+ point_c = self.get_first_different(Point::new(cx - 7, cy + 7), false, -1, 1).to_result_point();
+ point_d = self.get_first_different(Point::new(cx - 7, cy - 7), false, -1, -1).to_result_point();
+ } 0 => break
+ }
+
+ //Compute the center of the rectangle
+ let mut cx: i32 = MathUtils::round((point_a.get_x() + point_d.get_x() + point_b.get_x() + point_c.get_x()) / 4.0f);
+ let mut cy: i32 = MathUtils::round((point_a.get_y() + point_d.get_y() + point_b.get_y() + point_c.get_y()) / 4.0f);
+ // in order to compute a more accurate center.
+ let tryResult1 = 0;
+ 'try1: loop {
+ {
+ let corner_points: Vec = WhiteRectangleDetector::new(self.image, 15, cx, cy).detect();
+ point_a = corner_points[0];
+ point_b = corner_points[1];
+ point_c = corner_points[2];
+ point_d = corner_points[3];
+ }
+ break 'try1
+ }
+ match tryResult1 {
+ catch ( e: &NotFoundException) {
+ point_a = self.get_first_different(Point::new(cx + 7, cy - 7), false, 1, -1).to_result_point();
+ point_b = self.get_first_different(Point::new(cx + 7, cy + 7), false, 1, 1).to_result_point();
+ point_c = self.get_first_different(Point::new(cx - 7, cy + 7), false, -1, 1).to_result_point();
+ point_d = self.get_first_different(Point::new(cx - 7, cy - 7), false, -1, -1).to_result_point();
+ } 0 => break
+ }
+
+ // Recompute the center of the rectangle
+ cx = MathUtils::round((point_a.get_x() + point_d.get_x() + point_b.get_x() + point_c.get_x()) / 4.0f);
+ cy = MathUtils::round((point_a.get_y() + point_d.get_y() + point_b.get_y() + point_c.get_y()) / 4.0f);
+ return Point::new(cx, cy);
+ }
+
+ /**
+ * Gets the Aztec code corners from the bull's eye corners and the parameters.
+ *
+ * @param bullsEyeCorners the array of bull's eye corners
+ * @return the array of aztec code corners
+ */
+ fn get_matrix_corner_points(&self, bulls_eye_corners: &Vec) -> Vec {
+ return ::expand_square(bulls_eye_corners, 2 * self.nb_center_layers, &self.get_dimension());
+ }
+
+ /**
+ * Creates a BitMatrix by sampling the provided image.
+ * topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the
+ * diagonal just outside the bull's eye.
+ */
+ fn sample_grid(&self, image: &BitMatrix, top_left: &ResultPoint, top_right: &ResultPoint, bottom_right: &ResultPoint, bottom_left: &ResultPoint) -> /* throws NotFoundException */Result> {
+ let sampler: GridSampler = GridSampler::get_instance();
+ let dimension: i32 = self.get_dimension();
+ let low: f32 = dimension / 2.0f - self.nb_center_layers;
+ let high: f32 = dimension / 2.0f + self.nb_center_layers;
+ return Ok(sampler.sample_grid(image, dimension, dimension, // topleft
+ low, // topleft
+ low, // topright
+ high, // topright
+ low, // bottomright
+ high, // bottomright
+ high, // bottomleft
+ low, // bottomleft
+ high, &top_left.get_x(), &top_left.get_y(), &top_right.get_x(), &top_right.get_y(), &bottom_right.get_x(), &bottom_right.get_y(), &bottom_left.get_x(), &bottom_left.get_y()));
+ }
+
+ /**
+ * Samples a line.
+ *
+ * @param p1 start point (inclusive)
+ * @param p2 end point (exclusive)
+ * @param size number of bits
+ * @return the array of bits as an int (first bit is high-order bit of result)
+ */
+ fn sample_line(&self, p1: &ResultPoint, p2: &ResultPoint, size: i32) -> i32 {
+ let mut result: i32 = 0;
+ let d: f32 = ::distance(p1, p2);
+ let module_size: f32 = d / size;
+ let px: f32 = p1.get_x();
+ let py: f32 = p1.get_y();
+ let dx: f32 = module_size * (p2.get_x() - p1.get_x()) / d;
+ let dy: f32 = module_size * (p2.get_y() - p1.get_y()) / d;
+ {
+ let mut i: i32 = 0;
+ while i < size {
+ {
+ if self.image.get(&MathUtils::round(px + i * dx), &MathUtils::round(py + i * dy)) {
+ result |= 1 << (size - i - 1);
+ }
+ }
+ i += 1;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * @return true if the border of the rectangle passed in parameter is compound of white points only
+ * or black points only
+ */
+ fn is_white_or_black_rectangle(&self, p1: &Point, p2: &Point, p3: &Point, p4: &Point) -> bool {
+ let corr: i32 = 3;
+ p1 = Point::new(&Math::max(0, p1.get_x() - corr), &Math::min(self.image.get_height() - 1, p1.get_y() + corr));
+ p2 = Point::new(&Math::max(0, p2.get_x() - corr), &Math::max(0, p2.get_y() - corr));
+ p3 = Point::new(&Math::min(self.image.get_width() - 1, p3.get_x() + corr), &Math::max(0, &Math::min(self.image.get_height() - 1, p3.get_y() - corr)));
+ p4 = Point::new(&Math::min(self.image.get_width() - 1, p4.get_x() + corr), &Math::min(self.image.get_height() - 1, p4.get_y() + corr));
+ let c_init: i32 = self.get_color(p4, p1);
+ if c_init == 0 {
+ return false;
+ }
+ let mut c: i32 = self.get_color(p1, p2);
+ if c != c_init {
+ return false;
+ }
+ c = self.get_color(p2, p3);
+ if c != c_init {
+ return false;
+ }
+ c = self.get_color(p3, p4);
+ return c == c_init;
+ }
+
+ /**
+ * Gets the color of a segment
+ *
+ * @return 1 if segment more than 90% black, -1 if segment is more than 90% white, 0 else
+ */
+ fn get_color(&self, p1: &Point, p2: &Point) -> i32 {
+ let d: f32 = ::distance(p1, p2);
+ if d == 0.0f {
+ return 0;
+ }
+ let dx: f32 = (p2.get_x() - p1.get_x()) / d;
+ let dy: f32 = (p2.get_y() - p1.get_y()) / d;
+ let mut error: i32 = 0;
+ let mut px: f32 = p1.get_x();
+ let mut py: f32 = p1.get_y();
+ let color_model: bool = self.image.get(&p1.get_x(), &p1.get_y());
+ let i_max: i32 = Math::floor(d) as i32;
+ {
+ let mut i: i32 = 0;
+ while i < i_max {
+ {
+ if self.image.get(&MathUtils::round(px), &MathUtils::round(py)) != color_model {
+ error += 1;
+ }
+ px += dx;
+ py += dy;
+ }
+ i += 1;
+ }
+ }
+
+ let err_ratio: f32 = error / d;
+ if err_ratio > 0.1f && err_ratio < 0.9f {
+ return 0;
+ }
+ return if (err_ratio <= 0.1f) == color_model { 1 } else { -1 };
+ }
+
+ /**
+ * Gets the coordinate of the first point with a different color in the given direction
+ */
+ fn get_first_different(&self, init: &Point, color: bool, dx: i32, dy: i32) -> Point {
+ let mut x: i32 = init.get_x() + dx;
+ let mut y: i32 = init.get_y() + dy;
+ while self.is_valid(x, y) && self.image.get(x, y) == color {
+ x += dx;
+ y += dy;
+ }
+ x -= dx;
+ y -= dy;
+ while self.is_valid(x, y) && self.image.get(x, y) == color {
+ x += dx;
+ }
+ x -= dx;
+ while self.is_valid(x, y) && self.image.get(x, y) == color {
+ y += dy;
+ }
+ y -= dy;
+ return Point::new(x, y);
+ }
+
+ /**
+ * Expand the square represented by the corner points by pushing out equally in all directions
+ *
+ * @param cornerPoints the corners of the square, which has the bull's eye at its center
+ * @param oldSide the original length of the side of the square in the target bit matrix
+ * @param newSide the new length of the size of the square in the target bit matrix
+ * @return the corners of the expanded square
+ */
+ fn expand_square( corner_points: &Vec, old_side: i32, new_side: i32) -> Vec {
+ let ratio: f32 = new_side / (2.0f * old_side);
+ let mut dx: f32 = corner_points[0].get_x() - corner_points[2].get_x();
+ let mut dy: f32 = corner_points[0].get_y() - corner_points[2].get_y();
+ let mut centerx: f32 = (corner_points[0].get_x() + corner_points[2].get_x()) / 2.0f;
+ let mut centery: f32 = (corner_points[0].get_y() + corner_points[2].get_y()) / 2.0f;
+ let result0: ResultPoint = ResultPoint::new(centerx + ratio * dx, centery + ratio * dy);
+ let result2: ResultPoint = ResultPoint::new(centerx - ratio * dx, centery - ratio * dy);
+ dx = corner_points[1].get_x() - corner_points[3].get_x();
+ dy = corner_points[1].get_y() - corner_points[3].get_y();
+ centerx = (corner_points[1].get_x() + corner_points[3].get_x()) / 2.0f;
+ centery = (corner_points[1].get_y() + corner_points[3].get_y()) / 2.0f;
+ let result1: ResultPoint = ResultPoint::new(centerx + ratio * dx, centery + ratio * dy);
+ let result3: ResultPoint = ResultPoint::new(centerx - ratio * dx, centery - ratio * dy);
+ return : vec![ResultPoint; 4] = vec![result0, result1, result2, result3, ]
+ ;
+ }
+
+ fn is_valid(&self, x: i32, y: i32) -> bool {
+ return x >= 0 && x < self.image.get_width() && y >= 0 && y < self.image.get_height();
+ }
+
+ fn is_valid(&self, point: &ResultPoint) -> bool {
+ let x: i32 = MathUtils::round(&point.get_x());
+ let y: i32 = MathUtils::round(&point.get_y());
+ return self.is_valid(x, y);
+ }
+
+ fn distance( a: &Point, b: &Point) -> f32 {
+ return MathUtils::distance(&a.get_x(), &a.get_y(), &b.get_x(), &b.get_y());
+ }
+
+ fn distance( a: &ResultPoint, b: &ResultPoint) -> f32 {
+ return MathUtils::distance(&a.get_x(), &a.get_y(), &b.get_x(), &b.get_y());
+ }
+
+ fn get_dimension(&self) -> i32 {
+ if self.compact {
+ return 4 * self.nb_layers + 11;
+ }
+ return 4 * self.nb_layers + 2 * ((2 * self.nb_layers + 6) / 15) + 15;
+ }
+
+ struct Point {
+
+ let x: i32;
+
+ let y: i32;
+ }
+
+ impl Point {
+
+ fn to_result_point(&self) -> ResultPoint {
+ return ResultPoint::new(self.x, self.y);
+ }
+
+ fn new( x: i32, y: i32) -> Point {
+ let .x = x;
+ let .y = y;
+ }
+
+ fn get_x(&self) -> i32 {
+ return self.x;
+ }
+
+ fn get_y(&self) -> i32 {
+ return self.y;
+ }
+
+ pub fn to_string(&self) -> String {
+ return format!("<{} {}>", self.x, self.y);
+ }
+ }
+
+}
+
diff --git a/src/aztec/encoder.rs b/src/aztec/encoder.rs
index e69de29..1628bfb 100644
--- a/src/aztec/encoder.rs
+++ b/src/aztec/encoder.rs
@@ -0,0 +1,1242 @@
+use crate::common::{BitArray,BitMatrix,CharacterSetECI};
+use crate::common::reedsolomon{GenericGF,ReedSolomonEncoder};
+
+// Token.java
+const EMPTY: Token = SimpleToken::new(null, 0, 0);
+
+pub trait Token {
+
+ fn new( previous: &Token) -> Token {
+ let .previous = previous;
+ }
+
+ fn get_previous(&self) -> Token {
+ return self.previous;
+ }
+
+ fn add(&self, value: i32, bit_count: i32) -> Token {
+ return SimpleToken::new(self, value, bit_count);
+ }
+
+ fn add_binary_shift(&self, start: i32, byte_count: i32) -> Token {
+ //int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);
+ return BinaryShiftToken::new(self, start, byte_count);
+ }
+
+ fn append_to(&self, bit_array: &BitArray, text: &Vec) ;
+}
+
+// AztecCode.java
+/**
+ * Aztec 2D code representation
+ *
+ * @author Rustam Abdullaev
+ */
+pub struct AztecCode {
+
+ let compact: bool;
+
+ let size: i32;
+
+ let layers: i32;
+
+ let code_words: i32;
+
+ let matrix: BitMatrix;
+}
+
+impl AztecCode {
+
+ /**
+ * @return {@code true} if compact instead of full mode
+ */
+ pub fn is_compact(&self) -> bool {
+ return self.compact;
+ }
+
+ pub fn set_compact(&self, compact: bool) {
+ self.compact = compact;
+ }
+
+ /**
+ * @return size in pixels (width and height)
+ */
+ pub fn get_size(&self) -> i32 {
+ return self.size;
+ }
+
+ pub fn set_size(&self, size: i32) {
+ self.size = size;
+ }
+
+ /**
+ * @return number of levels
+ */
+ pub fn get_layers(&self) -> i32 {
+ return self.layers;
+ }
+
+ pub fn set_layers(&self, layers: i32) {
+ self.layers = layers;
+ }
+
+ /**
+ * @return number of data codewords
+ */
+ pub fn get_code_words(&self) -> i32 {
+ return self.code_words;
+ }
+
+ pub fn set_code_words(&self, code_words: i32) {
+ self.codeWords = code_words;
+ }
+
+ /**
+ * @return the symbol image
+ */
+ pub fn get_matrix(&self) -> BitMatrix {
+ return self.matrix;
+ }
+
+ pub fn set_matrix(&self, matrix: &BitMatrix) {
+ self.matrix = matrix;
+ }
+}
+
+// Encoder.java
+
+/**
+ * Generates Aztec 2D barcodes.
+ *
+ * @author Rustam Abdullaev
+ */
+
+// default minimal percentage of error check words
+const DEFAULT_EC_PERCENT: i32 = 33;
+
+const DEFAULT_AZTEC_LAYERS: i32 = 0;
+
+const MAX_NB_BITS: i32 = 32;
+
+const MAX_NB_BITS_COMPACT: i32 = 4;
+
+const WORD_SIZE: vec![Vec; 33] = vec![4, 6, 6, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, ]
+;
+pub struct Encoder {
+}
+
+impl Encoder {
+
+ fn new() -> Encoder {
+ }
+
+ /**
+ * Encodes the given string content as an Aztec symbol (without ECI code)
+ *
+ * @param data input data string; must be encodable as ISO/IEC 8859-1 (Latin-1)
+ * @return Aztec symbol matrix with metadata
+ */
+ pub fn encode( data: &String) -> AztecCode {
+ return ::encode(&data.get_bytes(StandardCharsets::ISO_8859_1));
+ }
+
+ /**
+ * Encodes the given string content as an Aztec symbol (without ECI code)
+ *
+ * @param data input data string; must be encodable as ISO/IEC 8859-1 (Latin-1)
+ * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008,
+ * a minimum of 23% + 3 words is recommended)
+ * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers
+ * @return Aztec symbol matrix with metadata
+ */
+ pub fn encode( data: &String, min_e_c_c_percent: i32, user_specified_layers: i32) -> AztecCode {
+ return ::encode(&data.get_bytes(StandardCharsets::ISO_8859_1), min_e_c_c_percent, user_specified_layers, null);
+ }
+
+ /**
+ * Encodes the given string content as an Aztec symbol
+ *
+ * @param data input data string
+ * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008,
+ * a minimum of 23% + 3 words is recommended)
+ * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers
+ * @param charset character set in which to encode string using ECI; if null, no ECI code
+ * will be inserted, and the string must be encodable as ISO/IEC 8859-1
+ * (Latin-1), the default encoding of the symbol.
+ * @return Aztec symbol matrix with metadata
+ */
+ pub fn encode( data: &String, min_e_c_c_percent: i32, user_specified_layers: i32, charset: &Charset) -> AztecCode {
+ let bytes: Vec = data.get_bytes( if null != charset { charset } else { StandardCharsets::ISO_8859_1 });
+ return ::encode(&bytes, min_e_c_c_percent, user_specified_layers, &charset);
+ }
+
+ /**
+ * Encodes the given binary content as an Aztec symbol (without ECI code)
+ *
+ * @param data input data string
+ * @return Aztec symbol matrix with metadata
+ */
+ pub fn encode( data: &Vec) -> AztecCode {
+ return ::encode(&data, DEFAULT_EC_PERCENT, DEFAULT_AZTEC_LAYERS, null);
+ }
+
+ /**
+ * Encodes the given binary content as an Aztec symbol (without ECI code)
+ *
+ * @param data input data string
+ * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008,
+ * a minimum of 23% + 3 words is recommended)
+ * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers
+ * @return Aztec symbol matrix with metadata
+ */
+ pub fn encode( data: &Vec, min_e_c_c_percent: i32, user_specified_layers: i32) -> AztecCode {
+ return ::encode(&data, min_e_c_c_percent, user_specified_layers, null);
+ }
+
+ /**
+ * Encodes the given binary content as an Aztec symbol
+ *
+ * @param data input data string
+ * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008,
+ * a minimum of 23% + 3 words is recommended)
+ * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers
+ * @param charset character set to mark using ECI; if null, no ECI code will be inserted, and the
+ * default encoding of ISO/IEC 8859-1 will be assuming by readers.
+ * @return Aztec symbol matrix with metadata
+ */
+ pub fn encode( data: &Vec, min_e_c_c_percent: i32, user_specified_layers: i32, charset: &Charset) -> AztecCode {
+ // High-level encode
+ let bits: BitArray = HighLevelEncoder::new(&data, &charset).encode();
+ // stuff bits and choose symbol size
+ let ecc_bits: i32 = bits.get_size() * min_e_c_c_percent / 100 + 11;
+ let total_size_bits: i32 = bits.get_size() + ecc_bits;
+ let mut compact: bool;
+ let mut layers: i32;
+ let total_bits_in_layer: i32;
+ let word_size: i32;
+ let stuffed_bits: BitArray;
+ if user_specified_layers != DEFAULT_AZTEC_LAYERS {
+ compact = user_specified_layers < 0;
+ layers = Math::abs(user_specified_layers);
+ if layers > ( if compact { MAX_NB_BITS_COMPACT } else { MAX_NB_BITS }) {
+ throw IllegalArgumentException::new(&String::format("Illegal value %s for layers", user_specified_layers));
+ }
+ total_bits_in_layer = self.total_bits_in_layer(layers, compact);
+ word_size = WORD_SIZE[layers];
+ let usable_bits_in_layers: i32 = total_bits_in_layer - (total_bits_in_layer % word_size);
+ stuffed_bits = ::stuff_bits(bits, word_size);
+ if stuffed_bits.get_size() + ecc_bits > usable_bits_in_layers {
+ throw IllegalArgumentException::new("Data to large for user specified layer");
+ }
+ if compact && stuffed_bits.get_size() > word_size * 64 {
+ // Compact format only allows 64 data words, though C4 can hold more words than that
+ throw IllegalArgumentException::new("Data to large for user specified layer");
+ }
+ } else {
+ word_size = 0;
+ stuffed_bits = null;
+ // is the same size, but has more data.
+ {
+ let mut i: i32 = 0;
+ loop {
+ {
+ if i > MAX_NB_BITS {
+ throw IllegalArgumentException::new("Data too large for an Aztec code");
+ }
+ compact = i <= 3;
+ layers = if compact { i + 1 } else { i };
+ total_bits_in_layer = self.total_bits_in_layer(layers, compact);
+ if total_size_bits > total_bits_in_layer {
+ continue;
+ }
+ // wordSize has changed
+ if stuffed_bits == null || word_size != WORD_SIZE[layers] {
+ word_size = WORD_SIZE[layers];
+ stuffed_bits = ::stuff_bits(bits, word_size);
+ }
+ let usable_bits_in_layers: i32 = total_bits_in_layer - (total_bits_in_layer % word_size);
+ if compact && stuffed_bits.get_size() > word_size * 64 {
+ // Compact format only allows 64 data words, though C4 can hold more words than that
+ continue;
+ }
+ if stuffed_bits.get_size() + ecc_bits <= usable_bits_in_layers {
+ break;
+ }
+ }
+ i += 1;
+ }
+ }
+
+ }
+ let message_bits: BitArray = ::generate_check_words(stuffed_bits, total_bits_in_layer, word_size);
+ // generate mode message
+ let message_size_in_words: i32 = stuffed_bits.get_size() / word_size;
+ let mode_message: BitArray = ::generate_mode_message(compact, layers, message_size_in_words);
+ // allocate symbol
+ // not including alignment lines
+ let base_matrix_size: i32 = ( if compact { 11 } else { 14 }) + layers * 4;
+ let alignment_map: [i32; base_matrix_size] = [0; base_matrix_size];
+ let matrix_size: i32;
+ if compact {
+ // no alignment marks in compact mode, alignmentMap is a no-op
+ matrix_size = base_matrix_size;
+ {
+ let mut i: i32 = 0;
+ while i < alignment_map.len() {
+ {
+ alignment_map[i] = i;
+ }
+ i += 1;
+ }
+ }
+
+ } else {
+ matrix_size = base_matrix_size + 1 + 2 * ((base_matrix_size / 2 - 1) / 15);
+ let orig_center: i32 = base_matrix_size / 2;
+ let center: i32 = matrix_size / 2;
+ {
+ let mut i: i32 = 0;
+ while i < orig_center {
+ {
+ let new_offset: i32 = i + i / 15;
+ alignment_map[orig_center - i - 1] = center - new_offset - 1;
+ alignment_map[orig_center + i] = center + new_offset + 1;
+ }
+ i += 1;
+ }
+ }
+
+ }
+ let matrix: BitMatrix = BitMatrix::new(matrix_size);
+ // draw data bits
+ {
+ let mut i: i32 = 0, let row_offset: i32 = 0;
+ while i < layers {
+ {
+ let row_size: i32 = (layers - i) * 4 + ( if compact { 9 } else { 12 });
+ {
+ let mut j: i32 = 0;
+ while j < row_size {
+ {
+ let column_offset: i32 = j * 2;
+ {
+ let mut k: i32 = 0;
+ while k < 2 {
+ {
+ if message_bits.get(row_offset + column_offset + k) {
+ matrix.set(alignment_map[i * 2 + k], alignment_map[i * 2 + j]);
+ }
+ if message_bits.get(row_offset + row_size * 2 + column_offset + k) {
+ matrix.set(alignment_map[i * 2 + j], alignment_map[base_matrix_size - 1 - i * 2 - k]);
+ }
+ if message_bits.get(row_offset + row_size * 4 + column_offset + k) {
+ matrix.set(alignment_map[base_matrix_size - 1 - i * 2 - k], alignment_map[base_matrix_size - 1 - i * 2 - j]);
+ }
+ if message_bits.get(row_offset + row_size * 6 + column_offset + k) {
+ matrix.set(alignment_map[base_matrix_size - 1 - i * 2 - j], alignment_map[i * 2 + k]);
+ }
+ }
+ k += 1;
+ }
+ }
+
+ }
+ j += 1;
+ }
+ }
+
+ row_offset += row_size * 8;
+ }
+ i += 1;
+ }
+ }
+
+ // draw mode message
+ ::draw_mode_message(matrix, compact, matrix_size, mode_message);
+ // draw alignment marks
+ if compact {
+ ::draw_bulls_eye(matrix, matrix_size / 2, 5);
+ } else {
+ ::draw_bulls_eye(matrix, matrix_size / 2, 7);
+ {
+ let mut i: i32 = 0, let mut j: i32 = 0;
+ while i < base_matrix_size / 2 - 1 {
+ {
+ {
+ let mut k: i32 = (matrix_size / 2) & 1;
+ while k < matrix_size {
+ {
+ matrix.set(matrix_size / 2 - j, k);
+ matrix.set(matrix_size / 2 + j, k);
+ matrix.set(k, matrix_size / 2 - j);
+ matrix.set(k, matrix_size / 2 + j);
+ }
+ k += 2;
+ }
+ }
+
+ }
+ i += 15;
+ j += 16;
+ }
+ }
+
+ }
+ let aztec: AztecCode = AztecCode::new();
+ aztec.set_compact(compact);
+ aztec.set_size(matrix_size);
+ aztec.set_layers(layers);
+ aztec.set_code_words(message_size_in_words);
+ aztec.set_matrix(matrix);
+ return aztec;
+ }
+
+ fn draw_bulls_eye( matrix: &BitMatrix, center: i32, size: i32) {
+ {
+ let mut i: i32 = 0;
+ while i < size {
+ {
+ {
+ let mut j: i32 = center - i;
+ while j <= center + i {
+ {
+ matrix.set(j, center - i);
+ matrix.set(j, center + i);
+ matrix.set(center - i, j);
+ matrix.set(center + i, j);
+ }
+ j += 1;
+ }
+ }
+
+ }
+ i += 2;
+ }
+ }
+
+ matrix.set(center - size, center - size);
+ matrix.set(center - size + 1, center - size);
+ matrix.set(center - size, center - size + 1);
+ matrix.set(center + size, center - size);
+ matrix.set(center + size, center - size + 1);
+ matrix.set(center + size, center + size - 1);
+ }
+
+ fn generate_mode_message( compact: bool, layers: i32, message_size_in_words: i32) -> BitArray {
+ let mode_message: BitArray = BitArray::new();
+ if compact {
+ mode_message.append_bits(layers - 1, 2);
+ mode_message.append_bits(message_size_in_words - 1, 6);
+ mode_message = ::generate_check_words(mode_message, 28, 4);
+ } else {
+ mode_message.append_bits(layers - 1, 5);
+ mode_message.append_bits(message_size_in_words - 1, 11);
+ mode_message = ::generate_check_words(mode_message, 40, 4);
+ }
+ return mode_message;
+ }
+
+ fn draw_mode_message( matrix: &BitMatrix, compact: bool, matrix_size: i32, mode_message: &BitArray) {
+ let center: i32 = matrix_size / 2;
+ if compact {
+ {
+ let mut i: i32 = 0;
+ while i < 7 {
+ {
+ let offset: i32 = center - 3 + i;
+ if mode_message.get(i) {
+ matrix.set(offset, center - 5);
+ }
+ if mode_message.get(i + 7) {
+ matrix.set(center + 5, offset);
+ }
+ if mode_message.get(20 - i) {
+ matrix.set(offset, center + 5);
+ }
+ if mode_message.get(27 - i) {
+ matrix.set(center - 5, offset);
+ }
+ }
+ i += 1;
+ }
+ }
+
+ } else {
+ {
+ let mut i: i32 = 0;
+ while i < 10 {
+ {
+ let offset: i32 = center - 5 + i + i / 5;
+ if mode_message.get(i) {
+ matrix.set(offset, center - 7);
+ }
+ if mode_message.get(i + 10) {
+ matrix.set(center + 7, offset);
+ }
+ if mode_message.get(29 - i) {
+ matrix.set(offset, center + 7);
+ }
+ if mode_message.get(39 - i) {
+ matrix.set(center - 7, offset);
+ }
+ }
+ i += 1;
+ }
+ }
+
+ }
+ }
+
+ fn generate_check_words( bit_array: &BitArray, total_bits: i32, word_size: i32) -> BitArray {
+ // bitArray is guaranteed to be a multiple of the wordSize, so no padding needed
+ let message_size_in_words: i32 = bit_array.get_size() / word_size;
+ let rs: ReedSolomonEncoder = ReedSolomonEncoder::new(&::get_g_f(word_size));
+ let total_words: i32 = total_bits / word_size;
+ let message_words: Vec = ::bits_to_words(bit_array, word_size, total_words);
+ rs.encode(&message_words, total_words - message_size_in_words);
+ let start_pad: i32 = total_bits % word_size;
+ let message_bits: BitArray = BitArray::new();
+ message_bits.append_bits(0, start_pad);
+ for let message_word: i32 in message_words {
+ message_bits.append_bits(message_word, word_size);
+ }
+ return message_bits;
+ }
+
+ fn bits_to_words( stuffed_bits: &BitArray, word_size: i32, total_words: i32) -> Vec {
+ let mut message: [i32; total_words] = [0; total_words];
+ let mut i: i32;
+ let mut n: i32;
+ {
+ i = 0;
+ n = stuffed_bits.get_size() / word_size;
+ while i < n {
+ {
+ let mut value: i32 = 0;
+ {
+ let mut j: i32 = 0;
+ while j < word_size {
+ {
+ value |= if stuffed_bits.get(i * word_size + j) { (1 << word_size - j - 1) } else { 0 };
+ }
+ j += 1;
+ }
+ }
+
+ message[i] = value;
+ }
+ i += 1;
+ }
+ }
+
+ return message;
+ }
+
+ fn get_g_f( word_size: i32) -> GenericGF {
+ match word_size {
+ 4 =>
+ {
+ return GenericGF::AZTEC_PARAM;
+ }
+ 6 =>
+ {
+ return GenericGF::AZTEC_DATA_6;
+ }
+ 8 =>
+ {
+ return GenericGF::AZTEC_DATA_8;
+ }
+ 10 =>
+ {
+ return GenericGF::AZTEC_DATA_10;
+ }
+ 12 =>
+ {
+ return GenericGF::AZTEC_DATA_12;
+ }
+ _ =>
+ {
+ throw IllegalArgumentException::new(format!("Unsupported word size {}", word_size));
+ }
+ }
+ }
+
+ fn stuff_bits( bits: &BitArray, word_size: i32) -> BitArray {
+ let out: BitArray = BitArray::new();
+ let n: i32 = bits.get_size();
+ let mask: i32 = (1 << word_size) - 2;
+ {
+ let mut i: i32 = 0;
+ while i < n {
+ {
+ let mut word: i32 = 0;
+ {
+ let mut j: i32 = 0;
+ while j < word_size {
+ {
+ if i + j >= n || bits.get(i + j) {
+ word |= 1 << (word_size - 1 - j);
+ }
+ }
+ j += 1;
+ }
+ }
+
+ if (word & mask) == mask {
+ out.append_bits(word & mask, word_size);
+ i -= 1;
+ } else if (word & mask) == 0 {
+ out.append_bits(word | 1, word_size);
+ i -= 1;
+ } else {
+ out.append_bits(word, word_size);
+ }
+ }
+ i += word_size;
+ }
+ }
+
+ return out;
+ }
+
+ fn total_bits_in_layer( layers: i32, compact: bool) -> i32 {
+ return (( if compact { 88 } else { 112 }) + 16 * layers) * layers;
+ }
+}
+
+// BinaryShiftToken.java
+struct BinaryShiftToken {
+ super: Token;
+
+ let binary_shift_start: i32;
+
+ let binary_shift_byte_count: i32;
+}
+
+impl Token for BinaryShiftToken {
+ pub fn append_to(&self, bit_array: &BitArray, text: &Vec) {
+ let bsbc: i32 = self.binary_shift_byte_count;
+ {
+ let mut i: i32 = 0;
+ while i < bsbc {
+ {
+ if i == 0 || (i == 31 && bsbc <= 62) {
+ // We need a header before the first character, and before
+ // character 31 when the total byte code is <= 62
+ // BINARY_SHIFT
+ bit_array.append_bits(31, 5);
+ if bsbc > 62 {
+ bit_array.append_bits(bsbc - 31, 16);
+ } else if i == 0 {
+ // 1 <= binaryShiftByteCode <= 62
+ bit_array.append_bits(&Math::min(bsbc, 31), 5);
+ } else {
+ // 32 <= binaryShiftCount <= 62 and i == 31
+ bit_array.append_bits(bsbc - 31, 5);
+ }
+ }
+ bit_array.append_bits(text[self.binary_shift_start + i], 8);
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ pub fn to_string(&self) -> String {
+ return format!("<{}::{}>", self.binary_shift_start, (self.binary_shift_start + self.binary_shift_byte_count - 1));
+ }
+}
+
+impl BinaryShiftToken {
+
+ fn new( previous: &Token, binary_shift_start: i32, binary_shift_byte_count: i32) -> BinaryShiftToken {
+ super(previous);
+ let .binaryShiftStart = binary_shift_start;
+ let .binaryShiftByteCount = binary_shift_byte_count;
+ }
+
+
+}
+
+// HighLevelEncoder.java
+/**
+ * This produces nearly optimal encodings of text into the first-level of
+ * encoding used by Aztec code.
+ *
+ * It uses a dynamic algorithm. For each prefix of the string, it determines
+ * a set of encodings that could lead to this prefix. We repeatedly add a
+ * character and generate a new set of optimal encodings until we have read
+ * through the entire input.
+ *
+ * @author Frank Yellin
+ * @author Rustam Abdullaev
+ */
+
+const MODE_NAMES: vec![Vec; 5] = vec!["UPPER", "LOWER", "DIGIT", "MIXED", "PUNCT", ]
+;
+
+// 5 bits
+ const MODE_UPPER: i32 = 0;
+
+// 5 bits
+ const MODE_LOWER: i32 = 1;
+
+// 4 bits
+ const MODE_DIGIT: i32 = 2;
+
+// 5 bits
+ const MODE_MIXED: i32 = 3;
+
+// 5 bits
+ const MODE_PUNCT: i32 = 4;
+
+// The Latch Table shows, for each pair of Modes, the optimal method for
+// getting from one mode to another. In the worst possible case, this can
+// be up to 14 bits. In the best possible case, we are already there!
+// The high half-word of each entry gives the number of bits.
+// The low half-word of each entry are the actual bits necessary to change
+ const LATCH_TABLE: vec![vec![Vec>; 5]; 5] = vec![vec![0, // UPPER -> LOWER
+(5 << 16) + 28, // UPPER -> DIGIT
+(5 << 16) + 30, // UPPER -> MIXED
+(5 << 16) + 29, // UPPER -> MIXED -> PUNCT
+(10 << 16) + (29 << 5) + 30, ]
+, vec![// LOWER -> DIGIT -> UPPER
+(9 << 16) + (30 << 4) + 14, 0, // LOWER -> DIGIT
+(5 << 16) + 30, // LOWER -> MIXED
+(5 << 16) + 29, // LOWER -> MIXED -> PUNCT
+(10 << 16) + (29 << 5) + 30, ]
+, vec![// DIGIT -> UPPER
+(4 << 16) + 14, // DIGIT -> UPPER -> LOWER
+(9 << 16) + (14 << 5) + 28, 0, // DIGIT -> UPPER -> MIXED
+(9 << 16) + (14 << 5) + 29, (14 << 16) + (14 << 10) + (29 << 5) + 30, ]
+, vec![// MIXED -> UPPER
+(5 << 16) + 29, // MIXED -> LOWER
+(5 << 16) + 28, // MIXED -> UPPER -> DIGIT
+(10 << 16) + (29 << 5) + 30, 0, // MIXED -> PUNCT
+(5 << 16) + 30, ]
+, vec![// PUNCT -> UPPER
+(5 << 16) + 31, // PUNCT -> UPPER -> LOWER
+(10 << 16) + (31 << 5) + 28, // PUNCT -> UPPER -> DIGIT
+(10 << 16) + (31 << 5) + 30, // PUNCT -> UPPER -> MIXED
+(10 << 16) + (31 << 5) + 29, 0, ]
+, ]
+;
+
+// A reverse mapping from [mode][char] to the encoding for that character
+// in that mode. An entry of 0 indicates no mapping exists.
+ const CHAR_MAP: [[i32; 256]; 5] = [[0; 256]; 5];
+
+// A map showing the available shift codes. (The shifts to BINARY are not
+// shown
+// mode shift codes, per table
+ const SHIFT_TABLE: [[i32; 6]; 6] = [[0; 6]; 6];
+pub struct HighLevelEncoder {
+
+ let text: Vec;
+
+ let mut charset: Charset;
+}
+
+impl HighLevelEncoder {
+
+ static {
+ CHAR_MAP[MODE_UPPER][' '] = 1;
+ {
+ let mut c: i32 = 'A';
+ while c <= 'Z' {
+ {
+ CHAR_MAP[MODE_UPPER][c] = c - 'A' + 2;
+ }
+ c += 1;
+ }
+ }
+
+ CHAR_MAP[MODE_LOWER][' '] = 1;
+ {
+ let mut c: i32 = 'a';
+ while c <= 'z' {
+ {
+ CHAR_MAP[MODE_LOWER][c] = c - 'a' + 2;
+ }
+ c += 1;
+ }
+ }
+
+ CHAR_MAP[MODE_DIGIT][' '] = 1;
+ {
+ let mut c: i32 = '0';
+ while c <= '9' {
+ {
+ CHAR_MAP[MODE_DIGIT][c] = c - '0' + 2;
+ }
+ c += 1;
+ }
+ }
+
+ CHAR_MAP[MODE_DIGIT][','] = 12;
+ CHAR_MAP[MODE_DIGIT]['.'] = 13;
+ let mixed_table: vec![Vec; 28] = vec!['\0', ' ', '\1', '\2', '\3', '\4', '\5', '\6', '\7', '\b', '\t', '\n', '\13', '\f', '\r', '\33', '\34', '\35', '\36', '\37', '@', '\\', '^', '_', '`', '|', '~', '\177', ]
+ ;
+ {
+ let mut i: i32 = 0;
+ while i < mixed_table.len() {
+ {
+ CHAR_MAP[MODE_MIXED][mixed_table[i]] = i;
+ }
+ i += 1;
+ }
+ }
+
+ let punct_table: vec![Vec; 31] = vec!['\0', '\r', '\0', '\0', '\0', '\0', '!', '\'', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '{', '}', ]
+ ;
+ {
+ let mut i: i32 = 0;
+ while i < punct_table.len() {
+ {
+ if punct_table[i] > 0 {
+ CHAR_MAP[MODE_PUNCT][punct_table[i]] = i;
+ }
+ }
+ i += 1;
+ }
+ }
+
+ }
+
+ static {
+ for let table: Vec in SHIFT_TABLE {
+ Arrays::fill(&table, -1);
+ }
+ SHIFT_TABLE[MODE_UPPER][MODE_PUNCT] = 0;
+ SHIFT_TABLE[MODE_LOWER][MODE_PUNCT] = 0;
+ SHIFT_TABLE[MODE_LOWER][MODE_UPPER] = 28;
+ SHIFT_TABLE[MODE_MIXED][MODE_PUNCT] = 0;
+ SHIFT_TABLE[MODE_DIGIT][MODE_PUNCT] = 0;
+ SHIFT_TABLE[MODE_DIGIT][MODE_UPPER] = 15;
+ }
+
+ pub fn new( text: &Vec) -> HighLevelEncoder {
+ let .text = text;
+ let .charset = null;
+ }
+
+ pub fn new( text: &Vec, charset: &Charset) -> HighLevelEncoder {
+ let .text = text;
+ let .charset = charset;
+ }
+
+ /**
+ * @return text represented by this encoder encoded as a {@link BitArray}
+ */
+ pub fn encode(&self) -> BitArray {
+ let initial_state: State = State::INITIAL_STATE;
+ if self.charset != null {
+ let eci: CharacterSetECI = CharacterSetECI::get_character_set_e_c_i(&self.charset);
+ if null == eci {
+ throw IllegalArgumentException::new(format!("No ECI code for character set {}", self.charset));
+ }
+ initial_state = initial_state.append_f_l_gn(&eci.get_value());
+ }
+ let mut states: Collection = Collections::singleton_list(initial_state);
+ {
+ let mut index: i32 = 0;
+ while index < self.text.len() {
+ {
+ let pair_code: i32;
+ let next_char: i32 = if index + 1 < self.text.len() { self.text[index + 1] } else { 0 };
+ match self.text[index] {
+ '\r' =>
+ {
+ pair_code = if next_char == '\n' { 2 } else { 0 };
+ break;
+ }
+ '.' =>
+ {
+ pair_code = if next_char == ' ' { 3 } else { 0 };
+ break;
+ }
+ ',' =>
+ {
+ pair_code = if next_char == ' ' { 4 } else { 0 };
+ break;
+ }
+ ':' =>
+ {
+ pair_code = if next_char == ' ' { 5 } else { 0 };
+ break;
+ }
+ _ =>
+ {
+ pair_code = 0;
+ }
+ }
+ if pair_code > 0 {
+ // We have one of the four special PUNCT pairs. Treat them specially.
+ // Get a new set of states for the two new characters.
+ states = ::update_state_list_for_pair(&states, index, pair_code);
+ index += 1;
+ } else {
+ // Get a new set of states for the new character.
+ states = self.update_state_list_for_char(&states, index);
+ }
+ }
+ index += 1;
+ }
+ }
+
+ // We are left with a set of states. Find the shortest one.
+ let min_state: State = Collections::min(&states, Comparator::new() {
+
+ pub fn compare(&self, a: &State, b: &State) -> i32 {
+ return a.get_bit_count() - b.get_bit_count();
+ }
+ });
+ // Convert it to a bit array, and return.
+ return min_state.to_bit_array(&self.text);
+ }
+
+ // We update a set of states for a new character by updating each state
+ // for the new character, merging the results, and then removing the
+ // non-optimal states.
+ fn update_state_list_for_char(&self, states: &Iterable, index: i32) -> Collection {
+ let result: Collection = LinkedList<>::new();
+ for let state: State in states {
+ self.update_state_for_char(state, index, &result);
+ }
+ return ::simplify_states(&result);
+ }
+
+ // Return a set of states that represent the possible ways of updating this
+ // state for the next character. The resulting set of states are added to
+ // the "result" list.
+ fn update_state_for_char(&self, state: &State, index: i32, result: &Collection) {
+ let ch: char = (self.text[index] & 0xFF) as char;
+ let char_in_current_table: bool = CHAR_MAP[state.get_mode()][ch] > 0;
+ let state_no_binary: State = null;
+ {
+ let mut mode: i32 = 0;
+ while mode <= MODE_PUNCT {
+ {
+ let char_in_mode: i32 = CHAR_MAP[mode][ch];
+ if char_in_mode > 0 {
+ if state_no_binary == null {
+ // Only create stateNoBinary the first time it's required.
+ state_no_binary = state.end_binary_shift(index);
+ }
+ // Try generating the character by latching to its mode
+ if !char_in_current_table || mode == state.get_mode() || mode == MODE_DIGIT {
+ // If the character is in the current table, we don't want to latch to
+ // any other mode except possibly digit (which uses only 4 bits). Any
+ // other latch would be equally successful *after* this character, and
+ // so wouldn't save any bits.
+ let latch_state: State = state_no_binary.latch_and_append(mode, char_in_mode);
+ result.add(latch_state);
+ }
+ // Try generating the character by switching to its mode.
+ if !char_in_current_table && SHIFT_TABLE[state.get_mode()][mode] >= 0 {
+ // It never makes sense to temporarily shift to another mode if the
+ // character exists in the current mode. That can never save bits.
+ let shift_state: State = state_no_binary.shift_and_append(mode, char_in_mode);
+ result.add(shift_state);
+ }
+ }
+ }
+ mode += 1;
+ }
+ }
+
+ if state.get_binary_shift_byte_count() > 0 || CHAR_MAP[state.get_mode()][ch] == 0 {
+ // It's never worthwhile to go into binary shift mode if you're not already
+ // in binary shift mode, and the character exists in your current mode.
+ // That can never save bits over just outputting the char in the current mode.
+ let binary_state: State = state.add_binary_shift_char(index);
+ result.add(binary_state);
+ }
+ }
+
+ fn update_state_list_for_pair( states: &Iterable, index: i32, pair_code: i32) -> Collection {
+ let result: Collection = LinkedList<>::new();
+ for let state: State in states {
+ ::update_state_for_pair(state, index, pair_code, &result);
+ }
+ return ::simplify_states(&result);
+ }
+
+ fn update_state_for_pair( state: &State, index: i32, pair_code: i32, result: &Collection) {
+ let state_no_binary: State = state.end_binary_shift(index);
+ // Possibility 1. Latch to MODE_PUNCT, and then append this code
+ result.add(&state_no_binary.latch_and_append(MODE_PUNCT, pair_code));
+ if state.get_mode() != MODE_PUNCT {
+ // Possibility 2. Shift to MODE_PUNCT, and then append this code.
+ // Every state except MODE_PUNCT (handled above) can shift
+ result.add(&state_no_binary.shift_and_append(MODE_PUNCT, pair_code));
+ }
+ if pair_code == 3 || pair_code == 4 {
+ // both characters are in DIGITS. Sometimes better to just add two digits
+ let digit_state: State = state_no_binary.latch_and_append(MODE_DIGIT, // period or comma in DIGIT
+ 16 - pair_code).latch_and_append(MODE_DIGIT, // space in DIGIT
+ 1);
+ result.add(digit_state);
+ }
+ if state.get_binary_shift_byte_count() > 0 {
+ // It only makes sense to do the characters as binary if we're already
+ // in binary mode.
+ let binary_state: State = state.add_binary_shift_char(index).add_binary_shift_char(index + 1);
+ result.add(binary_state);
+ }
+ }
+
+ fn simplify_states( states: &Iterable) -> Collection {
+ let result: Deque = LinkedList<>::new();
+ for let new_state: State in states {
+ let mut add: bool = true;
+ {
+ let iterator: Iterator = result.iterator();
+ while iterator.has_next(){
+ let old_state: State = iterator.next();
+ if old_state.is_better_than_or_equal_to(new_state) {
+ add = false;
+ break;
+ }
+ if new_state.is_better_than_or_equal_to(old_state) {
+ iterator.remove();
+ }
+ }
+ }
+
+ if add {
+ result.add_first(new_state);
+ }
+ }
+ return result;
+ }
+}
+
+// SimpleToken.java
+struct SimpleToken {
+ super: Token;
+
+ // For normal words, indicates value and bitCount
+ let value: i16;
+
+ let bit_count: i16;
+}
+
+impl Token for SimpleToken {
+ fn append_to(&self, bit_array: &BitArray, text: &Vec) {
+ bit_array.append_bits(self.value, self.bit_count);
+ }
+
+ pub fn to_string(&self) -> String {
+ let mut value: i32 = self.value & ((1 << self.bit_count) - 1);
+ value |= 1 << self.bit_count;
+ return '<' + Integer::to_binary_string(value | (1 << self.bit_count))::substring(1) + '>';
+ }
+}
+
+impl SimpleToken {
+
+ fn new( previous: &Token, value: i32, bit_count: i32) -> SimpleToken {
+ super(previous);
+ let .value = value as i16;
+ let .bitCount = bit_count as i16;
+ }
+
+}
+
+// State.java
+
+/**
+ * State represents all information about a sequence necessary to generate the current output.
+ * Note that a state is immutable.
+ */
+
+const INITIAL_STATE: State = State::new(Token::EMPTY, HighLevelEncoder::MODE_UPPER, 0, 0);
+struct State {
+
+ // The current mode of the encoding (or the mode to which we'll return if
+ // we're in Binary Shift mode.
+ let mode: i32;
+
+ // The list of tokens that we output. If we are in Binary Shift mode, this
+ // token list does *not* yet included the token for those bytes
+ let token: Token;
+
+ // If non-zero, the number of most recent bytes that should be output
+ // in Binary Shift mode.
+ let binary_shift_byte_count: i32;
+
+ // The total number of bits generated (including Binary Shift).
+ let bit_count: i32;
+
+ let binary_shift_cost: i32;
+}
+
+impl State {
+
+ fn new( token: &Token, mode: i32, binary_bytes: i32, bit_count: i32) -> State {
+ let .token = token;
+ let .mode = mode;
+ let .binaryShiftByteCount = binary_bytes;
+ let .bitCount = bit_count;
+ let .binaryShiftCost = ::calculate_binary_shift_cost(binary_bytes);
+ }
+
+ fn get_mode(&self) -> i32 {
+ return self.mode;
+ }
+
+ fn get_token(&self) -> Token {
+ return self.token;
+ }
+
+ fn get_binary_shift_byte_count(&self) -> i32 {
+ return self.binary_shift_byte_count;
+ }
+
+ fn get_bit_count(&self) -> i32 {
+ return self.bit_count;
+ }
+
+ fn append_f_l_gn(&self, eci: i32) -> State {
+ // 0: FLG(n)
+ let result: State = self.shift_and_append(HighLevelEncoder::MODE_PUNCT, 0);
+ let mut token: Token = result.token;
+ let bits_added: i32 = 3;
+ if eci < 0 {
+ // 0: FNC1
+ token = token.add(0, 3);
+ } else if eci > 999999 {
+ throw IllegalArgumentException::new("ECI code must be between 0 and 999999");
+ } else {
+ let eci_digits: Vec = Integer::to_string(eci)::get_bytes(StandardCharsets::ISO_8859_1);
+ // 1-6: number of ECI digits
+ token = token.add(eci_digits.len(), 3);
+ for let eci_digit: i8 in eci_digits {
+ token = token.add(eci_digit - '0' + 2, 4);
+ }
+ bits_added += eci_digits.len() * 4;
+ }
+ return State::new(token, self.mode, 0, self.bit_count + bits_added);
+ }
+
+ // Create a new state representing this state with a latch to a (not
+ // necessary different) mode, and then a code.
+ fn latch_and_append(&self, mode: i32, value: i32) -> State {
+ let bit_count: i32 = self.bitCount;
+ let mut token: Token = self.token;
+ if mode != self.mode {
+ let latch: i32 = HighLevelEncoder::LATCH_TABLE[self.mode][mode];
+ token = token.add(latch & 0xFFFF, latch >> 16);
+ bit_count += latch >> 16;
+ }
+ let latch_mode_bit_count: i32 = if mode == HighLevelEncoder::MODE_DIGIT { 4 } else { 5 };
+ token = token.add(value, latch_mode_bit_count);
+ return State::new(token, mode, 0, bit_count + latch_mode_bit_count);
+ }
+
+ // Create a new state representing this state, with a temporary shift
+ // to a different mode to output a single value.
+ fn shift_and_append(&self, mode: i32, value: i32) -> State {
+ let mut token: Token = self.token;
+ let this_mode_bit_count: i32 = if self.mode == HighLevelEncoder::MODE_DIGIT { 4 } else { 5 };
+ // Shifts exist only to UPPER and PUNCT, both with tokens size 5.
+ token = token.add(HighLevelEncoder::SHIFT_TABLE[self.mode][mode], this_mode_bit_count);
+ token = token.add(value, 5);
+ return State::new(token, self.mode, 0, self.bitCount + this_mode_bit_count + 5);
+ }
+
+ // Create a new state representing this state, but an additional character
+ // output in Binary Shift mode.
+ fn add_binary_shift_char(&self, index: i32) -> State {
+ let mut token: Token = self.token;
+ let mut mode: i32 = self.mode;
+ let bit_count: i32 = self.bitCount;
+ if self.mode == HighLevelEncoder::MODE_PUNCT || self.mode == HighLevelEncoder::MODE_DIGIT {
+ let latch: i32 = HighLevelEncoder::LATCH_TABLE[mode][HighLevelEncoder::MODE_UPPER];
+ token = token.add(latch & 0xFFFF, latch >> 16);
+ bit_count += latch >> 16;
+ mode = HighLevelEncoder::MODE_UPPER;
+ }
+ let delta_bit_count: i32 = if (self.binary_shift_byte_count == 0 || self.binary_shift_byte_count == 31) { 18 } else { if (self.binary_shift_byte_count == 62) { 9 } else { 8 } };
+ let mut result: State = State::new(token, mode, self.binary_shift_byte_count + 1, bit_count + delta_bit_count);
+ if result.binaryShiftByteCount == 2047 + 31 {
+ // The string is as long as it's allowed to be. We should end it.
+ result = result.end_binary_shift(index + 1);
+ }
+ return result;
+ }
+
+ // Create the state identical to this one, but we are no longer in
+ // Binary Shift mode.
+ fn end_binary_shift(&self, index: i32) -> State {
+ if self.binary_shift_byte_count == 0 {
+ return self;
+ }
+ let mut token: Token = self.token;
+ token = token.add_binary_shift(index - self.binary_shift_byte_count, self.binary_shift_byte_count);
+ return State::new(token, self.mode, 0, self.bitCount);
+ }
+
+ // Returns true if "this" state is better (or equal) to be in than "that"
+ // state under all possible circumstances.
+ fn is_better_than_or_equal_to(&self, other: &State) -> bool {
+ let new_mode_bit_count: i32 = self.bitCount + (HighLevelEncoder::LATCH_TABLE[self.mode][other.mode] >> 16);
+ if self.binaryShiftByteCount < other.binaryShiftByteCount {
+ // add additional B/S encoding cost of other, if any
+ new_mode_bit_count += other.binaryShiftCost - self.binaryShiftCost;
+ } else if self.binaryShiftByteCount > other.binaryShiftByteCount && other.binaryShiftByteCount > 0 {
+ // maximum possible additional cost (we end up exceeding the 31 byte boundary and other state can stay beneath it)
+ new_mode_bit_count += 10;
+ }
+ return new_mode_bit_count <= other.bitCount;
+ }
+
+ fn to_bit_array(&self, text: &Vec) -> BitArray {
+ let symbols: List = ArrayList<>::new();
+ {
+ let mut token: Token = self.end_binary_shift(text.len()).token;
+ while token != null {
+ {
+ symbols.add(token);
+ }
+ token = token.get_previous();
+ }
+ }
+
+ let bit_array: BitArray = BitArray::new();
+ // Add each token to the result in forward order
+ {
+ let mut i: i32 = symbols.size() - 1;
+ while i >= 0 {
+ {
+ symbols.get(i).append_to(bit_array, &text);
+ }
+ i -= 1;
+ }
+ }
+
+ return bit_array;
+ }
+
+ pub fn to_string(&self) -> String {
+ return String::format("%s bits=%d bytes=%d", HighLevelEncoder::MODE_NAMES[self.mode], self.bit_count, self.binary_shift_byte_count);
+ }
+
+ fn calculate_binary_shift_cost( binary_shift_byte_count: i32) -> i32 {
+ if binary_shift_byte_count > 62 {
+ // B/S with extended length
+ return 21;
+ }
+ if binary_shift_byte_count > 31 {
+ // two B/S
+ return 20;
+ }
+ if binary_shift_byte_count > 0 {
+ // one B/S
+ return 10;
+ }
+ return 0;
+ }
+}