move pdf417

This commit is contained in:
Henry Schimke
2022-08-14 18:08:45 -05:00
parent aff9e1088a
commit 7ade09dc7b
64 changed files with 12507 additions and 5995 deletions

View File

@@ -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;
}
}

View File

@@ -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<Integer, Integer> = 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<i32> {
let max_confidence: i32 = -1;
let result: Collection<Integer> = ArrayList<>::new();
for let entry: Entry<Integer, Integer> 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);
}
}

View File

@@ -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<BoundingBox, Rc<Exception>> {
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<BoundingBox, Rc<Exception>> {
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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
/**
* <p>This class contains the methods for decoding the PDF417 codewords.</p>
*
* @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<char> = ";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'".to_char_array();
const MIXED_CHARS: Vec<char> = "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<BigInteger>;
const NUMBER_OF_SEQUENCE_CODEWORDS: i32 = 2;
struct DecodedBitStreamParser {
}
impl DecodedBitStreamParser {
enum Mode {
ALPHA(), LOWER(), MIXED(), PUNCT(), ALPHA_SHIFT(), PUNCT_SHIFT()
}
static {
EXP900 = : [Option<BigInteger>; 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<i32>, ec_level: &String) -> /* throws FormatException */Result<DecoderResult, Rc<Exception>> {
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<i32>, code_index: i32, result_metadata: &PDF417ResultMetadata) -> /* throws FormatException */Result<i32, Rc<Exception>> {
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(&timestamp.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<i32>, code_index: i32, result: &ECIStringBuilder) -> /* throws FormatException */Result<i32, Rc<Exception>> {
// 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<i32>, byte_compaction_data: &Vec<i32>, 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<i32>, code_index: i32, result: &ECIStringBuilder) -> /* throws FormatException */Result<i32, Rc<Exception>> {
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<i32>, code_index: i32, result: &ECIStringBuilder) -> /* throws FormatException */Result<i32, Rc<Exception>> {
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<i32>, count: i32) -> /* throws FormatException */Result<String, Rc<Exception>> {
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));
}
}

View File

@@ -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<DetectionResultColumn>;
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<DetectionResultColumn>; barcode_column_count + 2] = [None; barcode_column_count + 2];
}
fn get_detection_result_columns(&self) -> Vec<DetectionResultColumn> {
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<Codeword> = 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<Codeword> = self.detection_result_columns[0].get_codewords();
const RRIcodewords: Vec<Codeword> = 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<Codeword> = 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<Codeword> = 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<Codeword>) {
let codeword: Codeword = codewords[codewords_row];
let previous_column_codewords: Vec<Codeword> = self.detection_result_columns[barcode_column - 1].get_codewords();
let next_column_codewords: Vec<Codeword> = 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<Codeword>; 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
}
}
}

View File

@@ -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<Codeword>;
}
impl DetectionResultColumn {
fn new( bounding_box: &BoundingBox) -> DetectionResultColumn {
let .boundingBox = BoundingBox::new(bounding_box);
codewords = : [Option<Codeword>; 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<Codeword> {
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
}
}
}

View File

@@ -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<Codeword> = 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<i32> {
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<Codeword> = 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<Codeword> = 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<Codeword>, 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());
}
}

View File

@@ -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;
/**
* <p>PDF417 error correction implementation.</p>
*
* <p>This <a href="http://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction#Example">example</a>
* is quite useful in understanding the algorithm.</p>
*
* @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<i32>, num_e_c_codewords: i32, erasures: &Vec<i32>) -> /* throws ChecksumException */Result<i32, Rc<Exception>> {
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<ModulusPoly> = 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<i32> = self.find_error_locations(sigma);
let error_magnitudes: Vec<i32> = 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<Vec<ModulusPoly>, Rc<Exception>> {
// 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<Vec<i32>, Rc<Exception>> {
// 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<i32>) -> Vec<i32> {
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;
}
}

View File

