diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/PDF417Common.java b/port_src/core/DONE/pdf417/PDF417Common.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/PDF417Common.java rename to port_src/core/DONE/pdf417/PDF417Common.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/PDF417Reader.java b/port_src/core/DONE/pdf417/PDF417Reader.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/PDF417Reader.java rename to port_src/core/DONE/pdf417/PDF417Reader.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java b/port_src/core/DONE/pdf417/PDF417ResultMetadata.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java rename to port_src/core/DONE/pdf417/PDF417ResultMetadata.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/PDF417Writer.java b/port_src/core/DONE/pdf417/PDF417Writer.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/PDF417Writer.java rename to port_src/core/DONE/pdf417/PDF417Writer.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/BarcodeMetadata.java b/port_src/core/DONE/pdf417/decoder/BarcodeMetadata.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/BarcodeMetadata.java rename to port_src/core/DONE/pdf417/decoder/BarcodeMetadata.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/BarcodeValue.java b/port_src/core/DONE/pdf417/decoder/BarcodeValue.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/BarcodeValue.java rename to port_src/core/DONE/pdf417/decoder/BarcodeValue.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/BoundingBox.java b/port_src/core/DONE/pdf417/decoder/BoundingBox.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/BoundingBox.java rename to port_src/core/DONE/pdf417/decoder/BoundingBox.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/Codeword.java b/port_src/core/DONE/pdf417/decoder/Codeword.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/Codeword.java rename to port_src/core/DONE/pdf417/decoder/Codeword.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java b/port_src/core/DONE/pdf417/decoder/DecodedBitStreamParser.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java rename to port_src/core/DONE/pdf417/decoder/DecodedBitStreamParser.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResult.java b/port_src/core/DONE/pdf417/decoder/DetectionResult.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResult.java rename to port_src/core/DONE/pdf417/decoder/DetectionResult.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResultColumn.java b/port_src/core/DONE/pdf417/decoder/DetectionResultColumn.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResultColumn.java rename to port_src/core/DONE/pdf417/decoder/DetectionResultColumn.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResultRowIndicatorColumn.java b/port_src/core/DONE/pdf417/decoder/DetectionResultRowIndicatorColumn.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/DetectionResultRowIndicatorColumn.java rename to port_src/core/DONE/pdf417/decoder/DetectionResultRowIndicatorColumn.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/PDF417CodewordDecoder.java b/port_src/core/DONE/pdf417/decoder/PDF417CodewordDecoder.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/PDF417CodewordDecoder.java rename to port_src/core/DONE/pdf417/decoder/PDF417CodewordDecoder.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/PDF417ScanningDecoder.java b/port_src/core/DONE/pdf417/decoder/PDF417ScanningDecoder.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/PDF417ScanningDecoder.java rename to port_src/core/DONE/pdf417/decoder/PDF417ScanningDecoder.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/ec/ErrorCorrection.java b/port_src/core/DONE/pdf417/decoder/ec/ErrorCorrection.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/ec/ErrorCorrection.java rename to port_src/core/DONE/pdf417/decoder/ec/ErrorCorrection.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/ec/ModulusGF.java b/port_src/core/DONE/pdf417/decoder/ec/ModulusGF.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/ec/ModulusGF.java rename to port_src/core/DONE/pdf417/decoder/ec/ModulusGF.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/decoder/ec/ModulusPoly.java b/port_src/core/DONE/pdf417/decoder/ec/ModulusPoly.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/decoder/ec/ModulusPoly.java rename to port_src/core/DONE/pdf417/decoder/ec/ModulusPoly.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/detector/Detector.java b/port_src/core/DONE/pdf417/detector/Detector.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/detector/Detector.java rename to port_src/core/DONE/pdf417/detector/Detector.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/detector/PDF417DetectorResult.java b/port_src/core/DONE/pdf417/detector/PDF417DetectorResult.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/detector/PDF417DetectorResult.java rename to port_src/core/DONE/pdf417/detector/PDF417DetectorResult.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/encoder/BarcodeMatrix.java b/port_src/core/DONE/pdf417/encoder/BarcodeMatrix.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/encoder/BarcodeMatrix.java rename to port_src/core/DONE/pdf417/encoder/BarcodeMatrix.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/encoder/BarcodeRow.java b/port_src/core/DONE/pdf417/encoder/BarcodeRow.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/encoder/BarcodeRow.java rename to port_src/core/DONE/pdf417/encoder/BarcodeRow.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/encoder/Compaction.java b/port_src/core/DONE/pdf417/encoder/Compaction.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/encoder/Compaction.java rename to port_src/core/DONE/pdf417/encoder/Compaction.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/encoder/Dimensions.java b/port_src/core/DONE/pdf417/encoder/Dimensions.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/encoder/Dimensions.java rename to port_src/core/DONE/pdf417/encoder/Dimensions.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417.java b/port_src/core/DONE/pdf417/encoder/PDF417.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417.java rename to port_src/core/DONE/pdf417/encoder/PDF417.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417ErrorCorrection.java b/port_src/core/DONE/pdf417/encoder/PDF417ErrorCorrection.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417ErrorCorrection.java rename to port_src/core/DONE/pdf417/encoder/PDF417ErrorCorrection.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoder.java b/port_src/core/DONE/pdf417/encoder/PDF417HighLevelEncoder.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoder.java rename to port_src/core/DONE/pdf417/encoder/PDF417HighLevelEncoder.java diff --git a/port_src/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoderTestAdapter.java b/port_src/core/DONE/pdf417/encoder/PDF417HighLevelEncoderTestAdapter.java similarity index 100% rename from port_src/core/src/main/java/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoderTestAdapter.java rename to port_src/core/DONE/pdf417/encoder/PDF417HighLevelEncoderTestAdapter.java diff --git a/port_src/output/zxing/pdf417/decoder/barcode_metadata.rs b/port_src/output/zxing/pdf417/decoder/barcode_metadata.rs deleted file mode 100644 index c9cfd16..0000000 --- a/port_src/output/zxing/pdf417/decoder/barcode_metadata.rs +++ /dev/null @@ -1,64 +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::pdf417::decoder; - -/** - * @author Guenther Grau - */ -struct BarcodeMetadata { - - let column_count: i32; - - let error_correction_level: i32; - - let row_count_upper_part: i32; - - let row_count_lower_part: i32; - - let row_count: i32; -} - -impl BarcodeMetadata { - - fn new( column_count: i32, row_count_upper_part: i32, row_count_lower_part: i32, error_correction_level: i32) -> BarcodeMetadata { - let .columnCount = column_count; - let .errorCorrectionLevel = error_correction_level; - let .rowCountUpperPart = row_count_upper_part; - let .rowCountLowerPart = row_count_lower_part; - let .rowCount = row_count_upper_part + row_count_lower_part; - } - - fn get_column_count(&self) -> i32 { - return self.column_count; - } - - fn get_error_correction_level(&self) -> i32 { - return self.error_correction_level; - } - - fn get_row_count(&self) -> i32 { - return self.row_count; - } - - fn get_row_count_upper_part(&self) -> i32 { - return self.row_count_upper_part; - } - - fn get_row_count_lower_part(&self) -> i32 { - return self.row_count_lower_part; - } -} - diff --git a/port_src/output/zxing/pdf417/decoder/barcode_value.rs b/port_src/output/zxing/pdf417/decoder/barcode_value.rs deleted file mode 100644 index e5fc3df..0000000 --- a/port_src/output/zxing/pdf417/decoder/barcode_value.rs +++ /dev/null @@ -1,63 +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::pdf417::decoder; - -/** - * @author Guenther Grau - */ -struct BarcodeValue { - - let values: Map = HashMap<>::new(); -} - -impl BarcodeValue { - - /** - * Add an occurrence of a value - */ - fn set_value(&self, value: i32) { - let mut confidence: Integer = self.values.get(value); - if confidence == null { - confidence = 0; - } - confidence += 1; - self.values.put(value, &confidence); - } - - /** - * Determines the maximum occurrence of a set value and returns all values which were set with this occurrence. - * @return an array of int, containing the values with the highest occurrence, or null, if no value was set - */ - fn get_value(&self) -> Vec { - let max_confidence: i32 = -1; - let result: Collection = ArrayList<>::new(); - for let entry: Entry in self.values.entry_set() { - if entry.get_value() > max_confidence { - max_confidence = entry.get_value(); - result.clear(); - result.add(&entry.get_key()); - } else if entry.get_value() == max_confidence { - result.add(&entry.get_key()); - } - } - return PDF417Common::to_int_array(&result); - } - - fn get_confidence(&self, value: i32) -> Integer { - return self.values.get(value); - } -} - diff --git a/port_src/output/zxing/pdf417/decoder/bounding_box.rs b/port_src/output/zxing/pdf417/decoder/bounding_box.rs deleted file mode 100644 index 08c8a2f..0000000 --- a/port_src/output/zxing/pdf417/decoder/bounding_box.rs +++ /dev/null @@ -1,156 +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::pdf417::decoder; - -/** - * @author Guenther Grau - */ -struct BoundingBox { - - let mut image: BitMatrix; - - let top_left: ResultPoint; - - let bottom_left: ResultPoint; - - let top_right: ResultPoint; - - let bottom_right: ResultPoint; - - let min_x: i32; - - let max_x: i32; - - let min_y: i32; - - let max_y: i32; -} - -impl BoundingBox { - - fn new( image: &BitMatrix, top_left: &ResultPoint, bottom_left: &ResultPoint, top_right: &ResultPoint, bottom_right: &ResultPoint) -> BoundingBox throws NotFoundException { - let left_unspecified: bool = top_left == null || bottom_left == null; - let right_unspecified: bool = top_right == null || bottom_right == null; - if left_unspecified && right_unspecified { - throw NotFoundException::get_not_found_instance(); - } - if left_unspecified { - top_left = ResultPoint::new(0, &top_right.get_y()); - bottom_left = ResultPoint::new(0, &bottom_right.get_y()); - } else if right_unspecified { - top_right = ResultPoint::new(image.get_width() - 1, &top_left.get_y()); - bottom_right = ResultPoint::new(image.get_width() - 1, &bottom_left.get_y()); - } - let .image = image; - let .topLeft = top_left; - let .bottomLeft = bottom_left; - let .topRight = top_right; - let .bottomRight = bottom_right; - let .minX = Math::min(&top_left.get_x(), &bottom_left.get_x()) as i32; - let .maxX = Math::max(&top_right.get_x(), &bottom_right.get_x()) as i32; - let .minY = Math::min(&top_left.get_y(), &top_right.get_y()) as i32; - let .maxY = Math::max(&bottom_left.get_y(), &bottom_right.get_y()) as i32; - } - - fn new( bounding_box: &BoundingBox) -> BoundingBox { - let .image = bounding_box.image; - let .topLeft = bounding_box.topLeft; - let .bottomLeft = bounding_box.bottomLeft; - let .topRight = bounding_box.topRight; - let .bottomRight = bounding_box.bottomRight; - let .minX = bounding_box.minX; - let .maxX = bounding_box.maxX; - let .minY = bounding_box.minY; - let .maxY = bounding_box.maxY; - } - - fn merge( left_box: &BoundingBox, right_box: &BoundingBox) -> /* throws NotFoundException */Result> { - if left_box == null { - return Ok(right_box); - } - if right_box == null { - return Ok(left_box); - } - return Ok(BoundingBox::new(left_box.image, left_box.topLeft, left_box.bottomLeft, right_box.topRight, right_box.bottomRight)); - } - - fn add_missing_rows(&self, missing_start_rows: i32, missing_end_rows: i32, is_left: bool) -> /* throws NotFoundException */Result> { - let new_top_left: ResultPoint = self.top_left; - let new_bottom_left: ResultPoint = self.bottom_left; - let new_top_right: ResultPoint = self.top_right; - let new_bottom_right: ResultPoint = self.bottom_right; - if missing_start_rows > 0 { - let top: ResultPoint = if is_left { self.top_left } else { self.top_right }; - let new_min_y: i32 = top.get_y() as i32 - missing_start_rows; - if new_min_y < 0 { - new_min_y = 0; - } - let new_top: ResultPoint = ResultPoint::new(&top.get_x(), new_min_y); - if is_left { - new_top_left = new_top; - } else { - new_top_right = new_top; - } - } - if missing_end_rows > 0 { - let bottom: ResultPoint = if is_left { self.bottom_left } else { self.bottom_right }; - let new_max_y: i32 = bottom.get_y() as i32 + missing_end_rows; - if new_max_y >= self.image.get_height() { - new_max_y = self.image.get_height() - 1; - } - let new_bottom: ResultPoint = ResultPoint::new(&bottom.get_x(), new_max_y); - if is_left { - new_bottom_left = new_bottom; - } else { - new_bottom_right = new_bottom; - } - } - return Ok(BoundingBox::new(self.image, new_top_left, new_bottom_left, new_top_right, new_bottom_right)); - } - - fn get_min_x(&self) -> i32 { - return self.min_x; - } - - fn get_max_x(&self) -> i32 { - return self.max_x; - } - - fn get_min_y(&self) -> i32 { - return self.min_y; - } - - fn get_max_y(&self) -> i32 { - return self.max_y; - } - - fn get_top_left(&self) -> ResultPoint { - return self.top_left; - } - - fn get_top_right(&self) -> ResultPoint { - return self.top_right; - } - - fn get_bottom_left(&self) -> ResultPoint { - return self.bottom_left; - } - - fn get_bottom_right(&self) -> ResultPoint { - return self.bottom_right; - } -} - diff --git a/port_src/output/zxing/pdf417/decoder/codeword.rs b/port_src/output/zxing/pdf417/decoder/codeword.rs deleted file mode 100644 index 85f04e0..0000000 --- a/port_src/output/zxing/pdf417/decoder/codeword.rs +++ /dev/null @@ -1,89 +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::pdf417::decoder; - -/** - * @author Guenther Grau - */ - - const BARCODE_ROW_UNKNOWN: i32 = -1; -struct Codeword { - - let start_x: i32; - - let end_x: i32; - - let bucket: i32; - - let value: i32; - - let row_number: i32 = BARCODE_ROW_UNKNOWN; -} - -impl Codeword { - - fn new( start_x: i32, end_x: i32, bucket: i32, value: i32) -> Codeword { - let .startX = start_x; - let .endX = end_x; - let .bucket = bucket; - let .value = value; - } - - fn has_valid_row_number(&self) -> bool { - return self.is_valid_row_number(self.row_number); - } - - fn is_valid_row_number(&self, row_number: i32) -> bool { - return row_number != BARCODE_ROW_UNKNOWN && self.bucket == (row_number % 3) * 3; - } - - fn set_row_number_as_row_indicator_column(&self) { - self.row_number = (self.value / 30) * 3 + self.bucket / 3; - } - - fn get_width(&self) -> i32 { - return self.end_x - self.start_x; - } - - fn get_start_x(&self) -> i32 { - return self.start_x; - } - - fn get_end_x(&self) -> i32 { - return self.end_x; - } - - fn get_bucket(&self) -> i32 { - return self.bucket; - } - - fn get_value(&self) -> i32 { - return self.value; - } - - fn get_row_number(&self) -> i32 { - return self.row_number; - } - - fn set_row_number(&self, row_number: i32) { - self.rowNumber = row_number; - } - - pub fn to_string(&self) -> String { - return format!("{}|{}", self.row_number, self.value); - } -} - diff --git a/port_src/output/zxing/pdf417/decoder/decoded_bit_stream_parser.rs b/port_src/output/zxing/pdf417/decoder/decoded_bit_stream_parser.rs deleted file mode 100644 index 8edac0b..0000000 --- a/port_src/output/zxing/pdf417/decoder/decoded_bit_stream_parser.rs +++ /dev/null @@ -1,857 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// package com::google::zxing::pdf417::decoder; - -/** - *

This class contains the methods for decoding the PDF417 codewords.

- * - * @author SITA Lab (kevin.osullivan@sita.aero) - * @author Guenther Grau - */ - - const TEXT_COMPACTION_MODE_LATCH: i32 = 900; - - const BYTE_COMPACTION_MODE_LATCH: i32 = 901; - - const NUMERIC_COMPACTION_MODE_LATCH: i32 = 902; - - const BYTE_COMPACTION_MODE_LATCH_6: i32 = 924; - - const ECI_USER_DEFINED: i32 = 925; - - const ECI_GENERAL_PURPOSE: i32 = 926; - - const ECI_CHARSET: i32 = 927; - - const BEGIN_MACRO_PDF417_CONTROL_BLOCK: i32 = 928; - - const BEGIN_MACRO_PDF417_OPTIONAL_FIELD: i32 = 923; - - const MACRO_PDF417_TERMINATOR: i32 = 922; - - const MODE_SHIFT_TO_BYTE_COMPACTION_MODE: i32 = 913; - - const MAX_NUMERIC_CODEWORDS: i32 = 15; - - const MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME: i32 = 0; - - const MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT: i32 = 1; - - const MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP: i32 = 2; - - const MACRO_PDF417_OPTIONAL_FIELD_SENDER: i32 = 3; - - const MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE: i32 = 4; - - const MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE: i32 = 5; - - const MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM: i32 = 6; - - const PL: i32 = 25; - - const LL: i32 = 27; - - const AS: i32 = 27; - - const ML: i32 = 28; - - const AL: i32 = 28; - - const PS: i32 = 29; - - const PAL: i32 = 29; - - const PUNCT_CHARS: Vec = ";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'".to_char_array(); - - const MIXED_CHARS: Vec = "0123456789&\r\t,:#-.$/+%*=^".to_char_array(); - -/** - * Table containing values for the exponent of 900. - * This is used in the numeric compaction decode algorithm. - */ - const EXP900: Vec; - - const NUMBER_OF_SEQUENCE_CODEWORDS: i32 = 2; -struct DecodedBitStreamParser { -} - -impl DecodedBitStreamParser { - - enum Mode { - - ALPHA(), LOWER(), MIXED(), PUNCT(), ALPHA_SHIFT(), PUNCT_SHIFT() - } - - static { - EXP900 = : [Option; 16] = [None; 16]; - EXP900[0] = BigInteger::ONE; - let nine_hundred: BigInteger = BigInteger::value_of(900); - EXP900[1] = nine_hundred; - { - let mut i: i32 = 2; - while i < EXP900.len() { - { - EXP900[i] = EXP900[i - 1]::multiply(&nine_hundred); - } - i += 1; - } - } - - } - - fn new() -> DecodedBitStreamParser { - } - - fn decode( codewords: &Vec, ec_level: &String) -> /* throws FormatException */Result> { - let result: ECIStringBuilder = ECIStringBuilder::new(codewords.len() * 2); - let code_index: i32 = ::text_compaction(&codewords, 1, result); - let result_metadata: PDF417ResultMetadata = PDF417ResultMetadata::new(); - while code_index < codewords[0] { - let code: i32 = codewords[code_index += 1 !!!check!!! post increment]; - match code { - TEXT_COMPACTION_MODE_LATCH => - { - code_index = ::text_compaction(&codewords, code_index, result); - break; - } - BYTE_COMPACTION_MODE_LATCH => - { - } - BYTE_COMPACTION_MODE_LATCH_6 => - { - code_index = ::byte_compaction(code, &codewords, code_index, result); - break; - } - MODE_SHIFT_TO_BYTE_COMPACTION_MODE => - { - result.append(codewords[code_index += 1 !!!check!!! post increment] as char); - break; - } - NUMERIC_COMPACTION_MODE_LATCH => - { - code_index = ::numeric_compaction(&codewords, code_index, result); - break; - } - ECI_CHARSET => - { - result.append_e_c_i(codewords[code_index += 1 !!!check!!! post increment]); - break; - } - ECI_GENERAL_PURPOSE => - { - // Can't do anything with generic ECI; skip its 2 characters - code_index += 2; - break; - } - ECI_USER_DEFINED => - { - // Can't do anything with user ECI; skip its 1 character - code_index += 1; - break; - } - BEGIN_MACRO_PDF417_CONTROL_BLOCK => - { - code_index = ::decode_macro_block(&codewords, code_index, result_metadata); - break; - } - BEGIN_MACRO_PDF417_OPTIONAL_FIELD => - { - } - MACRO_PDF417_TERMINATOR => - { - // Should not see these outside a macro block - throw FormatException::get_format_instance(); - } - _ => - { - // Default to text compaction. During testing numerous barcodes - // appeared to be missing the starting mode. In these cases defaulting - // to text compaction seems to work. - code_index -= 1; - code_index = ::text_compaction(&codewords, code_index, result); - break; - } - } - } - if result.is_empty() && result_metadata.get_file_id() == null { - throw FormatException::get_format_instance(); - } - let decoder_result: DecoderResult = DecoderResult::new(null, &result.to_string(), null, &ec_level); - decoder_result.set_other(result_metadata); - return Ok(decoder_result); - } - - fn decode_macro_block( codewords: &Vec, code_index: i32, result_metadata: &PDF417ResultMetadata) -> /* throws FormatException */Result> { - if code_index + NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0] { - // we must have at least two bytes left for the segment index - throw FormatException::get_format_instance(); - } - let segment_index_array: [i32; NUMBER_OF_SEQUENCE_CODEWORDS] = [0; NUMBER_OF_SEQUENCE_CODEWORDS]; - { - let mut i: i32 = 0; - while i < NUMBER_OF_SEQUENCE_CODEWORDS { - { - segment_index_array[i] = codewords[code_index]; - } - i += 1; - code_index += 1; - } - } - - let segment_index_string: String = ::decode_base900to_base10(&segment_index_array, NUMBER_OF_SEQUENCE_CODEWORDS); - if segment_index_string.is_empty() { - result_metadata.set_segment_index(0); - } else { - let tryResult1 = 0; - 'try1: loop { - { - result_metadata.set_segment_index(&Integer::parse_int(&segment_index_string)); - } - break 'try1 - } - match tryResult1 { - catch ( nfe: &NumberFormatException) { - throw FormatException::get_format_instance(); - } 0 => break - } - - } - // Decoding the fileId codewords as 0-899 numbers, each 0-filled to width 3. This follows the spec - // (See ISO/IEC 15438:2015 Annex H.6) and preserves all info, but some generators (e.g. TEC-IT) write - // the fileId using text compaction, so in those cases the fileId will appear mangled. - let file_id: StringBuilder = StringBuilder::new(); - while code_index < codewords[0] && code_index < codewords.len() && codewords[code_index] != MACRO_PDF417_TERMINATOR && codewords[code_index] != BEGIN_MACRO_PDF417_OPTIONAL_FIELD { - file_id.append(&String::format("%03d", codewords[code_index])); - code_index += 1; - } - if file_id.length() == 0 { - // at least one fileId codeword is required (Annex H.2) - throw FormatException::get_format_instance(); - } - result_metadata.set_file_id(&file_id.to_string()); - let optional_fields_start: i32 = -1; - if codewords[code_index] == BEGIN_MACRO_PDF417_OPTIONAL_FIELD { - optional_fields_start = code_index + 1; - } - while code_index < codewords[0] { - match codewords[code_index] { - BEGIN_MACRO_PDF417_OPTIONAL_FIELD => - { - code_index += 1; - match codewords[code_index] { - MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME => - { - let file_name: ECIStringBuilder = ECIStringBuilder::new(); - code_index = ::text_compaction(&codewords, code_index + 1, file_name); - result_metadata.set_file_name(&file_name.to_string()); - break; - } - MACRO_PDF417_OPTIONAL_FIELD_SENDER => - { - let sender: ECIStringBuilder = ECIStringBuilder::new(); - code_index = ::text_compaction(&codewords, code_index + 1, sender); - result_metadata.set_sender(&sender.to_string()); - break; - } - MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE => - { - let addressee: ECIStringBuilder = ECIStringBuilder::new(); - code_index = ::text_compaction(&codewords, code_index + 1, addressee); - result_metadata.set_addressee(&addressee.to_string()); - break; - } - MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT => - { - let segment_count: ECIStringBuilder = ECIStringBuilder::new(); - code_index = ::numeric_compaction(&codewords, code_index + 1, segment_count); - result_metadata.set_segment_count(&Integer::parse_int(&segment_count.to_string())); - break; - } - MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP => - { - let timestamp: ECIStringBuilder = ECIStringBuilder::new(); - code_index = ::numeric_compaction(&codewords, code_index + 1, timestamp); - result_metadata.set_timestamp(&Long::parse_long(×tamp.to_string())); - break; - } - MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM => - { - let checksum: ECIStringBuilder = ECIStringBuilder::new(); - code_index = ::numeric_compaction(&codewords, code_index + 1, checksum); - result_metadata.set_checksum(&Integer::parse_int(&checksum.to_string())); - break; - } - MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE => - { - let file_size: ECIStringBuilder = ECIStringBuilder::new(); - code_index = ::numeric_compaction(&codewords, code_index + 1, file_size); - result_metadata.set_file_size(&Long::parse_long(&file_size.to_string())); - break; - } - _ => - { - throw FormatException::get_format_instance(); - } - } - break; - } - MACRO_PDF417_TERMINATOR => - { - code_index += 1; - result_metadata.set_last_segment(true); - break; - } - _ => - { - throw FormatException::get_format_instance(); - } - } - } - // copy optional fields to additional options - if optional_fields_start != -1 { - let optional_fields_length: i32 = code_index - optional_fields_start; - if result_metadata.is_last_segment() { - // do not include terminator - optional_fields_length -= 1; - } - result_metadata.set_optional_data(&Arrays::copy_of_range(&codewords, optional_fields_start, optional_fields_start + optional_fields_length)); - } - return Ok(code_index); - } - - /** - * Text Compaction mode (see 5.4.1.5) permits all printable ASCII characters to be - * encoded, i.e. values 32 - 126 inclusive in accordance with ISO/IEC 646 (IRV), as - * well as selected control characters. - * - * @param codewords The array of codewords (data + error) - * @param codeIndex The current index into the codeword array. - * @param result The decoded data is appended to the result. - * @return The next index into the codeword array. - */ - fn text_compaction( codewords: &Vec, code_index: i32, result: &ECIStringBuilder) -> /* throws FormatException */Result> { - // 2 character per codeword - let text_compaction_data: [i32; (codewords[0] - code_index) * 2] = [0; (codewords[0] - code_index) * 2]; - // Used to hold the byte compaction value if there is a mode shift - let byte_compaction_data: [i32; (codewords[0] - code_index) * 2] = [0; (codewords[0] - code_index) * 2]; - let mut index: i32 = 0; - let mut end: bool = false; - let sub_mode: Mode = Mode::ALPHA; - while (code_index < codewords[0]) && !end { - let mut code: i32 = codewords[code_index += 1 !!!check!!! post increment]; - if code < TEXT_COMPACTION_MODE_LATCH { - text_compaction_data[index] = code / 30; - text_compaction_data[index + 1] = code % 30; - index += 2; - } else { - match code { - TEXT_COMPACTION_MODE_LATCH => - { - // reinitialize text compaction mode to alpha sub mode - text_compaction_data[index += 1 !!!check!!! post increment] = TEXT_COMPACTION_MODE_LATCH; - break; - } - BYTE_COMPACTION_MODE_LATCH => - { - } - BYTE_COMPACTION_MODE_LATCH_6 => - { - } - NUMERIC_COMPACTION_MODE_LATCH => - { - } - BEGIN_MACRO_PDF417_CONTROL_BLOCK => - { - } - BEGIN_MACRO_PDF417_OPTIONAL_FIELD => - { - } - MACRO_PDF417_TERMINATOR => - { - code_index -= 1; - end = true; - break; - } - MODE_SHIFT_TO_BYTE_COMPACTION_MODE => - { - // The Mode Shift codeword 913 shall cause a temporary - // switch from Text Compaction mode to Byte Compaction mode. - // This switch shall be in effect for only the next codeword, - // after which the mode shall revert to the prevailing sub-mode - // of the Text Compaction mode. Codeword 913 is only available - // in Text Compaction mode; its use is described in 5.4.2.4. - text_compaction_data[index] = MODE_SHIFT_TO_BYTE_COMPACTION_MODE; - code = codewords[code_index += 1 !!!check!!! post increment]; - byte_compaction_data[index] = code; - index += 1; - break; - } - ECI_CHARSET => - { - sub_mode = ::decode_text_compaction(&text_compaction_data, &byte_compaction_data, index, result, sub_mode); - result.append_e_c_i(codewords[code_index += 1 !!!check!!! post increment]); - text_compaction_data = : [i32; (codewords[0] - code_index) * 2] = [0; (codewords[0] - code_index) * 2]; - byte_compaction_data = : [i32; (codewords[0] - code_index) * 2] = [0; (codewords[0] - code_index) * 2]; - index = 0; - break; - } - } - } - } - ::decode_text_compaction(&text_compaction_data, &byte_compaction_data, index, result, sub_mode); - return Ok(code_index); - } - - /** - * The Text Compaction mode includes all the printable ASCII characters - * (i.e. values from 32 to 126) and three ASCII control characters: HT or tab - * (ASCII value 9), LF or line feed (ASCII value 10), and CR or carriage - * return (ASCII value 13). The Text Compaction mode also includes various latch - * and shift characters which are used exclusively within the mode. The Text - * Compaction mode encodes up to 2 characters per codeword. The compaction rules - * for converting data into PDF417 codewords are defined in 5.4.2.2. The sub-mode - * switches are defined in 5.4.2.3. - * - * @param textCompactionData The text compaction data. - * @param byteCompactionData The byte compaction data if there - * was a mode shift. - * @param length The size of the text compaction and byte compaction data. - * @param result The decoded data is appended to the result. - * @param startMode The mode in which decoding starts - * @return The mode in which decoding ended - */ - fn decode_text_compaction( text_compaction_data: &Vec, byte_compaction_data: &Vec, length: i32, result: &ECIStringBuilder, start_mode: &Mode) -> Mode { - // Beginning from an initial state - // The default compaction mode for PDF417 in effect at the start of each symbol shall always be Text - // Compaction mode Alpha sub-mode (uppercase alphabetic). A latch codeword from another mode to the Text - // Compaction mode shall always switch to the Text Compaction Alpha sub-mode. - let sub_mode: Mode = start_mode; - let prior_to_shift_mode: Mode = start_mode; - let latched_mode: Mode = start_mode; - let mut i: i32 = 0; - while i < length { - let sub_mode_ch: i32 = text_compaction_data[i]; - let mut ch: char = 0; - match sub_mode { - ALPHA => - { - // Alpha (uppercase alphabetic) - if sub_mode_ch < 26 { - // Upper case Alpha Character - ch = ('A' + sub_mode_ch) as char; - } else { - match sub_mode_ch { - 26 => - { - ch = ' '; - break; - } - LL => - { - sub_mode = Mode::LOWER; - latched_mode = sub_mode; - break; - } - ML => - { - sub_mode = Mode::MIXED; - latched_mode = sub_mode; - break; - } - PS => - { - // Shift to punctuation - prior_to_shift_mode = sub_mode; - sub_mode = Mode::PUNCT_SHIFT; - break; - } - MODE_SHIFT_TO_BYTE_COMPACTION_MODE => - { - result.append(byte_compaction_data[i] as char); - break; - } - TEXT_COMPACTION_MODE_LATCH => - { - sub_mode = Mode::ALPHA; - latched_mode = sub_mode; - break; - } - } - } - break; - } - LOWER => - { - // Lower (lowercase alphabetic) - if sub_mode_ch < 26 { - ch = ('a' + sub_mode_ch) as char; - } else { - match sub_mode_ch { - 26 => - { - ch = ' '; - break; - } - AS => - { - // Shift to alpha - prior_to_shift_mode = sub_mode; - sub_mode = Mode::ALPHA_SHIFT; - break; - } - ML => - { - sub_mode = Mode::MIXED; - latched_mode = sub_mode; - break; - } - PS => - { - // Shift to punctuation - prior_to_shift_mode = sub_mode; - sub_mode = Mode::PUNCT_SHIFT; - break; - } - MODE_SHIFT_TO_BYTE_COMPACTION_MODE => - { - result.append(byte_compaction_data[i] as char); - break; - } - TEXT_COMPACTION_MODE_LATCH => - { - sub_mode = Mode::ALPHA; - latched_mode = sub_mode; - break; - } - } - } - break; - } - MIXED => - { - // Mixed (numeric and some punctuation) - if sub_mode_ch < PL { - ch = MIXED_CHARS[sub_mode_ch]; - } else { - match sub_mode_ch { - PL => - { - sub_mode = Mode::PUNCT; - latched_mode = sub_mode; - break; - } - 26 => - { - ch = ' '; - break; - } - LL => - { - sub_mode = Mode::LOWER; - latched_mode = sub_mode; - break; - } - AL => - { - } - TEXT_COMPACTION_MODE_LATCH => - { - sub_mode = Mode::ALPHA; - latched_mode = sub_mode; - break; - } - PS => - { - // Shift to punctuation - prior_to_shift_mode = sub_mode; - sub_mode = Mode::PUNCT_SHIFT; - break; - } - MODE_SHIFT_TO_BYTE_COMPACTION_MODE => - { - result.append(byte_compaction_data[i] as char); - break; - } - } - } - break; - } - PUNCT => - { - // Punctuation - if sub_mode_ch < PAL { - ch = PUNCT_CHARS[sub_mode_ch]; - } else { - match sub_mode_ch { - PAL => - { - } - TEXT_COMPACTION_MODE_LATCH => - { - sub_mode = Mode::ALPHA; - latched_mode = sub_mode; - break; - } - MODE_SHIFT_TO_BYTE_COMPACTION_MODE => - { - result.append(byte_compaction_data[i] as char); - break; - } - } - } - break; - } - ALPHA_SHIFT => - { - // Restore sub-mode - sub_mode = prior_to_shift_mode; - if sub_mode_ch < 26 { - ch = ('A' + sub_mode_ch) as char; - } else { - match sub_mode_ch { - 26 => - { - ch = ' '; - break; - } - TEXT_COMPACTION_MODE_LATCH => - { - sub_mode = Mode::ALPHA; - break; - } - } - } - break; - } - PUNCT_SHIFT => - { - // Restore sub-mode - sub_mode = prior_to_shift_mode; - if sub_mode_ch < PAL { - ch = PUNCT_CHARS[sub_mode_ch]; - } else { - match sub_mode_ch { - PAL => - { - } - TEXT_COMPACTION_MODE_LATCH => - { - sub_mode = Mode::ALPHA; - break; - } - MODE_SHIFT_TO_BYTE_COMPACTION_MODE => - { - // PS before Shift-to-Byte is used as a padding character, - // see 5.4.2.4 of the specification - result.append(byte_compaction_data[i] as char); - break; - } - } - } - break; - } - } - if ch != 0 { - // Append decoded character to result - result.append(ch); - } - i += 1; - } - return latched_mode; - } - - /** - * Byte Compaction mode (see 5.4.3) permits all 256 possible 8-bit byte values to be encoded. - * This includes all ASCII characters value 0 to 127 inclusive and provides for international - * character set support. - * - * @param mode The byte compaction mode i.e. 901 or 924 - * @param codewords The array of codewords (data + error) - * @param codeIndex The current index into the codeword array. - * @param result The decoded data is appended to the result. - * @return The next index into the codeword array. - */ - fn byte_compaction( mode: i32, codewords: &Vec, code_index: i32, result: &ECIStringBuilder) -> /* throws FormatException */Result> { - let mut end: bool = false; - while code_index < codewords[0] && !end { - //handle leading ECIs - while code_index < codewords[0] && codewords[code_index] == ECI_CHARSET { - result.append_e_c_i(codewords[code_index += 1]); - code_index += 1; - } - if code_index >= codewords[0] || codewords[code_index] >= TEXT_COMPACTION_MODE_LATCH { - end = true; - } else { - //decode one block of 5 codewords to 6 bytes - let mut value: i64 = 0; - let mut count: i32 = 0; - loop { { - value = 900 * value + codewords[code_index += 1 !!!check!!! post increment]; - count += 1; - }if !(count < 5 && code_index < codewords[0] && codewords[code_index] < TEXT_COMPACTION_MODE_LATCH) break;} - if count == 5 && (mode == BYTE_COMPACTION_MODE_LATCH_6 || code_index < codewords[0] && codewords[code_index] < TEXT_COMPACTION_MODE_LATCH) { - { - let mut i: i32 = 0; - while i < 6 { - { - result.append((value >> (8 * (5 - i))) as i8); - } - i += 1; - } - } - - } else { - code_index -= count; - while (code_index < codewords[0]) && !end { - let code: i32 = codewords[code_index += 1 !!!check!!! post increment]; - if code < TEXT_COMPACTION_MODE_LATCH { - result.append(code as i8); - } else if code == ECI_CHARSET { - result.append_e_c_i(codewords[code_index += 1 !!!check!!! post increment]); - } else { - code_index -= 1; - end = true; - } - } - } - } - } - return Ok(code_index); - } - - /** - * Numeric Compaction mode (see 5.4.4) permits efficient encoding of numeric data strings. - * - * @param codewords The array of codewords (data + error) - * @param codeIndex The current index into the codeword array. - * @param result The decoded data is appended to the result. - * @return The next index into the codeword array. - */ - fn numeric_compaction( codewords: &Vec, code_index: i32, result: &ECIStringBuilder) -> /* throws FormatException */Result> { - let mut count: i32 = 0; - let mut end: bool = false; - let numeric_codewords: [i32; MAX_NUMERIC_CODEWORDS] = [0; MAX_NUMERIC_CODEWORDS]; - while code_index < codewords[0] && !end { - let code: i32 = codewords[code_index += 1 !!!check!!! post increment]; - if code_index == codewords[0] { - end = true; - } - if code < TEXT_COMPACTION_MODE_LATCH { - numeric_codewords[count] = code; - count += 1; - } else { - match code { - TEXT_COMPACTION_MODE_LATCH => - { - } - BYTE_COMPACTION_MODE_LATCH => - { - } - BYTE_COMPACTION_MODE_LATCH_6 => - { - } - BEGIN_MACRO_PDF417_CONTROL_BLOCK => - { - } - BEGIN_MACRO_PDF417_OPTIONAL_FIELD => - { - } - MACRO_PDF417_TERMINATOR => - { - } - ECI_CHARSET => - { - code_index -= 1; - end = true; - break; - } - } - } - if (count % MAX_NUMERIC_CODEWORDS == 0 || code == NUMERIC_COMPACTION_MODE_LATCH || end) && count > 0 { - // Re-invoking Numeric Compaction mode (by using codeword 902 - // while in Numeric Compaction mode) serves to terminate the - // current Numeric Compaction mode grouping as described in 5.4.4.2, - // and then to start a new one grouping. - result.append(&::decode_base900to_base10(&numeric_codewords, count)); - count = 0; - } - } - return Ok(code_index); - } - - /** - * Convert a list of Numeric Compacted codewords from Base 900 to Base 10. - * - * @param codewords The array of codewords - * @param count The number of codewords - * @return The decoded string representing the Numeric data. - */ - /* - EXAMPLE - Encode the fifteen digit numeric string 000213298174000 - Prefix the numeric string with a 1 and set the initial value of - t = 1 000 213 298 174 000 - Calculate codeword 0 - d0 = 1 000 213 298 174 000 mod 900 = 200 - - t = 1 000 213 298 174 000 div 900 = 1 111 348 109 082 - Calculate codeword 1 - d1 = 1 111 348 109 082 mod 900 = 282 - - t = 1 111 348 109 082 div 900 = 1 234 831 232 - Calculate codeword 2 - d2 = 1 234 831 232 mod 900 = 632 - - t = 1 234 831 232 div 900 = 1 372 034 - Calculate codeword 3 - d3 = 1 372 034 mod 900 = 434 - - t = 1 372 034 div 900 = 1 524 - Calculate codeword 4 - d4 = 1 524 mod 900 = 624 - - t = 1 524 div 900 = 1 - Calculate codeword 5 - d5 = 1 mod 900 = 1 - t = 1 div 900 = 0 - Codeword sequence is: 1, 624, 434, 632, 282, 200 - - Decode the above codewords involves - 1 x 900 power of 5 + 624 x 900 power of 4 + 434 x 900 power of 3 + - 632 x 900 power of 2 + 282 x 900 power of 1 + 200 x 900 power of 0 = 1000213298174000 - - Remove leading 1 => Result is 000213298174000 - */ - fn decode_base900to_base10( codewords: &Vec, count: i32) -> /* throws FormatException */Result> { - let mut result: BigInteger = BigInteger::ZERO; - { - let mut i: i32 = 0; - while i < count { - { - result = result.add(&EXP900[count - i - 1]::multiply(&BigInteger::value_of(codewords[i]))); - } - i += 1; - } - } - - let result_string: String = result.to_string(); - if result_string.char_at(0) != '1' { - throw FormatException::get_format_instance(); - } - return Ok(result_string.substring(1)); - } -} - diff --git a/port_src/output/zxing/pdf417/decoder/detection_result.rs b/port_src/output/zxing/pdf417/decoder/detection_result.rs deleted file mode 100644 index 0782d6c..0000000 --- a/port_src/output/zxing/pdf417/decoder/detection_result.rs +++ /dev/null @@ -1,367 +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::pdf417::decoder; - -/** - * @author Guenther Grau - */ - - const ADJUST_ROW_NUMBER_SKIP: i32 = 2; -struct DetectionResult { - - let barcode_metadata: BarcodeMetadata; - - let detection_result_columns: Vec; - - let bounding_box: BoundingBox; - - let barcode_column_count: i32; -} - -impl DetectionResult { - - fn new( barcode_metadata: &BarcodeMetadata, bounding_box: &BoundingBox) -> DetectionResult { - let .barcodeMetadata = barcode_metadata; - let .barcodeColumnCount = barcode_metadata.get_column_count(); - let .boundingBox = bounding_box; - detection_result_columns = : [Option; barcode_column_count + 2] = [None; barcode_column_count + 2]; - } - - fn get_detection_result_columns(&self) -> Vec { - self.adjust_indicator_column_row_numbers(self.detection_result_columns[0]); - self.adjust_indicator_column_row_numbers(self.detection_result_columns[self.barcode_column_count + 1]); - let unadjusted_codeword_count: i32 = PDF417Common.MAX_CODEWORDS_IN_BARCODE; - let previous_unadjusted_count: i32; - loop { { - previous_unadjusted_count = unadjusted_codeword_count; - unadjusted_codeword_count = self.adjust_row_numbers(); - }if !(unadjusted_codeword_count > 0 && unadjusted_codeword_count < previous_unadjusted_count) break;} - return self.detection_result_columns; - } - - fn adjust_indicator_column_row_numbers(&self, detection_result_column: &DetectionResultColumn) { - if detection_result_column != null { - (detection_result_column as DetectionResultRowIndicatorColumn).adjust_complete_indicator_column_row_numbers(self.barcode_metadata); - } - } - - // TODO ensure that no detected codewords with unknown row number are left - // we should be able to estimate the row height and use it as a hint for the row number - // we should also fill the rows top to bottom and bottom to top - /** - * @return number of codewords which don't have a valid row number. Note that the count is not accurate as codewords - * will be counted several times. It just serves as an indicator to see when we can stop adjusting row numbers - */ - fn adjust_row_numbers(&self) -> i32 { - let unadjusted_count: i32 = self.adjust_row_numbers_by_row(); - if unadjusted_count == 0 { - return 0; - } - { - let barcode_column: i32 = 1; - while barcode_column < self.barcode_column_count + 1 { - { - let codewords: Vec = self.detection_result_columns[barcode_column].get_codewords(); - { - let codewords_row: i32 = 0; - while codewords_row < codewords.len() { - { - if codewords[codewords_row] == null { - continue; - } - if !codewords[codewords_row].has_valid_row_number() { - self.adjust_row_numbers(barcode_column, codewords_row, codewords); - } - } - codewords_row += 1; - } - } - - } - barcode_column += 1; - } - } - - return unadjusted_count; - } - - fn adjust_row_numbers_by_row(&self) -> i32 { - self.adjust_row_numbers_from_both_r_i(); - // TODO we should only do full row adjustments if row numbers of left and right row indicator column match. - // Maybe it's even better to calculated the height (in codeword rows) and divide it by the number of barcode - // rows. This, together with the LRI and RRI row numbers should allow us to get a good estimate where a row - // number starts and ends. - let unadjusted_count: i32 = self.adjust_row_numbers_from_l_r_i(); - return unadjusted_count + self.adjust_row_numbers_from_r_r_i(); - } - - fn adjust_row_numbers_from_both_r_i(&self) { - if self.detection_result_columns[0] == null || self.detection_result_columns[self.barcode_column_count + 1] == null { - return; - } - const LRIcodewords: Vec = self.detection_result_columns[0].get_codewords(); - const RRIcodewords: Vec = self.detection_result_columns[self.barcode_column_count + 1].get_codewords(); - { - let codewords_row: i32 = 0; - while codewords_row < LRIcodewords.len() { - { - if LRIcodewords[codewords_row] != null && RRIcodewords[codewords_row] != null && LRIcodewords[codewords_row]::get_row_number() == RRIcodewords[codewords_row]::get_row_number() { - { - let barcode_column: i32 = 1; - while barcode_column <= self.barcode_column_count { - { - let codeword: Codeword = self.detection_result_columns[barcode_column].get_codewords()[codewords_row]; - if codeword == null { - continue; - } - codeword.set_row_number(&LRIcodewords[codewords_row]::get_row_number()); - if !codeword.has_valid_row_number() { - self.detection_result_columns[barcode_column].get_codewords()[codewords_row] = null; - } - } - barcode_column += 1; - } - } - - } - } - codewords_row += 1; - } - } - - } - - fn adjust_row_numbers_from_r_r_i(&self) -> i32 { - if self.detection_result_columns[self.barcode_column_count + 1] == null { - return 0; - } - let unadjusted_count: i32 = 0; - let codewords: Vec = self.detection_result_columns[self.barcode_column_count + 1].get_codewords(); - { - let codewords_row: i32 = 0; - while codewords_row < codewords.len() { - { - if codewords[codewords_row] == null { - continue; - } - let row_indicator_row_number: i32 = codewords[codewords_row].get_row_number(); - let invalid_row_counts: i32 = 0; - { - let barcode_column: i32 = self.barcode_column_count + 1; - while barcode_column > 0 && invalid_row_counts < ADJUST_ROW_NUMBER_SKIP { - { - let codeword: Codeword = self.detection_result_columns[barcode_column].get_codewords()[codewords_row]; - if codeword != null { - invalid_row_counts = ::adjust_row_number_if_valid(row_indicator_row_number, invalid_row_counts, codeword); - if !codeword.has_valid_row_number() { - unadjusted_count += 1; - } - } - } - barcode_column -= 1; - } - } - - } - codewords_row += 1; - } - } - - return unadjusted_count; - } - - fn adjust_row_numbers_from_l_r_i(&self) -> i32 { - if self.detection_result_columns[0] == null { - return 0; - } - let unadjusted_count: i32 = 0; - let codewords: Vec = self.detection_result_columns[0].get_codewords(); - { - let codewords_row: i32 = 0; - while codewords_row < codewords.len() { - { - if codewords[codewords_row] == null { - continue; - } - let row_indicator_row_number: i32 = codewords[codewords_row].get_row_number(); - let invalid_row_counts: i32 = 0; - { - let barcode_column: i32 = 1; - while barcode_column < self.barcode_column_count + 1 && invalid_row_counts < ADJUST_ROW_NUMBER_SKIP { - { - let codeword: Codeword = self.detection_result_columns[barcode_column].get_codewords()[codewords_row]; - if codeword != null { - invalid_row_counts = ::adjust_row_number_if_valid(row_indicator_row_number, invalid_row_counts, codeword); - if !codeword.has_valid_row_number() { - unadjusted_count += 1; - } - } - } - barcode_column += 1; - } - } - - } - codewords_row += 1; - } - } - - return unadjusted_count; - } - - fn adjust_row_number_if_valid( row_indicator_row_number: i32, invalid_row_counts: i32, codeword: &Codeword) -> i32 { - if codeword == null { - return invalid_row_counts; - } - if !codeword.has_valid_row_number() { - if codeword.is_valid_row_number(row_indicator_row_number) { - codeword.set_row_number(row_indicator_row_number); - invalid_row_counts = 0; - } else { - invalid_row_counts += 1; - } - } - return invalid_row_counts; - } - - fn adjust_row_numbers(&self, barcode_column: i32, codewords_row: i32, codewords: &Vec) { - let codeword: Codeword = codewords[codewords_row]; - let previous_column_codewords: Vec = self.detection_result_columns[barcode_column - 1].get_codewords(); - let next_column_codewords: Vec = previous_column_codewords; - if self.detection_result_columns[barcode_column + 1] != null { - next_column_codewords = self.detection_result_columns[barcode_column + 1].get_codewords(); - } - let other_codewords: [Option; 14] = [None; 14]; - other_codewords[2] = previous_column_codewords[codewords_row]; - other_codewords[3] = next_column_codewords[codewords_row]; - if codewords_row > 0 { - other_codewords[0] = codewords[codewords_row - 1]; - other_codewords[4] = previous_column_codewords[codewords_row - 1]; - other_codewords[5] = next_column_codewords[codewords_row - 1]; - } - if codewords_row > 1 { - other_codewords[8] = codewords[codewords_row - 2]; - other_codewords[10] = previous_column_codewords[codewords_row - 2]; - other_codewords[11] = next_column_codewords[codewords_row - 2]; - } - if codewords_row < codewords.len() - 1 { - other_codewords[1] = codewords[codewords_row + 1]; - other_codewords[6] = previous_column_codewords[codewords_row + 1]; - other_codewords[7] = next_column_codewords[codewords_row + 1]; - } - if codewords_row < codewords.len() - 2 { - other_codewords[9] = codewords[codewords_row + 2]; - other_codewords[12] = previous_column_codewords[codewords_row + 2]; - other_codewords[13] = next_column_codewords[codewords_row + 2]; - } - for let other_codeword: Codeword in other_codewords { - if ::adjust_row_number(codeword, other_codeword) { - return; - } - } - } - - /** - * @return true, if row number was adjusted, false otherwise - */ - fn adjust_row_number( codeword: &Codeword, other_codeword: &Codeword) -> bool { - if other_codeword == null { - return false; - } - if other_codeword.has_valid_row_number() && other_codeword.get_bucket() == codeword.get_bucket() { - codeword.set_row_number(&other_codeword.get_row_number()); - return true; - } - return false; - } - - fn get_barcode_column_count(&self) -> i32 { - return self.barcode_column_count; - } - - fn get_barcode_row_count(&self) -> i32 { - return self.barcode_metadata.get_row_count(); - } - - fn get_barcode_e_c_level(&self) -> i32 { - return self.barcode_metadata.get_error_correction_level(); - } - - fn set_bounding_box(&self, bounding_box: &BoundingBox) { - self.boundingBox = bounding_box; - } - - fn get_bounding_box(&self) -> BoundingBox { - return self.bounding_box; - } - - fn set_detection_result_column(&self, barcode_column: i32, detection_result_column: &DetectionResultColumn) { - self.detection_result_columns[barcode_column] = detection_result_column; - } - - fn get_detection_result_column(&self, barcode_column: i32) -> DetectionResultColumn { - return self.detection_result_columns[barcode_column]; - } - - pub fn to_string(&self) -> String { - let row_indicator_column: DetectionResultColumn = self.detection_result_columns[0]; - if row_indicator_column == null { - row_indicator_column = self.detection_result_columns[self.barcode_column_count + 1]; - } - let tryResult1 = 0; - 'try1: loop { - ( let formatter: Formatter = Formatter::new()) { - { - let codewords_row: i32 = 0; - while codewords_row < row_indicator_column.get_codewords().len() { - { - formatter.format("CW %3d:", codewords_row); - { - let barcode_column: i32 = 0; - while barcode_column < self.barcode_column_count + 2 { - { - if self.detection_result_columns[barcode_column] == null { - formatter.format(" | "); - continue; - } - let codeword: Codeword = self.detection_result_columns[barcode_column].get_codewords()[codewords_row]; - if codeword == null { - formatter.format(" | "); - continue; - } - formatter.format(" %3d|%3d", &codeword.get_row_number(), &codeword.get_value()); - } - barcode_column += 1; - } - } - - formatter.format("%n"); - } - codewords_row += 1; - } - } - - return formatter.to_string(); - } - break 'try1 - } - match tryResult1 { - 0 => break - } - - } -} - diff --git a/port_src/output/zxing/pdf417/decoder/detection_result_column.rs b/port_src/output/zxing/pdf417/decoder/detection_result_column.rs deleted file mode 100644 index 6a46fe9..0000000 --- a/port_src/output/zxing/pdf417/decoder/detection_result_column.rs +++ /dev/null @@ -1,110 +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::pdf417::decoder; - -/** - * @author Guenther Grau - */ - - const MAX_NEARBY_DISTANCE: i32 = 5; -struct DetectionResultColumn { - - let bounding_box: BoundingBox; - - let mut codewords: Vec; -} - -impl DetectionResultColumn { - - fn new( bounding_box: &BoundingBox) -> DetectionResultColumn { - let .boundingBox = BoundingBox::new(bounding_box); - codewords = : [Option; bounding_box.get_max_y() - bounding_box.get_min_y() + 1] = [None; bounding_box.get_max_y() - bounding_box.get_min_y() + 1]; - } - - fn get_codeword_nearby(&self, image_row: i32) -> Codeword { - let mut codeword: Codeword = self.get_codeword(image_row); - if codeword != null { - return codeword; - } - { - let mut i: i32 = 1; - while i < MAX_NEARBY_DISTANCE { - { - let near_image_row: i32 = self.image_row_to_codeword_index(image_row) - i; - if near_image_row >= 0 { - codeword = self.codewords[near_image_row]; - if codeword != null { - return codeword; - } - } - near_image_row = self.image_row_to_codeword_index(image_row) + i; - if near_image_row < self.codewords.len() { - codeword = self.codewords[near_image_row]; - if codeword != null { - return codeword; - } - } - } - i += 1; - } - } - - return null; - } - - fn image_row_to_codeword_index(&self, image_row: i32) -> i32 { - return image_row - self.bounding_box.get_min_y(); - } - - fn set_codeword(&self, image_row: i32, codeword: &Codeword) { - self.codewords[self.image_row_to_codeword_index(image_row)] = codeword; - } - - fn get_codeword(&self, image_row: i32) -> Codeword { - return self.codewords[self.image_row_to_codeword_index(image_row)]; - } - - fn get_bounding_box(&self) -> BoundingBox { - return self.bounding_box; - } - - fn get_codewords(&self) -> Vec { - return self.codewords; - } - - pub fn to_string(&self) -> String { - let tryResult1 = 0; - 'try1: loop { - ( let formatter: Formatter = Formatter::new()) { - let mut row: i32 = 0; - for let codeword: Codeword in self.codewords { - if codeword == null { - formatter.format("%3d: | %n", row += 1 !!!check!!! post increment); - continue; - } - formatter.format("%3d: %3d|%3d%n", row += 1 !!!check!!! post increment, &codeword.get_row_number(), &codeword.get_value()); - } - return formatter.to_string(); - } - break 'try1 - } - match tryResult1 { - 0 => break - } - - } -} - diff --git a/port_src/output/zxing/pdf417/decoder/detection_result_row_indicator_column.rs b/port_src/output/zxing/pdf417/decoder/detection_result_row_indicator_column.rs deleted file mode 100644 index 0f6a59f..0000000 --- a/port_src/output/zxing/pdf417/decoder/detection_result_row_indicator_column.rs +++ /dev/null @@ -1,279 +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::pdf417::decoder; - -/** - * @author Guenther Grau - */ -struct DetectionResultRowIndicatorColumn { - super: DetectionResultColumn; - - let is_left: bool; -} - -impl DetectionResultRowIndicatorColumn { - - fn new( bounding_box: &BoundingBox, is_left: bool) -> DetectionResultRowIndicatorColumn { - super(bounding_box); - let .isLeft = is_left; - } - - fn set_row_numbers(&self) { - for let codeword: Codeword in get_codewords() { - if codeword != null { - codeword.set_row_number_as_row_indicator_column(); - } - } - } - - // TODO implement properly - // TODO maybe we should add missing codewords to store the correct row number to make - // finding row numbers for other columns easier - // use row height count to make detection of invalid row numbers more reliable - fn adjust_complete_indicator_column_row_numbers(&self, barcode_metadata: &BarcodeMetadata) { - let mut codewords: Vec = get_codewords(); - self.set_row_numbers(); - self.remove_incorrect_codewords(codewords, barcode_metadata); - let bounding_box: BoundingBox = get_bounding_box(); - let top: ResultPoint = if self.is_left { bounding_box.get_top_left() } else { bounding_box.get_top_right() }; - let bottom: ResultPoint = if self.is_left { bounding_box.get_bottom_left() } else { bounding_box.get_bottom_right() }; - let first_row: i32 = image_row_to_codeword_index(top.get_y() as i32); - let last_row: i32 = image_row_to_codeword_index(bottom.get_y() as i32); - // We need to be careful using the average row height. Barcode could be skewed so that we have smaller and - // taller rows - //float averageRowHeight = (lastRow - firstRow) / (float) barcodeMetadata.getRowCount(); - let barcode_row: i32 = -1; - let max_row_height: i32 = 1; - let current_row_height: i32 = 0; - { - let codewords_row: i32 = first_row; - while codewords_row < last_row { - { - if codewords[codewords_row] == null { - continue; - } - let codeword: Codeword = codewords[codewords_row]; - let row_difference: i32 = codeword.get_row_number() - barcode_row; - if row_difference == 0 { - current_row_height += 1; - } else if row_difference == 1 { - max_row_height = Math::max(max_row_height, current_row_height); - current_row_height = 1; - barcode_row = codeword.get_row_number(); - } else if row_difference < 0 || codeword.get_row_number() >= barcode_metadata.get_row_count() || row_difference > codewords_row { - codewords[codewords_row] = null; - } else { - let checked_rows: i32; - if max_row_height > 2 { - checked_rows = (max_row_height - 2) * row_difference; - } else { - checked_rows = row_difference; - } - let close_previous_codeword_found: bool = checked_rows >= codewords_row; - { - let mut i: i32 = 1; - while i <= checked_rows && !close_previous_codeword_found { - { - // there must be (height * rowDifference) number of codewords missing. For now we assume height = 1. - // This should hopefully get rid of most problems already. - close_previous_codeword_found = codewords[codewords_row - i] != null; - } - i += 1; - } - } - - if close_previous_codeword_found { - codewords[codewords_row] = null; - } else { - barcode_row = codeword.get_row_number(); - current_row_height = 1; - } - } - } - codewords_row += 1; - } - } - - //return (int) (averageRowHeight + 0.5); - } - - fn get_row_heights(&self) -> Vec { - let barcode_metadata: BarcodeMetadata = self.get_barcode_metadata(); - if barcode_metadata == null { - return null; - } - self.adjust_incomplete_indicator_column_row_numbers(barcode_metadata); - let mut result: [i32; barcode_metadata.get_row_count()] = [0; barcode_metadata.get_row_count()]; - for let codeword: Codeword in get_codewords() { - if codeword != null { - let row_number: i32 = codeword.get_row_number(); - if row_number >= result.len() { - // We have more rows than the barcode metadata allows for, ignore them. - continue; - } - result[row_number] += 1; - } - // else throw exception? - } - return result; - } - - // TODO maybe we should add missing codewords to store the correct row number to make - // finding row numbers for other columns easier - // use row height count to make detection of invalid row numbers more reliable - fn adjust_incomplete_indicator_column_row_numbers(&self, barcode_metadata: &BarcodeMetadata) { - let bounding_box: BoundingBox = get_bounding_box(); - let top: ResultPoint = if self.is_left { bounding_box.get_top_left() } else { bounding_box.get_top_right() }; - let bottom: ResultPoint = if self.is_left { bounding_box.get_bottom_left() } else { bounding_box.get_bottom_right() }; - let first_row: i32 = image_row_to_codeword_index(top.get_y() as i32); - let last_row: i32 = image_row_to_codeword_index(bottom.get_y() as i32); - //float averageRowHeight = (lastRow - firstRow) / (float) barcodeMetadata.getRowCount(); - let mut codewords: Vec = get_codewords(); - let barcode_row: i32 = -1; - let max_row_height: i32 = 1; - let current_row_height: i32 = 0; - { - let codewords_row: i32 = first_row; - while codewords_row < last_row { - { - if codewords[codewords_row] == null { - continue; - } - let codeword: Codeword = codewords[codewords_row]; - codeword.set_row_number_as_row_indicator_column(); - let row_difference: i32 = codeword.get_row_number() - barcode_row; - if row_difference == 0 { - current_row_height += 1; - } else if row_difference == 1 { - max_row_height = Math::max(max_row_height, current_row_height); - current_row_height = 1; - barcode_row = codeword.get_row_number(); - } else if codeword.get_row_number() >= barcode_metadata.get_row_count() { - codewords[codewords_row] = null; - } else { - barcode_row = codeword.get_row_number(); - current_row_height = 1; - } - } - codewords_row += 1; - } - } - - //return (int) (averageRowHeight + 0.5); - } - - fn get_barcode_metadata(&self) -> BarcodeMetadata { - let codewords: Vec = get_codewords(); - let barcode_column_count: BarcodeValue = BarcodeValue::new(); - let barcode_row_count_upper_part: BarcodeValue = BarcodeValue::new(); - let barcode_row_count_lower_part: BarcodeValue = BarcodeValue::new(); - let barcode_e_c_level: BarcodeValue = BarcodeValue::new(); - for let codeword: Codeword in codewords { - if codeword == null { - continue; - } - codeword.set_row_number_as_row_indicator_column(); - let row_indicator_value: i32 = codeword.get_value() % 30; - let codeword_row_number: i32 = codeword.get_row_number(); - if !self.is_left { - codeword_row_number += 2; - } - match codeword_row_number % 3 { - 0 => - { - barcode_row_count_upper_part.set_value(row_indicator_value * 3 + 1); - break; - } - 1 => - { - barcode_e_c_level.set_value(row_indicator_value / 3); - barcode_row_count_lower_part.set_value(row_indicator_value % 3); - break; - } - 2 => - { - barcode_column_count.set_value(row_indicator_value + 1); - break; - } - } - } - // Maybe we should check if we have ambiguous values? - if (barcode_column_count.get_value().len() == 0) || (barcode_row_count_upper_part.get_value().len() == 0) || (barcode_row_count_lower_part.get_value().len() == 0) || (barcode_e_c_level.get_value().len() == 0) || barcode_column_count.get_value()[0] < 1 || barcode_row_count_upper_part.get_value()[0] + barcode_row_count_lower_part.get_value()[0] < PDF417Common.MIN_ROWS_IN_BARCODE || barcode_row_count_upper_part.get_value()[0] + barcode_row_count_lower_part.get_value()[0] > PDF417Common.MAX_ROWS_IN_BARCODE { - return null; - } - let barcode_metadata: BarcodeMetadata = BarcodeMetadata::new(barcode_column_count.get_value()[0], barcode_row_count_upper_part.get_value()[0], barcode_row_count_lower_part.get_value()[0], barcode_e_c_level.get_value()[0]); - self.remove_incorrect_codewords(codewords, barcode_metadata); - return barcode_metadata; - } - - fn remove_incorrect_codewords(&self, codewords: &Vec, barcode_metadata: &BarcodeMetadata) { - // TODO Maybe we should keep the incorrect codewords for the start and end positions? - { - let codeword_row: i32 = 0; - while codeword_row < codewords.len() { - { - let codeword: Codeword = codewords[codeword_row]; - if codewords[codeword_row] == null { - continue; - } - let row_indicator_value: i32 = codeword.get_value() % 30; - let codeword_row_number: i32 = codeword.get_row_number(); - if codeword_row_number > barcode_metadata.get_row_count() { - codewords[codeword_row] = null; - continue; - } - if !self.is_left { - codeword_row_number += 2; - } - match codeword_row_number % 3 { - 0 => - { - if row_indicator_value * 3 + 1 != barcode_metadata.get_row_count_upper_part() { - codewords[codeword_row] = null; - } - break; - } - 1 => - { - if row_indicator_value / 3 != barcode_metadata.get_error_correction_level() || row_indicator_value % 3 != barcode_metadata.get_row_count_lower_part() { - codewords[codeword_row] = null; - } - break; - } - 2 => - { - if row_indicator_value + 1 != barcode_metadata.get_column_count() { - codewords[codeword_row] = null; - } - break; - } - } - } - codeword_row += 1; - } - } - - } - - fn is_left(&self) -> bool { - return self.is_left; - } - - pub fn to_string(&self) -> String { - return format!("IsLeft: {}\n{}", self.is_left, super.to_string()); - } -} - diff --git a/port_src/output/zxing/pdf417/decoder/ec/error_correction.rs b/port_src/output/zxing/pdf417/decoder/ec/error_correction.rs deleted file mode 100644 index a3c132d..0000000 --- a/port_src/output/zxing/pdf417/decoder/ec/error_correction.rs +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// package com::google::zxing::pdf417::decoder::ec; - -/** - *

PDF417 error correction implementation.

- * - *

This example - * is quite useful in understanding the algorithm.

- * - * @author Sean Owen - * @see com.google.zxing.common.reedsolomon.ReedSolomonDecoder - */ -pub struct ErrorCorrection { - - let mut field: ModulusGF; -} - -impl ErrorCorrection { - - pub fn new() -> ErrorCorrection { - let .field = ModulusGF::PDF417_GF; - } - - /** - * @param received received codewords - * @param numECCodewords number of those codewords used for EC - * @param erasures location of erasures - * @return number of errors - * @throws ChecksumException if errors cannot be corrected, maybe because of too many errors - */ - pub fn decode(&self, received: &Vec, num_e_c_codewords: i32, erasures: &Vec) -> /* throws ChecksumException */Result> { - let poly: ModulusPoly = ModulusPoly::new(self.field, &received); - const S: [i32; num_e_c_codewords] = [0; num_e_c_codewords]; - let mut error: bool = false; - { - let mut i: i32 = num_e_c_codewords; - while i > 0 { - { - let eval: i32 = poly.evaluate_at(&self.field.exp(i)); - S[num_e_c_codewords - i] = eval; - if eval != 0 { - error = true; - } - } - i -= 1; - } - } - - if !error { - return Ok(0); - } - let known_errors: ModulusPoly = self.field.get_one(); - if erasures != null { - for let erasure: i32 in erasures { - let b: i32 = self.field.exp(received.len() - 1 - erasure); - // Add (1 - bx) term: - let term: ModulusPoly = ModulusPoly::new(self.field, : vec![i32; 2] = vec![self.field.subtract(0, b), 1, ] - ); - known_errors = known_errors.multiply(term); - } - } - let syndrome: ModulusPoly = ModulusPoly::new(self.field, &S); - //syndrome = syndrome.multiply(knownErrors); - let sigma_omega: Vec = self.run_euclidean_algorithm(&self.field.build_monomial(num_e_c_codewords, 1), syndrome, num_e_c_codewords); - let sigma: ModulusPoly = sigma_omega[0]; - let omega: ModulusPoly = sigma_omega[1]; - //sigma = sigma.multiply(knownErrors); - let error_locations: Vec = self.find_error_locations(sigma); - let error_magnitudes: Vec = self.find_error_magnitudes(omega, sigma, &error_locations); - { - let mut i: i32 = 0; - while i < error_locations.len() { - { - let mut position: i32 = received.len() - 1 - self.field.log(error_locations[i]); - if position < 0 { - throw ChecksumException::get_checksum_instance(); - } - received[position] = self.field.subtract(received[position], error_magnitudes[i]); - } - i += 1; - } - } - - return Ok(error_locations.len()); - } - - fn run_euclidean_algorithm(&self, a: &ModulusPoly, b: &ModulusPoly, R: i32) -> /* throws ChecksumException */Result, Rc> { - // Assume a's degree is >= b's - if a.get_degree() < b.get_degree() { - let temp: ModulusPoly = a; - a = b; - b = temp; - } - let r_last: ModulusPoly = a; - let mut r: ModulusPoly = b; - let t_last: ModulusPoly = self.field.get_zero(); - let mut t: ModulusPoly = self.field.get_one(); - // Run Euclidean algorithm until r's degree is less than R/2 - while r.get_degree() >= R / 2 { - let r_last_last: ModulusPoly = r_last; - let t_last_last: ModulusPoly = t_last; - r_last = r; - t_last = t; - // Divide rLastLast by rLast, with quotient in q and remainder in r - if r_last.is_zero() { - // Oops, Euclidean algorithm already terminated? - throw ChecksumException::get_checksum_instance(); - } - r = r_last_last; - let mut q: ModulusPoly = self.field.get_zero(); - let denominator_leading_term: i32 = r_last.get_coefficient(&r_last.get_degree()); - let dlt_inverse: i32 = self.field.inverse(denominator_leading_term); - while r.get_degree() >= r_last.get_degree() && !r.is_zero() { - let degree_diff: i32 = r.get_degree() - r_last.get_degree(); - let scale: i32 = self.field.multiply(&r.get_coefficient(&r.get_degree()), dlt_inverse); - q = q.add(&self.field.build_monomial(degree_diff, scale)); - r = r.subtract(&r_last.multiply_by_monomial(degree_diff, scale)); - } - t = q.multiply(t_last).subtract(t_last_last).negative(); - } - let sigma_tilde_at_zero: i32 = t.get_coefficient(0); - if sigma_tilde_at_zero == 0 { - throw ChecksumException::get_checksum_instance(); - } - let inverse: i32 = self.field.inverse(sigma_tilde_at_zero); - let sigma: ModulusPoly = t.multiply(inverse); - let omega: ModulusPoly = r.multiply(inverse); - return Ok( : vec![ModulusPoly; 2] = vec![sigma, omega, ] - ); - } - - fn find_error_locations(&self, error_locator: &ModulusPoly) -> /* throws ChecksumException */Result, Rc> { - // This is a direct application of Chien's search - let num_errors: i32 = error_locator.get_degree(); - let mut result: [i32; num_errors] = [0; num_errors]; - let mut e: i32 = 0; - { - let mut i: i32 = 1; - while i < self.field.get_size() && e < num_errors { - { - if error_locator.evaluate_at(i) == 0 { - result[e] = self.field.inverse(i); - e += 1; - } - } - i += 1; - } - } - - if e != num_errors { - throw ChecksumException::get_checksum_instance(); - } - return Ok(result); - } - - fn find_error_magnitudes(&self, error_evaluator: &ModulusPoly, error_locator: &ModulusPoly, error_locations: &Vec) -> Vec { - let error_locator_degree: i32 = error_locator.get_degree(); - if error_locator_degree < 1 { - return : [i32; 0] = [0; 0]; - } - let formal_derivative_coefficients: [i32; error_locator_degree] = [0; error_locator_degree]; - { - let mut i: i32 = 1; - while i <= error_locator_degree { - { - formal_derivative_coefficients[error_locator_degree - i] = self.field.multiply(i, &error_locator.get_coefficient(i)); - } - i += 1; - } - } - - let formal_derivative: ModulusPoly = ModulusPoly::new(self.field, &formal_derivative_coefficients); - // This is directly applying Forney's Formula - let s: i32 = error_locations.len(); - let mut result: [i32; s] = [0; s]; - { - let mut i: i32 = 0; - while i < s { - { - let xi_inverse: i32 = self.field.inverse(error_locations[i]); - let numerator: i32 = self.field.subtract(0, &error_evaluator.evaluate_at(xi_inverse)); - let denominator: i32 = self.field.inverse(&formal_derivative.evaluate_at(xi_inverse)); - result[i] = self.field.multiply(numerator, denominator); - } - i += 1; - } - } - - return result; - } -} - diff --git a/port_src/output/zxing/pdf417/decoder/ec/modulus_g_f.rs b/port_src/output/zxing/pdf417/decoder/ec/modulus_g_f.rs deleted file mode 100644 index 75f6055..0000000 --- a/port_src/output/zxing/pdf417/decoder/ec/modulus_g_f.rs +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// package com::google::zxing::pdf417::decoder::ec; - -/** - *

A field based on powers of a generator integer, modulo some modulus.

- * - * @author Sean Owen - * @see com.google.zxing.common.reedsolomon.GenericGF - */ - - const PDF417_GF: ModulusGF = ModulusGF::new(PDF417Common.NUMBER_OF_CODEWORDS, 3); -pub struct ModulusGF { - - let exp_table: Vec; - - let log_table: Vec; - - let mut zero: ModulusPoly; - - let mut one: ModulusPoly; - - let modulus: i32; -} - -impl ModulusGF { - - fn new( modulus: i32, generator: i32) -> ModulusGF { - let .modulus = modulus; - exp_table = : [i32; modulus] = [0; modulus]; - log_table = : [i32; modulus] = [0; modulus]; - let mut x: i32 = 1; - { - let mut i: i32 = 0; - while i < modulus { - { - exp_table[i] = x; - x = (x * generator) % modulus; - } - i += 1; - } - } - - { - let mut i: i32 = 0; - while i < modulus - 1 { - { - log_table[exp_table[i]] = i; - } - i += 1; - } - } - - // logTable[0] == 0 but this should never be used - zero = ModulusPoly::new(let , : vec![i32; 1] = vec![0, ] - ); - one = ModulusPoly::new(let , : vec![i32; 1] = vec![1, ] - ); - } - - fn get_zero(&self) -> ModulusPoly { - return self.zero; - } - - fn get_one(&self) -> ModulusPoly { - return self.one; - } - - fn build_monomial(&self, degree: i32, coefficient: i32) -> ModulusPoly { - if degree < 0 { - throw IllegalArgumentException::new(); - } - if coefficient == 0 { - return self.zero; - } - let mut coefficients: [i32; degree + 1] = [0; degree + 1]; - coefficients[0] = coefficient; - return ModulusPoly::new(self, &coefficients); - } - - fn add(&self, a: i32, b: i32) -> i32 { - return (a + b) % self.modulus; - } - - fn subtract(&self, a: i32, b: i32) -> i32 { - return (self.modulus + a - b) % self.modulus; - } - - fn exp(&self, a: i32) -> i32 { - return self.exp_table[a]; - } - - fn log(&self, a: i32) -> i32 { - if a == 0 { - throw IllegalArgumentException::new(); - } - return self.log_table[a]; - } - - fn inverse(&self, a: i32) -> i32 { - if a == 0 { - throw ArithmeticException::new(); - } - return self.exp_table[self.modulus - self.log_table[a] - 1]; - } - - fn multiply(&self, a: i32, b: i32) -> i32 { - if a == 0 || b == 0 { - return 0; - } - return self.exp_table[(self.log_table[a] + self.log_table[b]) % (self.modulus - 1)]; - } - - fn get_size(&self) -> i32 { - return self.modulus; - } -} - diff --git a/port_src/output/zxing/pdf417/decoder/ec/modulus_poly.rs b/port_src/output/zxing/pdf417/decoder/ec/modulus_poly.rs deleted file mode 100644 index 38e12f7..0000000 --- a/port_src/output/zxing/pdf417/decoder/ec/modulus_poly.rs +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// package com::google::zxing::pdf417::decoder::ec; - -/** - * @author Sean Owen - */ -struct ModulusPoly { - - let field: ModulusGF; - - let coefficients: Vec; -} - -impl ModulusPoly { - - fn new( field: &ModulusGF, coefficients: &Vec) -> ModulusPoly { - if coefficients.len() == 0 { - throw IllegalArgumentException::new(); - } - let .field = field; - let coefficients_length: i32 = coefficients.len(); - if coefficients_length > 1 && coefficients[0] == 0 { - // Leading term must be non-zero for anything except the constant polynomial "0" - let first_non_zero: i32 = 1; - while first_non_zero < coefficients_length && coefficients[first_non_zero] == 0 { - first_non_zero += 1; - } - if first_non_zero == coefficients_length { - let .coefficients = : vec![i32; 1] = vec![0, ] - ; - } else { - let .coefficients = : [i32; coefficients_length - first_non_zero] = [0; coefficients_length - first_non_zero]; - System::arraycopy(&coefficients, first_non_zero, let .coefficients, 0, let .coefficients.len()); - } - } else { - let .coefficients = coefficients; - } - } - - fn get_coefficients(&self) -> Vec { - return self.coefficients; - } - - /** - * @return degree of this polynomial - */ - fn get_degree(&self) -> i32 { - return self.coefficients.len() - 1; - } - - /** - * @return true iff this polynomial is the monomial "0" - */ - fn is_zero(&self) -> bool { - return self.coefficients[0] == 0; - } - - /** - * @return coefficient of x^degree term in this polynomial - */ - fn get_coefficient(&self, degree: i32) -> i32 { - return self.coefficients[self.coefficients.len() - 1 - degree]; - } - - /** - * @return evaluation of this polynomial at a given point - */ - fn evaluate_at(&self, a: i32) -> i32 { - if a == 0 { - // Just return the x^0 coefficient - return self.get_coefficient(0); - } - if a == 1 { - // Just the sum of the coefficients - let mut result: i32 = 0; - for let coefficient: i32 in self.coefficients { - result = self.field.add(result, coefficient); - } - return result; - } - let mut result: i32 = self.coefficients[0]; - let size: i32 = self.coefficients.len(); - { - let mut i: i32 = 1; - while i < size { - { - result = self.field.add(&self.field.multiply(a, result), self.coefficients[i]); - } - i += 1; - } - } - - return result; - } - - fn add(&self, other: &ModulusPoly) -> ModulusPoly { - if !self.field.equals(other.field) { - throw IllegalArgumentException::new("ModulusPolys do not have same ModulusGF field"); - } - if self.is_zero() { - return other; - } - if other.is_zero() { - return self; - } - let smaller_coefficients: Vec = self.coefficients; - let larger_coefficients: Vec = other.coefficients; - if smaller_coefficients.len() > larger_coefficients.len() { - let temp: Vec = smaller_coefficients; - smaller_coefficients = larger_coefficients; - larger_coefficients = temp; - } - let sum_diff: [i32; larger_coefficients.len()] = [0; larger_coefficients.len()]; - let length_diff: i32 = larger_coefficients.len() - smaller_coefficients.len(); - // Copy high-order terms only found in higher-degree polynomial's coefficients - System::arraycopy(&larger_coefficients, 0, &sum_diff, 0, length_diff); - { - let mut i: i32 = length_diff; - while i < larger_coefficients.len() { - { - sum_diff[i] = self.field.add(smaller_coefficients[i - length_diff], larger_coefficients[i]); - } - i += 1; - } - } - - return ModulusPoly::new(self.field, &sum_diff); - } - - fn subtract(&self, other: &ModulusPoly) -> ModulusPoly { - if !self.field.equals(other.field) { - throw IllegalArgumentException::new("ModulusPolys do not have same ModulusGF field"); - } - if other.is_zero() { - return self; - } - return self.add(&other.negative()); - } - - fn multiply(&self, other: &ModulusPoly) -> ModulusPoly { - if !self.field.equals(other.field) { - throw IllegalArgumentException::new("ModulusPolys do not have same ModulusGF field"); - } - if self.is_zero() || other.is_zero() { - return self.field.get_zero(); - } - let a_coefficients: Vec = self.coefficients; - let a_length: i32 = a_coefficients.len(); - let b_coefficients: Vec = other.coefficients; - let b_length: i32 = b_coefficients.len(); - let mut product: [i32; a_length + b_length - 1] = [0; a_length + b_length - 1]; - { - let mut i: i32 = 0; - while i < a_length { - { - let a_coeff: i32 = a_coefficients[i]; - { - let mut j: i32 = 0; - while j < b_length { - { - product[i + j] = self.field.add(product[i + j], &self.field.multiply(a_coeff, b_coefficients[j])); - } - j += 1; - } - } - - } - i += 1; - } - } - - return ModulusPoly::new(self.field, &product); - } - - fn negative(&self) -> ModulusPoly { - let size: i32 = self.coefficients.len(); - let negative_coefficients: [i32; size] = [0; size]; - { - let mut i: i32 = 0; - while i < size { - { - negative_coefficients[i] = self.field.subtract(0, self.coefficients[i]); - } - i += 1; - } - } - - return ModulusPoly::new(self.field, &negative_coefficients); - } - - fn multiply(&self, scalar: i32) -> ModulusPoly { - if scalar == 0 { - return self.field.get_zero(); - } - if scalar == 1 { - return self; - } - let size: i32 = self.coefficients.len(); - let mut product: [i32; size] = [0; size]; - { - let mut i: i32 = 0; - while i < size { - { - product[i] = self.field.multiply(self.coefficients[i], scalar); - } - i += 1; - } - } - - return ModulusPoly::new(self.field, &product); - } - - fn multiply_by_monomial(&self, degree: i32, coefficient: i32) -> ModulusPoly { - if degree < 0 { - throw IllegalArgumentException::new(); - } - if coefficient == 0 { - return self.field.get_zero(); - } - let size: i32 = self.coefficients.len(); - let mut product: [i32; size + degree] = [0; size + degree]; - { - let mut i: i32 = 0; - while i < size { - { - product[i] = self.field.multiply(self.coefficients[i], coefficient); - } - i += 1; - } - } - - return ModulusPoly::new(self.field, &product); - } - - pub fn to_string(&self) -> String { - let result: StringBuilder = StringBuilder::new(8 * self.get_degree()); - { - let mut degree: i32 = self.get_degree(); - while degree >= 0 { - { - let mut coefficient: i32 = self.get_coefficient(degree); - if coefficient != 0 { - if coefficient < 0 { - result.append(" - "); - coefficient = -coefficient; - } else { - if result.length() > 0 { - result.append(" + "); - } - } - if degree == 0 || coefficient != 1 { - result.append(coefficient); - } - if degree != 0 { - if degree == 1 { - result.append('x'); - } else { - result.append("x^"); - result.append(degree); - } - } - } - } - degree -= 1; - } - } - - return result.to_string(); - } -} - diff --git a/port_src/output/zxing/pdf417/decoder/p_d_f417_codeword_decoder.rs b/port_src/output/zxing/pdf417/decoder/p_d_f417_codeword_decoder.rs deleted file mode 100644 index d19a2ea..0000000 --- a/port_src/output/zxing/pdf417/decoder/p_d_f417_codeword_decoder.rs +++ /dev/null @@ -1,172 +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::pdf417::decoder; - -/** - * @author Guenther Grau - * @author creatale GmbH (christoph.schulz@creatale.de) - */ - - const RATIOS_TABLE: [[f32; PDF417Common.BARS_IN_MODULE]; PDF417Common.SYMBOL_TABLE.len()] = [[0.0; PDF417Common.BARS_IN_MODULE]; PDF417Common.SYMBOL_TABLE.len()]; -struct PDF417CodewordDecoder { -} - -impl PDF417CodewordDecoder { - - static { - // Pre-computes the symbol ratio table. - { - let mut i: i32 = 0; - while i < PDF417Common.SYMBOL_TABLE.len() { - { - let current_symbol: i32 = PDF417Common.SYMBOL_TABLE[i]; - let current_bit: i32 = current_symbol & 0x1; - { - let mut j: i32 = 0; - while j < PDF417Common.BARS_IN_MODULE { - { - let mut size: f32 = 0.0f; - while (current_symbol & 0x1) == current_bit { - size += 1.0f; - current_symbol >>= 1; - } - current_bit = current_symbol & 0x1; - RATIOS_TABLE[i][PDF417Common.BARS_IN_MODULE - j - 1] = size / PDF417Common.MODULES_IN_CODEWORD; - } - j += 1; - } - } - - } - i += 1; - } - } - - } - - fn new() -> PDF417CodewordDecoder { - } - - fn get_decoded_value( module_bit_count: &Vec) -> i32 { - let decoded_value: i32 = ::get_decoded_codeword_value(&::sample_bit_counts(&module_bit_count)); - if decoded_value != -1 { - return decoded_value; - } - return ::get_closest_decoded_value(&module_bit_count); - } - - fn sample_bit_counts( module_bit_count: &Vec) -> Vec { - let bit_count_sum: f32 = MathUtils::sum(&module_bit_count); - let mut result: [i32; PDF417Common.BARS_IN_MODULE] = [0; PDF417Common.BARS_IN_MODULE]; - let bit_count_index: i32 = 0; - let sum_previous_bits: i32 = 0; - { - let mut i: i32 = 0; - while i < PDF417Common.MODULES_IN_CODEWORD { - { - let sample_index: f32 = bit_count_sum / (2.0 * PDF417Common.MODULES_IN_CODEWORD) + (i * bit_count_sum) / PDF417Common.MODULES_IN_CODEWORD; - if sum_previous_bits + module_bit_count[bit_count_index] <= sample_index { - sum_previous_bits += module_bit_count[bit_count_index]; - bit_count_index += 1; - } - result[bit_count_index] += 1; - } - i += 1; - } - } - - return result; - } - - fn get_decoded_codeword_value( module_bit_count: &Vec) -> i32 { - let decoded_value: i32 = ::get_bit_value(&module_bit_count); - return if PDF417Common::get_codeword(decoded_value) == -1 { -1 } else { decoded_value }; - } - - fn get_bit_value( module_bit_count: &Vec) -> i32 { - let mut result: i64 = 0; - { - let mut i: i32 = 0; - while i < module_bit_count.len() { - { - { - let mut bit: i32 = 0; - while bit < module_bit_count[i] { - { - result = (result << 1) | ( if i % 2 == 0 { 1 } else { 0 }); - } - bit += 1; - } - } - - } - i += 1; - } - } - - return result as i32; - } - - fn get_closest_decoded_value( module_bit_count: &Vec) -> i32 { - let bit_count_sum: i32 = MathUtils::sum(&module_bit_count); - let bit_count_ratios: [f32; PDF417Common.BARS_IN_MODULE] = [0.0; PDF417Common.BARS_IN_MODULE]; - if bit_count_sum > 1 { - { - let mut i: i32 = 0; - while i < bit_count_ratios.len() { - { - bit_count_ratios[i] = module_bit_count[i] / bit_count_sum as f32; - } - i += 1; - } - } - - } - let best_match_error: f32 = Float::MAX_VALUE; - let best_match: i32 = -1; - { - let mut j: i32 = 0; - while j < RATIOS_TABLE.len() { - { - let mut error: f32 = 0.0f; - let ratio_table_row: Vec = RATIOS_TABLE[j]; - { - let mut k: i32 = 0; - while k < PDF417Common.BARS_IN_MODULE { - { - let diff: f32 = ratio_table_row[k] - bit_count_ratios[k]; - error += diff * diff; - if error >= best_match_error { - break; - } - } - k += 1; - } - } - - if error < best_match_error { - best_match_error = error; - best_match = PDF417Common.SYMBOL_TABLE[j]; - } - } - j += 1; - } - } - - return best_match; - } -} - diff --git a/port_src/output/zxing/pdf417/decoder/p_d_f417_scanning_decoder.rs b/port_src/output/zxing/pdf417/decoder/p_d_f417_scanning_decoder.rs deleted file mode 100644 index 8debf14..0000000 --- a/port_src/output/zxing/pdf417/decoder/p_d_f417_scanning_decoder.rs +++ /dev/null @@ -1,675 +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::pdf417::decoder; - -/** - * @author Guenther Grau - */ - - const CODEWORD_SKEW_SIZE: i32 = 2; - - const MAX_ERRORS: i32 = 3; - - const MAX_EC_CODEWORDS: i32 = 512; - - let error_correction: ErrorCorrection = ErrorCorrection::new(); -pub struct PDF417ScanningDecoder { -} - -impl PDF417ScanningDecoder { - - fn new() -> PDF417ScanningDecoder { - } - - // TODO don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern - // columns. That way width can be deducted from the pattern column. - // This approach also allows to detect more details about the barcode, e.g. if a bar type (white or black) is wider - // than it should be. This can happen if the scanner used a bad blackpoint. - pub fn decode( image: &BitMatrix, image_top_left: &ResultPoint, image_bottom_left: &ResultPoint, image_top_right: &ResultPoint, image_bottom_right: &ResultPoint, min_codeword_width: i32, max_codeword_width: i32) -> /* throws NotFoundException, FormatException, ChecksumException */Result> { - let bounding_box: BoundingBox = BoundingBox::new(image, image_top_left, image_bottom_left, image_top_right, image_bottom_right); - let left_row_indicator_column: DetectionResultRowIndicatorColumn = null; - let right_row_indicator_column: DetectionResultRowIndicatorColumn = null; - let detection_result: DetectionResult; - { - let first_pass: bool = true; - loop { - { - if image_top_left != null { - left_row_indicator_column = ::get_row_indicator_column(image, bounding_box, image_top_left, true, min_codeword_width, max_codeword_width); - } - if image_top_right != null { - right_row_indicator_column = ::get_row_indicator_column(image, bounding_box, image_top_right, false, min_codeword_width, max_codeword_width); - } - detection_result = ::merge(left_row_indicator_column, right_row_indicator_column); - if detection_result == null { - throw NotFoundException::get_not_found_instance(); - } - let result_box: BoundingBox = detection_result.get_bounding_box(); - if first_pass && result_box != null && (result_box.get_min_y() < bounding_box.get_min_y() || result_box.get_max_y() > bounding_box.get_max_y()) { - bounding_box = result_box; - } else { - break; - } - } - first_pass = false; - } - } - - detection_result.set_bounding_box(bounding_box); - let max_barcode_column: i32 = detection_result.get_barcode_column_count() + 1; - detection_result.set_detection_result_column(0, left_row_indicator_column); - detection_result.set_detection_result_column(max_barcode_column, right_row_indicator_column); - let left_to_right: bool = left_row_indicator_column != null; - { - let barcode_column_count: i32 = 1; - while barcode_column_count <= max_barcode_column { - { - let barcode_column: i32 = if left_to_right { barcode_column_count } else { max_barcode_column - barcode_column_count }; - if detection_result.get_detection_result_column(barcode_column) != null { - // This will be the case for the opposite row indicator column, which doesn't need to be decoded again. - continue; - } - let detection_result_column: DetectionResultColumn; - if barcode_column == 0 || barcode_column == max_barcode_column { - detection_result_column = DetectionResultRowIndicatorColumn::new(bounding_box, barcode_column == 0); - } else { - detection_result_column = DetectionResultColumn::new(bounding_box); - } - detection_result.set_detection_result_column(barcode_column, detection_result_column); - let start_column: i32 = -1; - let previous_start_column: i32 = start_column; - // TODO start at a row for which we know the start position, then detect upwards and downwards from there. - { - let image_row: i32 = bounding_box.get_min_y(); - while image_row <= bounding_box.get_max_y() { - { - start_column = ::get_start_column(detection_result, barcode_column, image_row, left_to_right); - if start_column < 0 || start_column > bounding_box.get_max_x() { - if previous_start_column == -1 { - continue; - } - start_column = previous_start_column; - } - let codeword: Codeword = ::detect_codeword(image, &bounding_box.get_min_x(), &bounding_box.get_max_x(), left_to_right, start_column, image_row, min_codeword_width, max_codeword_width); - if codeword != null { - detection_result_column.set_codeword(image_row, codeword); - previous_start_column = start_column; - min_codeword_width = Math::min(min_codeword_width, &codeword.get_width()); - max_codeword_width = Math::max(max_codeword_width, &codeword.get_width()); - } - } - image_row += 1; - } - } - - } - barcode_column_count += 1; - } - } - - return Ok(::create_decoder_result(detection_result)); - } - - fn merge( left_row_indicator_column: &DetectionResultRowIndicatorColumn, right_row_indicator_column: &DetectionResultRowIndicatorColumn) -> /* throws NotFoundException */Result> { - if left_row_indicator_column == null && right_row_indicator_column == null { - return Ok(null); - } - let barcode_metadata: BarcodeMetadata = ::get_barcode_metadata(left_row_indicator_column, right_row_indicator_column); - if barcode_metadata == null { - return Ok(null); - } - let bounding_box: BoundingBox = BoundingBox::merge(&::adjust_bounding_box(left_row_indicator_column), &::adjust_bounding_box(right_row_indicator_column)); - return Ok(DetectionResult::new(barcode_metadata, bounding_box)); - } - - fn adjust_bounding_box( row_indicator_column: &DetectionResultRowIndicatorColumn) -> /* throws NotFoundException */Result> { - if row_indicator_column == null { - return Ok(null); - } - let row_heights: Vec = row_indicator_column.get_row_heights(); - if row_heights == null { - return Ok(null); - } - let max_row_height: i32 = ::get_max(&row_heights); - let missing_start_rows: i32 = 0; - for let row_height: i32 in row_heights { - missing_start_rows += max_row_height - row_height; - if row_height > 0 { - break; - } - } - let codewords: Vec = row_indicator_column.get_codewords(); - { - let mut row: i32 = 0; - while missing_start_rows > 0 && codewords[row] == null { - { - missing_start_rows -= 1; - } - row += 1; - } - } - - let missing_end_rows: i32 = 0; - { - let mut row: i32 = row_heights.len() - 1; - while row >= 0 { - { - missing_end_rows += max_row_height - row_heights[row]; - if row_heights[row] > 0 { - break; - } - } - row -= 1; - } - } - - { - let mut row: i32 = codewords.len() - 1; - while missing_end_rows > 0 && codewords[row] == null { - { - missing_end_rows -= 1; - } - row -= 1; - } - } - - return Ok(row_indicator_column.get_bounding_box().add_missing_rows(missing_start_rows, missing_end_rows, &row_indicator_column.is_left())); - } - - fn get_max( values: &Vec) -> i32 { - let max_value: i32 = -1; - for let value: i32 in values { - max_value = Math::max(max_value, value); - } - return max_value; - } - - fn get_barcode_metadata( left_row_indicator_column: &DetectionResultRowIndicatorColumn, right_row_indicator_column: &DetectionResultRowIndicatorColumn) -> BarcodeMetadata { - let left_barcode_metadata: BarcodeMetadata; - if left_row_indicator_column == null || (left_barcode_metadata = left_row_indicator_column.get_barcode_metadata()) == null { - return if right_row_indicator_column == null { null } else { right_row_indicator_column.get_barcode_metadata() }; - } - let right_barcode_metadata: BarcodeMetadata; - if right_row_indicator_column == null || (right_barcode_metadata = right_row_indicator_column.get_barcode_metadata()) == null { - return left_barcode_metadata; - } - if left_barcode_metadata.get_column_count() != right_barcode_metadata.get_column_count() && left_barcode_metadata.get_error_correction_level() != right_barcode_metadata.get_error_correction_level() && left_barcode_metadata.get_row_count() != right_barcode_metadata.get_row_count() { - return null; - } - return left_barcode_metadata; - } - - fn get_row_indicator_column( image: &BitMatrix, bounding_box: &BoundingBox, start_point: &ResultPoint, left_to_right: bool, min_codeword_width: i32, max_codeword_width: i32) -> DetectionResultRowIndicatorColumn { - let row_indicator_column: DetectionResultRowIndicatorColumn = DetectionResultRowIndicatorColumn::new(bounding_box, left_to_right); - { - let mut i: i32 = 0; - while i < 2 { - { - let increment: i32 = if i == 0 { 1 } else { -1 }; - let start_column: i32 = start_point.get_x() as i32; - { - let image_row: i32 = start_point.get_y() as i32; - while image_row <= bounding_box.get_max_y() && image_row >= bounding_box.get_min_y() { - { - let codeword: Codeword = ::detect_codeword(image, 0, &image.get_width(), left_to_right, start_column, image_row, min_codeword_width, max_codeword_width); - if codeword != null { - row_indicator_column.set_codeword(image_row, codeword); - if left_to_right { - start_column = codeword.get_start_x(); - } else { - start_column = codeword.get_end_x(); - } - } - } - image_row += increment; - } - } - - } - i += 1; - } - } - - return row_indicator_column; - } - - fn adjust_codeword_count( detection_result: &DetectionResult, barcode_matrix: &Vec>) -> /* throws NotFoundException */Result> { - let barcode_matrix01: BarcodeValue = barcode_matrix[0][1]; - let number_of_codewords: Vec = barcode_matrix01.get_value(); - let calculated_number_of_codewords: i32 = detection_result.get_barcode_column_count() * detection_result.get_barcode_row_count() - ::get_number_of_e_c_code_words(&detection_result.get_barcode_e_c_level()); - if number_of_codewords.len() == 0 { - if calculated_number_of_codewords < 1 || calculated_number_of_codewords > PDF417Common.MAX_CODEWORDS_IN_BARCODE { - throw NotFoundException::get_not_found_instance(); - } - barcode_matrix01.set_value(calculated_number_of_codewords); - } else if number_of_codewords[0] != calculated_number_of_codewords { - if calculated_number_of_codewords >= 1 && calculated_number_of_codewords <= PDF417Common.MAX_CODEWORDS_IN_BARCODE { - // The calculated one is more reliable as it is derived from the row indicator columns - barcode_matrix01.set_value(calculated_number_of_codewords); - } - } - } - - fn create_decoder_result( detection_result: &DetectionResult) -> /* throws FormatException, ChecksumException, NotFoundException */Result> { - let barcode_matrix: Vec> = ::create_barcode_matrix(detection_result); - ::adjust_codeword_count(detection_result, barcode_matrix); - let erasures: Collection = ArrayList<>::new(); - let mut codewords: [i32; detection_result.get_barcode_row_count() * detection_result.get_barcode_column_count()] = [0; detection_result.get_barcode_row_count() * detection_result.get_barcode_column_count()]; - let ambiguous_index_values_list: List> = ArrayList<>::new(); - let ambiguous_indexes_list: Collection = ArrayList<>::new(); - { - let mut row: i32 = 0; - while row < detection_result.get_barcode_row_count() { - { - { - let mut column: i32 = 0; - while column < detection_result.get_barcode_column_count() { - { - let values: Vec = barcode_matrix[row][column + 1].get_value(); - let codeword_index: i32 = row * detection_result.get_barcode_column_count() + column; - if values.len() == 0 { - erasures.add(codeword_index); - } else if values.len() == 1 { - codewords[codeword_index] = values[0]; - } else { - ambiguous_indexes_list.add(codeword_index); - ambiguous_index_values_list.add(&values); - } - } - column += 1; - } - } - - } - row += 1; - } - } - - let ambiguous_index_values: [i32; ambiguous_index_values_list.size()] = [0; ambiguous_index_values_list.size()]; - { - let mut i: i32 = 0; - while i < ambiguous_index_values.len() { - { - ambiguous_index_values[i] = ambiguous_index_values_list.get(i); - } - i += 1; - } - } - - return Ok(::create_decoder_result_from_ambiguous_values(&detection_result.get_barcode_e_c_level(), &codewords, &PDF417Common::to_int_array(&erasures), &PDF417Common::to_int_array(&ambiguous_indexes_list), &ambiguous_index_values)); - } - - /** - * This method deals with the fact, that the decoding process doesn't always yield a single most likely value. The - * current error correction implementation doesn't deal with erasures very well, so it's better to provide a value - * for these ambiguous codewords instead of treating it as an erasure. The problem is that we don't know which of - * the ambiguous values to choose. We try decode using the first value, and if that fails, we use another of the - * ambiguous values and try to decode again. This usually only happens on very hard to read and decode barcodes, - * so decoding the normal barcodes is not affected by this. - * - * @param erasureArray contains the indexes of erasures - * @param ambiguousIndexes array with the indexes that have more than one most likely value - * @param ambiguousIndexValues two dimensional array that contains the ambiguous values. The first dimension must - * be the same length as the ambiguousIndexes array - */ - fn create_decoder_result_from_ambiguous_values( ec_level: i32, codewords: &Vec, erasure_array: &Vec, ambiguous_indexes: &Vec, ambiguous_index_values: &Vec>) -> /* throws FormatException, ChecksumException */Result> { - let ambiguous_index_count: [i32; ambiguous_indexes.len()] = [0; ambiguous_indexes.len()]; - let mut tries: i32 = 100; - while tries -= 1 !!!check!!! post decrement > 0 { - { - let mut i: i32 = 0; - while i < ambiguous_index_count.len() { - { - codewords[ambiguous_indexes[i]] = ambiguous_index_values[i][ambiguous_index_count[i]]; - } - i += 1; - } - } - - let tryResult1 = 0; - 'try1: loop { - { - return Ok(::decode_codewords(&codewords, ec_level, &erasure_array)); - } - break 'try1 - } - match tryResult1 { - catch ( ignored: &ChecksumException) { - } 0 => break - } - - if ambiguous_index_count.len() == 0 { - throw ChecksumException::get_checksum_instance(); - } - { - let mut i: i32 = 0; - while i < ambiguous_index_count.len() { - { - if ambiguous_index_count[i] < ambiguous_index_values[i].len() - 1 { - ambiguous_index_count[i] += 1; - break; - } else { - ambiguous_index_count[i] = 0; - if i == ambiguous_index_count.len() - 1 { - throw ChecksumException::get_checksum_instance(); - } - } - } - i += 1; - } - } - - } - throw ChecksumException::get_checksum_instance(); - } - - fn create_barcode_matrix( detection_result: &DetectionResult) -> Vec> { - let barcode_matrix: [[Option; detection_result.get_barcode_column_count() + 2]; detection_result.get_barcode_row_count()] = [[None; detection_result.get_barcode_column_count() + 2]; detection_result.get_barcode_row_count()]; - { - let mut row: i32 = 0; - while row < barcode_matrix.len() { - { - { - let mut column: i32 = 0; - while column < barcode_matrix[row].len() { - { - barcode_matrix[row][column] = BarcodeValue::new(); - } - column += 1; - } - } - - } - row += 1; - } - } - - let mut column: i32 = 0; - for let detection_result_column: DetectionResultColumn in detection_result.get_detection_result_columns() { - if detection_result_column != null { - for let codeword: Codeword in detection_result_column.get_codewords() { - if codeword != null { - let row_number: i32 = codeword.get_row_number(); - if row_number >= 0 { - if row_number >= barcode_matrix.len() { - // We have more rows than the barcode metadata allows for, ignore them. - continue; - } - barcode_matrix[row_number][column].set_value(&codeword.get_value()); - } - } - } - } - column += 1; - } - return barcode_matrix; - } - - fn is_valid_barcode_column( detection_result: &DetectionResult, barcode_column: i32) -> bool { - return barcode_column >= 0 && barcode_column <= detection_result.get_barcode_column_count() + 1; - } - - fn get_start_column( detection_result: &DetectionResult, barcode_column: i32, image_row: i32, left_to_right: bool) -> i32 { - let offset: i32 = if left_to_right { 1 } else { -1 }; - let mut codeword: Codeword = null; - if ::is_valid_barcode_column(detection_result, barcode_column - offset) { - codeword = detection_result.get_detection_result_column(barcode_column - offset).get_codeword(image_row); - } - if codeword != null { - return if left_to_right { codeword.get_end_x() } else { codeword.get_start_x() }; - } - codeword = detection_result.get_detection_result_column(barcode_column).get_codeword_nearby(image_row); - if codeword != null { - return if left_to_right { codeword.get_start_x() } else { codeword.get_end_x() }; - } - if ::is_valid_barcode_column(detection_result, barcode_column - offset) { - codeword = detection_result.get_detection_result_column(barcode_column - offset).get_codeword_nearby(image_row); - } - if codeword != null { - return if left_to_right { codeword.get_end_x() } else { codeword.get_start_x() }; - } - let skipped_columns: i32 = 0; - while ::is_valid_barcode_column(detection_result, barcode_column - offset) { - barcode_column -= offset; - for let previous_row_codeword: Codeword in detection_result.get_detection_result_column(barcode_column).get_codewords() { - if previous_row_codeword != null { - return ( if left_to_right { previous_row_codeword.get_end_x() } else { previous_row_codeword.get_start_x() }) + offset * skipped_columns * (previous_row_codeword.get_end_x() - previous_row_codeword.get_start_x()); - } - } - skipped_columns += 1; - } - return if left_to_right { detection_result.get_bounding_box().get_min_x() } else { detection_result.get_bounding_box().get_max_x() }; - } - - fn detect_codeword( image: &BitMatrix, min_column: i32, max_column: i32, left_to_right: bool, start_column: i32, image_row: i32, min_codeword_width: i32, max_codeword_width: i32) -> Codeword { - start_column = ::adjust_codeword_start_column(image, min_column, max_column, left_to_right, start_column, image_row); - // we usually know fairly exact now how long a codeword is. We should provide minimum and maximum expected length - // and try to adjust the read pixels, e.g. remove single pixel errors or try to cut off exceeding pixels. - // min and maxCodewordWidth should not be used as they are calculated for the whole barcode an can be inaccurate - // for the current position - let module_bit_count: Vec = ::get_module_bit_count(image, min_column, max_column, left_to_right, start_column, image_row); - if module_bit_count == null { - return null; - } - let end_column: i32; - let codeword_bit_count: i32 = MathUtils::sum(&module_bit_count); - if left_to_right { - end_column = start_column + codeword_bit_count; - } else { - { - let mut i: i32 = 0; - while i < module_bit_count.len() / 2 { - { - let tmp_count: i32 = module_bit_count[i]; - module_bit_count[i] = module_bit_count[module_bit_count.len() - 1 - i]; - module_bit_count[module_bit_count.len() - 1 - i] = tmp_count; - } - i += 1; - } - } - - end_column = start_column; - start_column = end_column - codeword_bit_count; - } - // sufficient for now - if !::check_codeword_skew(codeword_bit_count, min_codeword_width, max_codeword_width) { - // create the bit count from it and normalize it to 8. This would help with single pixel errors. - return null; - } - let decoded_value: i32 = PDF417CodewordDecoder::get_decoded_value(&module_bit_count); - let codeword: i32 = PDF417Common::get_codeword(decoded_value); - if codeword == -1 { - return null; - } - return Codeword::new(start_column, end_column, &::get_codeword_bucket_number(decoded_value), codeword); - } - - fn get_module_bit_count( image: &BitMatrix, min_column: i32, max_column: i32, left_to_right: bool, start_column: i32, image_row: i32) -> Vec { - let image_column: i32 = start_column; - let module_bit_count: [i32; 8] = [0; 8]; - let module_number: i32 = 0; - let increment: i32 = if left_to_right { 1 } else { -1 }; - let previous_pixel_value: bool = left_to_right; - while ( if left_to_right { image_column < max_column } else { image_column >= min_column }) && module_number < module_bit_count.len() { - if image.get(image_column, image_row) == previous_pixel_value { - module_bit_count[module_number] += 1; - image_column += increment; - } else { - module_number += 1; - previous_pixel_value = !previous_pixel_value; - } - } - if module_number == module_bit_count.len() || ((image_column == ( if left_to_right { max_column } else { min_column })) && module_number == module_bit_count.len() - 1) { - return module_bit_count; - } - return null; - } - - fn get_number_of_e_c_code_words( barcode_e_c_level: i32) -> i32 { - return 2 << barcode_e_c_level; - } - - fn adjust_codeword_start_column( image: &BitMatrix, min_column: i32, max_column: i32, left_to_right: bool, codeword_start_column: i32, image_row: i32) -> i32 { - let corrected_start_column: i32 = codeword_start_column; - let mut increment: i32 = if left_to_right { -1 } else { 1 }; - // there should be no black pixels before the start column. If there are, then we need to start earlier. - { - let mut i: i32 = 0; - while i < 2 { - { - while ( if left_to_right { corrected_start_column >= min_column } else { corrected_start_column < max_column }) && left_to_right == image.get(corrected_start_column, image_row) { - if Math::abs(codeword_start_column - corrected_start_column) > CODEWORD_SKEW_SIZE { - return codeword_start_column; - } - corrected_start_column += increment; - } - increment = -increment; - left_to_right = !left_to_right; - } - i += 1; - } - } - - return corrected_start_column; - } - - fn check_codeword_skew( codeword_size: i32, min_codeword_width: i32, max_codeword_width: i32) -> bool { - return min_codeword_width - CODEWORD_SKEW_SIZE <= codeword_size && codeword_size <= max_codeword_width + CODEWORD_SKEW_SIZE; - } - - fn decode_codewords( codewords: &Vec, ec_level: i32, erasures: &Vec) -> /* throws FormatException, ChecksumException */Result> { - if codewords.len() == 0 { - throw FormatException::get_format_instance(); - } - let num_e_c_codewords: i32 = 1 << (ec_level + 1); - let corrected_errors_count: i32 = ::correct_errors(&codewords, &erasures, num_e_c_codewords); - ::verify_codeword_count(&codewords, num_e_c_codewords); - // Decode the codewords - let decoder_result: DecoderResult = DecodedBitStreamParser::decode(&codewords, &String::value_of(ec_level)); - decoder_result.set_errors_corrected(corrected_errors_count); - decoder_result.set_erasures(erasures.len()); - return Ok(decoder_result); - } - - /** - *

Given data and error-correction codewords received, possibly corrupted by errors, attempts to - * correct the errors in-place.

- * - * @param codewords data and error correction codewords - * @param erasures positions of any known erasures - * @param numECCodewords number of error correction codewords that are available in codewords - * @throws ChecksumException if error correction fails - */ - fn correct_errors( codewords: &Vec, erasures: &Vec, num_e_c_codewords: i32) -> /* throws ChecksumException */Result> { - if erasures != null && erasures.len() > num_e_c_codewords / 2 + MAX_ERRORS || num_e_c_codewords < 0 || num_e_c_codewords > MAX_EC_CODEWORDS { - // Too many errors or EC Codewords is corrupted - throw ChecksumException::get_checksum_instance(); - } - return Ok(error_correction.decode(&codewords, num_e_c_codewords, &erasures)); - } - - /** - * Verify that all is OK with the codeword array. - */ - fn verify_codeword_count( codewords: &Vec, num_e_c_codewords: i32) -> /* throws FormatException */Result> { - if codewords.len() < 4 { - // Count CW, At least one Data CW, Error Correction CW, Error Correction CW - throw FormatException::get_format_instance(); - } - // The first codeword, the Symbol Length Descriptor, shall always encode the total number of data - // codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad - // codewords, but excluding the number of error correction codewords. - let number_of_codewords: i32 = codewords[0]; - if number_of_codewords > codewords.len() { - throw FormatException::get_format_instance(); - } - if number_of_codewords == 0 { - // Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords) - if num_e_c_codewords < codewords.len() { - codewords[0] = codewords.len() - num_e_c_codewords; - } else { - throw FormatException::get_format_instance(); - } - } - } - - fn get_bit_count_for_codeword( codeword: i32) -> Vec { - let mut result: [i32; 8] = [0; 8]; - let previous_value: i32 = 0; - let mut i: i32 = result.len() - 1; - while true { - if (codeword & 0x1) != previous_value { - previous_value = codeword & 0x1; - i -= 1; - if i < 0 { - break; - } - } - result[i] += 1; - codeword >>= 1; - } - return result; - } - - fn get_codeword_bucket_number( codeword: i32) -> i32 { - return ::get_codeword_bucket_number(&::get_bit_count_for_codeword(codeword)); - } - - fn get_codeword_bucket_number( module_bit_count: &Vec) -> i32 { - return (module_bit_count[0] - module_bit_count[2] + module_bit_count[4] - module_bit_count[6] + 9) % 9; - } - - pub fn to_string( barcode_matrix: &Vec>) -> String { - let tryResult1 = 0; - 'try1: loop { - ( let formatter: Formatter = Formatter::new()) { - { - let mut row: i32 = 0; - while row < barcode_matrix.len() { - { - formatter.format("Row %2d: ", row); - { - let mut column: i32 = 0; - while column < barcode_matrix[row].len() { - { - let barcode_value: BarcodeValue = barcode_matrix[row][column]; - if barcode_value.get_value().len() == 0 { - formatter.format(" ", null as Vec); - } else { - formatter.format("%4d(%2d)", barcode_value.get_value()[0], &barcode_value.get_confidence(barcode_value.get_value()[0])); - } - } - column += 1; - } - } - - formatter.format("%n"); - } - row += 1; - } - } - - return formatter.to_string(); - } - break 'try1 - } - match tryResult1 { - 0 => break - } - - } -} - diff --git a/port_src/output/zxing/pdf417/detector/detector.rs b/port_src/output/zxing/pdf417/detector/detector.rs deleted file mode 100644 index 48eb5d6..0000000 --- a/port_src/output/zxing/pdf417/detector/detector.rs +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// package com::google::zxing::pdf417::detector; - -/** - *

Encapsulates logic that can detect a PDF417 Code in an image, even if the - * PDF417 Code is rotated or skewed, or partially obscured.

- * - * @author SITA Lab (kevin.osullivan@sita.aero) - * @author dswitkin@google.com (Daniel Switkin) - * @author Guenther Grau - */ - - const INDEXES_START_PATTERN: vec![Vec; 4] = vec![0, 4, 1, 5, ] -; - - const INDEXES_STOP_PATTERN: vec![Vec; 4] = vec![6, 2, 7, 3, ] -; - - const MAX_AVG_VARIANCE: f32 = 0.42f; - - const MAX_INDIVIDUAL_VARIANCE: f32 = 0.8f; - -// B S B S B S B S Bar/Space pattern -// 11111111 0 1 0 1 0 1 000 - const START_PATTERN: vec![Vec; 8] = vec![8, 1, 1, 1, 1, 1, 1, 3, ] -; - -// 1111111 0 1 000 1 0 1 00 1 - const STOP_PATTERN: vec![Vec; 9] = vec![7, 1, 1, 3, 1, 1, 1, 2, 1, ] -; - - const MAX_PIXEL_DRIFT: i32 = 3; - - const MAX_PATTERN_DRIFT: i32 = 5; - -// if we set the value too low, then we don't detect the correct height of the bar if the start patterns are damaged. -// if we set the value too high, then we might detect the start pattern from a neighbor barcode. - const SKIPPED_ROW_COUNT_MAX: i32 = 25; - -// A PDF471 barcode should have at least 3 rows, with each row being >= 3 times the module width. -// Therefore it should be at least 9 pixels tall. To be conservative, we use about half the size to -// ensure we don't miss it. - const ROW_STEP: i32 = 5; - - const BARCODE_MIN_HEIGHT: i32 = 10; - - const ROTATIONS: vec![Vec; 4] = vec![0, 180, 270, 90, ] -; -pub struct Detector { -} - -impl Detector { - - fn new() -> Detector { - } - - /** - *

Detects a PDF417 Code in an image. Checks 0, 90, 180, and 270 degree rotations.

- * - * @param image barcode image to decode - * @param hints optional hints to detector - * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will - * be found and returned - * @return {@link PDF417DetectorResult} encapsulating results of detecting a PDF417 code - * @throws NotFoundException if no PDF417 Code can be found - */ - pub fn detect( image: &BinaryBitmap, hints: &Map, multiple: bool) -> /* throws NotFoundException */Result> { - // TODO detection improvement, tryHarder could try several different luminance thresholds/blackpoints or even - // different binarizers - //boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); - let original_matrix: BitMatrix = image.get_black_matrix(); - for let rotation: i32 in ROTATIONS { - let bit_matrix: BitMatrix = ::apply_rotation(original_matrix, rotation); - let barcode_coordinates: List> = ::detect(multiple, bit_matrix); - if !barcode_coordinates.is_empty() { - return Ok(PDF417DetectorResult::new(bit_matrix, &barcode_coordinates, rotation)); - } - } - return Ok(PDF417DetectorResult::new(original_matrix, ArrayList<>::new(), 0)); - } - - /** - * Applies a rotation to the supplied BitMatrix. - * @param matrix bit matrix to apply rotation to - * @param rotation the degrees of rotation to apply - * @return BitMatrix with applied rotation - */ - fn apply_rotation( matrix: &BitMatrix, rotation: i32) -> BitMatrix { - if rotation % 360 == 0 { - return matrix; - } - let new_matrix: BitMatrix = matrix.clone(); - new_matrix.rotate(rotation); - return new_matrix; - } - - /** - * Detects PDF417 codes in an image. Only checks 0 degree rotation - * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will - * be found and returned - * @param bitMatrix bit matrix to detect barcodes in - * @return List of ResultPoint arrays containing the coordinates of found barcodes - */ - fn detect( multiple: bool, bit_matrix: &BitMatrix) -> List> { - let barcode_coordinates: List> = ArrayList<>::new(); - let mut row: i32 = 0; - let mut column: i32 = 0; - let found_barcode_in_row: bool = false; - while row < bit_matrix.get_height() { - let vertices: Vec = ::find_vertices(bit_matrix, row, column); - if vertices[0] == null && vertices[3] == null { - if !found_barcode_in_row { - // we didn't find any barcode so that's the end of searching - break; - } - // we didn't find a barcode starting at the given column and row. Try again from the first column and slightly - // below the lowest barcode we found so far. - found_barcode_in_row = false; - column = 0; - for let barcode_coordinate: Vec in barcode_coordinates { - if barcode_coordinate[1] != null { - row = Math::max(row, &barcode_coordinate[1].get_y()) as i32; - } - if barcode_coordinate[3] != null { - row = Math::max(row, barcode_coordinate[3].get_y() as i32); - } - } - row += ROW_STEP; - continue; - } - found_barcode_in_row = true; - barcode_coordinates.add(vertices); - if !multiple { - break; - } - // start pattern of the barcode just found. - if vertices[2] != null { - column = vertices[2].get_x() as i32; - row = vertices[2].get_y() as i32; - } else { - column = vertices[4].get_x() as i32; - row = vertices[4].get_y() as i32; - } - } - return Ok(barcode_coordinates); - } - - /** - * Locate the vertices and the codewords area of a black blob using the Start - * and Stop patterns as locators. - * - * @param matrix the scanned barcode image. - * @return an array containing the vertices: - * vertices[0] x, y top left barcode - * vertices[1] x, y bottom left barcode - * vertices[2] x, y top right barcode - * vertices[3] x, y bottom right barcode - * vertices[4] x, y top left codeword area - * vertices[5] x, y bottom left codeword area - * vertices[6] x, y top right codeword area - * vertices[7] x, y bottom right codeword area - */ - fn find_vertices( matrix: &BitMatrix, start_row: i32, start_column: i32) -> Vec { - let height: i32 = matrix.get_height(); - let width: i32 = matrix.get_width(); - let result: [Option; 8] = [None; 8]; - ::copy_to_result(result, &::find_rows_with_pattern(matrix, height, width, start_row, start_column, &START_PATTERN), &INDEXES_START_PATTERN); - if result[4] != null { - start_column = result[4].get_x() as i32; - start_row = result[4].get_y() as i32; - } - ::copy_to_result(result, &::find_rows_with_pattern(matrix, height, width, start_row, start_column, &STOP_PATTERN), &INDEXES_STOP_PATTERN); - return result; - } - - fn copy_to_result( result: &Vec, tmp_result: &Vec, destination_indexes: &Vec) { - { - let mut i: i32 = 0; - while i < destination_indexes.len() { - { - result[destination_indexes[i]] = tmp_result[i]; - } - i += 1; - } - } - - } - - fn find_rows_with_pattern( matrix: &BitMatrix, height: i32, width: i32, start_row: i32, start_column: i32, pattern: &Vec) -> Vec { - let mut result: [Option; 4] = [None; 4]; - let mut found: bool = false; - let counters: [i32; pattern.len()] = [0; pattern.len()]; - while start_row < height { - { - let mut loc: Vec = ::find_guard_pattern(matrix, start_column, start_row, width, &pattern, &counters); - if loc != null { - while start_row > 0 { - let previous_row_loc: Vec = ::find_guard_pattern(matrix, start_column, start_row -= 1, width, &pattern, &counters); - if previous_row_loc != null { - loc = previous_row_loc; - } else { - start_row += 1; - break; - } - } - result[0] = ResultPoint::new(loc[0], start_row); - result[1] = ResultPoint::new(loc[1], start_row); - found = true; - break; - } - } - start_row += ROW_STEP; - } - - let stop_row: i32 = start_row + 1; - // Last row of the current symbol that contains pattern - if found { - let skipped_row_count: i32 = 0; - let previous_row_loc: vec![Vec; 2] = vec![result[0].get_x() as i32, result[1].get_x() as i32, ] - ; - while stop_row < height { - { - let loc: Vec = ::find_guard_pattern(matrix, previous_row_loc[0], stop_row, width, &pattern, &counters); - // larger drift and don't check for skipped rows. - if loc != null && Math::abs(previous_row_loc[0] - loc[0]) < MAX_PATTERN_DRIFT && Math::abs(previous_row_loc[1] - loc[1]) < MAX_PATTERN_DRIFT { - previous_row_loc = loc; - skipped_row_count = 0; - } else { - if skipped_row_count > SKIPPED_ROW_COUNT_MAX { - break; - } else { - skipped_row_count += 1; - } - } - } - stop_row += 1; - } - - stop_row -= skipped_row_count + 1; - result[2] = ResultPoint::new(previous_row_loc[0], stop_row); - result[3] = ResultPoint::new(previous_row_loc[1], stop_row); - } - if stop_row - start_row < BARCODE_MIN_HEIGHT { - Arrays::fill(result, null); - } - return result; - } - - /** - * @param matrix row of black/white values to search - * @param column x position to start search - * @param row y position to start search - * @param width the number of pixels to search on this row - * @param pattern pattern of counts of number of black and white pixels that are - * being searched for as a pattern - * @param counters array of counters, as long as pattern, to re-use - * @return start/end horizontal offset of guard pattern, as an array of two ints. - */ - fn find_guard_pattern( matrix: &BitMatrix, column: i32, row: i32, width: i32, pattern: &Vec, counters: &Vec) -> Vec { - Arrays::fill(&counters, 0, counters.len(), 0); - let pattern_start: i32 = column; - let pixel_drift: i32 = 0; - // if there are black pixels left of the current pixel shift to the left, but only for MAX_PIXEL_DRIFT pixels - while matrix.get(pattern_start, row) && pattern_start > 0 && pixel_drift += 1 !!!check!!! post increment < MAX_PIXEL_DRIFT { - pattern_start -= 1; - } - let mut x: i32 = pattern_start; - let counter_position: i32 = 0; - let pattern_length: i32 = pattern.len(); - { - let is_white: bool = false; - while x < width { - { - let pixel: bool = matrix.get(x, row); - if pixel != is_white { - counters[counter_position] += 1; - } else { - if counter_position == pattern_length - 1 { - if ::pattern_match_variance(&counters, &pattern) < MAX_AVG_VARIANCE { - return : vec![i32; 2] = vec![pattern_start, x, ] - ; - } - pattern_start += counters[0] + counters[1]; - System::arraycopy(&counters, 2, &counters, 0, counter_position - 1); - counters[counter_position - 1] = 0; - counters[counter_position] = 0; - counter_position -= 1; - } else { - counter_position += 1; - } - counters[counter_position] = 1; - is_white = !is_white; - } - } - x += 1; - } - } - - if counter_position == pattern_length - 1 && ::pattern_match_variance(&counters, &pattern) < MAX_AVG_VARIANCE { - return : vec![i32; 2] = vec![pattern_start, x - 1, ] - ; - } - return null; - } - - /** - * Determines how closely a set of observed counts of runs of black/white - * values matches a given target pattern. This is reported as the ratio of - * the total variance from the expected pattern proportions across all - * pattern elements, to the length of the pattern. - * - * @param counters observed counters - * @param pattern expected pattern - * @return ratio of total variance between counters and pattern compared to total pattern size - */ - fn pattern_match_variance( counters: &Vec, pattern: &Vec) -> f32 { - let num_counters: i32 = counters.len(); - let mut total: i32 = 0; - let pattern_length: i32 = 0; - { - let mut i: i32 = 0; - while i < num_counters { - { - total += counters[i]; - pattern_length += pattern[i]; - } - i += 1; - } - } - - if total < pattern_length { - // is too small to reliably match, so fail: - return Float::POSITIVE_INFINITY; - } - // We're going to fake floating-point math in integers. We just need to use more bits. - // Scale up patternLength so that intermediate values below like scaledCounter will have - // more "significant digits". - let unit_bar_width: f32 = total as f32 / pattern_length; - let max_individual_variance: f32 = MAX_INDIVIDUAL_VARIANCE * unit_bar_width; - let total_variance: f32 = 0.0f; - { - let mut x: i32 = 0; - while x < num_counters { - { - let counter: i32 = counters[x]; - let scaled_pattern: f32 = pattern[x] * unit_bar_width; - let variance: f32 = if counter > scaled_pattern { counter - scaled_pattern } else { scaled_pattern - counter }; - if variance > max_individual_variance { - return Float::POSITIVE_INFINITY; - } - total_variance += variance; - } - x += 1; - } - } - - return total_variance / total; - } -} - diff --git a/port_src/output/zxing/pdf417/detector/p_d_f417_detector_result.rs b/port_src/output/zxing/pdf417/detector/p_d_f417_detector_result.rs deleted file mode 100644 index d4db626..0000000 --- a/port_src/output/zxing/pdf417/detector/p_d_f417_detector_result.rs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// package com::google::zxing::pdf417::detector; - -/** - * @author Guenther Grau - */ -pub struct PDF417DetectorResult { - - let bits: BitMatrix; - - let points: List>; - - let rotation: i32; -} - -impl PDF417DetectorResult { - - pub fn new( bits: &BitMatrix, points: &List>, rotation: i32) -> PDF417DetectorResult { - let .bits = bits; - let .points = points; - let .rotation = rotation; - } - - pub fn new( bits: &BitMatrix, points: &List>) -> PDF417DetectorResult { - this(bits, &points, 0); - } - - pub fn get_bits(&self) -> BitMatrix { - return self.bits; - } - - pub fn get_points(&self) -> List> { - return self.points; - } - - pub fn get_rotation(&self) -> i32 { - return self.rotation; - } -} - diff --git a/port_src/output/zxing/pdf417/encoder/barcode_matrix.rs b/port_src/output/zxing/pdf417/encoder/barcode_matrix.rs deleted file mode 100644 index c7a4e23..0000000 --- a/port_src/output/zxing/pdf417/encoder/barcode_matrix.rs +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2011 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::pdf417::encoder; - -/** - * Holds all of the information for a barcode in a format where it can be easily accessible - * - * @author Jacob Haynes - */ -pub struct BarcodeMatrix { - - let mut matrix: Vec; - - let current_row: i32; - - let height: i32; - - let width: i32; -} - -impl BarcodeMatrix { - - /** - * @param height the height of the matrix (Rows) - * @param width the width of the matrix (Cols) - */ - fn new( height: i32, width: i32) -> BarcodeMatrix { - matrix = : [Option; height] = [None; height]; - //Initializes the array to the correct width - { - let mut i: i32 = 0, let matrix_length: i32 = matrix.len(); - while i < matrix_length { - { - matrix[i] = BarcodeRow::new((width + 4) * 17 + 1); - } - i += 1; - } - } - - let .width = width * 17; - let .height = height; - let .currentRow = -1; - } - - fn set(&self, x: i32, y: i32, value: i8) { - self.matrix[y].set(x, value); - } - - fn start_row(&self) { - self.current_row += 1; - } - - fn get_current_row(&self) -> BarcodeRow { - return self.matrix[self.current_row]; - } - - pub fn get_matrix(&self) -> Vec> { - return self.get_scaled_matrix(1, 1); - } - - pub fn get_scaled_matrix(&self, x_scale: i32, y_scale: i32) -> Vec> { - let matrix_out: [[i8; self.width * x_scale]; self.height * y_scale] = [[0; self.width * x_scale]; self.height * y_scale]; - let y_max: i32 = self.height * y_scale; - { - let mut i: i32 = 0; - while i < y_max { - { - matrix_out[y_max - i - 1] = self.matrix[i / y_scale].get_scaled_row(x_scale); - } - i += 1; - } - } - - return matrix_out; - } -} - diff --git a/port_src/output/zxing/pdf417/encoder/barcode_row.rs b/port_src/output/zxing/pdf417/encoder/barcode_row.rs deleted file mode 100644 index dfe8332..0000000 --- a/port_src/output/zxing/pdf417/encoder/barcode_row.rs +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2011 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::pdf417::encoder; - -/** - * @author Jacob Haynes - */ -struct BarcodeRow { - - let mut row: Vec; - - //A tacker for position in the bar - let current_location: i32; -} - -impl BarcodeRow { - - /** - * Creates a Barcode row of the width - */ - fn new( width: i32) -> BarcodeRow { - let .row = : [i8; width] = [0; width]; - current_location = 0; - } - - /** - * Sets a specific location in the bar - * - * @param x The location in the bar - * @param value Black if true, white if false; - */ - fn set(&self, x: i32, value: i8) { - self.row[x] = value; - } - - /** - * Sets a specific location in the bar - * - * @param x The location in the bar - * @param black Black if true, white if false; - */ - fn set(&self, x: i32, black: bool) { - self.row[x] = ( if black { 1 } else { 0 }) as i8; - } - - /** - * @param black A boolean which is true if the bar black false if it is white - * @param width How many spots wide the bar is. - */ - fn add_bar(&self, black: bool, width: i32) { - { - let mut ii: i32 = 0; - while ii < width { - { - self.set(self.current_location += 1 !!!check!!! post increment, black); - } - ii += 1; - } - } - - } - - /** - * This function scales the row - * - * @param scale How much you want the image to be scaled, must be greater than or equal to 1. - * @return the scaled row - */ - fn get_scaled_row(&self, scale: i32) -> Vec { - let mut output: [i8; self.row.len() * scale] = [0; self.row.len() * scale]; - { - let mut i: i32 = 0; - while i < output.len() { - { - output[i] = self.row[i / scale]; - } - i += 1; - } - } - - return output; - } -} - diff --git a/port_src/output/zxing/pdf417/encoder/compaction.rs b/port_src/output/zxing/pdf417/encoder/compaction.rs deleted file mode 100644 index 00cd60f..0000000 --- a/port_src/output/zxing/pdf417/encoder/compaction.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2011 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::pdf417::encoder; - -/** - * Represents possible PDF417 barcode compaction types. - */ -pub enum Compaction { - - AUTO(), TEXT(), BYTE(), NUMERIC() -} diff --git a/port_src/output/zxing/pdf417/encoder/dimensions.rs b/port_src/output/zxing/pdf417/encoder/dimensions.rs deleted file mode 100644 index fce0cc6..0000000 --- a/port_src/output/zxing/pdf417/encoder/dimensions.rs +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// package com::google::zxing::pdf417::encoder; - -/** - * Data object to specify the minimum and maximum number of rows and columns for a PDF417 barcode. - * - * @author qwandor@google.com (Andrew Walbran) - */ -pub struct Dimensions { - - let min_cols: i32; - - let max_cols: i32; - - let min_rows: i32; - - let max_rows: i32; -} - -impl Dimensions { - - pub fn new( min_cols: i32, max_cols: i32, min_rows: i32, max_rows: i32) -> Dimensions { - let .minCols = min_cols; - let .maxCols = max_cols; - let .minRows = min_rows; - let .maxRows = max_rows; - } - - pub fn get_min_cols(&self) -> i32 { - return self.min_cols; - } - - pub fn get_max_cols(&self) -> i32 { - return self.max_cols; - } - - pub fn get_min_rows(&self) -> i32 { - return self.min_rows; - } - - pub fn get_max_rows(&self) -> i32 { - return self.max_rows; - } -} - diff --git a/port_src/output/zxing/pdf417/encoder/p_d_f417.rs b/port_src/output/zxing/pdf417/encoder/p_d_f417.rs deleted file mode 100644 index 0c93387..0000000 --- a/port_src/output/zxing/pdf417/encoder/p_d_f417.rs +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part - * - * 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::pdf417::encoder; - -/** - * Top-level class for the logic part of the PDF417 implementation. - */ - -/** - * The start pattern (17 bits) - */ - const START_PATTERN: i32 = 0x1fea8; - -/** - * The stop pattern (18 bits) - */ - const STOP_PATTERN: i32 = 0x3fa29; - -/** - * The codeword table from the Annex A of ISO/IEC 15438:2001(E). - */ - const CODEWORD_TABLE: vec![vec![Vec>; 929]; 3] = vec![vec![0x1d5c0, 0x1eaf0, 0x1f57c, 0x1d4e0, 0x1ea78, 0x1f53e, 0x1a8c0, 0x1d470, 0x1a860, 0x15040, 0x1a830, 0x15020, 0x1adc0, 0x1d6f0, 0x1eb7c, 0x1ace0, 0x1d678, 0x1eb3e, 0x158c0, 0x1ac70, 0x15860, 0x15dc0, 0x1aef0, 0x1d77c, 0x15ce0, 0x1ae78, 0x1d73e, 0x15c70, 0x1ae3c, 0x15ef0, 0x1af7c, 0x15e78, 0x1af3e, 0x15f7c, 0x1f5fa, 0x1d2e0, 0x1e978, 0x1f4be, 0x1a4c0, 0x1d270, 0x1e93c, 0x1a460, 0x1d238, 0x14840, 0x1a430, 0x1d21c, 0x14820, 0x1a418, 0x14810, 0x1a6e0, 0x1d378, 0x1e9be, 0x14cc0, 0x1a670, 0x1d33c, 0x14c60, 0x1a638, 0x1d31e, 0x14c30, 0x1a61c, 0x14ee0, 0x1a778, 0x1d3be, 0x14e70, 0x1a73c, 0x14e38, 0x1a71e, 0x14f78, 0x1a7be, 0x14f3c, 0x14f1e, 0x1a2c0, 0x1d170, 0x1e8bc, 0x1a260, 0x1d138, 0x1e89e, 0x14440, 0x1a230, 0x1d11c, 0x14420, 0x1a218, 0x14410, 0x14408, 0x146c0, 0x1a370, 0x1d1bc, 0x14660, 0x1a338, 0x1d19e, 0x14630, 0x1a31c, 0x14618, 0x1460c, 0x14770, 0x1a3bc, 0x14738, 0x1a39e, 0x1471c, 0x147bc, 0x1a160, 0x1d0b8, 0x1e85e, 0x14240, 0x1a130, 0x1d09c, 0x14220, 0x1a118, 0x1d08e, 0x14210, 0x1a10c, 0x14208, 0x1a106, 0x14360, 0x1a1b8, 0x1d0de, 0x14330, 0x1a19c, 0x14318, 0x1a18e, 0x1430c, 0x14306, 0x1a1de, 0x1438e, 0x14140, 0x1a0b0, 0x1d05c, 0x14120, 0x1a098, 0x1d04e, 0x14110, 0x1a08c, 0x14108, 0x1a086, 0x14104, 0x141b0, 0x14198, 0x1418c, 0x140a0, 0x1d02e, 0x1a04c, 0x1a046, 0x14082, 0x1cae0, 0x1e578, 0x1f2be, 0x194c0, 0x1ca70, 0x1e53c, 0x19460, 0x1ca38, 0x1e51e, 0x12840, 0x19430, 0x12820, 0x196e0, 0x1cb78, 0x1e5be, 0x12cc0, 0x19670, 0x1cb3c, 0x12c60, 0x19638, 0x12c30, 0x12c18, 0x12ee0, 0x19778, 0x1cbbe, 0x12e70, 0x1973c, 0x12e38, 0x12e1c, 0x12f78, 0x197be, 0x12f3c, 0x12fbe, 0x1dac0, 0x1ed70, 0x1f6bc, 0x1da60, 0x1ed38, 0x1f69e, 0x1b440, 0x1da30, 0x1ed1c, 0x1b420, 0x1da18, 0x1ed0e, 0x1b410, 0x1da0c, 0x192c0, 0x1c970, 0x1e4bc, 0x1b6c0, 0x19260, 0x1c938, 0x1e49e, 0x1b660, 0x1db38, 0x1ed9e, 0x16c40, 0x12420, 0x19218, 0x1c90e, 0x16c20, 0x1b618, 0x16c10, 0x126c0, 0x19370, 0x1c9bc, 0x16ec0, 0x12660, 0x19338, 0x1c99e, 0x16e60, 0x1b738, 0x1db9e, 0x16e30, 0x12618, 0x16e18, 0x12770, 0x193bc, 0x16f70, 0x12738, 0x1939e, 0x16f38, 0x1b79e, 0x16f1c, 0x127bc, 0x16fbc, 0x1279e, 0x16f9e, 0x1d960, 0x1ecb8, 0x1f65e, 0x1b240, 0x1d930, 0x1ec9c, 0x1b220, 0x1d918, 0x1ec8e, 0x1b210, 0x1d90c, 0x1b208, 0x1b204, 0x19160, 0x1c8b8, 0x1e45e, 0x1b360, 0x19130, 0x1c89c, 0x16640, 0x12220, 0x1d99c, 0x1c88e, 0x16620, 0x12210, 0x1910c, 0x16610, 0x1b30c, 0x19106, 0x12204, 0x12360, 0x191b8, 0x1c8de, 0x16760, 0x12330, 0x1919c, 0x16730, 0x1b39c, 0x1918e, 0x16718, 0x1230c, 0x12306, 0x123b8, 0x191de, 0x167b8, 0x1239c, 0x1679c, 0x1238e, 0x1678e, 0x167de, 0x1b140, 0x1d8b0, 0x1ec5c, 0x1b120, 0x1d898, 0x1ec4e, 0x1b110, 0x1d88c, 0x1b108, 0x1d886, 0x1b104, 0x1b102, 0x12140, 0x190b0, 0x1c85c, 0x16340, 0x12120, 0x19098, 0x1c84e, 0x16320, 0x1b198, 0x1d8ce, 0x16310, 0x12108, 0x19086, 0x16308, 0x1b186, 0x16304, 0x121b0, 0x190dc, 0x163b0, 0x12198, 0x190ce, 0x16398, 0x1b1ce, 0x1638c, 0x12186, 0x16386, 0x163dc, 0x163ce, 0x1b0a0, 0x1d858, 0x1ec2e, 0x1b090, 0x1d84c, 0x1b088, 0x1d846, 0x1b084, 0x1b082, 0x120a0, 0x19058, 0x1c82e, 0x161a0, 0x12090, 0x1904c, 0x16190, 0x1b0cc, 0x19046, 0x16188, 0x12084, 0x16184, 0x12082, 0x120d8, 0x161d8, 0x161cc, 0x161c6, 0x1d82c, 0x1d826, 0x1b042, 0x1902c, 0x12048, 0x160c8, 0x160c4, 0x160c2, 0x18ac0, 0x1c570, 0x1e2bc, 0x18a60, 0x1c538, 0x11440, 0x18a30, 0x1c51c, 0x11420, 0x18a18, 0x11410, 0x11408, 0x116c0, 0x18b70, 0x1c5bc, 0x11660, 0x18b38, 0x1c59e, 0x11630, 0x18b1c, 0x11618, 0x1160c, 0x11770, 0x18bbc, 0x11738, 0x18b9e, 0x1171c, 0x117bc, 0x1179e, 0x1cd60, 0x1e6b8, 0x1f35e, 0x19a40, 0x1cd30, 0x1e69c, 0x19a20, 0x1cd18, 0x1e68e, 0x19a10, 0x1cd0c, 0x19a08, 0x1cd06, 0x18960, 0x1c4b8, 0x1e25e, 0x19b60, 0x18930, 0x1c49c, 0x13640, 0x11220, 0x1cd9c, 0x1c48e, 0x13620, 0x19b18, 0x1890c, 0x13610, 0x11208, 0x13608, 0x11360, 0x189b8, 0x1c4de, 0x13760, 0x11330, 0x1cdde, 0x13730, 0x19b9c, 0x1898e, 0x13718, 0x1130c, 0x1370c, 0x113b8, 0x189de, 0x137b8, 0x1139c, 0x1379c, 0x1138e, 0x113de, 0x137de, 0x1dd40, 0x1eeb0, 0x1f75c, 0x1dd20, 0x1ee98, 0x1f74e, 0x1dd10, 0x1ee8c, 0x1dd08, 0x1ee86, 0x1dd04, 0x19940, 0x1ccb0, 0x1e65c, 0x1bb40, 0x19920, 0x1eedc, 0x1e64e, 0x1bb20, 0x1dd98, 0x1eece, 0x1bb10, 0x19908, 0x1cc86, 0x1bb08, 0x1dd86, 0x19902, 0x11140, 0x188b0, 0x1c45c, 0x13340, 0x11120, 0x18898, 0x1c44e, 0x17740, 0x13320, 0x19998, 0x1ccce, 0x17720, 0x1bb98, 0x1ddce, 0x18886, 0x17710, 0x13308, 0x19986, 0x17708, 0x11102, 0x111b0, 0x188dc, 0x133b0, 0x11198, 0x188ce, 0x177b0, 0x13398, 0x199ce, 0x17798, 0x1bbce, 0x11186, 0x13386, 0x111dc, 0x133dc, 0x111ce, 0x177dc, 0x133ce, 0x1dca0, 0x1ee58, 0x1f72e, 0x1dc90, 0x1ee4c, 0x1dc88, 0x1ee46, 0x1dc84, 0x1dc82, 0x198a0, 0x1cc58, 0x1e62e, 0x1b9a0, 0x19890, 0x1ee6e, 0x1b990, 0x1dccc, 0x1cc46, 0x1b988, 0x19884, 0x1b984, 0x19882, 0x1b982, 0x110a0, 0x18858, 0x1c42e, 0x131a0, 0x11090, 0x1884c, 0x173a0, 0x13190, 0x198cc, 0x18846, 0x17390, 0x1b9cc, 0x11084, 0x17388, 0x13184, 0x11082, 0x13182, 0x110d8, 0x1886e, 0x131d8, 0x110cc, 0x173d8, 0x131cc, 0x110c6, 0x173cc, 0x131c6, 0x110ee, 0x173ee, 0x1dc50, 0x1ee2c, 0x1dc48, 0x1ee26, 0x1dc44, 0x1dc42, 0x19850, 0x1cc2c, 0x1b8d0, 0x19848, 0x1cc26, 0x1b8c8, 0x1dc66, 0x1b8c4, 0x19842, 0x1b8c2, 0x11050, 0x1882c, 0x130d0, 0x11048, 0x18826, 0x171d0, 0x130c8, 0x19866, 0x171c8, 0x1b8e6, 0x11042, 0x171c4, 0x130c2, 0x171c2, 0x130ec, 0x171ec, 0x171e6, 0x1ee16, 0x1dc22, 0x1cc16, 0x19824, 0x19822, 0x11028, 0x13068, 0x170e8, 0x11022, 0x13062, 0x18560, 0x10a40, 0x18530, 0x10a20, 0x18518, 0x1c28e, 0x10a10, 0x1850c, 0x10a08, 0x18506, 0x10b60, 0x185b8, 0x1c2de, 0x10b30, 0x1859c, 0x10b18, 0x1858e, 0x10b0c, 0x10b06, 0x10bb8, 0x185de, 0x10b9c, 0x10b8e, 0x10bde, 0x18d40, 0x1c6b0, 0x1e35c, 0x18d20, 0x1c698, 0x18d10, 0x1c68c, 0x18d08, 0x1c686, 0x18d04, 0x10940, 0x184b0, 0x1c25c, 0x11b40, 0x10920, 0x1c6dc, 0x1c24e, 0x11b20, 0x18d98, 0x1c6ce, 0x11b10, 0x10908, 0x18486, 0x11b08, 0x18d86, 0x10902, 0x109b0, 0x184dc, 0x11bb0, 0x10998, 0x184ce, 0x11b98, 0x18dce, 0x11b8c, 0x10986, 0x109dc, 0x11bdc, 0x109ce, 0x11bce, 0x1cea0, 0x1e758, 0x1f3ae, 0x1ce90, 0x1e74c, 0x1ce88, 0x1e746, 0x1ce84, 0x1ce82, 0x18ca0, 0x1c658, 0x19da0, 0x18c90, 0x1c64c, 0x19d90, 0x1cecc, 0x1c646, 0x19d88, 0x18c84, 0x19d84, 0x18c82, 0x19d82, 0x108a0, 0x18458, 0x119a0, 0x10890, 0x1c66e, 0x13ba0, 0x11990, 0x18ccc, 0x18446, 0x13b90, 0x19dcc, 0x10884, 0x13b88, 0x11984, 0x10882, 0x11982, 0x108d8, 0x1846e, 0x119d8, 0x108cc, 0x13bd8, 0x119cc, 0x108c6, 0x13bcc, 0x119c6, 0x108ee, 0x119ee, 0x13bee, 0x1ef50, 0x1f7ac, 0x1ef48, 0x1f7a6, 0x1ef44, 0x1ef42, 0x1ce50, 0x1e72c, 0x1ded0, 0x1ef6c, 0x1e726, 0x1dec8, 0x1ef66, 0x1dec4, 0x1ce42, 0x1dec2, 0x18c50, 0x1c62c, 0x19cd0, 0x18c48, 0x1c626, 0x1bdd0, 0x19cc8, 0x1ce66, 0x1bdc8, 0x1dee6, 0x18c42, 0x1bdc4, 0x19cc2, 0x1bdc2, 0x10850, 0x1842c, 0x118d0, 0x10848, 0x18426, 0x139d0, 0x118c8, 0x18c66, 0x17bd0, 0x139c8, 0x19ce6, 0x10842, 0x17bc8, 0x1bde6, 0x118c2, 0x17bc4, 0x1086c, 0x118ec, 0x10866, 0x139ec, 0x118e6, 0x17bec, 0x139e6, 0x17be6, 0x1ef28, 0x1f796, 0x1ef24, 0x1ef22, 0x1ce28, 0x1e716, 0x1de68, 0x1ef36, 0x1de64, 0x1ce22, 0x1de62, 0x18c28, 0x1c616, 0x19c68, 0x18c24, 0x1bce8, 0x19c64, 0x18c22, 0x1bce4, 0x19c62, 0x1bce2, 0x10828, 0x18416, 0x11868, 0x18c36, 0x138e8, 0x11864, 0x10822, 0x179e8, 0x138e4, 0x11862, 0x179e4, 0x138e2, 0x179e2, 0x11876, 0x179f6, 0x1ef12, 0x1de34, 0x1de32, 0x19c34, 0x1bc74, 0x1bc72, 0x11834, 0x13874, 0x178f4, 0x178f2, 0x10540, 0x10520, 0x18298, 0x10510, 0x10508, 0x10504, 0x105b0, 0x10598, 0x1058c, 0x10586, 0x105dc, 0x105ce, 0x186a0, 0x18690, 0x1c34c, 0x18688, 0x1c346, 0x18684, 0x18682, 0x104a0, 0x18258, 0x10da0, 0x186d8, 0x1824c, 0x10d90, 0x186cc, 0x10d88, 0x186c6, 0x10d84, 0x10482, 0x10d82, 0x104d8, 0x1826e, 0x10dd8, 0x186ee, 0x10dcc, 0x104c6, 0x10dc6, 0x104ee, 0x10dee, 0x1c750, 0x1c748, 0x1c744, 0x1c742, 0x18650, 0x18ed0, 0x1c76c, 0x1c326, 0x18ec8, 0x1c766, 0x18ec4, 0x18642, 0x18ec2, 0x10450, 0x10cd0, 0x10448, 0x18226, 0x11dd0, 0x10cc8, 0x10444, 0x11dc8, 0x10cc4, 0x10442, 0x11dc4, 0x10cc2, 0x1046c, 0x10cec, 0x10466, 0x11dec, 0x10ce6, 0x11de6, 0x1e7a8, 0x1e7a4, 0x1e7a2, 0x1c728, 0x1cf68, 0x1e7b6, 0x1cf64, 0x1c722, 0x1cf62, 0x18628, 0x1c316, 0x18e68, 0x1c736, 0x19ee8, 0x18e64, 0x18622, 0x19ee4, 0x18e62, 0x19ee2, 0x10428, 0x18216, 0x10c68, 0x18636, 0x11ce8, 0x10c64, 0x10422, 0x13de8, 0x11ce4, 0x10c62, 0x13de4, 0x11ce2, 0x10436, 0x10c76, 0x11cf6, 0x13df6, 0x1f7d4, 0x1f7d2, 0x1e794, 0x1efb4, 0x1e792, 0x1efb2, 0x1c714, 0x1cf34, 0x1c712, 0x1df74, 0x1cf32, 0x1df72, 0x18614, 0x18e34, 0x18612, 0x19e74, 0x18e32, 0x1bef4, ] -, vec![0x1f560, 0x1fab8, 0x1ea40, 0x1f530, 0x1fa9c, 0x1ea20, 0x1f518, 0x1fa8e, 0x1ea10, 0x1f50c, 0x1ea08, 0x1f506, 0x1ea04, 0x1eb60, 0x1f5b8, 0x1fade, 0x1d640, 0x1eb30, 0x1f59c, 0x1d620, 0x1eb18, 0x1f58e, 0x1d610, 0x1eb0c, 0x1d608, 0x1eb06, 0x1d604, 0x1d760, 0x1ebb8, 0x1f5de, 0x1ae40, 0x1d730, 0x1eb9c, 0x1ae20, 0x1d718, 0x1eb8e, 0x1ae10, 0x1d70c, 0x1ae08, 0x1d706, 0x1ae04, 0x1af60, 0x1d7b8, 0x1ebde, 0x15e40, 0x1af30, 0x1d79c, 0x15e20, 0x1af18, 0x1d78e, 0x15e10, 0x1af0c, 0x15e08, 0x1af06, 0x15f60, 0x1afb8, 0x1d7de, 0x15f30, 0x1af9c, 0x15f18, 0x1af8e, 0x15f0c, 0x15fb8, 0x1afde, 0x15f9c, 0x15f8e, 0x1e940, 0x1f4b0, 0x1fa5c, 0x1e920, 0x1f498, 0x1fa4e, 0x1e910, 0x1f48c, 0x1e908, 0x1f486, 0x1e904, 0x1e902, 0x1d340, 0x1e9b0, 0x1f4dc, 0x1d320, 0x1e998, 0x1f4ce, 0x1d310, 0x1e98c, 0x1d308, 0x1e986, 0x1d304, 0x1d302, 0x1a740, 0x1d3b0, 0x1e9dc, 0x1a720, 0x1d398, 0x1e9ce, 0x1a710, 0x1d38c, 0x1a708, 0x1d386, 0x1a704, 0x1a702, 0x14f40, 0x1a7b0, 0x1d3dc, 0x14f20, 0x1a798, 0x1d3ce, 0x14f10, 0x1a78c, 0x14f08, 0x1a786, 0x14f04, 0x14fb0, 0x1a7dc, 0x14f98, 0x1a7ce, 0x14f8c, 0x14f86, 0x14fdc, 0x14fce, 0x1e8a0, 0x1f458, 0x1fa2e, 0x1e890, 0x1f44c, 0x1e888, 0x1f446, 0x1e884, 0x1e882, 0x1d1a0, 0x1e8d8, 0x1f46e, 0x1d190, 0x1e8cc, 0x1d188, 0x1e8c6, 0x1d184, 0x1d182, 0x1a3a0, 0x1d1d8, 0x1e8ee, 0x1a390, 0x1d1cc, 0x1a388, 0x1d1c6, 0x1a384, 0x1a382, 0x147a0, 0x1a3d8, 0x1d1ee, 0x14790, 0x1a3cc, 0x14788, 0x1a3c6, 0x14784, 0x14782, 0x147d8, 0x1a3ee, 0x147cc, 0x147c6, 0x147ee, 0x1e850, 0x1f42c, 0x1e848, 0x1f426, 0x1e844, 0x1e842, 0x1d0d0, 0x1e86c, 0x1d0c8, 0x1e866, 0x1d0c4, 0x1d0c2, 0x1a1d0, 0x1d0ec, 0x1a1c8, 0x1d0e6, 0x1a1c4, 0x1a1c2, 0x143d0, 0x1a1ec, 0x143c8, 0x1a1e6, 0x143c4, 0x143c2, 0x143ec, 0x143e6, 0x1e828, 0x1f416, 0x1e824, 0x1e822, 0x1d068, 0x1e836, 0x1d064, 0x1d062, 0x1a0e8, 0x1d076, 0x1a0e4, 0x1a0e2, 0x141e8, 0x1a0f6, 0x141e4, 0x141e2, 0x1e814, 0x1e812, 0x1d034, 0x1d032, 0x1a074, 0x1a072, 0x1e540, 0x1f2b0, 0x1f95c, 0x1e520, 0x1f298, 0x1f94e, 0x1e510, 0x1f28c, 0x1e508, 0x1f286, 0x1e504, 0x1e502, 0x1cb40, 0x1e5b0, 0x1f2dc, 0x1cb20, 0x1e598, 0x1f2ce, 0x1cb10, 0x1e58c, 0x1cb08, 0x1e586, 0x1cb04, 0x1cb02, 0x19740, 0x1cbb0, 0x1e5dc, 0x19720, 0x1cb98, 0x1e5ce, 0x19710, 0x1cb8c, 0x19708, 0x1cb86, 0x19704, 0x19702, 0x12f40, 0x197b0, 0x1cbdc, 0x12f20, 0x19798, 0x1cbce, 0x12f10, 0x1978c, 0x12f08, 0x19786, 0x12f04, 0x12fb0, 0x197dc, 0x12f98, 0x197ce, 0x12f8c, 0x12f86, 0x12fdc, 0x12fce, 0x1f6a0, 0x1fb58, 0x16bf0, 0x1f690, 0x1fb4c, 0x169f8, 0x1f688, 0x1fb46, 0x168fc, 0x1f684, 0x1f682, 0x1e4a0, 0x1f258, 0x1f92e, 0x1eda0, 0x1e490, 0x1fb6e, 0x1ed90, 0x1f6cc, 0x1f246, 0x1ed88, 0x1e484, 0x1ed84, 0x1e482, 0x1ed82, 0x1c9a0, 0x1e4d8, 0x1f26e, 0x1dba0, 0x1c990, 0x1e4cc, 0x1db90, 0x1edcc, 0x1e4c6, 0x1db88, 0x1c984, 0x1db84, 0x1c982, 0x1db82, 0x193a0, 0x1c9d8, 0x1e4ee, 0x1b7a0, 0x19390, 0x1c9cc, 0x1b790, 0x1dbcc, 0x1c9c6, 0x1b788, 0x19384, 0x1b784, 0x19382, 0x1b782, 0x127a0, 0x193d8, 0x1c9ee, 0x16fa0, 0x12790, 0x193cc, 0x16f90, 0x1b7cc, 0x193c6, 0x16f88, 0x12784, 0x16f84, 0x12782, 0x127d8, 0x193ee, 0x16fd8, 0x127cc, 0x16fcc, 0x127c6, 0x16fc6, 0x127ee, 0x1f650, 0x1fb2c, 0x165f8, 0x1f648, 0x1fb26, 0x164fc, 0x1f644, 0x1647e, 0x1f642, 0x1e450, 0x1f22c, 0x1ecd0, 0x1e448, 0x1f226, 0x1ecc8, 0x1f666, 0x1ecc4, 0x1e442, 0x1ecc2, 0x1c8d0, 0x1e46c, 0x1d9d0, 0x1c8c8, 0x1e466, 0x1d9c8, 0x1ece6, 0x1d9c4, 0x1c8c2, 0x1d9c2, 0x191d0, 0x1c8ec, 0x1b3d0, 0x191c8, 0x1c8e6, 0x1b3c8, 0x1d9e6, 0x1b3c4, 0x191c2, 0x1b3c2, 0x123d0, 0x191ec, 0x167d0, 0x123c8, 0x191e6, 0x167c8, 0x1b3e6, 0x167c4, 0x123c2, 0x167c2, 0x123ec, 0x167ec, 0x123e6, 0x167e6, 0x1f628, 0x1fb16, 0x162fc, 0x1f624, 0x1627e, 0x1f622, 0x1e428, 0x1f216, 0x1ec68, 0x1f636, 0x1ec64, 0x1e422, 0x1ec62, 0x1c868, 0x1e436, 0x1d8e8, 0x1c864, 0x1d8e4, 0x1c862, 0x1d8e2, 0x190e8, 0x1c876, 0x1b1e8, 0x1d8f6, 0x1b1e4, 0x190e2, 0x1b1e2, 0x121e8, 0x190f6, 0x163e8, 0x121e4, 0x163e4, 0x121e2, 0x163e2, 0x121f6, 0x163f6, 0x1f614, 0x1617e, 0x1f612, 0x1e414, 0x1ec34, 0x1e412, 0x1ec32, 0x1c834, 0x1d874, 0x1c832, 0x1d872, 0x19074, 0x1b0f4, 0x19072, 0x1b0f2, 0x120f4, 0x161f4, 0x120f2, 0x161f2, 0x1f60a, 0x1e40a, 0x1ec1a, 0x1c81a, 0x1d83a, 0x1903a, 0x1b07a, 0x1e2a0, 0x1f158, 0x1f8ae, 0x1e290, 0x1f14c, 0x1e288, 0x1f146, 0x1e284, 0x1e282, 0x1c5a0, 0x1e2d8, 0x1f16e, 0x1c590, 0x1e2cc, 0x1c588, 0x1e2c6, 0x1c584, 0x1c582, 0x18ba0, 0x1c5d8, 0x1e2ee, 0x18b90, 0x1c5cc, 0x18b88, 0x1c5c6, 0x18b84, 0x18b82, 0x117a0, 0x18bd8, 0x1c5ee, 0x11790, 0x18bcc, 0x11788, 0x18bc6, 0x11784, 0x11782, 0x117d8, 0x18bee, 0x117cc, 0x117c6, 0x117ee, 0x1f350, 0x1f9ac, 0x135f8, 0x1f348, 0x1f9a6, 0x134fc, 0x1f344, 0x1347e, 0x1f342, 0x1e250, 0x1f12c, 0x1e6d0, 0x1e248, 0x1f126, 0x1e6c8, 0x1f366, 0x1e6c4, 0x1e242, 0x1e6c2, 0x1c4d0, 0x1e26c, 0x1cdd0, 0x1c4c8, 0x1e266, 0x1cdc8, 0x1e6e6, 0x1cdc4, 0x1c4c2, 0x1cdc2, 0x189d0, 0x1c4ec, 0x19bd0, 0x189c8, 0x1c4e6, 0x19bc8, 0x1cde6, 0x19bc4, 0x189c2, 0x19bc2, 0x113d0, 0x189ec, 0x137d0, 0x113c8, 0x189e6, 0x137c8, 0x19be6, 0x137c4, 0x113c2, 0x137c2, 0x113ec, 0x137ec, 0x113e6, 0x137e6, 0x1fba8, 0x175f0, 0x1bafc, 0x1fba4, 0x174f8, 0x1ba7e, 0x1fba2, 0x1747c, 0x1743e, 0x1f328, 0x1f996, 0x132fc, 0x1f768, 0x1fbb6, 0x176fc, 0x1327e, 0x1f764, 0x1f322, 0x1767e, 0x1f762, 0x1e228, 0x1f116, 0x1e668, 0x1e224, 0x1eee8, 0x1f776, 0x1e222, 0x1eee4, 0x1e662, 0x1eee2, 0x1c468, 0x1e236, 0x1cce8, 0x1c464, 0x1dde8, 0x1cce4, 0x1c462, 0x1dde4, 0x1cce2, 0x1dde2, 0x188e8, 0x1c476, 0x199e8, 0x188e4, 0x1bbe8, 0x199e4, 0x188e2, 0x1bbe4, 0x199e2, 0x1bbe2, 0x111e8, 0x188f6, 0x133e8, 0x111e4, 0x177e8, 0x133e4, 0x111e2, 0x177e4, 0x133e2, 0x177e2, 0x111f6, 0x133f6, 0x1fb94, 0x172f8, 0x1b97e, 0x1fb92, 0x1727c, 0x1723e, 0x1f314, 0x1317e, 0x1f734, 0x1f312, 0x1737e, 0x1f732, 0x1e214, 0x1e634, 0x1e212, 0x1ee74, 0x1e632, 0x1ee72, 0x1c434, 0x1cc74, 0x1c432, 0x1dcf4, 0x1cc72, 0x1dcf2, 0x18874, 0x198f4, 0x18872, 0x1b9f4, 0x198f2, 0x1b9f2, 0x110f4, 0x131f4, 0x110f2, 0x173f4, 0x131f2, 0x173f2, 0x1fb8a, 0x1717c, 0x1713e, 0x1f30a, 0x1f71a, 0x1e20a, 0x1e61a, 0x1ee3a, 0x1c41a, 0x1cc3a, 0x1dc7a, 0x1883a, 0x1987a, 0x1b8fa, 0x1107a, 0x130fa, 0x171fa, 0x170be, 0x1e150, 0x1f0ac, 0x1e148, 0x1f0a6, 0x1e144, 0x1e142, 0x1c2d0, 0x1e16c, 0x1c2c8, 0x1e166, 0x1c2c4, 0x1c2c2, 0x185d0, 0x1c2ec, 0x185c8, 0x1c2e6, 0x185c4, 0x185c2, 0x10bd0, 0x185ec, 0x10bc8, 0x185e6, 0x10bc4, 0x10bc2, 0x10bec, 0x10be6, 0x1f1a8, 0x1f8d6, 0x11afc, 0x1f1a4, 0x11a7e, 0x1f1a2, 0x1e128, 0x1f096, 0x1e368, 0x1e124, 0x1e364, 0x1e122, 0x1e362, 0x1c268, 0x1e136, 0x1c6e8, 0x1c264, 0x1c6e4, 0x1c262, 0x1c6e2, 0x184e8, 0x1c276, 0x18de8, 0x184e4, 0x18de4, 0x184e2, 0x18de2, 0x109e8, 0x184f6, 0x11be8, 0x109e4, 0x11be4, 0x109e2, 0x11be2, 0x109f6, 0x11bf6, 0x1f9d4, 0x13af8, 0x19d7e, 0x1f9d2, 0x13a7c, 0x13a3e, 0x1f194, 0x1197e, 0x1f3b4, 0x1f192, 0x13b7e, 0x1f3b2, 0x1e114, 0x1e334, 0x1e112, 0x1e774, 0x1e332, 0x1e772, 0x1c234, 0x1c674, 0x1c232, 0x1cef4, 0x1c672, 0x1cef2, 0x18474, 0x18cf4, 0x18472, 0x19df4, 0x18cf2, 0x19df2, 0x108f4, 0x119f4, 0x108f2, 0x13bf4, 0x119f2, 0x13bf2, 0x17af0, 0x1bd7c, 0x17a78, 0x1bd3e, 0x17a3c, 0x17a1e, 0x1f9ca, 0x1397c, 0x1fbda, 0x17b7c, 0x1393e, 0x17b3e, 0x1f18a, 0x1f39a, 0x1f7ba, 0x1e10a, 0x1e31a, 0x1e73a, 0x1ef7a, 0x1c21a, 0x1c63a, 0x1ce7a, 0x1defa, 0x1843a, 0x18c7a, 0x19cfa, 0x1bdfa, 0x1087a, 0x118fa, 0x139fa, 0x17978, 0x1bcbe, 0x1793c, 0x1791e, 0x138be, 0x179be, 0x178bc, 0x1789e, 0x1785e, 0x1e0a8, 0x1e0a4, 0x1e0a2, 0x1c168, 0x1e0b6, 0x1c164, 0x1c162, 0x182e8, 0x1c176, 0x182e4, 0x182e2, 0x105e8, 0x182f6, 0x105e4, 0x105e2, 0x105f6, 0x1f0d4, 0x10d7e, 0x1f0d2, 0x1e094, 0x1e1b4, 0x1e092, 0x1e1b2, 0x1c134, 0x1c374, 0x1c132, 0x1c372, 0x18274, 0x186f4, 0x18272, 0x186f2, 0x104f4, 0x10df4, 0x104f2, 0x10df2, 0x1f8ea, 0x11d7c, 0x11d3e, 0x1f0ca, 0x1f1da, 0x1e08a, 0x1e19a, 0x1e3ba, 0x1c11a, 0x1c33a, 0x1c77a, 0x1823a, 0x1867a, 0x18efa, 0x1047a, 0x10cfa, 0x11dfa, 0x13d78, 0x19ebe, 0x13d3c, 0x13d1e, 0x11cbe, 0x13dbe, 0x17d70, 0x1bebc, 0x17d38, 0x1be9e, 0x17d1c, 0x17d0e, 0x13cbc, 0x17dbc, 0x13c9e, 0x17d9e, 0x17cb8, 0x1be5e, 0x17c9c, 0x17c8e, 0x13c5e, 0x17cde, 0x17c5c, 0x17c4e, 0x17c2e, 0x1c0b4, 0x1c0b2, 0x18174, 0x18172, 0x102f4, 0x102f2, 0x1e0da, 0x1c09a, 0x1c1ba, 0x1813a, 0x1837a, 0x1027a, 0x106fa, 0x10ebe, 0x11ebc, 0x11e9e, 0x13eb8, 0x19f5e, 0x13e9c, 0x13e8e, 0x11e5e, 0x13ede, 0x17eb0, 0x1bf5c, 0x17e98, 0x1bf4e, 0x17e8c, 0x17e86, 0x13e5c, 0x17edc, 0x13e4e, 0x17ece, 0x17e58, 0x1bf2e, 0x17e4c, 0x17e46, 0x13e2e, 0x17e6e, 0x17e2c, 0x17e26, 0x10f5e, 0x11f5c, 0x11f4e, 0x13f58, 0x19fae, 0x13f4c, 0x13f46, 0x11f2e, 0x13f6e, 0x13f2c, 0x13f26, ] -, vec![0x1abe0, 0x1d5f8, 0x153c0, 0x1a9f0, 0x1d4fc, 0x151e0, 0x1a8f8, 0x1d47e, 0x150f0, 0x1a87c, 0x15078, 0x1fad0, 0x15be0, 0x1adf8, 0x1fac8, 0x159f0, 0x1acfc, 0x1fac4, 0x158f8, 0x1ac7e, 0x1fac2, 0x1587c, 0x1f5d0, 0x1faec, 0x15df8, 0x1f5c8, 0x1fae6, 0x15cfc, 0x1f5c4, 0x15c7e, 0x1f5c2, 0x1ebd0, 0x1f5ec, 0x1ebc8, 0x1f5e6, 0x1ebc4, 0x1ebc2, 0x1d7d0, 0x1ebec, 0x1d7c8, 0x1ebe6, 0x1d7c4, 0x1d7c2, 0x1afd0, 0x1d7ec, 0x1afc8, 0x1d7e6, 0x1afc4, 0x14bc0, 0x1a5f0, 0x1d2fc, 0x149e0, 0x1a4f8, 0x1d27e, 0x148f0, 0x1a47c, 0x14878, 0x1a43e, 0x1483c, 0x1fa68, 0x14df0, 0x1a6fc, 0x1fa64, 0x14cf8, 0x1a67e, 0x1fa62, 0x14c7c, 0x14c3e, 0x1f4e8, 0x1fa76, 0x14efc, 0x1f4e4, 0x14e7e, 0x1f4e2, 0x1e9e8, 0x1f4f6, 0x1e9e4, 0x1e9e2, 0x1d3e8, 0x1e9f6, 0x1d3e4, 0x1d3e2, 0x1a7e8, 0x1d3f6, 0x1a7e4, 0x1a7e2, 0x145e0, 0x1a2f8, 0x1d17e, 0x144f0, 0x1a27c, 0x14478, 0x1a23e, 0x1443c, 0x1441e, 0x1fa34, 0x146f8, 0x1a37e, 0x1fa32, 0x1467c, 0x1463e, 0x1f474, 0x1477e, 0x1f472, 0x1e8f4, 0x1e8f2, 0x1d1f4, 0x1d1f2, 0x1a3f4, 0x1a3f2, 0x142f0, 0x1a17c, 0x14278, 0x1a13e, 0x1423c, 0x1421e, 0x1fa1a, 0x1437c, 0x1433e, 0x1f43a, 0x1e87a, 0x1d0fa, 0x14178, 0x1a0be, 0x1413c, 0x1411e, 0x141be, 0x140bc, 0x1409e, 0x12bc0, 0x195f0, 0x1cafc, 0x129e0, 0x194f8, 0x1ca7e, 0x128f0, 0x1947c, 0x12878, 0x1943e, 0x1283c, 0x1f968, 0x12df0, 0x196fc, 0x1f964, 0x12cf8, 0x1967e, 0x1f962, 0x12c7c, 0x12c3e, 0x1f2e8, 0x1f976, 0x12efc, 0x1f2e4, 0x12e7e, 0x1f2e2, 0x1e5e8, 0x1f2f6, 0x1e5e4, 0x1e5e2, 0x1cbe8, 0x1e5f6, 0x1cbe4, 0x1cbe2, 0x197e8, 0x1cbf6, 0x197e4, 0x197e2, 0x1b5e0, 0x1daf8, 0x1ed7e, 0x169c0, 0x1b4f0, 0x1da7c, 0x168e0, 0x1b478, 0x1da3e, 0x16870, 0x1b43c, 0x16838, 0x1b41e, 0x1681c, 0x125e0, 0x192f8, 0x1c97e, 0x16de0, 0x124f0, 0x1927c, 0x16cf0, 0x1b67c, 0x1923e, 0x16c78, 0x1243c, 0x16c3c, 0x1241e, 0x16c1e, 0x1f934, 0x126f8, 0x1937e, 0x1fb74, 0x1f932, 0x16ef8, 0x1267c, 0x1fb72, 0x16e7c, 0x1263e, 0x16e3e, 0x1f274, 0x1277e, 0x1f6f4, 0x1f272, 0x16f7e, 0x1f6f2, 0x1e4f4, 0x1edf4, 0x1e4f2, 0x1edf2, 0x1c9f4, 0x1dbf4, 0x1c9f2, 0x1dbf2, 0x193f4, 0x193f2, 0x165c0, 0x1b2f0, 0x1d97c, 0x164e0, 0x1b278, 0x1d93e, 0x16470, 0x1b23c, 0x16438, 0x1b21e, 0x1641c, 0x1640e, 0x122f0, 0x1917c, 0x166f0, 0x12278, 0x1913e, 0x16678, 0x1b33e, 0x1663c, 0x1221e, 0x1661e, 0x1f91a, 0x1237c, 0x1fb3a, 0x1677c, 0x1233e, 0x1673e, 0x1f23a, 0x1f67a, 0x1e47a, 0x1ecfa, 0x1c8fa, 0x1d9fa, 0x191fa, 0x162e0, 0x1b178, 0x1d8be, 0x16270, 0x1b13c, 0x16238, 0x1b11e, 0x1621c, 0x1620e, 0x12178, 0x190be, 0x16378, 0x1213c, 0x1633c, 0x1211e, 0x1631e, 0x121be, 0x163be, 0x16170, 0x1b0bc, 0x16138, 0x1b09e, 0x1611c, 0x1610e, 0x120bc, 0x161bc, 0x1209e, 0x1619e, 0x160b8, 0x1b05e, 0x1609c, 0x1608e, 0x1205e, 0x160de, 0x1605c, 0x1604e, 0x115e0, 0x18af8, 0x1c57e, 0x114f0, 0x18a7c, 0x11478, 0x18a3e, 0x1143c, 0x1141e, 0x1f8b4, 0x116f8, 0x18b7e, 0x1f8b2, 0x1167c, 0x1163e, 0x1f174, 0x1177e, 0x1f172, 0x1e2f4, 0x1e2f2, 0x1c5f4, 0x1c5f2, 0x18bf4, 0x18bf2, 0x135c0, 0x19af0, 0x1cd7c, 0x134e0, 0x19a78, 0x1cd3e, 0x13470, 0x19a3c, 0x13438, 0x19a1e, 0x1341c, 0x1340e, 0x112f0, 0x1897c, 0x136f0, 0x11278, 0x1893e, 0x13678, 0x19b3e, 0x1363c, 0x1121e, 0x1361e, 0x1f89a, 0x1137c, 0x1f9ba, 0x1377c, 0x1133e, 0x1373e, 0x1f13a, 0x1f37a, 0x1e27a, 0x1e6fa, 0x1c4fa, 0x1cdfa, 0x189fa, 0x1bae0, 0x1dd78, 0x1eebe, 0x174c0, 0x1ba70, 0x1dd3c, 0x17460, 0x1ba38, 0x1dd1e, 0x17430, 0x1ba1c, 0x17418, 0x1ba0e, 0x1740c, 0x132e0, 0x19978, 0x1ccbe, 0x176e0, 0x13270, 0x1993c, 0x17670, 0x1bb3c, 0x1991e, 0x17638, 0x1321c, 0x1761c, 0x1320e, 0x1760e, 0x11178, 0x188be, 0x13378, 0x1113c, 0x17778, 0x1333c, 0x1111e, 0x1773c, 0x1331e, 0x1771e, 0x111be, 0x133be, 0x177be, 0x172c0, 0x1b970, 0x1dcbc, 0x17260, 0x1b938, 0x1dc9e, 0x17230, 0x1b91c, 0x17218, 0x1b90e, 0x1720c, 0x17206, 0x13170, 0x198bc, 0x17370, 0x13138, 0x1989e, 0x17338, 0x1b99e, 0x1731c, 0x1310e, 0x1730e, 0x110bc, 0x131bc, 0x1109e, 0x173bc, 0x1319e, 0x1739e, 0x17160, 0x1b8b8, 0x1dc5e, 0x17130, 0x1b89c, 0x17118, 0x1b88e, 0x1710c, 0x17106, 0x130b8, 0x1985e, 0x171b8, 0x1309c, 0x1719c, 0x1308e, 0x1718e, 0x1105e, 0x130de, 0x171de, 0x170b0, 0x1b85c, 0x17098, 0x1b84e, 0x1708c, 0x17086, 0x1305c, 0x170dc, 0x1304e, 0x170ce, 0x17058, 0x1b82e, 0x1704c, 0x17046, 0x1302e, 0x1706e, 0x1702c, 0x17026, 0x10af0, 0x1857c, 0x10a78, 0x1853e, 0x10a3c, 0x10a1e, 0x10b7c, 0x10b3e, 0x1f0ba, 0x1e17a, 0x1c2fa, 0x185fa, 0x11ae0, 0x18d78, 0x1c6be, 0x11a70, 0x18d3c, 0x11a38, 0x18d1e, 0x11a1c, 0x11a0e, 0x10978, 0x184be, 0x11b78, 0x1093c, 0x11b3c, 0x1091e, 0x11b1e, 0x109be, 0x11bbe, 0x13ac0, 0x19d70, 0x1cebc, 0x13a60, 0x19d38, 0x1ce9e, 0x13a30, 0x19d1c, 0x13a18, 0x19d0e, 0x13a0c, 0x13a06, 0x11970, 0x18cbc, 0x13b70, 0x11938, 0x18c9e, 0x13b38, 0x1191c, 0x13b1c, 0x1190e, 0x13b0e, 0x108bc, 0x119bc, 0x1089e, 0x13bbc, 0x1199e, 0x13b9e, 0x1bd60, 0x1deb8, 0x1ef5e, 0x17a40, 0x1bd30, 0x1de9c, 0x17a20, 0x1bd18, 0x1de8e, 0x17a10, 0x1bd0c, 0x17a08, 0x1bd06, 0x17a04, 0x13960, 0x19cb8, 0x1ce5e, 0x17b60, 0x13930, 0x19c9c, 0x17b30, 0x1bd9c, 0x19c8e, 0x17b18, 0x1390c, 0x17b0c, 0x13906, 0x17b06, 0x118b8, 0x18c5e, 0x139b8, 0x1189c, 0x17bb8, 0x1399c, 0x1188e, 0x17b9c, 0x1398e, 0x17b8e, 0x1085e, 0x118de, 0x139de, 0x17bde, 0x17940, 0x1bcb0, 0x1de5c, 0x17920, 0x1bc98, 0x1de4e, 0x17910, 0x1bc8c, 0x17908, 0x1bc86, 0x17904, 0x17902, 0x138b0, 0x19c5c, 0x179b0, 0x13898, 0x19c4e, 0x17998, 0x1bcce, 0x1798c, 0x13886, 0x17986, 0x1185c, 0x138dc, 0x1184e, 0x179dc, 0x138ce, 0x179ce, 0x178a0, 0x1bc58, 0x1de2e, 0x17890, 0x1bc4c, 0x17888, 0x1bc46, 0x17884, 0x17882, 0x13858, 0x19c2e, 0x178d8, 0x1384c, 0x178cc, 0x13846, 0x178c6, 0x1182e, 0x1386e, 0x178ee, 0x17850, 0x1bc2c, 0x17848, 0x1bc26, 0x17844, 0x17842, 0x1382c, 0x1786c, 0x13826, 0x17866, 0x17828, 0x1bc16, 0x17824, 0x17822, 0x13816, 0x17836, 0x10578, 0x182be, 0x1053c, 0x1051e, 0x105be, 0x10d70, 0x186bc, 0x10d38, 0x1869e, 0x10d1c, 0x10d0e, 0x104bc, 0x10dbc, 0x1049e, 0x10d9e, 0x11d60, 0x18eb8, 0x1c75e, 0x11d30, 0x18e9c, 0x11d18, 0x18e8e, 0x11d0c, 0x11d06, 0x10cb8, 0x1865e, 0x11db8, 0x10c9c, 0x11d9c, 0x10c8e, 0x11d8e, 0x1045e, 0x10cde, 0x11dde, 0x13d40, 0x19eb0, 0x1cf5c, 0x13d20, 0x19e98, 0x1cf4e, 0x13d10, 0x19e8c, 0x13d08, 0x19e86, 0x13d04, 0x13d02, 0x11cb0, 0x18e5c, 0x13db0, 0x11c98, 0x18e4e, 0x13d98, 0x19ece, 0x13d8c, 0x11c86, 0x13d86, 0x10c5c, 0x11cdc, 0x10c4e, 0x13ddc, 0x11cce, 0x13dce, 0x1bea0, 0x1df58, 0x1efae, 0x1be90, 0x1df4c, 0x1be88, 0x1df46, 0x1be84, 0x1be82, 0x13ca0, 0x19e58, 0x1cf2e, 0x17da0, 0x13c90, 0x19e4c, 0x17d90, 0x1becc, 0x19e46, 0x17d88, 0x13c84, 0x17d84, 0x13c82, 0x17d82, 0x11c58, 0x18e2e, 0x13cd8, 0x11c4c, 0x17dd8, 0x13ccc, 0x11c46, 0x17dcc, 0x13cc6, 0x17dc6, 0x10c2e, 0x11c6e, 0x13cee, 0x17dee, 0x1be50, 0x1df2c, 0x1be48, 0x1df26, 0x1be44, 0x1be42, 0x13c50, 0x19e2c, 0x17cd0, 0x13c48, 0x19e26, 0x17cc8, 0x1be66, 0x17cc4, 0x13c42, 0x17cc2, 0x11c2c, 0x13c6c, 0x11c26, 0x17cec, 0x13c66, 0x17ce6, 0x1be28, 0x1df16, 0x1be24, 0x1be22, 0x13c28, 0x19e16, 0x17c68, 0x13c24, 0x17c64, 0x13c22, 0x17c62, 0x11c16, 0x13c36, 0x17c76, 0x1be14, 0x1be12, 0x13c14, 0x17c34, 0x13c12, 0x17c32, 0x102bc, 0x1029e, 0x106b8, 0x1835e, 0x1069c, 0x1068e, 0x1025e, 0x106de, 0x10eb0, 0x1875c, 0x10e98, 0x1874e, 0x10e8c, 0x10e86, 0x1065c, 0x10edc, 0x1064e, 0x10ece, 0x11ea0, 0x18f58, 0x1c7ae, 0x11e90, 0x18f4c, 0x11e88, 0x18f46, 0x11e84, 0x11e82, 0x10e58, 0x1872e, 0x11ed8, 0x18f6e, 0x11ecc, 0x10e46, 0x11ec6, 0x1062e, 0x10e6e, 0x11eee, 0x19f50, 0x1cfac, 0x19f48, 0x1cfa6, 0x19f44, 0x19f42, 0x11e50, 0x18f2c, 0x13ed0, 0x19f6c, 0x18f26, 0x13ec8, 0x11e44, 0x13ec4, 0x11e42, 0x13ec2, 0x10e2c, 0x11e6c, 0x10e26, 0x13eec, 0x11e66, 0x13ee6, 0x1dfa8, 0x1efd6, 0x1dfa4, 0x1dfa2, 0x19f28, 0x1cf96, 0x1bf68, 0x19f24, 0x1bf64, 0x19f22, 0x1bf62, 0x11e28, 0x18f16, 0x13e68, 0x11e24, 0x17ee8, 0x13e64, 0x11e22, 0x17ee4, 0x13e62, 0x17ee2, 0x10e16, 0x11e36, 0x13e76, 0x17ef6, 0x1df94, 0x1df92, 0x19f14, 0x1bf34, 0x19f12, 0x1bf32, 0x11e14, 0x13e34, 0x11e12, 0x17e74, 0x13e32, 0x17e72, 0x1df8a, 0x19f0a, 0x1bf1a, 0x11e0a, 0x13e1a, 0x17e3a, 0x1035c, 0x1034e, 0x10758, 0x183ae, 0x1074c, 0x10746, 0x1032e, 0x1076e, 0x10f50, 0x187ac, 0x10f48, 0x187a6, 0x10f44, 0x10f42, 0x1072c, 0x10f6c, 0x10726, 0x10f66, 0x18fa8, 0x1c7d6, 0x18fa4, 0x18fa2, 0x10f28, 0x18796, 0x11f68, 0x18fb6, 0x11f64, 0x10f22, 0x11f62, 0x10716, 0x10f36, 0x11f76, 0x1cfd4, 0x1cfd2, 0x18f94, 0x19fb4, 0x18f92, 0x19fb2, 0x10f14, 0x11f34, 0x10f12, 0x13f74, 0x11f32, 0x13f72, 0x1cfca, 0x18f8a, 0x19f9a, 0x10f0a, 0x11f1a, 0x13f3a, 0x103ac, 0x103a6, 0x107a8, 0x183d6, 0x107a4, 0x107a2, 0x10396, 0x107b6, 0x187d4, 0x187d2, 0x10794, 0x10fb4, 0x10792, 0x10fb2, 0x1c7ea, ] -, ] -; - - const PREFERRED_RATIO: f32 = 3.0f; - -//1px in mm - const DEFAULT_MODULE_WIDTH: f32 = 0.357f; - -//mm - const HEIGHT: f32 = 2.0f; -pub struct PDF417 { - - let barcode_matrix: BarcodeMatrix; - - let compact: bool; - - let mut compaction: Compaction; - - let mut encoding: Charset; - - let min_cols: i32; - - let max_cols: i32; - - let max_rows: i32; - - let min_rows: i32; -} - -impl PDF417 { - - pub fn new() -> PDF417 { - this(false); - } - - pub fn new( compact: bool) -> PDF417 { - let .compact = compact; - compaction = Compaction::AUTO; - // Use default - encoding = null; - min_cols = 2; - max_cols = 30; - max_rows = 30; - min_rows = 2; - } - - pub fn get_barcode_matrix(&self) -> BarcodeMatrix { - return self.barcode_matrix; - } - - /** - * Calculates the necessary number of rows as described in annex Q of ISO/IEC 15438:2001(E). - * - * @param m the number of source codewords prior to the additional of the Symbol Length - * Descriptor and any pad codewords - * @param k the number of error correction codewords - * @param c the number of columns in the symbol in the data region (excluding start, stop and - * row indicator codewords) - * @return the number of rows in the symbol (r) - */ - fn calculate_number_of_rows( m: i32, k: i32, c: i32) -> i32 { - let mut r: i32 = ((m + 1 + k) / c) + 1; - if c * r >= (m + 1 + k + c) { - r -= 1; - } - return r; - } - - /** - * Calculates the number of pad codewords as described in 4.9.2 of ISO/IEC 15438:2001(E). - * - * @param m the number of source codewords prior to the additional of the Symbol Length - * Descriptor and any pad codewords - * @param k the number of error correction codewords - * @param c the number of columns in the symbol in the data region (excluding start, stop and - * row indicator codewords) - * @param r the number of rows in the symbol - * @return the number of pad codewords - */ - fn get_number_of_pad_codewords( m: i32, k: i32, c: i32, r: i32) -> i32 { - let n: i32 = c * r - k; - return if n > m + 1 { n - m - 1 } else { 0 }; - } - - fn encode_char( pattern: i32, len: i32, logic: &BarcodeRow) { - let mut map: i32 = 1 << len - 1; - //Initialize to inverse of first bit - let mut last: bool = (pattern & map) != 0; - let mut width: i32 = 0; - { - let mut i: i32 = 0; - while i < len { - { - let black: bool = (pattern & map) != 0; - if last == black { - width += 1; - } else { - logic.add_bar(last, width); - last = black; - width = 1; - } - map >>= 1; - } - i += 1; - } - } - - logic.add_bar(last, width); - } - - fn encode_low_level(&self, full_codewords: &CharSequence, c: i32, r: i32, error_correction_level: i32, logic: &BarcodeMatrix) { - let mut idx: i32 = 0; - { - let mut y: i32 = 0; - while y < r { - { - let cluster: i32 = y % 3; - logic.start_row(); - ::encode_char(START_PATTERN, 17, &logic.get_current_row()); - let mut left: i32; - let mut right: i32; - if cluster == 0 { - left = (30 * (y / 3)) + ((r - 1) / 3); - right = (30 * (y / 3)) + (c - 1); - } else if cluster == 1 { - left = (30 * (y / 3)) + (error_correction_level * 3) + ((r - 1) % 3); - right = (30 * (y / 3)) + ((r - 1) / 3); - } else { - left = (30 * (y / 3)) + (c - 1); - right = (30 * (y / 3)) + (error_correction_level * 3) + ((r - 1) % 3); - } - let mut pattern: i32 = CODEWORD_TABLE[cluster][left]; - ::encode_char(pattern, 17, &logic.get_current_row()); - { - let mut x: i32 = 0; - while x < c { - { - pattern = CODEWORD_TABLE[cluster][full_codewords.char_at(idx)]; - ::encode_char(pattern, 17, &logic.get_current_row()); - idx += 1; - } - x += 1; - } - } - - if self.compact { - // encodes stop line for compact pdf417 - ::encode_char(STOP_PATTERN, 1, &logic.get_current_row()); - } else { - pattern = CODEWORD_TABLE[cluster][right]; - ::encode_char(pattern, 17, &logic.get_current_row()); - ::encode_char(STOP_PATTERN, 18, &logic.get_current_row()); - } - } - y += 1; - } - } - - } - - /** - * @param msg message to encode - * @param errorCorrectionLevel PDF417 error correction level to use - * @throws WriterException if the contents cannot be encoded in this format - */ - pub fn generate_barcode_logic(&self, msg: &String, error_correction_level: i32) -> /* throws WriterException */Result> { - self.generate_barcode_logic(&msg, error_correction_level, false); - } - - /** - * @param msg message to encode - * @param errorCorrectionLevel PDF417 error correction level to use - * @param autoECI automatically insert ECIs if needed - * @throws WriterException if the contents cannot be encoded in this format - */ - pub fn generate_barcode_logic(&self, msg: &String, error_correction_level: i32, auto_e_c_i: bool) -> /* throws WriterException */Result> { - //1. step: High-level encoding - let error_correction_code_words: i32 = PDF417ErrorCorrection::get_error_correction_codeword_count(error_correction_level); - let high_level: String = PDF417HighLevelEncoder::encode_high_level(&msg, self.compaction, &self.encoding, auto_e_c_i); - let source_code_words: i32 = high_level.length(); - let dimension: Vec = self.determine_dimensions(source_code_words, error_correction_code_words); - let cols: i32 = dimension[0]; - let rows: i32 = dimension[1]; - let pad: i32 = ::get_number_of_pad_codewords(source_code_words, error_correction_code_words, cols, rows); - //2. step: construct data codewords - if source_code_words + error_correction_code_words + 1 > 929 { - // +1 for symbol length CW - throw WriterException::new(format!("Encoded message contains too many code words, message too big ({} bytes)", msg.length())); - } - let n: i32 = source_code_words + pad + 1; - let sb: StringBuilder = StringBuilder::new(n); - sb.append(n as char); - sb.append(&high_level); - { - let mut i: i32 = 0; - while i < pad { - { - //PAD characters - sb.append(900 as char); - } - i += 1; - } - } - - let data_codewords: String = sb.to_string(); - //3. step: Error correction - let ec: String = PDF417ErrorCorrection::generate_error_correction(&data_codewords, error_correction_level); - //4. step: low-level encoding - self.barcode_matrix = BarcodeMatrix::new(rows, cols); - self.encode_low_level(format!("{}{}", data_codewords, ec), cols, rows, error_correction_level, self.barcode_matrix); - } - - /** - * Determine optimal nr of columns and rows for the specified number of - * codewords. - * - * @param sourceCodeWords number of code words - * @param errorCorrectionCodeWords number of error correction code words - * @return dimension object containing cols as width and rows as height - */ - fn determine_dimensions(&self, source_code_words: i32, error_correction_code_words: i32) -> /* throws WriterException */Result, Rc> { - let mut ratio: f32 = 0.0f; - let mut dimension: Vec = null; - { - let mut cols: i32 = self.min_cols; - while cols <= self.max_cols { - { - let rows: i32 = ::calculate_number_of_rows(source_code_words, error_correction_code_words, cols); - if rows < self.min_rows { - break; - } - if rows > self.max_rows { - continue; - } - let new_ratio: f32 = ((17.0 * cols + 69.0) as f32 * DEFAULT_MODULE_WIDTH) / (rows * HEIGHT); - // ignore if previous ratio is closer to preferred ratio - if dimension != null && Math::abs(new_ratio - PREFERRED_RATIO) > Math::abs(ratio - PREFERRED_RATIO) { - continue; - } - ratio = new_ratio; - dimension = : vec![i32; 2] = vec![cols, rows, ] - ; - } - cols += 1; - } - } - - // Handle case when min values were larger than necessary - if dimension == null { - let rows: i32 = ::calculate_number_of_rows(source_code_words, error_correction_code_words, self.min_cols); - if rows < self.min_rows { - dimension = : vec![i32; 2] = vec![self.min_cols, self.min_rows, ] - ; - } - } - if dimension == null { - throw WriterException::new("Unable to fit message in columns"); - } - return Ok(dimension); - } - - /** - * Sets max/min row/col values - * - * @param maxCols maximum allowed columns - * @param minCols minimum allowed columns - * @param maxRows maximum allowed rows - * @param minRows minimum allowed rows - */ - pub fn set_dimensions(&self, max_cols: i32, min_cols: i32, max_rows: i32, min_rows: i32) { - self.maxCols = max_cols; - self.minCols = min_cols; - self.maxRows = max_rows; - self.minRows = min_rows; - } - - /** - * @param compaction compaction mode to use - */ - pub fn set_compaction(&self, compaction: &Compaction) { - self.compaction = compaction; - } - - /** - * @param compact if true, enables compaction - */ - pub fn set_compact(&self, compact: bool) { - self.compact = compact; - } - - /** - * @param encoding sets character encoding to use - */ - pub fn set_encoding(&self, encoding: &Charset) { - self.encoding = encoding; - } -} - diff --git a/port_src/output/zxing/pdf417/encoder/p_d_f417_error_correction.rs b/port_src/output/zxing/pdf417/encoder/p_d_f417_error_correction.rs deleted file mode 100644 index 6cbda7f..0000000 --- a/port_src/output/zxing/pdf417/encoder/p_d_f417_error_correction.rs +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part - * - * 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::pdf417::encoder; - -/** - * PDF417 error correction code following the algorithm described in ISO/IEC 15438:2001(E) in - * chapter 4.10. - */ - -/** - * Tables of coefficients for calculating error correction words - * (see annex F, ISO/IEC 15438:2001(E)) - */ - const EC_COEFFICIENTS: vec![vec![Vec>; 512]; 9] = vec![vec![27, 917, ] -, vec![522, 568, 723, 809, ] -, vec![237, 308, 436, 284, 646, 653, 428, 379, ] -, vec![274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, 42, 176, 65, ] -, vec![361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410, ] -, vec![539, 422, 6, 93, 862, 771, 453, 106, 610, 287, 107, 505, 733, 877, 381, 612, 723, 476, 462, 172, 430, 609, 858, 822, 543, 376, 511, 400, 672, 762, 283, 184, 440, 35, 519, 31, 460, 594, 225, 535, 517, 352, 605, 158, 651, 201, 488, 502, 648, 733, 717, 83, 404, 97, 280, 771, 840, 629, 4, 381, 843, 623, 264, 543, ] -, vec![521, 310, 864, 547, 858, 580, 296, 379, 53, 779, 897, 444, 400, 925, 749, 415, 822, 93, 217, 208, 928, 244, 583, 620, 246, 148, 447, 631, 292, 908, 490, 704, 516, 258, 457, 907, 594, 723, 674, 292, 272, 96, 684, 432, 686, 606, 860, 569, 193, 219, 129, 186, 236, 287, 192, 775, 278, 173, 40, 379, 712, 463, 646, 776, 171, 491, 297, 763, 156, 732, 95, 270, 447, 90, 507, 48, 228, 821, 808, 898, 784, 663, 627, 378, 382, 262, 380, 602, 754, 336, 89, 614, 87, 432, 670, 616, 157, 374, 242, 726, 600, 269, 375, 898, 845, 454, 354, 130, 814, 587, 804, 34, 211, 330, 539, 297, 827, 865, 37, 517, 834, 315, 550, 86, 801, 4, 108, 539, ] -, vec![524, 894, 75, 766, 882, 857, 74, 204, 82, 586, 708, 250, 905, 786, 138, 720, 858, 194, 311, 913, 275, 190, 375, 850, 438, 733, 194, 280, 201, 280, 828, 757, 710, 814, 919, 89, 68, 569, 11, 204, 796, 605, 540, 913, 801, 700, 799, 137, 439, 418, 592, 668, 353, 859, 370, 694, 325, 240, 216, 257, 284, 549, 209, 884, 315, 70, 329, 793, 490, 274, 877, 162, 749, 812, 684, 461, 334, 376, 849, 521, 307, 291, 803, 712, 19, 358, 399, 908, 103, 511, 51, 8, 517, 225, 289, 470, 637, 731, 66, 255, 917, 269, 463, 830, 730, 433, 848, 585, 136, 538, 906, 90, 2, 290, 743, 199, 655, 903, 329, 49, 802, 580, 355, 588, 188, 462, 10, 134, 628, 320, 479, 130, 739, 71, 263, 318, 374, 601, 192, 605, 142, 673, 687, 234, 722, 384, 177, 752, 607, 640, 455, 193, 689, 707, 805, 641, 48, 60, 732, 621, 895, 544, 261, 852, 655, 309, 697, 755, 756, 60, 231, 773, 434, 421, 726, 528, 503, 118, 49, 795, 32, 144, 500, 238, 836, 394, 280, 566, 319, 9, 647, 550, 73, 914, 342, 126, 32, 681, 331, 792, 620, 60, 609, 441, 180, 791, 893, 754, 605, 383, 228, 749, 760, 213, 54, 297, 134, 54, 834, 299, 922, 191, 910, 532, 609, 829, 189, 20, 167, 29, 872, 449, 83, 402, 41, 656, 505, 579, 481, 173, 404, 251, 688, 95, 497, 555, 642, 543, 307, 159, 924, 558, 648, 55, 497, 10, ] -, vec![352, 77, 373, 504, 35, 599, 428, 207, 409, 574, 118, 498, 285, 380, 350, 492, 197, 265, 920, 155, 914, 299, 229, 643, 294, 871, 306, 88, 87, 193, 352, 781, 846, 75, 327, 520, 435, 543, 203, 666, 249, 346, 781, 621, 640, 268, 794, 534, 539, 781, 408, 390, 644, 102, 476, 499, 290, 632, 545, 37, 858, 916, 552, 41, 542, 289, 122, 272, 383, 800, 485, 98, 752, 472, 761, 107, 784, 860, 658, 741, 290, 204, 681, 407, 855, 85, 99, 62, 482, 180, 20, 297, 451, 593, 913, 142, 808, 684, 287, 536, 561, 76, 653, 899, 729, 567, 744, 390, 513, 192, 516, 258, 240, 518, 794, 395, 768, 848, 51, 610, 384, 168, 190, 826, 328, 596, 786, 303, 570, 381, 415, 641, 156, 237, 151, 429, 531, 207, 676, 710, 89, 168, 304, 402, 40, 708, 575, 162, 864, 229, 65, 861, 841, 512, 164, 477, 221, 92, 358, 785, 288, 357, 850, 836, 827, 736, 707, 94, 8, 494, 114, 521, 2, 499, 851, 543, 152, 729, 771, 95, 248, 361, 578, 323, 856, 797, 289, 51, 684, 466, 533, 820, 669, 45, 902, 452, 167, 342, 244, 173, 35, 463, 651, 51, 699, 591, 452, 578, 37, 124, 298, 332, 552, 43, 427, 119, 662, 777, 475, 850, 764, 364, 578, 911, 283, 711, 472, 420, 245, 288, 594, 394, 511, 327, 589, 777, 699, 688, 43, 408, 842, 383, 721, 521, 560, 644, 714, 559, 62, 145, 873, 663, 713, 159, 672, 729, 624, 59, 193, 417, 158, 209, 563, 564, 343, 693, 109, 608, 563, 365, 181, 772, 677, 310, 248, 353, 708, 410, 579, 870, 617, 841, 632, 860, 289, 536, 35, 777, 618, 586, 424, 833, 77, 597, 346, 269, 757, 632, 695, 751, 331, 247, 184, 45, 787, 680, 18, 66, 407, 369, 54, 492, 228, 613, 830, 922, 437, 519, 644, 905, 789, 420, 305, 441, 207, 300, 892, 827, 141, 537, 381, 662, 513, 56, 252, 341, 242, 797, 838, 837, 720, 224, 307, 631, 61, 87, 560, 310, 756, 665, 397, 808, 851, 309, 473, 795, 378, 31, 647, 915, 459, 806, 590, 731, 425, 216, 548, 249, 321, 881, 699, 535, 673, 782, 210, 815, 905, 303, 843, 922, 281, 73, 469, 791, 660, 162, 498, 308, 155, 422, 907, 817, 187, 62, 16, 425, 535, 336, 286, 437, 375, 273, 610, 296, 183, 923, 116, 667, 751, 353, 62, 366, 691, 379, 687, 842, 37, 357, 720, 742, 330, 5, 39, 923, 311, 424, 242, 749, 321, 54, 669, 316, 342, 299, 534, 105, 667, 488, 640, 672, 576, 540, 316, 486, 721, 610, 46, 656, 447, 171, 616, 464, 190, 531, 297, 321, 762, 752, 533, 175, 134, 14, 381, 433, 717, 45, 111, 20, 596, 284, 736, 138, 646, 411, 877, 669, 141, 919, 45, 780, 407, 164, 332, 899, 165, 726, 600, 325, 498, 655, 357, 752, 768, 223, 849, 647, 63, 310, 863, 251, 366, 304, 282, 738, 675, 410, 389, 244, 31, 121, 303, 263, ] -, ] -; -struct PDF417ErrorCorrection { -} - -impl PDF417ErrorCorrection { - - fn new() -> PDF417ErrorCorrection { - } - - /** - * Determines the number of error correction codewords for a specified error correction - * level. - * - * @param errorCorrectionLevel the error correction level (0-8) - * @return the number of codewords generated for error correction - */ - fn get_error_correction_codeword_count( error_correction_level: i32) -> i32 { - if error_correction_level < 0 || error_correction_level > 8 { - throw IllegalArgumentException::new("Error correction level must be between 0 and 8!"); - } - return 1 << (error_correction_level + 1); - } - - /** - * Returns the recommended minimum error correction level as described in annex E of - * ISO/IEC 15438:2001(E). - * - * @param n the number of data codewords - * @return the recommended minimum error correction level - */ - fn get_recommended_minimum_error_correction_level( n: i32) -> /* throws WriterException */Result> { - if n <= 0 { - throw IllegalArgumentException::new("n must be > 0"); - } - if n <= 40 { - return Ok(2); - } - if n <= 160 { - return Ok(3); - } - if n <= 320 { - return Ok(4); - } - if n <= 863 { - return Ok(5); - } - throw WriterException::new("No recommendation possible"); - } - - /** - * Generates the error correction codewords according to 4.10 in ISO/IEC 15438:2001(E). - * - * @param dataCodewords the data codewords - * @param errorCorrectionLevel the error correction level (0-8) - * @return the String representing the error correction codewords - */ - fn generate_error_correction( data_codewords: &CharSequence, error_correction_level: i32) -> String { - let k: i32 = ::get_error_correction_codeword_count(error_correction_level); - let mut e: [Option; k] = [None; k]; - let sld: i32 = data_codewords.length(); - { - let mut i: i32 = 0; - while i < sld { - { - let t1: i32 = (data_codewords.char_at(i) + e[e.len() - 1]) % 929; - let mut t2: i32; - let mut t3: i32; - { - let mut j: i32 = k - 1; - while j >= 1 { - { - t2 = (t1 * EC_COEFFICIENTS[error_correction_level][j]) % 929; - t3 = 929 - t2; - e[j] = ((e[j - 1] + t3) % 929) as char; - } - j -= 1; - } - } - - t2 = (t1 * EC_COEFFICIENTS[error_correction_level][0]) % 929; - t3 = 929 - t2; - e[0] = (t3 % 929) as char; - } - i += 1; - } - } - - let sb: StringBuilder = StringBuilder::new(k); - { - let mut j: i32 = k - 1; - while j >= 0 { - { - if e[j] != 0 { - e[j] = (929 - e[j]) as char; - } - sb.append(e[j]); - } - j -= 1; - } - } - - return sb.to_string(); - } -} - diff --git a/port_src/output/zxing/pdf417/encoder/p_d_f417_high_level_encoder.rs b/port_src/output/zxing/pdf417/encoder/p_d_f417_high_level_encoder.rs deleted file mode 100644 index cdaef6a..0000000 --- a/port_src/output/zxing/pdf417/encoder/p_d_f417_high_level_encoder.rs +++ /dev/null @@ -1,778 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part - * - * 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::pdf417::encoder; - -/** - * PDF417 high-level encoder following the algorithm described in ISO/IEC 15438:2001(E) in - * annex P. - */ - -/** - * code for Text compaction - */ - const TEXT_COMPACTION: i32 = 0; - -/** - * code for Byte compaction - */ - const BYTE_COMPACTION: i32 = 1; - -/** - * code for Numeric compaction - */ - const NUMERIC_COMPACTION: i32 = 2; - -/** - * Text compaction submode Alpha - */ - const SUBMODE_ALPHA: i32 = 0; - -/** - * Text compaction submode Lower - */ - const SUBMODE_LOWER: i32 = 1; - -/** - * Text compaction submode Mixed - */ - const SUBMODE_MIXED: i32 = 2; - -/** - * Text compaction submode Punctuation - */ - const SUBMODE_PUNCTUATION: i32 = 3; - -/** - * mode latch to Text Compaction mode - */ - const LATCH_TO_TEXT: i32 = 900; - -/** - * mode latch to Byte Compaction mode (number of characters NOT a multiple of 6) - */ - const LATCH_TO_BYTE_PADDED: i32 = 901; - -/** - * mode latch to Numeric Compaction mode - */ - const LATCH_TO_NUMERIC: i32 = 902; - -/** - * mode shift to Byte Compaction mode - */ - const SHIFT_TO_BYTE: i32 = 913; - -/** - * mode latch to Byte Compaction mode (number of characters a multiple of 6) - */ - const LATCH_TO_BYTE: i32 = 924; - -/** - * identifier for a user defined Extended Channel Interpretation (ECI) - */ - const ECI_USER_DEFINED: i32 = 925; - -/** - * identifier for a general purpose ECO format - */ - const ECI_GENERAL_PURPOSE: i32 = 926; - -/** - * identifier for an ECI of a character set of code page - */ - const ECI_CHARSET: i32 = 927; - -/** - * Raw code table for text compaction Mixed sub-mode - */ - const TEXT_MIXED_RAW: vec![Vec; 30] = vec![48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 38, 13, 9, 44, 58, 35, 45, 46, 36, 47, 43, 37, 42, 61, 94, 0, 32, 0, 0, 0, ] -; - -/** - * Raw code table for text compaction: Punctuation sub-mode - */ - const TEXT_PUNCTUATION_RAW: vec![Vec; 30] = vec![59, 60, 62, 64, 91, 92, 93, 95, 96, 126, 33, 13, 9, 44, 58, 10, 45, 46, 36, 47, 34, 124, 42, 40, 41, 63, 123, 125, 39, 0, ] -; - - const MIXED: [i8; 128] = [0; 128]; - - const PUNCTUATION: [i8; 128] = [0; 128]; - - const DEFAULT_ENCODING: Charset = StandardCharsets::ISO_8859_1; -struct PDF417HighLevelEncoder { -} - -impl PDF417HighLevelEncoder { - - fn new() -> PDF417HighLevelEncoder { - } - - static { - //Construct inverse lookups - Arrays::fill(&MIXED, -1 as i8); - { - let mut i: i32 = 0; - while i < TEXT_MIXED_RAW.len() { - { - let mut b: i8 = TEXT_MIXED_RAW[i]; - if b > 0 { - MIXED[b] = i as i8; - } - } - i += 1; - } - } - - Arrays::fill(&PUNCTUATION, -1 as i8); - { - let mut i: i32 = 0; - while i < TEXT_PUNCTUATION_RAW.len() { - { - let mut b: i8 = TEXT_PUNCTUATION_RAW[i]; - if b > 0 { - PUNCTUATION[b] = i as i8; - } - } - i += 1; - } - } - - } - - /** - * Performs high-level encoding of a PDF417 message using the algorithm described in annex P - * of ISO/IEC 15438:2001(E). If byte compaction has been selected, then only byte compaction - * is used. - * - * @param msg the message - * @param compaction compaction mode to use - * @param encoding character encoding used to encode in default or byte compaction - * or {@code null} for default / not applicable - * @param autoECI encode input minimally using multiple ECIs if needed - * If autoECI encoding is specified and additionally {@code encoding} is specified, then the encoder - * will use the specified {@link Charset} for any character that can be encoded by it, regardless - * if a different encoding would lead to a more compact encoding. When no {@code encoding} is specified - * then charsets will be chosen so that the byte representation is minimal. - * @return the encoded message (the char values range from 0 to 928) - */ - fn encode_high_level( msg: &String, compaction: &Compaction, encoding: &Charset, auto_e_c_i: bool) -> /* throws WriterException */Result> { - if msg.is_empty() { - throw WriterException::new("Empty message not allowed"); - } - if encoding == null && !auto_e_c_i { - { - let mut i: i32 = 0; - while i < msg.length() { - { - if msg.char_at(i) > 255 { - throw WriterException::new(format!("Non-encodable character detected: {} (Unicode: {}). Consider specifying EncodeHintType.PDF417_AUTO_ECI and/or EncodeTypeHint.CHARACTER_SET.", msg.char_at(i), msg.char_at(i) as i32)); - } - } - i += 1; - } - } - - } - //the codewords 0..928 are encoded as Unicode characters - let sb: StringBuilder = StringBuilder::new(&msg.length()); - let mut input: ECIInput; - if auto_e_c_i { - input = MinimalECIInput::new(&msg, &encoding, -1); - } else { - input = NoECIInput::new(&msg); - if encoding == null { - encoding = DEFAULT_ENCODING; - } else if !DEFAULT_ENCODING::equals(&encoding) { - let eci: CharacterSetECI = CharacterSetECI::get_character_set_e_c_i(&encoding); - if eci != null { - ::encoding_e_c_i(&eci.get_value(), &sb); - } - } - } - let len: i32 = input.length(); - let mut p: i32 = 0; - let text_sub_mode: i32 = SUBMODE_ALPHA; - // User selected encoding mode - match compaction { - TEXT => - { - ::encode_text(input, p, len, &sb, text_sub_mode); - break; - } - BYTE => - { - if auto_e_c_i { - ::encode_multi_e_c_i_binary(input, 0, &input.length(), TEXT_COMPACTION, &sb); - } else { - let msg_bytes: Vec = input.to_string().get_bytes(&encoding); - ::encode_binary(&msg_bytes, p, msg_bytes.len(), BYTE_COMPACTION, &sb); - } - break; - } - NUMERIC => - { - sb.append(LATCH_TO_NUMERIC as char); - ::encode_numeric(input, p, len, &sb); - break; - } - _ => - { - //Default mode, see 4.4.2.1 - let encoding_mode: i32 = TEXT_COMPACTION; - while p < len { - while p < len && input.is_e_c_i(p) { - ::encoding_e_c_i(&input.get_e_c_i_value(p), &sb); - p += 1; - } - if p >= len { - break; - } - let n: i32 = ::determine_consecutive_digit_count(input, p); - if n >= 13 { - sb.append(LATCH_TO_NUMERIC as char); - encoding_mode = NUMERIC_COMPACTION; - //Reset after latch - text_sub_mode = SUBMODE_ALPHA; - ::encode_numeric(input, p, n, &sb); - p += n; - } else { - let t: i32 = ::determine_consecutive_text_count(input, p); - if t >= 5 || n == len { - if encoding_mode != TEXT_COMPACTION { - sb.append(LATCH_TO_TEXT as char); - encoding_mode = TEXT_COMPACTION; - //start with submode alpha after latch - text_sub_mode = SUBMODE_ALPHA; - } - text_sub_mode = ::encode_text(input, p, t, &sb, text_sub_mode); - p += t; - } else { - let mut b: i32 = ::determine_consecutive_binary_count(input, p, if auto_e_c_i { null } else { encoding }); - if b == 0 { - b = 1; - } - let bytes: Vec = if auto_e_c_i { null } else { input.sub_sequence(p, p + b).to_string().get_bytes(&encoding) }; - if ((bytes == null && b == 1) || (bytes != null && bytes.len() == 1)) && encoding_mode == TEXT_COMPACTION { - //Switch for one byte (instead of latch) - if auto_e_c_i { - ::encode_multi_e_c_i_binary(input, p, 1, TEXT_COMPACTION, &sb); - } else { - ::encode_binary(&bytes, 0, 1, TEXT_COMPACTION, &sb); - } - } else { - //Mode latch performed by encodeBinary() - if auto_e_c_i { - ::encode_multi_e_c_i_binary(input, p, p + b, encoding_mode, &sb); - } else { - ::encode_binary(&bytes, 0, bytes.len(), encoding_mode, &sb); - } - encoding_mode = BYTE_COMPACTION; - //Reset after latch - text_sub_mode = SUBMODE_ALPHA; - } - p += b; - } - } - } - break; - } - } - return Ok(sb.to_string()); - } - - /** - * Encode parts of the message using Text Compaction as described in ISO/IEC 15438:2001(E), - * chapter 4.4.2. - * - * @param input the input - * @param startpos the start position within the message - * @param count the number of characters to encode - * @param sb receives the encoded codewords - * @param initialSubmode should normally be SUBMODE_ALPHA - * @return the text submode in which this method ends - */ - fn encode_text( input: &ECIInput, startpos: i32, count: i32, sb: &StringBuilder, initial_submode: i32) -> /* throws WriterException */Result> { - let tmp: StringBuilder = StringBuilder::new(count); - let mut submode: i32 = initial_submode; - let mut idx: i32 = 0; - while true { - if input.is_e_c_i(startpos + idx) { - ::encoding_e_c_i(&input.get_e_c_i_value(startpos + idx), &sb); - idx += 1; - } else { - let ch: char = input.char_at(startpos + idx); - match submode { - SUBMODE_ALPHA => - { - if ::is_alpha_upper(ch) { - if ch == ' ' { - //space - tmp.append(26 as char); - } else { - tmp.append((ch - 65) as char); - } - } else { - if ::is_alpha_lower(ch) { - submode = SUBMODE_LOWER; - //ll - tmp.append(27 as char); - continue; - } else if ::is_mixed(ch) { - submode = SUBMODE_MIXED; - //ml - tmp.append(28 as char); - continue; - } else { - //ps - tmp.append(29 as char); - tmp.append(PUNCTUATION[ch] as char); - break; - } - } - break; - } - SUBMODE_LOWER => - { - if ::is_alpha_lower(ch) { - if ch == ' ' { - //space - tmp.append(26 as char); - } else { - tmp.append((ch - 97) as char); - } - } else { - if ::is_alpha_upper(ch) { - //as - tmp.append(27 as char); - tmp.append((ch - 65) as char); - //space cannot happen here, it is also in "Lower" - break; - } else if ::is_mixed(ch) { - submode = SUBMODE_MIXED; - //ml - tmp.append(28 as char); - continue; - } else { - //ps - tmp.append(29 as char); - tmp.append(PUNCTUATION[ch] as char); - break; - } - } - break; - } - SUBMODE_MIXED => - { - if ::is_mixed(ch) { - tmp.append(MIXED[ch] as char); - } else { - if ::is_alpha_upper(ch) { - submode = SUBMODE_ALPHA; - //al - tmp.append(28 as char); - continue; - } else if ::is_alpha_lower(ch) { - submode = SUBMODE_LOWER; - //ll - tmp.append(27 as char); - continue; - } else { - if startpos + idx + 1 < count { - if !input.is_e_c_i(startpos + idx + 1) && ::is_punctuation(&input.char_at(startpos + idx + 1)) { - submode = SUBMODE_PUNCTUATION; - //pl - tmp.append(25 as char); - continue; - } - } - //ps - tmp.append(29 as char); - tmp.append(PUNCTUATION[ch] as char); - } - } - break; - } - _ => - { - //SUBMODE_PUNCTUATION - if ::is_punctuation(ch) { - tmp.append(PUNCTUATION[ch] as char); - } else { - submode = SUBMODE_ALPHA; - //al - tmp.append(29 as char); - continue; - } - } - } - idx += 1; - if idx >= count { - break; - } - } - } - let mut h: char = 0; - let len: i32 = tmp.length(); - { - let mut i: i32 = 0; - while i < len { - { - let odd: bool = (i % 2) != 0; - if odd { - h = ((h * 30) + tmp.char_at(i)) as char; - sb.append(h); - } else { - h = tmp.char_at(i); - } - } - i += 1; - } - } - - if (len % 2) != 0 { - //ps - sb.append(((h * 30) + 29) as char); - } - return Ok(submode); - } - - /** - * Encode all of the message using Byte Compaction as described in ISO/IEC 15438:2001(E) - * - * @param input the input - * @param startpos the start position within the message - * @param count the number of bytes to encode - * @param startmode the mode from which this method starts - * @param sb receives the encoded codewords - */ - fn encode_multi_e_c_i_binary( input: &ECIInput, startpos: i32, count: i32, startmode: i32, sb: &StringBuilder) -> /* throws WriterException */Result> { - let end: i32 = Math::min(startpos + count, &input.length()); - let local_start: i32 = startpos; - while true { - //encode all leading ECIs and advance localStart - while local_start < end && input.is_e_c_i(local_start) { - ::encoding_e_c_i(&input.get_e_c_i_value(local_start), &sb); - local_start += 1; - } - let local_end: i32 = local_start; - //advance end until before the next ECI - while local_end < end && !input.is_e_c_i(local_end) { - local_end += 1; - } - let local_count: i32 = local_end - local_start; - if local_count <= 0 { - //done - break; - } else { - //encode the segment - ::encode_binary(&::sub_bytes(input, local_start, local_end), 0, local_count, if local_start == startpos { startmode } else { BYTE_COMPACTION }, &sb); - local_start = local_end; - } - } - } - - fn sub_bytes( input: &ECIInput, start: i32, end: i32) -> Vec { - let count: i32 = end - start; - let mut result: [i8; count] = [0; count]; - { - let mut i: i32 = start; - while i < end { - { - result[i - start] = (input.char_at(i) & 0xff) as i8; - } - i += 1; - } - } - - return result; - } - - /** - * Encode parts of the message using Byte Compaction as described in ISO/IEC 15438:2001(E), - * chapter 4.4.3. The Unicode characters will be converted to binary using the cp437 - * codepage. - * - * @param bytes the message converted to a byte array - * @param startpos the start position within the message - * @param count the number of bytes to encode - * @param startmode the mode from which this method starts - * @param sb receives the encoded codewords - */ - fn encode_binary( bytes: &Vec, startpos: i32, count: i32, startmode: i32, sb: &StringBuilder) { - if count == 1 && startmode == TEXT_COMPACTION { - sb.append(SHIFT_TO_BYTE as char); - } else { - if (count % 6) == 0 { - sb.append(LATCH_TO_BYTE as char); - } else { - sb.append(LATCH_TO_BYTE_PADDED as char); - } - } - let mut idx: i32 = startpos; - // Encode sixpacks - if count >= 6 { - let mut chars: [Option; 5] = [None; 5]; - while (startpos + count - idx) >= 6 { - let mut t: i64 = 0; - { - let mut i: i32 = 0; - while i < 6 { - { - t <<= 8; - t += bytes[idx + i] & 0xff; - } - i += 1; - } - } - - { - let mut i: i32 = 0; - while i < 5 { - { - chars[i] = (t % 900) as char; - t /= 900; - } - i += 1; - } - } - - { - let mut i: i32 = chars.len() - 1; - while i >= 0 { - { - sb.append(chars[i]); - } - i -= 1; - } - } - - idx += 6; - } - } - //Encode rest (remaining n<5 bytes if any) - { - let mut i: i32 = idx; - while i < startpos + count { - { - let ch: i32 = bytes[i] & 0xff; - sb.append(ch as char); - } - i += 1; - } - } - - } - - fn encode_numeric( input: &ECIInput, startpos: i32, count: i32, sb: &StringBuilder) { - let mut idx: i32 = 0; - let tmp: StringBuilder = StringBuilder::new(count / 3 + 1); - let num900: BigInteger = BigInteger::value_of(900); - let num0: BigInteger = BigInteger::value_of(0); - while idx < count { - tmp.set_length(0); - let len: i32 = Math::min(44, count - idx); - let part: String = format!("1{}", input.sub_sequence(startpos + idx, startpos + idx + len)); - let mut bigint: BigInteger = BigInteger::new(&part); - loop { { - tmp.append(bigint.mod(&num900).int_value() as char); - bigint = bigint.divide(&num900); - }if !(!bigint.equals(&num0)) break;} - //Reverse temporary string - { - let mut i: i32 = tmp.length() - 1; - while i >= 0 { - { - sb.append(&tmp.char_at(i)); - } - i -= 1; - } - } - - idx += len; - } - } - - fn is_digit( ch: char) -> bool { - return ch >= '0' && ch <= '9'; - } - - fn is_alpha_upper( ch: char) -> bool { - return ch == ' ' || (ch >= 'A' && ch <= 'Z'); - } - - fn is_alpha_lower( ch: char) -> bool { - return ch == ' ' || (ch >= 'a' && ch <= 'z'); - } - - fn is_mixed( ch: char) -> bool { - return MIXED[ch] != -1; - } - - fn is_punctuation( ch: char) -> bool { - return PUNCTUATION[ch] != -1; - } - - fn is_text( ch: char) -> bool { - return ch == '\t' || ch == '\n' || ch == '\r' || (ch >= 32 && ch <= 126); - } - - /** - * Determines the number of consecutive characters that are encodable using numeric compaction. - * - * @param input the input - * @param startpos the start position within the input - * @return the requested character count - */ - fn determine_consecutive_digit_count( input: &ECIInput, startpos: i32) -> i32 { - let mut count: i32 = 0; - let len: i32 = input.length(); - let mut idx: i32 = startpos; - if idx < len { - while idx < len && !input.is_e_c_i(idx) && ::is_digit(&input.char_at(idx)) { - count += 1; - idx += 1; - } - } - return count; - } - - /** - * Determines the number of consecutive characters that are encodable using text compaction. - * - * @param input the input - * @param startpos the start position within the input - * @return the requested character count - */ - fn determine_consecutive_text_count( input: &ECIInput, startpos: i32) -> i32 { - let len: i32 = input.length(); - let mut idx: i32 = startpos; - while idx < len { - let numeric_count: i32 = 0; - while numeric_count < 13 && idx < len && !input.is_e_c_i(idx) && ::is_digit(&input.char_at(idx)) { - numeric_count += 1; - idx += 1; - } - if numeric_count >= 13 { - return idx - startpos - numeric_count; - } - if numeric_count > 0 { - //Heuristic: All text-encodable chars or digits are binary encodable - continue; - } - //Check if character is encodable - if input.is_e_c_i(idx) || !::is_text(&input.char_at(idx)) { - break; - } - idx += 1; - } - return idx - startpos; - } - - /** - * Determines the number of consecutive characters that are encodable using binary compaction. - * - * @param input the input - * @param startpos the start position within the message - * @param encoding the charset used to convert the message to a byte array - * @return the requested character count - */ - fn determine_consecutive_binary_count( input: &ECIInput, startpos: i32, encoding: &Charset) -> /* throws WriterException */Result> { - let encoder: CharsetEncoder = if encoding == null { null } else { encoding.new_encoder() }; - let len: i32 = input.length(); - let mut idx: i32 = startpos; - while idx < len { - let numeric_count: i32 = 0; - let mut i: i32 = idx; - while numeric_count < 13 && !input.is_e_c_i(i) && ::is_digit(&input.char_at(i)) { - numeric_count += 1; - //textCount++; - i = idx + numeric_count; - if i >= len { - break; - } - } - if numeric_count >= 13 { - return Ok(idx - startpos); - } - if encoder != null && !encoder.can_encode(&input.char_at(idx)) { - assert!( input instanceof NoECIInput); - let ch: char = input.char_at(idx); - throw WriterException::new(format!("Non-encodable character detected: {} (Unicode: {})", ch, ch as i32)); - } - idx += 1; - } - return Ok(idx - startpos); - } - - fn encoding_e_c_i( eci: i32, sb: &StringBuilder) -> /* throws WriterException */Result> { - if eci >= 0 && eci < 900 { - sb.append(ECI_CHARSET as char); - sb.append(eci as char); - } else if eci < 810900 { - sb.append(ECI_GENERAL_PURPOSE as char); - sb.append((eci / 900 - 1) as char); - sb.append((eci % 900) as char); - } else if eci < 811800 { - sb.append(ECI_USER_DEFINED as char); - sb.append((810900 - eci) as char); - } else { - throw WriterException::new(format!("ECI number not in valid range from 0..811799, but was {}", eci)); - } - } - - #[derive(ECIInput)] - struct NoECIInput { - - let input: String; - } - - impl NoECIInput { - - fn new( input: &String) -> NoECIInput { - let .input = input; - } - - pub fn length(&self) -> i32 { - return self.input.length(); - } - - pub fn char_at(&self, index: i32) -> char { - return self.input.char_at(index); - } - - pub fn is_e_c_i(&self, index: i32) -> bool { - return false; - } - - pub fn get_e_c_i_value(&self, index: i32) -> i32 { - return -1; - } - - pub fn have_n_characters(&self, index: i32, n: i32) -> bool { - return index + n <= self.input.length(); - } - - pub fn sub_sequence(&self, start: i32, end: i32) -> CharSequence { - return self.input.sub_sequence(start, end); - } - - pub fn to_string(&self) -> String { - return self.input; - } - } - -} - diff --git a/port_src/output/zxing/pdf417/encoder/p_d_f417_high_level_encoder_test_adapter.rs b/port_src/output/zxing/pdf417/encoder/p_d_f417_high_level_encoder_test_adapter.rs deleted file mode 100644 index 0537b9c..0000000 --- a/port_src/output/zxing/pdf417/encoder/p_d_f417_high_level_encoder_test_adapter.rs +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2022 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// package com::google::zxing::pdf417::encoder; - -pub struct PDF417HighLevelEncoderTestAdapter { -} - -impl PDF417HighLevelEncoderTestAdapter { - - fn new() -> PDF417HighLevelEncoderTestAdapter { - } - - pub fn encode_high_level( msg: &String, compaction: &Compaction, encoding: &Charset, auto_e_c_i: bool) -> /* throws WriterException */Result> { - return Ok(PDF417HighLevelEncoder::encode_high_level(&msg, compaction, &encoding, auto_e_c_i)); - } -} - diff --git a/port_src/output/zxing/pdf417/p_d_f417_common.rs b/port_src/output/zxing/pdf417/p_d_f417_common.rs deleted file mode 100644 index 787846b..0000000 --- a/port_src/output/zxing/pdf417/p_d_f417_common.rs +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// package com::google::zxing::pdf417; - -/** - * @author SITA Lab (kevin.osullivan@sita.aero) - * @author Guenther Grau - */ - - const NUMBER_OF_CODEWORDS: i32 = 929; - -// Maximum Codewords (Data + Error). - const MAX_CODEWORDS_IN_BARCODE: i32 = NUMBER_OF_CODEWORDS - 1; - - const MIN_ROWS_IN_BARCODE: i32 = 3; - - const MAX_ROWS_IN_BARCODE: i32 = 90; - -// One left row indication column + max 30 data columns + one right row indicator column -//public static final int MAX_CODEWORDS_IN_ROW = 32; - const MODULES_IN_CODEWORD: i32 = 17; - - const MODULES_IN_STOP_PATTERN: i32 = 18; - - const BARS_IN_MODULE: i32 = 8; - - const EMPTY_INT_ARRAY; - -/** - * The sorted table of all possible symbols. Extracted from the PDF417 - * specification. The index of a symbol in this table corresponds to the - * index into the codeword table. - */ - const SYMBOL_TABLE: vec![Vec; 2787] = vec![0x1025e, 0x1027a, 0x1029e, 0x102bc, 0x102f2, 0x102f4, 0x1032e, 0x1034e, 0x1035c, 0x10396, 0x103a6, 0x103ac, 0x10422, 0x10428, 0x10436, 0x10442, 0x10444, 0x10448, 0x10450, 0x1045e, 0x10466, 0x1046c, 0x1047a, 0x10482, 0x1049e, 0x104a0, 0x104bc, 0x104c6, 0x104d8, 0x104ee, 0x104f2, 0x104f4, 0x10504, 0x10508, 0x10510, 0x1051e, 0x10520, 0x1053c, 0x10540, 0x10578, 0x10586, 0x1058c, 0x10598, 0x105b0, 0x105be, 0x105ce, 0x105dc, 0x105e2, 0x105e4, 0x105e8, 0x105f6, 0x1062e, 0x1064e, 0x1065c, 0x1068e, 0x1069c, 0x106b8, 0x106de, 0x106fa, 0x10716, 0x10726, 0x1072c, 0x10746, 0x1074c, 0x10758, 0x1076e, 0x10792, 0x10794, 0x107a2, 0x107a4, 0x107a8, 0x107b6, 0x10822, 0x10828, 0x10842, 0x10848, 0x10850, 0x1085e, 0x10866, 0x1086c, 0x1087a, 0x10882, 0x10884, 0x10890, 0x1089e, 0x108a0, 0x108bc, 0x108c6, 0x108cc, 0x108d8, 0x108ee, 0x108f2, 0x108f4, 0x10902, 0x10908, 0x1091e, 0x10920, 0x1093c, 0x10940, 0x10978, 0x10986, 0x10998, 0x109b0, 0x109be, 0x109ce, 0x109dc, 0x109e2, 0x109e4, 0x109e8, 0x109f6, 0x10a08, 0x10a10, 0x10a1e, 0x10a20, 0x10a3c, 0x10a40, 0x10a78, 0x10af0, 0x10b06, 0x10b0c, 0x10b18, 0x10b30, 0x10b3e, 0x10b60, 0x10b7c, 0x10b8e, 0x10b9c, 0x10bb8, 0x10bc2, 0x10bc4, 0x10bc8, 0x10bd0, 0x10bde, 0x10be6, 0x10bec, 0x10c2e, 0x10c4e, 0x10c5c, 0x10c62, 0x10c64, 0x10c68, 0x10c76, 0x10c8e, 0x10c9c, 0x10cb8, 0x10cc2, 0x10cc4, 0x10cc8, 0x10cd0, 0x10cde, 0x10ce6, 0x10cec, 0x10cfa, 0x10d0e, 0x10d1c, 0x10d38, 0x10d70, 0x10d7e, 0x10d82, 0x10d84, 0x10d88, 0x10d90, 0x10d9e, 0x10da0, 0x10dbc, 0x10dc6, 0x10dcc, 0x10dd8, 0x10dee, 0x10df2, 0x10df4, 0x10e16, 0x10e26, 0x10e2c, 0x10e46, 0x10e58, 0x10e6e, 0x10e86, 0x10e8c, 0x10e98, 0x10eb0, 0x10ebe, 0x10ece, 0x10edc, 0x10f0a, 0x10f12, 0x10f14, 0x10f22, 0x10f28, 0x10f36, 0x10f42, 0x10f44, 0x10f48, 0x10f50, 0x10f5e, 0x10f66, 0x10f6c, 0x10fb2, 0x10fb4, 0x11022, 0x11028, 0x11042, 0x11048, 0x11050, 0x1105e, 0x1107a, 0x11082, 0x11084, 0x11090, 0x1109e, 0x110a0, 0x110bc, 0x110c6, 0x110cc, 0x110d8, 0x110ee, 0x110f2, 0x110f4, 0x11102, 0x1111e, 0x11120, 0x1113c, 0x11140, 0x11178, 0x11186, 0x11198, 0x111b0, 0x111be, 0x111ce, 0x111dc, 0x111e2, 0x111e4, 0x111e8, 0x111f6, 0x11208, 0x1121e, 0x11220, 0x11278, 0x112f0, 0x1130c, 0x11330, 0x1133e, 0x11360, 0x1137c, 0x1138e, 0x1139c, 0x113b8, 0x113c2, 0x113c8, 0x113d0, 0x113de, 0x113e6, 0x113ec, 0x11408, 0x11410, 0x1141e, 0x11420, 0x1143c, 0x11440, 0x11478, 0x114f0, 0x115e0, 0x1160c, 0x11618, 0x11630, 0x1163e, 0x11660, 0x1167c, 0x116c0, 0x116f8, 0x1171c, 0x11738, 0x11770, 0x1177e, 0x11782, 0x11784, 0x11788, 0x11790, 0x1179e, 0x117a0, 0x117bc, 0x117c6, 0x117cc, 0x117d8, 0x117ee, 0x1182e, 0x11834, 0x1184e, 0x1185c, 0x11862, 0x11864, 0x11868, 0x11876, 0x1188e, 0x1189c, 0x118b8, 0x118c2, 0x118c8, 0x118d0, 0x118de, 0x118e6, 0x118ec, 0x118fa, 0x1190e, 0x1191c, 0x11938, 0x11970, 0x1197e, 0x11982, 0x11984, 0x11990, 0x1199e, 0x119a0, 0x119bc, 0x119c6, 0x119cc, 0x119d8, 0x119ee, 0x119f2, 0x119f4, 0x11a0e, 0x11a1c, 0x11a38, 0x11a70, 0x11a7e, 0x11ae0, 0x11afc, 0x11b08, 0x11b10, 0x11b1e, 0x11b20, 0x11b3c, 0x11b40, 0x11b78, 0x11b8c, 0x11b98, 0x11bb0, 0x11bbe, 0x11bce, 0x11bdc, 0x11be2, 0x11be4, 0x11be8, 0x11bf6, 0x11c16, 0x11c26, 0x11c2c, 0x11c46, 0x11c4c, 0x11c58, 0x11c6e, 0x11c86, 0x11c98, 0x11cb0, 0x11cbe, 0x11cce, 0x11cdc, 0x11ce2, 0x11ce4, 0x11ce8, 0x11cf6, 0x11d06, 0x11d0c, 0x11d18, 0x11d30, 0x11d3e, 0x11d60, 0x11d7c, 0x11d8e, 0x11d9c, 0x11db8, 0x11dc4, 0x11dc8, 0x11dd0, 0x11dde, 0x11de6, 0x11dec, 0x11dfa, 0x11e0a, 0x11e12, 0x11e14, 0x11e22, 0x11e24, 0x11e28, 0x11e36, 0x11e42, 0x11e44, 0x11e50, 0x11e5e, 0x11e66, 0x11e6c, 0x11e82, 0x11e84, 0x11e88, 0x11e90, 0x11e9e, 0x11ea0, 0x11ebc, 0x11ec6, 0x11ecc, 0x11ed8, 0x11eee, 0x11f1a, 0x11f2e, 0x11f32, 0x11f34, 0x11f4e, 0x11f5c, 0x11f62, 0x11f64, 0x11f68, 0x11f76, 0x12048, 0x1205e, 0x12082, 0x12084, 0x12090, 0x1209e, 0x120a0, 0x120bc, 0x120d8, 0x120f2, 0x120f4, 0x12108, 0x1211e, 0x12120, 0x1213c, 0x12140, 0x12178, 0x12186, 0x12198, 0x121b0, 0x121be, 0x121e2, 0x121e4, 0x121e8, 0x121f6, 0x12204, 0x12210, 0x1221e, 0x12220, 0x12278, 0x122f0, 0x12306, 0x1230c, 0x12330, 0x1233e, 0x12360, 0x1237c, 0x1238e, 0x1239c, 0x123b8, 0x123c2, 0x123c8, 0x123d0, 0x123e6, 0x123ec, 0x1241e, 0x12420, 0x1243c, 0x124f0, 0x125e0, 0x12618, 0x1263e, 0x12660, 0x1267c, 0x126c0, 0x126f8, 0x12738, 0x12770, 0x1277e, 0x12782, 0x12784, 0x12790, 0x1279e, 0x127a0, 0x127bc, 0x127c6, 0x127cc, 0x127d8, 0x127ee, 0x12820, 0x1283c, 0x12840, 0x12878, 0x128f0, 0x129e0, 0x12bc0, 0x12c18, 0x12c30, 0x12c3e, 0x12c60, 0x12c7c, 0x12cc0, 0x12cf8, 0x12df0, 0x12e1c, 0x12e38, 0x12e70, 0x12e7e, 0x12ee0, 0x12efc, 0x12f04, 0x12f08, 0x12f10, 0x12f20, 0x12f3c, 0x12f40, 0x12f78, 0x12f86, 0x12f8c, 0x12f98, 0x12fb0, 0x12fbe, 0x12fce, 0x12fdc, 0x1302e, 0x1304e, 0x1305c, 0x13062, 0x13068, 0x1308e, 0x1309c, 0x130b8, 0x130c2, 0x130c8, 0x130d0, 0x130de, 0x130ec, 0x130fa, 0x1310e, 0x13138, 0x13170, 0x1317e, 0x13182, 0x13184, 0x13190, 0x1319e, 0x131a0, 0x131bc, 0x131c6, 0x131cc, 0x131d8, 0x131f2, 0x131f4, 0x1320e, 0x1321c, 0x13270, 0x1327e, 0x132e0, 0x132fc, 0x13308, 0x1331e, 0x13320, 0x1333c, 0x13340, 0x13378, 0x13386, 0x13398, 0x133b0, 0x133be, 0x133ce, 0x133dc, 0x133e2, 0x133e4, 0x133e8, 0x133f6, 0x1340e, 0x1341c, 0x13438, 0x13470, 0x1347e, 0x134e0, 0x134fc, 0x135c0, 0x135f8, 0x13608, 0x13610, 0x1361e, 0x13620, 0x1363c, 0x13640, 0x13678, 0x136f0, 0x1370c, 0x13718, 0x13730, 0x1373e, 0x13760, 0x1377c, 0x1379c, 0x137b8, 0x137c2, 0x137c4, 0x137c8, 0x137d0, 0x137de, 0x137e6, 0x137ec, 0x13816, 0x13826, 0x1382c, 0x13846, 0x1384c, 0x13858, 0x1386e, 0x13874, 0x13886, 0x13898, 0x138b0, 0x138be, 0x138ce, 0x138dc, 0x138e2, 0x138e4, 0x138e8, 0x13906, 0x1390c, 0x13930, 0x1393e, 0x13960, 0x1397c, 0x1398e, 0x1399c, 0x139b8, 0x139c8, 0x139d0, 0x139de, 0x139e6, 0x139ec, 0x139fa, 0x13a06, 0x13a0c, 0x13a18, 0x13a30, 0x13a3e, 0x13a60, 0x13a7c, 0x13ac0, 0x13af8, 0x13b0e, 0x13b1c, 0x13b38, 0x13b70, 0x13b7e, 0x13b88, 0x13b90, 0x13b9e, 0x13ba0, 0x13bbc, 0x13bcc, 0x13bd8, 0x13bee, 0x13bf2, 0x13bf4, 0x13c12, 0x13c14, 0x13c22, 0x13c24, 0x13c28, 0x13c36, 0x13c42, 0x13c48, 0x13c50, 0x13c5e, 0x13c66, 0x13c6c, 0x13c82, 0x13c84, 0x13c90, 0x13c9e, 0x13ca0, 0x13cbc, 0x13cc6, 0x13ccc, 0x13cd8, 0x13cee, 0x13d02, 0x13d04, 0x13d08, 0x13d10, 0x13d1e, 0x13d20, 0x13d3c, 0x13d40, 0x13d78, 0x13d86, 0x13d8c, 0x13d98, 0x13db0, 0x13dbe, 0x13dce, 0x13ddc, 0x13de4, 0x13de8, 0x13df6, 0x13e1a, 0x13e2e, 0x13e32, 0x13e34, 0x13e4e, 0x13e5c, 0x13e62, 0x13e64, 0x13e68, 0x13e76, 0x13e8e, 0x13e9c, 0x13eb8, 0x13ec2, 0x13ec4, 0x13ec8, 0x13ed0, 0x13ede, 0x13ee6, 0x13eec, 0x13f26, 0x13f2c, 0x13f3a, 0x13f46, 0x13f4c, 0x13f58, 0x13f6e, 0x13f72, 0x13f74, 0x14082, 0x1409e, 0x140a0, 0x140bc, 0x14104, 0x14108, 0x14110, 0x1411e, 0x14120, 0x1413c, 0x14140, 0x14178, 0x1418c, 0x14198, 0x141b0, 0x141be, 0x141e2, 0x141e4, 0x141e8, 0x14208, 0x14210, 0x1421e, 0x14220, 0x1423c, 0x14240, 0x14278, 0x142f0, 0x14306, 0x1430c, 0x14318, 0x14330, 0x1433e, 0x14360, 0x1437c, 0x1438e, 0x143c2, 0x143c4, 0x143c8, 0x143d0, 0x143e6, 0x143ec, 0x14408, 0x14410, 0x1441e, 0x14420, 0x1443c, 0x14440, 0x14478, 0x144f0, 0x145e0, 0x1460c, 0x14618, 0x14630, 0x1463e, 0x14660, 0x1467c, 0x146c0, 0x146f8, 0x1471c, 0x14738, 0x14770, 0x1477e, 0x14782, 0x14784, 0x14788, 0x14790, 0x147a0, 0x147bc, 0x147c6, 0x147cc, 0x147d8, 0x147ee, 0x14810, 0x14820, 0x1483c, 0x14840, 0x14878, 0x148f0, 0x149e0, 0x14bc0, 0x14c30, 0x14c3e, 0x14c60, 0x14c7c, 0x14cc0, 0x14cf8, 0x14df0, 0x14e38, 0x14e70, 0x14e7e, 0x14ee0, 0x14efc, 0x14f04, 0x14f08, 0x14f10, 0x14f1e, 0x14f20, 0x14f3c, 0x14f40, 0x14f78, 0x14f86, 0x14f8c, 0x14f98, 0x14fb0, 0x14fce, 0x14fdc, 0x15020, 0x15040, 0x15078, 0x150f0, 0x151e0, 0x153c0, 0x15860, 0x1587c, 0x158c0, 0x158f8, 0x159f0, 0x15be0, 0x15c70, 0x15c7e, 0x15ce0, 0x15cfc, 0x15dc0, 0x15df8, 0x15e08, 0x15e10, 0x15e20, 0x15e40, 0x15e78, 0x15ef0, 0x15f0c, 0x15f18, 0x15f30, 0x15f60, 0x15f7c, 0x15f8e, 0x15f9c, 0x15fb8, 0x1604e, 0x1605c, 0x1608e, 0x1609c, 0x160b8, 0x160c2, 0x160c4, 0x160c8, 0x160de, 0x1610e, 0x1611c, 0x16138, 0x16170, 0x1617e, 0x16184, 0x16188, 0x16190, 0x1619e, 0x161a0, 0x161bc, 0x161c6, 0x161cc, 0x161d8, 0x161f2, 0x161f4, 0x1620e, 0x1621c, 0x16238, 0x16270, 0x1627e, 0x162e0, 0x162fc, 0x16304, 0x16308, 0x16310, 0x1631e, 0x16320, 0x1633c, 0x16340, 0x16378, 0x16386, 0x1638c, 0x16398, 0x163b0, 0x163be, 0x163ce, 0x163dc, 0x163e2, 0x163e4, 0x163e8, 0x163f6, 0x1640e, 0x1641c, 0x16438, 0x16470, 0x1647e, 0x164e0, 0x164fc, 0x165c0, 0x165f8, 0x16610, 0x1661e, 0x16620, 0x1663c, 0x16640, 0x16678, 0x166f0, 0x16718, 0x16730, 0x1673e, 0x16760, 0x1677c, 0x1678e, 0x1679c, 0x167b8, 0x167c2, 0x167c4, 0x167c8, 0x167d0, 0x167de, 0x167e6, 0x167ec, 0x1681c, 0x16838, 0x16870, 0x168e0, 0x168fc, 0x169c0, 0x169f8, 0x16bf0, 0x16c10, 0x16c1e, 0x16c20, 0x16c3c, 0x16c40, 0x16c78, 0x16cf0, 0x16de0, 0x16e18, 0x16e30, 0x16e3e, 0x16e60, 0x16e7c, 0x16ec0, 0x16ef8, 0x16f1c, 0x16f38, 0x16f70, 0x16f7e, 0x16f84, 0x16f88, 0x16f90, 0x16f9e, 0x16fa0, 0x16fbc, 0x16fc6, 0x16fcc, 0x16fd8, 0x17026, 0x1702c, 0x17046, 0x1704c, 0x17058, 0x1706e, 0x17086, 0x1708c, 0x17098, 0x170b0, 0x170be, 0x170ce, 0x170dc, 0x170e8, 0x17106, 0x1710c, 0x17118, 0x17130, 0x1713e, 0x17160, 0x1717c, 0x1718e, 0x1719c, 0x171b8, 0x171c2, 0x171c4, 0x171c8, 0x171d0, 0x171de, 0x171e6, 0x171ec, 0x171fa, 0x17206, 0x1720c, 0x17218, 0x17230, 0x1723e, 0x17260, 0x1727c, 0x172c0, 0x172f8, 0x1730e, 0x1731c, 0x17338, 0x17370, 0x1737e, 0x17388, 0x17390, 0x1739e, 0x173a0, 0x173bc, 0x173cc, 0x173d8, 0x173ee, 0x173f2, 0x173f4, 0x1740c, 0x17418, 0x17430, 0x1743e, 0x17460, 0x1747c, 0x174c0, 0x174f8, 0x175f0, 0x1760e, 0x1761c, 0x17638, 0x17670, 0x1767e, 0x176e0, 0x176fc, 0x17708, 0x17710, 0x1771e, 0x17720, 0x1773c, 0x17740, 0x17778, 0x17798, 0x177b0, 0x177be, 0x177dc, 0x177e2, 0x177e4, 0x177e8, 0x17822, 0x17824, 0x17828, 0x17836, 0x17842, 0x17844, 0x17848, 0x17850, 0x1785e, 0x17866, 0x1786c, 0x17882, 0x17884, 0x17888, 0x17890, 0x1789e, 0x178a0, 0x178bc, 0x178c6, 0x178cc, 0x178d8, 0x178ee, 0x178f2, 0x178f4, 0x17902, 0x17904, 0x17908, 0x17910, 0x1791e, 0x17920, 0x1793c, 0x17940, 0x17978, 0x17986, 0x1798c, 0x17998, 0x179b0, 0x179be, 0x179ce, 0x179dc, 0x179e2, 0x179e4, 0x179e8, 0x179f6, 0x17a04, 0x17a08, 0x17a10, 0x17a1e, 0x17a20, 0x17a3c, 0x17a40, 0x17a78, 0x17af0, 0x17b06, 0x17b0c, 0x17b18, 0x17b30, 0x17b3e, 0x17b60, 0x17b7c, 0x17b8e, 0x17b9c, 0x17bb8, 0x17bc4, 0x17bc8, 0x17bd0, 0x17bde, 0x17be6, 0x17bec, 0x17c2e, 0x17c32, 0x17c34, 0x17c4e, 0x17c5c, 0x17c62, 0x17c64, 0x17c68, 0x17c76, 0x17c8e, 0x17c9c, 0x17cb8, 0x17cc2, 0x17cc4, 0x17cc8, 0x17cd0, 0x17cde, 0x17ce6, 0x17cec, 0x17d0e, 0x17d1c, 0x17d38, 0x17d70, 0x17d82, 0x17d84, 0x17d88, 0x17d90, 0x17d9e, 0x17da0, 0x17dbc, 0x17dc6, 0x17dcc, 0x17dd8, 0x17dee, 0x17e26, 0x17e2c, 0x17e3a, 0x17e46, 0x17e4c, 0x17e58, 0x17e6e, 0x17e72, 0x17e74, 0x17e86, 0x17e8c, 0x17e98, 0x17eb0, 0x17ece, 0x17edc, 0x17ee2, 0x17ee4, 0x17ee8, 0x17ef6, 0x1813a, 0x18172, 0x18174, 0x18216, 0x18226, 0x1823a, 0x1824c, 0x18258, 0x1826e, 0x18272, 0x18274, 0x18298, 0x182be, 0x182e2, 0x182e4, 0x182e8, 0x182f6, 0x1835e, 0x1837a, 0x183ae, 0x183d6, 0x18416, 0x18426, 0x1842c, 0x1843a, 0x18446, 0x18458, 0x1846e, 0x18472, 0x18474, 0x18486, 0x184b0, 0x184be, 0x184ce, 0x184dc, 0x184e2, 0x184e4, 0x184e8, 0x184f6, 0x18506, 0x1850c, 0x18518, 0x18530, 0x1853e, 0x18560, 0x1857c, 0x1858e, 0x1859c, 0x185b8, 0x185c2, 0x185c4, 0x185c8, 0x185d0, 0x185de, 0x185e6, 0x185ec, 0x185fa, 0x18612, 0x18614, 0x18622, 0x18628, 0x18636, 0x18642, 0x18650, 0x1865e, 0x1867a, 0x18682, 0x18684, 0x18688, 0x18690, 0x1869e, 0x186a0, 0x186bc, 0x186c6, 0x186cc, 0x186d8, 0x186ee, 0x186f2, 0x186f4, 0x1872e, 0x1874e, 0x1875c, 0x18796, 0x187a6, 0x187ac, 0x187d2, 0x187d4, 0x18826, 0x1882c, 0x1883a, 0x18846, 0x1884c, 0x18858, 0x1886e, 0x18872, 0x18874, 0x18886, 0x18898, 0x188b0, 0x188be, 0x188ce, 0x188dc, 0x188e2, 0x188e4, 0x188e8, 0x188f6, 0x1890c, 0x18930, 0x1893e, 0x18960, 0x1897c, 0x1898e, 0x189b8, 0x189c2, 0x189c8, 0x189d0, 0x189de, 0x189e6, 0x189ec, 0x189fa, 0x18a18, 0x18a30, 0x18a3e, 0x18a60, 0x18a7c, 0x18ac0, 0x18af8, 0x18b1c, 0x18b38, 0x18b70, 0x18b7e, 0x18b82, 0x18b84, 0x18b88, 0x18b90, 0x18b9e, 0x18ba0, 0x18bbc, 0x18bc6, 0x18bcc, 0x18bd8, 0x18bee, 0x18bf2, 0x18bf4, 0x18c22, 0x18c24, 0x18c28, 0x18c36, 0x18c42, 0x18c48, 0x18c50, 0x18c5e, 0x18c66, 0x18c7a, 0x18c82, 0x18c84, 0x18c90, 0x18c9e, 0x18ca0, 0x18cbc, 0x18ccc, 0x18cf2, 0x18cf4, 0x18d04, 0x18d08, 0x18d10, 0x18d1e, 0x18d20, 0x18d3c, 0x18d40, 0x18d78, 0x18d86, 0x18d98, 0x18dce, 0x18de2, 0x18de4, 0x18de8, 0x18e2e, 0x18e32, 0x18e34, 0x18e4e, 0x18e5c, 0x18e62, 0x18e64, 0x18e68, 0x18e8e, 0x18e9c, 0x18eb8, 0x18ec2, 0x18ec4, 0x18ec8, 0x18ed0, 0x18efa, 0x18f16, 0x18f26, 0x18f2c, 0x18f46, 0x18f4c, 0x18f58, 0x18f6e, 0x18f8a, 0x18f92, 0x18f94, 0x18fa2, 0x18fa4, 0x18fa8, 0x18fb6, 0x1902c, 0x1903a, 0x19046, 0x1904c, 0x19058, 0x19072, 0x19074, 0x19086, 0x19098, 0x190b0, 0x190be, 0x190ce, 0x190dc, 0x190e2, 0x190e8, 0x190f6, 0x19106, 0x1910c, 0x19130, 0x1913e, 0x19160, 0x1917c, 0x1918e, 0x1919c, 0x191b8, 0x191c2, 0x191c8, 0x191d0, 0x191de, 0x191e6, 0x191ec, 0x191fa, 0x19218, 0x1923e, 0x19260, 0x1927c, 0x192c0, 0x192f8, 0x19338, 0x19370, 0x1937e, 0x19382, 0x19384, 0x19390, 0x1939e, 0x193a0, 0x193bc, 0x193c6, 0x193cc, 0x193d8, 0x193ee, 0x193f2, 0x193f4, 0x19430, 0x1943e, 0x19460, 0x1947c, 0x194c0, 0x194f8, 0x195f0, 0x19638, 0x19670, 0x1967e, 0x196e0, 0x196fc, 0x19702, 0x19704, 0x19708, 0x19710, 0x19720, 0x1973c, 0x19740, 0x19778, 0x19786, 0x1978c, 0x19798, 0x197b0, 0x197be, 0x197ce, 0x197dc, 0x197e2, 0x197e4, 0x197e8, 0x19822, 0x19824, 0x19842, 0x19848, 0x19850, 0x1985e, 0x19866, 0x1987a, 0x19882, 0x19884, 0x19890, 0x1989e, 0x198a0, 0x198bc, 0x198cc, 0x198f2, 0x198f4, 0x19902, 0x19908, 0x1991e, 0x19920, 0x1993c, 0x19940, 0x19978, 0x19986, 0x19998, 0x199ce, 0x199e2, 0x199e4, 0x199e8, 0x19a08, 0x19a10, 0x19a1e, 0x19a20, 0x19a3c, 0x19a40, 0x19a78, 0x19af0, 0x19b18, 0x19b3e, 0x19b60, 0x19b9c, 0x19bc2, 0x19bc4, 0x19bc8, 0x19bd0, 0x19be6, 0x19c2e, 0x19c34, 0x19c4e, 0x19c5c, 0x19c62, 0x19c64, 0x19c68, 0x19c8e, 0x19c9c, 0x19cb8, 0x19cc2, 0x19cc8, 0x19cd0, 0x19ce6, 0x19cfa, 0x19d0e, 0x19d1c, 0x19d38, 0x19d70, 0x19d7e, 0x19d82, 0x19d84, 0x19d88, 0x19d90, 0x19da0, 0x19dcc, 0x19df2, 0x19df4, 0x19e16, 0x19e26, 0x19e2c, 0x19e46, 0x19e4c, 0x19e58, 0x19e74, 0x19e86, 0x19e8c, 0x19e98, 0x19eb0, 0x19ebe, 0x19ece, 0x19ee2, 0x19ee4, 0x19ee8, 0x19f0a, 0x19f12, 0x19f14, 0x19f22, 0x19f24, 0x19f28, 0x19f42, 0x19f44, 0x19f48, 0x19f50, 0x19f5e, 0x19f6c, 0x19f9a, 0x19fae, 0x19fb2, 0x19fb4, 0x1a046, 0x1a04c, 0x1a072, 0x1a074, 0x1a086, 0x1a08c, 0x1a098, 0x1a0b0, 0x1a0be, 0x1a0e2, 0x1a0e4, 0x1a0e8, 0x1a0f6, 0x1a106, 0x1a10c, 0x1a118, 0x1a130, 0x1a13e, 0x1a160, 0x1a17c, 0x1a18e, 0x1a19c, 0x1a1b8, 0x1a1c2, 0x1a1c4, 0x1a1c8, 0x1a1d0, 0x1a1de, 0x1a1e6, 0x1a1ec, 0x1a218, 0x1a230, 0x1a23e, 0x1a260, 0x1a27c, 0x1a2c0, 0x1a2f8, 0x1a31c, 0x1a338, 0x1a370, 0x1a37e, 0x1a382, 0x1a384, 0x1a388, 0x1a390, 0x1a39e, 0x1a3a0, 0x1a3bc, 0x1a3c6, 0x1a3cc, 0x1a3d8, 0x1a3ee, 0x1a3f2, 0x1a3f4, 0x1a418, 0x1a430, 0x1a43e, 0x1a460, 0x1a47c, 0x1a4c0, 0x1a4f8, 0x1a5f0, 0x1a61c, 0x1a638, 0x1a670, 0x1a67e, 0x1a6e0, 0x1a6fc, 0x1a702, 0x1a704, 0x1a708, 0x1a710, 0x1a71e, 0x1a720, 0x1a73c, 0x1a740, 0x1a778, 0x1a786, 0x1a78c, 0x1a798, 0x1a7b0, 0x1a7be, 0x1a7ce, 0x1a7dc, 0x1a7e2, 0x1a7e4, 0x1a7e8, 0x1a830, 0x1a860, 0x1a87c, 0x1a8c0, 0x1a8f8, 0x1a9f0, 0x1abe0, 0x1ac70, 0x1ac7e, 0x1ace0, 0x1acfc, 0x1adc0, 0x1adf8, 0x1ae04, 0x1ae08, 0x1ae10, 0x1ae20, 0x1ae3c, 0x1ae40, 0x1ae78, 0x1aef0, 0x1af06, 0x1af0c, 0x1af18, 0x1af30, 0x1af3e, 0x1af60, 0x1af7c, 0x1af8e, 0x1af9c, 0x1afb8, 0x1afc4, 0x1afc8, 0x1afd0, 0x1afde, 0x1b042, 0x1b05e, 0x1b07a, 0x1b082, 0x1b084, 0x1b088, 0x1b090, 0x1b09e, 0x1b0a0, 0x1b0bc, 0x1b0cc, 0x1b0f2, 0x1b0f4, 0x1b102, 0x1b104, 0x1b108, 0x1b110, 0x1b11e, 0x1b120, 0x1b13c, 0x1b140, 0x1b178, 0x1b186, 0x1b198, 0x1b1ce, 0x1b1e2, 0x1b1e4, 0x1b1e8, 0x1b204, 0x1b208, 0x1b210, 0x1b21e, 0x1b220, 0x1b23c, 0x1b240, 0x1b278, 0x1b2f0, 0x1b30c, 0x1b33e, 0x1b360, 0x1b39c, 0x1b3c2, 0x1b3c4, 0x1b3c8, 0x1b3d0, 0x1b3e6, 0x1b410, 0x1b41e, 0x1b420, 0x1b43c, 0x1b440, 0x1b478, 0x1b4f0, 0x1b5e0, 0x1b618, 0x1b660, 0x1b67c, 0x1b6c0, 0x1b738, 0x1b782, 0x1b784, 0x1b788, 0x1b790, 0x1b79e, 0x1b7a0, 0x1b7cc, 0x1b82e, 0x1b84e, 0x1b85c, 0x1b88e, 0x1b89c, 0x1b8b8, 0x1b8c2, 0x1b8c4, 0x1b8c8, 0x1b8d0, 0x1b8e6, 0x1b8fa, 0x1b90e, 0x1b91c, 0x1b938, 0x1b970, 0x1b97e, 0x1b982, 0x1b984, 0x1b988, 0x1b990, 0x1b99e, 0x1b9a0, 0x1b9cc, 0x1b9f2, 0x1b9f4, 0x1ba0e, 0x1ba1c, 0x1ba38, 0x1ba70, 0x1ba7e, 0x1bae0, 0x1bafc, 0x1bb08, 0x1bb10, 0x1bb20, 0x1bb3c, 0x1bb40, 0x1bb98, 0x1bbce, 0x1bbe2, 0x1bbe4, 0x1bbe8, 0x1bc16, 0x1bc26, 0x1bc2c, 0x1bc46, 0x1bc4c, 0x1bc58, 0x1bc72, 0x1bc74, 0x1bc86, 0x1bc8c, 0x1bc98, 0x1bcb0, 0x1bcbe, 0x1bcce, 0x1bce2, 0x1bce4, 0x1bce8, 0x1bd06, 0x1bd0c, 0x1bd18, 0x1bd30, 0x1bd3e, 0x1bd60, 0x1bd7c, 0x1bd9c, 0x1bdc2, 0x1bdc4, 0x1bdc8, 0x1bdd0, 0x1bde6, 0x1bdfa, 0x1be12, 0x1be14, 0x1be22, 0x1be24, 0x1be28, 0x1be42, 0x1be44, 0x1be48, 0x1be50, 0x1be5e, 0x1be66, 0x1be82, 0x1be84, 0x1be88, 0x1be90, 0x1be9e, 0x1bea0, 0x1bebc, 0x1becc, 0x1bef4, 0x1bf1a, 0x1bf2e, 0x1bf32, 0x1bf34, 0x1bf4e, 0x1bf5c, 0x1bf62, 0x1bf64, 0x1bf68, 0x1c09a, 0x1c0b2, 0x1c0b4, 0x1c11a, 0x1c132, 0x1c134, 0x1c162, 0x1c164, 0x1c168, 0x1c176, 0x1c1ba, 0x1c21a, 0x1c232, 0x1c234, 0x1c24e, 0x1c25c, 0x1c262, 0x1c264, 0x1c268, 0x1c276, 0x1c28e, 0x1c2c2, 0x1c2c4, 0x1c2c8, 0x1c2d0, 0x1c2de, 0x1c2e6, 0x1c2ec, 0x1c2fa, 0x1c316, 0x1c326, 0x1c33a, 0x1c346, 0x1c34c, 0x1c372, 0x1c374, 0x1c41a, 0x1c42e, 0x1c432, 0x1c434, 0x1c44e, 0x1c45c, 0x1c462, 0x1c464, 0x1c468, 0x1c476, 0x1c48e, 0x1c49c, 0x1c4b8, 0x1c4c2, 0x1c4c8, 0x1c4d0, 0x1c4de, 0x1c4e6, 0x1c4ec, 0x1c4fa, 0x1c51c, 0x1c538, 0x1c570, 0x1c57e, 0x1c582, 0x1c584, 0x1c588, 0x1c590, 0x1c59e, 0x1c5a0, 0x1c5bc, 0x1c5c6, 0x1c5cc, 0x1c5d8, 0x1c5ee, 0x1c5f2, 0x1c5f4, 0x1c616, 0x1c626, 0x1c62c, 0x1c63a, 0x1c646, 0x1c64c, 0x1c658, 0x1c66e, 0x1c672, 0x1c674, 0x1c686, 0x1c68c, 0x1c698, 0x1c6b0, 0x1c6be, 0x1c6ce, 0x1c6dc, 0x1c6e2, 0x1c6e4, 0x1c6e8, 0x1c712, 0x1c714, 0x1c722, 0x1c728, 0x1c736, 0x1c742, 0x1c744, 0x1c748, 0x1c750, 0x1c75e, 0x1c766, 0x1c76c, 0x1c77a, 0x1c7ae, 0x1c7d6, 0x1c7ea, 0x1c81a, 0x1c82e, 0x1c832, 0x1c834, 0x1c84e, 0x1c85c, 0x1c862, 0x1c864, 0x1c868, 0x1c876, 0x1c88e, 0x1c89c, 0x1c8b8, 0x1c8c2, 0x1c8c8, 0x1c8d0, 0x1c8de, 0x1c8e6, 0x1c8ec, 0x1c8fa, 0x1c90e, 0x1c938, 0x1c970, 0x1c97e, 0x1c982, 0x1c984, 0x1c990, 0x1c99e, 0x1c9a0, 0x1c9bc, 0x1c9c6, 0x1c9cc, 0x1c9d8, 0x1c9ee, 0x1c9f2, 0x1c9f4, 0x1ca38, 0x1ca70, 0x1ca7e, 0x1cae0, 0x1cafc, 0x1cb02, 0x1cb04, 0x1cb08, 0x1cb10, 0x1cb20, 0x1cb3c, 0x1cb40, 0x1cb78, 0x1cb86, 0x1cb8c, 0x1cb98, 0x1cbb0, 0x1cbbe, 0x1cbce, 0x1cbdc, 0x1cbe2, 0x1cbe4, 0x1cbe8, 0x1cbf6, 0x1cc16, 0x1cc26, 0x1cc2c, 0x1cc3a, 0x1cc46, 0x1cc58, 0x1cc72, 0x1cc74, 0x1cc86, 0x1ccb0, 0x1ccbe, 0x1ccce, 0x1cce2, 0x1cce4, 0x1cce8, 0x1cd06, 0x1cd0c, 0x1cd18, 0x1cd30, 0x1cd3e, 0x1cd60, 0x1cd7c, 0x1cd9c, 0x1cdc2, 0x1cdc4, 0x1cdc8, 0x1cdd0, 0x1cdde, 0x1cde6, 0x1cdfa, 0x1ce22, 0x1ce28, 0x1ce42, 0x1ce50, 0x1ce5e, 0x1ce66, 0x1ce7a, 0x1ce82, 0x1ce84, 0x1ce88, 0x1ce90, 0x1ce9e, 0x1cea0, 0x1cebc, 0x1cecc, 0x1cef2, 0x1cef4, 0x1cf2e, 0x1cf32, 0x1cf34, 0x1cf4e, 0x1cf5c, 0x1cf62, 0x1cf64, 0x1cf68, 0x1cf96, 0x1cfa6, 0x1cfac, 0x1cfca, 0x1cfd2, 0x1cfd4, 0x1d02e, 0x1d032, 0x1d034, 0x1d04e, 0x1d05c, 0x1d062, 0x1d064, 0x1d068, 0x1d076, 0x1d08e, 0x1d09c, 0x1d0b8, 0x1d0c2, 0x1d0c4, 0x1d0c8, 0x1d0d0, 0x1d0de, 0x1d0e6, 0x1d0ec, 0x1d0fa, 0x1d11c, 0x1d138, 0x1d170, 0x1d17e, 0x1d182, 0x1d184, 0x1d188, 0x1d190, 0x1d19e, 0x1d1a0, 0x1d1bc, 0x1d1c6, 0x1d1cc, 0x1d1d8, 0x1d1ee, 0x1d1f2, 0x1d1f4, 0x1d21c, 0x1d238, 0x1d270, 0x1d27e, 0x1d2e0, 0x1d2fc, 0x1d302, 0x1d304, 0x1d308, 0x1d310, 0x1d31e, 0x1d320, 0x1d33c, 0x1d340, 0x1d378, 0x1d386, 0x1d38c, 0x1d398, 0x1d3b0, 0x1d3be, 0x1d3ce, 0x1d3dc, 0x1d3e2, 0x1d3e4, 0x1d3e8, 0x1d3f6, 0x1d470, 0x1d47e, 0x1d4e0, 0x1d4fc, 0x1d5c0, 0x1d5f8, 0x1d604, 0x1d608, 0x1d610, 0x1d620, 0x1d640, 0x1d678, 0x1d6f0, 0x1d706, 0x1d70c, 0x1d718, 0x1d730, 0x1d73e, 0x1d760, 0x1d77c, 0x1d78e, 0x1d79c, 0x1d7b8, 0x1d7c2, 0x1d7c4, 0x1d7c8, 0x1d7d0, 0x1d7de, 0x1d7e6, 0x1d7ec, 0x1d826, 0x1d82c, 0x1d83a, 0x1d846, 0x1d84c, 0x1d858, 0x1d872, 0x1d874, 0x1d886, 0x1d88c, 0x1d898, 0x1d8b0, 0x1d8be, 0x1d8ce, 0x1d8e2, 0x1d8e4, 0x1d8e8, 0x1d8f6, 0x1d90c, 0x1d918, 0x1d930, 0x1d93e, 0x1d960, 0x1d97c, 0x1d99c, 0x1d9c2, 0x1d9c4, 0x1d9c8, 0x1d9d0, 0x1d9e6, 0x1d9fa, 0x1da0c, 0x1da18, 0x1da30, 0x1da3e, 0x1da60, 0x1da7c, 0x1dac0, 0x1daf8, 0x1db38, 0x1db82, 0x1db84, 0x1db88, 0x1db90, 0x1db9e, 0x1dba0, 0x1dbcc, 0x1dbf2, 0x1dbf4, 0x1dc22, 0x1dc42, 0x1dc44, 0x1dc48, 0x1dc50, 0x1dc5e, 0x1dc66, 0x1dc7a, 0x1dc82, 0x1dc84, 0x1dc88, 0x1dc90, 0x1dc9e, 0x1dca0, 0x1dcbc, 0x1dccc, 0x1dcf2, 0x1dcf4, 0x1dd04, 0x1dd08, 0x1dd10, 0x1dd1e, 0x1dd20, 0x1dd3c, 0x1dd40, 0x1dd78, 0x1dd86, 0x1dd98, 0x1ddce, 0x1dde2, 0x1dde4, 0x1dde8, 0x1de2e, 0x1de32, 0x1de34, 0x1de4e, 0x1de5c, 0x1de62, 0x1de64, 0x1de68, 0x1de8e, 0x1de9c, 0x1deb8, 0x1dec2, 0x1dec4, 0x1dec8, 0x1ded0, 0x1dee6, 0x1defa, 0x1df16, 0x1df26, 0x1df2c, 0x1df46, 0x1df4c, 0x1df58, 0x1df72, 0x1df74, 0x1df8a, 0x1df92, 0x1df94, 0x1dfa2, 0x1dfa4, 0x1dfa8, 0x1e08a, 0x1e092, 0x1e094, 0x1e0a2, 0x1e0a4, 0x1e0a8, 0x1e0b6, 0x1e0da, 0x1e10a, 0x1e112, 0x1e114, 0x1e122, 0x1e124, 0x1e128, 0x1e136, 0x1e142, 0x1e144, 0x1e148, 0x1e150, 0x1e166, 0x1e16c, 0x1e17a, 0x1e19a, 0x1e1b2, 0x1e1b4, 0x1e20a, 0x1e212, 0x1e214, 0x1e222, 0x1e224, 0x1e228, 0x1e236, 0x1e242, 0x1e248, 0x1e250, 0x1e25e, 0x1e266, 0x1e26c, 0x1e27a, 0x1e282, 0x1e284, 0x1e288, 0x1e290, 0x1e2a0, 0x1e2bc, 0x1e2c6, 0x1e2cc, 0x1e2d8, 0x1e2ee, 0x1e2f2, 0x1e2f4, 0x1e31a, 0x1e332, 0x1e334, 0x1e35c, 0x1e362, 0x1e364, 0x1e368, 0x1e3ba, 0x1e40a, 0x1e412, 0x1e414, 0x1e422, 0x1e428, 0x1e436, 0x1e442, 0x1e448, 0x1e450, 0x1e45e, 0x1e466, 0x1e46c, 0x1e47a, 0x1e482, 0x1e484, 0x1e490, 0x1e49e, 0x1e4a0, 0x1e4bc, 0x1e4c6, 0x1e4cc, 0x1e4d8, 0x1e4ee, 0x1e4f2, 0x1e4f4, 0x1e502, 0x1e504, 0x1e508, 0x1e510, 0x1e51e, 0x1e520, 0x1e53c, 0x1e540, 0x1e578, 0x1e586, 0x1e58c, 0x1e598, 0x1e5b0, 0x1e5be, 0x1e5ce, 0x1e5dc, 0x1e5e2, 0x1e5e4, 0x1e5e8, 0x1e5f6, 0x1e61a, 0x1e62e, 0x1e632, 0x1e634, 0x1e64e, 0x1e65c, 0x1e662, 0x1e668, 0x1e68e, 0x1e69c, 0x1e6b8, 0x1e6c2, 0x1e6c4, 0x1e6c8, 0x1e6d0, 0x1e6e6, 0x1e6fa, 0x1e716, 0x1e726, 0x1e72c, 0x1e73a, 0x1e746, 0x1e74c, 0x1e758, 0x1e772, 0x1e774, 0x1e792, 0x1e794, 0x1e7a2, 0x1e7a4, 0x1e7a8, 0x1e7b6, 0x1e812, 0x1e814, 0x1e822, 0x1e824, 0x1e828, 0x1e836, 0x1e842, 0x1e844, 0x1e848, 0x1e850, 0x1e85e, 0x1e866, 0x1e86c, 0x1e87a, 0x1e882, 0x1e884, 0x1e888, 0x1e890, 0x1e89e, 0x1e8a0, 0x1e8bc, 0x1e8c6, 0x1e8cc, 0x1e8d8, 0x1e8ee, 0x1e8f2, 0x1e8f4, 0x1e902, 0x1e904, 0x1e908, 0x1e910, 0x1e920, 0x1e93c, 0x1e940, 0x1e978, 0x1e986, 0x1e98c, 0x1e998, 0x1e9b0, 0x1e9be, 0x1e9ce, 0x1e9dc, 0x1e9e2, 0x1e9e4, 0x1e9e8, 0x1e9f6, 0x1ea04, 0x1ea08, 0x1ea10, 0x1ea20, 0x1ea40, 0x1ea78, 0x1eaf0, 0x1eb06, 0x1eb0c, 0x1eb18, 0x1eb30, 0x1eb3e, 0x1eb60, 0x1eb7c, 0x1eb8e, 0x1eb9c, 0x1ebb8, 0x1ebc2, 0x1ebc4, 0x1ebc8, 0x1ebd0, 0x1ebde, 0x1ebe6, 0x1ebec, 0x1ec1a, 0x1ec2e, 0x1ec32, 0x1ec34, 0x1ec4e, 0x1ec5c, 0x1ec62, 0x1ec64, 0x1ec68, 0x1ec8e, 0x1ec9c, 0x1ecb8, 0x1ecc2, 0x1ecc4, 0x1ecc8, 0x1ecd0, 0x1ece6, 0x1ecfa, 0x1ed0e, 0x1ed1c, 0x1ed38, 0x1ed70, 0x1ed7e, 0x1ed82, 0x1ed84, 0x1ed88, 0x1ed90, 0x1ed9e, 0x1eda0, 0x1edcc, 0x1edf2, 0x1edf4, 0x1ee16, 0x1ee26, 0x1ee2c, 0x1ee3a, 0x1ee46, 0x1ee4c, 0x1ee58, 0x1ee6e, 0x1ee72, 0x1ee74, 0x1ee86, 0x1ee8c, 0x1ee98, 0x1eeb0, 0x1eebe, 0x1eece, 0x1eedc, 0x1eee2, 0x1eee4, 0x1eee8, 0x1ef12, 0x1ef22, 0x1ef24, 0x1ef28, 0x1ef36, 0x1ef42, 0x1ef44, 0x1ef48, 0x1ef50, 0x1ef5e, 0x1ef66, 0x1ef6c, 0x1ef7a, 0x1efae, 0x1efb2, 0x1efb4, 0x1efd6, 0x1f096, 0x1f0a6, 0x1f0ac, 0x1f0ba, 0x1f0ca, 0x1f0d2, 0x1f0d4, 0x1f116, 0x1f126, 0x1f12c, 0x1f13a, 0x1f146, 0x1f14c, 0x1f158, 0x1f16e, 0x1f172, 0x1f174, 0x1f18a, 0x1f192, 0x1f194, 0x1f1a2, 0x1f1a4, 0x1f1a8, 0x1f1da, 0x1f216, 0x1f226, 0x1f22c, 0x1f23a, 0x1f246, 0x1f258, 0x1f26e, 0x1f272, 0x1f274, 0x1f286, 0x1f28c, 0x1f298, 0x1f2b0, 0x1f2be, 0x1f2ce, 0x1f2dc, 0x1f2e2, 0x1f2e4, 0x1f2e8, 0x1f2f6, 0x1f30a, 0x1f312, 0x1f314, 0x1f322, 0x1f328, 0x1f342, 0x1f344, 0x1f348, 0x1f350, 0x1f35e, 0x1f366, 0x1f37a, 0x1f39a, 0x1f3ae, 0x1f3b2, 0x1f3b4, 0x1f416, 0x1f426, 0x1f42c, 0x1f43a, 0x1f446, 0x1f44c, 0x1f458, 0x1f46e, 0x1f472, 0x1f474, 0x1f486, 0x1f48c, 0x1f498, 0x1f4b0, 0x1f4be, 0x1f4ce, 0x1f4dc, 0x1f4e2, 0x1f4e4, 0x1f4e8, 0x1f4f6, 0x1f506, 0x1f50c, 0x1f518, 0x1f530, 0x1f53e, 0x1f560, 0x1f57c, 0x1f58e, 0x1f59c, 0x1f5b8, 0x1f5c2, 0x1f5c4, 0x1f5c8, 0x1f5d0, 0x1f5de, 0x1f5e6, 0x1f5ec, 0x1f5fa, 0x1f60a, 0x1f612, 0x1f614, 0x1f622, 0x1f624, 0x1f628, 0x1f636, 0x1f642, 0x1f644, 0x1f648, 0x1f650, 0x1f65e, 0x1f666, 0x1f67a, 0x1f682, 0x1f684, 0x1f688, 0x1f690, 0x1f69e, 0x1f6a0, 0x1f6bc, 0x1f6cc, 0x1f6f2, 0x1f6f4, 0x1f71a, 0x1f72e, 0x1f732, 0x1f734, 0x1f74e, 0x1f75c, 0x1f762, 0x1f764, 0x1f768, 0x1f776, 0x1f796, 0x1f7a6, 0x1f7ac, 0x1f7ba, 0x1f7d2, 0x1f7d4, 0x1f89a, 0x1f8ae, 0x1f8b2, 0x1f8b4, 0x1f8d6, 0x1f8ea, 0x1f91a, 0x1f92e, 0x1f932, 0x1f934, 0x1f94e, 0x1f95c, 0x1f962, 0x1f964, 0x1f968, 0x1f976, 0x1f996, 0x1f9a6, 0x1f9ac, 0x1f9ba, 0x1f9ca, 0x1f9d2, 0x1f9d4, 0x1fa1a, 0x1fa2e, 0x1fa32, 0x1fa34, 0x1fa4e, 0x1fa5c, 0x1fa62, 0x1fa64, 0x1fa68, 0x1fa76, 0x1fa8e, 0x1fa9c, 0x1fab8, 0x1fac2, 0x1fac4, 0x1fac8, 0x1fad0, 0x1fade, 0x1fae6, 0x1faec, 0x1fb16, 0x1fb26, 0x1fb2c, 0x1fb3a, 0x1fb46, 0x1fb4c, 0x1fb58, 0x1fb6e, 0x1fb72, 0x1fb74, 0x1fb8a, 0x1fb92, 0x1fb94, 0x1fba2, 0x1fba4, 0x1fba8, 0x1fbb6, 0x1fbda, ] -; - -/** - * This table contains to codewords for all symbols. - */ - const CODEWORD_TABLE: vec![Vec; 2787] = vec![2627, 1819, 2622, 2621, 1813, 1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865, 861, 859, 2511, 873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844, 1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815, 814, 813, 812, 2484, 817, 816, 1745, 1744, 1742, 1746, 2655, 2637, 2635, 2626, 2625, 2623, 2628, 1820, 2752, 2739, 2737, 2728, 2727, 2725, 2730, 2785, 2783, 2778, 2777, 2775, 2780, 787, 781, 747, 739, 736, 2413, 754, 752, 1719, 692, 689, 681, 2371, 678, 2369, 700, 697, 694, 703, 1688, 1686, 642, 638, 2343, 631, 2341, 627, 2338, 651, 646, 643, 2345, 654, 652, 1652, 1650, 1647, 1654, 601, 599, 2322, 596, 2321, 594, 2319, 2317, 611, 610, 608, 606, 2324, 603, 2323, 615, 614, 612, 1617, 1616, 1614, 1612, 616, 1619, 1618, 2575, 2538, 2536, 905, 901, 898, 909, 2509, 2507, 2504, 870, 867, 864, 860, 2512, 875, 872, 1781, 2490, 2489, 2487, 2485, 1748, 836, 834, 832, 830, 2494, 827, 2492, 843, 841, 839, 845, 1765, 1763, 2701, 2676, 2674, 2653, 2648, 2656, 2634, 2633, 2631, 2629, 1821, 2638, 2636, 2770, 2763, 2761, 2750, 2745, 2753, 2736, 2735, 2733, 2731, 1848, 2740, 2738, 2786, 2784, 591, 588, 576, 569, 566, 2296, 1590, 537, 534, 526, 2276, 522, 2274, 545, 542, 539, 548, 1572, 1570, 481, 2245, 466, 2242, 462, 2239, 492, 485, 482, 2249, 496, 494, 1534, 1531, 1528, 1538, 413, 2196, 406, 2191, 2188, 425, 419, 2202, 415, 2199, 432, 430, 427, 1472, 1467, 1464, 433, 1476, 1474, 368, 367, 2160, 365, 2159, 362, 2157, 2155, 2152, 378, 377, 375, 2166, 372, 2165, 369, 2162, 383, 381, 379, 2168, 1419, 1418, 1416, 1414, 385, 1411, 384, 1423, 1422, 1420, 1424, 2461, 802, 2441, 2439, 790, 786, 783, 794, 2409, 2406, 2403, 750, 742, 738, 2414, 756, 753, 1720, 2367, 2365, 2362, 2359, 1663, 693, 691, 684, 2373, 680, 2370, 702, 699, 696, 704, 1690, 1687, 2337, 2336, 2334, 2332, 1624, 2329, 1622, 640, 637, 2344, 634, 2342, 630, 2340, 650, 648, 645, 2346, 655, 653, 1653, 1651, 1649, 1655, 2612, 2597, 2595, 2571, 2568, 2565, 2576, 2534, 2529, 2526, 1787, 2540, 2537, 907, 904, 900, 910, 2503, 2502, 2500, 2498, 1768, 2495, 1767, 2510, 2508, 2506, 869, 866, 863, 2513, 876, 874, 1782, 2720, 2713, 2711, 2697, 2694, 2691, 2702, 2672, 2670, 2664, 1828, 2678, 2675, 2647, 2646, 2644, 2642, 1823, 2639, 1822, 2654, 2652, 2650, 2657, 2771, 1855, 2765, 2762, 1850, 1849, 2751, 2749, 2747, 2754, 353, 2148, 344, 342, 336, 2142, 332, 2140, 345, 1375, 1373, 306, 2130, 299, 2128, 295, 2125, 319, 314, 311, 2132, 1354, 1352, 1349, 1356, 262, 257, 2101, 253, 2096, 2093, 274, 273, 267, 2107, 263, 2104, 280, 278, 275, 1316, 1311, 1308, 1320, 1318, 2052, 202, 2050, 2044, 2040, 219, 2063, 212, 2060, 208, 2055, 224, 221, 2066, 1260, 1258, 1252, 231, 1248, 229, 1266, 1264, 1261, 1268, 155, 1998, 153, 1996, 1994, 1991, 1988, 165, 164, 2007, 162, 2006, 159, 2003, 2000, 172, 171, 169, 2012, 166, 2010, 1186, 1184, 1182, 1179, 175, 1176, 173, 1192, 1191, 1189, 1187, 176, 1194, 1193, 2313, 2307, 2305, 592, 589, 2294, 2292, 2289, 578, 572, 568, 2297, 580, 1591, 2272, 2267, 2264, 1547, 538, 536, 529, 2278, 525, 2275, 547, 544, 541, 1574, 1571, 2237, 2235, 2229, 1493, 2225, 1489, 478, 2247, 470, 2244, 465, 2241, 493, 488, 484, 2250, 498, 495, 1536, 1533, 1530, 1539, 2187, 2186, 2184, 2182, 1432, 2179, 1430, 2176, 1427, 414, 412, 2197, 409, 2195, 405, 2193, 2190, 426, 424, 421, 2203, 418, 2201, 431, 429, 1473, 1471, 1469, 1466, 434, 1477, 1475, 2478, 2472, 2470, 2459, 2457, 2454, 2462, 803, 2437, 2432, 2429, 1726, 2443, 2440, 792, 789, 785, 2401, 2399, 2393, 1702, 2389, 1699, 2411, 2408, 2405, 745, 741, 2415, 758, 755, 1721, 2358, 2357, 2355, 2353, 1661, 2350, 1660, 2347, 1657, 2368, 2366, 2364, 2361, 1666, 690, 687, 2374, 683, 2372, 701, 698, 705, 1691, 1689, 2619, 2617, 2610, 2608, 2605, 2613, 2593, 2588, 2585, 1803, 2599, 2596, 2563, 2561, 2555, 1797, 2551, 1795, 2573, 2570, 2567, 2577, 2525, 2524, 2522, 2520, 1786, 2517, 1785, 2514, 1783, 2535, 2533, 2531, 2528, 1788, 2541, 2539, 906, 903, 911, 2721, 1844, 2715, 2712, 1838, 1836, 2699, 2696, 2693, 2703, 1827, 1826, 1824, 2673, 2671, 2669, 2666, 1829, 2679, 2677, 1858, 1857, 2772, 1854, 1853, 1851, 1856, 2766, 2764, 143, 1987, 139, 1986, 135, 133, 131, 1984, 128, 1983, 125, 1981, 138, 137, 136, 1985, 1133, 1132, 1130, 112, 110, 1974, 107, 1973, 104, 1971, 1969, 122, 121, 119, 117, 1977, 114, 1976, 124, 1115, 1114, 1112, 1110, 1117, 1116, 84, 83, 1953, 81, 1952, 78, 1950, 1948, 1945, 94, 93, 91, 1959, 88, 1958, 85, 1955, 99, 97, 95, 1961, 1086, 1085, 1083, 1081, 1078, 100, 1090, 1089, 1087, 1091, 49, 47, 1917, 44, 1915, 1913, 1910, 1907, 59, 1926, 56, 1925, 53, 1922, 1919, 66, 64, 1931, 61, 1929, 1042, 1040, 1038, 71, 1035, 70, 1032, 68, 1048, 1047, 1045, 1043, 1050, 1049, 12, 10, 1869, 1867, 1864, 1861, 21, 1880, 19, 1877, 1874, 1871, 28, 1888, 25, 1886, 22, 1883, 982, 980, 977, 974, 32, 30, 991, 989, 987, 984, 34, 995, 994, 992, 2151, 2150, 2147, 2146, 2144, 356, 355, 354, 2149, 2139, 2138, 2136, 2134, 1359, 343, 341, 338, 2143, 335, 2141, 348, 347, 346, 1376, 1374, 2124, 2123, 2121, 2119, 1326, 2116, 1324, 310, 308, 305, 2131, 302, 2129, 298, 2127, 320, 318, 316, 313, 2133, 322, 321, 1355, 1353, 1351, 1357, 2092, 2091, 2089, 2087, 1276, 2084, 1274, 2081, 1271, 259, 2102, 256, 2100, 252, 2098, 2095, 272, 269, 2108, 266, 2106, 281, 279, 277, 1317, 1315, 1313, 1310, 282, 1321, 1319, 2039, 2037, 2035, 2032, 1203, 2029, 1200, 1197, 207, 2053, 205, 2051, 201, 2049, 2046, 2043, 220, 218, 2064, 215, 2062, 211, 2059, 228, 226, 223, 2069, 1259, 1257, 1254, 232, 1251, 230, 1267, 1265, 1263, 2316, 2315, 2312, 2311, 2309, 2314, 2304, 2303, 2301, 2299, 1593, 2308, 2306, 590, 2288, 2287, 2285, 2283, 1578, 2280, 1577, 2295, 2293, 2291, 579, 577, 574, 571, 2298, 582, 581, 1592, 2263, 2262, 2260, 2258, 1545, 2255, 1544, 2252, 1541, 2273, 2271, 2269, 2266, 1550, 535, 532, 2279, 528, 2277, 546, 543, 549, 1575, 1573, 2224, 2222, 2220, 1486, 2217, 1485, 2214, 1482, 1479, 2238, 2236, 2234, 2231, 1496, 2228, 1492, 480, 477, 2248, 473, 2246, 469, 2243, 490, 487, 2251, 497, 1537, 1535, 1532, 2477, 2476, 2474, 2479, 2469, 2468, 2466, 2464, 1730, 2473, 2471, 2453, 2452, 2450, 2448, 1729, 2445, 1728, 2460, 2458, 2456, 2463, 805, 804, 2428, 2427, 2425, 2423, 1725, 2420, 1724, 2417, 1722, 2438, 2436, 2434, 2431, 1727, 2444, 2442, 793, 791, 788, 795, 2388, 2386, 2384, 1697, 2381, 1696, 2378, 1694, 1692, 2402, 2400, 2398, 2395, 1703, 2392, 1701, 2412, 2410, 2407, 751, 748, 744, 2416, 759, 757, 1807, 2620, 2618, 1806, 1805, 2611, 2609, 2607, 2614, 1802, 1801, 1799, 2594, 2592, 2590, 2587, 1804, 2600, 2598, 1794, 1793, 1791, 1789, 2564, 2562, 2560, 2557, 1798, 2554, 1796, 2574, 2572, 2569, 2578, 1847, 1846, 2722, 1843, 1842, 1840, 1845, 2716, 2714, 1835, 1834, 1832, 1830, 1839, 1837, 2700, 2698, 2695, 2704, 1817, 1811, 1810, 897, 862, 1777, 829, 826, 838, 1760, 1758, 808, 2481, 1741, 1740, 1738, 1743, 2624, 1818, 2726, 2776, 782, 740, 737, 1715, 686, 679, 695, 1682, 1680, 639, 628, 2339, 647, 644, 1645, 1643, 1640, 1648, 602, 600, 597, 595, 2320, 593, 2318, 609, 607, 604, 1611, 1610, 1608, 1606, 613, 1615, 1613, 2328, 926, 924, 892, 886, 899, 857, 850, 2505, 1778, 824, 823, 821, 819, 2488, 818, 2486, 833, 831, 828, 840, 1761, 1759, 2649, 2632, 2630, 2746, 2734, 2732, 2782, 2781, 570, 567, 1587, 531, 527, 523, 540, 1566, 1564, 476, 467, 463, 2240, 486, 483, 1524, 1521, 1518, 1529, 411, 403, 2192, 399, 2189, 423, 416, 1462, 1457, 1454, 428, 1468, 1465, 2210, 366, 363, 2158, 360, 2156, 357, 2153, 376, 373, 370, 2163, 1410, 1409, 1407, 1405, 382, 1402, 380, 1417, 1415, 1412, 1421, 2175, 2174, 777, 774, 771, 784, 732, 725, 722, 2404, 743, 1716, 676, 674, 668, 2363, 665, 2360, 685, 1684, 1681, 626, 624, 622, 2335, 620, 2333, 617, 2330, 641, 635, 649, 1646, 1644, 1642, 2566, 928, 925, 2530, 2527, 894, 891, 888, 2501, 2499, 2496, 858, 856, 854, 851, 1779, 2692, 2668, 2665, 2645, 2643, 2640, 2651, 2768, 2759, 2757, 2744, 2743, 2741, 2748, 352, 1382, 340, 337, 333, 1371, 1369, 307, 300, 296, 2126, 315, 312, 1347, 1342, 1350, 261, 258, 250, 2097, 246, 2094, 271, 268, 264, 1306, 1301, 1298, 276, 1312, 1309, 2115, 203, 2048, 195, 2045, 191, 2041, 213, 209, 2056, 1246, 1244, 1238, 225, 1234, 222, 1256, 1253, 1249, 1262, 2080, 2079, 154, 1997, 150, 1995, 147, 1992, 1989, 163, 160, 2004, 156, 2001, 1175, 1174, 1172, 1170, 1167, 170, 1164, 167, 1185, 1183, 1180, 1177, 174, 1190, 1188, 2025, 2024, 2022, 587, 586, 564, 559, 556, 2290, 573, 1588, 520, 518, 512, 2268, 508, 2265, 530, 1568, 1565, 461, 457, 2233, 450, 2230, 446, 2226, 479, 471, 489, 1526, 1523, 1520, 397, 395, 2185, 392, 2183, 389, 2180, 2177, 410, 2194, 402, 422, 1463, 1461, 1459, 1456, 1470, 2455, 799, 2433, 2430, 779, 776, 773, 2397, 2394, 2390, 734, 728, 724, 746, 1717, 2356, 2354, 2351, 2348, 1658, 677, 675, 673, 670, 667, 688, 1685, 1683, 2606, 2589, 2586, 2559, 2556, 2552, 927, 2523, 2521, 2518, 2515, 1784, 2532, 895, 893, 890, 2718, 2709, 2707, 2689, 2687, 2684, 2663, 2662, 2660, 2658, 1825, 2667, 2769, 1852, 2760, 2758, 142, 141, 1139, 1138, 134, 132, 129, 126, 1982, 1129, 1128, 1126, 1131, 113, 111, 108, 105, 1972, 101, 1970, 120, 118, 115, 1109, 1108, 1106, 1104, 123, 1113, 1111, 82, 79, 1951, 75, 1949, 72, 1946, 92, 89, 86, 1956, 1077, 1076, 1074, 1072, 98, 1069, 96, 1084, 1082, 1079, 1088, 1968, 1967, 48, 45, 1916, 42, 1914, 39, 1911, 1908, 60, 57, 54, 1923, 50, 1920, 1031, 1030, 1028, 1026, 67, 1023, 65, 1020, 62, 1041, 1039, 1036, 1033, 69, 1046, 1044, 1944, 1943, 1941, 11, 9, 1868, 7, 1865, 1862, 1859, 20, 1878, 16, 1875, 13, 1872, 970, 968, 966, 963, 29, 960, 26, 23, 983, 981, 978, 975, 33, 971, 31, 990, 988, 985, 1906, 1904, 1902, 993, 351, 2145, 1383, 331, 330, 328, 326, 2137, 323, 2135, 339, 1372, 1370, 294, 293, 291, 289, 2122, 286, 2120, 283, 2117, 309, 303, 317, 1348, 1346, 1344, 245, 244, 242, 2090, 239, 2088, 236, 2085, 2082, 260, 2099, 249, 270, 1307, 1305, 1303, 1300, 1314, 189, 2038, 186, 2036, 183, 2033, 2030, 2026, 206, 198, 2047, 194, 216, 1247, 1245, 1243, 1240, 227, 1237, 1255, 2310, 2302, 2300, 2286, 2284, 2281, 565, 563, 561, 558, 575, 1589, 2261, 2259, 2256, 2253, 1542, 521, 519, 517, 514, 2270, 511, 533, 1569, 1567, 2223, 2221, 2218, 2215, 1483, 2211, 1480, 459, 456, 453, 2232, 449, 474, 491, 1527, 1525, 1522, 2475, 2467, 2465, 2451, 2449, 2446, 801, 800, 2426, 2424, 2421, 2418, 1723, 2435, 780, 778, 775, 2387, 2385, 2382, 2379, 1695, 2375, 1693, 2396, 735, 733, 730, 727, 749, 1718, 2616, 2615, 2604, 2603, 2601, 2584, 2583, 2581, 2579, 1800, 2591, 2550, 2549, 2547, 2545, 1792, 2542, 1790, 2558, 929, 2719, 1841, 2710, 2708, 1833, 1831, 2690, 2688, 2686, 1815, 1809, 1808, 1774, 1756, 1754, 1737, 1736, 1734, 1739, 1816, 1711, 1676, 1674, 633, 629, 1638, 1636, 1633, 1641, 598, 1605, 1604, 1602, 1600, 605, 1609, 1607, 2327, 887, 853, 1775, 822, 820, 1757, 1755, 1584, 524, 1560, 1558, 468, 464, 1514, 1511, 1508, 1519, 408, 404, 400, 1452, 1447, 1444, 417, 1458, 1455, 2208, 364, 361, 358, 2154, 1401, 1400, 1398, 1396, 374, 1393, 371, 1408, 1406, 1403, 1413, 2173, 2172, 772, 726, 723, 1712, 672, 669, 666, 682, 1678, 1675, 625, 623, 621, 618, 2331, 636, 632, 1639, 1637, 1635, 920, 918, 884, 880, 889, 849, 848, 847, 846, 2497, 855, 852, 1776, 2641, 2742, 2787, 1380, 334, 1367, 1365, 301, 297, 1340, 1338, 1335, 1343, 255, 251, 247, 1296, 1291, 1288, 265, 1302, 1299, 2113, 204, 196, 192, 2042, 1232, 1230, 1224, 214, 1220, 210, 1242, 1239, 1235, 1250, 2077, 2075, 151, 148, 1993, 144, 1990, 1163, 1162, 1160, 1158, 1155, 161, 1152, 157, 1173, 1171, 1168, 1165, 168, 1181, 1178, 2021, 2020, 2018, 2023, 585, 560, 557, 1585, 516, 509, 1562, 1559, 458, 447, 2227, 472, 1516, 1513, 1510, 398, 396, 393, 390, 2181, 386, 2178, 407, 1453, 1451, 1449, 1446, 420, 1460, 2209, 769, 764, 720, 712, 2391, 729, 1713, 664, 663, 661, 659, 2352, 656, 2349, 671, 1679, 1677, 2553, 922, 919, 2519, 2516, 885, 883, 881, 2685, 2661, 2659, 2767, 2756, 2755, 140, 1137, 1136, 130, 127, 1125, 1124, 1122, 1127, 109, 106, 102, 1103, 1102, 1100, 1098, 116, 1107, 1105, 1980, 80, 76, 73, 1947, 1068, 1067, 1065, 1063, 90, 1060, 87, 1075, 1073, 1070, 1080, 1966, 1965, 46, 43, 40, 1912, 36, 1909, 1019, 1018, 1016, 1014, 58, 1011, 55, 1008, 51, 1029, 1027, 1024, 1021, 63, 1037, 1034, 1940, 1939, 1937, 1942, 8, 1866, 4, 1863, 1, 1860, 956, 954, 952, 949, 946, 17, 14, 969, 967, 964, 961, 27, 957, 24, 979, 976, 972, 1901, 1900, 1898, 1896, 986, 1905, 1903, 350, 349, 1381, 329, 327, 324, 1368, 1366, 292, 290, 287, 284, 2118, 304, 1341, 1339, 1337, 1345, 243, 240, 237, 2086, 233, 2083, 254, 1297, 1295, 1293, 1290, 1304, 2114, 190, 187, 184, 2034, 180, 2031, 177, 2027, 199, 1233, 1231, 1229, 1226, 217, 1223, 1241, 2078, 2076, 584, 555, 554, 552, 550, 2282, 562, 1586, 507, 506, 504, 502, 2257, 499, 2254, 515, 1563, 1561, 445, 443, 441, 2219, 438, 2216, 435, 2212, 460, 454, 475, 1517, 1515, 1512, 2447, 798, 797, 2422, 2419, 770, 768, 766, 2383, 2380, 2376, 721, 719, 717, 714, 731, 1714, 2602, 2582, 2580, 2548, 2546, 2543, 923, 921, 2717, 2706, 2705, 2683, 2682, 2680, 1771, 1752, 1750, 1733, 1732, 1731, 1735, 1814, 1707, 1670, 1668, 1631, 1629, 1626, 1634, 1599, 1598, 1596, 1594, 1603, 1601, 2326, 1772, 1753, 1751, 1581, 1554, 1552, 1504, 1501, 1498, 1509, 1442, 1437, 1434, 401, 1448, 1445, 2206, 1392, 1391, 1389, 1387, 1384, 359, 1399, 1397, 1394, 1404, 2171, 2170, 1708, 1672, 1669, 619, 1632, 1630, 1628, 1773, 1378, 1363, 1361, 1333, 1328, 1336, 1286, 1281, 1278, 248, 1292, 1289, 2111, 1218, 1216, 1210, 197, 1206, 193, 1228, 1225, 1221, 1236, 2073, 2071, 1151, 1150, 1148, 1146, 152, 1143, 149, 1140, 145, 1161, 1159, 1156, 1153, 158, 1169, 1166, 2017, 2016, 2014, 2019, 1582, 510, 1556, 1553, 452, 448, 1506, 1500, 394, 391, 387, 1443, 1441, 1439, 1436, 1450, 2207, 765, 716, 713, 1709, 662, 660, 657, 1673, 1671, 916, 914, 879, 878, 877, 882, 1135, 1134, 1121, 1120, 1118, 1123, 1097, 1096, 1094, 1092, 103, 1101, 1099, 1979, 1059, 1058, 1056, 1054, 77, 1051, 74, 1066, 1064, 1061, 1071, 1964, 1963, 1007, 1006, 1004, 1002, 999, 41, 996, 37, 1017, 1015, 1012, 1009, 52, 1025, 1022, 1936, 1935, 1933, 1938, 942, 940, 938, 935, 932, 5, 2, 955, 953, 950, 947, 18, 943, 15, 965, 962, 958, 1895, 1894, 1892, 1890, 973, 1899, 1897, 1379, 325, 1364, 1362, 288, 285, 1334, 1332, 1330, 241, 238, 234, 1287, 1285, 1283, 1280, 1294, 2112, 188, 185, 181, 178, 2028, 1219, 1217, 1215, 1212, 200, 1209, 1227, 2074, 2072, 583, 553, 551, 1583, 505, 503, 500, 513, 1557, 1555, 444, 442, 439, 436, 2213, 455, 451, 1507, 1505, 1502, 796, 763, 762, 760, 767, 711, 710, 708, 706, 2377, 718, 715, 1710, 2544, 917, 915, 2681, 1627, 1597, 1595, 2325, 1769, 1749, 1747, 1499, 1438, 1435, 2204, 1390, 1388, 1385, 1395, 2169, 2167, 1704, 1665, 1662, 1625, 1623, 1620, 1770, 1329, 1282, 1279, 2109, 1214, 1207, 1222, 2068, 2065, 1149, 1147, 1144, 1141, 146, 1157, 1154, 2013, 2011, 2008, 2015, 1579, 1549, 1546, 1495, 1487, 1433, 1431, 1428, 1425, 388, 1440, 2205, 1705, 658, 1667, 1664, 1119, 1095, 1093, 1978, 1057, 1055, 1052, 1062, 1962, 1960, 1005, 1003, 1000, 997, 38, 1013, 1010, 1932, 1930, 1927, 1934, 941, 939, 936, 933, 6, 930, 3, 951, 948, 944, 1889, 1887, 1884, 1881, 959, 1893, 1891, 35, 1377, 1360, 1358, 1327, 1325, 1322, 1331, 1277, 1275, 1272, 1269, 235, 1284, 2110, 1205, 1204, 1201, 1198, 182, 1195, 179, 1213, 2070, 2067, 1580, 501, 1551, 1548, 440, 437, 1497, 1494, 1490, 1503, 761, 709, 707, 1706, 913, 912, 2198, 1386, 2164, 2161, 1621, 1766, 2103, 1208, 2058, 2054, 1145, 1142, 2005, 2002, 1999, 2009, 1488, 1429, 1426, 2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954, 1001, 998, 1924, 1921, 1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882, 1323, 1273, 1270, 2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576, 1543, 1540, 1484, 1481, 1478, 1491, 1700, ] -; -pub struct PDF417Common { -} - -impl PDF417Common { - - fn new() -> PDF417Common { - } - - /** - * @param moduleBitCount values to sum - * @return sum of values - * @deprecated call {@link MathUtils#sum(int[])} - */ - pub fn get_bit_count_sum( module_bit_count: &Vec) -> i32 { - return MathUtils::sum(&module_bit_count); - } - - pub fn to_int_array( list: &Collection) -> Vec { - if list == null || list.is_empty() { - return EMPTY_INT_ARRAY; - } - let mut result: [i32; list.size()] = [0; list.size()]; - let mut i: i32 = 0; - for let integer: Integer in list { - result[i += 1 !!!check!!! post increment] = integer; - } - return result; - } - - /** - * @param symbol encoded symbol to translate to a codeword - * @return the codeword corresponding to the symbol. - */ - pub fn get_codeword( symbol: i32) -> i32 { - let i: i32 = Arrays::binary_search(&SYMBOL_TABLE, symbol & 0x3FFFF); - if i < 0 { - return -1; - } - return (CODEWORD_TABLE[i] - 1) % NUMBER_OF_CODEWORDS; - } -} - diff --git a/port_src/output/zxing/pdf417/p_d_f417_reader.rs b/port_src/output/zxing/pdf417/p_d_f417_reader.rs deleted file mode 100644 index 90abb6c..0000000 --- a/port_src/output/zxing/pdf417/p_d_f417_reader.rs +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// package com::google::zxing::pdf417; - -/** - * This implementation can detect and decode PDF417 codes in an image. - * - * @author Guenther Grau - */ - - const EMPTY_RESULT_ARRAY: [Option; 0] = [None; 0]; -#[derive(Reader, MultipleBarcodeReader)] -pub struct PDF417Reader { -} - -impl PDF417Reader { - - /** - * Locates and decodes a PDF417 code in an image. - * - * @return a String representing the content encoded by the PDF417 code - * @throws NotFoundException if a PDF417 code cannot be found, - * @throws FormatException if a PDF417 cannot be decoded - */ - pub fn decode(&self, image: &BinaryBitmap) -> /* throws NotFoundException, FormatException, ChecksumException */Result> { - return Ok(::decode(image, null)); - } - - pub fn decode(&self, image: &BinaryBitmap, hints: &Map) -> /* throws NotFoundException, FormatException, ChecksumException */Result> { - let result: Vec = ::decode(image, &hints, false); - if result.len() == 0 || result[0] == null { - throw NotFoundException::get_not_found_instance(); - } - return Ok(result[0]); - } - - pub fn decode_multiple(&self, image: &BinaryBitmap) -> /* throws NotFoundException */Result, Rc> { - return Ok(self.decode_multiple(image, null)); - } - - pub fn decode_multiple(&self, image: &BinaryBitmap, hints: &Map) -> /* throws NotFoundException */Result, Rc> { - let tryResult1 = 0; - 'try1: loop { - { - return Ok(::decode(image, &hints, true)); - } - break 'try1 - } - match tryResult1 { - catch ( ignored: &FormatExceptionChecksumException | ) { - throw NotFoundException::get_not_found_instance(); - } 0 => break - } - - } - - fn decode( image: &BinaryBitmap, hints: &Map, multiple: bool) -> /* throws NotFoundException, FormatException, ChecksumException */Result, Rc> { - let results: List = ArrayList<>::new(); - let detector_result: PDF417DetectorResult = Detector::detect(image, &hints, multiple); - for let points: Vec in detector_result.get_points() { - let decoder_result: DecoderResult = PDF417ScanningDecoder::decode(&detector_result.get_bits(), points[4], points[5], points[6], points[7], &::get_min_codeword_width(points), &::get_max_codeword_width(points)); - let result: Result = Result::new(&decoder_result.get_text(), &decoder_result.get_raw_bytes(), points, BarcodeFormat::PDF_417); - result.put_metadata(ResultMetadataType::ERROR_CORRECTION_LEVEL, &decoder_result.get_e_c_level()); - let pdf417_result_metadata: PDF417ResultMetadata = decoder_result.get_other() as PDF417ResultMetadata; - if pdf417_result_metadata != null { - result.put_metadata(ResultMetadataType::PDF417_EXTRA_METADATA, pdf417_result_metadata); - } - result.put_metadata(ResultMetadataType::ORIENTATION, &detector_result.get_rotation()); - result.put_metadata(ResultMetadataType::SYMBOLOGY_IDENTIFIER, format!("]L{}", decoder_result.get_symbology_modifier())); - results.add(result); - } - return Ok(results.to_array(EMPTY_RESULT_ARRAY)); - } - - fn get_max_width( p1: &ResultPoint, p2: &ResultPoint) -> i32 { - if p1 == null || p2 == null { - return 0; - } - return Math::abs(p1.get_x() - p2.get_x()) as i32; - } - - fn get_min_width( p1: &ResultPoint, p2: &ResultPoint) -> i32 { - if p1 == null || p2 == null { - return Integer::MAX_VALUE; - } - return Math::abs(p1.get_x() - p2.get_x()) as i32; - } - - fn get_max_codeword_width( p: &Vec) -> i32 { - return Math::max(&Math::max(&::get_max_width(p[0], p[4]), ::get_max_width(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD / PDF417Common.MODULES_IN_STOP_PATTERN), &Math::max(&::get_max_width(p[1], p[5]), ::get_max_width(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD / PDF417Common.MODULES_IN_STOP_PATTERN)); - } - - fn get_min_codeword_width( p: &Vec) -> i32 { - return Math::min(&Math::min(&::get_min_width(p[0], p[4]), ::get_min_width(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD / PDF417Common.MODULES_IN_STOP_PATTERN), &Math::min(&::get_min_width(p[1], p[5]), ::get_min_width(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD / PDF417Common.MODULES_IN_STOP_PATTERN)); - } - - pub fn reset(&self) { - // nothing needs to be reset - } -} - diff --git a/port_src/output/zxing/pdf417/p_d_f417_result_metadata.rs b/port_src/output/zxing/pdf417/p_d_f417_result_metadata.rs deleted file mode 100644 index 67f5c22..0000000 --- a/port_src/output/zxing/pdf417/p_d_f417_result_metadata.rs +++ /dev/null @@ -1,180 +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::pdf417; - -/** - * @author Guenther Grau - */ -pub struct PDF417ResultMetadata { - - let segment_index: i32; - - let file_id: String; - - let last_segment: bool; - - let segment_count: i32 = -1; - - let sender: String; - - let addressee: String; - - let file_name: String; - - let file_size: i64 = -1; - - let timestamp: i64 = -1; - - let checksum: i32 = -1; - - let optional_data: Vec; -} - -impl PDF417ResultMetadata { - - /** - * The Segment ID represents the segment of the whole file distributed over different symbols. - * - * @return File segment index - */ - pub fn get_segment_index(&self) -> i32 { - return self.segment_index; - } - - pub fn set_segment_index(&self, segment_index: i32) { - self.segmentIndex = segment_index; - } - - /** - * Is the same for each related PDF417 symbol - * - * @return File ID - */ - pub fn get_file_id(&self) -> String { - return self.file_id; - } - - pub fn set_file_id(&self, file_id: &String) { - self.fileId = file_id; - } - - /** - * @return always null - * @deprecated use dedicated already parsed fields - */ - pub fn get_optional_data(&self) -> Vec { - return self.optional_data; - } - - /** - * @param optionalData old optional data format as int array - * @deprecated parse and use new fields - */ - pub fn set_optional_data(&self, optional_data: &Vec) { - self.optionalData = optional_data; - } - - /** - * @return true if it is the last segment - */ - pub fn is_last_segment(&self) -> bool { - return self.last_segment; - } - - pub fn set_last_segment(&self, last_segment: bool) { - self.lastSegment = last_segment; - } - - /** - * @return count of segments, -1 if not set - */ - pub fn get_segment_count(&self) -> i32 { - return self.segment_count; - } - - pub fn set_segment_count(&self, segment_count: i32) { - self.segmentCount = segment_count; - } - - pub fn get_sender(&self) -> String { - return self.sender; - } - - pub fn set_sender(&self, sender: &String) { - self.sender = sender; - } - - pub fn get_addressee(&self) -> String { - return self.addressee; - } - - pub fn set_addressee(&self, addressee: &String) { - self.addressee = addressee; - } - - /** - * Filename of the encoded file - * - * @return filename - */ - pub fn get_file_name(&self) -> String { - return self.file_name; - } - - pub fn set_file_name(&self, file_name: &String) { - self.fileName = file_name; - } - - /** - * filesize in bytes of the encoded file - * - * @return filesize in bytes, -1 if not set - */ - pub fn get_file_size(&self) -> i64 { - return self.file_size; - } - - pub fn set_file_size(&self, file_size: i64) { - self.fileSize = file_size; - } - - /** - * 16-bit CRC checksum using CCITT-16 - * - * @return crc checksum, -1 if not set - */ - pub fn get_checksum(&self) -> i32 { - return self.checksum; - } - - pub fn set_checksum(&self, checksum: i32) { - self.checksum = checksum; - } - - /** - * unix epock timestamp, elapsed seconds since 1970-01-01 - * - * @return elapsed seconds, -1 if not set - */ - pub fn get_timestamp(&self) -> i64 { - return self.timestamp; - } - - pub fn set_timestamp(&self, timestamp: i64) { - self.timestamp = timestamp; - } -} - diff --git a/port_src/output/zxing/pdf417/p_d_f417_writer.rs b/port_src/output/zxing/pdf417/p_d_f417_writer.rs deleted file mode 100644 index 4de238d..0000000 --- a/port_src/output/zxing/pdf417/p_d_f417_writer.rs +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// package com::google::zxing::pdf417; - -/** - * @author Jacob Haynes - * @author qwandor@google.com (Andrew Walbran) - */ - -/** - * default white space (margin) around the code - */ - const WHITE_SPACE: i32 = 30; - -/** - * default error correction level - */ - const DEFAULT_ERROR_CORRECTION_LEVEL: i32 = 2; -#[derive(Writer)] -pub struct PDF417Writer { -} - -impl PDF417Writer { - - pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32, hints: &Map) -> /* throws WriterException */Result> { - if format != BarcodeFormat::PDF_417 { - throw IllegalArgumentException::new(format!("Can only encode PDF_417, but got {}", format)); - } - let encoder: PDF417 = PDF417::new(); - let mut margin: i32 = WHITE_SPACE; - let error_correction_level: i32 = DEFAULT_ERROR_CORRECTION_LEVEL; - let auto_e_c_i: bool = false; - if hints != null { - if hints.contains_key(EncodeHintType::PDF417_COMPACT) { - encoder.set_compact(&Boolean::parse_boolean(&hints.get(EncodeHintType::PDF417_COMPACT).to_string())); - } - if hints.contains_key(EncodeHintType::PDF417_COMPACTION) { - encoder.set_compaction(&Compaction::value_of(&hints.get(EncodeHintType::PDF417_COMPACTION).to_string())); - } - if hints.contains_key(EncodeHintType::PDF417_DIMENSIONS) { - let dimensions: Dimensions = hints.get(EncodeHintType::PDF417_DIMENSIONS) as Dimensions; - encoder.set_dimensions(&dimensions.get_max_cols(), &dimensions.get_min_cols(), &dimensions.get_max_rows(), &dimensions.get_min_rows()); - } - if hints.contains_key(EncodeHintType::MARGIN) { - margin = Integer::parse_int(&hints.get(EncodeHintType::MARGIN).to_string()); - } - if hints.contains_key(EncodeHintType::ERROR_CORRECTION) { - error_correction_level = Integer::parse_int(&hints.get(EncodeHintType::ERROR_CORRECTION).to_string()); - } - if hints.contains_key(EncodeHintType::CHARACTER_SET) { - let encoding: Charset = Charset::for_name(&hints.get(EncodeHintType::CHARACTER_SET).to_string()); - encoder.set_encoding(&encoding); - } - auto_e_c_i = hints.contains_key(EncodeHintType::PDF417_AUTO_ECI) && Boolean::parse_boolean(&hints.get(EncodeHintType::PDF417_AUTO_ECI).to_string()); - } - return Ok(::bit_matrix_from_encoder(encoder, &contents, error_correction_level, width, height, margin, auto_e_c_i)); - } - - pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32) -> /* throws WriterException */Result> { - return Ok(self.encode(&contents, format, width, height, null)); - } - - /** - * Takes encoder, accounts for width/height, and retrieves bit matrix - */ - fn bit_matrix_from_encoder( encoder: &PDF417, contents: &String, error_correction_level: i32, width: i32, height: i32, margin: i32, auto_e_c_i: bool) -> /* throws WriterException */Result> { - encoder.generate_barcode_logic(&contents, error_correction_level, auto_e_c_i); - let aspect_ratio: i32 = 4; - let original_scale: Vec> = encoder.get_barcode_matrix().get_scaled_matrix(1, aspect_ratio); - let mut rotated: bool = false; - if (height > width) != (original_scale[0].len() < original_scale.len()) { - original_scale = ::rotate_array(&original_scale); - rotated = true; - } - let scale_x: i32 = width / original_scale[0].len(); - let scale_y: i32 = height / original_scale.len(); - let scale: i32 = Math::min(scale_x, scale_y); - if scale > 1 { - let scaled_matrix: Vec> = encoder.get_barcode_matrix().get_scaled_matrix(scale, scale * aspect_ratio); - if rotated { - scaled_matrix = ::rotate_array(&scaled_matrix); - } - return Ok(::bit_matrix_from_bit_array(&scaled_matrix, margin)); - } - return Ok(::bit_matrix_from_bit_array(&original_scale, margin)); - } - - /** - * This takes an array holding the values of the PDF 417 - * - * @param input a byte array of information with 0 is black, and 1 is white - * @param margin border around the barcode - * @return BitMatrix of the input - */ - fn bit_matrix_from_bit_array( input: &Vec>, margin: i32) -> BitMatrix { - // Creates the bit matrix with extra space for whitespace - let output: BitMatrix = BitMatrix::new(input[0].len() + 2 * margin, input.len() + 2 * margin); - output.clear(); - { - let mut y: i32 = 0, let y_output: i32 = output.get_height() - margin - 1; - while y < input.len() { - { - let input_y: Vec = input[y]; - { - let mut x: i32 = 0; - while x < input[0].len() { - { - // Zero is white in the byte matrix - if input_y[x] == 1 { - output.set(x + margin, y_output); - } - } - x += 1; - } - } - - } - y += 1; - y_output -= 1; - } - } - - return output; - } - - /** - * Takes and rotates the it 90 degrees - */ - fn rotate_array( bitarray: &Vec>) -> Vec> { - let mut temp: [[i8; bitarray.len()]; bitarray[0].len()] = [[0; bitarray.len()]; bitarray[0].len()]; - { - let mut ii: i32 = 0; - while ii < bitarray.len() { - { - // This makes the direction consistent on screen when rotating the - // screen; - let mut inverseii: i32 = bitarray.len() - ii - 1; - { - let mut jj: i32 = 0; - while jj < bitarray[0].len() { - { - temp[jj][inverseii] = bitarray[ii][jj]; - } - jj += 1; - } - } - - } - ii += 1; - } - } - - return temp; - } -} - diff --git a/src/oned/rss/expanded/decoders.rs b/src/oned/rss/expanded/decoders.rs index 1e1dd9c..9d96bed 100644 --- a/src/oned/rss/expanded/decoders.rs +++ b/src/oned/rss/expanded/decoders.rs @@ -1,3 +1,19 @@ +import com.google.zxing.FormatException; +import com.google.zxing.NotFoundException; +import com.google.zxing.common.BitArray; + +import com.google.zxing.FormatException; +import com.google.zxing.NotFoundException; +import com.google.zxing.common.BitArray; + +import com.google.zxing.NotFoundException; +import com.google.zxing.common.BitArray; + +import com.google.zxing.FormatException; + + + + // NEW FILE: a_i013103decoder.rs /* * Copyright (C) 2010 ZXing authors diff --git a/src/pdf417.rs b/src/pdf417.rs index e69de29..8cc2a6f 100644 --- a/src/pdf417.rs +++ b/src/pdf417.rs @@ -0,0 +1,588 @@ +import com.google.zxing.BarcodeFormat; +import com.google.zxing.BinaryBitmap; +import com.google.zxing.ChecksumException; +import com.google.zxing.DecodeHintType; +import com.google.zxing.FormatException; +import com.google.zxing.NotFoundException; +import com.google.zxing.Reader; +import com.google.zxing.Result; +import com.google.zxing.ResultMetadataType; +import com.google.zxing.ResultPoint; +import com.google.zxing.common.DecoderResult; +import com.google.zxing.multi.MultipleBarcodeReader; +import com.google.zxing.pdf417.decoder.PDF417ScanningDecoder; +import com.google.zxing.pdf417.detector.Detector; +import com.google.zxing.pdf417.detector.PDF417DetectorResult; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.Writer; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.pdf417.encoder.Compaction; +import com.google.zxing.pdf417.encoder.Dimensions; +import com.google.zxing.pdf417.encoder.PDF417; + +// NEW FILE: p_d_f417_common.rs +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::pdf417; + +/** + * @author SITA Lab (kevin.osullivan@sita.aero) + * @author Guenther Grau + */ + + const NUMBER_OF_CODEWORDS: i32 = 929; + +// Maximum Codewords (Data + Error). + const MAX_CODEWORDS_IN_BARCODE: i32 = NUMBER_OF_CODEWORDS - 1; + + const MIN_ROWS_IN_BARCODE: i32 = 3; + + const MAX_ROWS_IN_BARCODE: i32 = 90; + +// One left row indication column + max 30 data columns + one right row indicator column +//public static final int MAX_CODEWORDS_IN_ROW = 32; + const MODULES_IN_CODEWORD: i32 = 17; + + const MODULES_IN_STOP_PATTERN: i32 = 18; + + const BARS_IN_MODULE: i32 = 8; + + const EMPTY_INT_ARRAY; + +/** + * The sorted table of all possible symbols. Extracted from the PDF417 + * specification. The index of a symbol in this table corresponds to the + * index into the codeword table. + */ + const SYMBOL_TABLE: vec![Vec; 2787] = vec![0x1025e, 0x1027a, 0x1029e, 0x102bc, 0x102f2, 0x102f4, 0x1032e, 0x1034e, 0x1035c, 0x10396, 0x103a6, 0x103ac, 0x10422, 0x10428, 0x10436, 0x10442, 0x10444, 0x10448, 0x10450, 0x1045e, 0x10466, 0x1046c, 0x1047a, 0x10482, 0x1049e, 0x104a0, 0x104bc, 0x104c6, 0x104d8, 0x104ee, 0x104f2, 0x104f4, 0x10504, 0x10508, 0x10510, 0x1051e, 0x10520, 0x1053c, 0x10540, 0x10578, 0x10586, 0x1058c, 0x10598, 0x105b0, 0x105be, 0x105ce, 0x105dc, 0x105e2, 0x105e4, 0x105e8, 0x105f6, 0x1062e, 0x1064e, 0x1065c, 0x1068e, 0x1069c, 0x106b8, 0x106de, 0x106fa, 0x10716, 0x10726, 0x1072c, 0x10746, 0x1074c, 0x10758, 0x1076e, 0x10792, 0x10794, 0x107a2, 0x107a4, 0x107a8, 0x107b6, 0x10822, 0x10828, 0x10842, 0x10848, 0x10850, 0x1085e, 0x10866, 0x1086c, 0x1087a, 0x10882, 0x10884, 0x10890, 0x1089e, 0x108a0, 0x108bc, 0x108c6, 0x108cc, 0x108d8, 0x108ee, 0x108f2, 0x108f4, 0x10902, 0x10908, 0x1091e, 0x10920, 0x1093c, 0x10940, 0x10978, 0x10986, 0x10998, 0x109b0, 0x109be, 0x109ce, 0x109dc, 0x109e2, 0x109e4, 0x109e8, 0x109f6, 0x10a08, 0x10a10, 0x10a1e, 0x10a20, 0x10a3c, 0x10a40, 0x10a78, 0x10af0, 0x10b06, 0x10b0c, 0x10b18, 0x10b30, 0x10b3e, 0x10b60, 0x10b7c, 0x10b8e, 0x10b9c, 0x10bb8, 0x10bc2, 0x10bc4, 0x10bc8, 0x10bd0, 0x10bde, 0x10be6, 0x10bec, 0x10c2e, 0x10c4e, 0x10c5c, 0x10c62, 0x10c64, 0x10c68, 0x10c76, 0x10c8e, 0x10c9c, 0x10cb8, 0x10cc2, 0x10cc4, 0x10cc8, 0x10cd0, 0x10cde, 0x10ce6, 0x10cec, 0x10cfa, 0x10d0e, 0x10d1c, 0x10d38, 0x10d70, 0x10d7e, 0x10d82, 0x10d84, 0x10d88, 0x10d90, 0x10d9e, 0x10da0, 0x10dbc, 0x10dc6, 0x10dcc, 0x10dd8, 0x10dee, 0x10df2, 0x10df4, 0x10e16, 0x10e26, 0x10e2c, 0x10e46, 0x10e58, 0x10e6e, 0x10e86, 0x10e8c, 0x10e98, 0x10eb0, 0x10ebe, 0x10ece, 0x10edc, 0x10f0a, 0x10f12, 0x10f14, 0x10f22, 0x10f28, 0x10f36, 0x10f42, 0x10f44, 0x10f48, 0x10f50, 0x10f5e, 0x10f66, 0x10f6c, 0x10fb2, 0x10fb4, 0x11022, 0x11028, 0x11042, 0x11048, 0x11050, 0x1105e, 0x1107a, 0x11082, 0x11084, 0x11090, 0x1109e, 0x110a0, 0x110bc, 0x110c6, 0x110cc, 0x110d8, 0x110ee, 0x110f2, 0x110f4, 0x11102, 0x1111e, 0x11120, 0x1113c, 0x11140, 0x11178, 0x11186, 0x11198, 0x111b0, 0x111be, 0x111ce, 0x111dc, 0x111e2, 0x111e4, 0x111e8, 0x111f6, 0x11208, 0x1121e, 0x11220, 0x11278, 0x112f0, 0x1130c, 0x11330, 0x1133e, 0x11360, 0x1137c, 0x1138e, 0x1139c, 0x113b8, 0x113c2, 0x113c8, 0x113d0, 0x113de, 0x113e6, 0x113ec, 0x11408, 0x11410, 0x1141e, 0x11420, 0x1143c, 0x11440, 0x11478, 0x114f0, 0x115e0, 0x1160c, 0x11618, 0x11630, 0x1163e, 0x11660, 0x1167c, 0x116c0, 0x116f8, 0x1171c, 0x11738, 0x11770, 0x1177e, 0x11782, 0x11784, 0x11788, 0x11790, 0x1179e, 0x117a0, 0x117bc, 0x117c6, 0x117cc, 0x117d8, 0x117ee, 0x1182e, 0x11834, 0x1184e, 0x1185c, 0x11862, 0x11864, 0x11868, 0x11876, 0x1188e, 0x1189c, 0x118b8, 0x118c2, 0x118c8, 0x118d0, 0x118de, 0x118e6, 0x118ec, 0x118fa, 0x1190e, 0x1191c, 0x11938, 0x11970, 0x1197e, 0x11982, 0x11984, 0x11990, 0x1199e, 0x119a0, 0x119bc, 0x119c6, 0x119cc, 0x119d8, 0x119ee, 0x119f2, 0x119f4, 0x11a0e, 0x11a1c, 0x11a38, 0x11a70, 0x11a7e, 0x11ae0, 0x11afc, 0x11b08, 0x11b10, 0x11b1e, 0x11b20, 0x11b3c, 0x11b40, 0x11b78, 0x11b8c, 0x11b98, 0x11bb0, 0x11bbe, 0x11bce, 0x11bdc, 0x11be2, 0x11be4, 0x11be8, 0x11bf6, 0x11c16, 0x11c26, 0x11c2c, 0x11c46, 0x11c4c, 0x11c58, 0x11c6e, 0x11c86, 0x11c98, 0x11cb0, 0x11cbe, 0x11cce, 0x11cdc, 0x11ce2, 0x11ce4, 0x11ce8, 0x11cf6, 0x11d06, 0x11d0c, 0x11d18, 0x11d30, 0x11d3e, 0x11d60, 0x11d7c, 0x11d8e, 0x11d9c, 0x11db8, 0x11dc4, 0x11dc8, 0x11dd0, 0x11dde, 0x11de6, 0x11dec, 0x11dfa, 0x11e0a, 0x11e12, 0x11e14, 0x11e22, 0x11e24, 0x11e28, 0x11e36, 0x11e42, 0x11e44, 0x11e50, 0x11e5e, 0x11e66, 0x11e6c, 0x11e82, 0x11e84, 0x11e88, 0x11e90, 0x11e9e, 0x11ea0, 0x11ebc, 0x11ec6, 0x11ecc, 0x11ed8, 0x11eee, 0x11f1a, 0x11f2e, 0x11f32, 0x11f34, 0x11f4e, 0x11f5c, 0x11f62, 0x11f64, 0x11f68, 0x11f76, 0x12048, 0x1205e, 0x12082, 0x12084, 0x12090, 0x1209e, 0x120a0, 0x120bc, 0x120d8, 0x120f2, 0x120f4, 0x12108, 0x1211e, 0x12120, 0x1213c, 0x12140, 0x12178, 0x12186, 0x12198, 0x121b0, 0x121be, 0x121e2, 0x121e4, 0x121e8, 0x121f6, 0x12204, 0x12210, 0x1221e, 0x12220, 0x12278, 0x122f0, 0x12306, 0x1230c, 0x12330, 0x1233e, 0x12360, 0x1237c, 0x1238e, 0x1239c, 0x123b8, 0x123c2, 0x123c8, 0x123d0, 0x123e6, 0x123ec, 0x1241e, 0x12420, 0x1243c, 0x124f0, 0x125e0, 0x12618, 0x1263e, 0x12660, 0x1267c, 0x126c0, 0x126f8, 0x12738, 0x12770, 0x1277e, 0x12782, 0x12784, 0x12790, 0x1279e, 0x127a0, 0x127bc, 0x127c6, 0x127cc, 0x127d8, 0x127ee, 0x12820, 0x1283c, 0x12840, 0x12878, 0x128f0, 0x129e0, 0x12bc0, 0x12c18, 0x12c30, 0x12c3e, 0x12c60, 0x12c7c, 0x12cc0, 0x12cf8, 0x12df0, 0x12e1c, 0x12e38, 0x12e70, 0x12e7e, 0x12ee0, 0x12efc, 0x12f04, 0x12f08, 0x12f10, 0x12f20, 0x12f3c, 0x12f40, 0x12f78, 0x12f86, 0x12f8c, 0x12f98, 0x12fb0, 0x12fbe, 0x12fce, 0x12fdc, 0x1302e, 0x1304e, 0x1305c, 0x13062, 0x13068, 0x1308e, 0x1309c, 0x130b8, 0x130c2, 0x130c8, 0x130d0, 0x130de, 0x130ec, 0x130fa, 0x1310e, 0x13138, 0x13170, 0x1317e, 0x13182, 0x13184, 0x13190, 0x1319e, 0x131a0, 0x131bc, 0x131c6, 0x131cc, 0x131d8, 0x131f2, 0x131f4, 0x1320e, 0x1321c, 0x13270, 0x1327e, 0x132e0, 0x132fc, 0x13308, 0x1331e, 0x13320, 0x1333c, 0x13340, 0x13378, 0x13386, 0x13398, 0x133b0, 0x133be, 0x133ce, 0x133dc, 0x133e2, 0x133e4, 0x133e8, 0x133f6, 0x1340e, 0x1341c, 0x13438, 0x13470, 0x1347e, 0x134e0, 0x134fc, 0x135c0, 0x135f8, 0x13608, 0x13610, 0x1361e, 0x13620, 0x1363c, 0x13640, 0x13678, 0x136f0, 0x1370c, 0x13718, 0x13730, 0x1373e, 0x13760, 0x1377c, 0x1379c, 0x137b8, 0x137c2, 0x137c4, 0x137c8, 0x137d0, 0x137de, 0x137e6, 0x137ec, 0x13816, 0x13826, 0x1382c, 0x13846, 0x1384c, 0x13858, 0x1386e, 0x13874, 0x13886, 0x13898, 0x138b0, 0x138be, 0x138ce, 0x138dc, 0x138e2, 0x138e4, 0x138e8, 0x13906, 0x1390c, 0x13930, 0x1393e, 0x13960, 0x1397c, 0x1398e, 0x1399c, 0x139b8, 0x139c8, 0x139d0, 0x139de, 0x139e6, 0x139ec, 0x139fa, 0x13a06, 0x13a0c, 0x13a18, 0x13a30, 0x13a3e, 0x13a60, 0x13a7c, 0x13ac0, 0x13af8, 0x13b0e, 0x13b1c, 0x13b38, 0x13b70, 0x13b7e, 0x13b88, 0x13b90, 0x13b9e, 0x13ba0, 0x13bbc, 0x13bcc, 0x13bd8, 0x13bee, 0x13bf2, 0x13bf4, 0x13c12, 0x13c14, 0x13c22, 0x13c24, 0x13c28, 0x13c36, 0x13c42, 0x13c48, 0x13c50, 0x13c5e, 0x13c66, 0x13c6c, 0x13c82, 0x13c84, 0x13c90, 0x13c9e, 0x13ca0, 0x13cbc, 0x13cc6, 0x13ccc, 0x13cd8, 0x13cee, 0x13d02, 0x13d04, 0x13d08, 0x13d10, 0x13d1e, 0x13d20, 0x13d3c, 0x13d40, 0x13d78, 0x13d86, 0x13d8c, 0x13d98, 0x13db0, 0x13dbe, 0x13dce, 0x13ddc, 0x13de4, 0x13de8, 0x13df6, 0x13e1a, 0x13e2e, 0x13e32, 0x13e34, 0x13e4e, 0x13e5c, 0x13e62, 0x13e64, 0x13e68, 0x13e76, 0x13e8e, 0x13e9c, 0x13eb8, 0x13ec2, 0x13ec4, 0x13ec8, 0x13ed0, 0x13ede, 0x13ee6, 0x13eec, 0x13f26, 0x13f2c, 0x13f3a, 0x13f46, 0x13f4c, 0x13f58, 0x13f6e, 0x13f72, 0x13f74, 0x14082, 0x1409e, 0x140a0, 0x140bc, 0x14104, 0x14108, 0x14110, 0x1411e, 0x14120, 0x1413c, 0x14140, 0x14178, 0x1418c, 0x14198, 0x141b0, 0x141be, 0x141e2, 0x141e4, 0x141e8, 0x14208, 0x14210, 0x1421e, 0x14220, 0x1423c, 0x14240, 0x14278, 0x142f0, 0x14306, 0x1430c, 0x14318, 0x14330, 0x1433e, 0x14360, 0x1437c, 0x1438e, 0x143c2, 0x143c4, 0x143c8, 0x143d0, 0x143e6, 0x143ec, 0x14408, 0x14410, 0x1441e, 0x14420, 0x1443c, 0x14440, 0x14478, 0x144f0, 0x145e0, 0x1460c, 0x14618, 0x14630, 0x1463e, 0x14660, 0x1467c, 0x146c0, 0x146f8, 0x1471c, 0x14738, 0x14770, 0x1477e, 0x14782, 0x14784, 0x14788, 0x14790, 0x147a0, 0x147bc, 0x147c6, 0x147cc, 0x147d8, 0x147ee, 0x14810, 0x14820, 0x1483c, 0x14840, 0x14878, 0x148f0, 0x149e0, 0x14bc0, 0x14c30, 0x14c3e, 0x14c60, 0x14c7c, 0x14cc0, 0x14cf8, 0x14df0, 0x14e38, 0x14e70, 0x14e7e, 0x14ee0, 0x14efc, 0x14f04, 0x14f08, 0x14f10, 0x14f1e, 0x14f20, 0x14f3c, 0x14f40, 0x14f78, 0x14f86, 0x14f8c, 0x14f98, 0x14fb0, 0x14fce, 0x14fdc, 0x15020, 0x15040, 0x15078, 0x150f0, 0x151e0, 0x153c0, 0x15860, 0x1587c, 0x158c0, 0x158f8, 0x159f0, 0x15be0, 0x15c70, 0x15c7e, 0x15ce0, 0x15cfc, 0x15dc0, 0x15df8, 0x15e08, 0x15e10, 0x15e20, 0x15e40, 0x15e78, 0x15ef0, 0x15f0c, 0x15f18, 0x15f30, 0x15f60, 0x15f7c, 0x15f8e, 0x15f9c, 0x15fb8, 0x1604e, 0x1605c, 0x1608e, 0x1609c, 0x160b8, 0x160c2, 0x160c4, 0x160c8, 0x160de, 0x1610e, 0x1611c, 0x16138, 0x16170, 0x1617e, 0x16184, 0x16188, 0x16190, 0x1619e, 0x161a0, 0x161bc, 0x161c6, 0x161cc, 0x161d8, 0x161f2, 0x161f4, 0x1620e, 0x1621c, 0x16238, 0x16270, 0x1627e, 0x162e0, 0x162fc, 0x16304, 0x16308, 0x16310, 0x1631e, 0x16320, 0x1633c, 0x16340, 0x16378, 0x16386, 0x1638c, 0x16398, 0x163b0, 0x163be, 0x163ce, 0x163dc, 0x163e2, 0x163e4, 0x163e8, 0x163f6, 0x1640e, 0x1641c, 0x16438, 0x16470, 0x1647e, 0x164e0, 0x164fc, 0x165c0, 0x165f8, 0x16610, 0x1661e, 0x16620, 0x1663c, 0x16640, 0x16678, 0x166f0, 0x16718, 0x16730, 0x1673e, 0x16760, 0x1677c, 0x1678e, 0x1679c, 0x167b8, 0x167c2, 0x167c4, 0x167c8, 0x167d0, 0x167de, 0x167e6, 0x167ec, 0x1681c, 0x16838, 0x16870, 0x168e0, 0x168fc, 0x169c0, 0x169f8, 0x16bf0, 0x16c10, 0x16c1e, 0x16c20, 0x16c3c, 0x16c40, 0x16c78, 0x16cf0, 0x16de0, 0x16e18, 0x16e30, 0x16e3e, 0x16e60, 0x16e7c, 0x16ec0, 0x16ef8, 0x16f1c, 0x16f38, 0x16f70, 0x16f7e, 0x16f84, 0x16f88, 0x16f90, 0x16f9e, 0x16fa0, 0x16fbc, 0x16fc6, 0x16fcc, 0x16fd8, 0x17026, 0x1702c, 0x17046, 0x1704c, 0x17058, 0x1706e, 0x17086, 0x1708c, 0x17098, 0x170b0, 0x170be, 0x170ce, 0x170dc, 0x170e8, 0x17106, 0x1710c, 0x17118, 0x17130, 0x1713e, 0x17160, 0x1717c, 0x1718e, 0x1719c, 0x171b8, 0x171c2, 0x171c4, 0x171c8, 0x171d0, 0x171de, 0x171e6, 0x171ec, 0x171fa, 0x17206, 0x1720c, 0x17218, 0x17230, 0x1723e, 0x17260, 0x1727c, 0x172c0, 0x172f8, 0x1730e, 0x1731c, 0x17338, 0x17370, 0x1737e, 0x17388, 0x17390, 0x1739e, 0x173a0, 0x173bc, 0x173cc, 0x173d8, 0x173ee, 0x173f2, 0x173f4, 0x1740c, 0x17418, 0x17430, 0x1743e, 0x17460, 0x1747c, 0x174c0, 0x174f8, 0x175f0, 0x1760e, 0x1761c, 0x17638, 0x17670, 0x1767e, 0x176e0, 0x176fc, 0x17708, 0x17710, 0x1771e, 0x17720, 0x1773c, 0x17740, 0x17778, 0x17798, 0x177b0, 0x177be, 0x177dc, 0x177e2, 0x177e4, 0x177e8, 0x17822, 0x17824, 0x17828, 0x17836, 0x17842, 0x17844, 0x17848, 0x17850, 0x1785e, 0x17866, 0x1786c, 0x17882, 0x17884, 0x17888, 0x17890, 0x1789e, 0x178a0, 0x178bc, 0x178c6, 0x178cc, 0x178d8, 0x178ee, 0x178f2, 0x178f4, 0x17902, 0x17904, 0x17908, 0x17910, 0x1791e, 0x17920, 0x1793c, 0x17940, 0x17978, 0x17986, 0x1798c, 0x17998, 0x179b0, 0x179be, 0x179ce, 0x179dc, 0x179e2, 0x179e4, 0x179e8, 0x179f6, 0x17a04, 0x17a08, 0x17a10, 0x17a1e, 0x17a20, 0x17a3c, 0x17a40, 0x17a78, 0x17af0, 0x17b06, 0x17b0c, 0x17b18, 0x17b30, 0x17b3e, 0x17b60, 0x17b7c, 0x17b8e, 0x17b9c, 0x17bb8, 0x17bc4, 0x17bc8, 0x17bd0, 0x17bde, 0x17be6, 0x17bec, 0x17c2e, 0x17c32, 0x17c34, 0x17c4e, 0x17c5c, 0x17c62, 0x17c64, 0x17c68, 0x17c76, 0x17c8e, 0x17c9c, 0x17cb8, 0x17cc2, 0x17cc4, 0x17cc8, 0x17cd0, 0x17cde, 0x17ce6, 0x17cec, 0x17d0e, 0x17d1c, 0x17d38, 0x17d70, 0x17d82, 0x17d84, 0x17d88, 0x17d90, 0x17d9e, 0x17da0, 0x17dbc, 0x17dc6, 0x17dcc, 0x17dd8, 0x17dee, 0x17e26, 0x17e2c, 0x17e3a, 0x17e46, 0x17e4c, 0x17e58, 0x17e6e, 0x17e72, 0x17e74, 0x17e86, 0x17e8c, 0x17e98, 0x17eb0, 0x17ece, 0x17edc, 0x17ee2, 0x17ee4, 0x17ee8, 0x17ef6, 0x1813a, 0x18172, 0x18174, 0x18216, 0x18226, 0x1823a, 0x1824c, 0x18258, 0x1826e, 0x18272, 0x18274, 0x18298, 0x182be, 0x182e2, 0x182e4, 0x182e8, 0x182f6, 0x1835e, 0x1837a, 0x183ae, 0x183d6, 0x18416, 0x18426, 0x1842c, 0x1843a, 0x18446, 0x18458, 0x1846e, 0x18472, 0x18474, 0x18486, 0x184b0, 0x184be, 0x184ce, 0x184dc, 0x184e2, 0x184e4, 0x184e8, 0x184f6, 0x18506, 0x1850c, 0x18518, 0x18530, 0x1853e, 0x18560, 0x1857c, 0x1858e, 0x1859c, 0x185b8, 0x185c2, 0x185c4, 0x185c8, 0x185d0, 0x185de, 0x185e6, 0x185ec, 0x185fa, 0x18612, 0x18614, 0x18622, 0x18628, 0x18636, 0x18642, 0x18650, 0x1865e, 0x1867a, 0x18682, 0x18684, 0x18688, 0x18690, 0x1869e, 0x186a0, 0x186bc, 0x186c6, 0x186cc, 0x186d8, 0x186ee, 0x186f2, 0x186f4, 0x1872e, 0x1874e, 0x1875c, 0x18796, 0x187a6, 0x187ac, 0x187d2, 0x187d4, 0x18826, 0x1882c, 0x1883a, 0x18846, 0x1884c, 0x18858, 0x1886e, 0x18872, 0x18874, 0x18886, 0x18898, 0x188b0, 0x188be, 0x188ce, 0x188dc, 0x188e2, 0x188e4, 0x188e8, 0x188f6, 0x1890c, 0x18930, 0x1893e, 0x18960, 0x1897c, 0x1898e, 0x189b8, 0x189c2, 0x189c8, 0x189d0, 0x189de, 0x189e6, 0x189ec, 0x189fa, 0x18a18, 0x18a30, 0x18a3e, 0x18a60, 0x18a7c, 0x18ac0, 0x18af8, 0x18b1c, 0x18b38, 0x18b70, 0x18b7e, 0x18b82, 0x18b84, 0x18b88, 0x18b90, 0x18b9e, 0x18ba0, 0x18bbc, 0x18bc6, 0x18bcc, 0x18bd8, 0x18bee, 0x18bf2, 0x18bf4, 0x18c22, 0x18c24, 0x18c28, 0x18c36, 0x18c42, 0x18c48, 0x18c50, 0x18c5e, 0x18c66, 0x18c7a, 0x18c82, 0x18c84, 0x18c90, 0x18c9e, 0x18ca0, 0x18cbc, 0x18ccc, 0x18cf2, 0x18cf4, 0x18d04, 0x18d08, 0x18d10, 0x18d1e, 0x18d20, 0x18d3c, 0x18d40, 0x18d78, 0x18d86, 0x18d98, 0x18dce, 0x18de2, 0x18de4, 0x18de8, 0x18e2e, 0x18e32, 0x18e34, 0x18e4e, 0x18e5c, 0x18e62, 0x18e64, 0x18e68, 0x18e8e, 0x18e9c, 0x18eb8, 0x18ec2, 0x18ec4, 0x18ec8, 0x18ed0, 0x18efa, 0x18f16, 0x18f26, 0x18f2c, 0x18f46, 0x18f4c, 0x18f58, 0x18f6e, 0x18f8a, 0x18f92, 0x18f94, 0x18fa2, 0x18fa4, 0x18fa8, 0x18fb6, 0x1902c, 0x1903a, 0x19046, 0x1904c, 0x19058, 0x19072, 0x19074, 0x19086, 0x19098, 0x190b0, 0x190be, 0x190ce, 0x190dc, 0x190e2, 0x190e8, 0x190f6, 0x19106, 0x1910c, 0x19130, 0x1913e, 0x19160, 0x1917c, 0x1918e, 0x1919c, 0x191b8, 0x191c2, 0x191c8, 0x191d0, 0x191de, 0x191e6, 0x191ec, 0x191fa, 0x19218, 0x1923e, 0x19260, 0x1927c, 0x192c0, 0x192f8, 0x19338, 0x19370, 0x1937e, 0x19382, 0x19384, 0x19390, 0x1939e, 0x193a0, 0x193bc, 0x193c6, 0x193cc, 0x193d8, 0x193ee, 0x193f2, 0x193f4, 0x19430, 0x1943e, 0x19460, 0x1947c, 0x194c0, 0x194f8, 0x195f0, 0x19638, 0x19670, 0x1967e, 0x196e0, 0x196fc, 0x19702, 0x19704, 0x19708, 0x19710, 0x19720, 0x1973c, 0x19740, 0x19778, 0x19786, 0x1978c, 0x19798, 0x197b0, 0x197be, 0x197ce, 0x197dc, 0x197e2, 0x197e4, 0x197e8, 0x19822, 0x19824, 0x19842, 0x19848, 0x19850, 0x1985e, 0x19866, 0x1987a, 0x19882, 0x19884, 0x19890, 0x1989e, 0x198a0, 0x198bc, 0x198cc, 0x198f2, 0x198f4, 0x19902, 0x19908, 0x1991e, 0x19920, 0x1993c, 0x19940, 0x19978, 0x19986, 0x19998, 0x199ce, 0x199e2, 0x199e4, 0x199e8, 0x19a08, 0x19a10, 0x19a1e, 0x19a20, 0x19a3c, 0x19a40, 0x19a78, 0x19af0, 0x19b18, 0x19b3e, 0x19b60, 0x19b9c, 0x19bc2, 0x19bc4, 0x19bc8, 0x19bd0, 0x19be6, 0x19c2e, 0x19c34, 0x19c4e, 0x19c5c, 0x19c62, 0x19c64, 0x19c68, 0x19c8e, 0x19c9c, 0x19cb8, 0x19cc2, 0x19cc8, 0x19cd0, 0x19ce6, 0x19cfa, 0x19d0e, 0x19d1c, 0x19d38, 0x19d70, 0x19d7e, 0x19d82, 0x19d84, 0x19d88, 0x19d90, 0x19da0, 0x19dcc, 0x19df2, 0x19df4, 0x19e16, 0x19e26, 0x19e2c, 0x19e46, 0x19e4c, 0x19e58, 0x19e74, 0x19e86, 0x19e8c, 0x19e98, 0x19eb0, 0x19ebe, 0x19ece, 0x19ee2, 0x19ee4, 0x19ee8, 0x19f0a, 0x19f12, 0x19f14, 0x19f22, 0x19f24, 0x19f28, 0x19f42, 0x19f44, 0x19f48, 0x19f50, 0x19f5e, 0x19f6c, 0x19f9a, 0x19fae, 0x19fb2, 0x19fb4, 0x1a046, 0x1a04c, 0x1a072, 0x1a074, 0x1a086, 0x1a08c, 0x1a098, 0x1a0b0, 0x1a0be, 0x1a0e2, 0x1a0e4, 0x1a0e8, 0x1a0f6, 0x1a106, 0x1a10c, 0x1a118, 0x1a130, 0x1a13e, 0x1a160, 0x1a17c, 0x1a18e, 0x1a19c, 0x1a1b8, 0x1a1c2, 0x1a1c4, 0x1a1c8, 0x1a1d0, 0x1a1de, 0x1a1e6, 0x1a1ec, 0x1a218, 0x1a230, 0x1a23e, 0x1a260, 0x1a27c, 0x1a2c0, 0x1a2f8, 0x1a31c, 0x1a338, 0x1a370, 0x1a37e, 0x1a382, 0x1a384, 0x1a388, 0x1a390, 0x1a39e, 0x1a3a0, 0x1a3bc, 0x1a3c6, 0x1a3cc, 0x1a3d8, 0x1a3ee, 0x1a3f2, 0x1a3f4, 0x1a418, 0x1a430, 0x1a43e, 0x1a460, 0x1a47c, 0x1a4c0, 0x1a4f8, 0x1a5f0, 0x1a61c, 0x1a638, 0x1a670, 0x1a67e, 0x1a6e0, 0x1a6fc, 0x1a702, 0x1a704, 0x1a708, 0x1a710, 0x1a71e, 0x1a720, 0x1a73c, 0x1a740, 0x1a778, 0x1a786, 0x1a78c, 0x1a798, 0x1a7b0, 0x1a7be, 0x1a7ce, 0x1a7dc, 0x1a7e2, 0x1a7e4, 0x1a7e8, 0x1a830, 0x1a860, 0x1a87c, 0x1a8c0, 0x1a8f8, 0x1a9f0, 0x1abe0, 0x1ac70, 0x1ac7e, 0x1ace0, 0x1acfc, 0x1adc0, 0x1adf8, 0x1ae04, 0x1ae08, 0x1ae10, 0x1ae20, 0x1ae3c, 0x1ae40, 0x1ae78, 0x1aef0, 0x1af06, 0x1af0c, 0x1af18, 0x1af30, 0x1af3e, 0x1af60, 0x1af7c, 0x1af8e, 0x1af9c, 0x1afb8, 0x1afc4, 0x1afc8, 0x1afd0, 0x1afde, 0x1b042, 0x1b05e, 0x1b07a, 0x1b082, 0x1b084, 0x1b088, 0x1b090, 0x1b09e, 0x1b0a0, 0x1b0bc, 0x1b0cc, 0x1b0f2, 0x1b0f4, 0x1b102, 0x1b104, 0x1b108, 0x1b110, 0x1b11e, 0x1b120, 0x1b13c, 0x1b140, 0x1b178, 0x1b186, 0x1b198, 0x1b1ce, 0x1b1e2, 0x1b1e4, 0x1b1e8, 0x1b204, 0x1b208, 0x1b210, 0x1b21e, 0x1b220, 0x1b23c, 0x1b240, 0x1b278, 0x1b2f0, 0x1b30c, 0x1b33e, 0x1b360, 0x1b39c, 0x1b3c2, 0x1b3c4, 0x1b3c8, 0x1b3d0, 0x1b3e6, 0x1b410, 0x1b41e, 0x1b420, 0x1b43c, 0x1b440, 0x1b478, 0x1b4f0, 0x1b5e0, 0x1b618, 0x1b660, 0x1b67c, 0x1b6c0, 0x1b738, 0x1b782, 0x1b784, 0x1b788, 0x1b790, 0x1b79e, 0x1b7a0, 0x1b7cc, 0x1b82e, 0x1b84e, 0x1b85c, 0x1b88e, 0x1b89c, 0x1b8b8, 0x1b8c2, 0x1b8c4, 0x1b8c8, 0x1b8d0, 0x1b8e6, 0x1b8fa, 0x1b90e, 0x1b91c, 0x1b938, 0x1b970, 0x1b97e, 0x1b982, 0x1b984, 0x1b988, 0x1b990, 0x1b99e, 0x1b9a0, 0x1b9cc, 0x1b9f2, 0x1b9f4, 0x1ba0e, 0x1ba1c, 0x1ba38, 0x1ba70, 0x1ba7e, 0x1bae0, 0x1bafc, 0x1bb08, 0x1bb10, 0x1bb20, 0x1bb3c, 0x1bb40, 0x1bb98, 0x1bbce, 0x1bbe2, 0x1bbe4, 0x1bbe8, 0x1bc16, 0x1bc26, 0x1bc2c, 0x1bc46, 0x1bc4c, 0x1bc58, 0x1bc72, 0x1bc74, 0x1bc86, 0x1bc8c, 0x1bc98, 0x1bcb0, 0x1bcbe, 0x1bcce, 0x1bce2, 0x1bce4, 0x1bce8, 0x1bd06, 0x1bd0c, 0x1bd18, 0x1bd30, 0x1bd3e, 0x1bd60, 0x1bd7c, 0x1bd9c, 0x1bdc2, 0x1bdc4, 0x1bdc8, 0x1bdd0, 0x1bde6, 0x1bdfa, 0x1be12, 0x1be14, 0x1be22, 0x1be24, 0x1be28, 0x1be42, 0x1be44, 0x1be48, 0x1be50, 0x1be5e, 0x1be66, 0x1be82, 0x1be84, 0x1be88, 0x1be90, 0x1be9e, 0x1bea0, 0x1bebc, 0x1becc, 0x1bef4, 0x1bf1a, 0x1bf2e, 0x1bf32, 0x1bf34, 0x1bf4e, 0x1bf5c, 0x1bf62, 0x1bf64, 0x1bf68, 0x1c09a, 0x1c0b2, 0x1c0b4, 0x1c11a, 0x1c132, 0x1c134, 0x1c162, 0x1c164, 0x1c168, 0x1c176, 0x1c1ba, 0x1c21a, 0x1c232, 0x1c234, 0x1c24e, 0x1c25c, 0x1c262, 0x1c264, 0x1c268, 0x1c276, 0x1c28e, 0x1c2c2, 0x1c2c4, 0x1c2c8, 0x1c2d0, 0x1c2de, 0x1c2e6, 0x1c2ec, 0x1c2fa, 0x1c316, 0x1c326, 0x1c33a, 0x1c346, 0x1c34c, 0x1c372, 0x1c374, 0x1c41a, 0x1c42e, 0x1c432, 0x1c434, 0x1c44e, 0x1c45c, 0x1c462, 0x1c464, 0x1c468, 0x1c476, 0x1c48e, 0x1c49c, 0x1c4b8, 0x1c4c2, 0x1c4c8, 0x1c4d0, 0x1c4de, 0x1c4e6, 0x1c4ec, 0x1c4fa, 0x1c51c, 0x1c538, 0x1c570, 0x1c57e, 0x1c582, 0x1c584, 0x1c588, 0x1c590, 0x1c59e, 0x1c5a0, 0x1c5bc, 0x1c5c6, 0x1c5cc, 0x1c5d8, 0x1c5ee, 0x1c5f2, 0x1c5f4, 0x1c616, 0x1c626, 0x1c62c, 0x1c63a, 0x1c646, 0x1c64c, 0x1c658, 0x1c66e, 0x1c672, 0x1c674, 0x1c686, 0x1c68c, 0x1c698, 0x1c6b0, 0x1c6be, 0x1c6ce, 0x1c6dc, 0x1c6e2, 0x1c6e4, 0x1c6e8, 0x1c712, 0x1c714, 0x1c722, 0x1c728, 0x1c736, 0x1c742, 0x1c744, 0x1c748, 0x1c750, 0x1c75e, 0x1c766, 0x1c76c, 0x1c77a, 0x1c7ae, 0x1c7d6, 0x1c7ea, 0x1c81a, 0x1c82e, 0x1c832, 0x1c834, 0x1c84e, 0x1c85c, 0x1c862, 0x1c864, 0x1c868, 0x1c876, 0x1c88e, 0x1c89c, 0x1c8b8, 0x1c8c2, 0x1c8c8, 0x1c8d0, 0x1c8de, 0x1c8e6, 0x1c8ec, 0x1c8fa, 0x1c90e, 0x1c938, 0x1c970, 0x1c97e, 0x1c982, 0x1c984, 0x1c990, 0x1c99e, 0x1c9a0, 0x1c9bc, 0x1c9c6, 0x1c9cc, 0x1c9d8, 0x1c9ee, 0x1c9f2, 0x1c9f4, 0x1ca38, 0x1ca70, 0x1ca7e, 0x1cae0, 0x1cafc, 0x1cb02, 0x1cb04, 0x1cb08, 0x1cb10, 0x1cb20, 0x1cb3c, 0x1cb40, 0x1cb78, 0x1cb86, 0x1cb8c, 0x1cb98, 0x1cbb0, 0x1cbbe, 0x1cbce, 0x1cbdc, 0x1cbe2, 0x1cbe4, 0x1cbe8, 0x1cbf6, 0x1cc16, 0x1cc26, 0x1cc2c, 0x1cc3a, 0x1cc46, 0x1cc58, 0x1cc72, 0x1cc74, 0x1cc86, 0x1ccb0, 0x1ccbe, 0x1ccce, 0x1cce2, 0x1cce4, 0x1cce8, 0x1cd06, 0x1cd0c, 0x1cd18, 0x1cd30, 0x1cd3e, 0x1cd60, 0x1cd7c, 0x1cd9c, 0x1cdc2, 0x1cdc4, 0x1cdc8, 0x1cdd0, 0x1cdde, 0x1cde6, 0x1cdfa, 0x1ce22, 0x1ce28, 0x1ce42, 0x1ce50, 0x1ce5e, 0x1ce66, 0x1ce7a, 0x1ce82, 0x1ce84, 0x1ce88, 0x1ce90, 0x1ce9e, 0x1cea0, 0x1cebc, 0x1cecc, 0x1cef2, 0x1cef4, 0x1cf2e, 0x1cf32, 0x1cf34, 0x1cf4e, 0x1cf5c, 0x1cf62, 0x1cf64, 0x1cf68, 0x1cf96, 0x1cfa6, 0x1cfac, 0x1cfca, 0x1cfd2, 0x1cfd4, 0x1d02e, 0x1d032, 0x1d034, 0x1d04e, 0x1d05c, 0x1d062, 0x1d064, 0x1d068, 0x1d076, 0x1d08e, 0x1d09c, 0x1d0b8, 0x1d0c2, 0x1d0c4, 0x1d0c8, 0x1d0d0, 0x1d0de, 0x1d0e6, 0x1d0ec, 0x1d0fa, 0x1d11c, 0x1d138, 0x1d170, 0x1d17e, 0x1d182, 0x1d184, 0x1d188, 0x1d190, 0x1d19e, 0x1d1a0, 0x1d1bc, 0x1d1c6, 0x1d1cc, 0x1d1d8, 0x1d1ee, 0x1d1f2, 0x1d1f4, 0x1d21c, 0x1d238, 0x1d270, 0x1d27e, 0x1d2e0, 0x1d2fc, 0x1d302, 0x1d304, 0x1d308, 0x1d310, 0x1d31e, 0x1d320, 0x1d33c, 0x1d340, 0x1d378, 0x1d386, 0x1d38c, 0x1d398, 0x1d3b0, 0x1d3be, 0x1d3ce, 0x1d3dc, 0x1d3e2, 0x1d3e4, 0x1d3e8, 0x1d3f6, 0x1d470, 0x1d47e, 0x1d4e0, 0x1d4fc, 0x1d5c0, 0x1d5f8, 0x1d604, 0x1d608, 0x1d610, 0x1d620, 0x1d640, 0x1d678, 0x1d6f0, 0x1d706, 0x1d70c, 0x1d718, 0x1d730, 0x1d73e, 0x1d760, 0x1d77c, 0x1d78e, 0x1d79c, 0x1d7b8, 0x1d7c2, 0x1d7c4, 0x1d7c8, 0x1d7d0, 0x1d7de, 0x1d7e6, 0x1d7ec, 0x1d826, 0x1d82c, 0x1d83a, 0x1d846, 0x1d84c, 0x1d858, 0x1d872, 0x1d874, 0x1d886, 0x1d88c, 0x1d898, 0x1d8b0, 0x1d8be, 0x1d8ce, 0x1d8e2, 0x1d8e4, 0x1d8e8, 0x1d8f6, 0x1d90c, 0x1d918, 0x1d930, 0x1d93e, 0x1d960, 0x1d97c, 0x1d99c, 0x1d9c2, 0x1d9c4, 0x1d9c8, 0x1d9d0, 0x1d9e6, 0x1d9fa, 0x1da0c, 0x1da18, 0x1da30, 0x1da3e, 0x1da60, 0x1da7c, 0x1dac0, 0x1daf8, 0x1db38, 0x1db82, 0x1db84, 0x1db88, 0x1db90, 0x1db9e, 0x1dba0, 0x1dbcc, 0x1dbf2, 0x1dbf4, 0x1dc22, 0x1dc42, 0x1dc44, 0x1dc48, 0x1dc50, 0x1dc5e, 0x1dc66, 0x1dc7a, 0x1dc82, 0x1dc84, 0x1dc88, 0x1dc90, 0x1dc9e, 0x1dca0, 0x1dcbc, 0x1dccc, 0x1dcf2, 0x1dcf4, 0x1dd04, 0x1dd08, 0x1dd10, 0x1dd1e, 0x1dd20, 0x1dd3c, 0x1dd40, 0x1dd78, 0x1dd86, 0x1dd98, 0x1ddce, 0x1dde2, 0x1dde4, 0x1dde8, 0x1de2e, 0x1de32, 0x1de34, 0x1de4e, 0x1de5c, 0x1de62, 0x1de64, 0x1de68, 0x1de8e, 0x1de9c, 0x1deb8, 0x1dec2, 0x1dec4, 0x1dec8, 0x1ded0, 0x1dee6, 0x1defa, 0x1df16, 0x1df26, 0x1df2c, 0x1df46, 0x1df4c, 0x1df58, 0x1df72, 0x1df74, 0x1df8a, 0x1df92, 0x1df94, 0x1dfa2, 0x1dfa4, 0x1dfa8, 0x1e08a, 0x1e092, 0x1e094, 0x1e0a2, 0x1e0a4, 0x1e0a8, 0x1e0b6, 0x1e0da, 0x1e10a, 0x1e112, 0x1e114, 0x1e122, 0x1e124, 0x1e128, 0x1e136, 0x1e142, 0x1e144, 0x1e148, 0x1e150, 0x1e166, 0x1e16c, 0x1e17a, 0x1e19a, 0x1e1b2, 0x1e1b4, 0x1e20a, 0x1e212, 0x1e214, 0x1e222, 0x1e224, 0x1e228, 0x1e236, 0x1e242, 0x1e248, 0x1e250, 0x1e25e, 0x1e266, 0x1e26c, 0x1e27a, 0x1e282, 0x1e284, 0x1e288, 0x1e290, 0x1e2a0, 0x1e2bc, 0x1e2c6, 0x1e2cc, 0x1e2d8, 0x1e2ee, 0x1e2f2, 0x1e2f4, 0x1e31a, 0x1e332, 0x1e334, 0x1e35c, 0x1e362, 0x1e364, 0x1e368, 0x1e3ba, 0x1e40a, 0x1e412, 0x1e414, 0x1e422, 0x1e428, 0x1e436, 0x1e442, 0x1e448, 0x1e450, 0x1e45e, 0x1e466, 0x1e46c, 0x1e47a, 0x1e482, 0x1e484, 0x1e490, 0x1e49e, 0x1e4a0, 0x1e4bc, 0x1e4c6, 0x1e4cc, 0x1e4d8, 0x1e4ee, 0x1e4f2, 0x1e4f4, 0x1e502, 0x1e504, 0x1e508, 0x1e510, 0x1e51e, 0x1e520, 0x1e53c, 0x1e540, 0x1e578, 0x1e586, 0x1e58c, 0x1e598, 0x1e5b0, 0x1e5be, 0x1e5ce, 0x1e5dc, 0x1e5e2, 0x1e5e4, 0x1e5e8, 0x1e5f6, 0x1e61a, 0x1e62e, 0x1e632, 0x1e634, 0x1e64e, 0x1e65c, 0x1e662, 0x1e668, 0x1e68e, 0x1e69c, 0x1e6b8, 0x1e6c2, 0x1e6c4, 0x1e6c8, 0x1e6d0, 0x1e6e6, 0x1e6fa, 0x1e716, 0x1e726, 0x1e72c, 0x1e73a, 0x1e746, 0x1e74c, 0x1e758, 0x1e772, 0x1e774, 0x1e792, 0x1e794, 0x1e7a2, 0x1e7a4, 0x1e7a8, 0x1e7b6, 0x1e812, 0x1e814, 0x1e822, 0x1e824, 0x1e828, 0x1e836, 0x1e842, 0x1e844, 0x1e848, 0x1e850, 0x1e85e, 0x1e866, 0x1e86c, 0x1e87a, 0x1e882, 0x1e884, 0x1e888, 0x1e890, 0x1e89e, 0x1e8a0, 0x1e8bc, 0x1e8c6, 0x1e8cc, 0x1e8d8, 0x1e8ee, 0x1e8f2, 0x1e8f4, 0x1e902, 0x1e904, 0x1e908, 0x1e910, 0x1e920, 0x1e93c, 0x1e940, 0x1e978, 0x1e986, 0x1e98c, 0x1e998, 0x1e9b0, 0x1e9be, 0x1e9ce, 0x1e9dc, 0x1e9e2, 0x1e9e4, 0x1e9e8, 0x1e9f6, 0x1ea04, 0x1ea08, 0x1ea10, 0x1ea20, 0x1ea40, 0x1ea78, 0x1eaf0, 0x1eb06, 0x1eb0c, 0x1eb18, 0x1eb30, 0x1eb3e, 0x1eb60, 0x1eb7c, 0x1eb8e, 0x1eb9c, 0x1ebb8, 0x1ebc2, 0x1ebc4, 0x1ebc8, 0x1ebd0, 0x1ebde, 0x1ebe6, 0x1ebec, 0x1ec1a, 0x1ec2e, 0x1ec32, 0x1ec34, 0x1ec4e, 0x1ec5c, 0x1ec62, 0x1ec64, 0x1ec68, 0x1ec8e, 0x1ec9c, 0x1ecb8, 0x1ecc2, 0x1ecc4, 0x1ecc8, 0x1ecd0, 0x1ece6, 0x1ecfa, 0x1ed0e, 0x1ed1c, 0x1ed38, 0x1ed70, 0x1ed7e, 0x1ed82, 0x1ed84, 0x1ed88, 0x1ed90, 0x1ed9e, 0x1eda0, 0x1edcc, 0x1edf2, 0x1edf4, 0x1ee16, 0x1ee26, 0x1ee2c, 0x1ee3a, 0x1ee46, 0x1ee4c, 0x1ee58, 0x1ee6e, 0x1ee72, 0x1ee74, 0x1ee86, 0x1ee8c, 0x1ee98, 0x1eeb0, 0x1eebe, 0x1eece, 0x1eedc, 0x1eee2, 0x1eee4, 0x1eee8, 0x1ef12, 0x1ef22, 0x1ef24, 0x1ef28, 0x1ef36, 0x1ef42, 0x1ef44, 0x1ef48, 0x1ef50, 0x1ef5e, 0x1ef66, 0x1ef6c, 0x1ef7a, 0x1efae, 0x1efb2, 0x1efb4, 0x1efd6, 0x1f096, 0x1f0a6, 0x1f0ac, 0x1f0ba, 0x1f0ca, 0x1f0d2, 0x1f0d4, 0x1f116, 0x1f126, 0x1f12c, 0x1f13a, 0x1f146, 0x1f14c, 0x1f158, 0x1f16e, 0x1f172, 0x1f174, 0x1f18a, 0x1f192, 0x1f194, 0x1f1a2, 0x1f1a4, 0x1f1a8, 0x1f1da, 0x1f216, 0x1f226, 0x1f22c, 0x1f23a, 0x1f246, 0x1f258, 0x1f26e, 0x1f272, 0x1f274, 0x1f286, 0x1f28c, 0x1f298, 0x1f2b0, 0x1f2be, 0x1f2ce, 0x1f2dc, 0x1f2e2, 0x1f2e4, 0x1f2e8, 0x1f2f6, 0x1f30a, 0x1f312, 0x1f314, 0x1f322, 0x1f328, 0x1f342, 0x1f344, 0x1f348, 0x1f350, 0x1f35e, 0x1f366, 0x1f37a, 0x1f39a, 0x1f3ae, 0x1f3b2, 0x1f3b4, 0x1f416, 0x1f426, 0x1f42c, 0x1f43a, 0x1f446, 0x1f44c, 0x1f458, 0x1f46e, 0x1f472, 0x1f474, 0x1f486, 0x1f48c, 0x1f498, 0x1f4b0, 0x1f4be, 0x1f4ce, 0x1f4dc, 0x1f4e2, 0x1f4e4, 0x1f4e8, 0x1f4f6, 0x1f506, 0x1f50c, 0x1f518, 0x1f530, 0x1f53e, 0x1f560, 0x1f57c, 0x1f58e, 0x1f59c, 0x1f5b8, 0x1f5c2, 0x1f5c4, 0x1f5c8, 0x1f5d0, 0x1f5de, 0x1f5e6, 0x1f5ec, 0x1f5fa, 0x1f60a, 0x1f612, 0x1f614, 0x1f622, 0x1f624, 0x1f628, 0x1f636, 0x1f642, 0x1f644, 0x1f648, 0x1f650, 0x1f65e, 0x1f666, 0x1f67a, 0x1f682, 0x1f684, 0x1f688, 0x1f690, 0x1f69e, 0x1f6a0, 0x1f6bc, 0x1f6cc, 0x1f6f2, 0x1f6f4, 0x1f71a, 0x1f72e, 0x1f732, 0x1f734, 0x1f74e, 0x1f75c, 0x1f762, 0x1f764, 0x1f768, 0x1f776, 0x1f796, 0x1f7a6, 0x1f7ac, 0x1f7ba, 0x1f7d2, 0x1f7d4, 0x1f89a, 0x1f8ae, 0x1f8b2, 0x1f8b4, 0x1f8d6, 0x1f8ea, 0x1f91a, 0x1f92e, 0x1f932, 0x1f934, 0x1f94e, 0x1f95c, 0x1f962, 0x1f964, 0x1f968, 0x1f976, 0x1f996, 0x1f9a6, 0x1f9ac, 0x1f9ba, 0x1f9ca, 0x1f9d2, 0x1f9d4, 0x1fa1a, 0x1fa2e, 0x1fa32, 0x1fa34, 0x1fa4e, 0x1fa5c, 0x1fa62, 0x1fa64, 0x1fa68, 0x1fa76, 0x1fa8e, 0x1fa9c, 0x1fab8, 0x1fac2, 0x1fac4, 0x1fac8, 0x1fad0, 0x1fade, 0x1fae6, 0x1faec, 0x1fb16, 0x1fb26, 0x1fb2c, 0x1fb3a, 0x1fb46, 0x1fb4c, 0x1fb58, 0x1fb6e, 0x1fb72, 0x1fb74, 0x1fb8a, 0x1fb92, 0x1fb94, 0x1fba2, 0x1fba4, 0x1fba8, 0x1fbb6, 0x1fbda, ] +; + +/** + * This table contains to codewords for all symbols. + */ + const CODEWORD_TABLE: vec![Vec; 2787] = vec![2627, 1819, 2622, 2621, 1813, 1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865, 861, 859, 2511, 873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844, 1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815, 814, 813, 812, 2484, 817, 816, 1745, 1744, 1742, 1746, 2655, 2637, 2635, 2626, 2625, 2623, 2628, 1820, 2752, 2739, 2737, 2728, 2727, 2725, 2730, 2785, 2783, 2778, 2777, 2775, 2780, 787, 781, 747, 739, 736, 2413, 754, 752, 1719, 692, 689, 681, 2371, 678, 2369, 700, 697, 694, 703, 1688, 1686, 642, 638, 2343, 631, 2341, 627, 2338, 651, 646, 643, 2345, 654, 652, 1652, 1650, 1647, 1654, 601, 599, 2322, 596, 2321, 594, 2319, 2317, 611, 610, 608, 606, 2324, 603, 2323, 615, 614, 612, 1617, 1616, 1614, 1612, 616, 1619, 1618, 2575, 2538, 2536, 905, 901, 898, 909, 2509, 2507, 2504, 870, 867, 864, 860, 2512, 875, 872, 1781, 2490, 2489, 2487, 2485, 1748, 836, 834, 832, 830, 2494, 827, 2492, 843, 841, 839, 845, 1765, 1763, 2701, 2676, 2674, 2653, 2648, 2656, 2634, 2633, 2631, 2629, 1821, 2638, 2636, 2770, 2763, 2761, 2750, 2745, 2753, 2736, 2735, 2733, 2731, 1848, 2740, 2738, 2786, 2784, 591, 588, 576, 569, 566, 2296, 1590, 537, 534, 526, 2276, 522, 2274, 545, 542, 539, 548, 1572, 1570, 481, 2245, 466, 2242, 462, 2239, 492, 485, 482, 2249, 496, 494, 1534, 1531, 1528, 1538, 413, 2196, 406, 2191, 2188, 425, 419, 2202, 415, 2199, 432, 430, 427, 1472, 1467, 1464, 433, 1476, 1474, 368, 367, 2160, 365, 2159, 362, 2157, 2155, 2152, 378, 377, 375, 2166, 372, 2165, 369, 2162, 383, 381, 379, 2168, 1419, 1418, 1416, 1414, 385, 1411, 384, 1423, 1422, 1420, 1424, 2461, 802, 2441, 2439, 790, 786, 783, 794, 2409, 2406, 2403, 750, 742, 738, 2414, 756, 753, 1720, 2367, 2365, 2362, 2359, 1663, 693, 691, 684, 2373, 680, 2370, 702, 699, 696, 704, 1690, 1687, 2337, 2336, 2334, 2332, 1624, 2329, 1622, 640, 637, 2344, 634, 2342, 630, 2340, 650, 648, 645, 2346, 655, 653, 1653, 1651, 1649, 1655, 2612, 2597, 2595, 2571, 2568, 2565, 2576, 2534, 2529, 2526, 1787, 2540, 2537, 907, 904, 900, 910, 2503, 2502, 2500, 2498, 1768, 2495, 1767, 2510, 2508, 2506, 869, 866, 863, 2513, 876, 874, 1782, 2720, 2713, 2711, 2697, 2694, 2691, 2702, 2672, 2670, 2664, 1828, 2678, 2675, 2647, 2646, 2644, 2642, 1823, 2639, 1822, 2654, 2652, 2650, 2657, 2771, 1855, 2765, 2762, 1850, 1849, 2751, 2749, 2747, 2754, 353, 2148, 344, 342, 336, 2142, 332, 2140, 345, 1375, 1373, 306, 2130, 299, 2128, 295, 2125, 319, 314, 311, 2132, 1354, 1352, 1349, 1356, 262, 257, 2101, 253, 2096, 2093, 274, 273, 267, 2107, 263, 2104, 280, 278, 275, 1316, 1311, 1308, 1320, 1318, 2052, 202, 2050, 2044, 2040, 219, 2063, 212, 2060, 208, 2055, 224, 221, 2066, 1260, 1258, 1252, 231, 1248, 229, 1266, 1264, 1261, 1268, 155, 1998, 153, 1996, 1994, 1991, 1988, 165, 164, 2007, 162, 2006, 159, 2003, 2000, 172, 171, 169, 2012, 166, 2010, 1186, 1184, 1182, 1179, 175, 1176, 173, 1192, 1191, 1189, 1187, 176, 1194, 1193, 2313, 2307, 2305, 592, 589, 2294, 2292, 2289, 578, 572, 568, 2297, 580, 1591, 2272, 2267, 2264, 1547, 538, 536, 529, 2278, 525, 2275, 547, 544, 541, 1574, 1571, 2237, 2235, 2229, 1493, 2225, 1489, 478, 2247, 470, 2244, 465, 2241, 493, 488, 484, 2250, 498, 495, 1536, 1533, 1530, 1539, 2187, 2186, 2184, 2182, 1432, 2179, 1430, 2176, 1427, 414, 412, 2197, 409, 2195, 405, 2193, 2190, 426, 424, 421, 2203, 418, 2201, 431, 429, 1473, 1471, 1469, 1466, 434, 1477, 1475, 2478, 2472, 2470, 2459, 2457, 2454, 2462, 803, 2437, 2432, 2429, 1726, 2443, 2440, 792, 789, 785, 2401, 2399, 2393, 1702, 2389, 1699, 2411, 2408, 2405, 745, 741, 2415, 758, 755, 1721, 2358, 2357, 2355, 2353, 1661, 2350, 1660, 2347, 1657, 2368, 2366, 2364, 2361, 1666, 690, 687, 2374, 683, 2372, 701, 698, 705, 1691, 1689, 2619, 2617, 2610, 2608, 2605, 2613, 2593, 2588, 2585, 1803, 2599, 2596, 2563, 2561, 2555, 1797, 2551, 1795, 2573, 2570, 2567, 2577, 2525, 2524, 2522, 2520, 1786, 2517, 1785, 2514, 1783, 2535, 2533, 2531, 2528, 1788, 2541, 2539, 906, 903, 911, 2721, 1844, 2715, 2712, 1838, 1836, 2699, 2696, 2693, 2703, 1827, 1826, 1824, 2673, 2671, 2669, 2666, 1829, 2679, 2677, 1858, 1857, 2772, 1854, 1853, 1851, 1856, 2766, 2764, 143, 1987, 139, 1986, 135, 133, 131, 1984, 128, 1983, 125, 1981, 138, 137, 136, 1985, 1133, 1132, 1130, 112, 110, 1974, 107, 1973, 104, 1971, 1969, 122, 121, 119, 117, 1977, 114, 1976, 124, 1115, 1114, 1112, 1110, 1117, 1116, 84, 83, 1953, 81, 1952, 78, 1950, 1948, 1945, 94, 93, 91, 1959, 88, 1958, 85, 1955, 99, 97, 95, 1961, 1086, 1085, 1083, 1081, 1078, 100, 1090, 1089, 1087, 1091, 49, 47, 1917, 44, 1915, 1913, 1910, 1907, 59, 1926, 56, 1925, 53, 1922, 1919, 66, 64, 1931, 61, 1929, 1042, 1040, 1038, 71, 1035, 70, 1032, 68, 1048, 1047, 1045, 1043, 1050, 1049, 12, 10, 1869, 1867, 1864, 1861, 21, 1880, 19, 1877, 1874, 1871, 28, 1888, 25, 1886, 22, 1883, 982, 980, 977, 974, 32, 30, 991, 989, 987, 984, 34, 995, 994, 992, 2151, 2150, 2147, 2146, 2144, 356, 355, 354, 2149, 2139, 2138, 2136, 2134, 1359, 343, 341, 338, 2143, 335, 2141, 348, 347, 346, 1376, 1374, 2124, 2123, 2121, 2119, 1326, 2116, 1324, 310, 308, 305, 2131, 302, 2129, 298, 2127, 320, 318, 316, 313, 2133, 322, 321, 1355, 1353, 1351, 1357, 2092, 2091, 2089, 2087, 1276, 2084, 1274, 2081, 1271, 259, 2102, 256, 2100, 252, 2098, 2095, 272, 269, 2108, 266, 2106, 281, 279, 277, 1317, 1315, 1313, 1310, 282, 1321, 1319, 2039, 2037, 2035, 2032, 1203, 2029, 1200, 1197, 207, 2053, 205, 2051, 201, 2049, 2046, 2043, 220, 218, 2064, 215, 2062, 211, 2059, 228, 226, 223, 2069, 1259, 1257, 1254, 232, 1251, 230, 1267, 1265, 1263, 2316, 2315, 2312, 2311, 2309, 2314, 2304, 2303, 2301, 2299, 1593, 2308, 2306, 590, 2288, 2287, 2285, 2283, 1578, 2280, 1577, 2295, 2293, 2291, 579, 577, 574, 571, 2298, 582, 581, 1592, 2263, 2262, 2260, 2258, 1545, 2255, 1544, 2252, 1541, 2273, 2271, 2269, 2266, 1550, 535, 532, 2279, 528, 2277, 546, 543, 549, 1575, 1573, 2224, 2222, 2220, 1486, 2217, 1485, 2214, 1482, 1479, 2238, 2236, 2234, 2231, 1496, 2228, 1492, 480, 477, 2248, 473, 2246, 469, 2243, 490, 487, 2251, 497, 1537, 1535, 1532, 2477, 2476, 2474, 2479, 2469, 2468, 2466, 2464, 1730, 2473, 2471, 2453, 2452, 2450, 2448, 1729, 2445, 1728, 2460, 2458, 2456, 2463, 805, 804, 2428, 2427, 2425, 2423, 1725, 2420, 1724, 2417, 1722, 2438, 2436, 2434, 2431, 1727, 2444, 2442, 793, 791, 788, 795, 2388, 2386, 2384, 1697, 2381, 1696, 2378, 1694, 1692, 2402, 2400, 2398, 2395, 1703, 2392, 1701, 2412, 2410, 2407, 751, 748, 744, 2416, 759, 757, 1807, 2620, 2618, 1806, 1805, 2611, 2609, 2607, 2614, 1802, 1801, 1799, 2594, 2592, 2590, 2587, 1804, 2600, 2598, 1794, 1793, 1791, 1789, 2564, 2562, 2560, 2557, 1798, 2554, 1796, 2574, 2572, 2569, 2578, 1847, 1846, 2722, 1843, 1842, 1840, 1845, 2716, 2714, 1835, 1834, 1832, 1830, 1839, 1837, 2700, 2698, 2695, 2704, 1817, 1811, 1810, 897, 862, 1777, 829, 826, 838, 1760, 1758, 808, 2481, 1741, 1740, 1738, 1743, 2624, 1818, 2726, 2776, 782, 740, 737, 1715, 686, 679, 695, 1682, 1680, 639, 628, 2339, 647, 644, 1645, 1643, 1640, 1648, 602, 600, 597, 595, 2320, 593, 2318, 609, 607, 604, 1611, 1610, 1608, 1606, 613, 1615, 1613, 2328, 926, 924, 892, 886, 899, 857, 850, 2505, 1778, 824, 823, 821, 819, 2488, 818, 2486, 833, 831, 828, 840, 1761, 1759, 2649, 2632, 2630, 2746, 2734, 2732, 2782, 2781, 570, 567, 1587, 531, 527, 523, 540, 1566, 1564, 476, 467, 463, 2240, 486, 483, 1524, 1521, 1518, 1529, 411, 403, 2192, 399, 2189, 423, 416, 1462, 1457, 1454, 428, 1468, 1465, 2210, 366, 363, 2158, 360, 2156, 357, 2153, 376, 373, 370, 2163, 1410, 1409, 1407, 1405, 382, 1402, 380, 1417, 1415, 1412, 1421, 2175, 2174, 777, 774, 771, 784, 732, 725, 722, 2404, 743, 1716, 676, 674, 668, 2363, 665, 2360, 685, 1684, 1681, 626, 624, 622, 2335, 620, 2333, 617, 2330, 641, 635, 649, 1646, 1644, 1642, 2566, 928, 925, 2530, 2527, 894, 891, 888, 2501, 2499, 2496, 858, 856, 854, 851, 1779, 2692, 2668, 2665, 2645, 2643, 2640, 2651, 2768, 2759, 2757, 2744, 2743, 2741, 2748, 352, 1382, 340, 337, 333, 1371, 1369, 307, 300, 296, 2126, 315, 312, 1347, 1342, 1350, 261, 258, 250, 2097, 246, 2094, 271, 268, 264, 1306, 1301, 1298, 276, 1312, 1309, 2115, 203, 2048, 195, 2045, 191, 2041, 213, 209, 2056, 1246, 1244, 1238, 225, 1234, 222, 1256, 1253, 1249, 1262, 2080, 2079, 154, 1997, 150, 1995, 147, 1992, 1989, 163, 160, 2004, 156, 2001, 1175, 1174, 1172, 1170, 1167, 170, 1164, 167, 1185, 1183, 1180, 1177, 174, 1190, 1188, 2025, 2024, 2022, 587, 586, 564, 559, 556, 2290, 573, 1588, 520, 518, 512, 2268, 508, 2265, 530, 1568, 1565, 461, 457, 2233, 450, 2230, 446, 2226, 479, 471, 489, 1526, 1523, 1520, 397, 395, 2185, 392, 2183, 389, 2180, 2177, 410, 2194, 402, 422, 1463, 1461, 1459, 1456, 1470, 2455, 799, 2433, 2430, 779, 776, 773, 2397, 2394, 2390, 734, 728, 724, 746, 1717, 2356, 2354, 2351, 2348, 1658, 677, 675, 673, 670, 667, 688, 1685, 1683, 2606, 2589, 2586, 2559, 2556, 2552, 927, 2523, 2521, 2518, 2515, 1784, 2532, 895, 893, 890, 2718, 2709, 2707, 2689, 2687, 2684, 2663, 2662, 2660, 2658, 1825, 2667, 2769, 1852, 2760, 2758, 142, 141, 1139, 1138, 134, 132, 129, 126, 1982, 1129, 1128, 1126, 1131, 113, 111, 108, 105, 1972, 101, 1970, 120, 118, 115, 1109, 1108, 1106, 1104, 123, 1113, 1111, 82, 79, 1951, 75, 1949, 72, 1946, 92, 89, 86, 1956, 1077, 1076, 1074, 1072, 98, 1069, 96, 1084, 1082, 1079, 1088, 1968, 1967, 48, 45, 1916, 42, 1914, 39, 1911, 1908, 60, 57, 54, 1923, 50, 1920, 1031, 1030, 1028, 1026, 67, 1023, 65, 1020, 62, 1041, 1039, 1036, 1033, 69, 1046, 1044, 1944, 1943, 1941, 11, 9, 1868, 7, 1865, 1862, 1859, 20, 1878, 16, 1875, 13, 1872, 970, 968, 966, 963, 29, 960, 26, 23, 983, 981, 978, 975, 33, 971, 31, 990, 988, 985, 1906, 1904, 1902, 993, 351, 2145, 1383, 331, 330, 328, 326, 2137, 323, 2135, 339, 1372, 1370, 294, 293, 291, 289, 2122, 286, 2120, 283, 2117, 309, 303, 317, 1348, 1346, 1344, 245, 244, 242, 2090, 239, 2088, 236, 2085, 2082, 260, 2099, 249, 270, 1307, 1305, 1303, 1300, 1314, 189, 2038, 186, 2036, 183, 2033, 2030, 2026, 206, 198, 2047, 194, 216, 1247, 1245, 1243, 1240, 227, 1237, 1255, 2310, 2302, 2300, 2286, 2284, 2281, 565, 563, 561, 558, 575, 1589, 2261, 2259, 2256, 2253, 1542, 521, 519, 517, 514, 2270, 511, 533, 1569, 1567, 2223, 2221, 2218, 2215, 1483, 2211, 1480, 459, 456, 453, 2232, 449, 474, 491, 1527, 1525, 1522, 2475, 2467, 2465, 2451, 2449, 2446, 801, 800, 2426, 2424, 2421, 2418, 1723, 2435, 780, 778, 775, 2387, 2385, 2382, 2379, 1695, 2375, 1693, 2396, 735, 733, 730, 727, 749, 1718, 2616, 2615, 2604, 2603, 2601, 2584, 2583, 2581, 2579, 1800, 2591, 2550, 2549, 2547, 2545, 1792, 2542, 1790, 2558, 929, 2719, 1841, 2710, 2708, 1833, 1831, 2690, 2688, 2686, 1815, 1809, 1808, 1774, 1756, 1754, 1737, 1736, 1734, 1739, 1816, 1711, 1676, 1674, 633, 629, 1638, 1636, 1633, 1641, 598, 1605, 1604, 1602, 1600, 605, 1609, 1607, 2327, 887, 853, 1775, 822, 820, 1757, 1755, 1584, 524, 1560, 1558, 468, 464, 1514, 1511, 1508, 1519, 408, 404, 400, 1452, 1447, 1444, 417, 1458, 1455, 2208, 364, 361, 358, 2154, 1401, 1400, 1398, 1396, 374, 1393, 371, 1408, 1406, 1403, 1413, 2173, 2172, 772, 726, 723, 1712, 672, 669, 666, 682, 1678, 1675, 625, 623, 621, 618, 2331, 636, 632, 1639, 1637, 1635, 920, 918, 884, 880, 889, 849, 848, 847, 846, 2497, 855, 852, 1776, 2641, 2742, 2787, 1380, 334, 1367, 1365, 301, 297, 1340, 1338, 1335, 1343, 255, 251, 247, 1296, 1291, 1288, 265, 1302, 1299, 2113, 204, 196, 192, 2042, 1232, 1230, 1224, 214, 1220, 210, 1242, 1239, 1235, 1250, 2077, 2075, 151, 148, 1993, 144, 1990, 1163, 1162, 1160, 1158, 1155, 161, 1152, 157, 1173, 1171, 1168, 1165, 168, 1181, 1178, 2021, 2020, 2018, 2023, 585, 560, 557, 1585, 516, 509, 1562, 1559, 458, 447, 2227, 472, 1516, 1513, 1510, 398, 396, 393, 390, 2181, 386, 2178, 407, 1453, 1451, 1449, 1446, 420, 1460, 2209, 769, 764, 720, 712, 2391, 729, 1713, 664, 663, 661, 659, 2352, 656, 2349, 671, 1679, 1677, 2553, 922, 919, 2519, 2516, 885, 883, 881, 2685, 2661, 2659, 2767, 2756, 2755, 140, 1137, 1136, 130, 127, 1125, 1124, 1122, 1127, 109, 106, 102, 1103, 1102, 1100, 1098, 116, 1107, 1105, 1980, 80, 76, 73, 1947, 1068, 1067, 1065, 1063, 90, 1060, 87, 1075, 1073, 1070, 1080, 1966, 1965, 46, 43, 40, 1912, 36, 1909, 1019, 1018, 1016, 1014, 58, 1011, 55, 1008, 51, 1029, 1027, 1024, 1021, 63, 1037, 1034, 1940, 1939, 1937, 1942, 8, 1866, 4, 1863, 1, 1860, 956, 954, 952, 949, 946, 17, 14, 969, 967, 964, 961, 27, 957, 24, 979, 976, 972, 1901, 1900, 1898, 1896, 986, 1905, 1903, 350, 349, 1381, 329, 327, 324, 1368, 1366, 292, 290, 287, 284, 2118, 304, 1341, 1339, 1337, 1345, 243, 240, 237, 2086, 233, 2083, 254, 1297, 1295, 1293, 1290, 1304, 2114, 190, 187, 184, 2034, 180, 2031, 177, 2027, 199, 1233, 1231, 1229, 1226, 217, 1223, 1241, 2078, 2076, 584, 555, 554, 552, 550, 2282, 562, 1586, 507, 506, 504, 502, 2257, 499, 2254, 515, 1563, 1561, 445, 443, 441, 2219, 438, 2216, 435, 2212, 460, 454, 475, 1517, 1515, 1512, 2447, 798, 797, 2422, 2419, 770, 768, 766, 2383, 2380, 2376, 721, 719, 717, 714, 731, 1714, 2602, 2582, 2580, 2548, 2546, 2543, 923, 921, 2717, 2706, 2705, 2683, 2682, 2680, 1771, 1752, 1750, 1733, 1732, 1731, 1735, 1814, 1707, 1670, 1668, 1631, 1629, 1626, 1634, 1599, 1598, 1596, 1594, 1603, 1601, 2326, 1772, 1753, 1751, 1581, 1554, 1552, 1504, 1501, 1498, 1509, 1442, 1437, 1434, 401, 1448, 1445, 2206, 1392, 1391, 1389, 1387, 1384, 359, 1399, 1397, 1394, 1404, 2171, 2170, 1708, 1672, 1669, 619, 1632, 1630, 1628, 1773, 1378, 1363, 1361, 1333, 1328, 1336, 1286, 1281, 1278, 248, 1292, 1289, 2111, 1218, 1216, 1210, 197, 1206, 193, 1228, 1225, 1221, 1236, 2073, 2071, 1151, 1150, 1148, 1146, 152, 1143, 149, 1140, 145, 1161, 1159, 1156, 1153, 158, 1169, 1166, 2017, 2016, 2014, 2019, 1582, 510, 1556, 1553, 452, 448, 1506, 1500, 394, 391, 387, 1443, 1441, 1439, 1436, 1450, 2207, 765, 716, 713, 1709, 662, 660, 657, 1673, 1671, 916, 914, 879, 878, 877, 882, 1135, 1134, 1121, 1120, 1118, 1123, 1097, 1096, 1094, 1092, 103, 1101, 1099, 1979, 1059, 1058, 1056, 1054, 77, 1051, 74, 1066, 1064, 1061, 1071, 1964, 1963, 1007, 1006, 1004, 1002, 999, 41, 996, 37, 1017, 1015, 1012, 1009, 52, 1025, 1022, 1936, 1935, 1933, 1938, 942, 940, 938, 935, 932, 5, 2, 955, 953, 950, 947, 18, 943, 15, 965, 962, 958, 1895, 1894, 1892, 1890, 973, 1899, 1897, 1379, 325, 1364, 1362, 288, 285, 1334, 1332, 1330, 241, 238, 234, 1287, 1285, 1283, 1280, 1294, 2112, 188, 185, 181, 178, 2028, 1219, 1217, 1215, 1212, 200, 1209, 1227, 2074, 2072, 583, 553, 551, 1583, 505, 503, 500, 513, 1557, 1555, 444, 442, 439, 436, 2213, 455, 451, 1507, 1505, 1502, 796, 763, 762, 760, 767, 711, 710, 708, 706, 2377, 718, 715, 1710, 2544, 917, 915, 2681, 1627, 1597, 1595, 2325, 1769, 1749, 1747, 1499, 1438, 1435, 2204, 1390, 1388, 1385, 1395, 2169, 2167, 1704, 1665, 1662, 1625, 1623, 1620, 1770, 1329, 1282, 1279, 2109, 1214, 1207, 1222, 2068, 2065, 1149, 1147, 1144, 1141, 146, 1157, 1154, 2013, 2011, 2008, 2015, 1579, 1549, 1546, 1495, 1487, 1433, 1431, 1428, 1425, 388, 1440, 2205, 1705, 658, 1667, 1664, 1119, 1095, 1093, 1978, 1057, 1055, 1052, 1062, 1962, 1960, 1005, 1003, 1000, 997, 38, 1013, 1010, 1932, 1930, 1927, 1934, 941, 939, 936, 933, 6, 930, 3, 951, 948, 944, 1889, 1887, 1884, 1881, 959, 1893, 1891, 35, 1377, 1360, 1358, 1327, 1325, 1322, 1331, 1277, 1275, 1272, 1269, 235, 1284, 2110, 1205, 1204, 1201, 1198, 182, 1195, 179, 1213, 2070, 2067, 1580, 501, 1551, 1548, 440, 437, 1497, 1494, 1490, 1503, 761, 709, 707, 1706, 913, 912, 2198, 1386, 2164, 2161, 1621, 1766, 2103, 1208, 2058, 2054, 1145, 1142, 2005, 2002, 1999, 2009, 1488, 1429, 1426, 2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954, 1001, 998, 1924, 1921, 1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882, 1323, 1273, 1270, 2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576, 1543, 1540, 1484, 1481, 1478, 1491, 1700, ] +; +pub struct PDF417Common { +} + +impl PDF417Common { + + fn new() -> PDF417Common { + } + + /** + * @param moduleBitCount values to sum + * @return sum of values + * @deprecated call {@link MathUtils#sum(int[])} + */ + pub fn get_bit_count_sum( module_bit_count: &Vec) -> i32 { + return MathUtils::sum(&module_bit_count); + } + + pub fn to_int_array( list: &Collection) -> Vec { + if list == null || list.is_empty() { + return EMPTY_INT_ARRAY; + } + let mut result: [i32; list.size()] = [0; list.size()]; + let mut i: i32 = 0; + for let integer: Integer in list { + result[i += 1 !!!check!!! post increment] = integer; + } + return result; + } + + /** + * @param symbol encoded symbol to translate to a codeword + * @return the codeword corresponding to the symbol. + */ + pub fn get_codeword( symbol: i32) -> i32 { + let i: i32 = Arrays::binary_search(&SYMBOL_TABLE, symbol & 0x3FFFF); + if i < 0 { + return -1; + } + return (CODEWORD_TABLE[i] - 1) % NUMBER_OF_CODEWORDS; + } +} + +// NEW FILE: p_d_f417_reader.rs +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::pdf417; + +/** + * This implementation can detect and decode PDF417 codes in an image. + * + * @author Guenther Grau + */ + + const EMPTY_RESULT_ARRAY: [Option; 0] = [None; 0]; +#[derive(Reader, MultipleBarcodeReader)] +pub struct PDF417Reader { +} + +impl PDF417Reader { + + /** + * Locates and decodes a PDF417 code in an image. + * + * @return a String representing the content encoded by the PDF417 code + * @throws NotFoundException if a PDF417 code cannot be found, + * @throws FormatException if a PDF417 cannot be decoded + */ + pub fn decode(&self, image: &BinaryBitmap) -> /* throws NotFoundException, FormatException, ChecksumException */Result> { + return Ok(::decode(image, null)); + } + + pub fn decode(&self, image: &BinaryBitmap, hints: &Map) -> /* throws NotFoundException, FormatException, ChecksumException */Result> { + let result: Vec = ::decode(image, &hints, false); + if result.len() == 0 || result[0] == null { + throw NotFoundException::get_not_found_instance(); + } + return Ok(result[0]); + } + + pub fn decode_multiple(&self, image: &BinaryBitmap) -> /* throws NotFoundException */Result, Rc> { + return Ok(self.decode_multiple(image, null)); + } + + pub fn decode_multiple(&self, image: &BinaryBitmap, hints: &Map) -> /* throws NotFoundException */Result, Rc> { + let tryResult1 = 0; + 'try1: loop { + { + return Ok(::decode(image, &hints, true)); + } + break 'try1 + } + match tryResult1 { + catch ( ignored: &FormatExceptionChecksumException | ) { + throw NotFoundException::get_not_found_instance(); + } 0 => break + } + + } + + fn decode( image: &BinaryBitmap, hints: &Map, multiple: bool) -> /* throws NotFoundException, FormatException, ChecksumException */Result, Rc> { + let results: List = ArrayList<>::new(); + let detector_result: PDF417DetectorResult = Detector::detect(image, &hints, multiple); + for let points: Vec in detector_result.get_points() { + let decoder_result: DecoderResult = PDF417ScanningDecoder::decode(&detector_result.get_bits(), points[4], points[5], points[6], points[7], &::get_min_codeword_width(points), &::get_max_codeword_width(points)); + let result: Result = Result::new(&decoder_result.get_text(), &decoder_result.get_raw_bytes(), points, BarcodeFormat::PDF_417); + result.put_metadata(ResultMetadataType::ERROR_CORRECTION_LEVEL, &decoder_result.get_e_c_level()); + let pdf417_result_metadata: PDF417ResultMetadata = decoder_result.get_other() as PDF417ResultMetadata; + if pdf417_result_metadata != null { + result.put_metadata(ResultMetadataType::PDF417_EXTRA_METADATA, pdf417_result_metadata); + } + result.put_metadata(ResultMetadataType::ORIENTATION, &detector_result.get_rotation()); + result.put_metadata(ResultMetadataType::SYMBOLOGY_IDENTIFIER, format!("]L{}", decoder_result.get_symbology_modifier())); + results.add(result); + } + return Ok(results.to_array(EMPTY_RESULT_ARRAY)); + } + + fn get_max_width( p1: &ResultPoint, p2: &ResultPoint) -> i32 { + if p1 == null || p2 == null { + return 0; + } + return Math::abs(p1.get_x() - p2.get_x()) as i32; + } + + fn get_min_width( p1: &ResultPoint, p2: &ResultPoint) -> i32 { + if p1 == null || p2 == null { + return Integer::MAX_VALUE; + } + return Math::abs(p1.get_x() - p2.get_x()) as i32; + } + + fn get_max_codeword_width( p: &Vec) -> i32 { + return Math::max(&Math::max(&::get_max_width(p[0], p[4]), ::get_max_width(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD / PDF417Common.MODULES_IN_STOP_PATTERN), &Math::max(&::get_max_width(p[1], p[5]), ::get_max_width(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD / PDF417Common.MODULES_IN_STOP_PATTERN)); + } + + fn get_min_codeword_width( p: &Vec) -> i32 { + return Math::min(&Math::min(&::get_min_width(p[0], p[4]), ::get_min_width(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD / PDF417Common.MODULES_IN_STOP_PATTERN), &Math::min(&::get_min_width(p[1], p[5]), ::get_min_width(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD / PDF417Common.MODULES_IN_STOP_PATTERN)); + } + + pub fn reset(&self) { + // nothing needs to be reset + } +} + +// NEW FILE: p_d_f417_result_metadata.rs +/* + * 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::pdf417; + +/** + * @author Guenther Grau + */ +pub struct PDF417ResultMetadata { + + let segment_index: i32; + + let file_id: String; + + let last_segment: bool; + + let segment_count: i32 = -1; + + let sender: String; + + let addressee: String; + + let file_name: String; + + let file_size: i64 = -1; + + let timestamp: i64 = -1; + + let checksum: i32 = -1; + + let optional_data: Vec; +} + +impl PDF417ResultMetadata { + + /** + * The Segment ID represents the segment of the whole file distributed over different symbols. + * + * @return File segment index + */ + pub fn get_segment_index(&self) -> i32 { + return self.segment_index; + } + + pub fn set_segment_index(&self, segment_index: i32) { + self.segmentIndex = segment_index; + } + + /** + * Is the same for each related PDF417 symbol + * + * @return File ID + */ + pub fn get_file_id(&self) -> String { + return self.file_id; + } + + pub fn set_file_id(&self, file_id: &String) { + self.fileId = file_id; + } + + /** + * @return always null + * @deprecated use dedicated already parsed fields + */ + pub fn get_optional_data(&self) -> Vec { + return self.optional_data; + } + + /** + * @param optionalData old optional data format as int array + * @deprecated parse and use new fields + */ + pub fn set_optional_data(&self, optional_data: &Vec) { + self.optionalData = optional_data; + } + + /** + * @return true if it is the last segment + */ + pub fn is_last_segment(&self) -> bool { + return self.last_segment; + } + + pub fn set_last_segment(&self, last_segment: bool) { + self.lastSegment = last_segment; + } + + /** + * @return count of segments, -1 if not set + */ + pub fn get_segment_count(&self) -> i32 { + return self.segment_count; + } + + pub fn set_segment_count(&self, segment_count: i32) { + self.segmentCount = segment_count; + } + + pub fn get_sender(&self) -> String { + return self.sender; + } + + pub fn set_sender(&self, sender: &String) { + self.sender = sender; + } + + pub fn get_addressee(&self) -> String { + return self.addressee; + } + + pub fn set_addressee(&self, addressee: &String) { + self.addressee = addressee; + } + + /** + * Filename of the encoded file + * + * @return filename + */ + pub fn get_file_name(&self) -> String { + return self.file_name; + } + + pub fn set_file_name(&self, file_name: &String) { + self.fileName = file_name; + } + + /** + * filesize in bytes of the encoded file + * + * @return filesize in bytes, -1 if not set + */ + pub fn get_file_size(&self) -> i64 { + return self.file_size; + } + + pub fn set_file_size(&self, file_size: i64) { + self.fileSize = file_size; + } + + /** + * 16-bit CRC checksum using CCITT-16 + * + * @return crc checksum, -1 if not set + */ + pub fn get_checksum(&self) -> i32 { + return self.checksum; + } + + pub fn set_checksum(&self, checksum: i32) { + self.checksum = checksum; + } + + /** + * unix epock timestamp, elapsed seconds since 1970-01-01 + * + * @return elapsed seconds, -1 if not set + */ + pub fn get_timestamp(&self) -> i64 { + return self.timestamp; + } + + pub fn set_timestamp(&self, timestamp: i64) { + self.timestamp = timestamp; + } +} + +// NEW FILE: p_d_f417_writer.rs +/* + * Copyright 2012 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::pdf417; + +/** + * @author Jacob Haynes + * @author qwandor@google.com (Andrew Walbran) + */ + +/** + * default white space (margin) around the code + */ + const WHITE_SPACE: i32 = 30; + +/** + * default error correction level + */ + const DEFAULT_ERROR_CORRECTION_LEVEL: i32 = 2; +#[derive(Writer)] +pub struct PDF417Writer { +} + +impl PDF417Writer { + + pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32, hints: &Map) -> /* throws WriterException */Result> { + if format != BarcodeFormat::PDF_417 { + throw IllegalArgumentException::new(format!("Can only encode PDF_417, but got {}", format)); + } + let encoder: PDF417 = PDF417::new(); + let mut margin: i32 = WHITE_SPACE; + let error_correction_level: i32 = DEFAULT_ERROR_CORRECTION_LEVEL; + let auto_e_c_i: bool = false; + if hints != null { + if hints.contains_key(EncodeHintType::PDF417_COMPACT) { + encoder.set_compact(&Boolean::parse_boolean(&hints.get(EncodeHintType::PDF417_COMPACT).to_string())); + } + if hints.contains_key(EncodeHintType::PDF417_COMPACTION) { + encoder.set_compaction(&Compaction::value_of(&hints.get(EncodeHintType::PDF417_COMPACTION).to_string())); + } + if hints.contains_key(EncodeHintType::PDF417_DIMENSIONS) { + let dimensions: Dimensions = hints.get(EncodeHintType::PDF417_DIMENSIONS) as Dimensions; + encoder.set_dimensions(&dimensions.get_max_cols(), &dimensions.get_min_cols(), &dimensions.get_max_rows(), &dimensions.get_min_rows()); + } + if hints.contains_key(EncodeHintType::MARGIN) { + margin = Integer::parse_int(&hints.get(EncodeHintType::MARGIN).to_string()); + } + if hints.contains_key(EncodeHintType::ERROR_CORRECTION) { + error_correction_level = Integer::parse_int(&hints.get(EncodeHintType::ERROR_CORRECTION).to_string()); + } + if hints.contains_key(EncodeHintType::CHARACTER_SET) { + let encoding: Charset = Charset::for_name(&hints.get(EncodeHintType::CHARACTER_SET).to_string()); + encoder.set_encoding(&encoding); + } + auto_e_c_i = hints.contains_key(EncodeHintType::PDF417_AUTO_ECI) && Boolean::parse_boolean(&hints.get(EncodeHintType::PDF417_AUTO_ECI).to_string()); + } + return Ok(::bit_matrix_from_encoder(encoder, &contents, error_correction_level, width, height, margin, auto_e_c_i)); + } + + pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32) -> /* throws WriterException */Result> { + return Ok(self.encode(&contents, format, width, height, null)); + } + + /** + * Takes encoder, accounts for width/height, and retrieves bit matrix + */ + fn bit_matrix_from_encoder( encoder: &PDF417, contents: &String, error_correction_level: i32, width: i32, height: i32, margin: i32, auto_e_c_i: bool) -> /* throws WriterException */Result> { + encoder.generate_barcode_logic(&contents, error_correction_level, auto_e_c_i); + let aspect_ratio: i32 = 4; + let original_scale: Vec> = encoder.get_barcode_matrix().get_scaled_matrix(1, aspect_ratio); + let mut rotated: bool = false; + if (height > width) != (original_scale[0].len() < original_scale.len()) { + original_scale = ::rotate_array(&original_scale); + rotated = true; + } + let scale_x: i32 = width / original_scale[0].len(); + let scale_y: i32 = height / original_scale.len(); + let scale: i32 = Math::min(scale_x, scale_y); + if scale > 1 { + let scaled_matrix: Vec> = encoder.get_barcode_matrix().get_scaled_matrix(scale, scale * aspect_ratio); + if rotated { + scaled_matrix = ::rotate_array(&scaled_matrix); + } + return Ok(::bit_matrix_from_bit_array(&scaled_matrix, margin)); + } + return Ok(::bit_matrix_from_bit_array(&original_scale, margin)); + } + + /** + * This takes an array holding the values of the PDF 417 + * + * @param input a byte array of information with 0 is black, and 1 is white + * @param margin border around the barcode + * @return BitMatrix of the input + */ + fn bit_matrix_from_bit_array( input: &Vec>, margin: i32) -> BitMatrix { + // Creates the bit matrix with extra space for whitespace + let output: BitMatrix = BitMatrix::new(input[0].len() + 2 * margin, input.len() + 2 * margin); + output.clear(); + { + let mut y: i32 = 0, let y_output: i32 = output.get_height() - margin - 1; + while y < input.len() { + { + let input_y: Vec = input[y]; + { + let mut x: i32 = 0; + while x < input[0].len() { + { + // Zero is white in the byte matrix + if input_y[x] == 1 { + output.set(x + margin, y_output); + } + } + x += 1; + } + } + + } + y += 1; + y_output -= 1; + } + } + + return output; + } + + /** + * Takes and rotates the it 90 degrees + */ + fn rotate_array( bitarray: &Vec>) -> Vec> { + let mut temp: [[i8; bitarray.len()]; bitarray[0].len()] = [[0; bitarray.len()]; bitarray[0].len()]; + { + let mut ii: i32 = 0; + while ii < bitarray.len() { + { + // This makes the direction consistent on screen when rotating the + // screen; + let mut inverseii: i32 = bitarray.len() - ii - 1; + { + let mut jj: i32 = 0; + while jj < bitarray[0].len() { + { + temp[jj][inverseii] = bitarray[ii][jj]; + } + jj += 1; + } + } + + } + ii += 1; + } + } + + return temp; + } +} + diff --git a/src/pdf417/decoder.rs b/src/pdf417/decoder.rs index e69de29..a532da2 100644 --- a/src/pdf417/decoder.rs +++ b/src/pdf417/decoder.rs @@ -0,0 +1,2871 @@ +import com.google.zxing.pdf417.PDF417Common; + +import com.google.zxing.NotFoundException; +import com.google.zxing.ResultPoint; +import com.google.zxing.common.BitMatrix; + +import com.google.zxing.FormatException; +import com.google.zxing.common.ECIStringBuilder; +import com.google.zxing.common.DecoderResult; +import com.google.zxing.pdf417.PDF417ResultMetadata; + +import com.google.zxing.pdf417.PDF417Common; + +import com.google.zxing.ResultPoint; +import com.google.zxing.pdf417.PDF417Common; + +import com.google.zxing.common.detector.MathUtils; +import com.google.zxing.pdf417.PDF417Common; + +import com.google.zxing.ChecksumException; +import com.google.zxing.FormatException; +import com.google.zxing.NotFoundException; +import com.google.zxing.ResultPoint; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.common.DecoderResult; +import com.google.zxing.common.detector.MathUtils; +import com.google.zxing.pdf417.PDF417Common; +import com.google.zxing.pdf417.decoder.ec.ErrorCorrection; + +// NEW FILE: barcode_metadata.rs +/* + * 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::pdf417::decoder; + +/** + * @author Guenther Grau + */ +struct BarcodeMetadata { + + let column_count: i32; + + let error_correction_level: i32; + + let row_count_upper_part: i32; + + let row_count_lower_part: i32; + + let row_count: i32; +} + +impl BarcodeMetadata { + + fn new( column_count: i32, row_count_upper_part: i32, row_count_lower_part: i32, error_correction_level: i32) -> BarcodeMetadata { + let .columnCount = column_count; + let .errorCorrectionLevel = error_correction_level; + let .rowCountUpperPart = row_count_upper_part; + let .rowCountLowerPart = row_count_lower_part; + let .rowCount = row_count_upper_part + row_count_lower_part; + } + + fn get_column_count(&self) -> i32 { + return self.column_count; + } + + fn get_error_correction_level(&self) -> i32 { + return self.error_correction_level; + } + + fn get_row_count(&self) -> i32 { + return self.row_count; + } + + fn get_row_count_upper_part(&self) -> i32 { + return self.row_count_upper_part; + } + + fn get_row_count_lower_part(&self) -> i32 { + return self.row_count_lower_part; + } +} + +// NEW FILE: barcode_value.rs +/* + * 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::pdf417::decoder; + +/** + * @author Guenther Grau + */ +struct BarcodeValue { + + let values: Map = HashMap<>::new(); +} + +impl BarcodeValue { + + /** + * Add an occurrence of a value + */ + fn set_value(&self, value: i32) { + let mut confidence: Integer = self.values.get(value); + if confidence == null { + confidence = 0; + } + confidence += 1; + self.values.put(value, &confidence); + } + + /** + * Determines the maximum occurrence of a set value and returns all values which were set with this occurrence. + * @return an array of int, containing the values with the highest occurrence, or null, if no value was set + */ + fn get_value(&self) -> Vec { + let max_confidence: i32 = -1; + let result: Collection = ArrayList<>::new(); + for let entry: Entry in self.values.entry_set() { + if entry.get_value() > max_confidence { + max_confidence = entry.get_value(); + result.clear(); + result.add(&entry.get_key()); + } else if entry.get_value() == max_confidence { + result.add(&entry.get_key()); + } + } + return PDF417Common::to_int_array(&result); + } + + fn get_confidence(&self, value: i32) -> Integer { + return self.values.get(value); + } +} + +// NEW FILE: bounding_box.rs +/* + * 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::pdf417::decoder; + +/** + * @author Guenther Grau + */ +struct BoundingBox { + + let mut image: BitMatrix; + + let top_left: ResultPoint; + + let bottom_left: ResultPoint; + + let top_right: ResultPoint; + + let bottom_right: ResultPoint; + + let min_x: i32; + + let max_x: i32; + + let min_y: i32; + + let max_y: i32; +} + +impl BoundingBox { + + fn new( image: &BitMatrix, top_left: &ResultPoint, bottom_left: &ResultPoint, top_right: &ResultPoint, bottom_right: &ResultPoint) -> BoundingBox throws NotFoundException { + let left_unspecified: bool = top_left == null || bottom_left == null; + let right_unspecified: bool = top_right == null || bottom_right == null; + if left_unspecified && right_unspecified { + throw NotFoundException::get_not_found_instance(); + } + if left_unspecified { + top_left = ResultPoint::new(0, &top_right.get_y()); + bottom_left = ResultPoint::new(0, &bottom_right.get_y()); + } else if right_unspecified { + top_right = ResultPoint::new(image.get_width() - 1, &top_left.get_y()); + bottom_right = ResultPoint::new(image.get_width() - 1, &bottom_left.get_y()); + } + let .image = image; + let .topLeft = top_left; + let .bottomLeft = bottom_left; + let .topRight = top_right; + let .bottomRight = bottom_right; + let .minX = Math::min(&top_left.get_x(), &bottom_left.get_x()) as i32; + let .maxX = Math::max(&top_right.get_x(), &bottom_right.get_x()) as i32; + let .minY = Math::min(&top_left.get_y(), &top_right.get_y()) as i32; + let .maxY = Math::max(&bottom_left.get_y(), &bottom_right.get_y()) as i32; + } + + fn new( bounding_box: &BoundingBox) -> BoundingBox { + let .image = bounding_box.image; + let .topLeft = bounding_box.topLeft; + let .bottomLeft = bounding_box.bottomLeft; + let .topRight = bounding_box.topRight; + let .bottomRight = bounding_box.bottomRight; + let .minX = bounding_box.minX; + let .maxX = bounding_box.maxX; + let .minY = bounding_box.minY; + let .maxY = bounding_box.maxY; + } + + fn merge( left_box: &BoundingBox, right_box: &BoundingBox) -> /* throws NotFoundException */Result> { + if left_box == null { + return Ok(right_box); + } + if right_box == null { + return Ok(left_box); + } + return Ok(BoundingBox::new(left_box.image, left_box.topLeft, left_box.bottomLeft, right_box.topRight, right_box.bottomRight)); + } + + fn add_missing_rows(&self, missing_start_rows: i32, missing_end_rows: i32, is_left: bool) -> /* throws NotFoundException */Result> { + let new_top_left: ResultPoint = self.top_left; + let new_bottom_left: ResultPoint = self.bottom_left; + let new_top_right: ResultPoint = self.top_right; + let new_bottom_right: ResultPoint = self.bottom_right; + if missing_start_rows > 0 { + let top: ResultPoint = if is_left { self.top_left } else { self.top_right }; + let new_min_y: i32 = top.get_y() as i32 - missing_start_rows; + if new_min_y < 0 { + new_min_y = 0; + } + let new_top: ResultPoint = ResultPoint::new(&top.get_x(), new_min_y); + if is_left { + new_top_left = new_top; + } else { + new_top_right = new_top; + } + } + if missing_end_rows > 0 { + let bottom: ResultPoint = if is_left { self.bottom_left } else { self.bottom_right }; + let new_max_y: i32 = bottom.get_y() as i32 + missing_end_rows; + if new_max_y >= self.image.get_height() { + new_max_y = self.image.get_height() - 1; + } + let new_bottom: ResultPoint = ResultPoint::new(&bottom.get_x(), new_max_y); + if is_left { + new_bottom_left = new_bottom; + } else { + new_bottom_right = new_bottom; + } + } + return Ok(BoundingBox::new(self.image, new_top_left, new_bottom_left, new_top_right, new_bottom_right)); + } + + fn get_min_x(&self) -> i32 { + return self.min_x; + } + + fn get_max_x(&self) -> i32 { + return self.max_x; + } + + fn get_min_y(&self) -> i32 { + return self.min_y; + } + + fn get_max_y(&self) -> i32 { + return self.max_y; + } + + fn get_top_left(&self) -> ResultPoint { + return self.top_left; + } + + fn get_top_right(&self) -> ResultPoint { + return self.top_right; + } + + fn get_bottom_left(&self) -> ResultPoint { + return self.bottom_left; + } + + fn get_bottom_right(&self) -> ResultPoint { + return self.bottom_right; + } +} + +// NEW FILE: codeword.rs +/* + * 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::pdf417::decoder; + +/** + * @author Guenther Grau + */ + + const BARCODE_ROW_UNKNOWN: i32 = -1; +struct Codeword { + + let start_x: i32; + + let end_x: i32; + + let bucket: i32; + + let value: i32; + + let row_number: i32 = BARCODE_ROW_UNKNOWN; +} + +impl Codeword { + + fn new( start_x: i32, end_x: i32, bucket: i32, value: i32) -> Codeword { + let .startX = start_x; + let .endX = end_x; + let .bucket = bucket; + let .value = value; + } + + fn has_valid_row_number(&self) -> bool { + return self.is_valid_row_number(self.row_number); + } + + fn is_valid_row_number(&self, row_number: i32) -> bool { + return row_number != BARCODE_ROW_UNKNOWN && self.bucket == (row_number % 3) * 3; + } + + fn set_row_number_as_row_indicator_column(&self) { + self.row_number = (self.value / 30) * 3 + self.bucket / 3; + } + + fn get_width(&self) -> i32 { + return self.end_x - self.start_x; + } + + fn get_start_x(&self) -> i32 { + return self.start_x; + } + + fn get_end_x(&self) -> i32 { + return self.end_x; + } + + fn get_bucket(&self) -> i32 { + return self.bucket; + } + + fn get_value(&self) -> i32 { + return self.value; + } + + fn get_row_number(&self) -> i32 { + return self.row_number; + } + + fn set_row_number(&self, row_number: i32) { + self.rowNumber = row_number; + } + + pub fn to_string(&self) -> String { + return format!("{}|{}", self.row_number, self.value); + } +} + +// NEW FILE: decoded_bit_stream_parser.rs +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::pdf417::decoder; + +/** + *

This class contains the methods for decoding the PDF417 codewords.

+ * + * @author SITA Lab (kevin.osullivan@sita.aero) + * @author Guenther Grau + */ + + const TEXT_COMPACTION_MODE_LATCH: i32 = 900; + + const BYTE_COMPACTION_MODE_LATCH: i32 = 901; + + const NUMERIC_COMPACTION_MODE_LATCH: i32 = 902; + + const BYTE_COMPACTION_MODE_LATCH_6: i32 = 924; + + const ECI_USER_DEFINED: i32 = 925; + + const ECI_GENERAL_PURPOSE: i32 = 926; + + const ECI_CHARSET: i32 = 927; + + const BEGIN_MACRO_PDF417_CONTROL_BLOCK: i32 = 928; + + const BEGIN_MACRO_PDF417_OPTIONAL_FIELD: i32 = 923; + + const MACRO_PDF417_TERMINATOR: i32 = 922; + + const MODE_SHIFT_TO_BYTE_COMPACTION_MODE: i32 = 913; + + const MAX_NUMERIC_CODEWORDS: i32 = 15; + + const MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME: i32 = 0; + + const MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT: i32 = 1; + + const MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP: i32 = 2; + + const MACRO_PDF417_OPTIONAL_FIELD_SENDER: i32 = 3; + + const MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE: i32 = 4; + + const MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE: i32 = 5; + + const MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM: i32 = 6; + + const PL: i32 = 25; + + const LL: i32 = 27; + + const AS: i32 = 27; + + const ML: i32 = 28; + + const AL: i32 = 28; + + const PS: i32 = 29; + + const PAL: i32 = 29; + + const PUNCT_CHARS: Vec = ";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'".to_char_array(); + + const MIXED_CHARS: Vec = "0123456789&\r\t,:#-.$/+%*=^".to_char_array(); + +/** + * Table containing values for the exponent of 900. + * This is used in the numeric compaction decode algorithm. + */ + const EXP900: Vec; + + const NUMBER_OF_SEQUENCE_CODEWORDS: i32 = 2; +struct DecodedBitStreamParser { +} + +impl DecodedBitStreamParser { + + enum Mode { + + ALPHA(), LOWER(), MIXED(), PUNCT(), ALPHA_SHIFT(), PUNCT_SHIFT() + } + + static { + EXP900 = : [Option; 16] = [None; 16]; + EXP900[0] = BigInteger::ONE; + let nine_hundred: BigInteger = BigInteger::value_of(900); + EXP900[1] = nine_hundred; + { + let mut i: i32 = 2; + while i < EXP900.len() { + { + EXP900[i] = EXP900[i - 1]::multiply(&nine_hundred); + } + i += 1; + } + } + + } + + fn new() -> DecodedBitStreamParser { + } + + fn decode( codewords: &Vec, ec_level: &String) -> /* throws FormatException */Result> { + let result: ECIStringBuilder = ECIStringBuilder::new(codewords.len() * 2); + let code_index: i32 = ::text_compaction(&codewords, 1, result); + let result_metadata: PDF417ResultMetadata = PDF417ResultMetadata::new(); + while code_index < codewords[0] { + let code: i32 = codewords[code_index += 1 !!!check!!! post increment]; + match code { + TEXT_COMPACTION_MODE_LATCH => + { + code_index = ::text_compaction(&codewords, code_index, result); + break; + } + BYTE_COMPACTION_MODE_LATCH => + { + } + BYTE_COMPACTION_MODE_LATCH_6 => + { + code_index = ::byte_compaction(code, &codewords, code_index, result); + break; + } + MODE_SHIFT_TO_BYTE_COMPACTION_MODE => + { + result.append(codewords[code_index += 1 !!!check!!! post increment] as char); + break; + } + NUMERIC_COMPACTION_MODE_LATCH => + { + code_index = ::numeric_compaction(&codewords, code_index, result); + break; + } + ECI_CHARSET => + { + result.append_e_c_i(codewords[code_index += 1 !!!check!!! post increment]); + break; + } + ECI_GENERAL_PURPOSE => + { + // Can't do anything with generic ECI; skip its 2 characters + code_index += 2; + break; + } + ECI_USER_DEFINED => + { + // Can't do anything with user ECI; skip its 1 character + code_index += 1; + break; + } + BEGIN_MACRO_PDF417_CONTROL_BLOCK => + { + code_index = ::decode_macro_block(&codewords, code_index, result_metadata); + break; + } + BEGIN_MACRO_PDF417_OPTIONAL_FIELD => + { + } + MACRO_PDF417_TERMINATOR => + { + // Should not see these outside a macro block + throw FormatException::get_format_instance(); + } + _ => + { + // Default to text compaction. During testing numerous barcodes + // appeared to be missing the starting mode. In these cases defaulting + // to text compaction seems to work. + code_index -= 1; + code_index = ::text_compaction(&codewords, code_index, result); + break; + } + } + } + if result.is_empty() && result_metadata.get_file_id() == null { + throw FormatException::get_format_instance(); + } + let decoder_result: DecoderResult = DecoderResult::new(null, &result.to_string(), null, &ec_level); + decoder_result.set_other(result_metadata); + return Ok(decoder_result); + } + + fn decode_macro_block( codewords: &Vec, code_index: i32, result_metadata: &PDF417ResultMetadata) -> /* throws FormatException */Result> { + if code_index + NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0] { + // we must have at least two bytes left for the segment index + throw FormatException::get_format_instance(); + } + let segment_index_array: [i32; NUMBER_OF_SEQUENCE_CODEWORDS] = [0; NUMBER_OF_SEQUENCE_CODEWORDS]; + { + let mut i: i32 = 0; + while i < NUMBER_OF_SEQUENCE_CODEWORDS { + { + segment_index_array[i] = codewords[code_index]; + } + i += 1; + code_index += 1; + } + } + + let segment_index_string: String = ::decode_base900to_base10(&segment_index_array, NUMBER_OF_SEQUENCE_CODEWORDS); + if segment_index_string.is_empty() { + result_metadata.set_segment_index(0); + } else { + let tryResult1 = 0; + 'try1: loop { + { + result_metadata.set_segment_index(&Integer::parse_int(&segment_index_string)); + } + break 'try1 + } + match tryResult1 { + catch ( nfe: &NumberFormatException) { + throw FormatException::get_format_instance(); + } 0 => break + } + + } + // Decoding the fileId codewords as 0-899 numbers, each 0-filled to width 3. This follows the spec + // (See ISO/IEC 15438:2015 Annex H.6) and preserves all info, but some generators (e.g. TEC-IT) write + // the fileId using text compaction, so in those cases the fileId will appear mangled. + let file_id: StringBuilder = StringBuilder::new(); + while code_index < codewords[0] && code_index < codewords.len() && codewords[code_index] != MACRO_PDF417_TERMINATOR && codewords[code_index] != BEGIN_MACRO_PDF417_OPTIONAL_FIELD { + file_id.append(&String::format("%03d", codewords[code_index])); + code_index += 1; + } + if file_id.length() == 0 { + // at least one fileId codeword is required (Annex H.2) + throw FormatException::get_format_instance(); + } + result_metadata.set_file_id(&file_id.to_string()); + let optional_fields_start: i32 = -1; + if codewords[code_index] == BEGIN_MACRO_PDF417_OPTIONAL_FIELD { + optional_fields_start = code_index + 1; + } + while code_index < codewords[0] { + match codewords[code_index] { + BEGIN_MACRO_PDF417_OPTIONAL_FIELD => + { + code_index += 1; + match codewords[code_index] { + MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME => + { + let file_name: ECIStringBuilder = ECIStringBuilder::new(); + code_index = ::text_compaction(&codewords, code_index + 1, file_name); + result_metadata.set_file_name(&file_name.to_string()); + break; + } + MACRO_PDF417_OPTIONAL_FIELD_SENDER => + { + let sender: ECIStringBuilder = ECIStringBuilder::new(); + code_index = ::text_compaction(&codewords, code_index + 1, sender); + result_metadata.set_sender(&sender.to_string()); + break; + } + MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE => + { + let addressee: ECIStringBuilder = ECIStringBuilder::new(); + code_index = ::text_compaction(&codewords, code_index + 1, addressee); + result_metadata.set_addressee(&addressee.to_string()); + break; + } + MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT => + { + let segment_count: ECIStringBuilder = ECIStringBuilder::new(); + code_index = ::numeric_compaction(&codewords, code_index + 1, segment_count); + result_metadata.set_segment_count(&Integer::parse_int(&segment_count.to_string())); + break; + } + MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP => + { + let timestamp: ECIStringBuilder = ECIStringBuilder::new(); + code_index = ::numeric_compaction(&codewords, code_index + 1, timestamp); + result_metadata.set_timestamp(&Long::parse_long(×tamp.to_string())); + break; + } + MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM => + { + let checksum: ECIStringBuilder = ECIStringBuilder::new(); + code_index = ::numeric_compaction(&codewords, code_index + 1, checksum); + result_metadata.set_checksum(&Integer::parse_int(&checksum.to_string())); + break; + } + MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE => + { + let file_size: ECIStringBuilder = ECIStringBuilder::new(); + code_index = ::numeric_compaction(&codewords, code_index + 1, file_size); + result_metadata.set_file_size(&Long::parse_long(&file_size.to_string())); + break; + } + _ => + { + throw FormatException::get_format_instance(); + } + } + break; + } + MACRO_PDF417_TERMINATOR => + { + code_index += 1; + result_metadata.set_last_segment(true); + break; + } + _ => + { + throw FormatException::get_format_instance(); + } + } + } + // copy optional fields to additional options + if optional_fields_start != -1 { + let optional_fields_length: i32 = code_index - optional_fields_start; + if result_metadata.is_last_segment() { + // do not include terminator + optional_fields_length -= 1; + } + result_metadata.set_optional_data(&Arrays::copy_of_range(&codewords, optional_fields_start, optional_fields_start + optional_fields_length)); + } + return Ok(code_index); + } + + /** + * Text Compaction mode (see 5.4.1.5) permits all printable ASCII characters to be + * encoded, i.e. values 32 - 126 inclusive in accordance with ISO/IEC 646 (IRV), as + * well as selected control characters. + * + * @param codewords The array of codewords (data + error) + * @param codeIndex The current index into the codeword array. + * @param result The decoded data is appended to the result. + * @return The next index into the codeword array. + */ + fn text_compaction( codewords: &Vec, code_index: i32, result: &ECIStringBuilder) -> /* throws FormatException */Result> { + // 2 character per codeword + let text_compaction_data: [i32; (codewords[0] - code_index) * 2] = [0; (codewords[0] - code_index) * 2]; + // Used to hold the byte compaction value if there is a mode shift + let byte_compaction_data: [i32; (codewords[0] - code_index) * 2] = [0; (codewords[0] - code_index) * 2]; + let mut index: i32 = 0; + let mut end: bool = false; + let sub_mode: Mode = Mode::ALPHA; + while (code_index < codewords[0]) && !end { + let mut code: i32 = codewords[code_index += 1 !!!check!!! post increment]; + if code < TEXT_COMPACTION_MODE_LATCH { + text_compaction_data[index] = code / 30; + text_compaction_data[index + 1] = code % 30; + index += 2; + } else { + match code { + TEXT_COMPACTION_MODE_LATCH => + { + // reinitialize text compaction mode to alpha sub mode + text_compaction_data[index += 1 !!!check!!! post increment] = TEXT_COMPACTION_MODE_LATCH; + break; + } + BYTE_COMPACTION_MODE_LATCH => + { + } + BYTE_COMPACTION_MODE_LATCH_6 => + { + } + NUMERIC_COMPACTION_MODE_LATCH => + { + } + BEGIN_MACRO_PDF417_CONTROL_BLOCK => + { + } + BEGIN_MACRO_PDF417_OPTIONAL_FIELD => + { + } + MACRO_PDF417_TERMINATOR => + { + code_index -= 1; + end = true; + break; + } + MODE_SHIFT_TO_BYTE_COMPACTION_MODE => + { + // The Mode Shift codeword 913 shall cause a temporary + // switch from Text Compaction mode to Byte Compaction mode. + // This switch shall be in effect for only the next codeword, + // after which the mode shall revert to the prevailing sub-mode + // of the Text Compaction mode. Codeword 913 is only available + // in Text Compaction mode; its use is described in 5.4.2.4. + text_compaction_data[index] = MODE_SHIFT_TO_BYTE_COMPACTION_MODE; + code = codewords[code_index += 1 !!!check!!! post increment]; + byte_compaction_data[index] = code; + index += 1; + break; + } + ECI_CHARSET => + { + sub_mode = ::decode_text_compaction(&text_compaction_data, &byte_compaction_data, index, result, sub_mode); + result.append_e_c_i(codewords[code_index += 1 !!!check!!! post increment]); + text_compaction_data = : [i32; (codewords[0] - code_index) * 2] = [0; (codewords[0] - code_index) * 2]; + byte_compaction_data = : [i32; (codewords[0] - code_index) * 2] = [0; (codewords[0] - code_index) * 2]; + index = 0; + break; + } + } + } + } + ::decode_text_compaction(&text_compaction_data, &byte_compaction_data, index, result, sub_mode); + return Ok(code_index); + } + + /** + * The Text Compaction mode includes all the printable ASCII characters + * (i.e. values from 32 to 126) and three ASCII control characters: HT or tab + * (ASCII value 9), LF or line feed (ASCII value 10), and CR or carriage + * return (ASCII value 13). The Text Compaction mode also includes various latch + * and shift characters which are used exclusively within the mode. The Text + * Compaction mode encodes up to 2 characters per codeword. The compaction rules + * for converting data into PDF417 codewords are defined in 5.4.2.2. The sub-mode + * switches are defined in 5.4.2.3. + * + * @param textCompactionData The text compaction data. + * @param byteCompactionData The byte compaction data if there + * was a mode shift. + * @param length The size of the text compaction and byte compaction data. + * @param result The decoded data is appended to the result. + * @param startMode The mode in which decoding starts + * @return The mode in which decoding ended + */ + fn decode_text_compaction( text_compaction_data: &Vec, byte_compaction_data: &Vec, length: i32, result: &ECIStringBuilder, start_mode: &Mode) -> Mode { + // Beginning from an initial state + // The default compaction mode for PDF417 in effect at the start of each symbol shall always be Text + // Compaction mode Alpha sub-mode (uppercase alphabetic). A latch codeword from another mode to the Text + // Compaction mode shall always switch to the Text Compaction Alpha sub-mode. + let sub_mode: Mode = start_mode; + let prior_to_shift_mode: Mode = start_mode; + let latched_mode: Mode = start_mode; + let mut i: i32 = 0; + while i < length { + let sub_mode_ch: i32 = text_compaction_data[i]; + let mut ch: char = 0; + match sub_mode { + ALPHA => + { + // Alpha (uppercase alphabetic) + if sub_mode_ch < 26 { + // Upper case Alpha Character + ch = ('A' + sub_mode_ch) as char; + } else { + match sub_mode_ch { + 26 => + { + ch = ' '; + break; + } + LL => + { + sub_mode = Mode::LOWER; + latched_mode = sub_mode; + break; + } + ML => + { + sub_mode = Mode::MIXED; + latched_mode = sub_mode; + break; + } + PS => + { + // Shift to punctuation + prior_to_shift_mode = sub_mode; + sub_mode = Mode::PUNCT_SHIFT; + break; + } + MODE_SHIFT_TO_BYTE_COMPACTION_MODE => + { + result.append(byte_compaction_data[i] as char); + break; + } + TEXT_COMPACTION_MODE_LATCH => + { + sub_mode = Mode::ALPHA; + latched_mode = sub_mode; + break; + } + } + } + break; + } + LOWER => + { + // Lower (lowercase alphabetic) + if sub_mode_ch < 26 { + ch = ('a' + sub_mode_ch) as char; + } else { + match sub_mode_ch { + 26 => + { + ch = ' '; + break; + } + AS => + { + // Shift to alpha + prior_to_shift_mode = sub_mode; + sub_mode = Mode::ALPHA_SHIFT; + break; + } + ML => + { + sub_mode = Mode::MIXED; + latched_mode = sub_mode; + break; + } + PS => + { + // Shift to punctuation + prior_to_shift_mode = sub_mode; + sub_mode = Mode::PUNCT_SHIFT; + break; + } + MODE_SHIFT_TO_BYTE_COMPACTION_MODE => + { + result.append(byte_compaction_data[i] as char); + break; + } + TEXT_COMPACTION_MODE_LATCH => + { + sub_mode = Mode::ALPHA; + latched_mode = sub_mode; + break; + } + } + } + break; + } + MIXED => + { + // Mixed (numeric and some punctuation) + if sub_mode_ch < PL { + ch = MIXED_CHARS[sub_mode_ch]; + } else { + match sub_mode_ch { + PL => + { + sub_mode = Mode::PUNCT; + latched_mode = sub_mode; + break; + } + 26 => + { + ch = ' '; + break; + } + LL => + { + sub_mode = Mode::LOWER; + latched_mode = sub_mode; + break; + } + AL => + { + } + TEXT_COMPACTION_MODE_LATCH => + { + sub_mode = Mode::ALPHA; + latched_mode = sub_mode; + break; + } + PS => + { + // Shift to punctuation + prior_to_shift_mode = sub_mode; + sub_mode = Mode::PUNCT_SHIFT; + break; + } + MODE_SHIFT_TO_BYTE_COMPACTION_MODE => + { + result.append(byte_compaction_data[i] as char); + break; + } + } + } + break; + } + PUNCT => + { + // Punctuation + if sub_mode_ch < PAL { + ch = PUNCT_CHARS[sub_mode_ch]; + } else { + match sub_mode_ch { + PAL => + { + } + TEXT_COMPACTION_MODE_LATCH => + { + sub_mode = Mode::ALPHA; + latched_mode = sub_mode; + break; + } + MODE_SHIFT_TO_BYTE_COMPACTION_MODE => + { + result.append(byte_compaction_data[i] as char); + break; + } + } + } + break; + } + ALPHA_SHIFT => + { + // Restore sub-mode + sub_mode = prior_to_shift_mode; + if sub_mode_ch < 26 { + ch = ('A' + sub_mode_ch) as char; + } else { + match sub_mode_ch { + 26 => + { + ch = ' '; + break; + } + TEXT_COMPACTION_MODE_LATCH => + { + sub_mode = Mode::ALPHA; + break; + } + } + } + break; + } + PUNCT_SHIFT => + { + // Restore sub-mode + sub_mode = prior_to_shift_mode; + if sub_mode_ch < PAL { + ch = PUNCT_CHARS[sub_mode_ch]; + } else { + match sub_mode_ch { + PAL => + { + } + TEXT_COMPACTION_MODE_LATCH => + { + sub_mode = Mode::ALPHA; + break; + } + MODE_SHIFT_TO_BYTE_COMPACTION_MODE => + { + // PS before Shift-to-Byte is used as a padding character, + // see 5.4.2.4 of the specification + result.append(byte_compaction_data[i] as char); + break; + } + } + } + break; + } + } + if ch != 0 { + // Append decoded character to result + result.append(ch); + } + i += 1; + } + return latched_mode; + } + + /** + * Byte Compaction mode (see 5.4.3) permits all 256 possible 8-bit byte values to be encoded. + * This includes all ASCII characters value 0 to 127 inclusive and provides for international + * character set support. + * + * @param mode The byte compaction mode i.e. 901 or 924 + * @param codewords The array of codewords (data + error) + * @param codeIndex The current index into the codeword array. + * @param result The decoded data is appended to the result. + * @return The next index into the codeword array. + */ + fn byte_compaction( mode: i32, codewords: &Vec, code_index: i32, result: &ECIStringBuilder) -> /* throws FormatException */Result> { + let mut end: bool = false; + while code_index < codewords[0] && !end { + //handle leading ECIs + while code_index < codewords[0] && codewords[code_index] == ECI_CHARSET { + result.append_e_c_i(codewords[code_index += 1]); + code_index += 1; + } + if code_index >= codewords[0] || codewords[code_index] >= TEXT_COMPACTION_MODE_LATCH { + end = true; + } else { + //decode one block of 5 codewords to 6 bytes + let mut value: i64 = 0; + let mut count: i32 = 0; + loop { { + value = 900 * value + codewords[code_index += 1 !!!check!!! post increment]; + count += 1; + }if !(count < 5 && code_index < codewords[0] && codewords[code_index] < TEXT_COMPACTION_MODE_LATCH) break;} + if count == 5 && (mode == BYTE_COMPACTION_MODE_LATCH_6 || code_index < codewords[0] && codewords[code_index] < TEXT_COMPACTION_MODE_LATCH) { + { + let mut i: i32 = 0; + while i < 6 { + { + result.append((value >> (8 * (5 - i))) as i8); + } + i += 1; + } + } + + } else { + code_index -= count; + while (code_index < codewords[0]) && !end { + let code: i32 = codewords[code_index += 1 !!!check!!! post increment]; + if code < TEXT_COMPACTION_MODE_LATCH { + result.append(code as i8); + } else if code == ECI_CHARSET { + result.append_e_c_i(codewords[code_index += 1 !!!check!!! post increment]); + } else { + code_index -= 1; + end = true; + } + } + } + } + } + return Ok(code_index); + } + + /** + * Numeric Compaction mode (see 5.4.4) permits efficient encoding of numeric data strings. + * + * @param codewords The array of codewords (data + error) + * @param codeIndex The current index into the codeword array. + * @param result The decoded data is appended to the result. + * @return The next index into the codeword array. + */ + fn numeric_compaction( codewords: &Vec, code_index: i32, result: &ECIStringBuilder) -> /* throws FormatException */Result> { + let mut count: i32 = 0; + let mut end: bool = false; + let numeric_codewords: [i32; MAX_NUMERIC_CODEWORDS] = [0; MAX_NUMERIC_CODEWORDS]; + while code_index < codewords[0] && !end { + let code: i32 = codewords[code_index += 1 !!!check!!! post increment]; + if code_index == codewords[0] { + end = true; + } + if code < TEXT_COMPACTION_MODE_LATCH { + numeric_codewords[count] = code; + count += 1; + } else { + match code { + TEXT_COMPACTION_MODE_LATCH => + { + } + BYTE_COMPACTION_MODE_LATCH => + { + } + BYTE_COMPACTION_MODE_LATCH_6 => + { + } + BEGIN_MACRO_PDF417_CONTROL_BLOCK => + { + } + BEGIN_MACRO_PDF417_OPTIONAL_FIELD => + { + } + MACRO_PDF417_TERMINATOR => + { + } + ECI_CHARSET => + { + code_index -= 1; + end = true; + break; + } + } + } + if (count % MAX_NUMERIC_CODEWORDS == 0 || code == NUMERIC_COMPACTION_MODE_LATCH || end) && count > 0 { + // Re-invoking Numeric Compaction mode (by using codeword 902 + // while in Numeric Compaction mode) serves to terminate the + // current Numeric Compaction mode grouping as described in 5.4.4.2, + // and then to start a new one grouping. + result.append(&::decode_base900to_base10(&numeric_codewords, count)); + count = 0; + } + } + return Ok(code_index); + } + + /** + * Convert a list of Numeric Compacted codewords from Base 900 to Base 10. + * + * @param codewords The array of codewords + * @param count The number of codewords + * @return The decoded string representing the Numeric data. + */ + /* + EXAMPLE + Encode the fifteen digit numeric string 000213298174000 + Prefix the numeric string with a 1 and set the initial value of + t = 1 000 213 298 174 000 + Calculate codeword 0 + d0 = 1 000 213 298 174 000 mod 900 = 200 + + t = 1 000 213 298 174 000 div 900 = 1 111 348 109 082 + Calculate codeword 1 + d1 = 1 111 348 109 082 mod 900 = 282 + + t = 1 111 348 109 082 div 900 = 1 234 831 232 + Calculate codeword 2 + d2 = 1 234 831 232 mod 900 = 632 + + t = 1 234 831 232 div 900 = 1 372 034 + Calculate codeword 3 + d3 = 1 372 034 mod 900 = 434 + + t = 1 372 034 div 900 = 1 524 + Calculate codeword 4 + d4 = 1 524 mod 900 = 624 + + t = 1 524 div 900 = 1 + Calculate codeword 5 + d5 = 1 mod 900 = 1 + t = 1 div 900 = 0 + Codeword sequence is: 1, 624, 434, 632, 282, 200 + + Decode the above codewords involves + 1 x 900 power of 5 + 624 x 900 power of 4 + 434 x 900 power of 3 + + 632 x 900 power of 2 + 282 x 900 power of 1 + 200 x 900 power of 0 = 1000213298174000 + + Remove leading 1 => Result is 000213298174000 + */ + fn decode_base900to_base10( codewords: &Vec, count: i32) -> /* throws FormatException */Result> { + let mut result: BigInteger = BigInteger::ZERO; + { + let mut i: i32 = 0; + while i < count { + { + result = result.add(&EXP900[count - i - 1]::multiply(&BigInteger::value_of(codewords[i]))); + } + i += 1; + } + } + + let result_string: String = result.to_string(); + if result_string.char_at(0) != '1' { + throw FormatException::get_format_instance(); + } + return Ok(result_string.substring(1)); + } +} + +// NEW FILE: detection_result.rs +/* + * 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::pdf417::decoder; + +/** + * @author Guenther Grau + */ + + const ADJUST_ROW_NUMBER_SKIP: i32 = 2; +struct DetectionResult { + + let barcode_metadata: BarcodeMetadata; + + let detection_result_columns: Vec; + + let bounding_box: BoundingBox; + + let barcode_column_count: i32; +} + +impl DetectionResult { + + fn new( barcode_metadata: &BarcodeMetadata, bounding_box: &BoundingBox) -> DetectionResult { + let .barcodeMetadata = barcode_metadata; + let .barcodeColumnCount = barcode_metadata.get_column_count(); + let .boundingBox = bounding_box; + detection_result_columns = : [Option; barcode_column_count + 2] = [None; barcode_column_count + 2]; + } + + fn get_detection_result_columns(&self) -> Vec { + self.adjust_indicator_column_row_numbers(self.detection_result_columns[0]); + self.adjust_indicator_column_row_numbers(self.detection_result_columns[self.barcode_column_count + 1]); + let unadjusted_codeword_count: i32 = PDF417Common.MAX_CODEWORDS_IN_BARCODE; + let previous_unadjusted_count: i32; + loop { { + previous_unadjusted_count = unadjusted_codeword_count; + unadjusted_codeword_count = self.adjust_row_numbers(); + }if !(unadjusted_codeword_count > 0 && unadjusted_codeword_count < previous_unadjusted_count) break;} + return self.detection_result_columns; + } + + fn adjust_indicator_column_row_numbers(&self, detection_result_column: &DetectionResultColumn) { + if detection_result_column != null { + (detection_result_column as DetectionResultRowIndicatorColumn).adjust_complete_indicator_column_row_numbers(self.barcode_metadata); + } + } + + // TODO ensure that no detected codewords with unknown row number are left + // we should be able to estimate the row height and use it as a hint for the row number + // we should also fill the rows top to bottom and bottom to top + /** + * @return number of codewords which don't have a valid row number. Note that the count is not accurate as codewords + * will be counted several times. It just serves as an indicator to see when we can stop adjusting row numbers + */ + fn adjust_row_numbers(&self) -> i32 { + let unadjusted_count: i32 = self.adjust_row_numbers_by_row(); + if unadjusted_count == 0 { + return 0; + } + { + let barcode_column: i32 = 1; + while barcode_column < self.barcode_column_count + 1 { + { + let codewords: Vec = self.detection_result_columns[barcode_column].get_codewords(); + { + let codewords_row: i32 = 0; + while codewords_row < codewords.len() { + { + if codewords[codewords_row] == null { + continue; + } + if !codewords[codewords_row].has_valid_row_number() { + self.adjust_row_numbers(barcode_column, codewords_row, codewords); + } + } + codewords_row += 1; + } + } + + } + barcode_column += 1; + } + } + + return unadjusted_count; + } + + fn adjust_row_numbers_by_row(&self) -> i32 { + self.adjust_row_numbers_from_both_r_i(); + // TODO we should only do full row adjustments if row numbers of left and right row indicator column match. + // Maybe it's even better to calculated the height (in codeword rows) and divide it by the number of barcode + // rows. This, together with the LRI and RRI row numbers should allow us to get a good estimate where a row + // number starts and ends. + let unadjusted_count: i32 = self.adjust_row_numbers_from_l_r_i(); + return unadjusted_count + self.adjust_row_numbers_from_r_r_i(); + } + + fn adjust_row_numbers_from_both_r_i(&self) { + if self.detection_result_columns[0] == null || self.detection_result_columns[self.barcode_column_count + 1] == null { + return; + } + const LRIcodewords: Vec = self.detection_result_columns[0].get_codewords(); + const RRIcodewords: Vec = self.detection_result_columns[self.barcode_column_count + 1].get_codewords(); + { + let codewords_row: i32 = 0; + while codewords_row < LRIcodewords.len() { + { + if LRIcodewords[codewords_row] != null && RRIcodewords[codewords_row] != null && LRIcodewords[codewords_row]::get_row_number() == RRIcodewords[codewords_row]::get_row_number() { + { + let barcode_column: i32 = 1; + while barcode_column <= self.barcode_column_count { + { + let codeword: Codeword = self.detection_result_columns[barcode_column].get_codewords()[codewords_row]; + if codeword == null { + continue; + } + codeword.set_row_number(&LRIcodewords[codewords_row]::get_row_number()); + if !codeword.has_valid_row_number() { + self.detection_result_columns[barcode_column].get_codewords()[codewords_row] = null; + } + } + barcode_column += 1; + } + } + + } + } + codewords_row += 1; + } + } + + } + + fn adjust_row_numbers_from_r_r_i(&self) -> i32 { + if self.detection_result_columns[self.barcode_column_count + 1] == null { + return 0; + } + let unadjusted_count: i32 = 0; + let codewords: Vec = self.detection_result_columns[self.barcode_column_count + 1].get_codewords(); + { + let codewords_row: i32 = 0; + while codewords_row < codewords.len() { + { + if codewords[codewords_row] == null { + continue; + } + let row_indicator_row_number: i32 = codewords[codewords_row].get_row_number(); + let invalid_row_counts: i32 = 0; + { + let barcode_column: i32 = self.barcode_column_count + 1; + while barcode_column > 0 && invalid_row_counts < ADJUST_ROW_NUMBER_SKIP { + { + let codeword: Codeword = self.detection_result_columns[barcode_column].get_codewords()[codewords_row]; + if codeword != null { + invalid_row_counts = ::adjust_row_number_if_valid(row_indicator_row_number, invalid_row_counts, codeword); + if !codeword.has_valid_row_number() { + unadjusted_count += 1; + } + } + } + barcode_column -= 1; + } + } + + } + codewords_row += 1; + } + } + + return unadjusted_count; + } + + fn adjust_row_numbers_from_l_r_i(&self) -> i32 { + if self.detection_result_columns[0] == null { + return 0; + } + let unadjusted_count: i32 = 0; + let codewords: Vec = self.detection_result_columns[0].get_codewords(); + { + let codewords_row: i32 = 0; + while codewords_row < codewords.len() { + { + if codewords[codewords_row] == null { + continue; + } + let row_indicator_row_number: i32 = codewords[codewords_row].get_row_number(); + let invalid_row_counts: i32 = 0; + { + let barcode_column: i32 = 1; + while barcode_column < self.barcode_column_count + 1 && invalid_row_counts < ADJUST_ROW_NUMBER_SKIP { + { + let codeword: Codeword = self.detection_result_columns[barcode_column].get_codewords()[codewords_row]; + if codeword != null { + invalid_row_counts = ::adjust_row_number_if_valid(row_indicator_row_number, invalid_row_counts, codeword); + if !codeword.has_valid_row_number() { + unadjusted_count += 1; + } + } + } + barcode_column += 1; + } + } + + } + codewords_row += 1; + } + } + + return unadjusted_count; + } + + fn adjust_row_number_if_valid( row_indicator_row_number: i32, invalid_row_counts: i32, codeword: &Codeword) -> i32 { + if codeword == null { + return invalid_row_counts; + } + if !codeword.has_valid_row_number() { + if codeword.is_valid_row_number(row_indicator_row_number) { + codeword.set_row_number(row_indicator_row_number); + invalid_row_counts = 0; + } else { + invalid_row_counts += 1; + } + } + return invalid_row_counts; + } + + fn adjust_row_numbers(&self, barcode_column: i32, codewords_row: i32, codewords: &Vec) { + let codeword: Codeword = codewords[codewords_row]; + let previous_column_codewords: Vec = self.detection_result_columns[barcode_column - 1].get_codewords(); + let next_column_codewords: Vec = previous_column_codewords; + if self.detection_result_columns[barcode_column + 1] != null { + next_column_codewords = self.detection_result_columns[barcode_column + 1].get_codewords(); + } + let other_codewords: [Option; 14] = [None; 14]; + other_codewords[2] = previous_column_codewords[codewords_row]; + other_codewords[3] = next_column_codewords[codewords_row]; + if codewords_row > 0 { + other_codewords[0] = codewords[codewords_row - 1]; + other_codewords[4] = previous_column_codewords[codewords_row - 1]; + other_codewords[5] = next_column_codewords[codewords_row - 1]; + } + if codewords_row > 1 { + other_codewords[8] = codewords[codewords_row - 2]; + other_codewords[10] = previous_column_codewords[codewords_row - 2]; + other_codewords[11] = next_column_codewords[codewords_row - 2]; + } + if codewords_row < codewords.len() - 1 { + other_codewords[1] = codewords[codewords_row + 1]; + other_codewords[6] = previous_column_codewords[codewords_row + 1]; + other_codewords[7] = next_column_codewords[codewords_row + 1]; + } + if codewords_row < codewords.len() - 2 { + other_codewords[9] = codewords[codewords_row + 2]; + other_codewords[12] = previous_column_codewords[codewords_row + 2]; + other_codewords[13] = next_column_codewords[codewords_row + 2]; + } + for let other_codeword: Codeword in other_codewords { + if ::adjust_row_number(codeword, other_codeword) { + return; + } + } + } + + /** + * @return true, if row number was adjusted, false otherwise + */ + fn adjust_row_number( codeword: &Codeword, other_codeword: &Codeword) -> bool { + if other_codeword == null { + return false; + } + if other_codeword.has_valid_row_number() && other_codeword.get_bucket() == codeword.get_bucket() { + codeword.set_row_number(&other_codeword.get_row_number()); + return true; + } + return false; + } + + fn get_barcode_column_count(&self) -> i32 { + return self.barcode_column_count; + } + + fn get_barcode_row_count(&self) -> i32 { + return self.barcode_metadata.get_row_count(); + } + + fn get_barcode_e_c_level(&self) -> i32 { + return self.barcode_metadata.get_error_correction_level(); + } + + fn set_bounding_box(&self, bounding_box: &BoundingBox) { + self.boundingBox = bounding_box; + } + + fn get_bounding_box(&self) -> BoundingBox { + return self.bounding_box; + } + + fn set_detection_result_column(&self, barcode_column: i32, detection_result_column: &DetectionResultColumn) { + self.detection_result_columns[barcode_column] = detection_result_column; + } + + fn get_detection_result_column(&self, barcode_column: i32) -> DetectionResultColumn { + return self.detection_result_columns[barcode_column]; + } + + pub fn to_string(&self) -> String { + let row_indicator_column: DetectionResultColumn = self.detection_result_columns[0]; + if row_indicator_column == null { + row_indicator_column = self.detection_result_columns[self.barcode_column_count + 1]; + } + let tryResult1 = 0; + 'try1: loop { + ( let formatter: Formatter = Formatter::new()) { + { + let codewords_row: i32 = 0; + while codewords_row < row_indicator_column.get_codewords().len() { + { + formatter.format("CW %3d:", codewords_row); + { + let barcode_column: i32 = 0; + while barcode_column < self.barcode_column_count + 2 { + { + if self.detection_result_columns[barcode_column] == null { + formatter.format(" | "); + continue; + } + let codeword: Codeword = self.detection_result_columns[barcode_column].get_codewords()[codewords_row]; + if codeword == null { + formatter.format(" | "); + continue; + } + formatter.format(" %3d|%3d", &codeword.get_row_number(), &codeword.get_value()); + } + barcode_column += 1; + } + } + + formatter.format("%n"); + } + codewords_row += 1; + } + } + + return formatter.to_string(); + } + break 'try1 + } + match tryResult1 { + 0 => break + } + + } +} + +// NEW FILE: detection_result_column.rs +/* + * 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::pdf417::decoder; + +/** + * @author Guenther Grau + */ + + const MAX_NEARBY_DISTANCE: i32 = 5; +struct DetectionResultColumn { + + let bounding_box: BoundingBox; + + let mut codewords: Vec; +} + +impl DetectionResultColumn { + + fn new( bounding_box: &BoundingBox) -> DetectionResultColumn { + let .boundingBox = BoundingBox::new(bounding_box); + codewords = : [Option; bounding_box.get_max_y() - bounding_box.get_min_y() + 1] = [None; bounding_box.get_max_y() - bounding_box.get_min_y() + 1]; + } + + fn get_codeword_nearby(&self, image_row: i32) -> Codeword { + let mut codeword: Codeword = self.get_codeword(image_row); + if codeword != null { + return codeword; + } + { + let mut i: i32 = 1; + while i < MAX_NEARBY_DISTANCE { + { + let near_image_row: i32 = self.image_row_to_codeword_index(image_row) - i; + if near_image_row >= 0 { + codeword = self.codewords[near_image_row]; + if codeword != null { + return codeword; + } + } + near_image_row = self.image_row_to_codeword_index(image_row) + i; + if near_image_row < self.codewords.len() { + codeword = self.codewords[near_image_row]; + if codeword != null { + return codeword; + } + } + } + i += 1; + } + } + + return null; + } + + fn image_row_to_codeword_index(&self, image_row: i32) -> i32 { + return image_row - self.bounding_box.get_min_y(); + } + + fn set_codeword(&self, image_row: i32, codeword: &Codeword) { + self.codewords[self.image_row_to_codeword_index(image_row)] = codeword; + } + + fn get_codeword(&self, image_row: i32) -> Codeword { + return self.codewords[self.image_row_to_codeword_index(image_row)]; + } + + fn get_bounding_box(&self) -> BoundingBox { + return self.bounding_box; + } + + fn get_codewords(&self) -> Vec { + return self.codewords; + } + + pub fn to_string(&self) -> String { + let tryResult1 = 0; + 'try1: loop { + ( let formatter: Formatter = Formatter::new()) { + let mut row: i32 = 0; + for let codeword: Codeword in self.codewords { + if codeword == null { + formatter.format("%3d: | %n", row += 1 !!!check!!! post increment); + continue; + } + formatter.format("%3d: %3d|%3d%n", row += 1 !!!check!!! post increment, &codeword.get_row_number(), &codeword.get_value()); + } + return formatter.to_string(); + } + break 'try1 + } + match tryResult1 { + 0 => break + } + + } +} + +// NEW FILE: detection_result_row_indicator_column.rs +/* + * 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::pdf417::decoder; + +/** + * @author Guenther Grau + */ +struct DetectionResultRowIndicatorColumn { + super: DetectionResultColumn; + + let is_left: bool; +} + +impl DetectionResultRowIndicatorColumn { + + fn new( bounding_box: &BoundingBox, is_left: bool) -> DetectionResultRowIndicatorColumn { + super(bounding_box); + let .isLeft = is_left; + } + + fn set_row_numbers(&self) { + for let codeword: Codeword in get_codewords() { + if codeword != null { + codeword.set_row_number_as_row_indicator_column(); + } + } + } + + // TODO implement properly + // TODO maybe we should add missing codewords to store the correct row number to make + // finding row numbers for other columns easier + // use row height count to make detection of invalid row numbers more reliable + fn adjust_complete_indicator_column_row_numbers(&self, barcode_metadata: &BarcodeMetadata) { + let mut codewords: Vec = get_codewords(); + self.set_row_numbers(); + self.remove_incorrect_codewords(codewords, barcode_metadata); + let bounding_box: BoundingBox = get_bounding_box(); + let top: ResultPoint = if self.is_left { bounding_box.get_top_left() } else { bounding_box.get_top_right() }; + let bottom: ResultPoint = if self.is_left { bounding_box.get_bottom_left() } else { bounding_box.get_bottom_right() }; + let first_row: i32 = image_row_to_codeword_index(top.get_y() as i32); + let last_row: i32 = image_row_to_codeword_index(bottom.get_y() as i32); + // We need to be careful using the average row height. Barcode could be skewed so that we have smaller and + // taller rows + //float averageRowHeight = (lastRow - firstRow) / (float) barcodeMetadata.getRowCount(); + let barcode_row: i32 = -1; + let max_row_height: i32 = 1; + let current_row_height: i32 = 0; + { + let codewords_row: i32 = first_row; + while codewords_row < last_row { + { + if codewords[codewords_row] == null { + continue; + } + let codeword: Codeword = codewords[codewords_row]; + let row_difference: i32 = codeword.get_row_number() - barcode_row; + if row_difference == 0 { + current_row_height += 1; + } else if row_difference == 1 { + max_row_height = Math::max(max_row_height, current_row_height); + current_row_height = 1; + barcode_row = codeword.get_row_number(); + } else if row_difference < 0 || codeword.get_row_number() >= barcode_metadata.get_row_count() || row_difference > codewords_row { + codewords[codewords_row] = null; + } else { + let checked_rows: i32; + if max_row_height > 2 { + checked_rows = (max_row_height - 2) * row_difference; + } else { + checked_rows = row_difference; + } + let close_previous_codeword_found: bool = checked_rows >= codewords_row; + { + let mut i: i32 = 1; + while i <= checked_rows && !close_previous_codeword_found { + { + // there must be (height * rowDifference) number of codewords missing. For now we assume height = 1. + // This should hopefully get rid of most problems already. + close_previous_codeword_found = codewords[codewords_row - i] != null; + } + i += 1; + } + } + + if close_previous_codeword_found { + codewords[codewords_row] = null; + } else { + barcode_row = codeword.get_row_number(); + current_row_height = 1; + } + } + } + codewords_row += 1; + } + } + + //return (int) (averageRowHeight + 0.5); + } + + fn get_row_heights(&self) -> Vec { + let barcode_metadata: BarcodeMetadata = self.get_barcode_metadata(); + if barcode_metadata == null { + return null; + } + self.adjust_incomplete_indicator_column_row_numbers(barcode_metadata); + let mut result: [i32; barcode_metadata.get_row_count()] = [0; barcode_metadata.get_row_count()]; + for let codeword: Codeword in get_codewords() { + if codeword != null { + let row_number: i32 = codeword.get_row_number(); + if row_number >= result.len() { + // We have more rows than the barcode metadata allows for, ignore them. + continue; + } + result[row_number] += 1; + } + // else throw exception? + } + return result; + } + + // TODO maybe we should add missing codewords to store the correct row number to make + // finding row numbers for other columns easier + // use row height count to make detection of invalid row numbers more reliable + fn adjust_incomplete_indicator_column_row_numbers(&self, barcode_metadata: &BarcodeMetadata) { + let bounding_box: BoundingBox = get_bounding_box(); + let top: ResultPoint = if self.is_left { bounding_box.get_top_left() } else { bounding_box.get_top_right() }; + let bottom: ResultPoint = if self.is_left { bounding_box.get_bottom_left() } else { bounding_box.get_bottom_right() }; + let first_row: i32 = image_row_to_codeword_index(top.get_y() as i32); + let last_row: i32 = image_row_to_codeword_index(bottom.get_y() as i32); + //float averageRowHeight = (lastRow - firstRow) / (float) barcodeMetadata.getRowCount(); + let mut codewords: Vec = get_codewords(); + let barcode_row: i32 = -1; + let max_row_height: i32 = 1; + let current_row_height: i32 = 0; + { + let codewords_row: i32 = first_row; + while codewords_row < last_row { + { + if codewords[codewords_row] == null { + continue; + } + let codeword: Codeword = codewords[codewords_row]; + codeword.set_row_number_as_row_indicator_column(); + let row_difference: i32 = codeword.get_row_number() - barcode_row; + if row_difference == 0 { + current_row_height += 1; + } else if row_difference == 1 { + max_row_height = Math::max(max_row_height, current_row_height); + current_row_height = 1; + barcode_row = codeword.get_row_number(); + } else if codeword.get_row_number() >= barcode_metadata.get_row_count() { + codewords[codewords_row] = null; + } else { + barcode_row = codeword.get_row_number(); + current_row_height = 1; + } + } + codewords_row += 1; + } + } + + //return (int) (averageRowHeight + 0.5); + } + + fn get_barcode_metadata(&self) -> BarcodeMetadata { + let codewords: Vec = get_codewords(); + let barcode_column_count: BarcodeValue = BarcodeValue::new(); + let barcode_row_count_upper_part: BarcodeValue = BarcodeValue::new(); + let barcode_row_count_lower_part: BarcodeValue = BarcodeValue::new(); + let barcode_e_c_level: BarcodeValue = BarcodeValue::new(); + for let codeword: Codeword in codewords { + if codeword == null { + continue; + } + codeword.set_row_number_as_row_indicator_column(); + let row_indicator_value: i32 = codeword.get_value() % 30; + let codeword_row_number: i32 = codeword.get_row_number(); + if !self.is_left { + codeword_row_number += 2; + } + match codeword_row_number % 3 { + 0 => + { + barcode_row_count_upper_part.set_value(row_indicator_value * 3 + 1); + break; + } + 1 => + { + barcode_e_c_level.set_value(row_indicator_value / 3); + barcode_row_count_lower_part.set_value(row_indicator_value % 3); + break; + } + 2 => + { + barcode_column_count.set_value(row_indicator_value + 1); + break; + } + } + } + // Maybe we should check if we have ambiguous values? + if (barcode_column_count.get_value().len() == 0) || (barcode_row_count_upper_part.get_value().len() == 0) || (barcode_row_count_lower_part.get_value().len() == 0) || (barcode_e_c_level.get_value().len() == 0) || barcode_column_count.get_value()[0] < 1 || barcode_row_count_upper_part.get_value()[0] + barcode_row_count_lower_part.get_value()[0] < PDF417Common.MIN_ROWS_IN_BARCODE || barcode_row_count_upper_part.get_value()[0] + barcode_row_count_lower_part.get_value()[0] > PDF417Common.MAX_ROWS_IN_BARCODE { + return null; + } + let barcode_metadata: BarcodeMetadata = BarcodeMetadata::new(barcode_column_count.get_value()[0], barcode_row_count_upper_part.get_value()[0], barcode_row_count_lower_part.get_value()[0], barcode_e_c_level.get_value()[0]); + self.remove_incorrect_codewords(codewords, barcode_metadata); + return barcode_metadata; + } + + fn remove_incorrect_codewords(&self, codewords: &Vec, barcode_metadata: &BarcodeMetadata) { + // TODO Maybe we should keep the incorrect codewords for the start and end positions? + { + let codeword_row: i32 = 0; + while codeword_row < codewords.len() { + { + let codeword: Codeword = codewords[codeword_row]; + if codewords[codeword_row] == null { + continue; + } + let row_indicator_value: i32 = codeword.get_value() % 30; + let codeword_row_number: i32 = codeword.get_row_number(); + if codeword_row_number > barcode_metadata.get_row_count() { + codewords[codeword_row] = null; + continue; + } + if !self.is_left { + codeword_row_number += 2; + } + match codeword_row_number % 3 { + 0 => + { + if row_indicator_value * 3 + 1 != barcode_metadata.get_row_count_upper_part() { + codewords[codeword_row] = null; + } + break; + } + 1 => + { + if row_indicator_value / 3 != barcode_metadata.get_error_correction_level() || row_indicator_value % 3 != barcode_metadata.get_row_count_lower_part() { + codewords[codeword_row] = null; + } + break; + } + 2 => + { + if row_indicator_value + 1 != barcode_metadata.get_column_count() { + codewords[codeword_row] = null; + } + break; + } + } + } + codeword_row += 1; + } + } + + } + + fn is_left(&self) -> bool { + return self.is_left; + } + + pub fn to_string(&self) -> String { + return format!("IsLeft: {}\n{}", self.is_left, super.to_string()); + } +} + +// NEW FILE: p_d_f417_codeword_decoder.rs +/* + * 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::pdf417::decoder; + +/** + * @author Guenther Grau + * @author creatale GmbH (christoph.schulz@creatale.de) + */ + + const RATIOS_TABLE: [[f32; PDF417Common.BARS_IN_MODULE]; PDF417Common.SYMBOL_TABLE.len()] = [[0.0; PDF417Common.BARS_IN_MODULE]; PDF417Common.SYMBOL_TABLE.len()]; +struct PDF417CodewordDecoder { +} + +impl PDF417CodewordDecoder { + + static { + // Pre-computes the symbol ratio table. + { + let mut i: i32 = 0; + while i < PDF417Common.SYMBOL_TABLE.len() { + { + let current_symbol: i32 = PDF417Common.SYMBOL_TABLE[i]; + let current_bit: i32 = current_symbol & 0x1; + { + let mut j: i32 = 0; + while j < PDF417Common.BARS_IN_MODULE { + { + let mut size: f32 = 0.0f; + while (current_symbol & 0x1) == current_bit { + size += 1.0f; + current_symbol >>= 1; + } + current_bit = current_symbol & 0x1; + RATIOS_TABLE[i][PDF417Common.BARS_IN_MODULE - j - 1] = size / PDF417Common.MODULES_IN_CODEWORD; + } + j += 1; + } + } + + } + i += 1; + } + } + + } + + fn new() -> PDF417CodewordDecoder { + } + + fn get_decoded_value( module_bit_count: &Vec) -> i32 { + let decoded_value: i32 = ::get_decoded_codeword_value(&::sample_bit_counts(&module_bit_count)); + if decoded_value != -1 { + return decoded_value; + } + return ::get_closest_decoded_value(&module_bit_count); + } + + fn sample_bit_counts( module_bit_count: &Vec) -> Vec { + let bit_count_sum: f32 = MathUtils::sum(&module_bit_count); + let mut result: [i32; PDF417Common.BARS_IN_MODULE] = [0; PDF417Common.BARS_IN_MODULE]; + let bit_count_index: i32 = 0; + let sum_previous_bits: i32 = 0; + { + let mut i: i32 = 0; + while i < PDF417Common.MODULES_IN_CODEWORD { + { + let sample_index: f32 = bit_count_sum / (2.0 * PDF417Common.MODULES_IN_CODEWORD) + (i * bit_count_sum) / PDF417Common.MODULES_IN_CODEWORD; + if sum_previous_bits + module_bit_count[bit_count_index] <= sample_index { + sum_previous_bits += module_bit_count[bit_count_index]; + bit_count_index += 1; + } + result[bit_count_index] += 1; + } + i += 1; + } + } + + return result; + } + + fn get_decoded_codeword_value( module_bit_count: &Vec) -> i32 { + let decoded_value: i32 = ::get_bit_value(&module_bit_count); + return if PDF417Common::get_codeword(decoded_value) == -1 { -1 } else { decoded_value }; + } + + fn get_bit_value( module_bit_count: &Vec) -> i32 { + let mut result: i64 = 0; + { + let mut i: i32 = 0; + while i < module_bit_count.len() { + { + { + let mut bit: i32 = 0; + while bit < module_bit_count[i] { + { + result = (result << 1) | ( if i % 2 == 0 { 1 } else { 0 }); + } + bit += 1; + } + } + + } + i += 1; + } + } + + return result as i32; + } + + fn get_closest_decoded_value( module_bit_count: &Vec) -> i32 { + let bit_count_sum: i32 = MathUtils::sum(&module_bit_count); + let bit_count_ratios: [f32; PDF417Common.BARS_IN_MODULE] = [0.0; PDF417Common.BARS_IN_MODULE]; + if bit_count_sum > 1 { + { + let mut i: i32 = 0; + while i < bit_count_ratios.len() { + { + bit_count_ratios[i] = module_bit_count[i] / bit_count_sum as f32; + } + i += 1; + } + } + + } + let best_match_error: f32 = Float::MAX_VALUE; + let best_match: i32 = -1; + { + let mut j: i32 = 0; + while j < RATIOS_TABLE.len() { + { + let mut error: f32 = 0.0f; + let ratio_table_row: Vec = RATIOS_TABLE[j]; + { + let mut k: i32 = 0; + while k < PDF417Common.BARS_IN_MODULE { + { + let diff: f32 = ratio_table_row[k] - bit_count_ratios[k]; + error += diff * diff; + if error >= best_match_error { + break; + } + } + k += 1; + } + } + + if error < best_match_error { + best_match_error = error; + best_match = PDF417Common.SYMBOL_TABLE[j]; + } + } + j += 1; + } + } + + return best_match; + } +} + +// NEW FILE: p_d_f417_scanning_decoder.rs +/* + * 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::pdf417::decoder; + +/** + * @author Guenther Grau + */ + + const CODEWORD_SKEW_SIZE: i32 = 2; + + const MAX_ERRORS: i32 = 3; + + const MAX_EC_CODEWORDS: i32 = 512; + + let error_correction: ErrorCorrection = ErrorCorrection::new(); +pub struct PDF417ScanningDecoder { +} + +impl PDF417ScanningDecoder { + + fn new() -> PDF417ScanningDecoder { + } + + // TODO don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern + // columns. That way width can be deducted from the pattern column. + // This approach also allows to detect more details about the barcode, e.g. if a bar type (white or black) is wider + // than it should be. This can happen if the scanner used a bad blackpoint. + pub fn decode( image: &BitMatrix, image_top_left: &ResultPoint, image_bottom_left: &ResultPoint, image_top_right: &ResultPoint, image_bottom_right: &ResultPoint, min_codeword_width: i32, max_codeword_width: i32) -> /* throws NotFoundException, FormatException, ChecksumException */Result> { + let bounding_box: BoundingBox = BoundingBox::new(image, image_top_left, image_bottom_left, image_top_right, image_bottom_right); + let left_row_indicator_column: DetectionResultRowIndicatorColumn = null; + let right_row_indicator_column: DetectionResultRowIndicatorColumn = null; + let detection_result: DetectionResult; + { + let first_pass: bool = true; + loop { + { + if image_top_left != null { + left_row_indicator_column = ::get_row_indicator_column(image, bounding_box, image_top_left, true, min_codeword_width, max_codeword_width); + } + if image_top_right != null { + right_row_indicator_column = ::get_row_indicator_column(image, bounding_box, image_top_right, false, min_codeword_width, max_codeword_width); + } + detection_result = ::merge(left_row_indicator_column, right_row_indicator_column); + if detection_result == null { + throw NotFoundException::get_not_found_instance(); + } + let result_box: BoundingBox = detection_result.get_bounding_box(); + if first_pass && result_box != null && (result_box.get_min_y() < bounding_box.get_min_y() || result_box.get_max_y() > bounding_box.get_max_y()) { + bounding_box = result_box; + } else { + break; + } + } + first_pass = false; + } + } + + detection_result.set_bounding_box(bounding_box); + let max_barcode_column: i32 = detection_result.get_barcode_column_count() + 1; + detection_result.set_detection_result_column(0, left_row_indicator_column); + detection_result.set_detection_result_column(max_barcode_column, right_row_indicator_column); + let left_to_right: bool = left_row_indicator_column != null; + { + let barcode_column_count: i32 = 1; + while barcode_column_count <= max_barcode_column { + { + let barcode_column: i32 = if left_to_right { barcode_column_count } else { max_barcode_column - barcode_column_count }; + if detection_result.get_detection_result_column(barcode_column) != null { + // This will be the case for the opposite row indicator column, which doesn't need to be decoded again. + continue; + } + let detection_result_column: DetectionResultColumn; + if barcode_column == 0 || barcode_column == max_barcode_column { + detection_result_column = DetectionResultRowIndicatorColumn::new(bounding_box, barcode_column == 0); + } else { + detection_result_column = DetectionResultColumn::new(bounding_box); + } + detection_result.set_detection_result_column(barcode_column, detection_result_column); + let start_column: i32 = -1; + let previous_start_column: i32 = start_column; + // TODO start at a row for which we know the start position, then detect upwards and downwards from there. + { + let image_row: i32 = bounding_box.get_min_y(); + while image_row <= bounding_box.get_max_y() { + { + start_column = ::get_start_column(detection_result, barcode_column, image_row, left_to_right); + if start_column < 0 || start_column > bounding_box.get_max_x() { + if previous_start_column == -1 { + continue; + } + start_column = previous_start_column; + } + let codeword: Codeword = ::detect_codeword(image, &bounding_box.get_min_x(), &bounding_box.get_max_x(), left_to_right, start_column, image_row, min_codeword_width, max_codeword_width); + if codeword != null { + detection_result_column.set_codeword(image_row, codeword); + previous_start_column = start_column; + min_codeword_width = Math::min(min_codeword_width, &codeword.get_width()); + max_codeword_width = Math::max(max_codeword_width, &codeword.get_width()); + } + } + image_row += 1; + } + } + + } + barcode_column_count += 1; + } + } + + return Ok(::create_decoder_result(detection_result)); + } + + fn merge( left_row_indicator_column: &DetectionResultRowIndicatorColumn, right_row_indicator_column: &DetectionResultRowIndicatorColumn) -> /* throws NotFoundException */Result> { + if left_row_indicator_column == null && right_row_indicator_column == null { + return Ok(null); + } + let barcode_metadata: BarcodeMetadata = ::get_barcode_metadata(left_row_indicator_column, right_row_indicator_column); + if barcode_metadata == null { + return Ok(null); + } + let bounding_box: BoundingBox = BoundingBox::merge(&::adjust_bounding_box(left_row_indicator_column), &::adjust_bounding_box(right_row_indicator_column)); + return Ok(DetectionResult::new(barcode_metadata, bounding_box)); + } + + fn adjust_bounding_box( row_indicator_column: &DetectionResultRowIndicatorColumn) -> /* throws NotFoundException */Result> { + if row_indicator_column == null { + return Ok(null); + } + let row_heights: Vec = row_indicator_column.get_row_heights(); + if row_heights == null { + return Ok(null); + } + let max_row_height: i32 = ::get_max(&row_heights); + let missing_start_rows: i32 = 0; + for let row_height: i32 in row_heights { + missing_start_rows += max_row_height - row_height; + if row_height > 0 { + break; + } + } + let codewords: Vec = row_indicator_column.get_codewords(); + { + let mut row: i32 = 0; + while missing_start_rows > 0 && codewords[row] == null { + { + missing_start_rows -= 1; + } + row += 1; + } + } + + let missing_end_rows: i32 = 0; + { + let mut row: i32 = row_heights.len() - 1; + while row >= 0 { + { + missing_end_rows += max_row_height - row_heights[row]; + if row_heights[row] > 0 { + break; + } + } + row -= 1; + } + } + + { + let mut row: i32 = codewords.len() - 1; + while missing_end_rows > 0 && codewords[row] == null { + { + missing_end_rows -= 1; + } + row -= 1; + } + } + + return Ok(row_indicator_column.get_bounding_box().add_missing_rows(missing_start_rows, missing_end_rows, &row_indicator_column.is_left())); + } + + fn get_max( values: &Vec) -> i32 { + let max_value: i32 = -1; + for let value: i32 in values { + max_value = Math::max(max_value, value); + } + return max_value; + } + + fn get_barcode_metadata( left_row_indicator_column: &DetectionResultRowIndicatorColumn, right_row_indicator_column: &DetectionResultRowIndicatorColumn) -> BarcodeMetadata { + let left_barcode_metadata: BarcodeMetadata; + if left_row_indicator_column == null || (left_barcode_metadata = left_row_indicator_column.get_barcode_metadata()) == null { + return if right_row_indicator_column == null { null } else { right_row_indicator_column.get_barcode_metadata() }; + } + let right_barcode_metadata: BarcodeMetadata; + if right_row_indicator_column == null || (right_barcode_metadata = right_row_indicator_column.get_barcode_metadata()) == null { + return left_barcode_metadata; + } + if left_barcode_metadata.get_column_count() != right_barcode_metadata.get_column_count() && left_barcode_metadata.get_error_correction_level() != right_barcode_metadata.get_error_correction_level() && left_barcode_metadata.get_row_count() != right_barcode_metadata.get_row_count() { + return null; + } + return left_barcode_metadata; + } + + fn get_row_indicator_column( image: &BitMatrix, bounding_box: &BoundingBox, start_point: &ResultPoint, left_to_right: bool, min_codeword_width: i32, max_codeword_width: i32) -> DetectionResultRowIndicatorColumn { + let row_indicator_column: DetectionResultRowIndicatorColumn = DetectionResultRowIndicatorColumn::new(bounding_box, left_to_right); + { + let mut i: i32 = 0; + while i < 2 { + { + let increment: i32 = if i == 0 { 1 } else { -1 }; + let start_column: i32 = start_point.get_x() as i32; + { + let image_row: i32 = start_point.get_y() as i32; + while image_row <= bounding_box.get_max_y() && image_row >= bounding_box.get_min_y() { + { + let codeword: Codeword = ::detect_codeword(image, 0, &image.get_width(), left_to_right, start_column, image_row, min_codeword_width, max_codeword_width); + if codeword != null { + row_indicator_column.set_codeword(image_row, codeword); + if left_to_right { + start_column = codeword.get_start_x(); + } else { + start_column = codeword.get_end_x(); + } + } + } + image_row += increment; + } + } + + } + i += 1; + } + } + + return row_indicator_column; + } + + fn adjust_codeword_count( detection_result: &DetectionResult, barcode_matrix: &Vec>) -> /* throws NotFoundException */Result> { + let barcode_matrix01: BarcodeValue = barcode_matrix[0][1]; + let number_of_codewords: Vec = barcode_matrix01.get_value(); + let calculated_number_of_codewords: i32 = detection_result.get_barcode_column_count() * detection_result.get_barcode_row_count() - ::get_number_of_e_c_code_words(&detection_result.get_barcode_e_c_level()); + if number_of_codewords.len() == 0 { + if calculated_number_of_codewords < 1 || calculated_number_of_codewords > PDF417Common.MAX_CODEWORDS_IN_BARCODE { + throw NotFoundException::get_not_found_instance(); + } + barcode_matrix01.set_value(calculated_number_of_codewords); + } else if number_of_codewords[0] != calculated_number_of_codewords { + if calculated_number_of_codewords >= 1 && calculated_number_of_codewords <= PDF417Common.MAX_CODEWORDS_IN_BARCODE { + // The calculated one is more reliable as it is derived from the row indicator columns + barcode_matrix01.set_value(calculated_number_of_codewords); + } + } + } + + fn create_decoder_result( detection_result: &DetectionResult) -> /* throws FormatException, ChecksumException, NotFoundException */Result> { + let barcode_matrix: Vec> = ::create_barcode_matrix(detection_result); + ::adjust_codeword_count(detection_result, barcode_matrix); + let erasures: Collection = ArrayList<>::new(); + let mut codewords: [i32; detection_result.get_barcode_row_count() * detection_result.get_barcode_column_count()] = [0; detection_result.get_barcode_row_count() * detection_result.get_barcode_column_count()]; + let ambiguous_index_values_list: List> = ArrayList<>::new(); + let ambiguous_indexes_list: Collection = ArrayList<>::new(); + { + let mut row: i32 = 0; + while row < detection_result.get_barcode_row_count() { + { + { + let mut column: i32 = 0; + while column < detection_result.get_barcode_column_count() { + { + let values: Vec = barcode_matrix[row][column + 1].get_value(); + let codeword_index: i32 = row * detection_result.get_barcode_column_count() + column; + if values.len() == 0 { + erasures.add(codeword_index); + } else if values.len() == 1 { + codewords[codeword_index] = values[0]; + } else { + ambiguous_indexes_list.add(codeword_index); + ambiguous_index_values_list.add(&values); + } + } + column += 1; + } + } + + } + row += 1; + } + } + + let ambiguous_index_values: [i32; ambiguous_index_values_list.size()] = [0; ambiguous_index_values_list.size()]; + { + let mut i: i32 = 0; + while i < ambiguous_index_values.len() { + { + ambiguous_index_values[i] = ambiguous_index_values_list.get(i); + } + i += 1; + } + } + + return Ok(::create_decoder_result_from_ambiguous_values(&detection_result.get_barcode_e_c_level(), &codewords, &PDF417Common::to_int_array(&erasures), &PDF417Common::to_int_array(&ambiguous_indexes_list), &ambiguous_index_values)); + } + + /** + * This method deals with the fact, that the decoding process doesn't always yield a single most likely value. The + * current error correction implementation doesn't deal with erasures very well, so it's better to provide a value + * for these ambiguous codewords instead of treating it as an erasure. The problem is that we don't know which of + * the ambiguous values to choose. We try decode using the first value, and if that fails, we use another of the + * ambiguous values and try to decode again. This usually only happens on very hard to read and decode barcodes, + * so decoding the normal barcodes is not affected by this. + * + * @param erasureArray contains the indexes of erasures + * @param ambiguousIndexes array with the indexes that have more than one most likely value + * @param ambiguousIndexValues two dimensional array that contains the ambiguous values. The first dimension must + * be the same length as the ambiguousIndexes array + */ + fn create_decoder_result_from_ambiguous_values( ec_level: i32, codewords: &Vec, erasure_array: &Vec, ambiguous_indexes: &Vec, ambiguous_index_values: &Vec>) -> /* throws FormatException, ChecksumException */Result> { + let ambiguous_index_count: [i32; ambiguous_indexes.len()] = [0; ambiguous_indexes.len()]; + let mut tries: i32 = 100; + while tries -= 1 !!!check!!! post decrement > 0 { + { + let mut i: i32 = 0; + while i < ambiguous_index_count.len() { + { + codewords[ambiguous_indexes[i]] = ambiguous_index_values[i][ambiguous_index_count[i]]; + } + i += 1; + } + } + + let tryResult1 = 0; + 'try1: loop { + { + return Ok(::decode_codewords(&codewords, ec_level, &erasure_array)); + } + break 'try1 + } + match tryResult1 { + catch ( ignored: &ChecksumException) { + } 0 => break + } + + if ambiguous_index_count.len() == 0 { + throw ChecksumException::get_checksum_instance(); + } + { + let mut i: i32 = 0; + while i < ambiguous_index_count.len() { + { + if ambiguous_index_count[i] < ambiguous_index_values[i].len() - 1 { + ambiguous_index_count[i] += 1; + break; + } else { + ambiguous_index_count[i] = 0; + if i == ambiguous_index_count.len() - 1 { + throw ChecksumException::get_checksum_instance(); + } + } + } + i += 1; + } + } + + } + throw ChecksumException::get_checksum_instance(); + } + + fn create_barcode_matrix( detection_result: &DetectionResult) -> Vec> { + let barcode_matrix: [[Option; detection_result.get_barcode_column_count() + 2]; detection_result.get_barcode_row_count()] = [[None; detection_result.get_barcode_column_count() + 2]; detection_result.get_barcode_row_count()]; + { + let mut row: i32 = 0; + while row < barcode_matrix.len() { + { + { + let mut column: i32 = 0; + while column < barcode_matrix[row].len() { + { + barcode_matrix[row][column] = BarcodeValue::new(); + } + column += 1; + } + } + + } + row += 1; + } + } + + let mut column: i32 = 0; + for let detection_result_column: DetectionResultColumn in detection_result.get_detection_result_columns() { + if detection_result_column != null { + for let codeword: Codeword in detection_result_column.get_codewords() { + if codeword != null { + let row_number: i32 = codeword.get_row_number(); + if row_number >= 0 { + if row_number >= barcode_matrix.len() { + // We have more rows than the barcode metadata allows for, ignore them. + continue; + } + barcode_matrix[row_number][column].set_value(&codeword.get_value()); + } + } + } + } + column += 1; + } + return barcode_matrix; + } + + fn is_valid_barcode_column( detection_result: &DetectionResult, barcode_column: i32) -> bool { + return barcode_column >= 0 && barcode_column <= detection_result.get_barcode_column_count() + 1; + } + + fn get_start_column( detection_result: &DetectionResult, barcode_column: i32, image_row: i32, left_to_right: bool) -> i32 { + let offset: i32 = if left_to_right { 1 } else { -1 }; + let mut codeword: Codeword = null; + if ::is_valid_barcode_column(detection_result, barcode_column - offset) { + codeword = detection_result.get_detection_result_column(barcode_column - offset).get_codeword(image_row); + } + if codeword != null { + return if left_to_right { codeword.get_end_x() } else { codeword.get_start_x() }; + } + codeword = detection_result.get_detection_result_column(barcode_column).get_codeword_nearby(image_row); + if codeword != null { + return if left_to_right { codeword.get_start_x() } else { codeword.get_end_x() }; + } + if ::is_valid_barcode_column(detection_result, barcode_column - offset) { + codeword = detection_result.get_detection_result_column(barcode_column - offset).get_codeword_nearby(image_row); + } + if codeword != null { + return if left_to_right { codeword.get_end_x() } else { codeword.get_start_x() }; + } + let skipped_columns: i32 = 0; + while ::is_valid_barcode_column(detection_result, barcode_column - offset) { + barcode_column -= offset; + for let previous_row_codeword: Codeword in detection_result.get_detection_result_column(barcode_column).get_codewords() { + if previous_row_codeword != null { + return ( if left_to_right { previous_row_codeword.get_end_x() } else { previous_row_codeword.get_start_x() }) + offset * skipped_columns * (previous_row_codeword.get_end_x() - previous_row_codeword.get_start_x()); + } + } + skipped_columns += 1; + } + return if left_to_right { detection_result.get_bounding_box().get_min_x() } else { detection_result.get_bounding_box().get_max_x() }; + } + + fn detect_codeword( image: &BitMatrix, min_column: i32, max_column: i32, left_to_right: bool, start_column: i32, image_row: i32, min_codeword_width: i32, max_codeword_width: i32) -> Codeword { + start_column = ::adjust_codeword_start_column(image, min_column, max_column, left_to_right, start_column, image_row); + // we usually know fairly exact now how long a codeword is. We should provide minimum and maximum expected length + // and try to adjust the read pixels, e.g. remove single pixel errors or try to cut off exceeding pixels. + // min and maxCodewordWidth should not be used as they are calculated for the whole barcode an can be inaccurate + // for the current position + let module_bit_count: Vec = ::get_module_bit_count(image, min_column, max_column, left_to_right, start_column, image_row); + if module_bit_count == null { + return null; + } + let end_column: i32; + let codeword_bit_count: i32 = MathUtils::sum(&module_bit_count); + if left_to_right { + end_column = start_column + codeword_bit_count; + } else { + { + let mut i: i32 = 0; + while i < module_bit_count.len() / 2 { + { + let tmp_count: i32 = module_bit_count[i]; + module_bit_count[i] = module_bit_count[module_bit_count.len() - 1 - i]; + module_bit_count[module_bit_count.len() - 1 - i] = tmp_count; + } + i += 1; + } + } + + end_column = start_column; + start_column = end_column - codeword_bit_count; + } + // sufficient for now + if !::check_codeword_skew(codeword_bit_count, min_codeword_width, max_codeword_width) { + // create the bit count from it and normalize it to 8. This would help with single pixel errors. + return null; + } + let decoded_value: i32 = PDF417CodewordDecoder::get_decoded_value(&module_bit_count); + let codeword: i32 = PDF417Common::get_codeword(decoded_value); + if codeword == -1 { + return null; + } + return Codeword::new(start_column, end_column, &::get_codeword_bucket_number(decoded_value), codeword); + } + + fn get_module_bit_count( image: &BitMatrix, min_column: i32, max_column: i32, left_to_right: bool, start_column: i32, image_row: i32) -> Vec { + let image_column: i32 = start_column; + let module_bit_count: [i32; 8] = [0; 8]; + let module_number: i32 = 0; + let increment: i32 = if left_to_right { 1 } else { -1 }; + let previous_pixel_value: bool = left_to_right; + while ( if left_to_right { image_column < max_column } else { image_column >= min_column }) && module_number < module_bit_count.len() { + if image.get(image_column, image_row) == previous_pixel_value { + module_bit_count[module_number] += 1; + image_column += increment; + } else { + module_number += 1; + previous_pixel_value = !previous_pixel_value; + } + } + if module_number == module_bit_count.len() || ((image_column == ( if left_to_right { max_column } else { min_column })) && module_number == module_bit_count.len() - 1) { + return module_bit_count; + } + return null; + } + + fn get_number_of_e_c_code_words( barcode_e_c_level: i32) -> i32 { + return 2 << barcode_e_c_level; + } + + fn adjust_codeword_start_column( image: &BitMatrix, min_column: i32, max_column: i32, left_to_right: bool, codeword_start_column: i32, image_row: i32) -> i32 { + let corrected_start_column: i32 = codeword_start_column; + let mut increment: i32 = if left_to_right { -1 } else { 1 }; + // there should be no black pixels before the start column. If there are, then we need to start earlier. + { + let mut i: i32 = 0; + while i < 2 { + { + while ( if left_to_right { corrected_start_column >= min_column } else { corrected_start_column < max_column }) && left_to_right == image.get(corrected_start_column, image_row) { + if Math::abs(codeword_start_column - corrected_start_column) > CODEWORD_SKEW_SIZE { + return codeword_start_column; + } + corrected_start_column += increment; + } + increment = -increment; + left_to_right = !left_to_right; + } + i += 1; + } + } + + return corrected_start_column; + } + + fn check_codeword_skew( codeword_size: i32, min_codeword_width: i32, max_codeword_width: i32) -> bool { + return min_codeword_width - CODEWORD_SKEW_SIZE <= codeword_size && codeword_size <= max_codeword_width + CODEWORD_SKEW_SIZE; + } + + fn decode_codewords( codewords: &Vec, ec_level: i32, erasures: &Vec) -> /* throws FormatException, ChecksumException */Result> { + if codewords.len() == 0 { + throw FormatException::get_format_instance(); + } + let num_e_c_codewords: i32 = 1 << (ec_level + 1); + let corrected_errors_count: i32 = ::correct_errors(&codewords, &erasures, num_e_c_codewords); + ::verify_codeword_count(&codewords, num_e_c_codewords); + // Decode the codewords + let decoder_result: DecoderResult = DecodedBitStreamParser::decode(&codewords, &String::value_of(ec_level)); + decoder_result.set_errors_corrected(corrected_errors_count); + decoder_result.set_erasures(erasures.len()); + return Ok(decoder_result); + } + + /** + *

Given data and error-correction codewords received, possibly corrupted by errors, attempts to + * correct the errors in-place.

+ * + * @param codewords data and error correction codewords + * @param erasures positions of any known erasures + * @param numECCodewords number of error correction codewords that are available in codewords + * @throws ChecksumException if error correction fails + */ + fn correct_errors( codewords: &Vec, erasures: &Vec, num_e_c_codewords: i32) -> /* throws ChecksumException */Result> { + if erasures != null && erasures.len() > num_e_c_codewords / 2 + MAX_ERRORS || num_e_c_codewords < 0 || num_e_c_codewords > MAX_EC_CODEWORDS { + // Too many errors or EC Codewords is corrupted + throw ChecksumException::get_checksum_instance(); + } + return Ok(error_correction.decode(&codewords, num_e_c_codewords, &erasures)); + } + + /** + * Verify that all is OK with the codeword array. + */ + fn verify_codeword_count( codewords: &Vec, num_e_c_codewords: i32) -> /* throws FormatException */Result> { + if codewords.len() < 4 { + // Count CW, At least one Data CW, Error Correction CW, Error Correction CW + throw FormatException::get_format_instance(); + } + // The first codeword, the Symbol Length Descriptor, shall always encode the total number of data + // codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad + // codewords, but excluding the number of error correction codewords. + let number_of_codewords: i32 = codewords[0]; + if number_of_codewords > codewords.len() { + throw FormatException::get_format_instance(); + } + if number_of_codewords == 0 { + // Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords) + if num_e_c_codewords < codewords.len() { + codewords[0] = codewords.len() - num_e_c_codewords; + } else { + throw FormatException::get_format_instance(); + } + } + } + + fn get_bit_count_for_codeword( codeword: i32) -> Vec { + let mut result: [i32; 8] = [0; 8]; + let previous_value: i32 = 0; + let mut i: i32 = result.len() - 1; + while true { + if (codeword & 0x1) != previous_value { + previous_value = codeword & 0x1; + i -= 1; + if i < 0 { + break; + } + } + result[i] += 1; + codeword >>= 1; + } + return result; + } + + fn get_codeword_bucket_number( codeword: i32) -> i32 { + return ::get_codeword_bucket_number(&::get_bit_count_for_codeword(codeword)); + } + + fn get_codeword_bucket_number( module_bit_count: &Vec) -> i32 { + return (module_bit_count[0] - module_bit_count[2] + module_bit_count[4] - module_bit_count[6] + 9) % 9; + } + + pub fn to_string( barcode_matrix: &Vec>) -> String { + let tryResult1 = 0; + 'try1: loop { + ( let formatter: Formatter = Formatter::new()) { + { + let mut row: i32 = 0; + while row < barcode_matrix.len() { + { + formatter.format("Row %2d: ", row); + { + let mut column: i32 = 0; + while column < barcode_matrix[row].len() { + { + let barcode_value: BarcodeValue = barcode_matrix[row][column]; + if barcode_value.get_value().len() == 0 { + formatter.format(" ", null as Vec); + } else { + formatter.format("%4d(%2d)", barcode_value.get_value()[0], &barcode_value.get_confidence(barcode_value.get_value()[0])); + } + } + column += 1; + } + } + + formatter.format("%n"); + } + row += 1; + } + } + + return formatter.to_string(); + } + break 'try1 + } + match tryResult1 { + 0 => break + } + + } +} + diff --git a/src/pdf417/decoder/ec.rs b/src/pdf417/decoder/ec.rs index e69de29..b1e5975 100644 --- a/src/pdf417/decoder/ec.rs +++ b/src/pdf417/decoder/ec.rs @@ -0,0 +1,632 @@ +import com.google.zxing.ChecksumException; + +import com.google.zxing.pdf417.PDF417Common; + + + + +// NEW FILE: error_correction.rs +/* + * Copyright 2012 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::pdf417::decoder::ec; + +/** + *

PDF417 error correction implementation.

+ * + *

This example + * is quite useful in understanding the algorithm.

+ * + * @author Sean Owen + * @see com.google.zxing.common.reedsolomon.ReedSolomonDecoder + */ +pub struct ErrorCorrection { + + let mut field: ModulusGF; +} + +impl ErrorCorrection { + + pub fn new() -> ErrorCorrection { + let .field = ModulusGF::PDF417_GF; + } + + /** + * @param received received codewords + * @param numECCodewords number of those codewords used for EC + * @param erasures location of erasures + * @return number of errors + * @throws ChecksumException if errors cannot be corrected, maybe because of too many errors + */ + pub fn decode(&self, received: &Vec, num_e_c_codewords: i32, erasures: &Vec) -> /* throws ChecksumException */Result> { + let poly: ModulusPoly = ModulusPoly::new(self.field, &received); + const S: [i32; num_e_c_codewords] = [0; num_e_c_codewords]; + let mut error: bool = false; + { + let mut i: i32 = num_e_c_codewords; + while i > 0 { + { + let eval: i32 = poly.evaluate_at(&self.field.exp(i)); + S[num_e_c_codewords - i] = eval; + if eval != 0 { + error = true; + } + } + i -= 1; + } + } + + if !error { + return Ok(0); + } + let known_errors: ModulusPoly = self.field.get_one(); + if erasures != null { + for let erasure: i32 in erasures { + let b: i32 = self.field.exp(received.len() - 1 - erasure); + // Add (1 - bx) term: + let term: ModulusPoly = ModulusPoly::new(self.field, : vec![i32; 2] = vec![self.field.subtract(0, b), 1, ] + ); + known_errors = known_errors.multiply(term); + } + } + let syndrome: ModulusPoly = ModulusPoly::new(self.field, &S); + //syndrome = syndrome.multiply(knownErrors); + let sigma_omega: Vec = self.run_euclidean_algorithm(&self.field.build_monomial(num_e_c_codewords, 1), syndrome, num_e_c_codewords); + let sigma: ModulusPoly = sigma_omega[0]; + let omega: ModulusPoly = sigma_omega[1]; + //sigma = sigma.multiply(knownErrors); + let error_locations: Vec = self.find_error_locations(sigma); + let error_magnitudes: Vec = self.find_error_magnitudes(omega, sigma, &error_locations); + { + let mut i: i32 = 0; + while i < error_locations.len() { + { + let mut position: i32 = received.len() - 1 - self.field.log(error_locations[i]); + if position < 0 { + throw ChecksumException::get_checksum_instance(); + } + received[position] = self.field.subtract(received[position], error_magnitudes[i]); + } + i += 1; + } + } + + return Ok(error_locations.len()); + } + + fn run_euclidean_algorithm(&self, a: &ModulusPoly, b: &ModulusPoly, R: i32) -> /* throws ChecksumException */Result, Rc> { + // Assume a's degree is >= b's + if a.get_degree() < b.get_degree() { + let temp: ModulusPoly = a; + a = b; + b = temp; + } + let r_last: ModulusPoly = a; + let mut r: ModulusPoly = b; + let t_last: ModulusPoly = self.field.get_zero(); + let mut t: ModulusPoly = self.field.get_one(); + // Run Euclidean algorithm until r's degree is less than R/2 + while r.get_degree() >= R / 2 { + let r_last_last: ModulusPoly = r_last; + let t_last_last: ModulusPoly = t_last; + r_last = r; + t_last = t; + // Divide rLastLast by rLast, with quotient in q and remainder in r + if r_last.is_zero() { + // Oops, Euclidean algorithm already terminated? + throw ChecksumException::get_checksum_instance(); + } + r = r_last_last; + let mut q: ModulusPoly = self.field.get_zero(); + let denominator_leading_term: i32 = r_last.get_coefficient(&r_last.get_degree()); + let dlt_inverse: i32 = self.field.inverse(denominator_leading_term); + while r.get_degree() >= r_last.get_degree() && !r.is_zero() { + let degree_diff: i32 = r.get_degree() - r_last.get_degree(); + let scale: i32 = self.field.multiply(&r.get_coefficient(&r.get_degree()), dlt_inverse); + q = q.add(&self.field.build_monomial(degree_diff, scale)); + r = r.subtract(&r_last.multiply_by_monomial(degree_diff, scale)); + } + t = q.multiply(t_last).subtract(t_last_last).negative(); + } + let sigma_tilde_at_zero: i32 = t.get_coefficient(0); + if sigma_tilde_at_zero == 0 { + throw ChecksumException::get_checksum_instance(); + } + let inverse: i32 = self.field.inverse(sigma_tilde_at_zero); + let sigma: ModulusPoly = t.multiply(inverse); + let omega: ModulusPoly = r.multiply(inverse); + return Ok( : vec![ModulusPoly; 2] = vec![sigma, omega, ] + ); + } + + fn find_error_locations(&self, error_locator: &ModulusPoly) -> /* throws ChecksumException */Result, Rc> { + // This is a direct application of Chien's search + let num_errors: i32 = error_locator.get_degree(); + let mut result: [i32; num_errors] = [0; num_errors]; + let mut e: i32 = 0; + { + let mut i: i32 = 1; + while i < self.field.get_size() && e < num_errors { + { + if error_locator.evaluate_at(i) == 0 { + result[e] = self.field.inverse(i); + e += 1; + } + } + i += 1; + } + } + + if e != num_errors { + throw ChecksumException::get_checksum_instance(); + } + return Ok(result); + } + + fn find_error_magnitudes(&self, error_evaluator: &ModulusPoly, error_locator: &ModulusPoly, error_locations: &Vec) -> Vec { + let error_locator_degree: i32 = error_locator.get_degree(); + if error_locator_degree < 1 { + return : [i32; 0] = [0; 0]; + } + let formal_derivative_coefficients: [i32; error_locator_degree] = [0; error_locator_degree]; + { + let mut i: i32 = 1; + while i <= error_locator_degree { + { + formal_derivative_coefficients[error_locator_degree - i] = self.field.multiply(i, &error_locator.get_coefficient(i)); + } + i += 1; + } + } + + let formal_derivative: ModulusPoly = ModulusPoly::new(self.field, &formal_derivative_coefficients); + // This is directly applying Forney's Formula + let s: i32 = error_locations.len(); + let mut result: [i32; s] = [0; s]; + { + let mut i: i32 = 0; + while i < s { + { + let xi_inverse: i32 = self.field.inverse(error_locations[i]); + let numerator: i32 = self.field.subtract(0, &error_evaluator.evaluate_at(xi_inverse)); + let denominator: i32 = self.field.inverse(&formal_derivative.evaluate_at(xi_inverse)); + result[i] = self.field.multiply(numerator, denominator); + } + i += 1; + } + } + + return result; + } +} + +// NEW FILE: modulus_g_f.rs +/* + * Copyright 2012 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::pdf417::decoder::ec; + +/** + *

A field based on powers of a generator integer, modulo some modulus.

+ * + * @author Sean Owen + * @see com.google.zxing.common.reedsolomon.GenericGF + */ + + const PDF417_GF: ModulusGF = ModulusGF::new(PDF417Common.NUMBER_OF_CODEWORDS, 3); +pub struct ModulusGF { + + let exp_table: Vec; + + let log_table: Vec; + + let mut zero: ModulusPoly; + + let mut one: ModulusPoly; + + let modulus: i32; +} + +impl ModulusGF { + + fn new( modulus: i32, generator: i32) -> ModulusGF { + let .modulus = modulus; + exp_table = : [i32; modulus] = [0; modulus]; + log_table = : [i32; modulus] = [0; modulus]; + let mut x: i32 = 1; + { + let mut i: i32 = 0; + while i < modulus { + { + exp_table[i] = x; + x = (x * generator) % modulus; + } + i += 1; + } + } + + { + let mut i: i32 = 0; + while i < modulus - 1 { + { + log_table[exp_table[i]] = i; + } + i += 1; + } + } + + // logTable[0] == 0 but this should never be used + zero = ModulusPoly::new(let , : vec![i32; 1] = vec![0, ] + ); + one = ModulusPoly::new(let , : vec![i32; 1] = vec![1, ] + ); + } + + fn get_zero(&self) -> ModulusPoly { + return self.zero; + } + + fn get_one(&self) -> ModulusPoly { + return self.one; + } + + fn build_monomial(&self, degree: i32, coefficient: i32) -> ModulusPoly { + if degree < 0 { + throw IllegalArgumentException::new(); + } + if coefficient == 0 { + return self.zero; + } + let mut coefficients: [i32; degree + 1] = [0; degree + 1]; + coefficients[0] = coefficient; + return ModulusPoly::new(self, &coefficients); + } + + fn add(&self, a: i32, b: i32) -> i32 { + return (a + b) % self.modulus; + } + + fn subtract(&self, a: i32, b: i32) -> i32 { + return (self.modulus + a - b) % self.modulus; + } + + fn exp(&self, a: i32) -> i32 { + return self.exp_table[a]; + } + + fn log(&self, a: i32) -> i32 { + if a == 0 { + throw IllegalArgumentException::new(); + } + return self.log_table[a]; + } + + fn inverse(&self, a: i32) -> i32 { + if a == 0 { + throw ArithmeticException::new(); + } + return self.exp_table[self.modulus - self.log_table[a] - 1]; + } + + fn multiply(&self, a: i32, b: i32) -> i32 { + if a == 0 || b == 0 { + return 0; + } + return self.exp_table[(self.log_table[a] + self.log_table[b]) % (self.modulus - 1)]; + } + + fn get_size(&self) -> i32 { + return self.modulus; + } +} + +// NEW FILE: modulus_poly.rs +/* + * Copyright 2012 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::pdf417::decoder::ec; + +/** + * @author Sean Owen + */ +struct ModulusPoly { + + let field: ModulusGF; + + let coefficients: Vec; +} + +impl ModulusPoly { + + fn new( field: &ModulusGF, coefficients: &Vec) -> ModulusPoly { + if coefficients.len() == 0 { + throw IllegalArgumentException::new(); + } + let .field = field; + let coefficients_length: i32 = coefficients.len(); + if coefficients_length > 1 && coefficients[0] == 0 { + // Leading term must be non-zero for anything except the constant polynomial "0" + let first_non_zero: i32 = 1; + while first_non_zero < coefficients_length && coefficients[first_non_zero] == 0 { + first_non_zero += 1; + } + if first_non_zero == coefficients_length { + let .coefficients = : vec![i32; 1] = vec![0, ] + ; + } else { + let .coefficients = : [i32; coefficients_length - first_non_zero] = [0; coefficients_length - first_non_zero]; + System::arraycopy(&coefficients, first_non_zero, let .coefficients, 0, let .coefficients.len()); + } + } else { + let .coefficients = coefficients; + } + } + + fn get_coefficients(&self) -> Vec { + return self.coefficients; + } + + /** + * @return degree of this polynomial + */ + fn get_degree(&self) -> i32 { + return self.coefficients.len() - 1; + } + + /** + * @return true iff this polynomial is the monomial "0" + */ + fn is_zero(&self) -> bool { + return self.coefficients[0] == 0; + } + + /** + * @return coefficient of x^degree term in this polynomial + */ + fn get_coefficient(&self, degree: i32) -> i32 { + return self.coefficients[self.coefficients.len() - 1 - degree]; + } + + /** + * @return evaluation of this polynomial at a given point + */ + fn evaluate_at(&self, a: i32) -> i32 { + if a == 0 { + // Just return the x^0 coefficient + return self.get_coefficient(0); + } + if a == 1 { + // Just the sum of the coefficients + let mut result: i32 = 0; + for let coefficient: i32 in self.coefficients { + result = self.field.add(result, coefficient); + } + return result; + } + let mut result: i32 = self.coefficients[0]; + let size: i32 = self.coefficients.len(); + { + let mut i: i32 = 1; + while i < size { + { + result = self.field.add(&self.field.multiply(a, result), self.coefficients[i]); + } + i += 1; + } + } + + return result; + } + + fn add(&self, other: &ModulusPoly) -> ModulusPoly { + if !self.field.equals(other.field) { + throw IllegalArgumentException::new("ModulusPolys do not have same ModulusGF field"); + } + if self.is_zero() { + return other; + } + if other.is_zero() { + return self; + } + let smaller_coefficients: Vec = self.coefficients; + let larger_coefficients: Vec = other.coefficients; + if smaller_coefficients.len() > larger_coefficients.len() { + let temp: Vec = smaller_coefficients; + smaller_coefficients = larger_coefficients; + larger_coefficients = temp; + } + let sum_diff: [i32; larger_coefficients.len()] = [0; larger_coefficients.len()]; + let length_diff: i32 = larger_coefficients.len() - smaller_coefficients.len(); + // Copy high-order terms only found in higher-degree polynomial's coefficients + System::arraycopy(&larger_coefficients, 0, &sum_diff, 0, length_diff); + { + let mut i: i32 = length_diff; + while i < larger_coefficients.len() { + { + sum_diff[i] = self.field.add(smaller_coefficients[i - length_diff], larger_coefficients[i]); + } + i += 1; + } + } + + return ModulusPoly::new(self.field, &sum_diff); + } + + fn subtract(&self, other: &ModulusPoly) -> ModulusPoly { + if !self.field.equals(other.field) { + throw IllegalArgumentException::new("ModulusPolys do not have same ModulusGF field"); + } + if other.is_zero() { + return self; + } + return self.add(&other.negative()); + } + + fn multiply(&self, other: &ModulusPoly) -> ModulusPoly { + if !self.field.equals(other.field) { + throw IllegalArgumentException::new("ModulusPolys do not have same ModulusGF field"); + } + if self.is_zero() || other.is_zero() { + return self.field.get_zero(); + } + let a_coefficients: Vec = self.coefficients; + let a_length: i32 = a_coefficients.len(); + let b_coefficients: Vec = other.coefficients; + let b_length: i32 = b_coefficients.len(); + let mut product: [i32; a_length + b_length - 1] = [0; a_length + b_length - 1]; + { + let mut i: i32 = 0; + while i < a_length { + { + let a_coeff: i32 = a_coefficients[i]; + { + let mut j: i32 = 0; + while j < b_length { + { + product[i + j] = self.field.add(product[i + j], &self.field.multiply(a_coeff, b_coefficients[j])); + } + j += 1; + } + } + + } + i += 1; + } + } + + return ModulusPoly::new(self.field, &product); + } + + fn negative(&self) -> ModulusPoly { + let size: i32 = self.coefficients.len(); + let negative_coefficients: [i32; size] = [0; size]; + { + let mut i: i32 = 0; + while i < size { + { + negative_coefficients[i] = self.field.subtract(0, self.coefficients[i]); + } + i += 1; + } + } + + return ModulusPoly::new(self.field, &negative_coefficients); + } + + fn multiply(&self, scalar: i32) -> ModulusPoly { + if scalar == 0 { + return self.field.get_zero(); + } + if scalar == 1 { + return self; + } + let size: i32 = self.coefficients.len(); + let mut product: [i32; size] = [0; size]; + { + let mut i: i32 = 0; + while i < size { + { + product[i] = self.field.multiply(self.coefficients[i], scalar); + } + i += 1; + } + } + + return ModulusPoly::new(self.field, &product); + } + + fn multiply_by_monomial(&self, degree: i32, coefficient: i32) -> ModulusPoly { + if degree < 0 { + throw IllegalArgumentException::new(); + } + if coefficient == 0 { + return self.field.get_zero(); + } + let size: i32 = self.coefficients.len(); + let mut product: [i32; size + degree] = [0; size + degree]; + { + let mut i: i32 = 0; + while i < size { + { + product[i] = self.field.multiply(self.coefficients[i], coefficient); + } + i += 1; + } + } + + return ModulusPoly::new(self.field, &product); + } + + pub fn to_string(&self) -> String { + let result: StringBuilder = StringBuilder::new(8 * self.get_degree()); + { + let mut degree: i32 = self.get_degree(); + while degree >= 0 { + { + let mut coefficient: i32 = self.get_coefficient(degree); + if coefficient != 0 { + if coefficient < 0 { + result.append(" - "); + coefficient = -coefficient; + } else { + if result.length() > 0 { + result.append(" + "); + } + } + if degree == 0 || coefficient != 1 { + result.append(coefficient); + } + if degree != 0 { + if degree == 1 { + result.append('x'); + } else { + result.append("x^"); + result.append(degree); + } + } + } + } + degree -= 1; + } + } + + return result.to_string(); + } +} + diff --git a/src/pdf417/detector.rs b/src/pdf417/detector.rs index e69de29..72f5205 100644 --- a/src/pdf417/detector.rs +++ b/src/pdf417/detector.rs @@ -0,0 +1,441 @@ + +import com.google.zxing.BinaryBitmap; +import com.google.zxing.DecodeHintType; +import com.google.zxing.NotFoundException; +import com.google.zxing.ResultPoint; +import com.google.zxing.common.BitMatrix; + + +import com.google.zxing.ResultPoint; +import com.google.zxing.common.BitMatrix; + +// NEW FILE: detector.rs +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::pdf417::detector; + +/** + *

Encapsulates logic that can detect a PDF417 Code in an image, even if the + * PDF417 Code is rotated or skewed, or partially obscured.

+ * + * @author SITA Lab (kevin.osullivan@sita.aero) + * @author dswitkin@google.com (Daniel Switkin) + * @author Guenther Grau + */ + + const INDEXES_START_PATTERN: vec![Vec; 4] = vec![0, 4, 1, 5, ] +; + + const INDEXES_STOP_PATTERN: vec![Vec; 4] = vec![6, 2, 7, 3, ] +; + + const MAX_AVG_VARIANCE: f32 = 0.42f; + + const MAX_INDIVIDUAL_VARIANCE: f32 = 0.8f; + +// B S B S B S B S Bar/Space pattern +// 11111111 0 1 0 1 0 1 000 + const START_PATTERN: vec![Vec; 8] = vec![8, 1, 1, 1, 1, 1, 1, 3, ] +; + +// 1111111 0 1 000 1 0 1 00 1 + const STOP_PATTERN: vec![Vec; 9] = vec![7, 1, 1, 3, 1, 1, 1, 2, 1, ] +; + + const MAX_PIXEL_DRIFT: i32 = 3; + + const MAX_PATTERN_DRIFT: i32 = 5; + +// if we set the value too low, then we don't detect the correct height of the bar if the start patterns are damaged. +// if we set the value too high, then we might detect the start pattern from a neighbor barcode. + const SKIPPED_ROW_COUNT_MAX: i32 = 25; + +// A PDF471 barcode should have at least 3 rows, with each row being >= 3 times the module width. +// Therefore it should be at least 9 pixels tall. To be conservative, we use about half the size to +// ensure we don't miss it. + const ROW_STEP: i32 = 5; + + const BARCODE_MIN_HEIGHT: i32 = 10; + + const ROTATIONS: vec![Vec; 4] = vec![0, 180, 270, 90, ] +; +pub struct Detector { +} + +impl Detector { + + fn new() -> Detector { + } + + /** + *

Detects a PDF417 Code in an image. Checks 0, 90, 180, and 270 degree rotations.

+ * + * @param image barcode image to decode + * @param hints optional hints to detector + * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will + * be found and returned + * @return {@link PDF417DetectorResult} encapsulating results of detecting a PDF417 code + * @throws NotFoundException if no PDF417 Code can be found + */ + pub fn detect( image: &BinaryBitmap, hints: &Map, multiple: bool) -> /* throws NotFoundException */Result> { + // TODO detection improvement, tryHarder could try several different luminance thresholds/blackpoints or even + // different binarizers + //boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); + let original_matrix: BitMatrix = image.get_black_matrix(); + for let rotation: i32 in ROTATIONS { + let bit_matrix: BitMatrix = ::apply_rotation(original_matrix, rotation); + let barcode_coordinates: List> = ::detect(multiple, bit_matrix); + if !barcode_coordinates.is_empty() { + return Ok(PDF417DetectorResult::new(bit_matrix, &barcode_coordinates, rotation)); + } + } + return Ok(PDF417DetectorResult::new(original_matrix, ArrayList<>::new(), 0)); + } + + /** + * Applies a rotation to the supplied BitMatrix. + * @param matrix bit matrix to apply rotation to + * @param rotation the degrees of rotation to apply + * @return BitMatrix with applied rotation + */ + fn apply_rotation( matrix: &BitMatrix, rotation: i32) -> BitMatrix { + if rotation % 360 == 0 { + return matrix; + } + let new_matrix: BitMatrix = matrix.clone(); + new_matrix.rotate(rotation); + return new_matrix; + } + + /** + * Detects PDF417 codes in an image. Only checks 0 degree rotation + * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will + * be found and returned + * @param bitMatrix bit matrix to detect barcodes in + * @return List of ResultPoint arrays containing the coordinates of found barcodes + */ + fn detect( multiple: bool, bit_matrix: &BitMatrix) -> List> { + let barcode_coordinates: List> = ArrayList<>::new(); + let mut row: i32 = 0; + let mut column: i32 = 0; + let found_barcode_in_row: bool = false; + while row < bit_matrix.get_height() { + let vertices: Vec = ::find_vertices(bit_matrix, row, column); + if vertices[0] == null && vertices[3] == null { + if !found_barcode_in_row { + // we didn't find any barcode so that's the end of searching + break; + } + // we didn't find a barcode starting at the given column and row. Try again from the first column and slightly + // below the lowest barcode we found so far. + found_barcode_in_row = false; + column = 0; + for let barcode_coordinate: Vec in barcode_coordinates { + if barcode_coordinate[1] != null { + row = Math::max(row, &barcode_coordinate[1].get_y()) as i32; + } + if barcode_coordinate[3] != null { + row = Math::max(row, barcode_coordinate[3].get_y() as i32); + } + } + row += ROW_STEP; + continue; + } + found_barcode_in_row = true; + barcode_coordinates.add(vertices); + if !multiple { + break; + } + // start pattern of the barcode just found. + if vertices[2] != null { + column = vertices[2].get_x() as i32; + row = vertices[2].get_y() as i32; + } else { + column = vertices[4].get_x() as i32; + row = vertices[4].get_y() as i32; + } + } + return Ok(barcode_coordinates); + } + + /** + * Locate the vertices and the codewords area of a black blob using the Start + * and Stop patterns as locators. + * + * @param matrix the scanned barcode image. + * @return an array containing the vertices: + * vertices[0] x, y top left barcode + * vertices[1] x, y bottom left barcode + * vertices[2] x, y top right barcode + * vertices[3] x, y bottom right barcode + * vertices[4] x, y top left codeword area + * vertices[5] x, y bottom left codeword area + * vertices[6] x, y top right codeword area + * vertices[7] x, y bottom right codeword area + */ + fn find_vertices( matrix: &BitMatrix, start_row: i32, start_column: i32) -> Vec { + let height: i32 = matrix.get_height(); + let width: i32 = matrix.get_width(); + let result: [Option; 8] = [None; 8]; + ::copy_to_result(result, &::find_rows_with_pattern(matrix, height, width, start_row, start_column, &START_PATTERN), &INDEXES_START_PATTERN); + if result[4] != null { + start_column = result[4].get_x() as i32; + start_row = result[4].get_y() as i32; + } + ::copy_to_result(result, &::find_rows_with_pattern(matrix, height, width, start_row, start_column, &STOP_PATTERN), &INDEXES_STOP_PATTERN); + return result; + } + + fn copy_to_result( result: &Vec, tmp_result: &Vec, destination_indexes: &Vec) { + { + let mut i: i32 = 0; + while i < destination_indexes.len() { + { + result[destination_indexes[i]] = tmp_result[i]; + } + i += 1; + } + } + + } + + fn find_rows_with_pattern( matrix: &BitMatrix, height: i32, width: i32, start_row: i32, start_column: i32, pattern: &Vec) -> Vec { + let mut result: [Option; 4] = [None; 4]; + let mut found: bool = false; + let counters: [i32; pattern.len()] = [0; pattern.len()]; + while start_row < height { + { + let mut loc: Vec = ::find_guard_pattern(matrix, start_column, start_row, width, &pattern, &counters); + if loc != null { + while start_row > 0 { + let previous_row_loc: Vec = ::find_guard_pattern(matrix, start_column, start_row -= 1, width, &pattern, &counters); + if previous_row_loc != null { + loc = previous_row_loc; + } else { + start_row += 1; + break; + } + } + result[0] = ResultPoint::new(loc[0], start_row); + result[1] = ResultPoint::new(loc[1], start_row); + found = true; + break; + } + } + start_row += ROW_STEP; + } + + let stop_row: i32 = start_row + 1; + // Last row of the current symbol that contains pattern + if found { + let skipped_row_count: i32 = 0; + let previous_row_loc: vec![Vec; 2] = vec![result[0].get_x() as i32, result[1].get_x() as i32, ] + ; + while stop_row < height { + { + let loc: Vec = ::find_guard_pattern(matrix, previous_row_loc[0], stop_row, width, &pattern, &counters); + // larger drift and don't check for skipped rows. + if loc != null && Math::abs(previous_row_loc[0] - loc[0]) < MAX_PATTERN_DRIFT && Math::abs(previous_row_loc[1] - loc[1]) < MAX_PATTERN_DRIFT { + previous_row_loc = loc; + skipped_row_count = 0; + } else { + if skipped_row_count > SKIPPED_ROW_COUNT_MAX { + break; + } else { + skipped_row_count += 1; + } + } + } + stop_row += 1; + } + + stop_row -= skipped_row_count + 1; + result[2] = ResultPoint::new(previous_row_loc[0], stop_row); + result[3] = ResultPoint::new(previous_row_loc[1], stop_row); + } + if stop_row - start_row < BARCODE_MIN_HEIGHT { + Arrays::fill(result, null); + } + return result; + } + + /** + * @param matrix row of black/white values to search + * @param column x position to start search + * @param row y position to start search + * @param width the number of pixels to search on this row + * @param pattern pattern of counts of number of black and white pixels that are + * being searched for as a pattern + * @param counters array of counters, as long as pattern, to re-use + * @return start/end horizontal offset of guard pattern, as an array of two ints. + */ + fn find_guard_pattern( matrix: &BitMatrix, column: i32, row: i32, width: i32, pattern: &Vec, counters: &Vec) -> Vec { + Arrays::fill(&counters, 0, counters.len(), 0); + let pattern_start: i32 = column; + let pixel_drift: i32 = 0; + // if there are black pixels left of the current pixel shift to the left, but only for MAX_PIXEL_DRIFT pixels + while matrix.get(pattern_start, row) && pattern_start > 0 && pixel_drift += 1 !!!check!!! post increment < MAX_PIXEL_DRIFT { + pattern_start -= 1; + } + let mut x: i32 = pattern_start; + let counter_position: i32 = 0; + let pattern_length: i32 = pattern.len(); + { + let is_white: bool = false; + while x < width { + { + let pixel: bool = matrix.get(x, row); + if pixel != is_white { + counters[counter_position] += 1; + } else { + if counter_position == pattern_length - 1 { + if ::pattern_match_variance(&counters, &pattern) < MAX_AVG_VARIANCE { + return : vec![i32; 2] = vec![pattern_start, x, ] + ; + } + pattern_start += counters[0] + counters[1]; + System::arraycopy(&counters, 2, &counters, 0, counter_position - 1); + counters[counter_position - 1] = 0; + counters[counter_position] = 0; + counter_position -= 1; + } else { + counter_position += 1; + } + counters[counter_position] = 1; + is_white = !is_white; + } + } + x += 1; + } + } + + if counter_position == pattern_length - 1 && ::pattern_match_variance(&counters, &pattern) < MAX_AVG_VARIANCE { + return : vec![i32; 2] = vec![pattern_start, x - 1, ] + ; + } + return null; + } + + /** + * Determines how closely a set of observed counts of runs of black/white + * values matches a given target pattern. This is reported as the ratio of + * the total variance from the expected pattern proportions across all + * pattern elements, to the length of the pattern. + * + * @param counters observed counters + * @param pattern expected pattern + * @return ratio of total variance between counters and pattern compared to total pattern size + */ + fn pattern_match_variance( counters: &Vec, pattern: &Vec) -> f32 { + let num_counters: i32 = counters.len(); + let mut total: i32 = 0; + let pattern_length: i32 = 0; + { + let mut i: i32 = 0; + while i < num_counters { + { + total += counters[i]; + pattern_length += pattern[i]; + } + i += 1; + } + } + + if total < pattern_length { + // is too small to reliably match, so fail: + return Float::POSITIVE_INFINITY; + } + // We're going to fake floating-point math in integers. We just need to use more bits. + // Scale up patternLength so that intermediate values below like scaledCounter will have + // more "significant digits". + let unit_bar_width: f32 = total as f32 / pattern_length; + let max_individual_variance: f32 = MAX_INDIVIDUAL_VARIANCE * unit_bar_width; + let total_variance: f32 = 0.0f; + { + let mut x: i32 = 0; + while x < num_counters { + { + let counter: i32 = counters[x]; + let scaled_pattern: f32 = pattern[x] * unit_bar_width; + let variance: f32 = if counter > scaled_pattern { counter - scaled_pattern } else { scaled_pattern - counter }; + if variance > max_individual_variance { + return Float::POSITIVE_INFINITY; + } + total_variance += variance; + } + x += 1; + } + } + + return total_variance / total; + } +} + +// NEW FILE: p_d_f417_detector_result.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::pdf417::detector; + +/** + * @author Guenther Grau + */ +pub struct PDF417DetectorResult { + + let bits: BitMatrix; + + let points: List>; + + let rotation: i32; +} + +impl PDF417DetectorResult { + + pub fn new( bits: &BitMatrix, points: &List>, rotation: i32) -> PDF417DetectorResult { + let .bits = bits; + let .points = points; + let .rotation = rotation; + } + + pub fn new( bits: &BitMatrix, points: &List>) -> PDF417DetectorResult { + this(bits, &points, 0); + } + + pub fn get_bits(&self) -> BitMatrix { + return self.bits; + } + + pub fn get_points(&self) -> List> { + return self.points; + } + + pub fn get_rotation(&self) -> i32 { + return self.rotation; + } +} + diff --git a/src/pdf417/encoder.rs b/src/pdf417/encoder.rs index e69de29..72c6ac1 100644 --- a/src/pdf417/encoder.rs +++ b/src/pdf417/encoder.rs @@ -0,0 +1,1571 @@ +import com.google.zxing.WriterException; + +import com.google.zxing.WriterException; +import com.google.zxing.common.CharacterSetECI; +import com.google.zxing.common.ECIInput; +import com.google.zxing.common.MinimalECIInput; + + + +// NEW FILE: barcode_matrix.rs +/* + * Copyright 2011 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::pdf417::encoder; + +/** + * Holds all of the information for a barcode in a format where it can be easily accessible + * + * @author Jacob Haynes + */ +pub struct BarcodeMatrix { + + let mut matrix: Vec; + + let current_row: i32; + + let height: i32; + + let width: i32; +} + +impl BarcodeMatrix { + + /** + * @param height the height of the matrix (Rows) + * @param width the width of the matrix (Cols) + */ + fn new( height: i32, width: i32) -> BarcodeMatrix { + matrix = : [Option; height] = [None; height]; + //Initializes the array to the correct width + { + let mut i: i32 = 0, let matrix_length: i32 = matrix.len(); + while i < matrix_length { + { + matrix[i] = BarcodeRow::new((width + 4) * 17 + 1); + } + i += 1; + } + } + + let .width = width * 17; + let .height = height; + let .currentRow = -1; + } + + fn set(&self, x: i32, y: i32, value: i8) { + self.matrix[y].set(x, value); + } + + fn start_row(&self) { + self.current_row += 1; + } + + fn get_current_row(&self) -> BarcodeRow { + return self.matrix[self.current_row]; + } + + pub fn get_matrix(&self) -> Vec> { + return self.get_scaled_matrix(1, 1); + } + + pub fn get_scaled_matrix(&self, x_scale: i32, y_scale: i32) -> Vec> { + let matrix_out: [[i8; self.width * x_scale]; self.height * y_scale] = [[0; self.width * x_scale]; self.height * y_scale]; + let y_max: i32 = self.height * y_scale; + { + let mut i: i32 = 0; + while i < y_max { + { + matrix_out[y_max - i - 1] = self.matrix[i / y_scale].get_scaled_row(x_scale); + } + i += 1; + } + } + + return matrix_out; + } +} + +// NEW FILE: barcode_row.rs +/* + * Copyright 2011 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::pdf417::encoder; + +/** + * @author Jacob Haynes + */ +struct BarcodeRow { + + let mut row: Vec; + + //A tacker for position in the bar + let current_location: i32; +} + +impl BarcodeRow { + + /** + * Creates a Barcode row of the width + */ + fn new( width: i32) -> BarcodeRow { + let .row = : [i8; width] = [0; width]; + current_location = 0; + } + + /** + * Sets a specific location in the bar + * + * @param x The location in the bar + * @param value Black if true, white if false; + */ + fn set(&self, x: i32, value: i8) { + self.row[x] = value; + } + + /** + * Sets a specific location in the bar + * + * @param x The location in the bar + * @param black Black if true, white if false; + */ + fn set(&self, x: i32, black: bool) { + self.row[x] = ( if black { 1 } else { 0 }) as i8; + } + + /** + * @param black A boolean which is true if the bar black false if it is white + * @param width How many spots wide the bar is. + */ + fn add_bar(&self, black: bool, width: i32) { + { + let mut ii: i32 = 0; + while ii < width { + { + self.set(self.current_location += 1 !!!check!!! post increment, black); + } + ii += 1; + } + } + + } + + /** + * This function scales the row + * + * @param scale How much you want the image to be scaled, must be greater than or equal to 1. + * @return the scaled row + */ + fn get_scaled_row(&self, scale: i32) -> Vec { + let mut output: [i8; self.row.len() * scale] = [0; self.row.len() * scale]; + { + let mut i: i32 = 0; + while i < output.len() { + { + output[i] = self.row[i / scale]; + } + i += 1; + } + } + + return output; + } +} + +// NEW FILE: compaction.rs +/* + * Copyright 2011 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::pdf417::encoder; + +/** + * Represents possible PDF417 barcode compaction types. + */ +pub enum Compaction { + + AUTO(), TEXT(), BYTE(), NUMERIC() +} +// NEW FILE: dimensions.rs +/* + * Copyright 2012 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::pdf417::encoder; + +/** + * Data object to specify the minimum and maximum number of rows and columns for a PDF417 barcode. + * + * @author qwandor@google.com (Andrew Walbran) + */ +pub struct Dimensions { + + let min_cols: i32; + + let max_cols: i32; + + let min_rows: i32; + + let max_rows: i32; +} + +impl Dimensions { + + pub fn new( min_cols: i32, max_cols: i32, min_rows: i32, max_rows: i32) -> Dimensions { + let .minCols = min_cols; + let .maxCols = max_cols; + let .minRows = min_rows; + let .maxRows = max_rows; + } + + pub fn get_min_cols(&self) -> i32 { + return self.min_cols; + } + + pub fn get_max_cols(&self) -> i32 { + return self.max_cols; + } + + pub fn get_min_rows(&self) -> i32 { + return self.min_rows; + } + + pub fn get_max_rows(&self) -> i32 { + return self.max_rows; + } +} + +// NEW FILE: p_d_f417.rs +/* + * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part + * + * 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::pdf417::encoder; + +/** + * Top-level class for the logic part of the PDF417 implementation. + */ + +/** + * The start pattern (17 bits) + */ + const START_PATTERN: i32 = 0x1fea8; + +/** + * The stop pattern (18 bits) + */ + const STOP_PATTERN: i32 = 0x3fa29; + +/** + * The codeword table from the Annex A of ISO/IEC 15438:2001(E). + */ + const CODEWORD_TABLE: vec![vec![Vec>; 929]; 3] = vec![vec![0x1d5c0, 0x1eaf0, 0x1f57c, 0x1d4e0, 0x1ea78, 0x1f53e, 0x1a8c0, 0x1d470, 0x1a860, 0x15040, 0x1a830, 0x15020, 0x1adc0, 0x1d6f0, 0x1eb7c, 0x1ace0, 0x1d678, 0x1eb3e, 0x158c0, 0x1ac70, 0x15860, 0x15dc0, 0x1aef0, 0x1d77c, 0x15ce0, 0x1ae78, 0x1d73e, 0x15c70, 0x1ae3c, 0x15ef0, 0x1af7c, 0x15e78, 0x1af3e, 0x15f7c, 0x1f5fa, 0x1d2e0, 0x1e978, 0x1f4be, 0x1a4c0, 0x1d270, 0x1e93c, 0x1a460, 0x1d238, 0x14840, 0x1a430, 0x1d21c, 0x14820, 0x1a418, 0x14810, 0x1a6e0, 0x1d378, 0x1e9be, 0x14cc0, 0x1a670, 0x1d33c, 0x14c60, 0x1a638, 0x1d31e, 0x14c30, 0x1a61c, 0x14ee0, 0x1a778, 0x1d3be, 0x14e70, 0x1a73c, 0x14e38, 0x1a71e, 0x14f78, 0x1a7be, 0x14f3c, 0x14f1e, 0x1a2c0, 0x1d170, 0x1e8bc, 0x1a260, 0x1d138, 0x1e89e, 0x14440, 0x1a230, 0x1d11c, 0x14420, 0x1a218, 0x14410, 0x14408, 0x146c0, 0x1a370, 0x1d1bc, 0x14660, 0x1a338, 0x1d19e, 0x14630, 0x1a31c, 0x14618, 0x1460c, 0x14770, 0x1a3bc, 0x14738, 0x1a39e, 0x1471c, 0x147bc, 0x1a160, 0x1d0b8, 0x1e85e, 0x14240, 0x1a130, 0x1d09c, 0x14220, 0x1a118, 0x1d08e, 0x14210, 0x1a10c, 0x14208, 0x1a106, 0x14360, 0x1a1b8, 0x1d0de, 0x14330, 0x1a19c, 0x14318, 0x1a18e, 0x1430c, 0x14306, 0x1a1de, 0x1438e, 0x14140, 0x1a0b0, 0x1d05c, 0x14120, 0x1a098, 0x1d04e, 0x14110, 0x1a08c, 0x14108, 0x1a086, 0x14104, 0x141b0, 0x14198, 0x1418c, 0x140a0, 0x1d02e, 0x1a04c, 0x1a046, 0x14082, 0x1cae0, 0x1e578, 0x1f2be, 0x194c0, 0x1ca70, 0x1e53c, 0x19460, 0x1ca38, 0x1e51e, 0x12840, 0x19430, 0x12820, 0x196e0, 0x1cb78, 0x1e5be, 0x12cc0, 0x19670, 0x1cb3c, 0x12c60, 0x19638, 0x12c30, 0x12c18, 0x12ee0, 0x19778, 0x1cbbe, 0x12e70, 0x1973c, 0x12e38, 0x12e1c, 0x12f78, 0x197be, 0x12f3c, 0x12fbe, 0x1dac0, 0x1ed70, 0x1f6bc, 0x1da60, 0x1ed38, 0x1f69e, 0x1b440, 0x1da30, 0x1ed1c, 0x1b420, 0x1da18, 0x1ed0e, 0x1b410, 0x1da0c, 0x192c0, 0x1c970, 0x1e4bc, 0x1b6c0, 0x19260, 0x1c938, 0x1e49e, 0x1b660, 0x1db38, 0x1ed9e, 0x16c40, 0x12420, 0x19218, 0x1c90e, 0x16c20, 0x1b618, 0x16c10, 0x126c0, 0x19370, 0x1c9bc, 0x16ec0, 0x12660, 0x19338, 0x1c99e, 0x16e60, 0x1b738, 0x1db9e, 0x16e30, 0x12618, 0x16e18, 0x12770, 0x193bc, 0x16f70, 0x12738, 0x1939e, 0x16f38, 0x1b79e, 0x16f1c, 0x127bc, 0x16fbc, 0x1279e, 0x16f9e, 0x1d960, 0x1ecb8, 0x1f65e, 0x1b240, 0x1d930, 0x1ec9c, 0x1b220, 0x1d918, 0x1ec8e, 0x1b210, 0x1d90c, 0x1b208, 0x1b204, 0x19160, 0x1c8b8, 0x1e45e, 0x1b360, 0x19130, 0x1c89c, 0x16640, 0x12220, 0x1d99c, 0x1c88e, 0x16620, 0x12210, 0x1910c, 0x16610, 0x1b30c, 0x19106, 0x12204, 0x12360, 0x191b8, 0x1c8de, 0x16760, 0x12330, 0x1919c, 0x16730, 0x1b39c, 0x1918e, 0x16718, 0x1230c, 0x12306, 0x123b8, 0x191de, 0x167b8, 0x1239c, 0x1679c, 0x1238e, 0x1678e, 0x167de, 0x1b140, 0x1d8b0, 0x1ec5c, 0x1b120, 0x1d898, 0x1ec4e, 0x1b110, 0x1d88c, 0x1b108, 0x1d886, 0x1b104, 0x1b102, 0x12140, 0x190b0, 0x1c85c, 0x16340, 0x12120, 0x19098, 0x1c84e, 0x16320, 0x1b198, 0x1d8ce, 0x16310, 0x12108, 0x19086, 0x16308, 0x1b186, 0x16304, 0x121b0, 0x190dc, 0x163b0, 0x12198, 0x190ce, 0x16398, 0x1b1ce, 0x1638c, 0x12186, 0x16386, 0x163dc, 0x163ce, 0x1b0a0, 0x1d858, 0x1ec2e, 0x1b090, 0x1d84c, 0x1b088, 0x1d846, 0x1b084, 0x1b082, 0x120a0, 0x19058, 0x1c82e, 0x161a0, 0x12090, 0x1904c, 0x16190, 0x1b0cc, 0x19046, 0x16188, 0x12084, 0x16184, 0x12082, 0x120d8, 0x161d8, 0x161cc, 0x161c6, 0x1d82c, 0x1d826, 0x1b042, 0x1902c, 0x12048, 0x160c8, 0x160c4, 0x160c2, 0x18ac0, 0x1c570, 0x1e2bc, 0x18a60, 0x1c538, 0x11440, 0x18a30, 0x1c51c, 0x11420, 0x18a18, 0x11410, 0x11408, 0x116c0, 0x18b70, 0x1c5bc, 0x11660, 0x18b38, 0x1c59e, 0x11630, 0x18b1c, 0x11618, 0x1160c, 0x11770, 0x18bbc, 0x11738, 0x18b9e, 0x1171c, 0x117bc, 0x1179e, 0x1cd60, 0x1e6b8, 0x1f35e, 0x19a40, 0x1cd30, 0x1e69c, 0x19a20, 0x1cd18, 0x1e68e, 0x19a10, 0x1cd0c, 0x19a08, 0x1cd06, 0x18960, 0x1c4b8, 0x1e25e, 0x19b60, 0x18930, 0x1c49c, 0x13640, 0x11220, 0x1cd9c, 0x1c48e, 0x13620, 0x19b18, 0x1890c, 0x13610, 0x11208, 0x13608, 0x11360, 0x189b8, 0x1c4de, 0x13760, 0x11330, 0x1cdde, 0x13730, 0x19b9c, 0x1898e, 0x13718, 0x1130c, 0x1370c, 0x113b8, 0x189de, 0x137b8, 0x1139c, 0x1379c, 0x1138e, 0x113de, 0x137de, 0x1dd40, 0x1eeb0, 0x1f75c, 0x1dd20, 0x1ee98, 0x1f74e, 0x1dd10, 0x1ee8c, 0x1dd08, 0x1ee86, 0x1dd04, 0x19940, 0x1ccb0, 0x1e65c, 0x1bb40, 0x19920, 0x1eedc, 0x1e64e, 0x1bb20, 0x1dd98, 0x1eece, 0x1bb10, 0x19908, 0x1cc86, 0x1bb08, 0x1dd86, 0x19902, 0x11140, 0x188b0, 0x1c45c, 0x13340, 0x11120, 0x18898, 0x1c44e, 0x17740, 0x13320, 0x19998, 0x1ccce, 0x17720, 0x1bb98, 0x1ddce, 0x18886, 0x17710, 0x13308, 0x19986, 0x17708, 0x11102, 0x111b0, 0x188dc, 0x133b0, 0x11198, 0x188ce, 0x177b0, 0x13398, 0x199ce, 0x17798, 0x1bbce, 0x11186, 0x13386, 0x111dc, 0x133dc, 0x111ce, 0x177dc, 0x133ce, 0x1dca0, 0x1ee58, 0x1f72e, 0x1dc90, 0x1ee4c, 0x1dc88, 0x1ee46, 0x1dc84, 0x1dc82, 0x198a0, 0x1cc58, 0x1e62e, 0x1b9a0, 0x19890, 0x1ee6e, 0x1b990, 0x1dccc, 0x1cc46, 0x1b988, 0x19884, 0x1b984, 0x19882, 0x1b982, 0x110a0, 0x18858, 0x1c42e, 0x131a0, 0x11090, 0x1884c, 0x173a0, 0x13190, 0x198cc, 0x18846, 0x17390, 0x1b9cc, 0x11084, 0x17388, 0x13184, 0x11082, 0x13182, 0x110d8, 0x1886e, 0x131d8, 0x110cc, 0x173d8, 0x131cc, 0x110c6, 0x173cc, 0x131c6, 0x110ee, 0x173ee, 0x1dc50, 0x1ee2c, 0x1dc48, 0x1ee26, 0x1dc44, 0x1dc42, 0x19850, 0x1cc2c, 0x1b8d0, 0x19848, 0x1cc26, 0x1b8c8, 0x1dc66, 0x1b8c4, 0x19842, 0x1b8c2, 0x11050, 0x1882c, 0x130d0, 0x11048, 0x18826, 0x171d0, 0x130c8, 0x19866, 0x171c8, 0x1b8e6, 0x11042, 0x171c4, 0x130c2, 0x171c2, 0x130ec, 0x171ec, 0x171e6, 0x1ee16, 0x1dc22, 0x1cc16, 0x19824, 0x19822, 0x11028, 0x13068, 0x170e8, 0x11022, 0x13062, 0x18560, 0x10a40, 0x18530, 0x10a20, 0x18518, 0x1c28e, 0x10a10, 0x1850c, 0x10a08, 0x18506, 0x10b60, 0x185b8, 0x1c2de, 0x10b30, 0x1859c, 0x10b18, 0x1858e, 0x10b0c, 0x10b06, 0x10bb8, 0x185de, 0x10b9c, 0x10b8e, 0x10bde, 0x18d40, 0x1c6b0, 0x1e35c, 0x18d20, 0x1c698, 0x18d10, 0x1c68c, 0x18d08, 0x1c686, 0x18d04, 0x10940, 0x184b0, 0x1c25c, 0x11b40, 0x10920, 0x1c6dc, 0x1c24e, 0x11b20, 0x18d98, 0x1c6ce, 0x11b10, 0x10908, 0x18486, 0x11b08, 0x18d86, 0x10902, 0x109b0, 0x184dc, 0x11bb0, 0x10998, 0x184ce, 0x11b98, 0x18dce, 0x11b8c, 0x10986, 0x109dc, 0x11bdc, 0x109ce, 0x11bce, 0x1cea0, 0x1e758, 0x1f3ae, 0x1ce90, 0x1e74c, 0x1ce88, 0x1e746, 0x1ce84, 0x1ce82, 0x18ca0, 0x1c658, 0x19da0, 0x18c90, 0x1c64c, 0x19d90, 0x1cecc, 0x1c646, 0x19d88, 0x18c84, 0x19d84, 0x18c82, 0x19d82, 0x108a0, 0x18458, 0x119a0, 0x10890, 0x1c66e, 0x13ba0, 0x11990, 0x18ccc, 0x18446, 0x13b90, 0x19dcc, 0x10884, 0x13b88, 0x11984, 0x10882, 0x11982, 0x108d8, 0x1846e, 0x119d8, 0x108cc, 0x13bd8, 0x119cc, 0x108c6, 0x13bcc, 0x119c6, 0x108ee, 0x119ee, 0x13bee, 0x1ef50, 0x1f7ac, 0x1ef48, 0x1f7a6, 0x1ef44, 0x1ef42, 0x1ce50, 0x1e72c, 0x1ded0, 0x1ef6c, 0x1e726, 0x1dec8, 0x1ef66, 0x1dec4, 0x1ce42, 0x1dec2, 0x18c50, 0x1c62c, 0x19cd0, 0x18c48, 0x1c626, 0x1bdd0, 0x19cc8, 0x1ce66, 0x1bdc8, 0x1dee6, 0x18c42, 0x1bdc4, 0x19cc2, 0x1bdc2, 0x10850, 0x1842c, 0x118d0, 0x10848, 0x18426, 0x139d0, 0x118c8, 0x18c66, 0x17bd0, 0x139c8, 0x19ce6, 0x10842, 0x17bc8, 0x1bde6, 0x118c2, 0x17bc4, 0x1086c, 0x118ec, 0x10866, 0x139ec, 0x118e6, 0x17bec, 0x139e6, 0x17be6, 0x1ef28, 0x1f796, 0x1ef24, 0x1ef22, 0x1ce28, 0x1e716, 0x1de68, 0x1ef36, 0x1de64, 0x1ce22, 0x1de62, 0x18c28, 0x1c616, 0x19c68, 0x18c24, 0x1bce8, 0x19c64, 0x18c22, 0x1bce4, 0x19c62, 0x1bce2, 0x10828, 0x18416, 0x11868, 0x18c36, 0x138e8, 0x11864, 0x10822, 0x179e8, 0x138e4, 0x11862, 0x179e4, 0x138e2, 0x179e2, 0x11876, 0x179f6, 0x1ef12, 0x1de34, 0x1de32, 0x19c34, 0x1bc74, 0x1bc72, 0x11834, 0x13874, 0x178f4, 0x178f2, 0x10540, 0x10520, 0x18298, 0x10510, 0x10508, 0x10504, 0x105b0, 0x10598, 0x1058c, 0x10586, 0x105dc, 0x105ce, 0x186a0, 0x18690, 0x1c34c, 0x18688, 0x1c346, 0x18684, 0x18682, 0x104a0, 0x18258, 0x10da0, 0x186d8, 0x1824c, 0x10d90, 0x186cc, 0x10d88, 0x186c6, 0x10d84, 0x10482, 0x10d82, 0x104d8, 0x1826e, 0x10dd8, 0x186ee, 0x10dcc, 0x104c6, 0x10dc6, 0x104ee, 0x10dee, 0x1c750, 0x1c748, 0x1c744, 0x1c742, 0x18650, 0x18ed0, 0x1c76c, 0x1c326, 0x18ec8, 0x1c766, 0x18ec4, 0x18642, 0x18ec2, 0x10450, 0x10cd0, 0x10448, 0x18226, 0x11dd0, 0x10cc8, 0x10444, 0x11dc8, 0x10cc4, 0x10442, 0x11dc4, 0x10cc2, 0x1046c, 0x10cec, 0x10466, 0x11dec, 0x10ce6, 0x11de6, 0x1e7a8, 0x1e7a4, 0x1e7a2, 0x1c728, 0x1cf68, 0x1e7b6, 0x1cf64, 0x1c722, 0x1cf62, 0x18628, 0x1c316, 0x18e68, 0x1c736, 0x19ee8, 0x18e64, 0x18622, 0x19ee4, 0x18e62, 0x19ee2, 0x10428, 0x18216, 0x10c68, 0x18636, 0x11ce8, 0x10c64, 0x10422, 0x13de8, 0x11ce4, 0x10c62, 0x13de4, 0x11ce2, 0x10436, 0x10c76, 0x11cf6, 0x13df6, 0x1f7d4, 0x1f7d2, 0x1e794, 0x1efb4, 0x1e792, 0x1efb2, 0x1c714, 0x1cf34, 0x1c712, 0x1df74, 0x1cf32, 0x1df72, 0x18614, 0x18e34, 0x18612, 0x19e74, 0x18e32, 0x1bef4, ] +, vec![0x1f560, 0x1fab8, 0x1ea40, 0x1f530, 0x1fa9c, 0x1ea20, 0x1f518, 0x1fa8e, 0x1ea10, 0x1f50c, 0x1ea08, 0x1f506, 0x1ea04, 0x1eb60, 0x1f5b8, 0x1fade, 0x1d640, 0x1eb30, 0x1f59c, 0x1d620, 0x1eb18, 0x1f58e, 0x1d610, 0x1eb0c, 0x1d608, 0x1eb06, 0x1d604, 0x1d760, 0x1ebb8, 0x1f5de, 0x1ae40, 0x1d730, 0x1eb9c, 0x1ae20, 0x1d718, 0x1eb8e, 0x1ae10, 0x1d70c, 0x1ae08, 0x1d706, 0x1ae04, 0x1af60, 0x1d7b8, 0x1ebde, 0x15e40, 0x1af30, 0x1d79c, 0x15e20, 0x1af18, 0x1d78e, 0x15e10, 0x1af0c, 0x15e08, 0x1af06, 0x15f60, 0x1afb8, 0x1d7de, 0x15f30, 0x1af9c, 0x15f18, 0x1af8e, 0x15f0c, 0x15fb8, 0x1afde, 0x15f9c, 0x15f8e, 0x1e940, 0x1f4b0, 0x1fa5c, 0x1e920, 0x1f498, 0x1fa4e, 0x1e910, 0x1f48c, 0x1e908, 0x1f486, 0x1e904, 0x1e902, 0x1d340, 0x1e9b0, 0x1f4dc, 0x1d320, 0x1e998, 0x1f4ce, 0x1d310, 0x1e98c, 0x1d308, 0x1e986, 0x1d304, 0x1d302, 0x1a740, 0x1d3b0, 0x1e9dc, 0x1a720, 0x1d398, 0x1e9ce, 0x1a710, 0x1d38c, 0x1a708, 0x1d386, 0x1a704, 0x1a702, 0x14f40, 0x1a7b0, 0x1d3dc, 0x14f20, 0x1a798, 0x1d3ce, 0x14f10, 0x1a78c, 0x14f08, 0x1a786, 0x14f04, 0x14fb0, 0x1a7dc, 0x14f98, 0x1a7ce, 0x14f8c, 0x14f86, 0x14fdc, 0x14fce, 0x1e8a0, 0x1f458, 0x1fa2e, 0x1e890, 0x1f44c, 0x1e888, 0x1f446, 0x1e884, 0x1e882, 0x1d1a0, 0x1e8d8, 0x1f46e, 0x1d190, 0x1e8cc, 0x1d188, 0x1e8c6, 0x1d184, 0x1d182, 0x1a3a0, 0x1d1d8, 0x1e8ee, 0x1a390, 0x1d1cc, 0x1a388, 0x1d1c6, 0x1a384, 0x1a382, 0x147a0, 0x1a3d8, 0x1d1ee, 0x14790, 0x1a3cc, 0x14788, 0x1a3c6, 0x14784, 0x14782, 0x147d8, 0x1a3ee, 0x147cc, 0x147c6, 0x147ee, 0x1e850, 0x1f42c, 0x1e848, 0x1f426, 0x1e844, 0x1e842, 0x1d0d0, 0x1e86c, 0x1d0c8, 0x1e866, 0x1d0c4, 0x1d0c2, 0x1a1d0, 0x1d0ec, 0x1a1c8, 0x1d0e6, 0x1a1c4, 0x1a1c2, 0x143d0, 0x1a1ec, 0x143c8, 0x1a1e6, 0x143c4, 0x143c2, 0x143ec, 0x143e6, 0x1e828, 0x1f416, 0x1e824, 0x1e822, 0x1d068, 0x1e836, 0x1d064, 0x1d062, 0x1a0e8, 0x1d076, 0x1a0e4, 0x1a0e2, 0x141e8, 0x1a0f6, 0x141e4, 0x141e2, 0x1e814, 0x1e812, 0x1d034, 0x1d032, 0x1a074, 0x1a072, 0x1e540, 0x1f2b0, 0x1f95c, 0x1e520, 0x1f298, 0x1f94e, 0x1e510, 0x1f28c, 0x1e508, 0x1f286, 0x1e504, 0x1e502, 0x1cb40, 0x1e5b0, 0x1f2dc, 0x1cb20, 0x1e598, 0x1f2ce, 0x1cb10, 0x1e58c, 0x1cb08, 0x1e586, 0x1cb04, 0x1cb02, 0x19740, 0x1cbb0, 0x1e5dc, 0x19720, 0x1cb98, 0x1e5ce, 0x19710, 0x1cb8c, 0x19708, 0x1cb86, 0x19704, 0x19702, 0x12f40, 0x197b0, 0x1cbdc, 0x12f20, 0x19798, 0x1cbce, 0x12f10, 0x1978c, 0x12f08, 0x19786, 0x12f04, 0x12fb0, 0x197dc, 0x12f98, 0x197ce, 0x12f8c, 0x12f86, 0x12fdc, 0x12fce, 0x1f6a0, 0x1fb58, 0x16bf0, 0x1f690, 0x1fb4c, 0x169f8, 0x1f688, 0x1fb46, 0x168fc, 0x1f684, 0x1f682, 0x1e4a0, 0x1f258, 0x1f92e, 0x1eda0, 0x1e490, 0x1fb6e, 0x1ed90, 0x1f6cc, 0x1f246, 0x1ed88, 0x1e484, 0x1ed84, 0x1e482, 0x1ed82, 0x1c9a0, 0x1e4d8, 0x1f26e, 0x1dba0, 0x1c990, 0x1e4cc, 0x1db90, 0x1edcc, 0x1e4c6, 0x1db88, 0x1c984, 0x1db84, 0x1c982, 0x1db82, 0x193a0, 0x1c9d8, 0x1e4ee, 0x1b7a0, 0x19390, 0x1c9cc, 0x1b790, 0x1dbcc, 0x1c9c6, 0x1b788, 0x19384, 0x1b784, 0x19382, 0x1b782, 0x127a0, 0x193d8, 0x1c9ee, 0x16fa0, 0x12790, 0x193cc, 0x16f90, 0x1b7cc, 0x193c6, 0x16f88, 0x12784, 0x16f84, 0x12782, 0x127d8, 0x193ee, 0x16fd8, 0x127cc, 0x16fcc, 0x127c6, 0x16fc6, 0x127ee, 0x1f650, 0x1fb2c, 0x165f8, 0x1f648, 0x1fb26, 0x164fc, 0x1f644, 0x1647e, 0x1f642, 0x1e450, 0x1f22c, 0x1ecd0, 0x1e448, 0x1f226, 0x1ecc8, 0x1f666, 0x1ecc4, 0x1e442, 0x1ecc2, 0x1c8d0, 0x1e46c, 0x1d9d0, 0x1c8c8, 0x1e466, 0x1d9c8, 0x1ece6, 0x1d9c4, 0x1c8c2, 0x1d9c2, 0x191d0, 0x1c8ec, 0x1b3d0, 0x191c8, 0x1c8e6, 0x1b3c8, 0x1d9e6, 0x1b3c4, 0x191c2, 0x1b3c2, 0x123d0, 0x191ec, 0x167d0, 0x123c8, 0x191e6, 0x167c8, 0x1b3e6, 0x167c4, 0x123c2, 0x167c2, 0x123ec, 0x167ec, 0x123e6, 0x167e6, 0x1f628, 0x1fb16, 0x162fc, 0x1f624, 0x1627e, 0x1f622, 0x1e428, 0x1f216, 0x1ec68, 0x1f636, 0x1ec64, 0x1e422, 0x1ec62, 0x1c868, 0x1e436, 0x1d8e8, 0x1c864, 0x1d8e4, 0x1c862, 0x1d8e2, 0x190e8, 0x1c876, 0x1b1e8, 0x1d8f6, 0x1b1e4, 0x190e2, 0x1b1e2, 0x121e8, 0x190f6, 0x163e8, 0x121e4, 0x163e4, 0x121e2, 0x163e2, 0x121f6, 0x163f6, 0x1f614, 0x1617e, 0x1f612, 0x1e414, 0x1ec34, 0x1e412, 0x1ec32, 0x1c834, 0x1d874, 0x1c832, 0x1d872, 0x19074, 0x1b0f4, 0x19072, 0x1b0f2, 0x120f4, 0x161f4, 0x120f2, 0x161f2, 0x1f60a, 0x1e40a, 0x1ec1a, 0x1c81a, 0x1d83a, 0x1903a, 0x1b07a, 0x1e2a0, 0x1f158, 0x1f8ae, 0x1e290, 0x1f14c, 0x1e288, 0x1f146, 0x1e284, 0x1e282, 0x1c5a0, 0x1e2d8, 0x1f16e, 0x1c590, 0x1e2cc, 0x1c588, 0x1e2c6, 0x1c584, 0x1c582, 0x18ba0, 0x1c5d8, 0x1e2ee, 0x18b90, 0x1c5cc, 0x18b88, 0x1c5c6, 0x18b84, 0x18b82, 0x117a0, 0x18bd8, 0x1c5ee, 0x11790, 0x18bcc, 0x11788, 0x18bc6, 0x11784, 0x11782, 0x117d8, 0x18bee, 0x117cc, 0x117c6, 0x117ee, 0x1f350, 0x1f9ac, 0x135f8, 0x1f348, 0x1f9a6, 0x134fc, 0x1f344, 0x1347e, 0x1f342, 0x1e250, 0x1f12c, 0x1e6d0, 0x1e248, 0x1f126, 0x1e6c8, 0x1f366, 0x1e6c4, 0x1e242, 0x1e6c2, 0x1c4d0, 0x1e26c, 0x1cdd0, 0x1c4c8, 0x1e266, 0x1cdc8, 0x1e6e6, 0x1cdc4, 0x1c4c2, 0x1cdc2, 0x189d0, 0x1c4ec, 0x19bd0, 0x189c8, 0x1c4e6, 0x19bc8, 0x1cde6, 0x19bc4, 0x189c2, 0x19bc2, 0x113d0, 0x189ec, 0x137d0, 0x113c8, 0x189e6, 0x137c8, 0x19be6, 0x137c4, 0x113c2, 0x137c2, 0x113ec, 0x137ec, 0x113e6, 0x137e6, 0x1fba8, 0x175f0, 0x1bafc, 0x1fba4, 0x174f8, 0x1ba7e, 0x1fba2, 0x1747c, 0x1743e, 0x1f328, 0x1f996, 0x132fc, 0x1f768, 0x1fbb6, 0x176fc, 0x1327e, 0x1f764, 0x1f322, 0x1767e, 0x1f762, 0x1e228, 0x1f116, 0x1e668, 0x1e224, 0x1eee8, 0x1f776, 0x1e222, 0x1eee4, 0x1e662, 0x1eee2, 0x1c468, 0x1e236, 0x1cce8, 0x1c464, 0x1dde8, 0x1cce4, 0x1c462, 0x1dde4, 0x1cce2, 0x1dde2, 0x188e8, 0x1c476, 0x199e8, 0x188e4, 0x1bbe8, 0x199e4, 0x188e2, 0x1bbe4, 0x199e2, 0x1bbe2, 0x111e8, 0x188f6, 0x133e8, 0x111e4, 0x177e8, 0x133e4, 0x111e2, 0x177e4, 0x133e2, 0x177e2, 0x111f6, 0x133f6, 0x1fb94, 0x172f8, 0x1b97e, 0x1fb92, 0x1727c, 0x1723e, 0x1f314, 0x1317e, 0x1f734, 0x1f312, 0x1737e, 0x1f732, 0x1e214, 0x1e634, 0x1e212, 0x1ee74, 0x1e632, 0x1ee72, 0x1c434, 0x1cc74, 0x1c432, 0x1dcf4, 0x1cc72, 0x1dcf2, 0x18874, 0x198f4, 0x18872, 0x1b9f4, 0x198f2, 0x1b9f2, 0x110f4, 0x131f4, 0x110f2, 0x173f4, 0x131f2, 0x173f2, 0x1fb8a, 0x1717c, 0x1713e, 0x1f30a, 0x1f71a, 0x1e20a, 0x1e61a, 0x1ee3a, 0x1c41a, 0x1cc3a, 0x1dc7a, 0x1883a, 0x1987a, 0x1b8fa, 0x1107a, 0x130fa, 0x171fa, 0x170be, 0x1e150, 0x1f0ac, 0x1e148, 0x1f0a6, 0x1e144, 0x1e142, 0x1c2d0, 0x1e16c, 0x1c2c8, 0x1e166, 0x1c2c4, 0x1c2c2, 0x185d0, 0x1c2ec, 0x185c8, 0x1c2e6, 0x185c4, 0x185c2, 0x10bd0, 0x185ec, 0x10bc8, 0x185e6, 0x10bc4, 0x10bc2, 0x10bec, 0x10be6, 0x1f1a8, 0x1f8d6, 0x11afc, 0x1f1a4, 0x11a7e, 0x1f1a2, 0x1e128, 0x1f096, 0x1e368, 0x1e124, 0x1e364, 0x1e122, 0x1e362, 0x1c268, 0x1e136, 0x1c6e8, 0x1c264, 0x1c6e4, 0x1c262, 0x1c6e2, 0x184e8, 0x1c276, 0x18de8, 0x184e4, 0x18de4, 0x184e2, 0x18de2, 0x109e8, 0x184f6, 0x11be8, 0x109e4, 0x11be4, 0x109e2, 0x11be2, 0x109f6, 0x11bf6, 0x1f9d4, 0x13af8, 0x19d7e, 0x1f9d2, 0x13a7c, 0x13a3e, 0x1f194, 0x1197e, 0x1f3b4, 0x1f192, 0x13b7e, 0x1f3b2, 0x1e114, 0x1e334, 0x1e112, 0x1e774, 0x1e332, 0x1e772, 0x1c234, 0x1c674, 0x1c232, 0x1cef4, 0x1c672, 0x1cef2, 0x18474, 0x18cf4, 0x18472, 0x19df4, 0x18cf2, 0x19df2, 0x108f4, 0x119f4, 0x108f2, 0x13bf4, 0x119f2, 0x13bf2, 0x17af0, 0x1bd7c, 0x17a78, 0x1bd3e, 0x17a3c, 0x17a1e, 0x1f9ca, 0x1397c, 0x1fbda, 0x17b7c, 0x1393e, 0x17b3e, 0x1f18a, 0x1f39a, 0x1f7ba, 0x1e10a, 0x1e31a, 0x1e73a, 0x1ef7a, 0x1c21a, 0x1c63a, 0x1ce7a, 0x1defa, 0x1843a, 0x18c7a, 0x19cfa, 0x1bdfa, 0x1087a, 0x118fa, 0x139fa, 0x17978, 0x1bcbe, 0x1793c, 0x1791e, 0x138be, 0x179be, 0x178bc, 0x1789e, 0x1785e, 0x1e0a8, 0x1e0a4, 0x1e0a2, 0x1c168, 0x1e0b6, 0x1c164, 0x1c162, 0x182e8, 0x1c176, 0x182e4, 0x182e2, 0x105e8, 0x182f6, 0x105e4, 0x105e2, 0x105f6, 0x1f0d4, 0x10d7e, 0x1f0d2, 0x1e094, 0x1e1b4, 0x1e092, 0x1e1b2, 0x1c134, 0x1c374, 0x1c132, 0x1c372, 0x18274, 0x186f4, 0x18272, 0x186f2, 0x104f4, 0x10df4, 0x104f2, 0x10df2, 0x1f8ea, 0x11d7c, 0x11d3e, 0x1f0ca, 0x1f1da, 0x1e08a, 0x1e19a, 0x1e3ba, 0x1c11a, 0x1c33a, 0x1c77a, 0x1823a, 0x1867a, 0x18efa, 0x1047a, 0x10cfa, 0x11dfa, 0x13d78, 0x19ebe, 0x13d3c, 0x13d1e, 0x11cbe, 0x13dbe, 0x17d70, 0x1bebc, 0x17d38, 0x1be9e, 0x17d1c, 0x17d0e, 0x13cbc, 0x17dbc, 0x13c9e, 0x17d9e, 0x17cb8, 0x1be5e, 0x17c9c, 0x17c8e, 0x13c5e, 0x17cde, 0x17c5c, 0x17c4e, 0x17c2e, 0x1c0b4, 0x1c0b2, 0x18174, 0x18172, 0x102f4, 0x102f2, 0x1e0da, 0x1c09a, 0x1c1ba, 0x1813a, 0x1837a, 0x1027a, 0x106fa, 0x10ebe, 0x11ebc, 0x11e9e, 0x13eb8, 0x19f5e, 0x13e9c, 0x13e8e, 0x11e5e, 0x13ede, 0x17eb0, 0x1bf5c, 0x17e98, 0x1bf4e, 0x17e8c, 0x17e86, 0x13e5c, 0x17edc, 0x13e4e, 0x17ece, 0x17e58, 0x1bf2e, 0x17e4c, 0x17e46, 0x13e2e, 0x17e6e, 0x17e2c, 0x17e26, 0x10f5e, 0x11f5c, 0x11f4e, 0x13f58, 0x19fae, 0x13f4c, 0x13f46, 0x11f2e, 0x13f6e, 0x13f2c, 0x13f26, ] +, vec![0x1abe0, 0x1d5f8, 0x153c0, 0x1a9f0, 0x1d4fc, 0x151e0, 0x1a8f8, 0x1d47e, 0x150f0, 0x1a87c, 0x15078, 0x1fad0, 0x15be0, 0x1adf8, 0x1fac8, 0x159f0, 0x1acfc, 0x1fac4, 0x158f8, 0x1ac7e, 0x1fac2, 0x1587c, 0x1f5d0, 0x1faec, 0x15df8, 0x1f5c8, 0x1fae6, 0x15cfc, 0x1f5c4, 0x15c7e, 0x1f5c2, 0x1ebd0, 0x1f5ec, 0x1ebc8, 0x1f5e6, 0x1ebc4, 0x1ebc2, 0x1d7d0, 0x1ebec, 0x1d7c8, 0x1ebe6, 0x1d7c4, 0x1d7c2, 0x1afd0, 0x1d7ec, 0x1afc8, 0x1d7e6, 0x1afc4, 0x14bc0, 0x1a5f0, 0x1d2fc, 0x149e0, 0x1a4f8, 0x1d27e, 0x148f0, 0x1a47c, 0x14878, 0x1a43e, 0x1483c, 0x1fa68, 0x14df0, 0x1a6fc, 0x1fa64, 0x14cf8, 0x1a67e, 0x1fa62, 0x14c7c, 0x14c3e, 0x1f4e8, 0x1fa76, 0x14efc, 0x1f4e4, 0x14e7e, 0x1f4e2, 0x1e9e8, 0x1f4f6, 0x1e9e4, 0x1e9e2, 0x1d3e8, 0x1e9f6, 0x1d3e4, 0x1d3e2, 0x1a7e8, 0x1d3f6, 0x1a7e4, 0x1a7e2, 0x145e0, 0x1a2f8, 0x1d17e, 0x144f0, 0x1a27c, 0x14478, 0x1a23e, 0x1443c, 0x1441e, 0x1fa34, 0x146f8, 0x1a37e, 0x1fa32, 0x1467c, 0x1463e, 0x1f474, 0x1477e, 0x1f472, 0x1e8f4, 0x1e8f2, 0x1d1f4, 0x1d1f2, 0x1a3f4, 0x1a3f2, 0x142f0, 0x1a17c, 0x14278, 0x1a13e, 0x1423c, 0x1421e, 0x1fa1a, 0x1437c, 0x1433e, 0x1f43a, 0x1e87a, 0x1d0fa, 0x14178, 0x1a0be, 0x1413c, 0x1411e, 0x141be, 0x140bc, 0x1409e, 0x12bc0, 0x195f0, 0x1cafc, 0x129e0, 0x194f8, 0x1ca7e, 0x128f0, 0x1947c, 0x12878, 0x1943e, 0x1283c, 0x1f968, 0x12df0, 0x196fc, 0x1f964, 0x12cf8, 0x1967e, 0x1f962, 0x12c7c, 0x12c3e, 0x1f2e8, 0x1f976, 0x12efc, 0x1f2e4, 0x12e7e, 0x1f2e2, 0x1e5e8, 0x1f2f6, 0x1e5e4, 0x1e5e2, 0x1cbe8, 0x1e5f6, 0x1cbe4, 0x1cbe2, 0x197e8, 0x1cbf6, 0x197e4, 0x197e2, 0x1b5e0, 0x1daf8, 0x1ed7e, 0x169c0, 0x1b4f0, 0x1da7c, 0x168e0, 0x1b478, 0x1da3e, 0x16870, 0x1b43c, 0x16838, 0x1b41e, 0x1681c, 0x125e0, 0x192f8, 0x1c97e, 0x16de0, 0x124f0, 0x1927c, 0x16cf0, 0x1b67c, 0x1923e, 0x16c78, 0x1243c, 0x16c3c, 0x1241e, 0x16c1e, 0x1f934, 0x126f8, 0x1937e, 0x1fb74, 0x1f932, 0x16ef8, 0x1267c, 0x1fb72, 0x16e7c, 0x1263e, 0x16e3e, 0x1f274, 0x1277e, 0x1f6f4, 0x1f272, 0x16f7e, 0x1f6f2, 0x1e4f4, 0x1edf4, 0x1e4f2, 0x1edf2, 0x1c9f4, 0x1dbf4, 0x1c9f2, 0x1dbf2, 0x193f4, 0x193f2, 0x165c0, 0x1b2f0, 0x1d97c, 0x164e0, 0x1b278, 0x1d93e, 0x16470, 0x1b23c, 0x16438, 0x1b21e, 0x1641c, 0x1640e, 0x122f0, 0x1917c, 0x166f0, 0x12278, 0x1913e, 0x16678, 0x1b33e, 0x1663c, 0x1221e, 0x1661e, 0x1f91a, 0x1237c, 0x1fb3a, 0x1677c, 0x1233e, 0x1673e, 0x1f23a, 0x1f67a, 0x1e47a, 0x1ecfa, 0x1c8fa, 0x1d9fa, 0x191fa, 0x162e0, 0x1b178, 0x1d8be, 0x16270, 0x1b13c, 0x16238, 0x1b11e, 0x1621c, 0x1620e, 0x12178, 0x190be, 0x16378, 0x1213c, 0x1633c, 0x1211e, 0x1631e, 0x121be, 0x163be, 0x16170, 0x1b0bc, 0x16138, 0x1b09e, 0x1611c, 0x1610e, 0x120bc, 0x161bc, 0x1209e, 0x1619e, 0x160b8, 0x1b05e, 0x1609c, 0x1608e, 0x1205e, 0x160de, 0x1605c, 0x1604e, 0x115e0, 0x18af8, 0x1c57e, 0x114f0, 0x18a7c, 0x11478, 0x18a3e, 0x1143c, 0x1141e, 0x1f8b4, 0x116f8, 0x18b7e, 0x1f8b2, 0x1167c, 0x1163e, 0x1f174, 0x1177e, 0x1f172, 0x1e2f4, 0x1e2f2, 0x1c5f4, 0x1c5f2, 0x18bf4, 0x18bf2, 0x135c0, 0x19af0, 0x1cd7c, 0x134e0, 0x19a78, 0x1cd3e, 0x13470, 0x19a3c, 0x13438, 0x19a1e, 0x1341c, 0x1340e, 0x112f0, 0x1897c, 0x136f0, 0x11278, 0x1893e, 0x13678, 0x19b3e, 0x1363c, 0x1121e, 0x1361e, 0x1f89a, 0x1137c, 0x1f9ba, 0x1377c, 0x1133e, 0x1373e, 0x1f13a, 0x1f37a, 0x1e27a, 0x1e6fa, 0x1c4fa, 0x1cdfa, 0x189fa, 0x1bae0, 0x1dd78, 0x1eebe, 0x174c0, 0x1ba70, 0x1dd3c, 0x17460, 0x1ba38, 0x1dd1e, 0x17430, 0x1ba1c, 0x17418, 0x1ba0e, 0x1740c, 0x132e0, 0x19978, 0x1ccbe, 0x176e0, 0x13270, 0x1993c, 0x17670, 0x1bb3c, 0x1991e, 0x17638, 0x1321c, 0x1761c, 0x1320e, 0x1760e, 0x11178, 0x188be, 0x13378, 0x1113c, 0x17778, 0x1333c, 0x1111e, 0x1773c, 0x1331e, 0x1771e, 0x111be, 0x133be, 0x177be, 0x172c0, 0x1b970, 0x1dcbc, 0x17260, 0x1b938, 0x1dc9e, 0x17230, 0x1b91c, 0x17218, 0x1b90e, 0x1720c, 0x17206, 0x13170, 0x198bc, 0x17370, 0x13138, 0x1989e, 0x17338, 0x1b99e, 0x1731c, 0x1310e, 0x1730e, 0x110bc, 0x131bc, 0x1109e, 0x173bc, 0x1319e, 0x1739e, 0x17160, 0x1b8b8, 0x1dc5e, 0x17130, 0x1b89c, 0x17118, 0x1b88e, 0x1710c, 0x17106, 0x130b8, 0x1985e, 0x171b8, 0x1309c, 0x1719c, 0x1308e, 0x1718e, 0x1105e, 0x130de, 0x171de, 0x170b0, 0x1b85c, 0x17098, 0x1b84e, 0x1708c, 0x17086, 0x1305c, 0x170dc, 0x1304e, 0x170ce, 0x17058, 0x1b82e, 0x1704c, 0x17046, 0x1302e, 0x1706e, 0x1702c, 0x17026, 0x10af0, 0x1857c, 0x10a78, 0x1853e, 0x10a3c, 0x10a1e, 0x10b7c, 0x10b3e, 0x1f0ba, 0x1e17a, 0x1c2fa, 0x185fa, 0x11ae0, 0x18d78, 0x1c6be, 0x11a70, 0x18d3c, 0x11a38, 0x18d1e, 0x11a1c, 0x11a0e, 0x10978, 0x184be, 0x11b78, 0x1093c, 0x11b3c, 0x1091e, 0x11b1e, 0x109be, 0x11bbe, 0x13ac0, 0x19d70, 0x1cebc, 0x13a60, 0x19d38, 0x1ce9e, 0x13a30, 0x19d1c, 0x13a18, 0x19d0e, 0x13a0c, 0x13a06, 0x11970, 0x18cbc, 0x13b70, 0x11938, 0x18c9e, 0x13b38, 0x1191c, 0x13b1c, 0x1190e, 0x13b0e, 0x108bc, 0x119bc, 0x1089e, 0x13bbc, 0x1199e, 0x13b9e, 0x1bd60, 0x1deb8, 0x1ef5e, 0x17a40, 0x1bd30, 0x1de9c, 0x17a20, 0x1bd18, 0x1de8e, 0x17a10, 0x1bd0c, 0x17a08, 0x1bd06, 0x17a04, 0x13960, 0x19cb8, 0x1ce5e, 0x17b60, 0x13930, 0x19c9c, 0x17b30, 0x1bd9c, 0x19c8e, 0x17b18, 0x1390c, 0x17b0c, 0x13906, 0x17b06, 0x118b8, 0x18c5e, 0x139b8, 0x1189c, 0x17bb8, 0x1399c, 0x1188e, 0x17b9c, 0x1398e, 0x17b8e, 0x1085e, 0x118de, 0x139de, 0x17bde, 0x17940, 0x1bcb0, 0x1de5c, 0x17920, 0x1bc98, 0x1de4e, 0x17910, 0x1bc8c, 0x17908, 0x1bc86, 0x17904, 0x17902, 0x138b0, 0x19c5c, 0x179b0, 0x13898, 0x19c4e, 0x17998, 0x1bcce, 0x1798c, 0x13886, 0x17986, 0x1185c, 0x138dc, 0x1184e, 0x179dc, 0x138ce, 0x179ce, 0x178a0, 0x1bc58, 0x1de2e, 0x17890, 0x1bc4c, 0x17888, 0x1bc46, 0x17884, 0x17882, 0x13858, 0x19c2e, 0x178d8, 0x1384c, 0x178cc, 0x13846, 0x178c6, 0x1182e, 0x1386e, 0x178ee, 0x17850, 0x1bc2c, 0x17848, 0x1bc26, 0x17844, 0x17842, 0x1382c, 0x1786c, 0x13826, 0x17866, 0x17828, 0x1bc16, 0x17824, 0x17822, 0x13816, 0x17836, 0x10578, 0x182be, 0x1053c, 0x1051e, 0x105be, 0x10d70, 0x186bc, 0x10d38, 0x1869e, 0x10d1c, 0x10d0e, 0x104bc, 0x10dbc, 0x1049e, 0x10d9e, 0x11d60, 0x18eb8, 0x1c75e, 0x11d30, 0x18e9c, 0x11d18, 0x18e8e, 0x11d0c, 0x11d06, 0x10cb8, 0x1865e, 0x11db8, 0x10c9c, 0x11d9c, 0x10c8e, 0x11d8e, 0x1045e, 0x10cde, 0x11dde, 0x13d40, 0x19eb0, 0x1cf5c, 0x13d20, 0x19e98, 0x1cf4e, 0x13d10, 0x19e8c, 0x13d08, 0x19e86, 0x13d04, 0x13d02, 0x11cb0, 0x18e5c, 0x13db0, 0x11c98, 0x18e4e, 0x13d98, 0x19ece, 0x13d8c, 0x11c86, 0x13d86, 0x10c5c, 0x11cdc, 0x10c4e, 0x13ddc, 0x11cce, 0x13dce, 0x1bea0, 0x1df58, 0x1efae, 0x1be90, 0x1df4c, 0x1be88, 0x1df46, 0x1be84, 0x1be82, 0x13ca0, 0x19e58, 0x1cf2e, 0x17da0, 0x13c90, 0x19e4c, 0x17d90, 0x1becc, 0x19e46, 0x17d88, 0x13c84, 0x17d84, 0x13c82, 0x17d82, 0x11c58, 0x18e2e, 0x13cd8, 0x11c4c, 0x17dd8, 0x13ccc, 0x11c46, 0x17dcc, 0x13cc6, 0x17dc6, 0x10c2e, 0x11c6e, 0x13cee, 0x17dee, 0x1be50, 0x1df2c, 0x1be48, 0x1df26, 0x1be44, 0x1be42, 0x13c50, 0x19e2c, 0x17cd0, 0x13c48, 0x19e26, 0x17cc8, 0x1be66, 0x17cc4, 0x13c42, 0x17cc2, 0x11c2c, 0x13c6c, 0x11c26, 0x17cec, 0x13c66, 0x17ce6, 0x1be28, 0x1df16, 0x1be24, 0x1be22, 0x13c28, 0x19e16, 0x17c68, 0x13c24, 0x17c64, 0x13c22, 0x17c62, 0x11c16, 0x13c36, 0x17c76, 0x1be14, 0x1be12, 0x13c14, 0x17c34, 0x13c12, 0x17c32, 0x102bc, 0x1029e, 0x106b8, 0x1835e, 0x1069c, 0x1068e, 0x1025e, 0x106de, 0x10eb0, 0x1875c, 0x10e98, 0x1874e, 0x10e8c, 0x10e86, 0x1065c, 0x10edc, 0x1064e, 0x10ece, 0x11ea0, 0x18f58, 0x1c7ae, 0x11e90, 0x18f4c, 0x11e88, 0x18f46, 0x11e84, 0x11e82, 0x10e58, 0x1872e, 0x11ed8, 0x18f6e, 0x11ecc, 0x10e46, 0x11ec6, 0x1062e, 0x10e6e, 0x11eee, 0x19f50, 0x1cfac, 0x19f48, 0x1cfa6, 0x19f44, 0x19f42, 0x11e50, 0x18f2c, 0x13ed0, 0x19f6c, 0x18f26, 0x13ec8, 0x11e44, 0x13ec4, 0x11e42, 0x13ec2, 0x10e2c, 0x11e6c, 0x10e26, 0x13eec, 0x11e66, 0x13ee6, 0x1dfa8, 0x1efd6, 0x1dfa4, 0x1dfa2, 0x19f28, 0x1cf96, 0x1bf68, 0x19f24, 0x1bf64, 0x19f22, 0x1bf62, 0x11e28, 0x18f16, 0x13e68, 0x11e24, 0x17ee8, 0x13e64, 0x11e22, 0x17ee4, 0x13e62, 0x17ee2, 0x10e16, 0x11e36, 0x13e76, 0x17ef6, 0x1df94, 0x1df92, 0x19f14, 0x1bf34, 0x19f12, 0x1bf32, 0x11e14, 0x13e34, 0x11e12, 0x17e74, 0x13e32, 0x17e72, 0x1df8a, 0x19f0a, 0x1bf1a, 0x11e0a, 0x13e1a, 0x17e3a, 0x1035c, 0x1034e, 0x10758, 0x183ae, 0x1074c, 0x10746, 0x1032e, 0x1076e, 0x10f50, 0x187ac, 0x10f48, 0x187a6, 0x10f44, 0x10f42, 0x1072c, 0x10f6c, 0x10726, 0x10f66, 0x18fa8, 0x1c7d6, 0x18fa4, 0x18fa2, 0x10f28, 0x18796, 0x11f68, 0x18fb6, 0x11f64, 0x10f22, 0x11f62, 0x10716, 0x10f36, 0x11f76, 0x1cfd4, 0x1cfd2, 0x18f94, 0x19fb4, 0x18f92, 0x19fb2, 0x10f14, 0x11f34, 0x10f12, 0x13f74, 0x11f32, 0x13f72, 0x1cfca, 0x18f8a, 0x19f9a, 0x10f0a, 0x11f1a, 0x13f3a, 0x103ac, 0x103a6, 0x107a8, 0x183d6, 0x107a4, 0x107a2, 0x10396, 0x107b6, 0x187d4, 0x187d2, 0x10794, 0x10fb4, 0x10792, 0x10fb2, 0x1c7ea, ] +, ] +; + + const PREFERRED_RATIO: f32 = 3.0f; + +//1px in mm + const DEFAULT_MODULE_WIDTH: f32 = 0.357f; + +//mm + const HEIGHT: f32 = 2.0f; +pub struct PDF417 { + + let barcode_matrix: BarcodeMatrix; + + let compact: bool; + + let mut compaction: Compaction; + + let mut encoding: Charset; + + let min_cols: i32; + + let max_cols: i32; + + let max_rows: i32; + + let min_rows: i32; +} + +impl PDF417 { + + pub fn new() -> PDF417 { + this(false); + } + + pub fn new( compact: bool) -> PDF417 { + let .compact = compact; + compaction = Compaction::AUTO; + // Use default + encoding = null; + min_cols = 2; + max_cols = 30; + max_rows = 30; + min_rows = 2; + } + + pub fn get_barcode_matrix(&self) -> BarcodeMatrix { + return self.barcode_matrix; + } + + /** + * Calculates the necessary number of rows as described in annex Q of ISO/IEC 15438:2001(E). + * + * @param m the number of source codewords prior to the additional of the Symbol Length + * Descriptor and any pad codewords + * @param k the number of error correction codewords + * @param c the number of columns in the symbol in the data region (excluding start, stop and + * row indicator codewords) + * @return the number of rows in the symbol (r) + */ + fn calculate_number_of_rows( m: i32, k: i32, c: i32) -> i32 { + let mut r: i32 = ((m + 1 + k) / c) + 1; + if c * r >= (m + 1 + k + c) { + r -= 1; + } + return r; + } + + /** + * Calculates the number of pad codewords as described in 4.9.2 of ISO/IEC 15438:2001(E). + * + * @param m the number of source codewords prior to the additional of the Symbol Length + * Descriptor and any pad codewords + * @param k the number of error correction codewords + * @param c the number of columns in the symbol in the data region (excluding start, stop and + * row indicator codewords) + * @param r the number of rows in the symbol + * @return the number of pad codewords + */ + fn get_number_of_pad_codewords( m: i32, k: i32, c: i32, r: i32) -> i32 { + let n: i32 = c * r - k; + return if n > m + 1 { n - m - 1 } else { 0 }; + } + + fn encode_char( pattern: i32, len: i32, logic: &BarcodeRow) { + let mut map: i32 = 1 << len - 1; + //Initialize to inverse of first bit + let mut last: bool = (pattern & map) != 0; + let mut width: i32 = 0; + { + let mut i: i32 = 0; + while i < len { + { + let black: bool = (pattern & map) != 0; + if last == black { + width += 1; + } else { + logic.add_bar(last, width); + last = black; + width = 1; + } + map >>= 1; + } + i += 1; + } + } + + logic.add_bar(last, width); + } + + fn encode_low_level(&self, full_codewords: &CharSequence, c: i32, r: i32, error_correction_level: i32, logic: &BarcodeMatrix) { + let mut idx: i32 = 0; + { + let mut y: i32 = 0; + while y < r { + { + let cluster: i32 = y % 3; + logic.start_row(); + ::encode_char(START_PATTERN, 17, &logic.get_current_row()); + let mut left: i32; + let mut right: i32; + if cluster == 0 { + left = (30 * (y / 3)) + ((r - 1) / 3); + right = (30 * (y / 3)) + (c - 1); + } else if cluster == 1 { + left = (30 * (y / 3)) + (error_correction_level * 3) + ((r - 1) % 3); + right = (30 * (y / 3)) + ((r - 1) / 3); + } else { + left = (30 * (y / 3)) + (c - 1); + right = (30 * (y / 3)) + (error_correction_level * 3) + ((r - 1) % 3); + } + let mut pattern: i32 = CODEWORD_TABLE[cluster][left]; + ::encode_char(pattern, 17, &logic.get_current_row()); + { + let mut x: i32 = 0; + while x < c { + { + pattern = CODEWORD_TABLE[cluster][full_codewords.char_at(idx)]; + ::encode_char(pattern, 17, &logic.get_current_row()); + idx += 1; + } + x += 1; + } + } + + if self.compact { + // encodes stop line for compact pdf417 + ::encode_char(STOP_PATTERN, 1, &logic.get_current_row()); + } else { + pattern = CODEWORD_TABLE[cluster][right]; + ::encode_char(pattern, 17, &logic.get_current_row()); + ::encode_char(STOP_PATTERN, 18, &logic.get_current_row()); + } + } + y += 1; + } + } + + } + + /** + * @param msg message to encode + * @param errorCorrectionLevel PDF417 error correction level to use + * @throws WriterException if the contents cannot be encoded in this format + */ + pub fn generate_barcode_logic(&self, msg: &String, error_correction_level: i32) -> /* throws WriterException */Result> { + self.generate_barcode_logic(&msg, error_correction_level, false); + } + + /** + * @param msg message to encode + * @param errorCorrectionLevel PDF417 error correction level to use + * @param autoECI automatically insert ECIs if needed + * @throws WriterException if the contents cannot be encoded in this format + */ + pub fn generate_barcode_logic(&self, msg: &String, error_correction_level: i32, auto_e_c_i: bool) -> /* throws WriterException */Result> { + //1. step: High-level encoding + let error_correction_code_words: i32 = PDF417ErrorCorrection::get_error_correction_codeword_count(error_correction_level); + let high_level: String = PDF417HighLevelEncoder::encode_high_level(&msg, self.compaction, &self.encoding, auto_e_c_i); + let source_code_words: i32 = high_level.length(); + let dimension: Vec = self.determine_dimensions(source_code_words, error_correction_code_words); + let cols: i32 = dimension[0]; + let rows: i32 = dimension[1]; + let pad: i32 = ::get_number_of_pad_codewords(source_code_words, error_correction_code_words, cols, rows); + //2. step: construct data codewords + if source_code_words + error_correction_code_words + 1 > 929 { + // +1 for symbol length CW + throw WriterException::new(format!("Encoded message contains too many code words, message too big ({} bytes)", msg.length())); + } + let n: i32 = source_code_words + pad + 1; + let sb: StringBuilder = StringBuilder::new(n); + sb.append(n as char); + sb.append(&high_level); + { + let mut i: i32 = 0; + while i < pad { + { + //PAD characters + sb.append(900 as char); + } + i += 1; + } + } + + let data_codewords: String = sb.to_string(); + //3. step: Error correction + let ec: String = PDF417ErrorCorrection::generate_error_correction(&data_codewords, error_correction_level); + //4. step: low-level encoding + self.barcode_matrix = BarcodeMatrix::new(rows, cols); + self.encode_low_level(format!("{}{}", data_codewords, ec), cols, rows, error_correction_level, self.barcode_matrix); + } + + /** + * Determine optimal nr of columns and rows for the specified number of + * codewords. + * + * @param sourceCodeWords number of code words + * @param errorCorrectionCodeWords number of error correction code words + * @return dimension object containing cols as width and rows as height + */ + fn determine_dimensions(&self, source_code_words: i32, error_correction_code_words: i32) -> /* throws WriterException */Result, Rc> { + let mut ratio: f32 = 0.0f; + let mut dimension: Vec = null; + { + let mut cols: i32 = self.min_cols; + while cols <= self.max_cols { + { + let rows: i32 = ::calculate_number_of_rows(source_code_words, error_correction_code_words, cols); + if rows < self.min_rows { + break; + } + if rows > self.max_rows { + continue; + } + let new_ratio: f32 = ((17.0 * cols + 69.0) as f32 * DEFAULT_MODULE_WIDTH) / (rows * HEIGHT); + // ignore if previous ratio is closer to preferred ratio + if dimension != null && Math::abs(new_ratio - PREFERRED_RATIO) > Math::abs(ratio - PREFERRED_RATIO) { + continue; + } + ratio = new_ratio; + dimension = : vec![i32; 2] = vec![cols, rows, ] + ; + } + cols += 1; + } + } + + // Handle case when min values were larger than necessary + if dimension == null { + let rows: i32 = ::calculate_number_of_rows(source_code_words, error_correction_code_words, self.min_cols); + if rows < self.min_rows { + dimension = : vec![i32; 2] = vec![self.min_cols, self.min_rows, ] + ; + } + } + if dimension == null { + throw WriterException::new("Unable to fit message in columns"); + } + return Ok(dimension); + } + + /** + * Sets max/min row/col values + * + * @param maxCols maximum allowed columns + * @param minCols minimum allowed columns + * @param maxRows maximum allowed rows + * @param minRows minimum allowed rows + */ + pub fn set_dimensions(&self, max_cols: i32, min_cols: i32, max_rows: i32, min_rows: i32) { + self.maxCols = max_cols; + self.minCols = min_cols; + self.maxRows = max_rows; + self.minRows = min_rows; + } + + /** + * @param compaction compaction mode to use + */ + pub fn set_compaction(&self, compaction: &Compaction) { + self.compaction = compaction; + } + + /** + * @param compact if true, enables compaction + */ + pub fn set_compact(&self, compact: bool) { + self.compact = compact; + } + + /** + * @param encoding sets character encoding to use + */ + pub fn set_encoding(&self, encoding: &Charset) { + self.encoding = encoding; + } +} + +// NEW FILE: p_d_f417_error_correction.rs +/* + * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part + * + * 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::pdf417::encoder; + +/** + * PDF417 error correction code following the algorithm described in ISO/IEC 15438:2001(E) in + * chapter 4.10. + */ + +/** + * Tables of coefficients for calculating error correction words + * (see annex F, ISO/IEC 15438:2001(E)) + */ + const EC_COEFFICIENTS: vec![vec![Vec>; 512]; 9] = vec![vec![27, 917, ] +, vec![522, 568, 723, 809, ] +, vec![237, 308, 436, 284, 646, 653, 428, 379, ] +, vec![274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, 42, 176, 65, ] +, vec![361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410, ] +, vec![539, 422, 6, 93, 862, 771, 453, 106, 610, 287, 107, 505, 733, 877, 381, 612, 723, 476, 462, 172, 430, 609, 858, 822, 543, 376, 511, 400, 672, 762, 283, 184, 440, 35, 519, 31, 460, 594, 225, 535, 517, 352, 605, 158, 651, 201, 488, 502, 648, 733, 717, 83, 404, 97, 280, 771, 840, 629, 4, 381, 843, 623, 264, 543, ] +, vec![521, 310, 864, 547, 858, 580, 296, 379, 53, 779, 897, 444, 400, 925, 749, 415, 822, 93, 217, 208, 928, 244, 583, 620, 246, 148, 447, 631, 292, 908, 490, 704, 516, 258, 457, 907, 594, 723, 674, 292, 272, 96, 684, 432, 686, 606, 860, 569, 193, 219, 129, 186, 236, 287, 192, 775, 278, 173, 40, 379, 712, 463, 646, 776, 171, 491, 297, 763, 156, 732, 95, 270, 447, 90, 507, 48, 228, 821, 808, 898, 784, 663, 627, 378, 382, 262, 380, 602, 754, 336, 89, 614, 87, 432, 670, 616, 157, 374, 242, 726, 600, 269, 375, 898, 845, 454, 354, 130, 814, 587, 804, 34, 211, 330, 539, 297, 827, 865, 37, 517, 834, 315, 550, 86, 801, 4, 108, 539, ] +, vec![524, 894, 75, 766, 882, 857, 74, 204, 82, 586, 708, 250, 905, 786, 138, 720, 858, 194, 311, 913, 275, 190, 375, 850, 438, 733, 194, 280, 201, 280, 828, 757, 710, 814, 919, 89, 68, 569, 11, 204, 796, 605, 540, 913, 801, 700, 799, 137, 439, 418, 592, 668, 353, 859, 370, 694, 325, 240, 216, 257, 284, 549, 209, 884, 315, 70, 329, 793, 490, 274, 877, 162, 749, 812, 684, 461, 334, 376, 849, 521, 307, 291, 803, 712, 19, 358, 399, 908, 103, 511, 51, 8, 517, 225, 289, 470, 637, 731, 66, 255, 917, 269, 463, 830, 730, 433, 848, 585, 136, 538, 906, 90, 2, 290, 743, 199, 655, 903, 329, 49, 802, 580, 355, 588, 188, 462, 10, 134, 628, 320, 479, 130, 739, 71, 263, 318, 374, 601, 192, 605, 142, 673, 687, 234, 722, 384, 177, 752, 607, 640, 455, 193, 689, 707, 805, 641, 48, 60, 732, 621, 895, 544, 261, 852, 655, 309, 697, 755, 756, 60, 231, 773, 434, 421, 726, 528, 503, 118, 49, 795, 32, 144, 500, 238, 836, 394, 280, 566, 319, 9, 647, 550, 73, 914, 342, 126, 32, 681, 331, 792, 620, 60, 609, 441, 180, 791, 893, 754, 605, 383, 228, 749, 760, 213, 54, 297, 134, 54, 834, 299, 922, 191, 910, 532, 609, 829, 189, 20, 167, 29, 872, 449, 83, 402, 41, 656, 505, 579, 481, 173, 404, 251, 688, 95, 497, 555, 642, 543, 307, 159, 924, 558, 648, 55, 497, 10, ] +, vec![352, 77, 373, 504, 35, 599, 428, 207, 409, 574, 118, 498, 285, 380, 350, 492, 197, 265, 920, 155, 914, 299, 229, 643, 294, 871, 306, 88, 87, 193, 352, 781, 846, 75, 327, 520, 435, 543, 203, 666, 249, 346, 781, 621, 640, 268, 794, 534, 539, 781, 408, 390, 644, 102, 476, 499, 290, 632, 545, 37, 858, 916, 552, 41, 542, 289, 122, 272, 383, 800, 485, 98, 752, 472, 761, 107, 784, 860, 658, 741, 290, 204, 681, 407, 855, 85, 99, 62, 482, 180, 20, 297, 451, 593, 913, 142, 808, 684, 287, 536, 561, 76, 653, 899, 729, 567, 744, 390, 513, 192, 516, 258, 240, 518, 794, 395, 768, 848, 51, 610, 384, 168, 190, 826, 328, 596, 786, 303, 570, 381, 415, 641, 156, 237, 151, 429, 531, 207, 676, 710, 89, 168, 304, 402, 40, 708, 575, 162, 864, 229, 65, 861, 841, 512, 164, 477, 221, 92, 358, 785, 288, 357, 850, 836, 827, 736, 707, 94, 8, 494, 114, 521, 2, 499, 851, 543, 152, 729, 771, 95, 248, 361, 578, 323, 856, 797, 289, 51, 684, 466, 533, 820, 669, 45, 902, 452, 167, 342, 244, 173, 35, 463, 651, 51, 699, 591, 452, 578, 37, 124, 298, 332, 552, 43, 427, 119, 662, 777, 475, 850, 764, 364, 578, 911, 283, 711, 472, 420, 245, 288, 594, 394, 511, 327, 589, 777, 699, 688, 43, 408, 842, 383, 721, 521, 560, 644, 714, 559, 62, 145, 873, 663, 713, 159, 672, 729, 624, 59, 193, 417, 158, 209, 563, 564, 343, 693, 109, 608, 563, 365, 181, 772, 677, 310, 248, 353, 708, 410, 579, 870, 617, 841, 632, 860, 289, 536, 35, 777, 618, 586, 424, 833, 77, 597, 346, 269, 757, 632, 695, 751, 331, 247, 184, 45, 787, 680, 18, 66, 407, 369, 54, 492, 228, 613, 830, 922, 437, 519, 644, 905, 789, 420, 305, 441, 207, 300, 892, 827, 141, 537, 381, 662, 513, 56, 252, 341, 242, 797, 838, 837, 720, 224, 307, 631, 61, 87, 560, 310, 756, 665, 397, 808, 851, 309, 473, 795, 378, 31, 647, 915, 459, 806, 590, 731, 425, 216, 548, 249, 321, 881, 699, 535, 673, 782, 210, 815, 905, 303, 843, 922, 281, 73, 469, 791, 660, 162, 498, 308, 155, 422, 907, 817, 187, 62, 16, 425, 535, 336, 286, 437, 375, 273, 610, 296, 183, 923, 116, 667, 751, 353, 62, 366, 691, 379, 687, 842, 37, 357, 720, 742, 330, 5, 39, 923, 311, 424, 242, 749, 321, 54, 669, 316, 342, 299, 534, 105, 667, 488, 640, 672, 576, 540, 316, 486, 721, 610, 46, 656, 447, 171, 616, 464, 190, 531, 297, 321, 762, 752, 533, 175, 134, 14, 381, 433, 717, 45, 111, 20, 596, 284, 736, 138, 646, 411, 877, 669, 141, 919, 45, 780, 407, 164, 332, 899, 165, 726, 600, 325, 498, 655, 357, 752, 768, 223, 849, 647, 63, 310, 863, 251, 366, 304, 282, 738, 675, 410, 389, 244, 31, 121, 303, 263, ] +, ] +; +struct PDF417ErrorCorrection { +} + +impl PDF417ErrorCorrection { + + fn new() -> PDF417ErrorCorrection { + } + + /** + * Determines the number of error correction codewords for a specified error correction + * level. + * + * @param errorCorrectionLevel the error correction level (0-8) + * @return the number of codewords generated for error correction + */ + fn get_error_correction_codeword_count( error_correction_level: i32) -> i32 { + if error_correction_level < 0 || error_correction_level > 8 { + throw IllegalArgumentException::new("Error correction level must be between 0 and 8!"); + } + return 1 << (error_correction_level + 1); + } + + /** + * Returns the recommended minimum error correction level as described in annex E of + * ISO/IEC 15438:2001(E). + * + * @param n the number of data codewords + * @return the recommended minimum error correction level + */ + fn get_recommended_minimum_error_correction_level( n: i32) -> /* throws WriterException */Result> { + if n <= 0 { + throw IllegalArgumentException::new("n must be > 0"); + } + if n <= 40 { + return Ok(2); + } + if n <= 160 { + return Ok(3); + } + if n <= 320 { + return Ok(4); + } + if n <= 863 { + return Ok(5); + } + throw WriterException::new("No recommendation possible"); + } + + /** + * Generates the error correction codewords according to 4.10 in ISO/IEC 15438:2001(E). + * + * @param dataCodewords the data codewords + * @param errorCorrectionLevel the error correction level (0-8) + * @return the String representing the error correction codewords + */ + fn generate_error_correction( data_codewords: &CharSequence, error_correction_level: i32) -> String { + let k: i32 = ::get_error_correction_codeword_count(error_correction_level); + let mut e: [Option; k] = [None; k]; + let sld: i32 = data_codewords.length(); + { + let mut i: i32 = 0; + while i < sld { + { + let t1: i32 = (data_codewords.char_at(i) + e[e.len() - 1]) % 929; + let mut t2: i32; + let mut t3: i32; + { + let mut j: i32 = k - 1; + while j >= 1 { + { + t2 = (t1 * EC_COEFFICIENTS[error_correction_level][j]) % 929; + t3 = 929 - t2; + e[j] = ((e[j - 1] + t3) % 929) as char; + } + j -= 1; + } + } + + t2 = (t1 * EC_COEFFICIENTS[error_correction_level][0]) % 929; + t3 = 929 - t2; + e[0] = (t3 % 929) as char; + } + i += 1; + } + } + + let sb: StringBuilder = StringBuilder::new(k); + { + let mut j: i32 = k - 1; + while j >= 0 { + { + if e[j] != 0 { + e[j] = (929 - e[j]) as char; + } + sb.append(e[j]); + } + j -= 1; + } + } + + return sb.to_string(); + } +} + +// NEW FILE: p_d_f417_high_level_encoder.rs +/* + * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part + * + * 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::pdf417::encoder; + +/** + * PDF417 high-level encoder following the algorithm described in ISO/IEC 15438:2001(E) in + * annex P. + */ + +/** + * code for Text compaction + */ + const TEXT_COMPACTION: i32 = 0; + +/** + * code for Byte compaction + */ + const BYTE_COMPACTION: i32 = 1; + +/** + * code for Numeric compaction + */ + const NUMERIC_COMPACTION: i32 = 2; + +/** + * Text compaction submode Alpha + */ + const SUBMODE_ALPHA: i32 = 0; + +/** + * Text compaction submode Lower + */ + const SUBMODE_LOWER: i32 = 1; + +/** + * Text compaction submode Mixed + */ + const SUBMODE_MIXED: i32 = 2; + +/** + * Text compaction submode Punctuation + */ + const SUBMODE_PUNCTUATION: i32 = 3; + +/** + * mode latch to Text Compaction mode + */ + const LATCH_TO_TEXT: i32 = 900; + +/** + * mode latch to Byte Compaction mode (number of characters NOT a multiple of 6) + */ + const LATCH_TO_BYTE_PADDED: i32 = 901; + +/** + * mode latch to Numeric Compaction mode + */ + const LATCH_TO_NUMERIC: i32 = 902; + +/** + * mode shift to Byte Compaction mode + */ + const SHIFT_TO_BYTE: i32 = 913; + +/** + * mode latch to Byte Compaction mode (number of characters a multiple of 6) + */ + const LATCH_TO_BYTE: i32 = 924; + +/** + * identifier for a user defined Extended Channel Interpretation (ECI) + */ + const ECI_USER_DEFINED: i32 = 925; + +/** + * identifier for a general purpose ECO format + */ + const ECI_GENERAL_PURPOSE: i32 = 926; + +/** + * identifier for an ECI of a character set of code page + */ + const ECI_CHARSET: i32 = 927; + +/** + * Raw code table for text compaction Mixed sub-mode + */ + const TEXT_MIXED_RAW: vec![Vec; 30] = vec![48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 38, 13, 9, 44, 58, 35, 45, 46, 36, 47, 43, 37, 42, 61, 94, 0, 32, 0, 0, 0, ] +; + +/** + * Raw code table for text compaction: Punctuation sub-mode + */ + const TEXT_PUNCTUATION_RAW: vec![Vec; 30] = vec![59, 60, 62, 64, 91, 92, 93, 95, 96, 126, 33, 13, 9, 44, 58, 10, 45, 46, 36, 47, 34, 124, 42, 40, 41, 63, 123, 125, 39, 0, ] +; + + const MIXED: [i8; 128] = [0; 128]; + + const PUNCTUATION: [i8; 128] = [0; 128]; + + const DEFAULT_ENCODING: Charset = StandardCharsets::ISO_8859_1; +struct PDF417HighLevelEncoder { +} + +impl PDF417HighLevelEncoder { + + fn new() -> PDF417HighLevelEncoder { + } + + static { + //Construct inverse lookups + Arrays::fill(&MIXED, -1 as i8); + { + let mut i: i32 = 0; + while i < TEXT_MIXED_RAW.len() { + { + let mut b: i8 = TEXT_MIXED_RAW[i]; + if b > 0 { + MIXED[b] = i as i8; + } + } + i += 1; + } + } + + Arrays::fill(&PUNCTUATION, -1 as i8); + { + let mut i: i32 = 0; + while i < TEXT_PUNCTUATION_RAW.len() { + { + let mut b: i8 = TEXT_PUNCTUATION_RAW[i]; + if b > 0 { + PUNCTUATION[b] = i as i8; + } + } + i += 1; + } + } + + } + + /** + * Performs high-level encoding of a PDF417 message using the algorithm described in annex P + * of ISO/IEC 15438:2001(E). If byte compaction has been selected, then only byte compaction + * is used. + * + * @param msg the message + * @param compaction compaction mode to use + * @param encoding character encoding used to encode in default or byte compaction + * or {@code null} for default / not applicable + * @param autoECI encode input minimally using multiple ECIs if needed + * If autoECI encoding is specified and additionally {@code encoding} is specified, then the encoder + * will use the specified {@link Charset} for any character that can be encoded by it, regardless + * if a different encoding would lead to a more compact encoding. When no {@code encoding} is specified + * then charsets will be chosen so that the byte representation is minimal. + * @return the encoded message (the char values range from 0 to 928) + */ + fn encode_high_level( msg: &String, compaction: &Compaction, encoding: &Charset, auto_e_c_i: bool) -> /* throws WriterException */Result> { + if msg.is_empty() { + throw WriterException::new("Empty message not allowed"); + } + if encoding == null && !auto_e_c_i { + { + let mut i: i32 = 0; + while i < msg.length() { + { + if msg.char_at(i) > 255 { + throw WriterException::new(format!("Non-encodable character detected: {} (Unicode: {}). Consider specifying EncodeHintType.PDF417_AUTO_ECI and/or EncodeTypeHint.CHARACTER_SET.", msg.char_at(i), msg.char_at(i) as i32)); + } + } + i += 1; + } + } + + } + //the codewords 0..928 are encoded as Unicode characters + let sb: StringBuilder = StringBuilder::new(&msg.length()); + let mut input: ECIInput; + if auto_e_c_i { + input = MinimalECIInput::new(&msg, &encoding, -1); + } else { + input = NoECIInput::new(&msg); + if encoding == null { + encoding = DEFAULT_ENCODING; + } else if !DEFAULT_ENCODING::equals(&encoding) { + let eci: CharacterSetECI = CharacterSetECI::get_character_set_e_c_i(&encoding); + if eci != null { + ::encoding_e_c_i(&eci.get_value(), &sb); + } + } + } + let len: i32 = input.length(); + let mut p: i32 = 0; + let text_sub_mode: i32 = SUBMODE_ALPHA; + // User selected encoding mode + match compaction { + TEXT => + { + ::encode_text(input, p, len, &sb, text_sub_mode); + break; + } + BYTE => + { + if auto_e_c_i { + ::encode_multi_e_c_i_binary(input, 0, &input.length(), TEXT_COMPACTION, &sb); + } else { + let msg_bytes: Vec = input.to_string().get_bytes(&encoding); + ::encode_binary(&msg_bytes, p, msg_bytes.len(), BYTE_COMPACTION, &sb); + } + break; + } + NUMERIC => + { + sb.append(LATCH_TO_NUMERIC as char); + ::encode_numeric(input, p, len, &sb); + break; + } + _ => + { + //Default mode, see 4.4.2.1 + let encoding_mode: i32 = TEXT_COMPACTION; + while p < len { + while p < len && input.is_e_c_i(p) { + ::encoding_e_c_i(&input.get_e_c_i_value(p), &sb); + p += 1; + } + if p >= len { + break; + } + let n: i32 = ::determine_consecutive_digit_count(input, p); + if n >= 13 { + sb.append(LATCH_TO_NUMERIC as char); + encoding_mode = NUMERIC_COMPACTION; + //Reset after latch + text_sub_mode = SUBMODE_ALPHA; + ::encode_numeric(input, p, n, &sb); + p += n; + } else { + let t: i32 = ::determine_consecutive_text_count(input, p); + if t >= 5 || n == len { + if encoding_mode != TEXT_COMPACTION { + sb.append(LATCH_TO_TEXT as char); + encoding_mode = TEXT_COMPACTION; + //start with submode alpha after latch + text_sub_mode = SUBMODE_ALPHA; + } + text_sub_mode = ::encode_text(input, p, t, &sb, text_sub_mode); + p += t; + } else { + let mut b: i32 = ::determine_consecutive_binary_count(input, p, if auto_e_c_i { null } else { encoding }); + if b == 0 { + b = 1; + } + let bytes: Vec = if auto_e_c_i { null } else { input.sub_sequence(p, p + b).to_string().get_bytes(&encoding) }; + if ((bytes == null && b == 1) || (bytes != null && bytes.len() == 1)) && encoding_mode == TEXT_COMPACTION { + //Switch for one byte (instead of latch) + if auto_e_c_i { + ::encode_multi_e_c_i_binary(input, p, 1, TEXT_COMPACTION, &sb); + } else { + ::encode_binary(&bytes, 0, 1, TEXT_COMPACTION, &sb); + } + } else { + //Mode latch performed by encodeBinary() + if auto_e_c_i { + ::encode_multi_e_c_i_binary(input, p, p + b, encoding_mode, &sb); + } else { + ::encode_binary(&bytes, 0, bytes.len(), encoding_mode, &sb); + } + encoding_mode = BYTE_COMPACTION; + //Reset after latch + text_sub_mode = SUBMODE_ALPHA; + } + p += b; + } + } + } + break; + } + } + return Ok(sb.to_string()); + } + + /** + * Encode parts of the message using Text Compaction as described in ISO/IEC 15438:2001(E), + * chapter 4.4.2. + * + * @param input the input + * @param startpos the start position within the message + * @param count the number of characters to encode + * @param sb receives the encoded codewords + * @param initialSubmode should normally be SUBMODE_ALPHA + * @return the text submode in which this method ends + */ + fn encode_text( input: &ECIInput, startpos: i32, count: i32, sb: &StringBuilder, initial_submode: i32) -> /* throws WriterException */Result> { + let tmp: StringBuilder = StringBuilder::new(count); + let mut submode: i32 = initial_submode; + let mut idx: i32 = 0; + while true { + if input.is_e_c_i(startpos + idx) { + ::encoding_e_c_i(&input.get_e_c_i_value(startpos + idx), &sb); + idx += 1; + } else { + let ch: char = input.char_at(startpos + idx); + match submode { + SUBMODE_ALPHA => + { + if ::is_alpha_upper(ch) { + if ch == ' ' { + //space + tmp.append(26 as char); + } else { + tmp.append((ch - 65) as char); + } + } else { + if ::is_alpha_lower(ch) { + submode = SUBMODE_LOWER; + //ll + tmp.append(27 as char); + continue; + } else if ::is_mixed(ch) { + submode = SUBMODE_MIXED; + //ml + tmp.append(28 as char); + continue; + } else { + //ps + tmp.append(29 as char); + tmp.append(PUNCTUATION[ch] as char); + break; + } + } + break; + } + SUBMODE_LOWER => + { + if ::is_alpha_lower(ch) { + if ch == ' ' { + //space + tmp.append(26 as char); + } else { + tmp.append((ch - 97) as char); + } + } else { + if ::is_alpha_upper(ch) { + //as + tmp.append(27 as char); + tmp.append((ch - 65) as char); + //space cannot happen here, it is also in "Lower" + break; + } else if ::is_mixed(ch) { + submode = SUBMODE_MIXED; + //ml + tmp.append(28 as char); + continue; + } else { + //ps + tmp.append(29 as char); + tmp.append(PUNCTUATION[ch] as char); + break; + } + } + break; + } + SUBMODE_MIXED => + { + if ::is_mixed(ch) { + tmp.append(MIXED[ch] as char); + } else { + if ::is_alpha_upper(ch) { + submode = SUBMODE_ALPHA; + //al + tmp.append(28 as char); + continue; + } else if ::is_alpha_lower(ch) { + submode = SUBMODE_LOWER; + //ll + tmp.append(27 as char); + continue; + } else { + if startpos + idx + 1 < count { + if !input.is_e_c_i(startpos + idx + 1) && ::is_punctuation(&input.char_at(startpos + idx + 1)) { + submode = SUBMODE_PUNCTUATION; + //pl + tmp.append(25 as char); + continue; + } + } + //ps + tmp.append(29 as char); + tmp.append(PUNCTUATION[ch] as char); + } + } + break; + } + _ => + { + //SUBMODE_PUNCTUATION + if ::is_punctuation(ch) { + tmp.append(PUNCTUATION[ch] as char); + } else { + submode = SUBMODE_ALPHA; + //al + tmp.append(29 as char); + continue; + } + } + } + idx += 1; + if idx >= count { + break; + } + } + } + let mut h: char = 0; + let len: i32 = tmp.length(); + { + let mut i: i32 = 0; + while i < len { + { + let odd: bool = (i % 2) != 0; + if odd { + h = ((h * 30) + tmp.char_at(i)) as char; + sb.append(h); + } else { + h = tmp.char_at(i); + } + } + i += 1; + } + } + + if (len % 2) != 0 { + //ps + sb.append(((h * 30) + 29) as char); + } + return Ok(submode); + } + + /** + * Encode all of the message using Byte Compaction as described in ISO/IEC 15438:2001(E) + * + * @param input the input + * @param startpos the start position within the message + * @param count the number of bytes to encode + * @param startmode the mode from which this method starts + * @param sb receives the encoded codewords + */ + fn encode_multi_e_c_i_binary( input: &ECIInput, startpos: i32, count: i32, startmode: i32, sb: &StringBuilder) -> /* throws WriterException */Result> { + let end: i32 = Math::min(startpos + count, &input.length()); + let local_start: i32 = startpos; + while true { + //encode all leading ECIs and advance localStart + while local_start < end && input.is_e_c_i(local_start) { + ::encoding_e_c_i(&input.get_e_c_i_value(local_start), &sb); + local_start += 1; + } + let local_end: i32 = local_start; + //advance end until before the next ECI + while local_end < end && !input.is_e_c_i(local_end) { + local_end += 1; + } + let local_count: i32 = local_end - local_start; + if local_count <= 0 { + //done + break; + } else { + //encode the segment + ::encode_binary(&::sub_bytes(input, local_start, local_end), 0, local_count, if local_start == startpos { startmode } else { BYTE_COMPACTION }, &sb); + local_start = local_end; + } + } + } + + fn sub_bytes( input: &ECIInput, start: i32, end: i32) -> Vec { + let count: i32 = end - start; + let mut result: [i8; count] = [0; count]; + { + let mut i: i32 = start; + while i < end { + { + result[i - start] = (input.char_at(i) & 0xff) as i8; + } + i += 1; + } + } + + return result; + } + + /** + * Encode parts of the message using Byte Compaction as described in ISO/IEC 15438:2001(E), + * chapter 4.4.3. The Unicode characters will be converted to binary using the cp437 + * codepage. + * + * @param bytes the message converted to a byte array + * @param startpos the start position within the message + * @param count the number of bytes to encode + * @param startmode the mode from which this method starts + * @param sb receives the encoded codewords + */ + fn encode_binary( bytes: &Vec, startpos: i32, count: i32, startmode: i32, sb: &StringBuilder) { + if count == 1 && startmode == TEXT_COMPACTION { + sb.append(SHIFT_TO_BYTE as char); + } else { + if (count % 6) == 0 { + sb.append(LATCH_TO_BYTE as char); + } else { + sb.append(LATCH_TO_BYTE_PADDED as char); + } + } + let mut idx: i32 = startpos; + // Encode sixpacks + if count >= 6 { + let mut chars: [Option; 5] = [None; 5]; + while (startpos + count - idx) >= 6 { + let mut t: i64 = 0; + { + let mut i: i32 = 0; + while i < 6 { + { + t <<= 8; + t += bytes[idx + i] & 0xff; + } + i += 1; + } + } + + { + let mut i: i32 = 0; + while i < 5 { + { + chars[i] = (t % 900) as char; + t /= 900; + } + i += 1; + } + } + + { + let mut i: i32 = chars.len() - 1; + while i >= 0 { + { + sb.append(chars[i]); + } + i -= 1; + } + } + + idx += 6; + } + } + //Encode rest (remaining n<5 bytes if any) + { + let mut i: i32 = idx; + while i < startpos + count { + { + let ch: i32 = bytes[i] & 0xff; + sb.append(ch as char); + } + i += 1; + } + } + + } + + fn encode_numeric( input: &ECIInput, startpos: i32, count: i32, sb: &StringBuilder) { + let mut idx: i32 = 0; + let tmp: StringBuilder = StringBuilder::new(count / 3 + 1); + let num900: BigInteger = BigInteger::value_of(900); + let num0: BigInteger = BigInteger::value_of(0); + while idx < count { + tmp.set_length(0); + let len: i32 = Math::min(44, count - idx); + let part: String = format!("1{}", input.sub_sequence(startpos + idx, startpos + idx + len)); + let mut bigint: BigInteger = BigInteger::new(&part); + loop { { + tmp.append(bigint.mod(&num900).int_value() as char); + bigint = bigint.divide(&num900); + }if !(!bigint.equals(&num0)) break;} + //Reverse temporary string + { + let mut i: i32 = tmp.length() - 1; + while i >= 0 { + { + sb.append(&tmp.char_at(i)); + } + i -= 1; + } + } + + idx += len; + } + } + + fn is_digit( ch: char) -> bool { + return ch >= '0' && ch <= '9'; + } + + fn is_alpha_upper( ch: char) -> bool { + return ch == ' ' || (ch >= 'A' && ch <= 'Z'); + } + + fn is_alpha_lower( ch: char) -> bool { + return ch == ' ' || (ch >= 'a' && ch <= 'z'); + } + + fn is_mixed( ch: char) -> bool { + return MIXED[ch] != -1; + } + + fn is_punctuation( ch: char) -> bool { + return PUNCTUATION[ch] != -1; + } + + fn is_text( ch: char) -> bool { + return ch == '\t' || ch == '\n' || ch == '\r' || (ch >= 32 && ch <= 126); + } + + /** + * Determines the number of consecutive characters that are encodable using numeric compaction. + * + * @param input the input + * @param startpos the start position within the input + * @return the requested character count + */ + fn determine_consecutive_digit_count( input: &ECIInput, startpos: i32) -> i32 { + let mut count: i32 = 0; + let len: i32 = input.length(); + let mut idx: i32 = startpos; + if idx < len { + while idx < len && !input.is_e_c_i(idx) && ::is_digit(&input.char_at(idx)) { + count += 1; + idx += 1; + } + } + return count; + } + + /** + * Determines the number of consecutive characters that are encodable using text compaction. + * + * @param input the input + * @param startpos the start position within the input + * @return the requested character count + */ + fn determine_consecutive_text_count( input: &ECIInput, startpos: i32) -> i32 { + let len: i32 = input.length(); + let mut idx: i32 = startpos; + while idx < len { + let numeric_count: i32 = 0; + while numeric_count < 13 && idx < len && !input.is_e_c_i(idx) && ::is_digit(&input.char_at(idx)) { + numeric_count += 1; + idx += 1; + } + if numeric_count >= 13 { + return idx - startpos - numeric_count; + } + if numeric_count > 0 { + //Heuristic: All text-encodable chars or digits are binary encodable + continue; + } + //Check if character is encodable + if input.is_e_c_i(idx) || !::is_text(&input.char_at(idx)) { + break; + } + idx += 1; + } + return idx - startpos; + } + + /** + * Determines the number of consecutive characters that are encodable using binary compaction. + * + * @param input the input + * @param startpos the start position within the message + * @param encoding the charset used to convert the message to a byte array + * @return the requested character count + */ + fn determine_consecutive_binary_count( input: &ECIInput, startpos: i32, encoding: &Charset) -> /* throws WriterException */Result> { + let encoder: CharsetEncoder = if encoding == null { null } else { encoding.new_encoder() }; + let len: i32 = input.length(); + let mut idx: i32 = startpos; + while idx < len { + let numeric_count: i32 = 0; + let mut i: i32 = idx; + while numeric_count < 13 && !input.is_e_c_i(i) && ::is_digit(&input.char_at(i)) { + numeric_count += 1; + //textCount++; + i = idx + numeric_count; + if i >= len { + break; + } + } + if numeric_count >= 13 { + return Ok(idx - startpos); + } + if encoder != null && !encoder.can_encode(&input.char_at(idx)) { + assert!( input instanceof NoECIInput); + let ch: char = input.char_at(idx); + throw WriterException::new(format!("Non-encodable character detected: {} (Unicode: {})", ch, ch as i32)); + } + idx += 1; + } + return Ok(idx - startpos); + } + + fn encoding_e_c_i( eci: i32, sb: &StringBuilder) -> /* throws WriterException */Result> { + if eci >= 0 && eci < 900 { + sb.append(ECI_CHARSET as char); + sb.append(eci as char); + } else if eci < 810900 { + sb.append(ECI_GENERAL_PURPOSE as char); + sb.append((eci / 900 - 1) as char); + sb.append((eci % 900) as char); + } else if eci < 811800 { + sb.append(ECI_USER_DEFINED as char); + sb.append((810900 - eci) as char); + } else { + throw WriterException::new(format!("ECI number not in valid range from 0..811799, but was {}", eci)); + } + } + + #[derive(ECIInput)] + struct NoECIInput { + + let input: String; + } + + impl NoECIInput { + + fn new( input: &String) -> NoECIInput { + let .input = input; + } + + pub fn length(&self) -> i32 { + return self.input.length(); + } + + pub fn char_at(&self, index: i32) -> char { + return self.input.char_at(index); + } + + pub fn is_e_c_i(&self, index: i32) -> bool { + return false; + } + + pub fn get_e_c_i_value(&self, index: i32) -> i32 { + return -1; + } + + pub fn have_n_characters(&self, index: i32, n: i32) -> bool { + return index + n <= self.input.length(); + } + + pub fn sub_sequence(&self, start: i32, end: i32) -> CharSequence { + return self.input.sub_sequence(start, end); + } + + pub fn to_string(&self) -> String { + return self.input; + } + } + +} + +// NEW FILE: p_d_f417_high_level_encoder_test_adapter.rs +/* + * Copyright 2022 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::pdf417::encoder; + +pub struct PDF417HighLevelEncoderTestAdapter { +} + +impl PDF417HighLevelEncoderTestAdapter { + + fn new() -> PDF417HighLevelEncoderTestAdapter { + } + + pub fn encode_high_level( msg: &String, compaction: &Compaction, encoding: &Charset, auto_e_c_i: bool) -> /* throws WriterException */Result> { + return Ok(PDF417HighLevelEncoder::encode_high_level(&msg, compaction, &encoding, auto_e_c_i)); + } +} + diff --git a/src/qrcode.rs b/src/qrcode.rs index e69de29..9edd631 100644 --- a/src/qrcode.rs +++ b/src/qrcode.rs @@ -0,0 +1,310 @@ +// NEW FILE: q_r_code_reader.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode; + +/** + * This implementation can detect and decode QR Codes in an image. + * + * @author Sean Owen + */ + + const NO_POINTS: [Option; 0] = [None; 0]; +#[derive(Reader)] +pub struct QRCodeReader { + + let decoder: Decoder = Decoder::new(); +} + +impl QRCodeReader { + + pub fn get_decoder(&self) -> Decoder { + return self.decoder; + } + + /** + * Locates and decodes a QR code in an image. + * + * @return a String representing the content encoded by the QR code + * @throws NotFoundException if a QR code cannot be found + * @throws FormatException if a QR code cannot be decoded + * @throws ChecksumException if error correction fails + */ + pub fn decode(&self, image: &BinaryBitmap) -> /* throws NotFoundException, ChecksumException, FormatException */Result> { + return Ok(self.decode(image, null)); + } + + pub fn decode(&self, image: &BinaryBitmap, hints: &Map) -> /* throws NotFoundException, ChecksumException, FormatException */Result> { + let decoder_result: DecoderResult; + let mut points: Vec; + if hints != null && hints.contains_key(DecodeHintType::PURE_BARCODE) { + let bits: BitMatrix = ::extract_pure_bits(&image.get_black_matrix()); + decoder_result = self.decoder.decode(bits, &hints); + points = NO_POINTS; + } else { + let detector_result: DetectorResult = Detector::new(&image.get_black_matrix()).detect(&hints); + decoder_result = self.decoder.decode(&detector_result.get_bits(), &hints); + points = detector_result.get_points(); + } + // If the code was mirrored: swap the bottom-left and the top-right points. + if decoder_result.get_other() instanceof QRCodeDecoderMetaData { + (decoder_result.get_other() as QRCodeDecoderMetaData).apply_mirrored_correction(points); + } + let result: Result = Result::new(&decoder_result.get_text(), &decoder_result.get_raw_bytes(), points, BarcodeFormat::QR_CODE); + 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); + } + if decoder_result.has_structured_append() { + result.put_metadata(ResultMetadataType::STRUCTURED_APPEND_SEQUENCE, &decoder_result.get_structured_append_sequence_number()); + result.put_metadata(ResultMetadataType::STRUCTURED_APPEND_PARITY, &decoder_result.get_structured_append_parity()); + } + result.put_metadata(ResultMetadataType::SYMBOLOGY_IDENTIFIER, format!("]Q{}", decoder_result.get_symbology_modifier())); + return Ok(result); + } + + pub fn reset(&self) { + // do nothing + } + + /** + * This method detects a code in a "pure" image -- that is, pure monochrome image + * which contains only an unrotated, unskewed, image of a code, with some white border + * around it. This is a specialized method that works exceptionally fast in this special + * case. + */ + fn extract_pure_bits( image: &BitMatrix) -> /* throws NotFoundException */Result> { + let left_top_black: Vec = image.get_top_left_on_bit(); + let right_bottom_black: Vec = image.get_bottom_right_on_bit(); + if left_top_black == null || right_bottom_black == null { + throw NotFoundException::get_not_found_instance(); + } + let module_size: f32 = self.module_size(&left_top_black, image); + let mut top: i32 = left_top_black[1]; + let bottom: i32 = right_bottom_black[1]; + let mut left: i32 = left_top_black[0]; + let mut right: i32 = right_bottom_black[0]; + // Sanity check! + if left >= right || top >= bottom { + throw NotFoundException::get_not_found_instance(); + } + if bottom - top != right - left { + // Special case, where bottom-right module wasn't black so we found something else in the last row + // Assume it's a square, so use height as the width + right = left + (bottom - top); + if right >= image.get_width() { + // Abort if that would not make sense -- off image + throw NotFoundException::get_not_found_instance(); + } + } + let matrix_width: i32 = Math::round((right - left + 1.0) / module_size); + let matrix_height: i32 = Math::round((bottom - top + 1.0) / module_size); + if matrix_width <= 0 || matrix_height <= 0 { + throw NotFoundException::get_not_found_instance(); + } + if matrix_height != matrix_width { + // Only possibly decode square regions + throw NotFoundException::get_not_found_instance(); + } + // Push in the "border" by half the module width so that we start + // sampling in the middle of the module. Just in case the image is a + // little off, this will help recover. + let nudge: i32 = (module_size / 2.0f) as i32; + top += nudge; + left += nudge; + // But careful that this does not sample off the edge + // "right" is the farthest-right valid pixel location -- right+1 is not necessarily + // This is positive by how much the inner x loop below would be too large + let nudged_too_far_right: i32 = left + ((matrix_width - 1.0) * module_size) as i32 - right; + if nudged_too_far_right > 0 { + if nudged_too_far_right > nudge { + // Neither way fits; abort + throw NotFoundException::get_not_found_instance(); + } + left -= nudged_too_far_right; + } + // See logic above + let nudged_too_far_down: i32 = top + ((matrix_height - 1.0) * module_size) as i32 - bottom; + if nudged_too_far_down > 0 { + if nudged_too_far_down > nudge { + // Neither way fits; abort + throw NotFoundException::get_not_found_instance(); + } + top -= nudged_too_far_down; + } + // Now just read off the bits + let bits: BitMatrix = BitMatrix::new(matrix_width, matrix_height); + { + let mut y: i32 = 0; + while y < matrix_height { + { + let i_offset: i32 = top + (y * module_size) as i32; + { + let mut x: i32 = 0; + while x < matrix_width { + { + if image.get(left + (x * module_size) as i32, i_offset) { + bits.set(x, y); + } + } + x += 1; + } + } + + } + y += 1; + } + } + + return Ok(bits); + } + + fn module_size( left_top_black: &Vec, image: &BitMatrix) -> /* throws NotFoundException */Result> { + let height: i32 = image.get_height(); + let width: i32 = image.get_width(); + let mut x: i32 = left_top_black[0]; + let mut y: i32 = left_top_black[1]; + let in_black: bool = true; + let mut transitions: i32 = 0; + while x < width && y < height { + if in_black != image.get(x, y) { + if transitions += 1 == 5 { + break; + } + in_black = !in_black; + } + x += 1; + y += 1; + } + if x == width || y == height { + throw NotFoundException::get_not_found_instance(); + } + return Ok((x - left_top_black[0]) / 7.0f); + } +} + +// NEW FILE: q_r_code_writer.rs +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode; + +/** + * This object renders a QR Code as a BitMatrix 2D array of greyscale values. + * + * @author dswitkin@google.com (Daniel Switkin) + */ + + const QUIET_ZONE_SIZE: i32 = 4; +#[derive(Writer)] +pub struct QRCodeWriter { +} + +impl QRCodeWriter { + + pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32) -> /* throws WriterException */Result> { + return Ok(self.encode(&contents, format, width, height, null)); + } + + pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32, hints: &Map) -> /* throws WriterException */Result> { + if contents.is_empty() { + throw IllegalArgumentException::new("Found empty contents"); + } + if format != BarcodeFormat::QR_CODE { + throw IllegalArgumentException::new(format!("Can only encode QR_CODE, but got {}", format)); + } + if width < 0 || height < 0 { + throw IllegalArgumentException::new(format!("Requested dimensions are too small: {}x{}", width, height)); + } + let error_correction_level: ErrorCorrectionLevel = ErrorCorrectionLevel::L; + let quiet_zone: i32 = QUIET_ZONE_SIZE; + if hints != null { + if hints.contains_key(EncodeHintType::ERROR_CORRECTION) { + error_correction_level = ErrorCorrectionLevel::value_of(&hints.get(EncodeHintType::ERROR_CORRECTION).to_string()); + } + if hints.contains_key(EncodeHintType::MARGIN) { + quiet_zone = Integer::parse_int(&hints.get(EncodeHintType::MARGIN).to_string()); + } + } + let code: QRCode = Encoder::encode(&contents, error_correction_level, &hints); + return Ok(::render_result(code, width, height, quiet_zone)); + } + + // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses + // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap). + fn render_result( code: &QRCode, width: i32, height: i32, quiet_zone: i32) -> BitMatrix { + let input: ByteMatrix = code.get_matrix(); + if input == null { + throw IllegalStateException::new(); + } + let input_width: i32 = input.get_width(); + let input_height: i32 = input.get_height(); + let qr_width: i32 = input_width + (quiet_zone * 2); + let qr_height: i32 = input_height + (quiet_zone * 2); + let output_width: i32 = Math::max(width, qr_width); + let output_height: i32 = Math::max(height, qr_height); + let multiple: i32 = Math::min(output_width / qr_width, output_height / qr_height); + // Padding includes both the quiet zone and the extra white pixels to accommodate the requested + // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone. + // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will + // handle all the padding from 100x100 (the actual QR) up to 200x160. + 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) == 1 { + 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/src/qrcode/decoder.rs b/src/qrcode/decoder.rs index e69de29..870a31b 100644 --- a/src/qrcode/decoder.rs +++ b/src/qrcode/decoder.rs @@ -0,0 +1,1928 @@ +// NEW FILE: bit_matrix_parser.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::decoder; + +/** + * @author Sean Owen + */ +struct BitMatrixParser { + + let bit_matrix: BitMatrix; + + let parsed_version: Version; + + let parsed_format_info: FormatInformation; + + let mirror: bool; +} + +impl BitMatrixParser { + + /** + * @param bitMatrix {@link BitMatrix} to parse + * @throws FormatException if dimension is not >= 21 and 1 mod 4 + */ + fn new( bit_matrix: &BitMatrix) -> BitMatrixParser throws FormatException { + let dimension: i32 = bit_matrix.get_height(); + if dimension < 21 || (dimension & 0x03) != 1 { + throw FormatException::get_format_instance(); + } + let .bitMatrix = bit_matrix; + } + + /** + *

Reads format information from one of its two locations within the QR Code.

+ * + * @return {@link FormatInformation} encapsulating the QR Code's format info + * @throws FormatException if both format information locations cannot be parsed as + * the valid encoding of format information + */ + fn read_format_information(&self) -> /* throws FormatException */Result> { + if self.parsed_format_info != null { + return Ok(self.parsed_format_info); + } + // Read top-left format info bits + let format_info_bits1: i32 = 0; + { + let mut i: i32 = 0; + while i < 6 { + { + format_info_bits1 = self.copy_bit(i, 8, format_info_bits1); + } + i += 1; + } + } + + // .. and skip a bit in the timing pattern ... + format_info_bits1 = self.copy_bit(7, 8, format_info_bits1); + format_info_bits1 = self.copy_bit(8, 8, format_info_bits1); + format_info_bits1 = self.copy_bit(8, 7, format_info_bits1); + // .. and skip a bit in the timing pattern ... + { + let mut j: i32 = 5; + while j >= 0 { + { + format_info_bits1 = self.copy_bit(8, j, format_info_bits1); + } + j -= 1; + } + } + + // Read the top-right/bottom-left pattern too + let dimension: i32 = self.bit_matrix.get_height(); + let format_info_bits2: i32 = 0; + let j_min: i32 = dimension - 7; + { + let mut j: i32 = dimension - 1; + while j >= j_min { + { + format_info_bits2 = self.copy_bit(8, j, format_info_bits2); + } + j -= 1; + } + } + + { + let mut i: i32 = dimension - 8; + while i < dimension { + { + format_info_bits2 = self.copy_bit(i, 8, format_info_bits2); + } + i += 1; + } + } + + self.parsed_format_info = FormatInformation::decode_format_information(format_info_bits1, format_info_bits2); + if self.parsed_format_info != null { + return Ok(self.parsed_format_info); + } + throw FormatException::get_format_instance(); + } + + /** + *

Reads version information from one of its two locations within the QR Code.

+ * + * @return {@link Version} encapsulating the QR Code's version + * @throws FormatException if both version information locations cannot be parsed as + * the valid encoding of version information + */ + fn read_version(&self) -> /* throws FormatException */Result> { + if self.parsed_version != null { + return Ok(self.parsed_version); + } + let dimension: i32 = self.bit_matrix.get_height(); + let provisional_version: i32 = (dimension - 17) / 4; + if provisional_version <= 6 { + return Ok(Version::get_version_for_number(provisional_version)); + } + // Read top-right version info: 3 wide by 6 tall + let version_bits: i32 = 0; + let ij_min: i32 = dimension - 11; + { + let mut j: i32 = 5; + while j >= 0 { + { + { + let mut i: i32 = dimension - 9; + while i >= ij_min { + { + version_bits = self.copy_bit(i, j, version_bits); + } + i -= 1; + } + } + + } + j -= 1; + } + } + + let the_parsed_version: Version = Version::decode_version_information(version_bits); + if the_parsed_version != null && the_parsed_version.get_dimension_for_version() == dimension { + self.parsed_version = the_parsed_version; + return Ok(the_parsed_version); + } + // Hmm, failed. Try bottom left: 6 wide by 3 tall + version_bits = 0; + { + let mut i: i32 = 5; + while i >= 0 { + { + { + let mut j: i32 = dimension - 9; + while j >= ij_min { + { + version_bits = self.copy_bit(i, j, version_bits); + } + j -= 1; + } + } + + } + i -= 1; + } + } + + the_parsed_version = Version::decode_version_information(version_bits); + if the_parsed_version != null && the_parsed_version.get_dimension_for_version() == dimension { + self.parsed_version = the_parsed_version; + return Ok(the_parsed_version); + } + throw FormatException::get_format_instance(); + } + + fn copy_bit(&self, i: i32, j: i32, version_bits: i32) -> i32 { + let bit: bool = if self.mirror { self.bit_matrix.get(j, i) } else { self.bit_matrix.get(i, j) }; + return if bit { (version_bits << 1) | 0x1 } else { version_bits << 1 }; + } + + /** + *

Reads the bits in the {@link BitMatrix} representing the finder pattern in the + * correct order in order to reconstruct the codewords bytes contained within the + * QR Code.

+ * + * @return bytes encoded within the QR Code + * @throws FormatException if the exact number of bytes expected is not read + */ + fn read_codewords(&self) -> /* throws FormatException */Result, Rc> { + let format_info: FormatInformation = self.read_format_information(); + let version: Version = self.read_version(); + // Get the data mask for the format used in this QR Code. This will exclude + // some bits from reading as we wind through the bit matrix. + let data_mask: DataMask = DataMask::values()[format_info.get_data_mask()]; + let dimension: i32 = self.bit_matrix.get_height(); + data_mask.unmask_bit_matrix(self.bit_matrix, dimension); + let function_pattern: BitMatrix = version.build_function_pattern(); + let reading_up: bool = true; + let mut result: [i8; version.get_total_codewords()] = [0; version.get_total_codewords()]; + let result_offset: i32 = 0; + let current_byte: i32 = 0; + let bits_read: i32 = 0; + // Read columns in pairs, from right to left + { + let mut j: i32 = dimension - 1; + while j > 0 { + { + if j == 6 { + // Skip whole column with vertical alignment pattern; + // saves time and makes the other code proceed more cleanly + j -= 1; + } + // Read alternatingly from bottom to top then top to bottom + { + let mut count: i32 = 0; + while count < dimension { + { + let i: i32 = if reading_up { dimension - 1 - count } else { count }; + { + let mut col: i32 = 0; + while col < 2 { + { + // Ignore bits covered by the function pattern + if !function_pattern.get(j - col, i) { + // Read a bit + bits_read += 1; + current_byte <<= 1; + if self.bit_matrix.get(j - col, i) { + current_byte |= 1; + } + // If we've made a whole byte, save it off + if bits_read == 8 { + result[result_offset += 1 !!!check!!! post increment] = current_byte as i8; + bits_read = 0; + current_byte = 0; + } + } + } + col += 1; + } + } + + } + count += 1; + } + } + + // readingUp = !readingUp; // switch directions + reading_up ^= true; + } + j -= 2; + } + } + + if result_offset != version.get_total_codewords() { + throw FormatException::get_format_instance(); + } + return Ok(result); + } + + /** + * Revert the mask removal done while reading the code words. The bit matrix should revert to its original state. + */ + fn remask(&self) { + if self.parsed_format_info == null { + // We have no format information, and have no data mask + return; + } + let data_mask: DataMask = DataMask::values()[self.parsed_format_info.get_data_mask()]; + let dimension: i32 = self.bit_matrix.get_height(); + data_mask.unmask_bit_matrix(self.bit_matrix, dimension); + } + + /** + * Prepare the parser for a mirrored operation. + * This flag has effect only on the {@link #readFormatInformation()} and the + * {@link #readVersion()}. Before proceeding with {@link #readCodewords()} the + * {@link #mirror()} method should be called. + * + * @param mirror Whether to read version and format information mirrored. + */ + fn set_mirror(&self, mirror: bool) { + self.parsed_version = null; + self.parsed_format_info = null; + self.mirror = mirror; + } + + /** Mirror the bit matrix in order to attempt a second reading. */ + fn mirror(&self) { + { + let mut x: i32 = 0; + while x < self.bit_matrix.get_width() { + { + { + let mut y: i32 = x + 1; + while y < self.bit_matrix.get_height() { + { + if self.bit_matrix.get(x, y) != self.bit_matrix.get(y, x) { + self.bit_matrix.flip(y, x); + self.bit_matrix.flip(x, y); + } + } + y += 1; + } + } + + } + x += 1; + } + } + + } +} + +// NEW FILE: data_block.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::decoder; + +/** + *

Encapsulates a block of data within a QR Code. QR Codes may split their data into + * multiple blocks, each of which is a unit of data and error-correction codewords. Each + * is represented by an instance of this class.

+ * + * @author Sean Owen + */ +struct DataBlock { + + let num_data_codewords: i32; + + let mut codewords: Vec; +} + +impl DataBlock { + + fn new( num_data_codewords: i32, codewords: &Vec) -> DataBlock { + let .numDataCodewords = num_data_codewords; + let .codewords = codewords; + } + + /** + *

When QR Codes use multiple data blocks, they are actually interleaved. + * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This + * method will separate the data into original blocks.

+ * + * @param rawCodewords bytes as read directly from the QR Code + * @param version version of the QR Code + * @param ecLevel error-correction level of the QR Code + * @return DataBlocks containing original bytes, "de-interleaved" from representation in the + * QR Code + */ + fn get_data_blocks( raw_codewords: &Vec, version: &Version, ec_level: &ErrorCorrectionLevel) -> Vec { + if raw_codewords.len() != version.get_total_codewords() { + throw IllegalArgumentException::new(); + } + // Figure out the number and size of data blocks used by this version and + // error correction level + let ec_blocks: Version.ECBlocks = version.get_e_c_blocks_for_level(ec_level); + // First count the total number of data blocks + let total_blocks: i32 = 0; + let ec_block_array: Vec = ec_blocks.get_e_c_blocks(); + for let ec_block: Version.ECB in ec_block_array { + total_blocks += ec_block.get_count(); + } + // Now establish DataBlocks of the appropriate size and number of data codewords + let mut result: [Option; total_blocks] = [None; total_blocks]; + let num_result_blocks: i32 = 0; + for let ec_block: Version.ECB in ec_block_array { + { + let mut i: i32 = 0; + while i < ec_block.get_count() { + { + let num_data_codewords: i32 = ec_block.get_data_codewords(); + let num_block_codewords: i32 = ec_blocks.get_e_c_codewords_per_block() + num_data_codewords; + result[num_result_blocks += 1 !!!check!!! post increment] = DataBlock::new(num_data_codewords, : [i8; num_block_codewords] = [0; num_block_codewords]); + } + i += 1; + } + } + + } + // All blocks have the same amount of data, except that the last n + // (where n may be 0) have 1 more byte. Figure out where these start. + let shorter_blocks_total_codewords: i32 = result[0].codewords.len(); + let longer_blocks_start_at: i32 = result.len() - 1; + while longer_blocks_start_at >= 0 { + let num_codewords: i32 = result[longer_blocks_start_at].codewords.len(); + if num_codewords == shorter_blocks_total_codewords { + break; + } + longer_blocks_start_at -= 1; + } + longer_blocks_start_at += 1; + let shorter_blocks_num_data_codewords: i32 = shorter_blocks_total_codewords - ec_blocks.get_e_c_codewords_per_block(); + // The last elements of result may be 1 element longer; + // first fill out as many elements as all of them have + let raw_codewords_offset: i32 = 0; + { + let mut i: i32 = 0; + while i < shorter_blocks_num_data_codewords { + { + { + let mut j: i32 = 0; + while j < num_result_blocks { + { + result[j].codewords[i] = raw_codewords[raw_codewords_offset += 1 !!!check!!! post increment]; + } + j += 1; + } + } + + } + i += 1; + } + } + + // Fill out the last data block in the longer ones + { + let mut j: i32 = longer_blocks_start_at; + while j < num_result_blocks { + { + result[j].codewords[shorter_blocks_num_data_codewords] = raw_codewords[raw_codewords_offset += 1 !!!check!!! post increment]; + } + j += 1; + } + } + + // Now add in error correction blocks + let max: i32 = result[0].codewords.len(); + { + let mut i: i32 = shorter_blocks_num_data_codewords; + while i < max { + { + { + let mut j: i32 = 0; + while j < num_result_blocks { + { + let i_offset: i32 = if j < longer_blocks_start_at { i } else { i + 1 }; + result[j].codewords[i_offset] = raw_codewords[raw_codewords_offset += 1 !!!check!!! post increment]; + } + j += 1; + } + } + + } + i += 1; + } + } + + return result; + } + + fn get_num_data_codewords(&self) -> i32 { + return self.num_data_codewords; + } + + fn get_codewords(&self) -> Vec { + return self.codewords; + } +} + +// NEW FILE: data_mask.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::decoder; + +/** + *

Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations + * of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix, + * including areas used for finder patterns, timing patterns, etc. These areas should be unused + * after the point they are unmasked anyway.

+ * + *

Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position + * and j is row position. In fact, as the text says, i is row position and j is column position.

+ * + * @author Sean Owen + */ +enum DataMask { + + /** + * 000: mask bits for which (x + y) mod 2 == 0 + */ + DATA_MASK_000() { + + fn is_masked(&self, i: i32, j: i32) -> bool { + return ((i + j) & 0x01) == 0; + } + } + , /** + * 001: mask bits for which x mod 2 == 0 + */ + DATA_MASK_001() { + + fn is_masked(&self, i: i32, j: i32) -> bool { + return (i & 0x01) == 0; + } + } + , /** + * 010: mask bits for which y mod 3 == 0 + */ + DATA_MASK_010() { + + fn is_masked(&self, i: i32, j: i32) -> bool { + return j % 3 == 0; + } + } + , /** + * 011: mask bits for which (x + y) mod 3 == 0 + */ + DATA_MASK_011() { + + fn is_masked(&self, i: i32, j: i32) -> bool { + return (i + j) % 3 == 0; + } + } + , /** + * 100: mask bits for which (x/2 + y/3) mod 2 == 0 + */ + DATA_MASK_100() { + + fn is_masked(&self, i: i32, j: i32) -> bool { + return (((i / 2) + (j / 3)) & 0x01) == 0; + } + } + , /** + * 101: mask bits for which xy mod 2 + xy mod 3 == 0 + * equivalently, such that xy mod 6 == 0 + */ + DATA_MASK_101() { + + fn is_masked(&self, i: i32, j: i32) -> bool { + return (i * j) % 6 == 0; + } + } + , /** + * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0 + * equivalently, such that xy mod 6 < 3 + */ + DATA_MASK_110() { + + fn is_masked(&self, i: i32, j: i32) -> bool { + return ((i * j) % 6) < 3; + } + } + , /** + * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0 + * equivalently, such that (x + y + xy mod 3) mod 2 == 0 + */ + DATA_MASK_111() { + + fn is_masked(&self, i: i32, j: i32) -> bool { + return ((i + j + ((i * j) % 3)) & 0x01) == 0; + } + } + ; + + // End of enum constants. + /** + *

Implementations of this method reverse the data masking process applied to a QR Code and + * make its bits ready to read.

+ * + * @param bits representation of QR Code bits + * @param dimension dimension of QR Code, represented by bits, being unmasked + */ + fn unmask_bit_matrix(&self, bits: &BitMatrix, dimension: i32) { + { + let mut i: i32 = 0; + while i < dimension { + { + { + let mut j: i32 = 0; + while j < dimension { + { + if self.is_masked(i, j) { + bits.flip(j, i); + } + } + j += 1; + } + } + + } + i += 1; + } + } + + } + + fn is_masked(&self, i: i32, j: i32) -> bool ; +} +// NEW FILE: decoded_bit_stream_parser.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::decoder; + +/** + *

QR Codes can encode text as bits in one of several modes, and can use multiple modes + * in one QR Code. This class decodes the bits back into text.

+ * + *

See ISO 18004:2006, 6.4.3 - 6.4.7

+ * + * @author Sean Owen + */ + +/** + * See ISO 18004:2006, 6.4.4 Table 5 + */ + const ALPHANUMERIC_CHARS: Vec = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".to_char_array(); + + const GB2312_SUBSET: i32 = 1; +struct DecodedBitStreamParser { +} + +impl DecodedBitStreamParser { + + fn new() -> DecodedBitStreamParser { + } + + fn decode( bytes: &Vec, version: &Version, ec_level: &ErrorCorrectionLevel, hints: &Map) -> /* throws FormatException */Result> { + let bits: BitSource = BitSource::new(&bytes); + let result: StringBuilder = StringBuilder::new(50); + let byte_segments: List> = ArrayList<>::new(1); + let symbol_sequence: i32 = -1; + let parity_data: i32 = -1; + let symbology_modifier: i32; + let tryResult1 = 0; + 'try1: loop { + { + let current_character_set_e_c_i: CharacterSetECI = null; + let fc1_in_effect: bool = false; + let has_f_n_c1first: bool = false; + let has_f_n_c1second: bool = false; + let mut mode: Mode; + loop { { + // While still another segment to read... + if bits.available() < 4 { + // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here + mode = Mode::TERMINATOR; + } else { + // mode is encoded by 4 bits + mode = Mode::for_bits(&bits.read_bits(4)); + } + match mode { + TERMINATOR => + { + break; + } + FNC1_FIRST_POSITION => + { + // symbology detection + has_f_n_c1first = true; + // We do little with FNC1 except alter the parsed result a bit according to the spec + fc1_in_effect = true; + break; + } + FNC1_SECOND_POSITION => + { + // symbology detection + has_f_n_c1second = true; + // We do little with FNC1 except alter the parsed result a bit according to the spec + fc1_in_effect = true; + break; + } + STRUCTURED_APPEND => + { + if bits.available() < 16 { + throw FormatException::get_format_instance(); + } + // sequence number and parity is added later to the result metadata + // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue + symbol_sequence = bits.read_bits(8); + parity_data = bits.read_bits(8); + break; + } + ECI => + { + // Count doesn't apply to ECI + let value: i32 = ::parse_e_c_i_value(bits); + current_character_set_e_c_i = CharacterSetECI::get_character_set_e_c_i_by_value(value); + if current_character_set_e_c_i == null { + throw FormatException::get_format_instance(); + } + break; + } + HANZI => + { + // First handle Hanzi mode which does not start with character count + // Chinese mode contains a sub set indicator right after mode indicator + let subset: i32 = bits.read_bits(4); + let count_hanzi: i32 = bits.read_bits(&mode.get_character_count_bits(version)); + if subset == GB2312_SUBSET { + ::decode_hanzi_segment(bits, &result, count_hanzi); + } + break; + } + _ => + { + // "Normal" QR code modes: + // How many characters will follow, encoded in this mode? + let count: i32 = bits.read_bits(&mode.get_character_count_bits(version)); + match mode { + NUMERIC => + { + ::decode_numeric_segment(bits, &result, count); + break; + } + ALPHANUMERIC => + { + ::decode_alphanumeric_segment(bits, &result, count, fc1_in_effect); + break; + } + BYTE => + { + ::decode_byte_segment(bits, &result, count, current_character_set_e_c_i, &byte_segments, &hints); + break; + } + KANJI => + { + ::decode_kanji_segment(bits, &result, count); + break; + } + _ => + { + throw FormatException::get_format_instance(); + } + } + break; + } + } + }if !(mode != Mode::TERMINATOR) break;} + if current_character_set_e_c_i != null { + if has_f_n_c1first { + symbology_modifier = 4; + } else if has_f_n_c1second { + symbology_modifier = 6; + } else { + symbology_modifier = 2; + } + } else { + if has_f_n_c1first { + symbology_modifier = 3; + } else if has_f_n_c1second { + symbology_modifier = 5; + } else { + symbology_modifier = 1; + } + } + } + break 'try1 + } + match tryResult1 { + catch ( iae: &IllegalArgumentException) { + throw FormatException::get_format_instance(); + } 0 => break + } + + return Ok(DecoderResult::new(&bytes, &result.to_string(), if byte_segments.is_empty() { null } else { byte_segments }, if ec_level == null { null } else { ec_level.to_string() }, symbol_sequence, parity_data, symbology_modifier)); + } + + /** + * See specification GBT 18284-2000 + */ + fn decode_hanzi_segment( bits: &BitSource, result: &StringBuilder, count: i32) -> /* throws FormatException */Result> { + // Don't crash trying to read more bits than we have available. + if count * 13 > bits.available() { + throw FormatException::get_format_instance(); + } + // Each character will require 2 bytes. Read the characters as 2-byte pairs + // and decode as GB2312 afterwards + let mut buffer: [i8; 2 * count] = [0; 2 * count]; + let mut offset: i32 = 0; + while count > 0 { + // Each 13 bits encodes a 2-byte character + let two_bytes: i32 = bits.read_bits(13); + let assembled_two_bytes: i32 = ((two_bytes / 0x060) << 8) | (two_bytes % 0x060); + if assembled_two_bytes < 0x00A00 { + // In the 0xA1A1 to 0xAAFE range + assembled_two_bytes += 0x0A1A1; + } else { + // In the 0xB0A1 to 0xFAFE range + assembled_two_bytes += 0x0A6A1; + } + buffer[offset] = ((assembled_two_bytes >> 8) & 0xFF) as i8; + buffer[offset + 1] = (assembled_two_bytes & 0xFF) as i8; + offset += 2; + count -= 1; + } + result.append(String::new(&buffer, StringUtils::GB2312_CHARSET)); + } + + fn decode_kanji_segment( bits: &BitSource, result: &StringBuilder, count: i32) -> /* throws FormatException */Result> { + // Don't crash trying to read more bits than we have available. + if count * 13 > bits.available() { + throw FormatException::get_format_instance(); + } + // Each character will require 2 bytes. Read the characters as 2-byte pairs + // and decode as Shift_JIS afterwards + let mut buffer: [i8; 2 * count] = [0; 2 * count]; + let mut offset: i32 = 0; + while count > 0 { + // Each 13 bits encodes a 2-byte character + let two_bytes: i32 = bits.read_bits(13); + let assembled_two_bytes: i32 = ((two_bytes / 0x0C0) << 8) | (two_bytes % 0x0C0); + if assembled_two_bytes < 0x01F00 { + // In the 0x8140 to 0x9FFC range + assembled_two_bytes += 0x08140; + } else { + // In the 0xE040 to 0xEBBF range + assembled_two_bytes += 0x0C140; + } + buffer[offset] = (assembled_two_bytes >> 8) as i8; + buffer[offset + 1] = assembled_two_bytes as i8; + offset += 2; + count -= 1; + } + result.append(String::new(&buffer, StringUtils::SHIFT_JIS_CHARSET)); + } + + fn decode_byte_segment( bits: &BitSource, result: &StringBuilder, count: i32, current_character_set_e_c_i: &CharacterSetECI, byte_segments: &Collection>, hints: &Map) -> /* throws FormatException */Result> { + // Don't crash trying to read more bits than we have available. + if 8 * count > bits.available() { + throw FormatException::get_format_instance(); + } + let read_bytes: [i8; count] = [0; count]; + { + let mut i: i32 = 0; + while i < count { + { + read_bytes[i] = bits.read_bits(8) as i8; + } + i += 1; + } + } + + let mut encoding: Charset; + if current_character_set_e_c_i == null { + // The spec isn't clear on this mode; see + // section 6.4.5: t does not say which encoding to assuming + // upon decoding. I have seen ISO-8859-1 used as well as + // Shift_JIS -- without anything like an ECI designator to + // give a hint. + encoding = StringUtils::guess_charset(&read_bytes, &hints); + } else { + encoding = current_character_set_e_c_i.get_charset(); + } + result.append(String::new(&read_bytes, &encoding)); + byte_segments.add(&read_bytes); + } + + fn to_alpha_numeric_char( value: i32) -> /* throws FormatException */Result> { + if value >= ALPHANUMERIC_CHARS.len() { + throw FormatException::get_format_instance(); + } + return Ok(ALPHANUMERIC_CHARS[value]); + } + + fn decode_alphanumeric_segment( bits: &BitSource, result: &StringBuilder, count: i32, fc1_in_effect: bool) -> /* throws FormatException */Result> { + // Read two characters at a time + let start: i32 = result.length(); + while count > 1 { + if bits.available() < 11 { + throw FormatException::get_format_instance(); + } + let next_two_chars_bits: i32 = bits.read_bits(11); + result.append(&::to_alpha_numeric_char(next_two_chars_bits / 45)); + result.append(&::to_alpha_numeric_char(next_two_chars_bits % 45)); + count -= 2; + } + if count == 1 { + // special case: one character left + if bits.available() < 6 { + throw FormatException::get_format_instance(); + } + result.append(&::to_alpha_numeric_char(&bits.read_bits(6))); + } + // See section 6.4.8.1, 6.4.8.2 + if fc1_in_effect { + // We need to massage the result a bit if in an FNC1 mode: + { + let mut i: i32 = start; + while i < result.length() { + { + if result.char_at(i) == '%' { + if i < result.length() - 1 && result.char_at(i + 1) == '%' { + // %% is rendered as % + result.delete_char_at(i + 1); + } else { + // In alpha mode, % should be converted to FNC1 separator 0x1D + result.set_char_at(i, 0x1D as char); + } + } + } + i += 1; + } + } + + } + } + + fn decode_numeric_segment( bits: &BitSource, result: &StringBuilder, count: i32) -> /* throws FormatException */Result> { + // Read three digits at a time + while count >= 3 { + // Each 10 bits encodes three digits + if bits.available() < 10 { + throw FormatException::get_format_instance(); + } + let three_digits_bits: i32 = bits.read_bits(10); + if three_digits_bits >= 1000 { + throw FormatException::get_format_instance(); + } + result.append(&::to_alpha_numeric_char(three_digits_bits / 100)); + result.append(&::to_alpha_numeric_char((three_digits_bits / 10) % 10)); + result.append(&::to_alpha_numeric_char(three_digits_bits % 10)); + count -= 3; + } + if count == 2 { + // Two digits left over to read, encoded in 7 bits + if bits.available() < 7 { + throw FormatException::get_format_instance(); + } + let two_digits_bits: i32 = bits.read_bits(7); + if two_digits_bits >= 100 { + throw FormatException::get_format_instance(); + } + result.append(&::to_alpha_numeric_char(two_digits_bits / 10)); + result.append(&::to_alpha_numeric_char(two_digits_bits % 10)); + } else if count == 1 { + // One digit left over to read + if bits.available() < 4 { + throw FormatException::get_format_instance(); + } + let digit_bits: i32 = bits.read_bits(4); + if digit_bits >= 10 { + throw FormatException::get_format_instance(); + } + result.append(&::to_alpha_numeric_char(digit_bits)); + } + } + + fn parse_e_c_i_value( bits: &BitSource) -> /* throws FormatException */Result> { + let first_byte: i32 = bits.read_bits(8); + if (first_byte & 0x80) == 0 { + // just one byte + return Ok(first_byte & 0x7F); + } + if (first_byte & 0xC0) == 0x80 { + // two bytes + let second_byte: i32 = bits.read_bits(8); + return Ok(((first_byte & 0x3F) << 8) | second_byte); + } + if (first_byte & 0xE0) == 0xC0 { + // three bytes + let second_third_bytes: i32 = bits.read_bits(16); + return Ok(((first_byte & 0x1F) << 16) | second_third_bytes); + } + throw FormatException::get_format_instance(); + } +} + +// NEW FILE: decoder.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::decoder; + +/** + *

The main class which implements QR Code decoding -- as opposed to locating and extracting + * the QR Code from an image.

+ * + * @author Sean Owen + */ +pub struct Decoder { + + let rs_decoder: ReedSolomonDecoder; +} + +impl Decoder { + + pub fn new() -> Decoder { + rs_decoder = ReedSolomonDecoder::new(GenericGF::QR_CODE_FIELD_256); + } + + pub fn decode(&self, image: &Vec>) -> /* throws ChecksumException, FormatException */Result> { + return Ok(self.decode(&image, null)); + } + + /** + *

Convenience method that can decode a QR Code represented as a 2D array of booleans. + * "true" is taken to mean a black module.

+ * + * @param image booleans representing white/black QR Code modules + * @param hints decoding hints that should be used to influence decoding + * @return text and bytes encoded within the QR Code + * @throws FormatException if the QR Code cannot be decoded + * @throws ChecksumException if error correction fails + */ + pub fn decode(&self, image: &Vec>, hints: &Map) -> /* throws ChecksumException, FormatException */Result> { + return Ok(self.decode(&BitMatrix::parse(&image), &hints)); + } + + pub fn decode(&self, bits: &BitMatrix) -> /* throws ChecksumException, FormatException */Result> { + return Ok(self.decode(bits, null)); + } + + /** + *

Decodes a QR Code represented as a {@link BitMatrix}. A 1 or "true" is taken to mean a black module.

+ * + * @param bits booleans representing white/black QR Code modules + * @param hints decoding hints that should be used to influence decoding + * @return text and bytes encoded within the QR Code + * @throws FormatException if the QR Code cannot be decoded + * @throws ChecksumException if error correction fails + */ + pub fn decode(&self, bits: &BitMatrix, hints: &Map) -> /* throws FormatException, ChecksumException */Result> { + // Construct a parser and read version, error-correction level + let parser: BitMatrixParser = BitMatrixParser::new(bits); + let mut fe: FormatException = null; + let mut ce: ChecksumException = null; + let tryResult1 = 0; + 'try1: loop { + { + return Ok(self.decode(parser, &hints)); + } + break 'try1 + } + match tryResult1 { + catch ( e: &FormatException) { + fe = e; + } catch ( e: &ChecksumException) { + ce = e; + } 0 => break + } + + let tryResult1 = 0; + 'try1: loop { + { + // Revert the bit matrix + parser.remask(); + // Will be attempting a mirrored reading of the version and format info. + parser.set_mirror(true); + // Preemptively read the version. + parser.read_version(); + // Preemptively read the format information. + parser.read_format_information(); + /* + * Since we're here, this means we have successfully detected some kind + * of version and format information when mirrored. This is a good sign, + * that the QR code may be mirrored, and we should try once more with a + * mirrored content. + */ + // Prepare for a mirrored reading. + parser.mirror(); + let result: DecoderResult = self.decode(parser, &hints); + // Success! Notify the caller that the code was mirrored. + result.set_other(QRCodeDecoderMetaData::new(true)); + return Ok(result); + } + break 'try1 + } + match tryResult1 { + catch ( e: &FormatExceptionChecksumException | ) { + if fe != null { + throw fe; + } + throw ce; + } 0 => break + } + + } + + fn decode(&self, parser: &BitMatrixParser, hints: &Map) -> /* throws FormatException, ChecksumException */Result> { + let version: Version = parser.read_version(); + let ec_level: ErrorCorrectionLevel = parser.read_format_information().get_error_correction_level(); + // Read codewords + let codewords: Vec = parser.read_codewords(); + // Separate into data blocks + let data_blocks: Vec = DataBlock::get_data_blocks(&codewords, version, ec_level); + // Count total number of data bytes + let total_bytes: i32 = 0; + for let data_block: DataBlock in data_blocks { + total_bytes += data_block.get_num_data_codewords(); + } + let result_bytes: [i8; total_bytes] = [0; total_bytes]; + let result_offset: i32 = 0; + // Error-correct and copy data blocks together into a stream of bytes + for let data_block: DataBlock in data_blocks { + let codeword_bytes: Vec = data_block.get_codewords(); + let num_data_codewords: i32 = data_block.get_num_data_codewords(); + self.correct_errors(&codeword_bytes, num_data_codewords); + { + let mut i: i32 = 0; + while i < num_data_codewords { + { + result_bytes[result_offset += 1 !!!check!!! post increment] = codeword_bytes[i]; + } + i += 1; + } + } + + } + // Decode the contents of that stream of bytes + return Ok(DecodedBitStreamParser::decode(&result_bytes, version, ec_level, &hints)); + } + + /** + *

Given data and error-correction codewords received, possibly corrupted by errors, attempts to + * correct the errors in-place using Reed-Solomon error correction.

+ * + * @param codewordBytes data and error correction codewords + * @param numDataCodewords number of codewords that are data bytes + * @throws ChecksumException if error correction fails + */ + fn correct_errors(&self, codeword_bytes: &Vec, num_data_codewords: i32) -> /* throws ChecksumException */Result> { + let num_codewords: i32 = codeword_bytes.len(); + // First read into an array of ints + let codewords_ints: [i32; num_codewords] = [0; num_codewords]; + { + let mut i: i32 = 0; + while i < num_codewords { + { + codewords_ints[i] = codeword_bytes[i] & 0xFF; + } + i += 1; + } + } + + let tryResult1 = 0; + 'try1: loop { + { + self.rs_decoder.decode(&codewords_ints, codeword_bytes.len() - num_data_codewords); + } + break 'try1 + } + match tryResult1 { + catch ( ignored: &ReedSolomonException) { + throw ChecksumException::get_checksum_instance(); + } 0 => break + } + + // We don't care about errors in the error-correction codewords + { + let mut i: i32 = 0; + while i < num_data_codewords { + { + codeword_bytes[i] = codewords_ints[i] as i8; + } + i += 1; + } + } + + } +} + +// NEW FILE: error_correction_level.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::decoder; + +/** + *

See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels + * defined by the QR code standard.

+ * + * @author Sean Owen + */ +pub enum ErrorCorrectionLevel { + + /** L = ~7% correction */ + L(0x01), /** M = ~15% correction */ + M(0x00), /** Q = ~25% correction */ + Q(0x03), /** H = ~30% correction */ + H(0x02); + + const FOR_BITS: vec![Vec; 4] = vec![M, L, H, Q, ] + ; + + let bits: i32; + + fn new( bits: i32) -> ErrorCorrectionLevel { + let .bits = bits; + } + + pub fn get_bits(&self) -> i32 { + return self.bits; + } + + /** + * @param bits int containing the two bits encoding a QR Code's error correction level + * @return ErrorCorrectionLevel representing the encoded error correction level + */ + pub fn for_bits( bits: i32) -> ErrorCorrectionLevel { + if bits < 0 || bits >= FOR_BITS.len() { + throw IllegalArgumentException::new(); + } + return FOR_BITS[bits]; + } +} +// NEW FILE: format_information.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::decoder; + +/** + *

Encapsulates a QR Code's format information, including the data mask used and + * error correction level.

+ * + * @author Sean Owen + * @see DataMask + * @see ErrorCorrectionLevel + */ + + const FORMAT_INFO_MASK_QR: i32 = 0x5412; + +/** + * See ISO 18004:2006, Annex C, Table C.1 + */ + const FORMAT_INFO_DECODE_LOOKUP: vec![vec![Vec>; 2]; 32] = vec![vec![0x5412, 0x00, ] +, vec![0x5125, 0x01, ] +, vec![0x5E7C, 0x02, ] +, vec![0x5B4B, 0x03, ] +, vec![0x45F9, 0x04, ] +, vec![0x40CE, 0x05, ] +, vec![0x4F97, 0x06, ] +, vec![0x4AA0, 0x07, ] +, vec![0x77C4, 0x08, ] +, vec![0x72F3, 0x09, ] +, vec![0x7DAA, 0x0A, ] +, vec![0x789D, 0x0B, ] +, vec![0x662F, 0x0C, ] +, vec![0x6318, 0x0D, ] +, vec![0x6C41, 0x0E, ] +, vec![0x6976, 0x0F, ] +, vec![0x1689, 0x10, ] +, vec![0x13BE, 0x11, ] +, vec![0x1CE7, 0x12, ] +, vec![0x19D0, 0x13, ] +, vec![0x0762, 0x14, ] +, vec![0x0255, 0x15, ] +, vec![0x0D0C, 0x16, ] +, vec![0x083B, 0x17, ] +, vec![0x355F, 0x18, ] +, vec![0x3068, 0x19, ] +, vec![0x3F31, 0x1A, ] +, vec![0x3A06, 0x1B, ] +, vec![0x24B4, 0x1C, ] +, vec![0x2183, 0x1D, ] +, vec![0x2EDA, 0x1E, ] +, vec![0x2BED, 0x1F, ] +, ] +; +struct FormatInformation { + + let error_correction_level: ErrorCorrectionLevel; + + let data_mask: i8; +} + +impl FormatInformation { + + fn new( format_info: i32) -> FormatInformation { + // Bits 3,4 + error_correction_level = ErrorCorrectionLevel::for_bits((format_info >> 3) & 0x03); + // Bottom 3 bits + data_mask = (format_info & 0x07) as i8; + } + + fn num_bits_differing( a: i32, b: i32) -> i32 { + return Integer::bit_count(a ^ b); + } + + /** + * @param maskedFormatInfo1 format info indicator, with mask still applied + * @param maskedFormatInfo2 second copy of same info; both are checked at the same time + * to establish best match + * @return information about the format it specifies, or {@code null} + * if doesn't seem to match any known pattern + */ + fn decode_format_information( masked_format_info1: i32, masked_format_info2: i32) -> FormatInformation { + let format_info: FormatInformation = ::do_decode_format_information(masked_format_info1, masked_format_info2); + if format_info != null { + return format_info; + } + // first + return ::do_decode_format_information(masked_format_info1 ^ FORMAT_INFO_MASK_QR, masked_format_info2 ^ FORMAT_INFO_MASK_QR); + } + + fn do_decode_format_information( masked_format_info1: i32, masked_format_info2: i32) -> FormatInformation { + // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing + let best_difference: i32 = Integer::MAX_VALUE; + let best_format_info: i32 = 0; + for let decode_info: Vec in FORMAT_INFO_DECODE_LOOKUP { + let target_info: i32 = decode_info[0]; + if target_info == masked_format_info1 || target_info == masked_format_info2 { + // Found an exact match + return FormatInformation::new(decode_info[1]); + } + let bits_difference: i32 = ::num_bits_differing(masked_format_info1, target_info); + if bits_difference < best_difference { + best_format_info = decode_info[1]; + best_difference = bits_difference; + } + if masked_format_info1 != masked_format_info2 { + // also try the other option + bits_difference = ::num_bits_differing(masked_format_info2, target_info); + if bits_difference < best_difference { + best_format_info = decode_info[1]; + best_difference = bits_difference; + } + } + } + // differing means we found a match + if best_difference <= 3 { + return FormatInformation::new(best_format_info); + } + return null; + } + + fn get_error_correction_level(&self) -> ErrorCorrectionLevel { + return self.error_correction_level; + } + + fn get_data_mask(&self) -> i8 { + return self.data_mask; + } + + pub fn hash_code(&self) -> i32 { + return (self.error_correction_level.ordinal() << 3) | self.data_mask; + } + + pub fn equals(&self, o: &Object) -> bool { + if !(o instanceof FormatInformation) { + return false; + } + let other: FormatInformation = o as FormatInformation; + return self.errorCorrectionLevel == other.errorCorrectionLevel && self.dataMask == other.dataMask; + } +} + +// NEW FILE: mode.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::decoder; + +/** + *

See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which + * data can be encoded to bits in the QR code standard.

+ * + * @author Sean Owen + */ +pub enum Mode { + + // Not really a mode... + TERMINATOR( : vec![i32; 3] = vec![0, 0, 0, ] + , 0x00), NUMERIC( : vec![i32; 3] = vec![10, 12, 14, ] + , 0x01), ALPHANUMERIC( : vec![i32; 3] = vec![9, 11, 13, ] + , 0x02), // Not supported + STRUCTURED_APPEND( : vec![i32; 3] = vec![0, 0, 0, ] + , 0x03), BYTE( : vec![i32; 3] = vec![8, 16, 16, ] + , 0x04), // character counts don't apply + ECI( : vec![i32; 3] = vec![0, 0, 0, ] + , 0x07), KANJI( : vec![i32; 3] = vec![8, 10, 12, ] + , 0x08), FNC1_FIRST_POSITION( : vec![i32; 3] = vec![0, 0, 0, ] + , 0x05), FNC1_SECOND_POSITION( : vec![i32; 3] = vec![0, 0, 0, ] + , 0x09), /** See GBT 18284-2000; "Hanzi" is a transliteration of this mode name. */ + HANZI( : vec![i32; 3] = vec![8, 10, 12, ] + , 0x0D); + + let character_count_bits_for_versions: Vec; + + let bits: i32; + + fn new( character_count_bits_for_versions: &Vec, bits: i32) -> Mode { + let .characterCountBitsForVersions = character_count_bits_for_versions; + let .bits = bits; + } + + /** + * @param bits four bits encoding a QR Code data mode + * @return Mode encoded by these bits + * @throws IllegalArgumentException if bits do not correspond to a known mode + */ + pub fn for_bits( bits: i32) -> Mode { + match bits { + 0x0 => + { + return TERMINATOR; + } + 0x1 => + { + return NUMERIC; + } + 0x2 => + { + return ALPHANUMERIC; + } + 0x3 => + { + return STRUCTURED_APPEND; + } + 0x4 => + { + return BYTE; + } + 0x5 => + { + return FNC1_FIRST_POSITION; + } + 0x7 => + { + return ECI; + } + 0x8 => + { + return KANJI; + } + 0x9 => + { + return FNC1_SECOND_POSITION; + } + 0xD => + { + // 0xD is defined in GBT 18284-2000, may not be supported in foreign country + return HANZI; + } + _ => + { + throw IllegalArgumentException::new(); + } + } + } + + /** + * @param version version in question + * @return number of bits used, in this QR Code symbol {@link Version}, to encode the + * count of characters that will follow encoded in this Mode + */ + pub fn get_character_count_bits(&self, version: &Version) -> i32 { + let number: i32 = version.get_version_number(); + let mut offset: i32; + if number <= 9 { + offset = 0; + } else if number <= 26 { + offset = 1; + } else { + offset = 2; + } + return self.character_count_bits_for_versions[offset]; + } + + pub fn get_bits(&self) -> i32 { + return self.bits; + } +} +// NEW FILE: q_r_code_decoder_meta_data.rs +/* + * 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::qrcode::decoder; + +/** + * Meta-data container for QR Code decoding. Instances of this class may be used to convey information back to the + * decoding caller. Callers are expected to process this. + * + * @see com.google.zxing.common.DecoderResult#getOther() + */ +pub struct QRCodeDecoderMetaData { + + let mirrored: bool; +} + +impl QRCodeDecoderMetaData { + + fn new( mirrored: bool) -> QRCodeDecoderMetaData { + let .mirrored = mirrored; + } + + /** + * @return true if the QR Code was mirrored. + */ + pub fn is_mirrored(&self) -> bool { + return self.mirrored; + } + + /** + * Apply the result points' order correction due to mirroring. + * + * @param points Array of points to apply mirror correction to. + */ + pub fn apply_mirrored_correction(&self, points: &Vec) { + if !self.mirrored || points == null || points.len() < 3 { + return; + } + let bottom_left: ResultPoint = points[0]; + points[0] = points[2]; + points[2] = bottom_left; + // No need to 'fix' top-left and alignment pattern. + } +} + +// NEW FILE: version.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::decoder; + +/** + * See ISO 18004:2006 Annex D + * + * @author Sean Owen + */ + +/** + * See ISO 18004:2006 Annex D. + * Element i represents the raw version bits that specify version i + 7 + */ + const VERSION_DECODE_INFO: vec![Vec; 34] = vec![0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78, 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B, 0x2542E, 0x26A64, 0x27541, 0x28C69, ] +; + + const VERSIONS: Vec = ::build_versions(); +pub struct Version { + + let version_number: i32; + + let alignment_pattern_centers: Vec; + + let ec_blocks: Vec; + + let total_codewords: i32; +} + +impl Version { + + fn new( version_number: i32, alignment_pattern_centers: &Vec, ec_blocks: &ECBlocks) -> Version { + let .versionNumber = version_number; + let .alignmentPatternCenters = alignment_pattern_centers; + let .ecBlocks = ec_blocks; + let mut total: i32 = 0; + let ec_codewords: i32 = ec_blocks[0].get_e_c_codewords_per_block(); + let ecb_array: Vec = ec_blocks[0].get_e_c_blocks(); + for let ec_block: ECB in ecb_array { + total += ec_block.get_count() * (ec_block.get_data_codewords() + ec_codewords); + } + let .totalCodewords = total; + } + + pub fn get_version_number(&self) -> i32 { + return self.version_number; + } + + pub fn get_alignment_pattern_centers(&self) -> Vec { + return self.alignment_pattern_centers; + } + + pub fn get_total_codewords(&self) -> i32 { + return self.total_codewords; + } + + pub fn get_dimension_for_version(&self) -> i32 { + return 17 + 4 * self.version_number; + } + + pub fn get_e_c_blocks_for_level(&self, ec_level: &ErrorCorrectionLevel) -> ECBlocks { + return self.ec_blocks[ec_level.ordinal()]; + } + + /** + *

Deduces version information purely from QR Code dimensions.

+ * + * @param dimension dimension in modules + * @return Version for a QR Code of that dimension + * @throws FormatException if dimension is not 1 mod 4 + */ + pub fn get_provisional_version_for_dimension( dimension: i32) -> /* throws FormatException */Result> { + if dimension % 4 != 1 { + throw FormatException::get_format_instance(); + } + let tryResult1 = 0; + 'try1: loop { + { + return Ok(::get_version_for_number((dimension - 17) / 4)); + } + break 'try1 + } + match tryResult1 { + catch ( ignored: &IllegalArgumentException) { + throw FormatException::get_format_instance(); + } 0 => break + } + + } + + pub fn get_version_for_number( version_number: i32) -> Version { + if version_number < 1 || version_number > 40 { + throw IllegalArgumentException::new(); + } + return VERSIONS[version_number - 1]; + } + + fn decode_version_information( version_bits: i32) -> Version { + let best_difference: i32 = Integer::MAX_VALUE; + let best_version: i32 = 0; + { + let mut i: i32 = 0; + while i < VERSION_DECODE_INFO.len() { + { + let target_version: i32 = VERSION_DECODE_INFO[i]; + // Do the version info bits match exactly? done. + if target_version == version_bits { + return ::get_version_for_number(i + 7); + } + // Otherwise see if this is the closest to a real version info bit string + // we have seen so far + let bits_difference: i32 = FormatInformation::num_bits_differing(version_bits, target_version); + if bits_difference < best_difference { + best_version = i + 7; + best_difference = bits_difference; + } + } + i += 1; + } + } + + // differ in less than 8 bits. + if best_difference <= 3 { + return ::get_version_for_number(best_version); + } + // If we didn't find a close enough match, fail + return null; + } + + /** + * See ISO 18004:2006 Annex E + */ + fn build_function_pattern(&self) -> BitMatrix { + let dimension: i32 = self.get_dimension_for_version(); + let bit_matrix: BitMatrix = BitMatrix::new(dimension); + // Top left finder pattern + separator + format + bit_matrix.set_region(0, 0, 9, 9); + // Top right finder pattern + separator + format + bit_matrix.set_region(dimension - 8, 0, 8, 9); + // Bottom left finder pattern + separator + format + bit_matrix.set_region(0, dimension - 8, 9, 8); + // Alignment patterns + let max: i32 = self.alignment_pattern_centers.len(); + { + let mut x: i32 = 0; + while x < max { + { + let i: i32 = self.alignment_pattern_centers[x] - 2; + { + let mut y: i32 = 0; + while y < max { + { + if (x != 0 || (y != 0 && y != max - 1)) && (x != max - 1 || y != 0) { + bit_matrix.set_region(self.alignment_pattern_centers[y] - 2, i, 5, 5); + } + // else no o alignment patterns near the three finder patterns + } + y += 1; + } + } + + } + x += 1; + } + } + + // Vertical timing pattern + bit_matrix.set_region(6, 9, 1, dimension - 17); + // Horizontal timing pattern + bit_matrix.set_region(9, 6, dimension - 17, 1); + if self.version_number > 6 { + // Version info, top right + bit_matrix.set_region(dimension - 11, 0, 3, 6); + // Version info, bottom left + bit_matrix.set_region(0, dimension - 11, 6, 3); + } + return bit_matrix; + } + + /** + *

Encapsulates a set of error-correction blocks in one symbol version. Most versions will + * use blocks of differing sizes within one version, so, this encapsulates the parameters for + * each set of blocks. It also holds the number of error-correction codewords per block since it + * will be the same across all blocks within one version.

+ */ + pub struct ECBlocks { + + let ec_codewords_per_block: i32; + + let ec_blocks: Vec; + } + + impl ECBlocks { + + fn new( ec_codewords_per_block: i32, ec_blocks: &ECB) -> ECBlocks { + let .ecCodewordsPerBlock = ec_codewords_per_block; + let .ecBlocks = ec_blocks; + } + + pub fn get_e_c_codewords_per_block(&self) -> i32 { + return self.ec_codewords_per_block; + } + + pub fn get_num_blocks(&self) -> i32 { + let mut total: i32 = 0; + for let ec_block: ECB in self.ec_blocks { + total += ec_block.get_count(); + } + return total; + } + + pub fn get_total_e_c_codewords(&self) -> i32 { + return self.ec_codewords_per_block * self.get_num_blocks(); + } + + pub fn get_e_c_blocks(&self) -> Vec { + return self.ec_blocks; + } + } + + + /** + *

Encapsulates the parameters for one error-correction block in one symbol version. + * This includes the number of data codewords, and the number of times a block with these + * parameters is used consecutively in the QR code version's format.

+ */ + pub struct ECB { + + let count: i32; + + let data_codewords: i32; + } + + impl ECB { + + fn new( count: i32, data_codewords: i32) -> ECB { + let .count = count; + let .dataCodewords = data_codewords; + } + + pub fn get_count(&self) -> i32 { + return self.count; + } + + pub fn get_data_codewords(&self) -> i32 { + return self.data_codewords; + } + } + + + pub fn to_string(&self) -> String { + return String::value_of(self.version_number); + } + + /** + * See ISO 18004:2006 6.5.1 Table 9 + */ + fn build_versions() -> Vec { + return : vec![Version; 40] = vec![Version::new(1, , ECBlocks::new(7, ECB::new(1, 19)), ECBlocks::new(10, ECB::new(1, 16)), ECBlocks::new(13, ECB::new(1, 13)), ECBlocks::new(17, ECB::new(1, 9))), Version::new(2, : vec![i32; 2] = vec![6, 18, ] + , ECBlocks::new(10, ECB::new(1, 34)), ECBlocks::new(16, ECB::new(1, 28)), ECBlocks::new(22, ECB::new(1, 22)), ECBlocks::new(28, ECB::new(1, 16))), Version::new(3, : vec![i32; 2] = vec![6, 22, ] + , ECBlocks::new(15, ECB::new(1, 55)), ECBlocks::new(26, ECB::new(1, 44)), ECBlocks::new(18, ECB::new(2, 17)), ECBlocks::new(22, ECB::new(2, 13))), Version::new(4, : vec![i32; 2] = vec![6, 26, ] + , ECBlocks::new(20, ECB::new(1, 80)), ECBlocks::new(18, ECB::new(2, 32)), ECBlocks::new(26, ECB::new(2, 24)), ECBlocks::new(16, ECB::new(4, 9))), Version::new(5, : vec![i32; 2] = vec![6, 30, ] + , ECBlocks::new(26, ECB::new(1, 108)), ECBlocks::new(24, ECB::new(2, 43)), ECBlocks::new(18, ECB::new(2, 15), ECB::new(2, 16)), ECBlocks::new(22, ECB::new(2, 11), ECB::new(2, 12))), Version::new(6, : vec![i32; 2] = vec![6, 34, ] + , ECBlocks::new(18, ECB::new(2, 68)), ECBlocks::new(16, ECB::new(4, 27)), ECBlocks::new(24, ECB::new(4, 19)), ECBlocks::new(28, ECB::new(4, 15))), Version::new(7, : vec![i32; 3] = vec![6, 22, 38, ] + , ECBlocks::new(20, ECB::new(2, 78)), ECBlocks::new(18, ECB::new(4, 31)), ECBlocks::new(18, ECB::new(2, 14), ECB::new(4, 15)), ECBlocks::new(26, ECB::new(4, 13), ECB::new(1, 14))), Version::new(8, : vec![i32; 3] = vec![6, 24, 42, ] + , ECBlocks::new(24, ECB::new(2, 97)), ECBlocks::new(22, ECB::new(2, 38), ECB::new(2, 39)), ECBlocks::new(22, ECB::new(4, 18), ECB::new(2, 19)), ECBlocks::new(26, ECB::new(4, 14), ECB::new(2, 15))), Version::new(9, : vec![i32; 3] = vec![6, 26, 46, ] + , ECBlocks::new(30, ECB::new(2, 116)), ECBlocks::new(22, ECB::new(3, 36), ECB::new(2, 37)), ECBlocks::new(20, ECB::new(4, 16), ECB::new(4, 17)), ECBlocks::new(24, ECB::new(4, 12), ECB::new(4, 13))), Version::new(10, : vec![i32; 3] = vec![6, 28, 50, ] + , ECBlocks::new(18, ECB::new(2, 68), ECB::new(2, 69)), ECBlocks::new(26, ECB::new(4, 43), ECB::new(1, 44)), ECBlocks::new(24, ECB::new(6, 19), ECB::new(2, 20)), ECBlocks::new(28, ECB::new(6, 15), ECB::new(2, 16))), Version::new(11, : vec![i32; 3] = vec![6, 30, 54, ] + , ECBlocks::new(20, ECB::new(4, 81)), ECBlocks::new(30, ECB::new(1, 50), ECB::new(4, 51)), ECBlocks::new(28, ECB::new(4, 22), ECB::new(4, 23)), ECBlocks::new(24, ECB::new(3, 12), ECB::new(8, 13))), Version::new(12, : vec![i32; 3] = vec![6, 32, 58, ] + , ECBlocks::new(24, ECB::new(2, 92), ECB::new(2, 93)), ECBlocks::new(22, ECB::new(6, 36), ECB::new(2, 37)), ECBlocks::new(26, ECB::new(4, 20), ECB::new(6, 21)), ECBlocks::new(28, ECB::new(7, 14), ECB::new(4, 15))), Version::new(13, : vec![i32; 3] = vec![6, 34, 62, ] + , ECBlocks::new(26, ECB::new(4, 107)), ECBlocks::new(22, ECB::new(8, 37), ECB::new(1, 38)), ECBlocks::new(24, ECB::new(8, 20), ECB::new(4, 21)), ECBlocks::new(22, ECB::new(12, 11), ECB::new(4, 12))), Version::new(14, : vec![i32; 4] = vec![6, 26, 46, 66, ] + , ECBlocks::new(30, ECB::new(3, 115), ECB::new(1, 116)), ECBlocks::new(24, ECB::new(4, 40), ECB::new(5, 41)), ECBlocks::new(20, ECB::new(11, 16), ECB::new(5, 17)), ECBlocks::new(24, ECB::new(11, 12), ECB::new(5, 13))), Version::new(15, : vec![i32; 4] = vec![6, 26, 48, 70, ] + , ECBlocks::new(22, ECB::new(5, 87), ECB::new(1, 88)), ECBlocks::new(24, ECB::new(5, 41), ECB::new(5, 42)), ECBlocks::new(30, ECB::new(5, 24), ECB::new(7, 25)), ECBlocks::new(24, ECB::new(11, 12), ECB::new(7, 13))), Version::new(16, : vec![i32; 4] = vec![6, 26, 50, 74, ] + , ECBlocks::new(24, ECB::new(5, 98), ECB::new(1, 99)), ECBlocks::new(28, ECB::new(7, 45), ECB::new(3, 46)), ECBlocks::new(24, ECB::new(15, 19), ECB::new(2, 20)), ECBlocks::new(30, ECB::new(3, 15), ECB::new(13, 16))), Version::new(17, : vec![i32; 4] = vec![6, 30, 54, 78, ] + , ECBlocks::new(28, ECB::new(1, 107), ECB::new(5, 108)), ECBlocks::new(28, ECB::new(10, 46), ECB::new(1, 47)), ECBlocks::new(28, ECB::new(1, 22), ECB::new(15, 23)), ECBlocks::new(28, ECB::new(2, 14), ECB::new(17, 15))), Version::new(18, : vec![i32; 4] = vec![6, 30, 56, 82, ] + , ECBlocks::new(30, ECB::new(5, 120), ECB::new(1, 121)), ECBlocks::new(26, ECB::new(9, 43), ECB::new(4, 44)), ECBlocks::new(28, ECB::new(17, 22), ECB::new(1, 23)), ECBlocks::new(28, ECB::new(2, 14), ECB::new(19, 15))), Version::new(19, : vec![i32; 4] = vec![6, 30, 58, 86, ] + , ECBlocks::new(28, ECB::new(3, 113), ECB::new(4, 114)), ECBlocks::new(26, ECB::new(3, 44), ECB::new(11, 45)), ECBlocks::new(26, ECB::new(17, 21), ECB::new(4, 22)), ECBlocks::new(26, ECB::new(9, 13), ECB::new(16, 14))), Version::new(20, : vec![i32; 4] = vec![6, 34, 62, 90, ] + , ECBlocks::new(28, ECB::new(3, 107), ECB::new(5, 108)), ECBlocks::new(26, ECB::new(3, 41), ECB::new(13, 42)), ECBlocks::new(30, ECB::new(15, 24), ECB::new(5, 25)), ECBlocks::new(28, ECB::new(15, 15), ECB::new(10, 16))), Version::new(21, : vec![i32; 5] = vec![6, 28, 50, 72, 94, ] + , ECBlocks::new(28, ECB::new(4, 116), ECB::new(4, 117)), ECBlocks::new(26, ECB::new(17, 42)), ECBlocks::new(28, ECB::new(17, 22), ECB::new(6, 23)), ECBlocks::new(30, ECB::new(19, 16), ECB::new(6, 17))), Version::new(22, : vec![i32; 5] = vec![6, 26, 50, 74, 98, ] + , ECBlocks::new(28, ECB::new(2, 111), ECB::new(7, 112)), ECBlocks::new(28, ECB::new(17, 46)), ECBlocks::new(30, ECB::new(7, 24), ECB::new(16, 25)), ECBlocks::new(24, ECB::new(34, 13))), Version::new(23, : vec![i32; 5] = vec![6, 30, 54, 78, 102, ] + , ECBlocks::new(30, ECB::new(4, 121), ECB::new(5, 122)), ECBlocks::new(28, ECB::new(4, 47), ECB::new(14, 48)), ECBlocks::new(30, ECB::new(11, 24), ECB::new(14, 25)), ECBlocks::new(30, ECB::new(16, 15), ECB::new(14, 16))), Version::new(24, : vec![i32; 5] = vec![6, 28, 54, 80, 106, ] + , ECBlocks::new(30, ECB::new(6, 117), ECB::new(4, 118)), ECBlocks::new(28, ECB::new(6, 45), ECB::new(14, 46)), ECBlocks::new(30, ECB::new(11, 24), ECB::new(16, 25)), ECBlocks::new(30, ECB::new(30, 16), ECB::new(2, 17))), Version::new(25, : vec![i32; 5] = vec![6, 32, 58, 84, 110, ] + , ECBlocks::new(26, ECB::new(8, 106), ECB::new(4, 107)), ECBlocks::new(28, ECB::new(8, 47), ECB::new(13, 48)), ECBlocks::new(30, ECB::new(7, 24), ECB::new(22, 25)), ECBlocks::new(30, ECB::new(22, 15), ECB::new(13, 16))), Version::new(26, : vec![i32; 5] = vec![6, 30, 58, 86, 114, ] + , ECBlocks::new(28, ECB::new(10, 114), ECB::new(2, 115)), ECBlocks::new(28, ECB::new(19, 46), ECB::new(4, 47)), ECBlocks::new(28, ECB::new(28, 22), ECB::new(6, 23)), ECBlocks::new(30, ECB::new(33, 16), ECB::new(4, 17))), Version::new(27, : vec![i32; 5] = vec![6, 34, 62, 90, 118, ] + , ECBlocks::new(30, ECB::new(8, 122), ECB::new(4, 123)), ECBlocks::new(28, ECB::new(22, 45), ECB::new(3, 46)), ECBlocks::new(30, ECB::new(8, 23), ECB::new(26, 24)), ECBlocks::new(30, ECB::new(12, 15), ECB::new(28, 16))), Version::new(28, : vec![i32; 6] = vec![6, 26, 50, 74, 98, 122, ] + , ECBlocks::new(30, ECB::new(3, 117), ECB::new(10, 118)), ECBlocks::new(28, ECB::new(3, 45), ECB::new(23, 46)), ECBlocks::new(30, ECB::new(4, 24), ECB::new(31, 25)), ECBlocks::new(30, ECB::new(11, 15), ECB::new(31, 16))), Version::new(29, : vec![i32; 6] = vec![6, 30, 54, 78, 102, 126, ] + , ECBlocks::new(30, ECB::new(7, 116), ECB::new(7, 117)), ECBlocks::new(28, ECB::new(21, 45), ECB::new(7, 46)), ECBlocks::new(30, ECB::new(1, 23), ECB::new(37, 24)), ECBlocks::new(30, ECB::new(19, 15), ECB::new(26, 16))), Version::new(30, : vec![i32; 6] = vec![6, 26, 52, 78, 104, 130, ] + , ECBlocks::new(30, ECB::new(5, 115), ECB::new(10, 116)), ECBlocks::new(28, ECB::new(19, 47), ECB::new(10, 48)), ECBlocks::new(30, ECB::new(15, 24), ECB::new(25, 25)), ECBlocks::new(30, ECB::new(23, 15), ECB::new(25, 16))), Version::new(31, : vec![i32; 6] = vec![6, 30, 56, 82, 108, 134, ] + , ECBlocks::new(30, ECB::new(13, 115), ECB::new(3, 116)), ECBlocks::new(28, ECB::new(2, 46), ECB::new(29, 47)), ECBlocks::new(30, ECB::new(42, 24), ECB::new(1, 25)), ECBlocks::new(30, ECB::new(23, 15), ECB::new(28, 16))), Version::new(32, : vec![i32; 6] = vec![6, 34, 60, 86, 112, 138, ] + , ECBlocks::new(30, ECB::new(17, 115)), ECBlocks::new(28, ECB::new(10, 46), ECB::new(23, 47)), ECBlocks::new(30, ECB::new(10, 24), ECB::new(35, 25)), ECBlocks::new(30, ECB::new(19, 15), ECB::new(35, 16))), Version::new(33, : vec![i32; 6] = vec![6, 30, 58, 86, 114, 142, ] + , ECBlocks::new(30, ECB::new(17, 115), ECB::new(1, 116)), ECBlocks::new(28, ECB::new(14, 46), ECB::new(21, 47)), ECBlocks::new(30, ECB::new(29, 24), ECB::new(19, 25)), ECBlocks::new(30, ECB::new(11, 15), ECB::new(46, 16))), Version::new(34, : vec![i32; 6] = vec![6, 34, 62, 90, 118, 146, ] + , ECBlocks::new(30, ECB::new(13, 115), ECB::new(6, 116)), ECBlocks::new(28, ECB::new(14, 46), ECB::new(23, 47)), ECBlocks::new(30, ECB::new(44, 24), ECB::new(7, 25)), ECBlocks::new(30, ECB::new(59, 16), ECB::new(1, 17))), Version::new(35, : vec![i32; 7] = vec![6, 30, 54, 78, 102, 126, 150, ] + , ECBlocks::new(30, ECB::new(12, 121), ECB::new(7, 122)), ECBlocks::new(28, ECB::new(12, 47), ECB::new(26, 48)), ECBlocks::new(30, ECB::new(39, 24), ECB::new(14, 25)), ECBlocks::new(30, ECB::new(22, 15), ECB::new(41, 16))), Version::new(36, : vec![i32; 7] = vec![6, 24, 50, 76, 102, 128, 154, ] + , ECBlocks::new(30, ECB::new(6, 121), ECB::new(14, 122)), ECBlocks::new(28, ECB::new(6, 47), ECB::new(34, 48)), ECBlocks::new(30, ECB::new(46, 24), ECB::new(10, 25)), ECBlocks::new(30, ECB::new(2, 15), ECB::new(64, 16))), Version::new(37, : vec![i32; 7] = vec![6, 28, 54, 80, 106, 132, 158, ] + , ECBlocks::new(30, ECB::new(17, 122), ECB::new(4, 123)), ECBlocks::new(28, ECB::new(29, 46), ECB::new(14, 47)), ECBlocks::new(30, ECB::new(49, 24), ECB::new(10, 25)), ECBlocks::new(30, ECB::new(24, 15), ECB::new(46, 16))), Version::new(38, : vec![i32; 7] = vec![6, 32, 58, 84, 110, 136, 162, ] + , ECBlocks::new(30, ECB::new(4, 122), ECB::new(18, 123)), ECBlocks::new(28, ECB::new(13, 46), ECB::new(32, 47)), ECBlocks::new(30, ECB::new(48, 24), ECB::new(14, 25)), ECBlocks::new(30, ECB::new(42, 15), ECB::new(32, 16))), Version::new(39, : vec![i32; 7] = vec![6, 26, 54, 82, 110, 138, 166, ] + , ECBlocks::new(30, ECB::new(20, 117), ECB::new(4, 118)), ECBlocks::new(28, ECB::new(40, 47), ECB::new(7, 48)), ECBlocks::new(30, ECB::new(43, 24), ECB::new(22, 25)), ECBlocks::new(30, ECB::new(10, 15), ECB::new(67, 16))), Version::new(40, : vec![i32; 7] = vec![6, 30, 58, 86, 114, 142, 170, ] + , ECBlocks::new(30, ECB::new(19, 118), ECB::new(6, 119)), ECBlocks::new(28, ECB::new(18, 47), ECB::new(31, 48)), ECBlocks::new(30, ECB::new(34, 24), ECB::new(34, 25)), ECBlocks::new(30, ECB::new(20, 15), ECB::new(61, 16))), ] + ; + } +} + diff --git a/src/qrcode/detector.rs b/src/qrcode/detector.rs index e69de29..d278d90 100644 --- a/src/qrcode/detector.rs +++ b/src/qrcode/detector.rs @@ -0,0 +1,1549 @@ +// NEW FILE: alignment_pattern.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::detector; + +/** + *

Encapsulates an alignment pattern, which are the smaller square patterns found in + * all but the simplest QR Codes.

+ * + * @author Sean Owen + */ +pub struct AlignmentPattern { + super: ResultPoint; + + let estimated_module_size: f32; +} + +impl AlignmentPattern { + + fn new( pos_x: f32, pos_y: f32, estimated_module_size: f32) -> AlignmentPattern { + super(pos_x, pos_y); + let .estimatedModuleSize = estimated_module_size; + } + + /** + *

Determines if this alignment pattern "about equals" an alignment pattern at the stated + * position and size -- meaning, it is at nearly the same center with nearly the same size.

+ */ + fn about_equals(&self, module_size: f32, i: f32, j: f32) -> bool { + if Math::abs(i - get_y()) <= module_size && Math::abs(j - get_x()) <= module_size { + let module_size_diff: f32 = Math::abs(module_size - self.estimated_module_size); + return module_size_diff <= 1.0f || module_size_diff <= self.estimated_module_size; + } + return false; + } + + /** + * Combines this object's current estimate of a finder pattern position and module size + * with a new estimate. It returns a new {@code FinderPattern} containing an average of the two. + */ + fn combine_estimate(&self, i: f32, j: f32, new_module_size: f32) -> AlignmentPattern { + let combined_x: f32 = (get_x() + j) / 2.0f; + let combined_y: f32 = (get_y() + i) / 2.0f; + let combined_module_size: f32 = (self.estimated_module_size + new_module_size) / 2.0f; + return AlignmentPattern::new(combined_x, combined_y, combined_module_size); + } +} + +// NEW FILE: alignment_pattern_finder.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::detector; + +/** + *

This class attempts to find alignment patterns in a QR Code. Alignment patterns look like finder + * patterns but are smaller and appear at regular intervals throughout the image.

+ * + *

At the moment this only looks for the bottom-right alignment pattern.

+ * + *

This is mostly a simplified copy of {@link FinderPatternFinder}. It is copied, + * pasted and stripped down here for maximum performance but does unfortunately duplicate + * some code.

+ * + *

This class is thread-safe but not reentrant. Each thread must allocate its own object.

+ * + * @author Sean Owen + */ +struct AlignmentPatternFinder { + + let image: BitMatrix; + + let possible_centers: List; + + let start_x: i32; + + let start_y: i32; + + let width: i32; + + let height: i32; + + let module_size: f32; + + let cross_check_state_count: Vec; + + let result_point_callback: ResultPointCallback; +} + +impl AlignmentPatternFinder { + + /** + *

Creates a finder that will look in a portion of the whole image.

+ * + * @param image image to search + * @param startX left column from which to start searching + * @param startY top row from which to start searching + * @param width width of region to search + * @param height height of region to search + * @param moduleSize estimated module size so far + */ + fn new( image: &BitMatrix, start_x: i32, start_y: i32, width: i32, height: i32, module_size: f32, result_point_callback: &ResultPointCallback) -> AlignmentPatternFinder { + let .image = image; + let .possibleCenters = ArrayList<>::new(5); + let .startX = start_x; + let .startY = start_y; + let .width = width; + let .height = height; + let .moduleSize = module_size; + let .crossCheckStateCount = : [i32; 3] = [0; 3]; + let .resultPointCallback = result_point_callback; + } + + /** + *

This method attempts to find the bottom-right alignment pattern in the image. It is a bit messy since + * it's pretty performance-critical and so is written to be fast foremost.

+ * + * @return {@link AlignmentPattern} if found + * @throws NotFoundException if not found + */ + fn find(&self) -> /* throws NotFoundException */Result> { + let start_x: i32 = self.startX; + let height: i32 = self.height; + let max_j: i32 = start_x + self.width; + let middle_i: i32 = self.start_y + (height / 2); + // We are looking for black/white/black modules in 1:1:1 ratio; + // this tracks the number of black/white/black modules seen so far + let state_count: [i32; 3] = [0; 3]; + { + let i_gen: i32 = 0; + while i_gen < height { + { + // Search from middle outwards + let i: i32 = middle_i + ( if (i_gen & 0x01) == 0 { (i_gen + 1) / 2 } else { -((i_gen + 1) / 2) }); + state_count[0] = 0; + state_count[1] = 0; + state_count[2] = 0; + let mut j: i32 = start_x; + // white run continued to the left of the start point + while j < max_j && !self.image.get(j, i) { + j += 1; + } + let current_state: i32 = 0; + while j < max_j { + if self.image.get(j, i) { + // Black pixel + if current_state == 1 { + // Counting black pixels + state_count[1] += 1; + } else { + // Counting white pixels + if current_state == 2 { + // A winner? + if self.found_pattern_cross(&state_count) { + // Yes + let confirmed: AlignmentPattern = self.handle_possible_center(&state_count, i, j); + if confirmed != null { + return Ok(confirmed); + } + } + state_count[0] = state_count[2]; + state_count[1] = 1; + state_count[2] = 0; + current_state = 1; + } else { + state_count[current_state += 1] += 1; + } + } + } else { + // White pixel + if current_state == 1 { + // Counting black pixels + current_state += 1; + } + state_count[current_state] += 1; + } + j += 1; + } + if self.found_pattern_cross(&state_count) { + let confirmed: AlignmentPattern = self.handle_possible_center(&state_count, i, max_j); + if confirmed != null { + return Ok(confirmed); + } + } + } + i_gen += 1; + } + } + + // any guess at all, return it. + if !self.possible_centers.is_empty() { + return Ok(self.possible_centers.get(0)); + } + throw NotFoundException::get_not_found_instance(); + } + + /** + * Given a count of black/white/black pixels just seen and an end position, + * figures the location of the center of this black/white/black run. + */ + fn center_from_end( state_count: &Vec, end: i32) -> f32 { + return (end - state_count[2]) - state_count[1] / 2.0f; + } + + /** + * @param stateCount count of black/white/black pixels just read + * @return true iff the proportions of the counts is close enough to the 1/1/1 ratios + * used by alignment patterns to be considered a match + */ + fn found_pattern_cross(&self, state_count: &Vec) -> bool { + let module_size: f32 = self.moduleSize; + let max_variance: f32 = module_size / 2.0f; + { + let mut i: i32 = 0; + while i < 3 { + { + if Math::abs(module_size - state_count[i]) >= max_variance { + return false; + } + } + i += 1; + } + } + + return true; + } + + /** + *

After a horizontal scan finds a potential alignment pattern, this method + * "cross-checks" by scanning down vertically through the center of the possible + * alignment pattern to see if the same proportion is detected.

+ * + * @param startI row where an alignment pattern was detected + * @param centerJ center of the section that appears to cross an alignment pattern + * @param maxCount maximum reasonable number of modules that should be + * observed in any reading state, based on the results of the horizontal scan + * @return vertical center of alignment pattern, or {@link Float#NaN} if not found + */ + fn cross_check_vertical(&self, start_i: i32, center_j: i32, max_count: i32, original_state_count_total: i32) -> f32 { + let image: BitMatrix = self.image; + let max_i: i32 = image.get_height(); + let state_count: Vec = self.cross_check_state_count; + state_count[0] = 0; + state_count[1] = 0; + state_count[2] = 0; + // Start counting up from center + let mut i: i32 = start_i; + while i >= 0 && image.get(center_j, i) && state_count[1] <= max_count { + state_count[1] += 1; + i -= 1; + } + // If already too many modules in this state or ran off the edge: + if i < 0 || state_count[1] > max_count { + return Float::NaN; + } + while i >= 0 && !image.get(center_j, i) && state_count[0] <= max_count { + state_count[0] += 1; + i -= 1; + } + if state_count[0] > max_count { + return Float::NaN; + } + // Now also count down from center + i = start_i + 1; + while i < max_i && image.get(center_j, i) && state_count[1] <= max_count { + state_count[1] += 1; + i += 1; + } + if i == max_i || state_count[1] > max_count { + return Float::NaN; + } + while i < max_i && !image.get(center_j, i) && state_count[2] <= max_count { + state_count[2] += 1; + i += 1; + } + if state_count[2] > max_count { + return Float::NaN; + } + let state_count_total: i32 = state_count[0] + state_count[1] + state_count[2]; + if 5 * Math::abs(state_count_total - original_state_count_total) >= 2 * original_state_count_total { + return Float::NaN; + } + return if self.found_pattern_cross(&state_count) { ::center_from_end(&state_count, i) } else { Float::NaN }; + } + + /** + *

This is called when a horizontal scan finds a possible alignment pattern. It will + * cross check with a vertical scan, and if successful, will see if this pattern had been + * found on a previous horizontal scan. If so, we consider it confirmed and conclude we have + * found the alignment pattern.

+ * + * @param stateCount reading state module counts from horizontal scan + * @param i row where alignment pattern may be found + * @param j end of possible alignment pattern in row + * @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not + */ + fn handle_possible_center(&self, state_count: &Vec, i: i32, j: i32) -> AlignmentPattern { + let state_count_total: i32 = state_count[0] + state_count[1] + state_count[2]; + let center_j: f32 = ::center_from_end(&state_count, j); + let center_i: f32 = self.cross_check_vertical(i, center_j as i32, 2 * state_count[1], state_count_total); + if !Float::is_na_n(center_i) { + let estimated_module_size: f32 = (state_count[0] + state_count[1] + state_count[2]) / 3.0f; + for let center: AlignmentPattern in self.possible_centers { + // Look for about the same center and module size: + if center.about_equals(estimated_module_size, center_i, center_j) { + return center.combine_estimate(center_i, center_j, estimated_module_size); + } + } + // Hadn't found this before; save it + let point: AlignmentPattern = AlignmentPattern::new(center_j, center_i, estimated_module_size); + self.possible_centers.add(point); + if self.result_point_callback != null { + self.result_point_callback.found_possible_result_point(point); + } + } + return null; + } +} + +// NEW FILE: detector.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::detector; + +/** + *

Encapsulates logic that can detect a QR Code in an image, even if the QR Code + * is rotated or skewed, or partially obscured.

+ * + * @author Sean Owen + */ +pub struct Detector { + + let image: BitMatrix; + + let result_point_callback: ResultPointCallback; +} + +impl Detector { + + pub fn new( image: &BitMatrix) -> Detector { + let .image = image; + } + + pub fn get_image(&self) -> BitMatrix { + return self.image; + } + + pub fn get_result_point_callback(&self) -> ResultPointCallback { + return self.result_point_callback; + } + + /** + *

Detects a QR Code in an image.

+ * + * @return {@link DetectorResult} encapsulating results of detecting a QR Code + * @throws NotFoundException if QR Code cannot be found + * @throws FormatException if a QR Code cannot be decoded + */ + pub fn detect(&self) -> /* throws NotFoundException, FormatException */Result> { + return Ok(self.detect(null)); + } + + /** + *

Detects a QR Code in an image.

+ * + * @param hints optional hints to detector + * @return {@link DetectorResult} encapsulating results of detecting a QR Code + * @throws NotFoundException if QR Code cannot be found + * @throws FormatException if a QR Code cannot be decoded + */ + pub fn detect(&self, hints: &Map) -> /* throws NotFoundException, FormatException */Result> { + self.result_point_callback = if hints == null { null } else { hints.get(DecodeHintType::NEED_RESULT_POINT_CALLBACK) as ResultPointCallback }; + let finder: FinderPatternFinder = FinderPatternFinder::new(self.image, self.result_point_callback); + let info: FinderPatternInfo = finder.find(&hints); + return Ok(self.process_finder_pattern_info(info)); + } + + pub fn process_finder_pattern_info(&self, info: &FinderPatternInfo) -> /* throws NotFoundException, FormatException */Result> { + let top_left: FinderPattern = info.get_top_left(); + let top_right: FinderPattern = info.get_top_right(); + let bottom_left: FinderPattern = info.get_bottom_left(); + let module_size: f32 = self.calculate_module_size(top_left, top_right, bottom_left); + if module_size < 1.0f { + throw NotFoundException::get_not_found_instance(); + } + let dimension: i32 = ::compute_dimension(top_left, top_right, bottom_left, module_size); + let provisional_version: Version = Version::get_provisional_version_for_dimension(dimension); + let modules_between_f_p_centers: i32 = provisional_version.get_dimension_for_version() - 7; + let alignment_pattern: AlignmentPattern = null; + // Anything above version 1 has an alignment pattern + if provisional_version.get_alignment_pattern_centers().len() > 0 { + // Guess where a "bottom right" finder pattern would have been + let bottom_right_x: f32 = top_right.get_x() - top_left.get_x() + bottom_left.get_x(); + let bottom_right_y: f32 = top_right.get_y() - top_left.get_y() + bottom_left.get_y(); + // Estimate that alignment pattern is closer by 3 modules + // from "bottom right" to known top left location + let correction_to_top_left: f32 = 1.0f - 3.0f / modules_between_f_p_centers; + let est_alignment_x: i32 = (top_left.get_x() + correction_to_top_left * (bottom_right_x - top_left.get_x())) as i32; + let est_alignment_y: i32 = (top_left.get_y() + correction_to_top_left * (bottom_right_y - top_left.get_y())) as i32; + // Kind of arbitrary -- expand search radius before giving up + { + let mut i: i32 = 4; + while i <= 16 { + { + let tryResult1 = 0; + 'try1: loop { + { + alignment_pattern = self.find_alignment_in_region(module_size, est_alignment_x, est_alignment_y, i); + break; + } + break 'try1 + } + match tryResult1 { + catch ( re: &NotFoundException) { + } 0 => break + } + + } + i <<= 1; + } + } + + // If we didn't find alignment pattern... well try anyway without it + } + let transform: PerspectiveTransform = ::create_transform(top_left, top_right, bottom_left, alignment_pattern, dimension); + let bits: BitMatrix = ::sample_grid(self.image, transform, dimension); + let mut points: Vec; + if alignment_pattern == null { + points = : vec![ResultPoint; 3] = vec![bottom_left, top_left, top_right, ] + ; + } else { + points = : vec![ResultPoint; 4] = vec![bottom_left, top_left, top_right, alignment_pattern, ] + ; + } + return Ok(DetectorResult::new(bits, points)); + } + + fn create_transform( top_left: &ResultPoint, top_right: &ResultPoint, bottom_left: &ResultPoint, alignment_pattern: &ResultPoint, dimension: i32) -> PerspectiveTransform { + let dim_minus_three: f32 = dimension - 3.5f; + let bottom_right_x: f32; + let bottom_right_y: f32; + let source_bottom_right_x: f32; + let source_bottom_right_y: f32; + if alignment_pattern != null { + bottom_right_x = alignment_pattern.get_x(); + bottom_right_y = alignment_pattern.get_y(); + source_bottom_right_x = dim_minus_three - 3.0f; + source_bottom_right_y = source_bottom_right_x; + } else { + // Don't have an alignment pattern, just make up the bottom-right point + bottom_right_x = (top_right.get_x() - top_left.get_x()) + bottom_left.get_x(); + bottom_right_y = (top_right.get_y() - top_left.get_y()) + bottom_left.get_y(); + source_bottom_right_x = dim_minus_three; + source_bottom_right_y = dim_minus_three; + } + return PerspectiveTransform::quadrilateral_to_quadrilateral(3.5f, 3.5f, dim_minus_three, 3.5f, source_bottom_right_x, source_bottom_right_y, 3.5f, dim_minus_three, &top_left.get_x(), &top_left.get_y(), &top_right.get_x(), &top_right.get_y(), bottom_right_x, bottom_right_y, &bottom_left.get_x(), &bottom_left.get_y()); + } + + fn sample_grid( image: &BitMatrix, transform: &PerspectiveTransform, dimension: i32) -> /* throws NotFoundException */Result> { + let sampler: GridSampler = GridSampler::get_instance(); + return Ok(sampler.sample_grid(image, dimension, dimension, transform)); + } + + /** + *

Computes the dimension (number of modules on a size) of the QR Code based on the position + * of the finder patterns and estimated module size.

+ */ + fn compute_dimension( top_left: &ResultPoint, top_right: &ResultPoint, bottom_left: &ResultPoint, module_size: f32) -> /* throws NotFoundException */Result> { + let tltr_centers_dimension: i32 = MathUtils::round(ResultPoint::distance(top_left, top_right) / module_size); + let tlbl_centers_dimension: i32 = MathUtils::round(ResultPoint::distance(top_left, bottom_left) / module_size); + let mut dimension: i32 = ((tltr_centers_dimension + tlbl_centers_dimension) / 2) + 7; + match // mod 4 + dimension & 0x03 { + 0 => + { + dimension += 1; + break; + } + // 1? do nothing + 2 => + { + dimension -= 1; + break; + } + 3 => + { + throw NotFoundException::get_not_found_instance(); + } + } + return Ok(dimension); + } + + /** + *

Computes an average estimated module size based on estimated derived from the positions + * of the three finder patterns.

+ * + * @param topLeft detected top-left finder pattern center + * @param topRight detected top-right finder pattern center + * @param bottomLeft detected bottom-left finder pattern center + * @return estimated module size + */ + pub fn calculate_module_size(&self, top_left: &ResultPoint, top_right: &ResultPoint, bottom_left: &ResultPoint) -> f32 { + // Take the average + return (self.calculate_module_size_one_way(top_left, top_right) + self.calculate_module_size_one_way(top_left, bottom_left)) / 2.0f; + } + + /** + *

Estimates module size based on two finder patterns -- it uses + * {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the + * width of each, measuring along the axis between their centers.

+ */ + fn calculate_module_size_one_way(&self, pattern: &ResultPoint, other_pattern: &ResultPoint) -> f32 { + let module_size_est1: f32 = self.size_of_black_white_black_run_both_ways(pattern.get_x() as i32, pattern.get_y() as i32, other_pattern.get_x() as i32, other_pattern.get_y() as i32); + let module_size_est2: f32 = self.size_of_black_white_black_run_both_ways(other_pattern.get_x() as i32, other_pattern.get_y() as i32, pattern.get_x() as i32, pattern.get_y() as i32); + if Float::is_na_n(module_size_est1) { + return module_size_est2 / 7.0f; + } + if Float::is_na_n(module_size_est2) { + return module_size_est1 / 7.0f; + } + // and 1 white and 1 black module on either side. Ergo, divide sum by 14. + return (module_size_est1 + module_size_est2) / 14.0f; + } + + /** + * See {@link #sizeOfBlackWhiteBlackRun(int, int, int, int)}; computes the total width of + * a finder pattern by looking for a black-white-black run from the center in the direction + * of another point (another finder pattern center), and in the opposite direction too. + */ + fn size_of_black_white_black_run_both_ways(&self, from_x: i32, from_y: i32, to_x: i32, to_y: i32) -> f32 { + let mut result: f32 = self.size_of_black_white_black_run(from_x, from_y, to_x, to_y); + // Now count other way -- don't run off image though of course + let mut scale: f32 = 1.0f; + let other_to_x: i32 = from_x - (to_x - from_x); + if other_to_x < 0 { + scale = from_x / (from_x - other_to_x) as f32; + other_to_x = 0; + } else if other_to_x >= self.image.get_width() { + scale = (self.image.get_width() - 1.0 - from_x) / (other_to_x - from_x) as f32; + other_to_x = self.image.get_width() - 1; + } + let other_to_y: i32 = (from_y - (to_y - from_y) * scale) as i32; + scale = 1.0f; + if other_to_y < 0 { + scale = from_y / (from_y - other_to_y) as f32; + other_to_y = 0; + } else if other_to_y >= self.image.get_height() { + scale = (self.image.get_height() - 1.0 - from_y) / (other_to_y - from_y) as f32; + other_to_y = self.image.get_height() - 1; + } + other_to_x = (from_x + (other_to_x - from_x) * scale) as i32; + result += self.size_of_black_white_black_run(from_x, from_y, other_to_x, other_to_y); + // Middle pixel is double-counted this way; subtract 1 + return result - 1.0f; + } + + /** + *

This method traces a line from a point in the image, in the direction towards another point. + * It begins in a black region, and keeps going until it finds white, then black, then white again. + * It reports the distance from the start to this point.

+ * + *

This is used when figuring out how wide a finder pattern is, when the finder pattern + * may be skewed or rotated.

+ */ + fn size_of_black_white_black_run(&self, from_x: i32, from_y: i32, to_x: i32, to_y: i32) -> f32 { + // Mild variant of Bresenham's algorithm; + // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm + let steep: bool = Math::abs(to_y - from_y) > Math::abs(to_x - from_x); + if steep { + let mut temp: i32 = from_x; + from_x = from_y; + from_y = temp; + temp = to_x; + to_x = to_y; + to_y = temp; + } + let dx: i32 = Math::abs(to_x - from_x); + let dy: i32 = Math::abs(to_y - from_y); + let mut error: i32 = -dx / 2; + let xstep: i32 = if from_x < to_x { 1 } else { -1 }; + let ystep: i32 = if from_y < to_y { 1 } else { -1 }; + // In black pixels, looking for white, first or second time. + let mut state: i32 = 0; + // Loop up until x == toX, but not beyond + let x_limit: i32 = to_x + xstep; + { + let mut x: i32 = from_x, let mut y: i32 = from_y; + while x != x_limit { + { + let real_x: i32 = if steep { y } else { x }; + let real_y: i32 = if steep { x } else { y }; + // color, advance to next state or end if we are in state 2 already + if (state == 1) == self.image.get(real_x, real_y) { + if state == 2 { + return MathUtils::distance(x, y, from_x, from_y); + } + state += 1; + } + error += dy; + if error > 0 { + if y == to_y { + break; + } + y += ystep; + error -= dx; + } + } + x += xstep; + } + } + + // small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this. + if state == 2 { + return MathUtils::distance(to_x + xstep, to_y, from_x, from_y); + } + // else we didn't find even black-white-black; no estimate is really possible + return Float::NaN; + } + + /** + *

Attempts to locate an alignment pattern in a limited region of the image, which is + * guessed to contain it. This method uses {@link AlignmentPattern}.

+ * + * @param overallEstModuleSize estimated module size so far + * @param estAlignmentX x coordinate of center of area probably containing alignment pattern + * @param estAlignmentY y coordinate of above + * @param allowanceFactor number of pixels in all directions to search from the center + * @return {@link AlignmentPattern} if found, or null otherwise + * @throws NotFoundException if an unexpected error occurs during detection + */ + pub fn find_alignment_in_region(&self, overall_est_module_size: f32, est_alignment_x: i32, est_alignment_y: i32, allowance_factor: f32) -> /* throws NotFoundException */Result> { + // Look for an alignment pattern (3 modules in size) around where it + // should be + let allowance: i32 = (allowance_factor * overall_est_module_size) as i32; + let alignment_area_left_x: i32 = Math::max(0, est_alignment_x - allowance); + let alignment_area_right_x: i32 = Math::min(self.image.get_width() - 1, est_alignment_x + allowance); + if alignment_area_right_x - alignment_area_left_x < overall_est_module_size * 3.0 { + throw NotFoundException::get_not_found_instance(); + } + let alignment_area_top_y: i32 = Math::max(0, est_alignment_y - allowance); + let alignment_area_bottom_y: i32 = Math::min(self.image.get_height() - 1, est_alignment_y + allowance); + if alignment_area_bottom_y - alignment_area_top_y < overall_est_module_size * 3.0 { + throw NotFoundException::get_not_found_instance(); + } + let alignment_finder: AlignmentPatternFinder = AlignmentPatternFinder::new(self.image, alignment_area_left_x, alignment_area_top_y, alignment_area_right_x - alignment_area_left_x, alignment_area_bottom_y - alignment_area_top_y, overall_est_module_size, self.result_point_callback); + return Ok(alignment_finder.find()); + } +} + +// NEW FILE: finder_pattern.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::detector; + +/** + *

Encapsulates a finder pattern, which are the three square patterns found in + * the corners of QR Codes. It also encapsulates a count of similar finder patterns, + * as a convenience to the finder's bookkeeping.

+ * + * @author Sean Owen + */ +pub struct FinderPattern { + super: ResultPoint; + + let estimated_module_size: f32; + + let count: i32; +} + +impl FinderPattern { + + fn new( pos_x: f32, pos_y: f32, estimated_module_size: f32) -> FinderPattern { + this(pos_x, pos_y, estimated_module_size, 1); + } + + fn new( pos_x: f32, pos_y: f32, estimated_module_size: f32, count: i32) -> FinderPattern { + super(pos_x, pos_y); + let .estimatedModuleSize = estimated_module_size; + let .count = count; + } + + pub fn get_estimated_module_size(&self) -> f32 { + return self.estimated_module_size; + } + + pub fn get_count(&self) -> i32 { + return self.count; + } + + /** + *

Determines if this finder pattern "about equals" a finder pattern at the stated + * position and size -- meaning, it is at nearly the same center with nearly the same size.

+ */ + fn about_equals(&self, module_size: f32, i: f32, j: f32) -> bool { + if Math::abs(i - get_y()) <= module_size && Math::abs(j - get_x()) <= module_size { + let module_size_diff: f32 = Math::abs(module_size - self.estimated_module_size); + return module_size_diff <= 1.0f || module_size_diff <= self.estimated_module_size; + } + return false; + } + + /** + * Combines this object's current estimate of a finder pattern position and module size + * with a new estimate. It returns a new {@code FinderPattern} containing a weighted average + * based on count. + */ + fn combine_estimate(&self, i: f32, j: f32, new_module_size: f32) -> FinderPattern { + let combined_count: i32 = self.count + 1; + let combined_x: f32 = (self.count * get_x() + j) / combined_count; + let combined_y: f32 = (self.count * get_y() + i) / combined_count; + let combined_module_size: f32 = (self.count * self.estimated_module_size + new_module_size) / combined_count; + return FinderPattern::new(combined_x, combined_y, combined_module_size, combined_count); + } +} + +// NEW FILE: finder_pattern_finder.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::detector; + +/** + *

This class attempts to find finder patterns in a QR Code. Finder patterns are the square + * markers at three corners of a QR Code.

+ * + *

This class is thread-safe but not reentrant. Each thread must allocate its own object. + * + * @author Sean Owen + */ + + const CENTER_QUORUM: i32 = 2; + + let module_comparator: EstimatedModuleComparator = EstimatedModuleComparator::new(); + +// 1 pixel/module times 3 modules/center + const MIN_SKIP: i32 = 3; + +// support up to version 20 for mobile clients + const MAX_MODULES: i32 = 97; +pub struct FinderPatternFinder { + + let image: BitMatrix; + + let possible_centers: List; + + let has_skipped: bool; + + let cross_check_state_count: Vec; + + let result_point_callback: ResultPointCallback; +} + +impl FinderPatternFinder { + + /** + *

Creates a finder that will search the image for three finder patterns.

+ * + * @param image image to search + */ + pub fn new( image: &BitMatrix) -> FinderPatternFinder { + this(image, null); + } + + pub fn new( image: &BitMatrix, result_point_callback: &ResultPointCallback) -> FinderPatternFinder { + let .image = image; + let .possibleCenters = ArrayList<>::new(); + let .crossCheckStateCount = : [i32; 5] = [0; 5]; + let .resultPointCallback = result_point_callback; + } + + pub fn get_image(&self) -> BitMatrix { + return self.image; + } + + pub fn get_possible_centers(&self) -> List { + return self.possible_centers; + } + + fn find(&self, hints: &Map) -> /* throws NotFoundException */Result> { + let try_harder: bool = hints != null && hints.contains_key(DecodeHintType::TRY_HARDER); + let max_i: i32 = self.image.get_height(); + let max_j: i32 = self.image.get_width(); + // We are looking for black/white/black/white/black modules in + // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far + // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the + // image, and then account for the center being 3 modules in size. This gives the smallest + // number of pixels the center could be, so skip this often. When trying harder, look for all + // QR versions regardless of how dense they are. + let i_skip: i32 = (3 * max_i) / (4 * MAX_MODULES); + if i_skip < MIN_SKIP || try_harder { + i_skip = MIN_SKIP; + } + let mut done: bool = false; + let state_count: [i32; 5] = [0; 5]; + { + let mut i: i32 = i_skip - 1; + while i < max_i && !done { + { + // Get a row of black/white values + ::do_clear_counts(&state_count); + let current_state: i32 = 0; + { + let mut j: i32 = 0; + while j < max_j { + { + if self.image.get(j, i) { + // Black pixel + if (current_state & 1) == 1 { + // Counting white pixels + current_state += 1; + } + state_count[current_state] += 1; + } else { + // White pixel + if (current_state & 1) == 0 { + // Counting black pixels + if current_state == 4 { + // A winner? + if ::found_pattern_cross(&state_count) { + // Yes + let confirmed: bool = self.handle_possible_center(&state_count, i, j); + if confirmed { + // Start examining every other line. Checking each line turned out to be too + // expensive and didn't improve performance. + i_skip = 2; + if self.has_skipped { + done = self.have_multiply_confirmed_centers(); + } else { + let row_skip: i32 = self.find_row_skip(); + if row_skip > state_count[2] { + // Skip rows between row of lower confirmed center + // and top of presumed third confirmed center + // but back up a bit to get a full chance of detecting + // it, entire width of center of finder pattern + // Skip by rowSkip, but back off by stateCount[2] (size of last center + // of pattern we saw) to be conservative, and also back off by iSkip which + // is about to be re-added + i += row_skip - state_count[2] - i_skip; + j = max_j - 1; + } + } + } else { + ::do_shift_counts2(&state_count); + current_state = 3; + continue; + } + // Clear state to start looking again + current_state = 0; + ::do_clear_counts(&state_count); + } else { + // No, shift counts back by two + ::do_shift_counts2(&state_count); + current_state = 3; + } + } else { + state_count[current_state += 1] += 1; + } + } else { + // Counting white pixels + state_count[current_state] += 1; + } + } + } + j += 1; + } + } + + if ::found_pattern_cross(&state_count) { + let confirmed: bool = self.handle_possible_center(&state_count, i, max_j); + if confirmed { + i_skip = state_count[0]; + if self.has_skipped { + // Found a third one + done = self.have_multiply_confirmed_centers(); + } + } + } + } + i += i_skip; + } + } + + let pattern_info: Vec = self.select_best_patterns(); + ResultPoint::order_best_patterns(pattern_info); + return Ok(FinderPatternInfo::new(pattern_info)); + } + + /** + * Given a count of black/white/black/white/black pixels just seen and an end position, + * figures the location of the center of this run. + */ + fn center_from_end( state_count: &Vec, end: i32) -> f32 { + return (end - state_count[4] - state_count[3]) - state_count[2] / 2.0f; + } + + /** + * @param stateCount count of black/white/black/white/black pixels just read + * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios + * used by finder patterns to be considered a match + */ + pub fn found_pattern_cross( state_count: &Vec) -> bool { + let total_module_size: i32 = 0; + { + let mut i: i32 = 0; + while i < 5 { + { + let count: i32 = state_count[i]; + if count == 0 { + return false; + } + total_module_size += count; + } + i += 1; + } + } + + if total_module_size < 7 { + return false; + } + let module_size: f32 = total_module_size / 7.0f; + let max_variance: f32 = module_size / 2.0f; + // Allow less than 50% variance from 1-1-3-1-1 proportions + return Math::abs(module_size - state_count[0]) < max_variance && Math::abs(module_size - state_count[1]) < max_variance && Math::abs(3.0f * module_size - state_count[2]) < 3.0 * max_variance && Math::abs(module_size - state_count[3]) < max_variance && Math::abs(module_size - state_count[4]) < max_variance; + } + + /** + * @param stateCount count of black/white/black/white/black pixels just read + * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios + * used by finder patterns to be considered a match + */ + pub fn found_pattern_diagonal( state_count: &Vec) -> bool { + let total_module_size: i32 = 0; + { + let mut i: i32 = 0; + while i < 5 { + { + let count: i32 = state_count[i]; + if count == 0 { + return false; + } + total_module_size += count; + } + i += 1; + } + } + + if total_module_size < 7 { + return false; + } + let module_size: f32 = total_module_size / 7.0f; + let max_variance: f32 = module_size / 1.333f; + // Allow less than 75% variance from 1-1-3-1-1 proportions + return Math::abs(module_size - state_count[0]) < max_variance && Math::abs(module_size - state_count[1]) < max_variance && Math::abs(3.0f * module_size - state_count[2]) < 3.0 * max_variance && Math::abs(module_size - state_count[3]) < max_variance && Math::abs(module_size - state_count[4]) < max_variance; + } + + fn get_cross_check_state_count(&self) -> Vec { + ::do_clear_counts(&self.cross_check_state_count); + return self.cross_check_state_count; + } + + pub fn clear_counts(&self, counts: &Vec) { + ::do_clear_counts(&counts); + } + + pub fn shift_counts2(&self, state_count: &Vec) { + ::do_shift_counts2(&state_count); + } + + pub fn do_clear_counts( counts: &Vec) { + Arrays::fill(&counts, 0); + } + + pub fn do_shift_counts2( state_count: &Vec) { + state_count[0] = state_count[2]; + state_count[1] = state_count[3]; + state_count[2] = state_count[4]; + state_count[3] = 1; + state_count[4] = 0; + } + + /** + * After a vertical and horizontal scan finds a potential finder pattern, this method + * "cross-cross-cross-checks" by scanning down diagonally through the center of the possible + * finder pattern to see if the same proportion is detected. + * + * @param centerI row where a finder pattern was detected + * @param centerJ center of the section that appears to cross a finder pattern + * @return true if proportions are withing expected limits + */ + fn cross_check_diagonal(&self, center_i: i32, center_j: i32) -> bool { + let state_count: Vec = self.get_cross_check_state_count(); + // Start counting up, left from center finding black center mass + let mut i: i32 = 0; + while center_i >= i && center_j >= i && self.image.get(center_j - i, center_i - i) { + state_count[2] += 1; + i += 1; + } + if state_count[2] == 0 { + return false; + } + // Continue up, left finding white space + while center_i >= i && center_j >= i && !self.image.get(center_j - i, center_i - i) { + state_count[1] += 1; + i += 1; + } + if state_count[1] == 0 { + return false; + } + // Continue up, left finding black border + while center_i >= i && center_j >= i && self.image.get(center_j - i, center_i - i) { + state_count[0] += 1; + i += 1; + } + if state_count[0] == 0 { + return false; + } + let max_i: i32 = self.image.get_height(); + let max_j: i32 = self.image.get_width(); + // Now also count down, right from center + i = 1; + while center_i + i < max_i && center_j + i < max_j && self.image.get(center_j + i, center_i + i) { + state_count[2] += 1; + i += 1; + } + while center_i + i < max_i && center_j + i < max_j && !self.image.get(center_j + i, center_i + i) { + state_count[3] += 1; + i += 1; + } + if state_count[3] == 0 { + return false; + } + while center_i + i < max_i && center_j + i < max_j && self.image.get(center_j + i, center_i + i) { + state_count[4] += 1; + i += 1; + } + if state_count[4] == 0 { + return false; + } + return ::found_pattern_diagonal(&state_count); + } + + /** + *

After a horizontal scan finds a potential finder pattern, this method + * "cross-checks" by scanning down vertically through the center of the possible + * finder pattern to see if the same proportion is detected.

+ * + * @param startI row where a finder pattern was detected + * @param centerJ center of the section that appears to cross a finder pattern + * @param maxCount maximum reasonable number of modules that should be + * observed in any reading state, based on the results of the horizontal scan + * @return vertical center of finder pattern, or {@link Float#NaN} if not found + */ + fn cross_check_vertical(&self, start_i: i32, center_j: i32, max_count: i32, original_state_count_total: i32) -> f32 { + let image: BitMatrix = self.image; + let max_i: i32 = image.get_height(); + let state_count: Vec = self.get_cross_check_state_count(); + // Start counting up from center + let mut i: i32 = start_i; + while i >= 0 && image.get(center_j, i) { + state_count[2] += 1; + i -= 1; + } + if i < 0 { + return Float::NaN; + } + while i >= 0 && !image.get(center_j, i) && state_count[1] <= max_count { + state_count[1] += 1; + i -= 1; + } + // If already too many modules in this state or ran off the edge: + if i < 0 || state_count[1] > max_count { + return Float::NaN; + } + while i >= 0 && image.get(center_j, i) && state_count[0] <= max_count { + state_count[0] += 1; + i -= 1; + } + if state_count[0] > max_count { + return Float::NaN; + } + // Now also count down from center + i = start_i + 1; + while i < max_i && image.get(center_j, i) { + state_count[2] += 1; + i += 1; + } + if i == max_i { + return Float::NaN; + } + while i < max_i && !image.get(center_j, i) && state_count[3] < max_count { + state_count[3] += 1; + i += 1; + } + if i == max_i || state_count[3] >= max_count { + return Float::NaN; + } + while i < max_i && image.get(center_j, i) && state_count[4] < max_count { + state_count[4] += 1; + i += 1; + } + if state_count[4] >= max_count { + return Float::NaN; + } + // If we found a finder-pattern-like section, but its size is more than 40% different than + // the original, assume it's a false positive + let state_count_total: i32 = state_count[0] + state_count[1] + state_count[2] + state_count[3] + state_count[4]; + if 5 * Math::abs(state_count_total - original_state_count_total) >= 2 * original_state_count_total { + return Float::NaN; + } + return if ::found_pattern_cross(&state_count) { ::center_from_end(&state_count, i) } else { Float::NaN }; + } + + /** + *

Like {@link #crossCheckVertical(int, int, int, int)}, and in fact is basically identical, + * except it reads horizontally instead of vertically. This is used to cross-cross + * check a vertical cross check and locate the real center of the alignment pattern.

+ */ + fn cross_check_horizontal(&self, start_j: i32, center_i: i32, max_count: i32, original_state_count_total: i32) -> f32 { + let image: BitMatrix = self.image; + let max_j: i32 = image.get_width(); + let state_count: Vec = self.get_cross_check_state_count(); + let mut j: i32 = start_j; + while j >= 0 && image.get(j, center_i) { + state_count[2] += 1; + j -= 1; + } + if j < 0 { + return Float::NaN; + } + while j >= 0 && !image.get(j, center_i) && state_count[1] <= max_count { + state_count[1] += 1; + j -= 1; + } + if j < 0 || state_count[1] > max_count { + return Float::NaN; + } + while j >= 0 && image.get(j, center_i) && state_count[0] <= max_count { + state_count[0] += 1; + j -= 1; + } + if state_count[0] > max_count { + return Float::NaN; + } + j = start_j + 1; + while j < max_j && image.get(j, center_i) { + state_count[2] += 1; + j += 1; + } + if j == max_j { + return Float::NaN; + } + while j < max_j && !image.get(j, center_i) && state_count[3] < max_count { + state_count[3] += 1; + j += 1; + } + if j == max_j || state_count[3] >= max_count { + return Float::NaN; + } + while j < max_j && image.get(j, center_i) && state_count[4] < max_count { + state_count[4] += 1; + j += 1; + } + if state_count[4] >= max_count { + return Float::NaN; + } + // If we found a finder-pattern-like section, but its size is significantly different than + // the original, assume it's a false positive + let state_count_total: i32 = state_count[0] + state_count[1] + state_count[2] + state_count[3] + state_count[4]; + if 5 * Math::abs(state_count_total - original_state_count_total) >= original_state_count_total { + return Float::NaN; + } + return if ::found_pattern_cross(&state_count) { ::center_from_end(&state_count, j) } else { Float::NaN }; + } + + /** + * @param stateCount reading state module counts from horizontal scan + * @param i row where finder pattern may be found + * @param j end of possible finder pattern in row + * @param pureBarcode ignored + * @return true if a finder pattern candidate was found this time + * @deprecated only exists for backwards compatibility + * @see #handlePossibleCenter(int[], int, int) + */ + pub fn handle_possible_center(&self, state_count: &Vec, i: i32, j: i32, pure_barcode: bool) -> bool { + return self.handle_possible_center(&state_count, i, j); + } + + /** + *

This is called when a horizontal scan finds a possible alignment pattern. It will + * cross check with a vertical scan, and if successful, will, ah, cross-cross-check + * with another horizontal scan. This is needed primarily to locate the real horizontal + * center of the pattern in cases of extreme skew. + * And then we cross-cross-cross check with another diagonal scan.

+ * + *

If that succeeds the finder pattern location is added to a list that tracks + * the number of times each location has been nearly-matched as a finder pattern. + * Each additional find is more evidence that the location is in fact a finder + * pattern center + * + * @param stateCount reading state module counts from horizontal scan + * @param i row where finder pattern may be found + * @param j end of possible finder pattern in row + * @return true if a finder pattern candidate was found this time + */ + pub fn handle_possible_center(&self, state_count: &Vec, i: i32, j: i32) -> bool { + let state_count_total: i32 = state_count[0] + state_count[1] + state_count[2] + state_count[3] + state_count[4]; + let center_j: f32 = ::center_from_end(&state_count, j); + let center_i: f32 = self.cross_check_vertical(i, center_j as i32, state_count[2], state_count_total); + if !Float::is_na_n(center_i) { + // Re-cross check + center_j = self.cross_check_horizontal(center_j as i32, center_i as i32, state_count[2], state_count_total); + if !Float::is_na_n(center_j) && self.cross_check_diagonal(center_i as i32, center_j as i32) { + let estimated_module_size: f32 = state_count_total / 7.0f; + let mut found: bool = false; + { + let mut index: i32 = 0; + while index < self.possible_centers.size() { + { + let center: FinderPattern = self.possible_centers.get(index); + // Look for about the same center and module size: + if center.about_equals(estimated_module_size, center_i, center_j) { + self.possible_centers.set(index, ¢er.combine_estimate(center_i, center_j, estimated_module_size)); + found = true; + break; + } + } + index += 1; + } + } + + if !found { + let point: FinderPattern = FinderPattern::new(center_j, center_i, estimated_module_size); + self.possible_centers.add(point); + if self.result_point_callback != null { + self.result_point_callback.found_possible_result_point(point); + } + } + return true; + } + } + return false; + } + + /** + * @return number of rows we could safely skip during scanning, based on the first + * two finder patterns that have been located. In some cases their position will + * allow us to infer that the third pattern must lie below a certain point farther + * down in the image. + */ + fn find_row_skip(&self) -> i32 { + let max: i32 = self.possible_centers.size(); + if max <= 1 { + return 0; + } + let first_confirmed_center: ResultPoint = null; + for let center: FinderPattern in self.possible_centers { + if center.get_count() >= CENTER_QUORUM { + if first_confirmed_center == null { + first_confirmed_center = center; + } else { + // We have two confirmed centers + // How far down can we skip before resuming looking for the next + // pattern? In the worst case, only the difference between the + // difference in the x / y coordinates of the two centers. + // This is the case where you find top left last. + self.has_skipped = true; + return (Math::abs(first_confirmed_center.get_x() - center.get_x()) - Math::abs(first_confirmed_center.get_y() - center.get_y())) as i32 / 2; + } + } + } + return 0; + } + + /** + * @return true iff we have found at least 3 finder patterns that have been detected + * at least {@link #CENTER_QUORUM} times each, and, the estimated module size of the + * candidates is "pretty similar" + */ + fn have_multiply_confirmed_centers(&self) -> bool { + let confirmed_count: i32 = 0; + let total_module_size: f32 = 0.0f; + let max: i32 = self.possible_centers.size(); + for let pattern: FinderPattern in self.possible_centers { + if pattern.get_count() >= CENTER_QUORUM { + confirmed_count += 1; + total_module_size += pattern.get_estimated_module_size(); + } + } + if confirmed_count < 3 { + return false; + } + // OK, we have at least 3 confirmed centers, but, it's possible that one is a "false positive" + // and that we need to keep looking. We detect this by asking if the estimated module sizes + // vary too much. We arbitrarily say that when the total deviation from average exceeds + // 5% of the total module size estimates, it's too much. + let average: f32 = total_module_size / max; + let total_deviation: f32 = 0.0f; + for let pattern: FinderPattern in self.possible_centers { + total_deviation += Math::abs(pattern.get_estimated_module_size() - average); + } + return total_deviation <= 0.05f * total_module_size; + } + + /** + * Get square of distance between a and b. + */ + fn squared_distance( a: &FinderPattern, b: &FinderPattern) -> f64 { + let x: f64 = a.get_x() - b.get_x(); + let y: f64 = a.get_y() - b.get_y(); + return x * x + y * y; + } + + /** + * @return the 3 best {@link FinderPattern}s from our list of candidates. The "best" are + * those have similar module size and form a shape closer to a isosceles right triangle. + * @throws NotFoundException if 3 such finder patterns do not exist + */ + fn select_best_patterns(&self) -> /* throws NotFoundException */Result, Rc> { + let start_size: i32 = self.possible_centers.size(); + if start_size < 3 { + // Couldn't find enough finder patterns + throw NotFoundException::get_not_found_instance(); + } + self.possible_centers.sort(module_comparator); + let mut distortion: f64 = Double::MAX_VALUE; + let best_patterns: [Option; 3] = [None; 3]; + { + let mut i: i32 = 0; + while i < self.possible_centers.size() - 2 { + { + let fpi: FinderPattern = self.possible_centers.get(i); + let min_module_size: f32 = fpi.get_estimated_module_size(); + { + let mut j: i32 = i + 1; + while j < self.possible_centers.size() - 1 { + { + let fpj: FinderPattern = self.possible_centers.get(j); + let squares0: f64 = ::squared_distance(fpi, fpj); + { + let mut k: i32 = j + 1; + while k < self.possible_centers.size() { + { + let fpk: FinderPattern = self.possible_centers.get(k); + let max_module_size: f32 = fpk.get_estimated_module_size(); + if max_module_size > min_module_size * 1.4f { + // module size is not similar + continue; + } + let mut a: f64 = squares0; + let mut b: f64 = ::squared_distance(fpj, fpk); + let mut c: f64 = ::squared_distance(fpi, fpk); + // sorts ascending - inlined + if a < b { + if b > c { + if a < c { + let temp: f64 = b; + b = c; + c = temp; + } else { + let temp: f64 = a; + a = c; + c = b; + b = temp; + } + } + } else { + if b < c { + if a < c { + let temp: f64 = a; + a = b; + b = temp; + } else { + let temp: f64 = a; + a = b; + b = c; + c = temp; + } + } else { + let temp: f64 = a; + a = c; + c = temp; + } + } + // a^2 + b^2 = c^2 (Pythagorean theorem), and a = b (isosceles triangle). + // Since any right triangle satisfies the formula c^2 - b^2 - a^2 = 0, + // we need to check both two equal sides separately. + // The value of |c^2 - 2 * b^2| + |c^2 - 2 * a^2| increases as dissimilarity + // from isosceles right triangle. + let d: f64 = Math::abs(c - 2.0 * b) + Math::abs(c - 2.0 * a); + if d < distortion { + distortion = d; + best_patterns[0] = fpi; + best_patterns[1] = fpj; + best_patterns[2] = fpk; + } + } + k += 1; + } + } + + } + j += 1; + } + } + + } + i += 1; + } + } + + if distortion == Double::MAX_VALUE { + throw NotFoundException::get_not_found_instance(); + } + return Ok(best_patterns); + } + + /** + *

Orders by {@link FinderPattern#getEstimatedModuleSize()}

+ */ + #[derive(Comparator, Serializable)] + struct EstimatedModuleComparator { + } + + impl EstimatedModuleComparator { + + pub fn compare(&self, center1: &FinderPattern, center2: &FinderPattern) -> i32 { + return Float::compare(¢er1.get_estimated_module_size(), ¢er2.get_estimated_module_size()); + } + } + +} + +// NEW FILE: finder_pattern_info.rs +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::detector; + +/** + *

Encapsulates information about finder patterns in an image, including the location of + * the three finder patterns, and their estimated module size.

+ * + * @author Sean Owen + */ +pub struct FinderPatternInfo { + + let bottom_left: FinderPattern; + + let top_left: FinderPattern; + + let top_right: FinderPattern; +} + +impl FinderPatternInfo { + + pub fn new( pattern_centers: &Vec) -> FinderPatternInfo { + let .bottomLeft = pattern_centers[0]; + let .topLeft = pattern_centers[1]; + let .topRight = pattern_centers[2]; + } + + pub fn get_bottom_left(&self) -> FinderPattern { + return self.bottom_left; + } + + pub fn get_top_left(&self) -> FinderPattern { + return self.top_left; + } + + pub fn get_top_right(&self) -> FinderPattern { + return self.top_right; + } +} + diff --git a/src/qrcode/encoder.rs b/src/qrcode/encoder.rs index e69de29..21fc2d1 100644 --- a/src/qrcode/encoder.rs +++ b/src/qrcode/encoder.rs @@ -0,0 +1,2601 @@ +// NEW FILE: block_pair.rs +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::encoder; + +struct BlockPair { + + let data_bytes: Vec; + + let error_correction_bytes: Vec; +} + +impl BlockPair { + + fn new( data: &Vec, error_correction: &Vec) -> BlockPair { + data_bytes = data; + error_correction_bytes = error_correction; + } + + pub fn get_data_bytes(&self) -> Vec { + return self.data_bytes; + } + + pub fn get_error_correction_bytes(&self) -> Vec { + return self.error_correction_bytes; + } +} + +// NEW FILE: byte_matrix.rs +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::encoder; + +/** + * JAVAPORT: The original code was a 2D array of ints, but since it only ever gets assigned + * -1, 0, and 1, I'm going to use less memory and go with bytes. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +pub struct ByteMatrix { + + let mut bytes: Vec>; + + let width: i32; + + let height: i32; +} + +impl ByteMatrix { + + pub fn new( width: i32, height: i32) -> ByteMatrix { + bytes = : [[i8; width]; height] = [[0; width]; height]; + let .width = width; + let .height = height; + } + + pub fn get_height(&self) -> i32 { + return self.height; + } + + pub fn get_width(&self) -> i32 { + return self.width; + } + + pub fn get(&self, x: i32, y: i32) -> i8 { + return self.bytes[y][x]; + } + + /** + * @return an internal representation as bytes, in row-major order. array[y][x] represents point (x,y) + */ + pub fn get_array(&self) -> Vec> { + return self.bytes; + } + + pub fn set(&self, x: i32, y: i32, value: i8) { + self.bytes[y][x] = value; + } + + pub fn set(&self, x: i32, y: i32, value: i32) { + self.bytes[y][x] = value as i8; + } + + pub fn set(&self, x: i32, y: i32, value: bool) { + self.bytes[y][x] = ( if value { 1 } else { 0 }) as i8; + } + + pub fn clear(&self, value: i8) { + for let a_byte: Vec in self.bytes { + Arrays::fill(&a_byte, value); + } + } + + pub fn to_string(&self) -> String { + let result: StringBuilder = StringBuilder::new(2 * self.width * self.height + 2); + { + let mut y: i32 = 0; + while y < self.height { + { + let bytes_y: Vec = self.bytes[y]; + { + let mut x: i32 = 0; + while x < self.width { + { + match bytes_y[x] { + 0 => + { + result.append(" 0"); + break; + } + 1 => + { + result.append(" 1"); + break; + } + _ => + { + result.append(" "); + break; + } + } + } + x += 1; + } + } + + result.append('\n'); + } + y += 1; + } + } + + return result.to_string(); + } +} + +// NEW FILE: encoder.rs +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::encoder; + +/** + * @author satorux@google.com (Satoru Takabayashi) - creator + * @author dswitkin@google.com (Daniel Switkin) - ported from C++ + */ + +// The original table is defined in the table 5 of JISX0510:2004 (p.19). + const ALPHANUMERIC_TABLE: vec![Vec; 96] = vec![// 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x00-0x0f +// 0x00-0x0f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x10-0x1f +// 0x10-0x1f +-1, // 0x20-0x2f +36, // 0x20-0x2f +// 0x20-0x2f +-1, // 0x20-0x2f +// 0x20-0x2f +-1, // 0x20-0x2f +// 0x20-0x2f +-1, // 0x20-0x2f +37, // 0x20-0x2f +38, // 0x20-0x2f +// 0x20-0x2f +-1, // 0x20-0x2f +// 0x20-0x2f +-1, // 0x20-0x2f +// 0x20-0x2f +-1, // 0x20-0x2f +// 0x20-0x2f +-1, // 0x20-0x2f +39, // 0x20-0x2f +40, // 0x20-0x2f +// 0x20-0x2f +-1, // 0x20-0x2f +41, // 0x20-0x2f +42, // 0x20-0x2f +43, // 0x30-0x3f +0, // 0x30-0x3f +1, // 0x30-0x3f +2, // 0x30-0x3f +3, // 0x30-0x3f +4, // 0x30-0x3f +5, // 0x30-0x3f +6, // 0x30-0x3f +7, // 0x30-0x3f +8, // 0x30-0x3f +9, // 0x30-0x3f +44, // 0x30-0x3f +// 0x30-0x3f +-1, // 0x30-0x3f +// 0x30-0x3f +-1, // 0x30-0x3f +// 0x30-0x3f +-1, // 0x30-0x3f +// 0x30-0x3f +-1, // 0x30-0x3f +// 0x30-0x3f +-1, // 0x40-0x4f +// 0x40-0x4f +-1, // 0x40-0x4f +10, // 0x40-0x4f +11, // 0x40-0x4f +12, // 0x40-0x4f +13, // 0x40-0x4f +14, // 0x40-0x4f +15, // 0x40-0x4f +16, // 0x40-0x4f +17, // 0x40-0x4f +18, // 0x40-0x4f +19, // 0x40-0x4f +20, // 0x40-0x4f +21, // 0x40-0x4f +22, // 0x40-0x4f +23, // 0x40-0x4f +24, // 0x50-0x5f +25, // 0x50-0x5f +26, // 0x50-0x5f +27, // 0x50-0x5f +28, // 0x50-0x5f +29, // 0x50-0x5f +30, // 0x50-0x5f +31, // 0x50-0x5f +32, // 0x50-0x5f +33, // 0x50-0x5f +34, // 0x50-0x5f +35, // 0x50-0x5f +// 0x50-0x5f +-1, // 0x50-0x5f +// 0x50-0x5f +-1, // 0x50-0x5f +// 0x50-0x5f +-1, // 0x50-0x5f +// 0x50-0x5f +-1, // 0x50-0x5f +// 0x50-0x5f +-1, ] +; + + const DEFAULT_BYTE_MODE_ENCODING: Charset = StandardCharsets::ISO_8859_1; +pub struct Encoder { +} + +impl Encoder { + + fn new() -> Encoder { + } + + // The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details. + // Basically it applies four rules and summate all penalties. + fn calculate_mask_penalty( matrix: &ByteMatrix) -> i32 { + return MaskUtil::apply_mask_penalty_rule1(matrix) + MaskUtil::apply_mask_penalty_rule2(matrix) + MaskUtil::apply_mask_penalty_rule3(matrix) + MaskUtil::apply_mask_penalty_rule4(matrix); + } + + /** + * @param content text to encode + * @param ecLevel error correction level to use + * @return {@link QRCode} representing the encoded QR code + * @throws WriterException if encoding can't succeed, because of for example invalid content + * or configuration + */ + pub fn encode( content: &String, ec_level: &ErrorCorrectionLevel) -> /* throws WriterException */Result> { + return Ok(::encode(&content, ec_level, null)); + } + + pub fn encode( content: &String, ec_level: &ErrorCorrectionLevel, hints: &Map) -> /* throws WriterException */Result> { + let mut version: Version; + let header_and_data_bits: BitArray; + let mut mode: Mode; + let has_g_s1_format_hint: bool = hints != null && hints.contains_key(EncodeHintType::GS1_FORMAT) && Boolean::parse_boolean(&hints.get(EncodeHintType::GS1_FORMAT).to_string()); + let has_compaction_hint: bool = hints != null && hints.contains_key(EncodeHintType::QR_COMPACT) && Boolean::parse_boolean(&hints.get(EncodeHintType::QR_COMPACT).to_string()); + // Determine what character encoding has been specified by the caller, if any + let mut encoding: Charset = DEFAULT_BYTE_MODE_ENCODING; + let has_encoding_hint: bool = hints != null && hints.contains_key(EncodeHintType::CHARACTER_SET); + if has_encoding_hint { + encoding = Charset::for_name(&hints.get(EncodeHintType::CHARACTER_SET).to_string()); + } + if has_compaction_hint { + mode = Mode::BYTE; + let priority_encoding: Charset = if encoding.equals(&DEFAULT_BYTE_MODE_ENCODING) { null } else { encoding }; + let rn: MinimalEncoder.ResultList = MinimalEncoder::encode(&content, null, &priority_encoding, has_g_s1_format_hint, ec_level); + header_and_data_bits = BitArray::new(); + rn.get_bits(header_and_data_bits); + version = rn.get_version(); + } else { + // Pick an encoding mode appropriate for the content. Note that this will not attempt to use + // multiple modes / segments even if that were more efficient. + mode = ::choose_mode(&content, &encoding); + // This will store the header information, like mode and + // length, as well as "header" segments like an ECI segment. + let header_bits: BitArray = BitArray::new(); + // Append ECI segment if applicable + if mode == Mode::BYTE && has_encoding_hint { + let eci: CharacterSetECI = CharacterSetECI::get_character_set_e_c_i(&encoding); + if eci != null { + ::append_e_c_i(eci, header_bits); + } + } + // Append the FNC1 mode header for GS1 formatted data if applicable + if has_g_s1_format_hint { + // GS1 formatted codes are prefixed with a FNC1 in first position mode header + ::append_mode_info(Mode::FNC1_FIRST_POSITION, header_bits); + } + // (With ECI in place,) Write the mode marker + ::append_mode_info(mode, header_bits); + // Collect data within the main segment, separately, to count its size if needed. Don't add it to + // main payload yet. + let data_bits: BitArray = BitArray::new(); + ::append_bytes(&content, mode, data_bits, &encoding); + if hints != null && hints.contains_key(EncodeHintType::QR_VERSION) { + let version_number: i32 = Integer::parse_int(&hints.get(EncodeHintType::QR_VERSION).to_string()); + version = Version::get_version_for_number(version_number); + let bits_needed: i32 = ::calculate_bits_needed(mode, header_bits, data_bits, version); + if !::will_fit(bits_needed, version, ec_level) { + throw WriterException::new("Data too big for requested version"); + } + } else { + version = ::recommend_version(ec_level, mode, header_bits, data_bits); + } + header_and_data_bits = BitArray::new(); + header_and_data_bits.append_bit_array(header_bits); + // Find "length" of main segment and write it + let num_letters: i32 = if mode == Mode::BYTE { data_bits.get_size_in_bytes() } else { content.length() }; + ::append_length_info(num_letters, version, mode, header_and_data_bits); + // Put data together into the overall payload + header_and_data_bits.append_bit_array(data_bits); + } + let ec_blocks: Version.ECBlocks = version.get_e_c_blocks_for_level(ec_level); + let num_data_bytes: i32 = version.get_total_codewords() - ec_blocks.get_total_e_c_codewords(); + // Terminate the bits properly. + ::terminate_bits(num_data_bytes, header_and_data_bits); + // Interleave data bits with error correction code. + let final_bits: BitArray = ::interleave_with_e_c_bytes(header_and_data_bits, &version.get_total_codewords(), num_data_bytes, &ec_blocks.get_num_blocks()); + let qr_code: QRCode = QRCode::new(); + qr_code.set_e_c_level(ec_level); + qr_code.set_mode(mode); + qr_code.set_version(version); + // Choose the mask pattern and set to "qrCode". + let dimension: i32 = version.get_dimension_for_version(); + let matrix: ByteMatrix = ByteMatrix::new(dimension, dimension); + // Enable manual selection of the pattern to be used via hint + let mask_pattern: i32 = -1; + if hints != null && hints.contains_key(EncodeHintType::QR_MASK_PATTERN) { + let hint_mask_pattern: i32 = Integer::parse_int(&hints.get(EncodeHintType::QR_MASK_PATTERN).to_string()); + mask_pattern = if QRCode::is_valid_mask_pattern(hint_mask_pattern) { hint_mask_pattern } else { -1 }; + } + if mask_pattern == -1 { + mask_pattern = ::choose_mask_pattern(final_bits, ec_level, version, matrix); + } + qr_code.set_mask_pattern(mask_pattern); + // Build the matrix and set it to "qrCode". + MatrixUtil::build_matrix(final_bits, ec_level, version, mask_pattern, matrix); + qr_code.set_matrix(matrix); + return Ok(qr_code); + } + + /** + * Decides the smallest version of QR code that will contain all of the provided data. + * + * @throws WriterException if the data cannot fit in any version + */ + fn recommend_version( ec_level: &ErrorCorrectionLevel, mode: &Mode, header_bits: &BitArray, data_bits: &BitArray) -> /* throws WriterException */Result> { + // Hard part: need to know version to know how many bits length takes. But need to know how many + // bits it takes to know version. First we take a guess at version by assuming version will be + // the minimum, 1: + let provisional_bits_needed: i32 = ::calculate_bits_needed(mode, header_bits, data_bits, &Version::get_version_for_number(1)); + let provisional_version: Version = ::choose_version(provisional_bits_needed, ec_level); + // Use that guess to calculate the right version. I am still not sure this works in 100% of cases. + let bits_needed: i32 = ::calculate_bits_needed(mode, header_bits, data_bits, provisional_version); + return Ok(::choose_version(bits_needed, ec_level)); + } + + fn calculate_bits_needed( mode: &Mode, header_bits: &BitArray, data_bits: &BitArray, version: &Version) -> i32 { + return header_bits.get_size() + mode.get_character_count_bits(version) + data_bits.get_size(); + } + + /** + * @return the code point of the table used in alphanumeric mode or + * -1 if there is no corresponding code in the table. + */ + fn get_alphanumeric_code( code: i32) -> i32 { + if code < ALPHANUMERIC_TABLE.len() { + return ALPHANUMERIC_TABLE[code]; + } + return -1; + } + + pub fn choose_mode( content: &String) -> Mode { + return ::choose_mode(&content, null); + } + + /** + * Choose the best mode by examining the content. Note that 'encoding' is used as a hint; + * if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}. + */ + fn choose_mode( content: &String, encoding: &Charset) -> Mode { + if StringUtils::SHIFT_JIS_CHARSET::equals(&encoding) && ::is_only_double_byte_kanji(&content) { + // Choose Kanji mode if all input are double-byte characters + return Mode::KANJI; + } + let has_numeric: bool = false; + let has_alphanumeric: bool = false; + { + let mut i: i32 = 0; + while i < content.length() { + { + let c: char = content.char_at(i); + if c >= '0' && c <= '9' { + has_numeric = true; + } else if ::get_alphanumeric_code(c) != -1 { + has_alphanumeric = true; + } else { + return Mode::BYTE; + } + } + i += 1; + } + } + + if has_alphanumeric { + return Mode::ALPHANUMERIC; + } + if has_numeric { + return Mode::NUMERIC; + } + return Mode::BYTE; + } + + fn is_only_double_byte_kanji( content: &String) -> bool { + let bytes: Vec = content.get_bytes(StringUtils::SHIFT_JIS_CHARSET); + let length: i32 = bytes.len(); + if length % 2 != 0 { + return false; + } + { + let mut i: i32 = 0; + while i < length { + { + let byte1: i32 = bytes[i] & 0xFF; + if (byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB) { + return false; + } + } + i += 2; + } + } + + return true; + } + + fn choose_mask_pattern( bits: &BitArray, ec_level: &ErrorCorrectionLevel, version: &Version, matrix: &ByteMatrix) -> /* throws WriterException */Result> { + // Lower penalty is better. + let min_penalty: i32 = Integer::MAX_VALUE; + let best_mask_pattern: i32 = -1; + // We try all mask patterns to choose the best one. + { + let mask_pattern: i32 = 0; + while mask_pattern < QRCode.NUM_MASK_PATTERNS { + { + MatrixUtil::build_matrix(bits, ec_level, version, mask_pattern, matrix); + let penalty: i32 = ::calculate_mask_penalty(matrix); + if penalty < min_penalty { + min_penalty = penalty; + best_mask_pattern = mask_pattern; + } + } + mask_pattern += 1; + } + } + + return Ok(best_mask_pattern); + } + + fn choose_version( num_input_bits: i32, ec_level: &ErrorCorrectionLevel) -> /* throws WriterException */Result> { + { + let version_num: i32 = 1; + while version_num <= 40 { + { + let version: Version = Version::get_version_for_number(version_num); + if ::will_fit(num_input_bits, version, ec_level) { + return Ok(version); + } + } + version_num += 1; + } + } + + throw WriterException::new("Data too big"); + } + + /** + * @return true if the number of input bits will fit in a code with the specified version and + * error correction level. + */ + fn will_fit( num_input_bits: i32, version: &Version, ec_level: &ErrorCorrectionLevel) -> bool { + // In the following comments, we use numbers of Version 7-H. + // numBytes = 196 + let num_bytes: i32 = version.get_total_codewords(); + // getNumECBytes = 130 + let ec_blocks: Version.ECBlocks = version.get_e_c_blocks_for_level(ec_level); + let num_ec_bytes: i32 = ec_blocks.get_total_e_c_codewords(); + // getNumDataBytes = 196 - 130 = 66 + let num_data_bytes: i32 = num_bytes - num_ec_bytes; + let total_input_bytes: i32 = (num_input_bits + 7) / 8; + return num_data_bytes >= total_input_bytes; + } + + /** + * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24). + */ + fn terminate_bits( num_data_bytes: i32, bits: &BitArray) -> /* throws WriterException */Result> { + let capacity: i32 = num_data_bytes * 8; + if bits.get_size() > capacity { + throw WriterException::new(format!("data bits cannot fit in the QR Code{} > {}", bits.get_size(), capacity)); + } + // Append Mode.TERMINATE if there is enough space (value is 0000) + { + let mut i: i32 = 0; + while i < 4 && bits.get_size() < capacity { + { + bits.append_bit(false); + } + i += 1; + } + } + + // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details. + // If the last byte isn't 8-bit aligned, we'll add padding bits. + let num_bits_in_last_byte: i32 = bits.get_size() & 0x07; + if num_bits_in_last_byte > 0 { + { + let mut i: i32 = num_bits_in_last_byte; + while i < 8 { + { + bits.append_bit(false); + } + i += 1; + } + } + + } + // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24). + let num_padding_bytes: i32 = num_data_bytes - bits.get_size_in_bytes(); + { + let mut i: i32 = 0; + while i < num_padding_bytes { + { + bits.append_bits( if (i & 0x01) == 0 { 0xEC } else { 0x11 }, 8); + } + i += 1; + } + } + + if bits.get_size() != capacity { + throw WriterException::new("Bits size does not equal capacity"); + } + } + + /** + * Get number of data bytes and number of error correction bytes for block id "blockID". Store + * the result in "numDataBytesInBlock", and "numECBytesInBlock". See table 12 in 8.5.1 of + * JISX0510:2004 (p.30) + */ + fn get_num_data_bytes_and_num_e_c_bytes_for_block_i_d( num_total_bytes: i32, num_data_bytes: i32, num_r_s_blocks: i32, block_i_d: i32, num_data_bytes_in_block: &Vec, num_e_c_bytes_in_block: &Vec) -> /* throws WriterException */Result> { + if block_i_d >= num_r_s_blocks { + throw WriterException::new("Block ID too large"); + } + // numRsBlocksInGroup2 = 196 % 5 = 1 + let num_rs_blocks_in_group2: i32 = num_total_bytes % num_r_s_blocks; + // numRsBlocksInGroup1 = 5 - 1 = 4 + let num_rs_blocks_in_group1: i32 = num_r_s_blocks - num_rs_blocks_in_group2; + // numTotalBytesInGroup1 = 196 / 5 = 39 + let num_total_bytes_in_group1: i32 = num_total_bytes / num_r_s_blocks; + // numTotalBytesInGroup2 = 39 + 1 = 40 + let num_total_bytes_in_group2: i32 = num_total_bytes_in_group1 + 1; + // numDataBytesInGroup1 = 66 / 5 = 13 + let num_data_bytes_in_group1: i32 = num_data_bytes / num_r_s_blocks; + // numDataBytesInGroup2 = 13 + 1 = 14 + let num_data_bytes_in_group2: i32 = num_data_bytes_in_group1 + 1; + // numEcBytesInGroup1 = 39 - 13 = 26 + let num_ec_bytes_in_group1: i32 = num_total_bytes_in_group1 - num_data_bytes_in_group1; + // numEcBytesInGroup2 = 40 - 14 = 26 + let num_ec_bytes_in_group2: i32 = num_total_bytes_in_group2 - num_data_bytes_in_group2; + // 26 = 26 + if num_ec_bytes_in_group1 != num_ec_bytes_in_group2 { + throw WriterException::new("EC bytes mismatch"); + } + // 5 = 4 + 1. + if num_r_s_blocks != num_rs_blocks_in_group1 + num_rs_blocks_in_group2 { + throw WriterException::new("RS blocks mismatch"); + } + // 196 = (13 + 26) * 4 + (14 + 26) * 1 + if num_total_bytes != ((num_data_bytes_in_group1 + num_ec_bytes_in_group1) * num_rs_blocks_in_group1) + ((num_data_bytes_in_group2 + num_ec_bytes_in_group2) * num_rs_blocks_in_group2) { + throw WriterException::new("Total bytes mismatch"); + } + if block_i_d < num_rs_blocks_in_group1 { + num_data_bytes_in_block[0] = num_data_bytes_in_group1; + num_e_c_bytes_in_block[0] = num_ec_bytes_in_group1; + } else { + num_data_bytes_in_block[0] = num_data_bytes_in_group2; + num_e_c_bytes_in_block[0] = num_ec_bytes_in_group2; + } + } + + /** + * Interleave "bits" with corresponding error correction bytes. On success, store the result in + * "result". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details. + */ + fn interleave_with_e_c_bytes( bits: &BitArray, num_total_bytes: i32, num_data_bytes: i32, num_r_s_blocks: i32) -> /* throws WriterException */Result> { + // "bits" must have "getNumDataBytes" bytes of data. + if bits.get_size_in_bytes() != num_data_bytes { + throw WriterException::new("Number of bits and data bytes does not match"); + } + // Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll + // store the divided data bytes blocks and error correction bytes blocks into "blocks". + let data_bytes_offset: i32 = 0; + let max_num_data_bytes: i32 = 0; + let max_num_ec_bytes: i32 = 0; + // Since, we know the number of reedsolmon blocks, we can initialize the vector with the number. + let blocks: Collection = ArrayList<>::new(num_r_s_blocks); + { + let mut i: i32 = 0; + while i < num_r_s_blocks { + { + let num_data_bytes_in_block: [i32; 1] = [0; 1]; + let num_ec_bytes_in_block: [i32; 1] = [0; 1]; + ::get_num_data_bytes_and_num_e_c_bytes_for_block_i_d(num_total_bytes, num_data_bytes, num_r_s_blocks, i, &num_data_bytes_in_block, &num_ec_bytes_in_block); + let size: i32 = num_data_bytes_in_block[0]; + let data_bytes: [i8; size] = [0; size]; + bits.to_bytes(8 * data_bytes_offset, &data_bytes, 0, size); + let ec_bytes: Vec = ::generate_e_c_bytes(&data_bytes, num_ec_bytes_in_block[0]); + blocks.add(BlockPair::new(&data_bytes, &ec_bytes)); + max_num_data_bytes = Math::max(max_num_data_bytes, size); + max_num_ec_bytes = Math::max(max_num_ec_bytes, ec_bytes.len()); + data_bytes_offset += num_data_bytes_in_block[0]; + } + i += 1; + } + } + + if num_data_bytes != data_bytes_offset { + throw WriterException::new("Data bytes does not match offset"); + } + let result: BitArray = BitArray::new(); + // First, place data blocks. + { + let mut i: i32 = 0; + while i < max_num_data_bytes { + { + for let block: BlockPair in blocks { + let data_bytes: Vec = block.get_data_bytes(); + if i < data_bytes.len() { + result.append_bits(data_bytes[i], 8); + } + } + } + i += 1; + } + } + + // Then, place error correction blocks. + { + let mut i: i32 = 0; + while i < max_num_ec_bytes { + { + for let block: BlockPair in blocks { + let ec_bytes: Vec = block.get_error_correction_bytes(); + if i < ec_bytes.len() { + result.append_bits(ec_bytes[i], 8); + } + } + } + i += 1; + } + } + + if num_total_bytes != result.get_size_in_bytes() { + // Should be same. + throw WriterException::new(format!("Interleaving error: {} and {} differ.", num_total_bytes, result.get_size_in_bytes())); + } + return Ok(result); + } + + fn generate_e_c_bytes( data_bytes: &Vec, num_ec_bytes_in_block: i32) -> Vec { + let num_data_bytes: i32 = data_bytes.len(); + let to_encode: [i32; num_data_bytes + num_ec_bytes_in_block] = [0; num_data_bytes + num_ec_bytes_in_block]; + { + let mut i: i32 = 0; + while i < num_data_bytes { + { + to_encode[i] = data_bytes[i] & 0xFF; + } + i += 1; + } + } + + ReedSolomonEncoder::new(GenericGF::QR_CODE_FIELD_256).encode(&to_encode, num_ec_bytes_in_block); + let ec_bytes: [i8; num_ec_bytes_in_block] = [0; num_ec_bytes_in_block]; + { + let mut i: i32 = 0; + while i < num_ec_bytes_in_block { + { + ec_bytes[i] = to_encode[num_data_bytes + i] as i8; + } + i += 1; + } + } + + return ec_bytes; + } + + /** + * Append mode info. On success, store the result in "bits". + */ + fn append_mode_info( mode: &Mode, bits: &BitArray) { + bits.append_bits(&mode.get_bits(), 4); + } + + /** + * Append length info. On success, store the result in "bits". + */ + fn append_length_info( num_letters: i32, version: &Version, mode: &Mode, bits: &BitArray) -> /* throws WriterException */Result> { + let num_bits: i32 = mode.get_character_count_bits(version); + if num_letters >= (1 << num_bits) { + throw WriterException::new(format!("{} is bigger than {}", num_letters, ((1 << num_bits) - 1))); + } + bits.append_bits(num_letters, num_bits); + } + + /** + * Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits". + */ + fn append_bytes( content: &String, mode: &Mode, bits: &BitArray, encoding: &Charset) -> /* throws WriterException */Result> { + match mode { + NUMERIC => + { + ::append_numeric_bytes(&content, bits); + break; + } + ALPHANUMERIC => + { + ::append_alphanumeric_bytes(&content, bits); + break; + } + BYTE => + { + ::append8_bit_bytes(&content, bits, &encoding); + break; + } + KANJI => + { + ::append_kanji_bytes(&content, bits); + break; + } + _ => + { + throw WriterException::new(format!("Invalid mode: {}", mode)); + } + } + } + + fn append_numeric_bytes( content: &CharSequence, bits: &BitArray) { + let length: i32 = content.length(); + let mut i: i32 = 0; + while i < length { + let num1: i32 = content.char_at(i) - '0'; + if i + 2 < length { + // Encode three numeric letters in ten bits. + let num2: i32 = content.char_at(i + 1) - '0'; + let num3: i32 = content.char_at(i + 2) - '0'; + bits.append_bits(num1 * 100 + num2 * 10 + num3, 10); + i += 3; + } else if i + 1 < length { + // Encode two numeric letters in seven bits. + let num2: i32 = content.char_at(i + 1) - '0'; + bits.append_bits(num1 * 10 + num2, 7); + i += 2; + } else { + // Encode one numeric letter in four bits. + bits.append_bits(num1, 4); + i += 1; + } + } + } + + fn append_alphanumeric_bytes( content: &CharSequence, bits: &BitArray) -> /* throws WriterException */Result> { + let length: i32 = content.length(); + let mut i: i32 = 0; + while i < length { + let code1: i32 = ::get_alphanumeric_code(&content.char_at(i)); + if code1 == -1 { + throw WriterException::new(); + } + if i + 1 < length { + let code2: i32 = ::get_alphanumeric_code(&content.char_at(i + 1)); + if code2 == -1 { + throw WriterException::new(); + } + // Encode two alphanumeric letters in 11 bits. + bits.append_bits(code1 * 45 + code2, 11); + i += 2; + } else { + // Encode one alphanumeric letter in six bits. + bits.append_bits(code1, 6); + i += 1; + } + } + } + + fn append8_bit_bytes( content: &String, bits: &BitArray, encoding: &Charset) { + let bytes: Vec = content.get_bytes(&encoding); + for let b: i8 in bytes { + bits.append_bits(b, 8); + } + } + + fn append_kanji_bytes( content: &String, bits: &BitArray) -> /* throws WriterException */Result> { + let bytes: Vec = content.get_bytes(StringUtils::SHIFT_JIS_CHARSET); + if bytes.len() % 2 != 0 { + throw WriterException::new("Kanji byte size not even"); + } + // bytes.length must be even + let max_i: i32 = bytes.len() - 1; + { + let mut i: i32 = 0; + while i < max_i { + { + let byte1: i32 = bytes[i] & 0xFF; + let byte2: i32 = bytes[i + 1] & 0xFF; + let code: i32 = (byte1 << 8) | byte2; + let mut subtracted: i32 = -1; + if code >= 0x8140 && code <= 0x9ffc { + subtracted = code - 0x8140; + } else if code >= 0xe040 && code <= 0xebbf { + subtracted = code - 0xc140; + } + if subtracted == -1 { + throw WriterException::new("Invalid byte sequence"); + } + let encoded: i32 = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff); + bits.append_bits(encoded, 13); + } + i += 2; + } + } + + } + + fn append_e_c_i( eci: &CharacterSetECI, bits: &BitArray) { + bits.append_bits(&Mode::ECI::get_bits(), 4); + // This is correct for values up to 127, which is all we need now. + bits.append_bits(&eci.get_value(), 8); + } +} + +// NEW FILE: mask_util.rs +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::encoder; + +/** + * @author Satoru Takabayashi + * @author Daniel Switkin + * @author Sean Owen + */ + +// Penalty weights from section 6.8.2.1 + const N1: i32 = 3; + + const N2: i32 = 3; + + const N3: i32 = 40; + + const N4: i32 = 10; +struct MaskUtil { +} + +impl MaskUtil { + + fn new() -> MaskUtil { + // do nothing + } + + /** + * Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and + * give penalty to them. Example: 00000 or 11111. + */ + fn apply_mask_penalty_rule1( matrix: &ByteMatrix) -> i32 { + return ::apply_mask_penalty_rule1_internal(matrix, true) + ::apply_mask_penalty_rule1_internal(matrix, false); + } + + /** + * Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give + * penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a + * penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block. + */ + fn apply_mask_penalty_rule2( matrix: &ByteMatrix) -> i32 { + let mut penalty: i32 = 0; + let array: Vec> = matrix.get_array(); + let width: i32 = matrix.get_width(); + let height: i32 = matrix.get_height(); + { + let mut y: i32 = 0; + while y < height - 1 { + { + let array_y: Vec = array[y]; + { + let mut x: i32 = 0; + while x < width - 1 { + { + let value: i32 = array_y[x]; + if value == array_y[x + 1] && value == array[y + 1][x] && value == array[y + 1][x + 1] { + penalty += 1; + } + } + x += 1; + } + } + + } + y += 1; + } + } + + return N2 * penalty; + } + + /** + * Apply mask penalty rule 3 and return the penalty. Find consecutive runs of 1:1:3:1:1:4 + * starting with black, or 4:1:1:3:1:1 starting with white, and give penalty to them. If we + * find patterns like 000010111010000, we give penalty once. + */ + fn apply_mask_penalty_rule3( matrix: &ByteMatrix) -> i32 { + let num_penalties: i32 = 0; + let array: Vec> = matrix.get_array(); + let width: i32 = matrix.get_width(); + let height: i32 = matrix.get_height(); + { + let mut y: i32 = 0; + while y < height { + { + { + let mut x: i32 = 0; + while x < width { + { + // We can at least optimize this access + let array_y: Vec = array[y]; + if x + 6 < width && array_y[x] == 1 && array_y[x + 1] == 0 && array_y[x + 2] == 1 && array_y[x + 3] == 1 && array_y[x + 4] == 1 && array_y[x + 5] == 0 && array_y[x + 6] == 1 && (::is_white_horizontal(&array_y, x - 4, x) || ::is_white_horizontal(&array_y, x + 7, x + 11)) { + num_penalties += 1; + } + if y + 6 < height && array[y][x] == 1 && array[y + 1][x] == 0 && array[y + 2][x] == 1 && array[y + 3][x] == 1 && array[y + 4][x] == 1 && array[y + 5][x] == 0 && array[y + 6][x] == 1 && (::is_white_vertical(&array, x, y - 4, y) || ::is_white_vertical(&array, x, y + 7, y + 11)) { + num_penalties += 1; + } + } + x += 1; + } + } + + } + y += 1; + } + } + + return num_penalties * N3; + } + + fn is_white_horizontal( row_array: &Vec, from: i32, to: i32) -> bool { + if from < 0 || row_array.len() < to { + return false; + } + { + let mut i: i32 = from; + while i < to { + { + if row_array[i] == 1 { + return false; + } + } + i += 1; + } + } + + return true; + } + + fn is_white_vertical( array: &Vec>, col: i32, from: i32, to: i32) -> bool { + if from < 0 || array.len() < to { + return false; + } + { + let mut i: i32 = from; + while i < to { + { + if array[i][col] == 1 { + return false; + } + } + i += 1; + } + } + + return true; + } + + /** + * Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give + * penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance. + */ + fn apply_mask_penalty_rule4( matrix: &ByteMatrix) -> i32 { + let num_dark_cells: i32 = 0; + let array: Vec> = matrix.get_array(); + let width: i32 = matrix.get_width(); + let height: i32 = matrix.get_height(); + { + let mut y: i32 = 0; + while y < height { + { + let array_y: Vec = array[y]; + { + let mut x: i32 = 0; + while x < width { + { + if array_y[x] == 1 { + num_dark_cells += 1; + } + } + x += 1; + } + } + + } + y += 1; + } + } + + let num_total_cells: i32 = matrix.get_height() * matrix.get_width(); + let five_percent_variances: i32 = Math::abs(num_dark_cells * 2 - num_total_cells) * 10 / num_total_cells; + return five_percent_variances * N4; + } + + /** + * Return the mask bit for "getMaskPattern" at "x" and "y". See 8.8 of JISX0510:2004 for mask + * pattern conditions. + */ + fn get_data_mask_bit( mask_pattern: i32, x: i32, y: i32) -> bool { + let mut intermediate: i32; + let mut temp: i32; + match mask_pattern { + 0 => + { + intermediate = (y + x) & 0x1; + break; + } + 1 => + { + intermediate = y & 0x1; + break; + } + 2 => + { + intermediate = x % 3; + break; + } + 3 => + { + intermediate = (y + x) % 3; + break; + } + 4 => + { + intermediate = ((y / 2) + (x / 3)) & 0x1; + break; + } + 5 => + { + temp = y * x; + intermediate = (temp & 0x1) + (temp % 3); + break; + } + 6 => + { + temp = y * x; + intermediate = ((temp & 0x1) + (temp % 3)) & 0x1; + break; + } + 7 => + { + temp = y * x; + intermediate = ((temp % 3) + ((y + x) & 0x1)) & 0x1; + break; + } + _ => + { + throw IllegalArgumentException::new(format!("Invalid mask pattern: {}", mask_pattern)); + } + } + return intermediate == 0; + } + + /** + * Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both + * vertical and horizontal orders respectively. + */ + fn apply_mask_penalty_rule1_internal( matrix: &ByteMatrix, is_horizontal: bool) -> i32 { + let mut penalty: i32 = 0; + let i_limit: i32 = if is_horizontal { matrix.get_height() } else { matrix.get_width() }; + let j_limit: i32 = if is_horizontal { matrix.get_width() } else { matrix.get_height() }; + let array: Vec> = matrix.get_array(); + { + let mut i: i32 = 0; + while i < i_limit { + { + let num_same_bit_cells: i32 = 0; + let prev_bit: i32 = -1; + { + let mut j: i32 = 0; + while j < j_limit { + { + let bit: i32 = if is_horizontal { array[i][j] } else { array[j][i] }; + if bit == prev_bit { + num_same_bit_cells += 1; + } else { + if num_same_bit_cells >= 5 { + penalty += N1 + (num_same_bit_cells - 5); + } + // Include the cell itself. + num_same_bit_cells = 1; + prev_bit = bit; + } + } + j += 1; + } + } + + if num_same_bit_cells >= 5 { + penalty += N1 + (num_same_bit_cells - 5); + } + } + i += 1; + } + } + + return penalty; + } +} + +// NEW FILE: matrix_util.rs +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::encoder; + +/** + * @author satorux@google.com (Satoru Takabayashi) - creator + * @author dswitkin@google.com (Daniel Switkin) - ported from C++ + */ + + const POSITION_DETECTION_PATTERN: vec![vec![Vec>; 7]; 7] = vec![vec![1, 1, 1, 1, 1, 1, 1, ] +, vec![1, 0, 0, 0, 0, 0, 1, ] +, vec![1, 0, 1, 1, 1, 0, 1, ] +, vec![1, 0, 1, 1, 1, 0, 1, ] +, vec![1, 0, 1, 1, 1, 0, 1, ] +, vec![1, 0, 0, 0, 0, 0, 1, ] +, vec![1, 1, 1, 1, 1, 1, 1, ] +, ] +; + + const POSITION_ADJUSTMENT_PATTERN: vec![vec![Vec>; 5]; 5] = vec![vec![1, 1, 1, 1, 1, ] +, vec![1, 0, 0, 0, 1, ] +, vec![1, 0, 1, 0, 1, ] +, vec![1, 0, 0, 0, 1, ] +, vec![1, 1, 1, 1, 1, ] +, ] +; + +// From Appendix E. Table 1, JIS0510X:2004 (p 71). The table was double-checked by komatsu. + const POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE: vec![vec![Vec>; 7]; 40] = vec![// Version 1 +vec![-1, -1, -1, -1, -1, -1, -1, ] +, // Version 2 +vec![6, 18, -1, -1, -1, -1, -1, ] +, // Version 3 +vec![6, 22, -1, -1, -1, -1, -1, ] +, // Version 4 +vec![6, 26, -1, -1, -1, -1, -1, ] +, // Version 5 +vec![6, 30, -1, -1, -1, -1, -1, ] +, // Version 6 +vec![6, 34, -1, -1, -1, -1, -1, ] +, // Version 7 +vec![6, 22, 38, -1, -1, -1, -1, ] +, // Version 8 +vec![6, 24, 42, -1, -1, -1, -1, ] +, // Version 9 +vec![6, 26, 46, -1, -1, -1, -1, ] +, // Version 10 +vec![6, 28, 50, -1, -1, -1, -1, ] +, // Version 11 +vec![6, 30, 54, -1, -1, -1, -1, ] +, // Version 12 +vec![6, 32, 58, -1, -1, -1, -1, ] +, // Version 13 +vec![6, 34, 62, -1, -1, -1, -1, ] +, // Version 14 +vec![6, 26, 46, 66, -1, -1, -1, ] +, // Version 15 +vec![6, 26, 48, 70, -1, -1, -1, ] +, // Version 16 +vec![6, 26, 50, 74, -1, -1, -1, ] +, // Version 17 +vec![6, 30, 54, 78, -1, -1, -1, ] +, // Version 18 +vec![6, 30, 56, 82, -1, -1, -1, ] +, // Version 19 +vec![6, 30, 58, 86, -1, -1, -1, ] +, // Version 20 +vec![6, 34, 62, 90, -1, -1, -1, ] +, // Version 21 +vec![6, 28, 50, 72, 94, -1, -1, ] +, // Version 22 +vec![6, 26, 50, 74, 98, -1, -1, ] +, // Version 23 +vec![6, 30, 54, 78, 102, -1, -1, ] +, // Version 24 +vec![6, 28, 54, 80, 106, -1, -1, ] +, // Version 25 +vec![6, 32, 58, 84, 110, -1, -1, ] +, // Version 26 +vec![6, 30, 58, 86, 114, -1, -1, ] +, // Version 27 +vec![6, 34, 62, 90, 118, -1, -1, ] +, // Version 28 +vec![6, 26, 50, 74, 98, 122, -1, ] +, // Version 29 +vec![6, 30, 54, 78, 102, 126, -1, ] +, // Version 30 +vec![6, 26, 52, 78, 104, 130, -1, ] +, // Version 31 +vec![6, 30, 56, 82, 108, 134, -1, ] +, // Version 32 +vec![6, 34, 60, 86, 112, 138, -1, ] +, // Version 33 +vec![6, 30, 58, 86, 114, 142, -1, ] +, // Version 34 +vec![6, 34, 62, 90, 118, 146, -1, ] +, // Version 35 +vec![6, 30, 54, 78, 102, 126, 150, ] +, // Version 36 +vec![6, 24, 50, 76, 102, 128, 154, ] +, // Version 37 +vec![6, 28, 54, 80, 106, 132, 158, ] +, // Version 38 +vec![6, 32, 58, 84, 110, 136, 162, ] +, // Version 39 +vec![6, 26, 54, 82, 110, 138, 166, ] +, // Version 40 +vec![6, 30, 58, 86, 114, 142, 170, ] +, ] +; + +// Type info cells at the left top corner. + const TYPE_INFO_COORDINATES: vec![vec![Vec>; 2]; 15] = vec![vec![8, 0, ] +, vec![8, 1, ] +, vec![8, 2, ] +, vec![8, 3, ] +, vec![8, 4, ] +, vec![8, 5, ] +, vec![8, 7, ] +, vec![8, 8, ] +, vec![7, 8, ] +, vec![5, 8, ] +, vec![4, 8, ] +, vec![3, 8, ] +, vec![2, 8, ] +, vec![1, 8, ] +, vec![0, 8, ] +, ] +; + +// From Appendix D in JISX0510:2004 (p. 67) +// 1 1111 0010 0101 + const VERSION_INFO_POLY: i32 = 0x1f25; + +// From Appendix C in JISX0510:2004 (p.65). + const TYPE_INFO_POLY: i32 = 0x537; + + const TYPE_INFO_MASK_PATTERN: i32 = 0x5412; +struct MatrixUtil { +} + +impl MatrixUtil { + + fn new() -> MatrixUtil { + // do nothing + } + + // Set all cells to -1. -1 means that the cell is empty (not set yet). + // + // JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding + // with the ByteMatrix initialized all to zero. + fn clear_matrix( matrix: &ByteMatrix) { + matrix.clear(-1 as i8); + } + + // Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On + // success, store the result in "matrix" and return true. + fn build_matrix( data_bits: &BitArray, ec_level: &ErrorCorrectionLevel, version: &Version, mask_pattern: i32, matrix: &ByteMatrix) -> /* throws WriterException */Result> { + ::clear_matrix(matrix); + ::embed_basic_patterns(version, matrix); + // Type information appear with any version. + ::embed_type_info(ec_level, mask_pattern, matrix); + // Version info appear if version >= 7. + ::maybe_embed_version_info(version, matrix); + // Data should be embedded at end. + ::embed_data_bits(data_bits, mask_pattern, matrix); + } + + // Embed basic patterns. On success, modify the matrix and return true. + // The basic patterns are: + // - Position detection patterns + // - Timing patterns + // - Dark dot at the left bottom corner + // - Position adjustment patterns, if need be + fn embed_basic_patterns( version: &Version, matrix: &ByteMatrix) -> /* throws WriterException */Result> { + // Let's get started with embedding big squares at corners. + ::embed_position_detection_patterns_and_separators(matrix); + // Then, embed the dark dot at the left bottom corner. + ::embed_dark_dot_at_left_bottom_corner(matrix); + // Position adjustment patterns appear if version >= 2. + ::maybe_embed_position_adjustment_patterns(version, matrix); + // Timing patterns should be embedded after position adj. patterns. + ::embed_timing_patterns(matrix); + } + + // Embed type information. On success, modify the matrix. + fn embed_type_info( ec_level: &ErrorCorrectionLevel, mask_pattern: i32, matrix: &ByteMatrix) -> /* throws WriterException */Result> { + let type_info_bits: BitArray = BitArray::new(); + ::make_type_info_bits(ec_level, mask_pattern, type_info_bits); + { + let mut i: i32 = 0; + while i < type_info_bits.get_size() { + { + // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in + // "typeInfoBits". + let bit: bool = type_info_bits.get(type_info_bits.get_size() - 1 - i); + // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46). + let coordinates: Vec = TYPE_INFO_COORDINATES[i]; + let x1: i32 = coordinates[0]; + let y1: i32 = coordinates[1]; + matrix.set(x1, y1, bit); + let mut x2: i32; + let mut y2: i32; + if i < 8 { + // Right top corner. + x2 = matrix.get_width() - i - 1; + y2 = 8; + } else { + // Left bottom corner. + x2 = 8; + y2 = matrix.get_height() - 7 + (i - 8); + } + matrix.set(x2, y2, bit); + } + i += 1; + } + } + + } + + // Embed version information if need be. On success, modify the matrix and return true. + // See 8.10 of JISX0510:2004 (p.47) for how to embed version information. + fn maybe_embed_version_info( version: &Version, matrix: &ByteMatrix) -> /* throws WriterException */Result> { + if version.get_version_number() < 7 { + // Don't need version info. + return; + } + let version_info_bits: BitArray = BitArray::new(); + ::make_version_info_bits(version, version_info_bits); + // It will decrease from 17 to 0. + let bit_index: i32 = 6 * 3 - 1; + { + let mut i: i32 = 0; + while i < 6 { + { + { + let mut j: i32 = 0; + while j < 3 { + { + // Place bits in LSB (least significant bit) to MSB order. + let bit: bool = version_info_bits.get(bit_index); + bit_index -= 1; + // Left bottom corner. + matrix.set(i, matrix.get_height() - 11 + j, bit); + // Right bottom corner. + matrix.set(matrix.get_height() - 11 + j, i, bit); + } + j += 1; + } + } + + } + i += 1; + } + } + + } + + // Embed "dataBits" using "getMaskPattern". On success, modify the matrix and return true. + // For debugging purposes, it skips masking process if "getMaskPattern" is -1. + // See 8.7 of JISX0510:2004 (p.38) for how to embed data bits. + fn embed_data_bits( data_bits: &BitArray, mask_pattern: i32, matrix: &ByteMatrix) -> /* throws WriterException */Result> { + let bit_index: i32 = 0; + let mut direction: i32 = -1; + // Start from the right bottom cell. + let mut x: i32 = matrix.get_width() - 1; + let mut y: i32 = matrix.get_height() - 1; + while x > 0 { + // Skip the vertical timing pattern. + if x == 6 { + x -= 1; + } + while y >= 0 && y < matrix.get_height() { + { + let mut i: i32 = 0; + while i < 2 { + { + let xx: i32 = x - i; + // Skip the cell if it's not empty. + if !::is_empty(&matrix.get(xx, y)) { + continue; + } + let mut bit: bool; + if bit_index < data_bits.get_size() { + bit = data_bits.get(bit_index); + bit_index += 1; + } else { + // Padding bit. If there is no bit left, we'll fill the left cells with 0, as described + // in 8.4.9 of JISX0510:2004 (p. 24). + bit = false; + } + // Skip masking if mask_pattern is -1. + if mask_pattern != -1 && MaskUtil::get_data_mask_bit(mask_pattern, xx, y) { + bit = !bit; + } + matrix.set(xx, y, bit); + } + i += 1; + } + } + + y += direction; + } + // Reverse the direction. + direction = -direction; + y += direction; + // Move to the left. + x -= 2; + } + // All bits should be consumed. + if bit_index != data_bits.get_size() { + throw WriterException::new(format!("Not all bits consumed: {}/{}", bit_index, data_bits.get_size())); + } + } + + // Return the position of the most significant bit set (to one) in the "value". The most + // significant bit is position 32. If there is no bit set, return 0. Examples: + // - findMSBSet(0) => 0 + // - findMSBSet(1) => 1 + // - findMSBSet(255) => 8 + fn find_m_s_b_set( value: i32) -> i32 { + return 32 - Integer::number_of_leading_zeros(value); + } + + // Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for "value" using polynomial "poly". The BCH + // code is used for encoding type information and version information. + // Example: Calculation of version information of 7. + // f(x) is created from 7. + // - 7 = 000111 in 6 bits + // - f(x) = x^2 + x^1 + x^0 + // g(x) is given by the standard (p. 67) + // - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1 + // Multiply f(x) by x^(18 - 6) + // - f'(x) = f(x) * x^(18 - 6) + // - f'(x) = x^14 + x^13 + x^12 + // Calculate the remainder of f'(x) / g(x) + // x^2 + // __________________________________________________ + // g(x) )x^14 + x^13 + x^12 + // x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2 + // -------------------------------------------------- + // x^11 + x^10 + x^7 + x^4 + x^2 + // + // The remainder is x^11 + x^10 + x^7 + x^4 + x^2 + // Encode it in binary: 110010010100 + // The return value is 0xc94 (1100 1001 0100) + // + // Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit + // operations. We don't care if coefficients are positive or negative. + fn calculate_b_c_h_code( value: i32, poly: i32) -> i32 { + if poly == 0 { + throw IllegalArgumentException::new("0 polynomial"); + } + // If poly is "1 1111 0010 0101" (version info poly), msbSetInPoly is 13. We'll subtract 1 + // from 13 to make it 12. + let msb_set_in_poly: i32 = ::find_m_s_b_set(poly); + value <<= msb_set_in_poly - 1; + // Do the division business using exclusive-or operations. + while ::find_m_s_b_set(value) >= msb_set_in_poly { + value ^= poly << (::find_m_s_b_set(value) - msb_set_in_poly); + } + // Now the "value" is the remainder (i.e. the BCH code) + return value; + } + + // Make bit vector of type information. On success, store the result in "bits" and return true. + // Encode error correction level and mask pattern. See 8.9 of + // JISX0510:2004 (p.45) for details. + fn make_type_info_bits( ec_level: &ErrorCorrectionLevel, mask_pattern: i32, bits: &BitArray) -> /* throws WriterException */Result> { + if !QRCode::is_valid_mask_pattern(mask_pattern) { + throw WriterException::new("Invalid mask pattern"); + } + let type_info: i32 = (ec_level.get_bits() << 3) | mask_pattern; + bits.append_bits(type_info, 5); + let bch_code: i32 = ::calculate_b_c_h_code(type_info, TYPE_INFO_POLY); + bits.append_bits(bch_code, 10); + let mask_bits: BitArray = BitArray::new(); + mask_bits.append_bits(TYPE_INFO_MASK_PATTERN, 15); + bits.xor(mask_bits); + if bits.get_size() != 15 { + // Just in case. + throw WriterException::new(format!("should not happen but we got: {}", bits.get_size())); + } + } + + // Make bit vector of version information. On success, store the result in "bits" and return true. + // See 8.10 of JISX0510:2004 (p.45) for details. + fn make_version_info_bits( version: &Version, bits: &BitArray) -> /* throws WriterException */Result> { + bits.append_bits(&version.get_version_number(), 6); + let bch_code: i32 = ::calculate_b_c_h_code(&version.get_version_number(), VERSION_INFO_POLY); + bits.append_bits(bch_code, 12); + if bits.get_size() != 18 { + // Just in case. + throw WriterException::new(format!("should not happen but we got: {}", bits.get_size())); + } + } + + // Check if "value" is empty. + fn is_empty( value: i32) -> bool { + return value == -1; + } + + fn embed_timing_patterns( matrix: &ByteMatrix) { + // separation patterns (size 1). Thus, 8 = 7 + 1. + { + let mut i: i32 = 8; + while i < matrix.get_width() - 8 { + { + let bit: i32 = (i + 1) % 2; + // Horizontal line. + if ::is_empty(&matrix.get(i, 6)) { + matrix.set(i, 6, bit); + } + // Vertical line. + if ::is_empty(&matrix.get(6, i)) { + matrix.set(6, i, bit); + } + } + i += 1; + } + } + + } + + // Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46) + fn embed_dark_dot_at_left_bottom_corner( matrix: &ByteMatrix) -> /* throws WriterException */Result> { + if matrix.get(8, matrix.get_height() - 8) == 0 { + throw WriterException::new(); + } + matrix.set(8, matrix.get_height() - 8, 1); + } + + fn embed_horizontal_separation_pattern( x_start: i32, y_start: i32, matrix: &ByteMatrix) -> /* throws WriterException */Result> { + { + let mut x: i32 = 0; + while x < 8 { + { + if !::is_empty(&matrix.get(x_start + x, y_start)) { + throw WriterException::new(); + } + matrix.set(x_start + x, y_start, 0); + } + x += 1; + } + } + + } + + fn embed_vertical_separation_pattern( x_start: i32, y_start: i32, matrix: &ByteMatrix) -> /* throws WriterException */Result> { + { + let mut y: i32 = 0; + while y < 7 { + { + if !::is_empty(&matrix.get(x_start, y_start + y)) { + throw WriterException::new(); + } + matrix.set(x_start, y_start + y, 0); + } + y += 1; + } + } + + } + + fn embed_position_adjustment_pattern( x_start: i32, y_start: i32, matrix: &ByteMatrix) { + { + let mut y: i32 = 0; + while y < 5 { + { + let pattern_y: Vec = POSITION_ADJUSTMENT_PATTERN[y]; + { + let mut x: i32 = 0; + while x < 5 { + { + matrix.set(x_start + x, y_start + y, pattern_y[x]); + } + x += 1; + } + } + + } + y += 1; + } + } + + } + + fn embed_position_detection_pattern( x_start: i32, y_start: i32, matrix: &ByteMatrix) { + { + let mut y: i32 = 0; + while y < 7 { + { + let pattern_y: Vec = POSITION_DETECTION_PATTERN[y]; + { + let mut x: i32 = 0; + while x < 7 { + { + matrix.set(x_start + x, y_start + y, pattern_y[x]); + } + x += 1; + } + } + + } + y += 1; + } + } + + } + + // Embed position detection patterns and surrounding vertical/horizontal separators. + fn embed_position_detection_patterns_and_separators( matrix: &ByteMatrix) -> /* throws WriterException */Result> { + // Embed three big squares at corners. + let pdp_width: i32 = POSITION_DETECTION_PATTERN[0].len(); + // Left top corner. + ::embed_position_detection_pattern(0, 0, matrix); + // Right top corner. + ::embed_position_detection_pattern(matrix.get_width() - pdp_width, 0, matrix); + // Left bottom corner. + ::embed_position_detection_pattern(0, matrix.get_width() - pdp_width, matrix); + // Embed horizontal separation patterns around the squares. + let hsp_width: i32 = 8; + // Left top corner. + ::embed_horizontal_separation_pattern(0, hsp_width - 1, matrix); + // Right top corner. + ::embed_horizontal_separation_pattern(matrix.get_width() - hsp_width, hsp_width - 1, matrix); + // Left bottom corner. + ::embed_horizontal_separation_pattern(0, matrix.get_width() - hsp_width, matrix); + // Embed vertical separation patterns around the squares. + let vsp_size: i32 = 7; + // Left top corner. + ::embed_vertical_separation_pattern(vsp_size, 0, matrix); + // Right top corner. + ::embed_vertical_separation_pattern(matrix.get_height() - vsp_size - 1, 0, matrix); + // Left bottom corner. + ::embed_vertical_separation_pattern(vsp_size, matrix.get_height() - vsp_size, matrix); + } + + // Embed position adjustment patterns if need be. + fn maybe_embed_position_adjustment_patterns( version: &Version, matrix: &ByteMatrix) { + if version.get_version_number() < 2 { + // The patterns appear if version >= 2 + return; + } + let index: i32 = version.get_version_number() - 1; + let coordinates: Vec = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index]; + for let y: i32 in coordinates { + if y >= 0 { + for let x: i32 in coordinates { + if x >= 0 && ::is_empty(&matrix.get(x, y)) { + // If the cell is unset, we embed the position adjustment pattern here. + // -2 is necessary since the x/y coordinates point to the center of the pattern, not the + // left top corner. + ::embed_position_adjustment_pattern(x - 2, y - 2, matrix); + } + } + } + } + } +} + +// NEW FILE: minimal_encoder.rs +/* + * Copyright 2021 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::encoder; + +/** + * Encoder that encodes minimally + * + * Algorithm: + * + * The eleventh commandment was "Thou Shalt Compute" or "Thou Shalt Not Compute" - I forget which (Alan Perilis). + * + * This implementation computes. As an alternative, the QR-Code specification suggests heuristics like this one: + * + * If initial input data is in the exclusive subset of the Alphanumeric character set AND if there are less than + * [6,7,8] characters followed by data from the remainder of the 8-bit byte character set, THEN select the 8- + * bit byte mode ELSE select Alphanumeric mode; + * + * This is probably right for 99.99% of cases but there is at least this one counter example: The string "AAAAAAa" + * encodes 2 bits smaller as ALPHANUMERIC(AAAAAA), BYTE(a) than by encoding it as BYTE(AAAAAAa). + * Perhaps that is the only counter example but without having proof, it remains unclear. + * + * ECI switching: + * + * In multi language content the algorithm selects the most compact representation using ECI modes. + * For example the most compact representation of the string "\u0150\u015C" (O-double-acute, S-circumflex) is + * ECI(UTF-8), BYTE(\u0150\u015C) while prepending one or more times the same leading character as in + * "\u0150\u0150\u015C", the most compact representation uses two ECIs so that the string is encoded as + * ECI(ISO-8859-2), BYTE(\u0150\u0150), ECI(ISO-8859-3), BYTE(\u015C). + * + * @author Alex Geller + */ +struct MinimalEncoder { + + let string_to_encode: String; + + let is_g_s1: bool; + + let mut encoders: ECIEncoderSet; + + let ec_level: ErrorCorrectionLevel; +} + +impl MinimalEncoder { + + enum VersionSize { + + SMALL("version 1-9"), MEDIUM("version 10-26"), LARGE("version 27-40"); + + let description: String; + + fn new( description: &String) -> VersionSize { + let .description = description; + } + + pub fn to_string(&self) -> String { + return self.description; + } + } + + /** + * Creates a MinimalEncoder + * + * @param stringToEncode The string to encode + * @param priorityCharset The preferred {@link Charset}. When the value of the argument is null, the algorithm + * chooses charsets that leads to a minimal representation. Otherwise the algorithm will use the priority + * charset to encode any character in the input that can be encoded by it if the charset is among the + * supported charsets. + * @param isGS1 {@code true} if a FNC1 is to be prepended; {@code false} otherwise + * @param ecLevel The error correction level. + * @see ResultList#getVersion + */ + fn new( string_to_encode: &String, priority_charset: &Charset, is_g_s1: bool, ec_level: &ErrorCorrectionLevel) -> MinimalEncoder { + let .stringToEncode = string_to_encode; + let .isGS1 = is_g_s1; + let .encoders = ECIEncoderSet::new(&string_to_encode, &priority_charset, -1); + let .ecLevel = ec_level; + } + + /** + * Encodes the string minimally + * + * @param stringToEncode The string to encode + * @param version The preferred {@link Version}. A minimal version is computed (see + * {@link ResultList#getVersion method} when the value of the argument is null + * @param priorityCharset The preferred {@link Charset}. When the value of the argument is null, the algorithm + * chooses charsets that leads to a minimal representation. Otherwise the algorithm will use the priority + * charset to encode any character in the input that can be encoded by it if the charset is among the + * supported charsets. + * @param isGS1 {@code true} if a FNC1 is to be prepended; {@code false} otherwise + * @param ecLevel The error correction level. + * @return An instance of {@code ResultList} representing the minimal solution. + * @see ResultList#getBits + * @see ResultList#getVersion + * @see ResultList#getSize + */ + fn encode( string_to_encode: &String, version: &Version, priority_charset: &Charset, is_g_s1: bool, ec_level: &ErrorCorrectionLevel) -> /* throws WriterException */Result> { + return Ok(MinimalEncoder::new(&string_to_encode, &priority_charset, is_g_s1, ec_level).encode(version)); + } + + fn encode(&self, version: &Version) -> /* throws WriterException */Result> { + if version == null { + // compute minimal encoding trying the three version sizes. + let versions: vec![Vec; 3] = vec![::get_version(VersionSize::SMALL), ::get_version(VersionSize::MEDIUM), ::get_version(VersionSize::LARGE), ] + ; + let results: vec![Vec; 3] = vec![self.encode_specific_version(versions[0]), self.encode_specific_version(versions[1]), self.encode_specific_version(versions[2]), ] + ; + let smallest_size: i32 = Integer::MAX_VALUE; + let smallest_result: i32 = -1; + { + let mut i: i32 = 0; + while i < 3 { + { + let size: i32 = results[i].get_size(); + if Encoder::will_fit(size, versions[i], self.ec_level) && size < smallest_size { + smallest_size = size; + smallest_result = i; + } + } + i += 1; + } + } + + if smallest_result < 0 { + throw WriterException::new("Data too big for any version"); + } + return Ok(results[smallest_result]); + } else { + // compute minimal encoding for a given version + let result: ResultList = self.encode_specific_version(version); + if !Encoder::will_fit(&result.get_size(), &::get_version(&::get_version_size(&result.get_version())), self.ec_level) { + throw WriterException::new(format!("Data too big for version{}", version)); + } + return Ok(result); + } + } + + fn get_version_size( version: &Version) -> VersionSize { + return if version.get_version_number() <= 9 { VersionSize::SMALL } else { if version.get_version_number() <= 26 { VersionSize::MEDIUM } else { VersionSize::LARGE } }; + } + + fn get_version( version_size: &VersionSize) -> Version { + match version_size { + SMALL => + { + return Version::get_version_for_number(9); + } + MEDIUM => + { + return Version::get_version_for_number(26); + } + LARGE => + { + } + _ => + { + return Version::get_version_for_number(40); + } + } + } + + fn is_numeric( c: char) -> bool { + return c >= '0' && c <= '9'; + } + + fn is_double_byte_kanji( c: char) -> bool { + return Encoder::is_only_double_byte_kanji(&String::value_of(c)); + } + + fn is_alphanumeric( c: char) -> bool { + return Encoder::get_alphanumeric_code(c) != -1; + } + + fn can_encode(&self, mode: &Mode, c: char) -> bool { + match mode { + KANJI => + { + return ::is_double_byte_kanji(c); + } + ALPHANUMERIC => + { + return ::is_alphanumeric(c); + } + NUMERIC => + { + return ::is_numeric(c); + } + // any character can be encoded as byte(s). Up to the caller to manage splitting into + BYTE => + { + return true; + } + // multiple bytes when String.getBytes(Charset) return more than one byte. + _ => + { + return false; + } + } + } + + fn get_compacted_ordinal( mode: &Mode) -> i32 { + if mode == null { + return 0; + } + match mode { + KANJI => + { + return 0; + } + ALPHANUMERIC => + { + return 1; + } + NUMERIC => + { + return 2; + } + BYTE => + { + return 3; + } + _ => + { + throw IllegalStateException::new(format!("Illegal mode {}", mode)); + } + } + } + + fn add_edge(&self, edges: &Vec>>, position: i32, edge: &Edge) { + let vertex_index: i32 = position + edge.characterLength; + let mode_edges: Vec = edges[vertex_index][edge.charsetEncoderIndex]; + let mode_ordinal: i32 = ::get_compacted_ordinal(edge.mode); + if mode_edges[mode_ordinal] == null || mode_edges[mode_ordinal].cachedTotalSize > edge.cachedTotalSize { + mode_edges[mode_ordinal] = edge; + } + } + + fn add_edges(&self, version: &Version, edges: &Vec>>, from: i32, previous: &Edge) { + let mut start: i32 = 0; + let mut end: i32 = self.encoders.length(); + let priority_encoder_index: i32 = self.encoders.get_priority_encoder_index(); + if priority_encoder_index >= 0 && self.encoders.can_encode(&self.string_to_encode.char_at(from), priority_encoder_index) { + start = priority_encoder_index; + end = priority_encoder_index + 1; + } + { + let mut i: i32 = start; + while i < end { + { + if self.encoders.can_encode(&self.string_to_encode.char_at(from), i) { + self.add_edge(edges, from, Edge::new(Mode::BYTE, from, i, 1, previous, version)); + } + } + i += 1; + } + } + + if self.can_encode(Mode::KANJI, &self.string_to_encode.char_at(from)) { + self.add_edge(edges, from, Edge::new(Mode::KANJI, from, 0, 1, previous, version)); + } + let input_length: i32 = self.string_to_encode.length(); + if self.can_encode(Mode::ALPHANUMERIC, &self.string_to_encode.char_at(from)) { + self.add_edge(edges, from, Edge::new(Mode::ALPHANUMERIC, from, 0, if from + 1 >= input_length || !self.can_encode(Mode::ALPHANUMERIC, &self.string_to_encode.char_at(from + 1)) { 1 } else { 2 }, previous, version)); + } + if self.can_encode(Mode::NUMERIC, &self.string_to_encode.char_at(from)) { + self.add_edge(edges, from, Edge::new(Mode::NUMERIC, from, 0, if from + 1 >= input_length || !self.can_encode(Mode::NUMERIC, &self.string_to_encode.char_at(from + 1)) { 1 } else { if from + 2 >= input_length || !self.can_encode(Mode::NUMERIC, &self.string_to_encode.char_at(from + 2)) { 2 } else { 3 } }, previous, version)); + } + } + + fn encode_specific_version(&self, version: &Version) -> /* throws WriterException */Result> { + let input_length: i32 = self.string_to_encode.length(); + // Array that represents vertices. There is a vertex for every character, encoding and mode. The vertex contains + // a list of all edges that lead to it that have the same encoding and mode. + // The lists are created lazily + // The last dimension in the array below encodes the 4 modes KANJI, ALPHANUMERIC, NUMERIC and BYTE via the + // function getCompactedOrdinal(Mode) + let edges: [[[Option; 4]; self.encoders.length()]; input_length + 1] = [[[None; 4]; self.encoders.length()]; input_length + 1]; + self.add_edges(version, edges, 0, null); + { + let mut i: i32 = 1; + while i <= input_length { + { + { + let mut j: i32 = 0; + while j < self.encoders.length() { + { + { + let mut k: i32 = 0; + while k < 4 { + { + if edges[i][j][k] != null && i < input_length { + self.add_edges(version, edges, i, edges[i][j][k]); + } + } + k += 1; + } + } + + } + j += 1; + } + } + + } + i += 1; + } + } + + let minimal_j: i32 = -1; + let minimal_k: i32 = -1; + let minimal_size: i32 = Integer::MAX_VALUE; + { + let mut j: i32 = 0; + while j < self.encoders.length() { + { + { + let mut k: i32 = 0; + while k < 4 { + { + if edges[input_length][j][k] != null { + let edge: Edge = edges[input_length][j][k]; + if edge.cachedTotalSize < minimal_size { + minimal_size = edge.cachedTotalSize; + minimal_j = j; + minimal_k = k; + } + } + } + k += 1; + } + } + + } + j += 1; + } + } + + if minimal_j < 0 { + throw WriterException::new(format!("Internal error: failed to encode \"{}\"", self.string_to_encode)); + } + return Ok(ResultList::new(version, edges[input_length][minimal_j][minimal_k])); + } + + struct Edge { + + let mode: Mode; + + let from_position: i32; + + let charset_encoder_index: i32; + + let character_length: i32; + + let previous: Edge; + + let cached_total_size: i32; + } + + impl Edge { + + fn new( mode: &Mode, from_position: i32, charset_encoder_index: i32, character_length: i32, previous: &Edge, version: &Version) -> Edge { + let .mode = mode; + let .fromPosition = from_position; + let .charsetEncoderIndex = if mode == Mode::BYTE || previous == null { charset_encoder_index } else { // inherit the encoding if not of type BYTE + previous.charsetEncoderIndex }; + let .characterLength = character_length; + let .previous = previous; + let mut size: i32 = if previous != null { previous.cachedTotalSize } else { 0 }; + let need_e_c_i: bool = mode == Mode::BYTE && // at the beginning and charset is not ISO-8859-1 + (previous == null && let .charsetEncoderIndex != 0) || (previous != null && let .charsetEncoderIndex != previous.charsetEncoderIndex); + if previous == null || mode != previous.mode || need_e_c_i { + size += 4 + mode.get_character_count_bits(version); + } + match mode { + KANJI => + { + size += 13; + break; + } + ALPHANUMERIC => + { + size += if character_length == 1 { 6 } else { 11 }; + break; + } + NUMERIC => + { + size += if character_length == 1 { 4 } else { if character_length == 2 { 7 } else { 10 } }; + break; + } + BYTE => + { + size += 8 * encoders.encode(&string_to_encode.substring(from_position, from_position + character_length), charset_encoder_index).len(); + if need_e_c_i { + // the ECI assignment numbers for ISO-8859-x, UTF-8 and UTF-16 are all 8 bit long + size += 4 + 8; + } + break; + } + } + cached_total_size = size; + } + } + + + struct ResultList { + + let list: List = ArrayList<>::new(); + + let version: Version; + } + + impl ResultList { + + fn new( version: &Version, solution: &Edge) -> ResultList { + let mut length: i32 = 0; + let mut current: Edge = solution; + let contains_e_c_i: bool = false; + while current != null { + length += current.characterLength; + let previous: Edge = current.previous; + let need_e_c_i: bool = current.mode == Mode::BYTE && // at the beginning and charset is not ISO-8859-1 + (previous == null && current.charsetEncoderIndex != 0) || (previous != null && current.charsetEncoderIndex != previous.charsetEncoderIndex); + if need_e_c_i { + contains_e_c_i = true; + } + if previous == null || previous.mode != current.mode || need_e_c_i { + list.add(0, ResultNode::new(current.mode, current.fromPosition, current.charsetEncoderIndex, length)); + length = 0; + } + if need_e_c_i { + list.add(0, ResultNode::new(Mode::ECI, current.fromPosition, current.charsetEncoderIndex, 0)); + } + current = previous; + } + // If there is no ECI at the beginning then we put an ECI to the default charset (ISO-8859-1) + if is_g_s1 { + let mut first: ResultNode = list.get(0); + if first != null && first.mode != Mode::ECI && contains_e_c_i { + // prepend a default character set ECI + list.add(0, ResultNode::new(Mode::ECI, 0, 0, 0)); + } + first = list.get(0); + // prepend or insert a FNC1_FIRST_POSITION after the ECI (if any) + list.add( if first.mode != Mode::ECI { 0 } else { 1 }, ResultNode::new(Mode::FNC1_FIRST_POSITION, 0, 0, 0)); + } + // set version to smallest version into which the bits fit. + let version_number: i32 = version.get_version_number(); + let lower_limit: i32; + let upper_limit: i32; + match ::get_version_size(version) { + SMALL => + { + lower_limit = 1; + upper_limit = 9; + break; + } + MEDIUM => + { + lower_limit = 10; + upper_limit = 26; + break; + } + LARGE => + { + } + _ => + { + lower_limit = 27; + upper_limit = 40; + break; + } + } + let size: i32 = self.get_size(version); + // increase version if needed + while version_number < upper_limit && !Encoder::will_fit(size, &Version::get_version_for_number(version_number), ec_level) { + version_number += 1; + } + // shrink version if possible + while version_number > lower_limit && Encoder::will_fit(size, &Version::get_version_for_number(version_number - 1), ec_level) { + version_number -= 1; + } + let .version = Version::get_version_for_number(version_number); + } + + /** + * returns the size in bits + */ + fn get_size(&self) -> i32 { + return self.get_size(self.version); + } + + fn get_size(&self, version: &Version) -> i32 { + let mut result: i32 = 0; + for let result_node: ResultNode in self.list { + result += result_node.get_size(version); + } + return result; + } + + /** + * appends the bits + */ + fn get_bits(&self, bits: &BitArray) -> /* throws WriterException */Result> { + for let result_node: ResultNode in self.list { + result_node.get_bits(bits); + } + } + + fn get_version(&self) -> Version { + return self.version; + } + + pub fn to_string(&self) -> String { + let result: StringBuilder = StringBuilder::new(); + let mut previous: ResultNode = null; + for let current: ResultNode in self.list { + if previous != null { + result.append(","); + } + result.append(¤t.to_string()); + previous = current; + } + return result.to_string(); + } + + struct ResultNode { + + let mode: Mode; + + let from_position: i32; + + let charset_encoder_index: i32; + + let character_length: i32; + } + + impl ResultNode { + + fn new( mode: &Mode, from_position: i32, charset_encoder_index: i32, character_length: i32) -> ResultNode { + let .mode = mode; + let .fromPosition = from_position; + let .charsetEncoderIndex = charset_encoder_index; + let .characterLength = character_length; + } + + /** + * returns the size in bits + */ + fn get_size(&self, version: &Version) -> i32 { + let mut size: i32 = 4 + self.mode.get_character_count_bits(version); + match self.mode { + KANJI => + { + size += 13 * self.character_length; + break; + } + ALPHANUMERIC => + { + size += (self.character_length / 2) * 11; + size += if (self.character_length % 2) == 1 { 6 } else { 0 }; + break; + } + NUMERIC => + { + size += (self.character_length / 3) * 10; + let rest: i32 = self.character_length % 3; + size += if rest == 1 { 4 } else { if rest == 2 { 7 } else { 0 } }; + break; + } + BYTE => + { + size += 8 * self.get_character_count_indicator(); + break; + } + ECI => + { + // the ECI assignment numbers for ISO-8859-x, UTF-8 and UTF-16 are all 8 bit long + size += 8; + } + } + return size; + } + + /** + * returns the length in characters according to the specification (differs from getCharacterLength() in BYTE mode + * for multi byte encoded characters) + */ + fn get_character_count_indicator(&self) -> i32 { + return if self.mode == Mode::BYTE { self.encoders.encode(&self.string_to_encode.substring(self.from_position, self.from_position + self.character_length), self.charset_encoder_index).len() } else { self.character_length }; + } + + /** + * appends the bits + */ + fn get_bits(&self, bits: &BitArray) -> /* throws WriterException */Result> { + bits.append_bits(&self.mode.get_bits(), 4); + if self.character_length > 0 { + let length: i32 = self.get_character_count_indicator(); + bits.append_bits(length, &self.mode.get_character_count_bits(self.version)); + } + if self.mode == Mode::ECI { + bits.append_bits(&self.encoders.get_e_c_i_value(self.charset_encoder_index), 8); + } else if self.character_length > 0 { + // append data + Encoder::append_bytes(&self.string_to_encode.substring(self.from_position, self.from_position + self.character_length), self.mode, bits, &self.encoders.get_charset(self.charset_encoder_index)); + } + } + + pub fn to_string(&self) -> String { + let result: StringBuilder = StringBuilder::new(); + result.append(self.mode).append('('); + if self.mode == Mode::ECI { + result.append(&self.encoders.get_charset(self.charset_encoder_index).display_name()); + } else { + result.append(&self.make_printable(&self.string_to_encode.substring(self.from_position, self.from_position + self.character_length))); + } + result.append(')'); + return result.to_string(); + } + + fn make_printable(&self, s: &String) -> String { + let result: StringBuilder = StringBuilder::new(); + { + let mut i: i32 = 0; + while i < s.length() { + { + if s.char_at(i) < 32 || s.char_at(i) > 126 { + result.append('.'); + } else { + result.append(&s.char_at(i)); + } + } + i += 1; + } + } + + return result.to_string(); + } + } + + } + +} + +// NEW FILE: q_r_code.rs +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// package com::google::zxing::qrcode::encoder; + +/** + * @author satorux@google.com (Satoru Takabayashi) - creator + * @author dswitkin@google.com (Daniel Switkin) - ported from C++ + */ + + const NUM_MASK_PATTERNS: i32 = 8; +pub struct QRCode { + + let mut mode: Mode; + + let ec_level: ErrorCorrectionLevel; + + let version: Version; + + let mask_pattern: i32; + + let mut matrix: ByteMatrix; +} + +impl QRCode { + + pub fn new() -> QRCode { + mask_pattern = -1; + } + + /** + * @return the mode. Not relevant if {@link com.google.zxing.EncodeHintType#QR_COMPACT} is selected. + */ + pub fn get_mode(&self) -> Mode { + return self.mode; + } + + pub fn get_e_c_level(&self) -> ErrorCorrectionLevel { + return self.ec_level; + } + + pub fn get_version(&self) -> Version { + return self.version; + } + + pub fn get_mask_pattern(&self) -> i32 { + return self.mask_pattern; + } + + pub fn get_matrix(&self) -> ByteMatrix { + return self.matrix; + } + + pub fn to_string(&self) -> String { + let result: StringBuilder = StringBuilder::new(200); + result.append("<<\n"); + result.append(" mode: "); + result.append(self.mode); + result.append("\n ecLevel: "); + result.append(self.ec_level); + result.append("\n version: "); + result.append(self.version); + result.append("\n maskPattern: "); + result.append(self.mask_pattern); + if self.matrix == null { + result.append("\n matrix: null\n"); + } else { + result.append("\n matrix:\n"); + result.append(self.matrix); + } + result.append(">>\n"); + return result.to_string(); + } + + pub fn set_mode(&self, value: &Mode) { + self.mode = value; + } + + pub fn set_e_c_level(&self, value: &ErrorCorrectionLevel) { + self.ec_level = value; + } + + pub fn set_version(&self, version: &Version) { + self.version = version; + } + + pub fn set_mask_pattern(&self, value: i32) { + self.mask_pattern = value; + } + + pub fn set_matrix(&self, value: &ByteMatrix) { + self.matrix = value; + } + + // Check if "mask_pattern" is valid. + pub fn is_valid_mask_pattern( mask_pattern: i32) -> bool { + return mask_pattern >= 0 && mask_pattern < NUM_MASK_PATTERNS; + } +} +