mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 12:22:34 +00:00
red lines on datamatrix
This commit is contained in:
@@ -1939,7 +1939,7 @@ impl DecoderResult {
|
||||
pub fn new(
|
||||
raw_bytes: &Vec<i8>,
|
||||
text: &String,
|
||||
byte_segments: &List<Vec<i8>>,
|
||||
byte_segments: &Vec<Vec<i8>>,
|
||||
ec_level: &String,
|
||||
sa_sequence: Option<i32>,
|
||||
sa_parity: Option<i32>,
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
pub mod decoder;
|
||||
pub mod detector;
|
||||
pub mod encoder;
|
||||
|
||||
use crate::{BarcodeFormat,BinaryBitmap,DecodeHintType,ChecksumException,FormatException,NotFoundException,Reader,RXingResult,ResultMetadataType,ResultPoint,EncodeHintType,Writer,Dimension};
|
||||
use crate::common::{DecoderResult,BitMatrix,DetectorResult,};
|
||||
use crate::datamatrix::decoder::{Decoder};
|
||||
@@ -14,10 +18,9 @@ use crate::qrcode::encoder::ByteMatrix;
|
||||
*/
|
||||
|
||||
const NO_POINTS: [Option<ResultPoint>; 0] = [None; 0];
|
||||
#[derive(Reader)]
|
||||
pub struct DataMatrixReader {
|
||||
|
||||
let decoder: Decoder = Decoder::new();
|
||||
decoder: Decoder
|
||||
}
|
||||
|
||||
impl Reader for DataMatrixReader{
|
||||
@@ -29,11 +32,7 @@ impl Reader for DataMatrixReader{
|
||||
* @throws FormatException if a Data Matrix 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>> {
|
||||
fn decode(&self, image: &BinaryBitmap, hints: &Map<DecodeHintType, _>) -> Result<Result, NotFoundException, ChecksumException, FormatException> {
|
||||
let decoder_result: DecoderResult;
|
||||
let mut points: Vec<ResultPoint>;
|
||||
if hints != null && hints.contains_key(DecodeHintType::PURE_BARCODE) {
|
||||
@@ -58,14 +57,18 @@ pub fn decode(&self, image: &BinaryBitmap, hints: &Map<DecodeHintType, ?>) ->
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
pub fn reset(&self) {
|
||||
fn reset(&self) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
impl DataMatrixReader {
|
||||
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self{
|
||||
decoder: Decoder::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method detects a code in a "pure" image -- that is, pure monochrome image
|
||||
@@ -73,11 +76,11 @@ impl DataMatrixReader {
|
||||
* 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>> {
|
||||
fn extract_pure_bits( image: &BitMatrix) -> Result<BitMatrix, NotFoundException> {
|
||||
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();
|
||||
return Err( NotFoundException::get_not_found_instance());
|
||||
}
|
||||
let module_size: i32 = self.module_size(&left_top_black, image);
|
||||
let mut top: i32 = left_top_black[1];
|
||||
@@ -87,7 +90,7 @@ impl DataMatrixReader {
|
||||
let matrix_width: i32 = (right - left + 1) / module_size;
|
||||
let matrix_height: i32 = (bottom - top + 1) / module_size;
|
||||
if matrix_width <= 0 || matrix_height <= 0 {
|
||||
throw NotFoundException::get_not_found_instance();
|
||||
return Err( 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
|
||||
@@ -122,7 +125,7 @@ impl DataMatrixReader {
|
||||
return Ok(bits);
|
||||
}
|
||||
|
||||
fn module_size( left_top_black: &Vec<i32>, image: &BitMatrix) -> /* throws NotFoundException */Result<i32, Rc<Exception>> {
|
||||
fn module_size( left_top_black: &Vec<i32>, image: &BitMatrix) -> Result<i32, NotFoundException> {
|
||||
let width: i32 = image.get_width();
|
||||
let mut x: i32 = left_top_black[0];
|
||||
let y: i32 = left_top_black[1];
|
||||
@@ -130,11 +133,11 @@ impl DataMatrixReader {
|
||||
x += 1;
|
||||
}
|
||||
if x == width {
|
||||
throw NotFoundException::get_not_found_instance();
|
||||
return Err( NotFoundException::get_not_found_instance());
|
||||
}
|
||||
let module_size: i32 = x - left_top_black[0];
|
||||
if module_size == 0 {
|
||||
throw NotFoundException::get_not_found_instance();
|
||||
return Err( NotFoundException::get_not_found_instance());
|
||||
}
|
||||
return Ok(module_size);
|
||||
}
|
||||
@@ -150,24 +153,20 @@ impl DataMatrixReader {
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
* @author Guillaume Le Biller Added to zxing lib.
|
||||
*/
|
||||
#[derive(Writer)]
|
||||
pub struct DataMatrixWriter {
|
||||
}
|
||||
|
||||
impl Writer for DataMatrixWriter{
|
||||
pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32) -> BitMatrix {
|
||||
return self.encode(&contents, format, width, height, null);
|
||||
}
|
||||
|
||||
pub fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32, hints: &Map<EncodeHintType, ?>) -> BitMatrix {
|
||||
fn encode(&self, contents: &String, format: &BarcodeFormat, width: i32, height: i32, hints: &Map<EncodeHintType, _>) -> BitMatrix {
|
||||
if contents.is_empty() {
|
||||
throw IllegalArgumentException::new("Found empty contents");
|
||||
return Err( IllegalArgumentException::new("Found empty contents"));
|
||||
}
|
||||
if format != BarcodeFormat::DATA_MATRIX {
|
||||
throw IllegalArgumentException::new(format!("Can only encode DATA_MATRIX, but got {}", format));
|
||||
return Err( IllegalArgumentException::new(format!("Can only encode DATA_MATRIX, but got {}", format)));
|
||||
}
|
||||
if width < 0 || height < 0 {
|
||||
throw IllegalArgumentException::new(format!("Requested dimensions can't be negative: {}x{}", width, height));
|
||||
return Err( IllegalArgumentException::new(format!("Requested dimensions can't be negative: {}x{}", width, height)));
|
||||
}
|
||||
// Try to get force shape & min / max size
|
||||
let mut shape: SymbolShapeHint = SymbolShapeHint::FORCE_NONE;
|
||||
@@ -197,14 +196,14 @@ impl Writer for DataMatrixWriter{
|
||||
if has_encoding_hint {
|
||||
charset = Charset::for_name(&hints.get(EncodeHintType::CHARACTER_SET).to_string());
|
||||
}
|
||||
encoded = MinimalEncoder::encode_high_level(&contents, &charset, if has_g_s1_format_hint { 0x1D } else { -1 }, shape);
|
||||
encoded = MinimalEncoder::encode_high_level(&contents, &charset, if has_g_s1_format_hint { 0x1D } else { -1 }, &shape);
|
||||
} else {
|
||||
let has_force_c40_hint: bool = hints != null && hints.contains_key(EncodeHintType::FORCE_C40) && Boolean::parse_boolean(&hints.get(EncodeHintType::FORCE_C40).to_string());
|
||||
encoded = HighLevelEncoder::encode_high_level(&contents, shape, min_size, max_size, has_force_c40_hint);
|
||||
}
|
||||
let symbol_info: SymbolInfo = SymbolInfo::lookup(&encoded.length(), shape, min_size, max_size, true);
|
||||
//2. step: ECC generation
|
||||
let codewords: String = ErrorCorrection::encode_e_c_c200(&encoded, symbol_info);
|
||||
let codewords: String = ErrorCorrection::encode_e_c_c200(&encoded, &symbol_info);
|
||||
//3. step: Module placement in Matrix
|
||||
let placement: DefaultPlacement = DefaultPlacement::new(&codewords, &symbol_info.get_symbol_data_width(), &symbol_info.get_symbol_data_height());
|
||||
placement.place();
|
||||
@@ -329,7 +328,8 @@ impl DataMatrixWriter {
|
||||
{
|
||||
// Write the contents of this row of the bytematrix
|
||||
{
|
||||
let input_x: i32 = 0, let output_x: i32 = left_padding;
|
||||
let input_x: i32 = 0;
|
||||
let output_x: i32 = left_padding;
|
||||
while input_x < matrix_width {
|
||||
{
|
||||
if matrix.get(input_x, input_y) == 1 {
|
||||
|
||||
@@ -9,11 +9,11 @@ use crate::common::reedsolomon::{GenericGF,ReedSolomonDecoder,ReedSolomonExcepti
|
||||
*/
|
||||
struct BitMatrixParser {
|
||||
|
||||
let mapping_bit_matrix: BitMatrix;
|
||||
mapping_bit_matrix: BitMatrix,
|
||||
|
||||
let read_mapping_matrix: BitMatrix;
|
||||
read_mapping_matrix: BitMatrix,
|
||||
|
||||
let mut version: Version;
|
||||
version: Version
|
||||
}
|
||||
|
||||
impl BitMatrixParser {
|
||||
@@ -22,15 +22,18 @@ impl BitMatrixParser {
|
||||
* @param bitMatrix {@link BitMatrix} to parse
|
||||
* @throws FormatException if dimension is < 8 or > 144 or not 0 mod 2
|
||||
*/
|
||||
fn new( bit_matrix: &BitMatrix) -> BitMatrixParser throws FormatException {
|
||||
fn new( bit_matrix: &BitMatrix) -> Result<Self, FormatException> {
|
||||
let dimension: i32 = bit_matrix.get_height();
|
||||
if dimension < 8 || dimension > 144 || (dimension & 0x01) != 0 {
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
version = ::read_version(bit_matrix);
|
||||
let .mappingBitMatrix = self.extract_data_region(bit_matrix);
|
||||
let .readMappingMatrix = BitMatrix::new(&let .mappingBitMatrix.get_width(), &let .mappingBitMatrix.get_height());
|
||||
}
|
||||
let new_bmp : Self;
|
||||
new_bmp.version = ::read_version(bit_matrix);
|
||||
new_bmp .mappingBitMatrix = self.extract_data_region(bit_matrix);
|
||||
new_bmp .readMappingMatrix = BitMatrix::new(&new_bmp.mappingBitMatrix.get_width(), &new_bmp.mappingBitMatrix.get_height());
|
||||
|
||||
Ok(new_bmp)
|
||||
}
|
||||
|
||||
fn get_version(&self) -> Version {
|
||||
return self.version;
|
||||
@@ -61,7 +64,7 @@ impl BitMatrixParser {
|
||||
* @return bytes encoded within the Data Matrix Code
|
||||
* @throws FormatException if the exact number of bytes expected is not read
|
||||
*/
|
||||
fn read_codewords(&self) -> /* throws FormatException */Result<Vec<i8>, Rc<Exception>> {
|
||||
fn read_codewords(&self) -> Result<Vec<i8>, FormatException> {
|
||||
let mut result: [i8; self.version.get_total_codewords()] = [0; self.version.get_total_codewords()];
|
||||
let result_offset: i32 = 0;
|
||||
let mut row: i32 = 4;
|
||||
@@ -76,22 +79,22 @@ impl BitMatrixParser {
|
||||
loop { {
|
||||
// Check the four corner cases
|
||||
if (row == num_rows) && (column == 0) && !corner1_read {
|
||||
result[result_offset += 1 !!!check!!! post increment] = self.read_corner1(num_rows, num_columns) as i8;
|
||||
result[result_offset += 1 ] = self.read_corner1(num_rows, num_columns) as i8;
|
||||
row -= 2;
|
||||
column += 2;
|
||||
corner1_read = true;
|
||||
} else if (row == num_rows - 2) && (column == 0) && ((num_columns & 0x03) != 0) && !corner2_read {
|
||||
result[result_offset += 1 !!!check!!! post increment] = self.read_corner2(num_rows, num_columns) as i8;
|
||||
result[result_offset += 1 ] = self.read_corner2(num_rows, num_columns) as i8;
|
||||
row -= 2;
|
||||
column += 2;
|
||||
corner2_read = true;
|
||||
} else if (row == num_rows + 4) && (column == 2) && ((num_columns & 0x07) == 0) && !corner3_read {
|
||||
result[result_offset += 1 !!!check!!! post increment] = self.read_corner3(num_rows, num_columns) as i8;
|
||||
result[result_offset += 1 ] = self.read_corner3(num_rows, num_columns) as i8;
|
||||
row -= 2;
|
||||
column += 2;
|
||||
corner3_read = true;
|
||||
} else if (row == num_rows - 2) && (column == 0) && ((num_columns & 0x07) == 4) && !corner4_read {
|
||||
result[result_offset += 1 !!!check!!! post increment] = self.read_corner4(num_rows, num_columns) as i8;
|
||||
result[result_offset += 1 ] = self.read_corner4(num_rows, num_columns) as i8;
|
||||
row -= 2;
|
||||
column += 2;
|
||||
corner4_read = true;
|
||||
@@ -99,27 +102,27 @@ impl BitMatrixParser {
|
||||
// Sweep upward diagonally to the right
|
||||
loop { {
|
||||
if (row < num_rows) && (column >= 0) && !self.read_mapping_matrix.get(column, row) {
|
||||
result[result_offset += 1 !!!check!!! post increment] = self.read_utah(row, column, num_rows, num_columns) as i8;
|
||||
result[result_offset += 1 ] = self.read_utah(row, column, num_rows, num_columns) as i8;
|
||||
}
|
||||
row -= 2;
|
||||
column += 2;
|
||||
}if !((row >= 0) && (column < num_columns)) break;}
|
||||
}if !((row >= 0) && (column < num_columns)) {break;}}
|
||||
row += 1;
|
||||
column += 3;
|
||||
// Sweep downward diagonally to the left
|
||||
loop { {
|
||||
if (row >= 0) && (column < num_columns) && !self.read_mapping_matrix.get(column, row) {
|
||||
result[result_offset += 1 !!!check!!! post increment] = self.read_utah(row, column, num_rows, num_columns) as i8;
|
||||
result[result_offset += 1 ] = self.read_utah(row, column, num_rows, num_columns) as i8;
|
||||
}
|
||||
row += 2;
|
||||
column -= 2;
|
||||
}if !((row < num_rows) && (column >= 0)) break;}
|
||||
}if !((row < num_rows) && (column >= 0)) {break;}}
|
||||
row += 3;
|
||||
column += 1;
|
||||
}
|
||||
}if !((row < num_rows) || (column < num_columns)) break;}
|
||||
}if !((row < num_rows) || (column < num_columns)) {break;}}
|
||||
if result_offset != self.version.get_total_codewords() {
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
@@ -388,7 +391,7 @@ impl BitMatrixParser {
|
||||
let symbol_size_rows: i32 = self.version.get_symbol_size_rows();
|
||||
let symbol_size_columns: i32 = self.version.get_symbol_size_columns();
|
||||
if bit_matrix.get_height() != symbol_size_rows {
|
||||
throw IllegalArgumentException::new("Dimension of bitMatrix must match the version size");
|
||||
return Err( IllegalArgumentException::new("Dimension of bitMatrix must match the version size"));
|
||||
}
|
||||
let data_region_size_rows: i32 = self.version.get_data_region_size_rows();
|
||||
let data_region_size_columns: i32 = self.version.get_data_region_size_columns();
|
||||
@@ -457,17 +460,18 @@ impl BitMatrixParser {
|
||||
*/
|
||||
struct DataBlock {
|
||||
|
||||
let num_data_codewords: i32;
|
||||
num_data_codewords: i32,
|
||||
|
||||
let mut codewords: Vec<i8>;
|
||||
codewords: Vec<i8>
|
||||
}
|
||||
|
||||
impl DataBlock {
|
||||
|
||||
fn new( num_data_codewords: i32, codewords: &Vec<i8>) -> DataBlock {
|
||||
let .numDataCodewords = num_data_codewords;
|
||||
let .codewords = codewords;
|
||||
}
|
||||
fn new( num_data_codewords: i32, codewords: &Vec<i8>) -> Self {
|
||||
Self {
|
||||
num_data_codewords,
|
||||
codewords: codewords,
|
||||
}}
|
||||
|
||||
/**
|
||||
* <p>When Data Matrix Codes use multiple data blocks, they actually interleave the bytes of each of them.
|
||||
@@ -481,24 +485,24 @@ impl DataBlock {
|
||||
*/
|
||||
fn get_data_blocks( raw_codewords: &Vec<i8>, version: &Version) -> Vec<DataBlock> {
|
||||
// Figure out the number and size of data blocks used by this version
|
||||
let ec_blocks: Version.ECBlocks = version.get_e_c_blocks();
|
||||
let ec_blocks: Version::ECBlocks = version.get_e_c_blocks();
|
||||
// First count the total number of data blocks
|
||||
let total_blocks: i32 = 0;
|
||||
let ec_block_array: Vec<Version.ECB> = ec_blocks.get_e_c_blocks();
|
||||
for let ec_block: Version.ECB in ec_block_array {
|
||||
let ec_block_array: Vec<Version::ECB> = ec_blocks.get_e_c_blocks();
|
||||
for ec_block in ec_block_array {
|
||||
total_blocks += ec_block.get_count();
|
||||
}
|
||||
// Now establish DataBlocks of the appropriate size and number of data codewords
|
||||
let mut result: [Option<DataBlock>; total_blocks] = [None; total_blocks];
|
||||
let num_result_blocks: i32 = 0;
|
||||
for let ec_block: Version.ECB in ec_block_array {
|
||||
for ec_block in ec_block_array {
|
||||
{
|
||||
let mut i: i32 = 0;
|
||||
while i < ec_block.get_count() {
|
||||
{
|
||||
let num_data_codewords: i32 = ec_block.get_data_codewords();
|
||||
let num_block_codewords: i32 = ec_blocks.get_e_c_codewords() + num_data_codewords;
|
||||
result[num_result_blocks += 1 !!!check!!! post increment] = DataBlock::new(num_data_codewords, : [i8; num_block_codewords] = [0; num_block_codewords]);
|
||||
result[num_result_blocks += 1 ] = DataBlock::new(num_data_codewords, [0; num_block_codewords]);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
@@ -523,7 +527,7 @@ impl DataBlock {
|
||||
let mut j: i32 = 0;
|
||||
while j < num_result_blocks {
|
||||
{
|
||||
result[j].codewords[i] = raw_codewords[raw_codewords_offset += 1 !!!check!!! post increment];
|
||||
result[j].codewords[i] = raw_codewords[raw_codewords_offset += 1 ];
|
||||
}
|
||||
j += 1;
|
||||
}
|
||||
@@ -541,7 +545,7 @@ impl DataBlock {
|
||||
let mut j: i32 = 0;
|
||||
while j < num_longer_blocks {
|
||||
{
|
||||
result[j].codewords[longer_blocks_num_data_codewords - 1] = raw_codewords[raw_codewords_offset += 1 !!!check!!! post increment];
|
||||
result[j].codewords[longer_blocks_num_data_codewords - 1] = raw_codewords[raw_codewords_offset += 1 ];
|
||||
}
|
||||
j += 1;
|
||||
}
|
||||
@@ -559,7 +563,7 @@ impl DataBlock {
|
||||
{
|
||||
let j_offset: i32 = if special_version { (j + 8) % num_result_blocks } else { j };
|
||||
let i_offset: i32 = if special_version && j_offset > 7 { i - 1 } else { i };
|
||||
result[j_offset].codewords[i_offset] = raw_codewords[raw_codewords_offset += 1 !!!check!!! post increment];
|
||||
result[j_offset].codewords[i_offset] = raw_codewords[raw_codewords_offset += 1 ];
|
||||
}
|
||||
j += 1;
|
||||
}
|
||||
@@ -571,7 +575,7 @@ impl DataBlock {
|
||||
}
|
||||
|
||||
if raw_codewords_offset != raw_codewords.len() {
|
||||
throw IllegalArgumentException::new();
|
||||
return Err( IllegalArgumentException::new());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -615,28 +619,31 @@ impl DataBlock {
|
||||
|
||||
const TEXT_SHIFT3_SET_CHARS: vec![Vec<char>; 32] = vec!['`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', 127 as char, ]
|
||||
;
|
||||
|
||||
enum Mode {
|
||||
|
||||
// Not really a mode
|
||||
PAD_ENCODE(), ASCII_ENCODE(), C40_ENCODE(), TEXT_ENCODE(), ANSIX12_ENCODE(), EDIFACT_ENCODE(), BASE256_ENCODE(), ECI_ENCODE()
|
||||
}
|
||||
|
||||
struct DecodedBitStreamParser {
|
||||
}
|
||||
|
||||
impl DecodedBitStreamParser {
|
||||
|
||||
enum Mode {
|
||||
|
||||
// Not really a mode
|
||||
PAD_ENCODE(), ASCII_ENCODE(), C40_ENCODE(), TEXT_ENCODE(), ANSIX12_ENCODE(), EDIFACT_ENCODE(), BASE256_ENCODE(), ECI_ENCODE()
|
||||
}
|
||||
|
||||
|
||||
fn new() -> DecodedBitStreamParser {
|
||||
}
|
||||
|
||||
fn decode( bytes: &Vec<i8>) -> /* throws FormatException */Result<DecoderResult, Rc<Exception>> {
|
||||
let bits: BitSource = BitSource::new(&bytes);
|
||||
let result: ECIStringBuilder = ECIStringBuilder::new(100);
|
||||
let result: ECIStringBuilder = ECIStringBuilder::new();
|
||||
let result_trailer: StringBuilder = StringBuilder::new(0);
|
||||
let byte_segments: List<Vec<i8>> = ArrayList<>::new(1);
|
||||
let byte_segments: List<Vec<i8>> = Vec::new();
|
||||
let mut mode: Mode = Mode::ASCII_ENCODE;
|
||||
// Could look directly at 'bytes', if we're sure of not having to account for multi byte values
|
||||
let fnc1_positions: Set<Integer> = HashSet<>::new();
|
||||
let fnc1_positions: Set<Integer> = HashSet::new();
|
||||
let symbology_modifier: i32;
|
||||
let is_e_c_iencoded: bool = false;
|
||||
loop { {
|
||||
@@ -678,12 +685,12 @@ impl DataBlock {
|
||||
}
|
||||
_ =>
|
||||
{
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
}
|
||||
mode = Mode::ASCII_ENCODE;
|
||||
}
|
||||
}if !(mode != Mode::PAD_ENCODE && bits.available() > 0) break;}
|
||||
}if !(mode != Mode::PAD_ENCODE && bits.available() > 0) {break;}}
|
||||
if result_trailer.length() > 0 {
|
||||
result.append_characters(&result_trailer);
|
||||
}
|
||||
@@ -704,8 +711,11 @@ impl DataBlock {
|
||||
} else {
|
||||
symbology_modifier = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
return Ok(DecoderResult::new(&bytes, &result.to_string(), if byte_segments.is_empty() { null } else { byte_segments }, null, symbology_modifier));
|
||||
return Ok(DecoderResult::new(&bytes, &result.to_string(), &byte_segments , null, Some(symbology_modifier), None, None));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -716,7 +726,7 @@ impl DataBlock {
|
||||
loop { {
|
||||
let one_byte: i32 = bits.read_bits(8);
|
||||
if one_byte == 0 {
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
} else if one_byte <= 128 {
|
||||
// ASCII data (ASCII value + 1)
|
||||
if upper_shift {
|
||||
@@ -775,15 +785,15 @@ impl DataBlock {
|
||||
// 05 Macro
|
||||
236 =>
|
||||
{
|
||||
result.append("[)>\u001E05\u001D");
|
||||
result_trailer.insert(0, "\u001E\u0004");
|
||||
result.append("[)>\u{001E05}\u{001D}");
|
||||
result_trailer.insert(0, "\u{001E}\u{0004}");
|
||||
break;
|
||||
}
|
||||
// 06 Macro
|
||||
237 =>
|
||||
{
|
||||
result.append("[)>\u001E06\u001D");
|
||||
resultTrailer.insert(0, "\u001E\u0004");
|
||||
result.append("[)>\u{001E06}\u{001D}");
|
||||
resultTrailer.insert(0, "\u{001E}\u{0004}");
|
||||
break;
|
||||
}
|
||||
// Latch to ANSI X12 encodation
|
||||
@@ -810,20 +820,20 @@ impl DataBlock {
|
||||
{
|
||||
// but work around encoders that end with 254, latch back to ASCII
|
||||
if one_byte != 254 || bits.available() != 0 {
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}if !(bits.available() > 0) break;}
|
||||
}if !(bits.available() > 0) {break;}}
|
||||
return Ok(Mode::ASCII_ENCODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* See ISO 16022:2006, 5.2.5 and Annex C, Table C.1
|
||||
*/
|
||||
fn decode_c40_segment( bits: &BitSource, result: &ECIStringBuilder, fnc1positions: &Set<Integer>) -> /* throws FormatException */Result<Void, Rc<Exception>> {
|
||||
fn decode_c40_segment( bits: &BitSource, result: &ECIStringBuilder, fnc1positions: &Set<Integer>) -> Result<(), FormatException> {
|
||||
// Three C40 values are encoded in a 16-bit value as
|
||||
// (1600 * C1) + (40 * C2) + C3 + 1
|
||||
// TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time
|
||||
@@ -860,7 +870,7 @@ impl DataBlock {
|
||||
result.append(c40char);
|
||||
}
|
||||
} else {
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -903,7 +913,7 @@ impl DataBlock {
|
||||
}
|
||||
_ =>
|
||||
{
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -923,7 +933,7 @@ impl DataBlock {
|
||||
}
|
||||
_ =>
|
||||
{
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -931,7 +941,8 @@ impl DataBlock {
|
||||
}
|
||||
}
|
||||
|
||||
}if !(bits.available() > 0) break;}
|
||||
}if !(bits.available() > 0) {break;}}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -974,7 +985,7 @@ impl DataBlock {
|
||||
result.append(text_char);
|
||||
}
|
||||
} else {
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1018,7 +1029,7 @@ impl DataBlock {
|
||||
}
|
||||
_ =>
|
||||
{
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1037,13 +1048,13 @@ impl DataBlock {
|
||||
}
|
||||
shift = 0;
|
||||
} else {
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
break;
|
||||
}
|
||||
_ =>
|
||||
{
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1051,7 +1062,8 @@ impl DataBlock {
|
||||
}
|
||||
}
|
||||
|
||||
}if !(bits.available() > 0) break;}
|
||||
}if !(bits.available() > 0) {break;}}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1111,7 +1123,7 @@ impl DataBlock {
|
||||
// A - Z
|
||||
result.append((c_value + 51) as char);
|
||||
} else {
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1121,7 +1133,8 @@ impl DataBlock {
|
||||
}
|
||||
}
|
||||
|
||||
}if !(bits.available() > 0) break;}
|
||||
}if !(bits.available() > 0) {break;}}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_two_bytes( first_byte: i32, second_byte: i32, result: &Vec<i32>) {
|
||||
@@ -1169,17 +1182,17 @@ impl DataBlock {
|
||||
}
|
||||
}
|
||||
|
||||
}if !(bits.available() > 0) break;}
|
||||
}if !(bits.available() > 0) {break;}}
|
||||
}
|
||||
|
||||
/**
|
||||
* See ISO 16022:2006, 5.2.9 and Annex B, B.2
|
||||
*/
|
||||
fn decode_base256_segment( bits: &BitSource, result: &ECIStringBuilder, byte_segments: &Collection<Vec<i8>>) -> /* throws FormatException */Result<Void, Rc<Exception>> {
|
||||
fn decode_base256_segment( bits: &BitSource, result: &ECIStringBuilder, byte_segments: &Collection<Vec<i8>>) -> Result<(), FormatException> {
|
||||
// Figure out how long the Base 256 Segment is.
|
||||
// position is 1-indexed
|
||||
let codeword_position: i32 = 1 + bits.get_byte_offset();
|
||||
let d1: i32 = ::unrandomize255_state(&bits.read_bits(8), codeword_position += 1 !!!check!!! post increment);
|
||||
let d1: i32 = ::unrandomize255_state(&bits.read_bits(8), codeword_position += 1 );
|
||||
let mut count: i32;
|
||||
if d1 == 0 {
|
||||
// Read the remainder of the symbol
|
||||
@@ -1187,11 +1200,11 @@ impl DataBlock {
|
||||
} else if d1 < 250 {
|
||||
count = d1;
|
||||
} else {
|
||||
count = 250 * (d1 - 249) + ::unrandomize255_state(&bits.read_bits(8), codeword_position += 1 !!!check!!! post increment);
|
||||
count = 250 * (d1 - 249) + ::unrandomize255_state(&bits.read_bits(8), codeword_position += 1 );
|
||||
}
|
||||
// We're seeing NegativeArraySizeException errors from users.
|
||||
if count < 0 {
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
let mut bytes: [i8; count] = [0; count];
|
||||
{
|
||||
@@ -1200,29 +1213,37 @@ impl DataBlock {
|
||||
{
|
||||
// http://www.bcgen.com/demo/IDAutomationStreamingDataMatrix.aspx?MODE=3&D=Fred&PFMT=3&PT=F&X=0.3&O=0&LM=0.2
|
||||
if bits.available() < 8 {
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
bytes[i] = ::unrandomize255_state(&bits.read_bits(8), codeword_position += 1 !!!check!!! post increment) as i8;
|
||||
bytes[i] = ::unrandomize255_state(&bits.read_bits(8), codeword_position += 1 ) as i8;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
byte_segments.add(&bytes);
|
||||
result.append(String::new(&bytes, StandardCharsets::ISO_8859_1));
|
||||
{
|
||||
use encoding::{Encoding,DecoderTrap};
|
||||
use encoding::all::ISO_8859_1;
|
||||
|
||||
result.append(ISO_8859_1.decode(&bytes, DecoderTrap::Strict).unwrap_or("".to_owned()))
|
||||
// result.append(String::new(&bytes, StandardCharsets::ISO_8859_1));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/**
|
||||
* See ISO 16022:2007, 5.4.1
|
||||
*/
|
||||
fn decode_e_c_i_segment( bits: &BitSource, result: &ECIStringBuilder) -> /* throws FormatException */Result<Void, Rc<Exception>> {
|
||||
fn decode_e_c_i_segment( bits: &BitSource, result: &ECIStringBuilder) -> Result<(),FormatException> {
|
||||
if bits.available() < 8 {
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
let c1: i32 = bits.read_bits(8);
|
||||
if c1 <= 127 {
|
||||
result.append_e_c_i(c1 - 1);
|
||||
}
|
||||
Ok(())
|
||||
//currently we only support character set ECIs
|
||||
/*} else {
|
||||
if (bits.available() < 8) {
|
||||
@@ -1259,7 +1280,7 @@ impl DataBlock {
|
||||
*/
|
||||
pub struct Decoder {
|
||||
|
||||
let rs_decoder: ReedSolomonDecoder;
|
||||
rs_decoder: ReedSolomonDecoder
|
||||
}
|
||||
|
||||
impl Decoder {
|
||||
@@ -1297,10 +1318,10 @@ impl Decoder {
|
||||
// Read codewords
|
||||
let codewords: Vec<i8> = parser.read_codewords();
|
||||
// Separate into data blocks
|
||||
let data_blocks: Vec<DataBlock> = DataBlock::get_data_blocks(&codewords, version);
|
||||
let data_blocks: Vec<DataBlock> = DataBlock::get_data_blocks(&codewords, &version);
|
||||
// Count total number of data bytes
|
||||
let total_bytes: i32 = 0;
|
||||
for let db: DataBlock in data_blocks {
|
||||
for db in data_blocks {
|
||||
total_bytes += db.get_num_data_codewords();
|
||||
}
|
||||
let result_bytes: [i8; total_bytes] = [0; total_bytes];
|
||||
@@ -1342,7 +1363,7 @@ impl Decoder {
|
||||
* @param numDataCodewords number of codewords that are data bytes
|
||||
* @throws ChecksumException if error correction fails
|
||||
*/
|
||||
fn correct_errors(&self, codeword_bytes: &Vec<i8>, num_data_codewords: i32) -> /* throws ChecksumException */Result<Void, Rc<Exception>> {
|
||||
fn correct_errors(&self, codeword_bytes: &Vec<i8>, num_data_codewords: i32) -> Result<(), ChecksumException> {
|
||||
let num_codewords: i32 = codeword_bytes.len();
|
||||
// First read into an array of ints
|
||||
let codewords_ints: [i32; num_codewords] = [0; num_codewords];
|
||||
@@ -1356,18 +1377,9 @@ impl Decoder {
|
||||
}
|
||||
}
|
||||
|
||||
let tryResult1 = 0;
|
||||
'try1: loop {
|
||||
{
|
||||
|
||||
self.rs_decoder.decode(&codewords_ints, codeword_bytes.len() - num_data_codewords);
|
||||
}
|
||||
break 'try1
|
||||
}
|
||||
match tryResult1 {
|
||||
catch ( ignored: &ReedSolomonException) {
|
||||
throw ChecksumException::get_checksum_instance();
|
||||
} 0 => break
|
||||
}
|
||||
|
||||
|
||||
// We don't care about errors in the error-correction codewords
|
||||
{
|
||||
@@ -1379,6 +1391,7 @@ impl Decoder {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1395,38 +1408,41 @@ impl Decoder {
|
||||
const VERSIONS: Vec<Version> = ::build_versions();
|
||||
pub struct Version {
|
||||
|
||||
let version_number: i32;
|
||||
version_number: i32,
|
||||
|
||||
let symbol_size_rows: i32;
|
||||
symbol_size_rows: i32,
|
||||
|
||||
let symbol_size_columns: i32;
|
||||
symbol_size_columns: i32,
|
||||
|
||||
let data_region_size_rows: i32;
|
||||
data_region_size_rows: i32,
|
||||
|
||||
let data_region_size_columns: i32;
|
||||
data_region_size_columns: i32,
|
||||
|
||||
let ec_blocks: ECBlocks;
|
||||
ec_blocks: ECBlocks,
|
||||
|
||||
let total_codewords: i32;
|
||||
total_codewords: i32
|
||||
}
|
||||
|
||||
impl Version {
|
||||
|
||||
fn new( version_number: i32, symbol_size_rows: i32, symbol_size_columns: i32, data_region_size_rows: i32, data_region_size_columns: i32, ec_blocks: &ECBlocks) -> Version {
|
||||
let .versionNumber = version_number;
|
||||
let .symbolSizeRows = symbol_size_rows;
|
||||
let .symbolSizeColumns = symbol_size_columns;
|
||||
let .dataRegionSizeRows = data_region_size_rows;
|
||||
let .dataRegionSizeColumns = data_region_size_columns;
|
||||
let .ecBlocks = ec_blocks;
|
||||
fn new( version_number: i32, symbol_size_rows: i32, symbol_size_columns: i32, data_region_size_rows: i32, data_region_size_columns: i32, ec_blocks: &ECBlocks) -> Self {
|
||||
let new_v : Self;
|
||||
new_v .versionNumber = version_number;
|
||||
new_v .symbolSizeRows = symbol_size_rows;
|
||||
new_v .symbolSizeColumns = symbol_size_columns;
|
||||
new_v .dataRegionSizeRows = data_region_size_rows;
|
||||
new_v .dataRegionSizeColumns = data_region_size_columns;
|
||||
new_v .ecBlocks = ec_blocks;
|
||||
// Calculate the total number of codewords
|
||||
let mut total: i32 = 0;
|
||||
let ec_codewords: i32 = ec_blocks.get_e_c_codewords();
|
||||
let ecb_array: Vec<ECB> = ec_blocks.get_e_c_blocks();
|
||||
for let ec_block: ECB in ecb_array {
|
||||
for ec_block in ecb_array {
|
||||
total += ec_block.get_count() * (ec_block.get_data_codewords() + ec_codewords);
|
||||
}
|
||||
let .totalCodewords = total;
|
||||
new_v .totalCodewords = total;
|
||||
|
||||
new_v
|
||||
}
|
||||
|
||||
pub fn get_version_number(&self) -> i32 {
|
||||
@@ -1467,79 +1483,14 @@ impl Version {
|
||||
*/
|
||||
pub fn get_version_for_dimensions( num_rows: i32, num_columns: i32) -> /* throws FormatException */Result<Version, Rc<Exception>> {
|
||||
if (num_rows & 0x01) != 0 || (num_columns & 0x01) != 0 {
|
||||
throw FormatException::get_format_instance();
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
for let version: Version in VERSIONS {
|
||||
for version in VERSIONS {
|
||||
if version.symbolSizeRows == num_rows && version.symbolSizeColumns == num_columns {
|
||||
return Ok(version);
|
||||
}
|
||||
}
|
||||
throw FormatException::get_format_instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will
|
||||
* use blocks of differing sizes within one version, so, this encapsulates the parameters for
|
||||
* each set of blocks. It also holds the number of error-correction codewords per block since it
|
||||
* will be the same across all blocks within one version.</p>
|
||||
*/
|
||||
struct ECBlocks {
|
||||
|
||||
let ec_codewords: i32;
|
||||
|
||||
let ec_blocks: Vec<ECB>;
|
||||
}
|
||||
|
||||
impl ECBlocks {
|
||||
|
||||
fn new( ec_codewords: i32, ec_blocks: &ECB) -> ECBlocks {
|
||||
let .ecCodewords = ec_codewords;
|
||||
let .ecBlocks = : vec![ECB; 1] = vec![ec_blocks, ]
|
||||
;
|
||||
}
|
||||
|
||||
fn new( ec_codewords: i32, ec_blocks1: &ECB, ec_blocks2: &ECB) -> ECBlocks {
|
||||
let .ecCodewords = ec_codewords;
|
||||
let .ecBlocks = : vec![ECB; 2] = vec![ec_blocks1, ec_blocks2, ]
|
||||
;
|
||||
}
|
||||
|
||||
fn get_e_c_codewords(&self) -> i32 {
|
||||
return self.ec_codewords;
|
||||
}
|
||||
|
||||
fn get_e_c_blocks(&self) -> Vec<ECB> {
|
||||
return self.ec_blocks;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Encapsulates the parameters for one error-correction block in one symbol version.
|
||||
* This includes the number of data codewords, and the number of times a block with these
|
||||
* parameters is used consecutively in the Data Matrix code version's format.</p>
|
||||
*/
|
||||
struct ECB {
|
||||
|
||||
let count: i32;
|
||||
|
||||
let data_codewords: i32;
|
||||
}
|
||||
|
||||
impl ECB {
|
||||
|
||||
fn new( count: i32, data_codewords: i32) -> ECB {
|
||||
let .count = count;
|
||||
let .dataCodewords = data_codewords;
|
||||
}
|
||||
|
||||
fn get_count(&self) -> i32 {
|
||||
return self.count;
|
||||
}
|
||||
|
||||
fn get_data_codewords(&self) -> i32 {
|
||||
return self.data_codewords;
|
||||
}
|
||||
return Err( FormatException::get_format_instance());
|
||||
}
|
||||
|
||||
|
||||
@@ -1551,9 +1502,79 @@ impl Version {
|
||||
* See ISO 16022:2006 5.5.1 Table 7
|
||||
*/
|
||||
fn build_versions() -> Vec<Version> {
|
||||
return : vec![Version; 48] = vec![Version::new(1, 10, 10, 8, 8, ECBlocks::new(5, ECB::new(1, 3))), Version::new(2, 12, 12, 10, 10, ECBlocks::new(7, ECB::new(1, 5))), Version::new(3, 14, 14, 12, 12, ECBlocks::new(10, ECB::new(1, 8))), Version::new(4, 16, 16, 14, 14, ECBlocks::new(12, ECB::new(1, 12))), Version::new(5, 18, 18, 16, 16, ECBlocks::new(14, ECB::new(1, 18))), Version::new(6, 20, 20, 18, 18, ECBlocks::new(18, ECB::new(1, 22))), Version::new(7, 22, 22, 20, 20, ECBlocks::new(20, ECB::new(1, 30))), Version::new(8, 24, 24, 22, 22, ECBlocks::new(24, ECB::new(1, 36))), Version::new(9, 26, 26, 24, 24, ECBlocks::new(28, ECB::new(1, 44))), Version::new(10, 32, 32, 14, 14, ECBlocks::new(36, ECB::new(1, 62))), Version::new(11, 36, 36, 16, 16, ECBlocks::new(42, ECB::new(1, 86))), Version::new(12, 40, 40, 18, 18, ECBlocks::new(48, ECB::new(1, 114))), Version::new(13, 44, 44, 20, 20, ECBlocks::new(56, ECB::new(1, 144))), Version::new(14, 48, 48, 22, 22, ECBlocks::new(68, ECB::new(1, 174))), Version::new(15, 52, 52, 24, 24, ECBlocks::new(42, ECB::new(2, 102))), Version::new(16, 64, 64, 14, 14, ECBlocks::new(56, ECB::new(2, 140))), Version::new(17, 72, 72, 16, 16, ECBlocks::new(36, ECB::new(4, 92))), Version::new(18, 80, 80, 18, 18, ECBlocks::new(48, ECB::new(4, 114))), Version::new(19, 88, 88, 20, 20, ECBlocks::new(56, ECB::new(4, 144))), Version::new(20, 96, 96, 22, 22, ECBlocks::new(68, ECB::new(4, 174))), Version::new(21, 104, 104, 24, 24, ECBlocks::new(56, ECB::new(6, 136))), Version::new(22, 120, 120, 18, 18, ECBlocks::new(68, ECB::new(6, 175))), Version::new(23, 132, 132, 20, 20, ECBlocks::new(62, ECB::new(8, 163))), Version::new(24, 144, 144, 22, 22, ECBlocks::new(62, ECB::new(8, 156), ECB::new(2, 155))), Version::new(25, 8, 18, 6, 16, ECBlocks::new(7, ECB::new(1, 5))), Version::new(26, 8, 32, 6, 14, ECBlocks::new(11, ECB::new(1, 10))), Version::new(27, 12, 26, 10, 24, ECBlocks::new(14, ECB::new(1, 16))), Version::new(28, 12, 36, 10, 16, ECBlocks::new(18, ECB::new(1, 22))), Version::new(29, 16, 36, 14, 16, ECBlocks::new(24, ECB::new(1, 32))), Version::new(30, 16, 48, 14, 22, ECBlocks::new(28, ECB::new(1, 49))), // ISO 21471:2020 (DMRE) 5.5.1 Table 7
|
||||
Version::new(31, 8, 48, 6, 22, ECBlocks::new(15, ECB::new(1, 18))), Version::new(32, 8, 64, 6, 14, ECBlocks::new(18, ECB::new(1, 24))), Version::new(33, 8, 80, 6, 18, ECBlocks::new(22, ECB::new(1, 32))), Version::new(34, 8, 96, 6, 22, ECBlocks::new(28, ECB::new(1, 38))), Version::new(35, 8, 120, 6, 18, ECBlocks::new(32, ECB::new(1, 49))), Version::new(36, 8, 144, 6, 22, ECBlocks::new(36, ECB::new(1, 63))), Version::new(37, 12, 64, 10, 14, ECBlocks::new(27, ECB::new(1, 43))), Version::new(38, 12, 88, 10, 20, ECBlocks::new(36, ECB::new(1, 64))), Version::new(39, 16, 64, 14, 14, ECBlocks::new(36, ECB::new(1, 62))), Version::new(40, 20, 36, 18, 16, ECBlocks::new(28, ECB::new(1, 44))), Version::new(41, 20, 44, 18, 20, ECBlocks::new(34, ECB::new(1, 56))), Version::new(42, 20, 64, 18, 14, ECBlocks::new(42, ECB::new(1, 84))), Version::new(43, 22, 48, 20, 22, ECBlocks::new(38, ECB::new(1, 72))), Version::new(44, 24, 48, 22, 22, ECBlocks::new(41, ECB::new(1, 80))), Version::new(45, 24, 64, 22, 14, ECBlocks::new(46, ECB::new(1, 108))), Version::new(46, 26, 40, 24, 18, ECBlocks::new(38, ECB::new(1, 70))), Version::new(47, 26, 48, 24, 22, ECBlocks::new(42, ECB::new(1, 90))), Version::new(48, 26, 64, 24, 14, ECBlocks::new(50, ECB::new(1, 118))), ]
|
||||
return vec![Version::new(1, 10, 10, 8, 8, &ECBlocks::new_simple(5, &ECB::new(1, 3))), Version::new(2, 12, 12, 10, 10, &ECBlocks::new_simple(7, &ECB::new(1, 5))), Version::new(3, 14, 14, 12, 12, &ECBlocks::new_simple(10, &ECB::new(1, 8))), Version::new(4, 16, 16, 14, 14, &ECBlocks::new_simple(12, &ECB::new(1, 12))), Version::new(5, 18, 18, 16, 16,& ECBlocks::new_simple(14, &ECB::new(1, 18))), Version::new(6, 20, 20, 18, 18, &ECBlocks::new_simple(18, &ECB::new(1, 22))), Version::new(7, 22, 22, 20, 20, &ECBlocks::new_simple(20, &ECB::new(1, 30))), Version::new(8, 24, 24, 22, 22,& ECBlocks::new_simple(24, &ECB::new(1, 36))), Version::new(9, 26, 26, 24, 24,& ECBlocks::new_simple(28, &ECB::new(1, 44))), Version::new(10, 32, 32, 14, 14,& ECBlocks::new_simple(36, &ECB::new(1, 62))), Version::new(11, 36, 36, 16, 16, &ECBlocks::new_simple(42,& ECB::new(1, 86))), Version::new(12, 40, 40, 18, 18, &ECBlocks::new_simple(48, &ECB::new(1, 114))), Version::new(13, 44, 44, 20, 20,& ECBlocks::new_simple(56,& ECB::new(1, 144))), Version::new(14, 48, 48, 22, 22,& ECBlocks::new_simple(68,& ECB::new(1, 174))), Version::new(15, 52, 52, 24, 24,& ECBlocks::new_simple(42, &ECB::new(2, 102))), Version::new(16, 64, 64, 14, 14,& ECBlocks::new_simple(56, &ECB::new(2, 140))), Version::new(17, 72, 72, 16, 16, &ECBlocks::new_simple(36, &ECB::new(4, 92))), Version::new(18, 80, 80, 18, 18,& ECBlocks::new_simple(48, &ECB::new(4, 114))), Version::new(19, 88, 88, 20, 20,& ECBlocks::new_simple(56, &ECB::new(4, 144))), Version::new(20, 96, 96, 22, 22, &ECBlocks::new_simple(68, &ECB::new(4, 174))), Version::new(21, 104, 104, 24, 24, &ECBlocks::new_simple(56, &ECB::new(6, 136))), Version::new(22, 120, 120, 18, 18, &ECBlocks::new_simple(68, &ECB::new(6, 175))), Version::new(23, 132, 132, 20, 20, &ECBlocks::new_simple(62, &ECB::new(8, 163))), Version::new(24, 144, 144, 22, 22, &ECBlocks::new(62, &ECB::new(8, 156), &ECB::new(2, 155))), Version::new(25, 8, 18, 6, 16, &ECBlocks::new_simple(7, &ECB::new(1, 5))), Version::new(26, 8, 32, 6, 14,& ECBlocks::new_simple(11, &ECB::new(1, 10))), Version::new(27, 12, 26, 10, 24,& ECBlocks::new_simple(14, &ECB::new(1, 16))), Version::new(28, 12, 36, 10, 16,& ECBlocks::new_simple(18, &ECB::new(1, 22))), Version::new(29, 16, 36, 14, 16, &ECBlocks::new_simple(24,& ECB::new(1, 32))), Version::new(30, 16, 48, 14, 22, &ECBlocks::new_simple(28, &ECB::new(1, 49))), // ISO 21471:2020 (DMRE) 5.5.1 Table 7
|
||||
Version::new(31, 8, 48, 6, 22,& ECBlocks::new_simple(15, &ECB::new(1, 18))), Version::new(32, 8, 64, 6, 14,& ECBlocks::new_simple(18, &ECB::new(1, 24))), Version::new(33, 8, 80, 6, 18, &ECBlocks::new_simple(22, &ECB::new(1, 32))), Version::new(34, 8, 96, 6, 22, &ECBlocks::new_simple(28, &ECB::new(1, 38))), Version::new(35, 8, 120, 6, 18, &ECBlocks::new_simple(32, &ECB::new(1, 49))), Version::new(36, 8, 144, 6, 22, &ECBlocks::new_simple(36, &ECB::new(1, 63))), Version::new(37, 12, 64, 10, 14, &ECBlocks::new_simple(27, &ECB::new(1, 43))), Version::new(38, 12, 88, 10, 20, &ECBlocks::new_simple(36, &ECB::new(1, 64))), Version::new(39, 16, 64, 14, 14,& ECBlocks::new_simple(36, &ECB::new(1, 62))), Version::new(40, 20, 36, 18, 16,& ECBlocks::new_simple(28, &ECB::new(1, 44))), Version::new(41, 20, 44, 18, 20,& ECBlocks::new_simple(34, &ECB::new(1, 56))), Version::new(42, 20, 64, 18, 14,& ECBlocks::new_simple(42,& ECB::new(1, 84))), Version::new(43, 22, 48, 20, 22, &ECBlocks::new_simple(38,& ECB::new(1, 72))), Version::new(44, 24, 48, 22, 22, &ECBlocks::new_simple(41, &ECB::new(1, 80))), Version::new(45, 24, 64, 22, 14, &ECBlocks::new_simple(46, &ECB::new(1, 108))), Version::new(46, 26, 40, 24, 18, &ECBlocks::new_simple(38, &ECB::new(1, 70))), Version::new(47, 26, 48, 24, 22, &ECBlocks::new_simple(42, &ECB::new(1, 90))), Version::new(48, 26, 64, 24, 14, &ECBlocks::new_simple(50, &ECB::new(1, 118))), ]
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will
|
||||
* use blocks of differing sizes within one version, so, this encapsulates the parameters for
|
||||
* each set of blocks. It also holds the number of error-correction codewords per block since it
|
||||
* will be the same across all blocks within one version.</p>
|
||||
*/
|
||||
struct ECBlocks {
|
||||
|
||||
ec_codewords: i32,
|
||||
|
||||
ec_blocks: Vec<ECB>,
|
||||
}
|
||||
|
||||
impl ECBlocks {
|
||||
|
||||
fn new_simple( ec_codewords: i32, ec_blocks: &ECB) -> Self {
|
||||
Self{
|
||||
ec_codewords: ec_codewords,
|
||||
ec_blocks: vec![ec_blocks, ]
|
||||
}
|
||||
}
|
||||
|
||||
fn new( ec_codewords: i32, ec_blocks1: &ECB, ec_blocks2: &ECB) -> ECBlocks {
|
||||
Self{
|
||||
ec_codewords: ec_codewords,
|
||||
ec_blocks: vec![ec_blocks1, ec_blocks2, ]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn get_e_c_codewords(&self) -> i32 {
|
||||
return self.ec_codewords;
|
||||
}
|
||||
|
||||
fn get_e_c_blocks(&self) -> Vec<ECB> {
|
||||
return self.ec_blocks;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Encapsulates the parameters for one error-correction block in one symbol version.
|
||||
* This includes the number of data codewords, and the number of times a block with these
|
||||
* parameters is used consecutively in the Data Matrix code version's format.</p>
|
||||
*/
|
||||
struct ECB {
|
||||
|
||||
count: i32,
|
||||
|
||||
data_codewords: i32
|
||||
}
|
||||
|
||||
impl ECB {
|
||||
|
||||
fn new( count: i32, data_codewords: i32) -> Self {
|
||||
Self {
|
||||
|
||||
count,
|
||||
data_codewords
|
||||
}
|
||||
}
|
||||
|
||||
fn get_count(&self) -> i32 {
|
||||
return self.count;
|
||||
}
|
||||
|
||||
fn get_data_codewords(&self) -> i32 {
|
||||
return self.data_codewords;
|
||||
}
|
||||
}
|
||||
@@ -11,16 +11,19 @@ use crate::common::detector::WhiteRectangleDetector;
|
||||
*/
|
||||
pub struct Detector {
|
||||
|
||||
let image: BitMatrix;
|
||||
image: BitMatrix,
|
||||
|
||||
let rectangle_detector: WhiteRectangleDetector;
|
||||
rectangle_detector: WhiteRectangleDetector
|
||||
}
|
||||
|
||||
impl Detector {
|
||||
|
||||
pub fn new( image: &BitMatrix) -> Detector throws NotFoundException {
|
||||
let .image = image;
|
||||
rectangle_detector = WhiteRectangleDetector::new(image);
|
||||
pub fn new( image: &BitMatrix) -> Result<Self, NotFoundException> {
|
||||
let d : Self;
|
||||
d .image = image;
|
||||
d.rectangle_detector = WhiteRectangleDetector::new(image, None, None, None);
|
||||
|
||||
Ok(d)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,21 +32,21 @@ impl Detector {
|
||||
* @return {@link DetectorResult} encapsulating results of detecting a Data Matrix Code
|
||||
* @throws NotFoundException if no Data Matrix Code can be found
|
||||
*/
|
||||
pub fn detect(&self) -> /* throws NotFoundException */Result<DetectorResult, Rc<Exception>> {
|
||||
pub fn detect(&self) -> Result<DetectorResult, NotFoundException> {
|
||||
let corner_points: Vec<ResultPoint> = self.rectangle_detector.detect();
|
||||
let mut points: Vec<ResultPoint> = self.detect_solid1(corner_points);
|
||||
points = self.detect_solid2(points);
|
||||
points[3] = self.correct_top_right(points);
|
||||
let mut points: Vec<ResultPoint> = self.detect_solid1(&corner_points);
|
||||
points = self.detect_solid2(points?);
|
||||
points[3] = self.correct_top_right(points?);
|
||||
if points[3] == null {
|
||||
throw NotFoundException::get_not_found_instance();
|
||||
return Err( NotFoundException::get_not_found_instance());
|
||||
}
|
||||
points = self.shift_to_module_center(points);
|
||||
points = self.shift_to_module_center(points?);
|
||||
let top_left: ResultPoint = points[0];
|
||||
let bottom_left: ResultPoint = points[1];
|
||||
let bottom_right: ResultPoint = points[2];
|
||||
let top_right: ResultPoint = points[3];
|
||||
let dimension_top: i32 = self.transitions_between(top_left, top_right) + 1;
|
||||
let dimension_right: i32 = self.transitions_between(bottom_right, top_right) + 1;
|
||||
let dimension_top: i32 = self.transitions_between(&top_left, &top_right) + 1;
|
||||
let dimension_right: i32 = self.transitions_between(&bottom_right, &top_right) + 1;
|
||||
if (dimension_top & 0x01) == 1 {
|
||||
dimension_top += 1;
|
||||
}
|
||||
@@ -55,7 +58,7 @@ impl Detector {
|
||||
dimension_top = dimension_right = Math::max(dimension_top, dimension_right);
|
||||
}
|
||||
let bits: BitMatrix = ::sample_grid(self.image, top_left, bottom_left, bottom_right, top_right, dimension_top, dimension_right);
|
||||
return Ok(DetectorResult::new(bits, : vec![ResultPoint; 4] = vec![top_left, bottom_left, bottom_right, top_right, ]
|
||||
return Ok(DetectorResult::new(bits, vec![top_left, bottom_left, bottom_right, top_right, ]
|
||||
));
|
||||
}
|
||||
|
||||
@@ -91,10 +94,10 @@ impl Detector {
|
||||
let point_b: ResultPoint = corner_points[1];
|
||||
let point_c: ResultPoint = corner_points[3];
|
||||
let point_d: ResultPoint = corner_points[2];
|
||||
let tr_a_b: i32 = self.transitions_between(point_a, point_b);
|
||||
let tr_b_c: i32 = self.transitions_between(point_b, point_c);
|
||||
let tr_c_d: i32 = self.transitions_between(point_c, point_d);
|
||||
let tr_d_a: i32 = self.transitions_between(point_d, point_a);
|
||||
let tr_a_b: i32 = self.transitions_between(&point_a, &point_b);
|
||||
let tr_b_c: i32 = self.transitions_between(&point_b, &point_c);
|
||||
let tr_c_d: i32 = self.transitions_between(&point_c, &point_d);
|
||||
let tr_d_a: i32 = self.transitions_between(&point_d, &point_a);
|
||||
// 0..3
|
||||
// : :
|
||||
// 1--2
|
||||
@@ -137,11 +140,11 @@ impl Detector {
|
||||
let point_d: ResultPoint = points[3];
|
||||
// Transition detection on the edge is not stable.
|
||||
// To safely detect, shift the points to the module center.
|
||||
let tr: i32 = self.transitions_between(point_a, point_d);
|
||||
let tr: i32 = self.transitions_between(&point_a, &point_d);
|
||||
let point_bs: ResultPoint = ::shift_point(point_b, point_c, (tr + 1) * 4);
|
||||
let point_cs: ResultPoint = ::shift_point(point_c, point_b, (tr + 1) * 4);
|
||||
let tr_b_a: i32 = self.transitions_between(point_bs, point_a);
|
||||
let tr_c_d: i32 = self.transitions_between(point_cs, point_d);
|
||||
let tr_b_a: i32 = self.transitions_between(&point_bs, &point_a);
|
||||
let tr_c_d: i32 = self.transitions_between(&point_cs, &point_d);
|
||||
// 1--2
|
||||
if tr_b_a < tr_c_d {
|
||||
// solid sides: A-B-C
|
||||
@@ -171,25 +174,25 @@ impl Detector {
|
||||
let point_c: ResultPoint = points[2];
|
||||
let point_d: ResultPoint = points[3];
|
||||
// shift points for safe transition detection.
|
||||
let tr_top: i32 = self.transitions_between(point_a, point_d);
|
||||
let tr_right: i32 = self.transitions_between(point_b, point_d);
|
||||
let tr_top: i32 = self.transitions_between(&point_a, &point_d);
|
||||
let tr_right: i32 = self.transitions_between(&point_b, &point_d);
|
||||
let point_as: ResultPoint = ::shift_point(point_a, point_b, (tr_right + 1) * 4);
|
||||
let point_cs: ResultPoint = ::shift_point(point_c, point_b, (tr_top + 1) * 4);
|
||||
tr_top = self.transitions_between(point_as, point_d);
|
||||
tr_right = self.transitions_between(point_cs, point_d);
|
||||
tr_top = self.transitions_between(&point_as, &point_d);
|
||||
tr_right = self.transitions_between(&point_cs, &point_d);
|
||||
let candidate1: ResultPoint = ResultPoint::new(point_d.get_x() + (point_c.get_x() - point_b.get_x()) / (tr_top + 1), point_d.get_y() + (point_c.get_y() - point_b.get_y()) / (tr_top + 1));
|
||||
let candidate2: ResultPoint = ResultPoint::new(point_d.get_x() + (point_a.get_x() - point_b.get_x()) / (tr_right + 1), point_d.get_y() + (point_a.get_y() - point_b.get_y()) / (tr_right + 1));
|
||||
if !self.is_valid(candidate1) {
|
||||
if self.is_valid(candidate2) {
|
||||
if !self.is_valid(&candidate1) {
|
||||
if self.is_valid(&candidate2) {
|
||||
return candidate2;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if !self.is_valid(candidate2) {
|
||||
if !self.is_valid(&candidate2) {
|
||||
return candidate1;
|
||||
}
|
||||
let sumc1: i32 = self.transitions_between(point_as, candidate1) + self.transitions_between(point_cs, candidate1);
|
||||
let sumc2: i32 = self.transitions_between(point_as, candidate2) + self.transitions_between(point_cs, candidate2);
|
||||
let sumc1: i32 = self.transitions_between(&point_as, &candidate1) + self.transitions_between(&point_cs, &candidate1);
|
||||
let sumc2: i32 = self.transitions_between(&point_as, &candidate2) + self.transitions_between(&point_cs, &candidate2);
|
||||
if sumc1 > sumc2 {
|
||||
return candidate1;
|
||||
} else {
|
||||
@@ -209,14 +212,14 @@ impl Detector {
|
||||
let point_c: ResultPoint = points[2];
|
||||
let point_d: ResultPoint = points[3];
|
||||
// calculate pseudo dimensions
|
||||
let dim_h: i32 = self.transitions_between(point_a, point_d) + 1;
|
||||
let dim_v: i32 = self.transitions_between(point_c, point_d) + 1;
|
||||
let dim_h: i32 = self.transitions_between(&point_a, &point_d) + 1;
|
||||
let dim_v: i32 = self.transitions_between(&point_c, &point_d) + 1;
|
||||
// shift points for safe dimension detection
|
||||
let point_as: ResultPoint = ::shift_point(point_a, point_b, dim_v * 4);
|
||||
let point_cs: ResultPoint = ::shift_point(point_c, point_b, dim_h * 4);
|
||||
// calculate more precise dimensions
|
||||
dim_h = self.transitions_between(point_as, point_d) + 1;
|
||||
dim_v = self.transitions_between(point_cs, point_d) + 1;
|
||||
dim_h = self.transitions_between(&point_as, &point_d) + 1;
|
||||
dim_v = self.transitions_between(&point_cs, &point_d) + 1;
|
||||
if (dim_h & 0x01) == 1 {
|
||||
dim_h += 1;
|
||||
}
|
||||
@@ -242,7 +245,7 @@ impl Detector {
|
||||
point_cs = ::shift_point(point_cs, point_b, dim_h * 4);
|
||||
point_ds = ::shift_point(point_d, point_c, dim_v * 4);
|
||||
point_ds = ::shift_point(point_ds, point_a, dim_h * 4);
|
||||
return : vec![ResultPoint; 4] = vec![point_as, point_bs, point_cs, point_ds, ]
|
||||
return vec![point_as, point_bs, point_cs, point_ds, ]
|
||||
;
|
||||
}
|
||||
|
||||
@@ -252,7 +255,7 @@ impl Detector {
|
||||
|
||||
fn sample_grid( image: &BitMatrix, top_left: &ResultPoint, bottom_left: &ResultPoint, bottom_right: &ResultPoint, top_right: &ResultPoint, dimension_x: i32, dimension_y: i32) -> /* throws NotFoundException */Result<BitMatrix, Rc<Exception>> {
|
||||
let sampler: GridSampler = GridSampler::get_instance();
|
||||
return Ok(sampler.sample_grid(image, dimension_x, dimension_y, 0.5f, 0.5f, dimension_x - 0.5f, 0.5f, dimension_x - 0.5f, dimension_y - 0.5f, 0.5f, dimension_y - 0.5f, &top_left.get_x(), &top_left.get_y(), &top_right.get_x(), &top_right.get_y(), &bottom_right.get_x(), &bottom_right.get_y(), &bottom_left.get_x(), &bottom_left.get_y()));
|
||||
return Ok(sampler.sample_grid(image, dimension_x, dimension_y, 0.5f32, 0.5f32, dimension_x - 0.5f32, 0.5f32, dimension_x - 0.5f32, dimension_y - 0.5f32, 0.5f32, dimension_y - 0.5f32, &top_left.get_x(), &top_left.get_y(), &top_right.get_x(), &top_right.get_y(), &bottom_right.get_x(), &bottom_right.get_y(), &bottom_left.get_x(), &bottom_left.get_y()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,7 +284,8 @@ impl Detector {
|
||||
let mut transitions: i32 = 0;
|
||||
let in_black: bool = self.image.get( if steep { from_y } else { from_x }, if steep { from_x } else { from_y });
|
||||
{
|
||||
let mut x: i32 = from_x, let mut y: i32 = from_y;
|
||||
let mut x: i32 = from_x;
|
||||
let mut y: i32 = from_y;
|
||||
while x != to_x {
|
||||
{
|
||||
let is_black: bool = self.image.get( if steep { y } else { x }, if steep { x } else { y });
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user