@@ -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;
/**
* <p>A field based on powers of a generator integer, modulo some modulus.</p>
*
* @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<i32>;
let log_table: Vec<i32>;
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;
}
}

View File

@@ -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<i32>;
}
impl ModulusPoly {
fn new( field: &ModulusGF, coefficients: &Vec<i32>) -> 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<i32> {
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<i32> = self.coefficients;
let larger_coefficients: Vec<i32> = other.coefficients;
if smaller_coefficients.len() > larger_coefficients.len() {
let temp: Vec<i32> = 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<i32> = self.coefficients;
let a_length: i32 = a_coefficients.len();
let b_coefficients: Vec<i32> = 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();
}
}

View File

@@ -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>) -> 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<i32>) -> Vec<i32> {
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>) -> 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>) -> 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>) -> 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<f32> = 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;
}
}

View File

@@ -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<DecoderResult, Rc<Exception>> {
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<DetectionResult, Rc<Exception>> {
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<BoundingBox, Rc<Exception>> {
if row_indicator_column == null {
return Ok(null);
}
let row_heights: Vec<i32> = 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<Codeword> = 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>) -> 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<Vec<BarcodeValue>>) -> /* throws NotFoundException */Result<Void, Rc<Exception>> {
let barcode_matrix01: BarcodeValue = barcode_matrix[0][1];
let number_of_codewords: Vec<i32> = 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<DecoderResult, Rc<Exception>> {
let barcode_matrix: Vec<Vec<BarcodeValue>> = ::create_barcode_matrix(detection_result);
::adjust_codeword_count(detection_result, barcode_matrix);
let erasures: Collection<Integer> = 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<Vec<i32>> = ArrayList<>::new();
let ambiguous_indexes_list: Collection<Integer> = 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<i32> = 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<i32>, erasure_array: &Vec<i32>, ambiguous_indexes: &Vec<i32>, ambiguous_index_values: &Vec<Vec<i32>>) -> /* throws FormatException, ChecksumException */Result<DecoderResult, Rc<Exception>> {
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<Vec<BarcodeValue>> {
let barcode_matrix: [[Option<BarcodeValue>; 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<i32> = ::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<i32> {
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<i32>, ec_level: i32, erasures: &Vec<i32>) -> /* throws FormatException, ChecksumException */Result<DecoderResult, Rc<Exception>> {
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);
}
/**
* <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to
* correct the errors in-place.</p>
*
* @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<i32>, erasures: &Vec<i32>, num_e_c_codewords: i32) -> /* throws ChecksumException */Result<i32, Rc<Exception>> {
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<i32>, num_e_c_codewords: i32) -> /* throws FormatException */Result<Void, Rc<Exception>> {
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<i32> {
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>) -> 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<Vec<BarcodeValue>>) -> 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<Object>);
} 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
}
}
}

View File

@@ -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;
/**
* <p>Encapsulates logic that can detect a PDF417 Code in an image, even if the
* PDF417 Code is rotated or skewed, or partially obscured.</p>
*
* @author SITA Lab (kevin.osullivan@sita.aero)
* @author dswitkin@google.com (Daniel Switkin)
* @author Guenther Grau
*/
const INDEXES_START_PATTERN: vec![Vec<i32>; 4] = vec![0, 4, 1, 5, ]
;
const INDEXES_STOP_PATTERN: vec![Vec<i32>; 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<i32>; 8] = vec![8, 1, 1, 1, 1, 1, 1, 3, ]
;
// 1111111 0 1 000 1 0 1 00 1
const STOP_PATTERN: vec![Vec<i32>; 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<i32>; 4] = vec![0, 180, 270, 90, ]
;
pub struct Detector {
}
impl Detector {
fn new() -> Detector {
}
/**
* <p>Detects a PDF417 Code in an image. Checks 0, 90, 180, and 270 degree rotations.</p>
*
* @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<DecodeHintType, ?>, multiple: bool) -> /* throws NotFoundException */Result<PDF417DetectorResult, Rc<Exception>> {
// 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<Vec<ResultPoint>> = ::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<Vec<ResultPoint>> {
let barcode_coordinates: List<Vec<ResultPoint>> = 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<ResultPoint> = ::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<ResultPoint> 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<ResultPoint> {
let height: i32 = matrix.get_height();
let width: i32 = matrix.get_width();
let result: [Option<ResultPoint>; 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<ResultPoint>, tmp_result: &Vec<ResultPoint>, destination_indexes: &Vec<i32>) {
{
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<i32>) -> Vec<ResultPoint> {
let mut result: [Option<ResultPoint>; 4] = [None; 4];
let mut found: bool = false;
let counters: [i32; pattern.len()] = [0; pattern.len()];
while start_row < height {
{
let mut loc: Vec<i32> = ::find_guard_pattern(matrix, start_column, start_row, width, &pattern, &counters);
if loc != null {
while start_row > 0 {
let previous_row_loc: Vec<i32> = ::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<i32>; 2] = vec![result[0].get_x() as i32, result[1].get_x() as i32, ]
;
while stop_row < height {
{
let loc: Vec<i32> = ::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<i32>, counters: &Vec<i32>) -> Vec<i32> {
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<i32>, pattern: &Vec<i32>) -> 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;
}
}

View File

@@ -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<Vec<ResultPoint>>;
let rotation: i32;
}
impl PDF417DetectorResult {
pub fn new( bits: &BitMatrix, points: &List<Vec<ResultPoint>>, rotation: i32) -> PDF417DetectorResult {
let .bits = bits;
let .points = points;
let .rotation = rotation;
}
pub fn new( bits: &BitMatrix, points: &List<Vec<ResultPoint>>) -> PDF417DetectorResult {
this(bits, &points, 0);
}
pub fn get_bits(&self) -> BitMatrix {
return self.bits;
}
pub fn get_points(&self) -> List<Vec<ResultPoint>> {
return self.points;
}
pub fn get_rotation(&self) -> i32 {
return self.rotation;
}
}

View File

@@ -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<BarcodeRow>;
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<BarcodeRow>; 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<Vec<i8>> {
return self.get_scaled_matrix(1, 1);
}
pub fn get_scaled_matrix(&self, x_scale: i32, y_scale: i32) -> Vec<Vec<i8>> {
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;
}
}

View File

@@ -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<i8>;
//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<i8> {
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;
}
}

View File

@@ -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()
}

View File

@@ -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;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -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<Vec<i32>>; 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<i32, Rc<Exception>> {
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<char>; 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();
}
}

View File

@@ -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<i8>; 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<i8>; 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<String, Rc<Exception>> {
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<i8> = 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<i8> = 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<i32, Rc<Exception>> {
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<Void, Rc<Exception>> {
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<i8> {
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<i8>, 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<char>; 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<i32, Rc<Exception>> {
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<Void, Rc<Exception>> {
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;
}
}
}

View File

@@ -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<String, Rc<Exception>> {
return Ok(PDF417HighLevelEncoder::encode_high_level(&msg, compaction, &encoding, auto_e_c_i));
}
}

File diff suppressed because one or more lines are too long

View File

@@ -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<Result>; 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<Result, Rc<Exception>> {
return Ok(::decode(image, null));
}
pub fn decode(&self, image: &BinaryBitmap, hints: &Map<DecodeHintType, ?>) -> /* throws NotFoundException, FormatException, ChecksumException */Result<Result, Rc<Exception>> {
let result: Vec<Result> = ::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<Vec<Result>, Rc<Exception>> {
return Ok(self.decode_multiple(image, null));
}
pub fn decode_multiple(&self, image: &BinaryBitmap, hints: &Map<DecodeHintType, ?>) -> /* throws NotFoundException */Result<Vec<Result>, Rc<Exception>> {
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<DecodeHintType, ?>, multiple: bool) -> /* throws NotFoundException, FormatException, ChecksumException */Result<Vec<Result>, Rc<Exception>> {
let results: List<Result> = ArrayList<>::new();
let detector_result: PDF417DetectorResult = Detector::detect(image, &hints, multiple);
for let points: Vec<ResultPoint> 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<ResultPoint>) -> 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<ResultPoint>) -> 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
}
}

View File

@@ -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<i32>;
}
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<i32> {
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<i32>) {
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;
}
}

View File

@@ -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<EncodeHintType, ?>) -> /* throws WriterException */Result<BitMatrix, Rc<Exception>> {
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<BitMatrix, Rc<Exception>> {
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<BitMatrix, Rc<Exception>> {
encoder.generate_barcode_logic(&contents, error_correction_level, auto_e_c_i);
let aspect_ratio: i32 = 4;
let original_scale: Vec<Vec<i8>> = 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<Vec<i8>> = 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<Vec<i8>>, 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<i8> = 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<i8>>) -> Vec<Vec<i8>> {
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;
}
}

View File

@@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -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;
/**
* <p>PDF417 error correction implementation.</p>
*
* <p>This <a href="http://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction#Example">example</a>
* is quite useful in understanding the algorithm.</p>
*
* @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<i32>, num_e_c_codewords: i32, erasures: &Vec<i32>) -> /* throws ChecksumException */Result<i32, Rc<Exception>> {
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<ModulusPoly> = 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<i32> = self.find_error_locations(sigma);
let error_magnitudes: Vec<i32> = 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<Vec<ModulusPoly>, Rc<Exception>> {
// 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<Vec<i32>, Rc<Exception>> {
// 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<i32>) -> Vec<i32> {
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;
/**
* <p>A field based on powers of a generator integer, modulo some modulus.</p>
*
* @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<i32>;
let log_table: Vec<i32>;
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<i32>;
}
impl ModulusPoly {
fn new( field: &ModulusGF, coefficients: &Vec<i32>) -> 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<i32> {
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<i32> = self.coefficients;
let larger_coefficients: Vec<i32> = other.coefficients;
if smaller_coefficients.len() > larger_coefficients.len() {
let temp: Vec<i32> = 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<i32> = self.coefficients;
let a_length: i32 = a_coefficients.len();
let b_coefficients: Vec<i32> = 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();
}
}

View File

@@ -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;
/**
* <p>Encapsulates logic that can detect a PDF417 Code in an image, even if the
* PDF417 Code is rotated or skewed, or partially obscured.</p>
*
* @author SITA Lab (kevin.osullivan@sita.aero)
* @author dswitkin@google.com (Daniel Switkin)
* @author Guenther Grau
*/
const INDEXES_START_PATTERN: vec![Vec<i32>; 4] = vec![0, 4, 1, 5, ]
;
const INDEXES_STOP_PATTERN: vec![Vec<i32>; 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<i32>; 8] = vec![8, 1, 1, 1, 1, 1, 1, 3, ]
;
// 1111111 0 1 000 1 0 1 00 1
const STOP_PATTERN: vec![Vec<i32>; 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<i32>; 4] = vec![0, 180, 270, 90, ]
;
pub struct Detector {
}
impl Detector {
fn new() -> Detector {
}
/**
* <p>Detects a PDF417 Code in an image. Checks 0, 90, 180, and 270 degree rotations.</p>
*
* @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<DecodeHintType, ?>, multiple: bool) -> /* throws NotFoundException */Result<PDF417DetectorResult, Rc<Exception>> {
// 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<Vec<ResultPoint>> = ::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<Vec<ResultPoint>> {
let barcode_coordinates: List<Vec<ResultPoint>> = 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<ResultPoint> = ::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<ResultPoint> 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<ResultPoint> {
let height: i32 = matrix.get_height();
let width: i32 = matrix.get_width();
let result: [Option<ResultPoint>; 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<ResultPoint>, tmp_result: &Vec<ResultPoint>, destination_indexes: &Vec<i32>) {
{
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<i32>) -> Vec<ResultPoint> {
let mut result: [Option<ResultPoint>; 4] = [None; 4];
let mut found: bool = false;
let counters: [i32; pattern.len()] = [0; pattern.len()];
while start_row < height {
{
let mut loc: Vec<i32> = ::find_guard_pattern(matrix, start_column, start_row, width, &pattern, &counters);
if loc != null {
while start_row > 0 {
let previous_row_loc: Vec<i32> = ::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<i32>; 2] = vec![result[0].get_x() as i32, result[1].get_x() as i32, ]
;
while stop_row < height {
{
let loc: Vec<i32> = ::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<i32>, counters: &Vec<i32>) -> Vec<i32> {
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<i32>, pattern: &Vec<i32>) -> 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<Vec<ResultPoint>>;
let rotation: i32;
}
impl PDF417DetectorResult {
pub fn new( bits: &BitMatrix, points: &List<Vec<ResultPoint>>, rotation: i32) -> PDF417DetectorResult {
let .bits = bits;
let .points = points;
let .rotation = rotation;
}
pub fn new( bits: &BitMatrix, points: &List<Vec<ResultPoint>>) -> PDF417DetectorResult {
this(bits, &points, 0);
}
pub fn get_bits(&self) -> BitMatrix {
return self.bits;
}
pub fn get_points(&self) -> List<Vec<ResultPoint>> {
return self.points;
}
pub fn get_rotation(&self) -> i32 {
return self.rotation;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -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<ResultPoint>; 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<Result, Rc<Exception>> {
return Ok(self.decode(image, null));
}
pub fn decode(&self, image: &BinaryBitmap, hints: &Map<DecodeHintType, ?>) -> /* throws NotFoundException, ChecksumException, FormatException */Result<Result, Rc<Exception>> {
let decoder_result: DecoderResult;
let mut points: Vec<ResultPoint>;
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<Vec<i8>> = 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<BitMatrix, Rc<Exception>> {
let left_top_black: Vec<i32> = image.get_top_left_on_bit();
let right_bottom_black: Vec<i32> = 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<i32>, image: &BitMatrix) -> /* throws NotFoundException */Result<f32, Rc<Exception>> {
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<BitMatrix, Rc<Exception>> {
return Ok(self.encode(&contents, format, width, height, null));
}
pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32, hints: &Map<EncodeHintType, ?>) -> /* throws WriterException */Result<BitMatrix, Rc<Exception>> {
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;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff