From 09f25bfacc94984b2973ec230e0862843f069648 Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Thu, 29 Dec 2022 17:33:45 -0600 Subject: [PATCH] fixed datamatrix detection (incorrect) in ean13 2 --- src/PlanarYUVLuminanceSourceTestCase.java | 83 ------------------- src/RGBLuminanceSourceTestCase.java | 63 -------------- src/common/reedsolomon/reedsolomon_decoder.rs | 4 +- src/datamatrix/encoder/encoder_context.rs | 11 ++- .../encoder/high_level_encode_test_case.rs | 83 ++++++++++++------- src/datamatrix/encoder/high_level_encoder.rs | 70 ++++++++++++---- src/datamatrix/encoder/symbol_info.rs | 1 + ...intInvertedDataMatrixBlackBoxTestCase.java | 0 8 files changed, 120 insertions(+), 195 deletions(-) delete mode 100644 src/PlanarYUVLuminanceSourceTestCase.java delete mode 100644 src/RGBLuminanceSourceTestCase.java rename tests/{ => negative}/NoHintInvertedDataMatrixBlackBoxTestCase.java (100%) diff --git a/src/PlanarYUVLuminanceSourceTestCase.java b/src/PlanarYUVLuminanceSourceTestCase.java deleted file mode 100644 index 4d5912a..0000000 --- a/src/PlanarYUVLuminanceSourceTestCase.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2014 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; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Tests {@link PlanarYUVLuminanceSource}. - */ -public final class PlanarYUVLuminanceSourceTestCase extends Assert { - - private static final byte[] YUV = { - 0, 1, 1, 2, 3, 5, - 8, 13, 21, 34, 55, 89, - 0, -1, -1, -2, -3, -5, - -8, -13, -21, -34, -55, -89, - 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, - }; - private static final int COLS = 6; - private static final int ROWS = 4; - private static final byte[] Y = new byte[COLS * ROWS]; - static { - System.arraycopy(YUV, 0, Y, 0, Y.length); - } - - @Test - public void testNoCrop() { - PlanarYUVLuminanceSource source = - new PlanarYUVLuminanceSource(YUV, COLS, ROWS, 0, 0, COLS, ROWS, false); - assertEquals(Y, 0, source.getMatrix(), 0, Y.length); - for (int r = 0; r < ROWS; r++) { - assertEquals(Y, r * COLS, source.getRow(r, null), 0, COLS); - } - } - - @Test - public void testCrop() { - PlanarYUVLuminanceSource source = - new PlanarYUVLuminanceSource(YUV, COLS, ROWS, 1, 1, COLS - 2, ROWS - 2, false); - assertTrue(source.isCropSupported()); - byte[] cropMatrix = source.getMatrix(); - for (int r = 0; r < ROWS - 2; r++) { - assertEquals(Y, (r + 1) * COLS + 1, cropMatrix, r * (COLS - 2), COLS - 2); - } - for (int r = 0; r < ROWS - 2; r++) { - assertEquals(Y, (r + 1) * COLS + 1, source.getRow(r, null), 0, COLS - 2); - } - } - - @Test - public void testThumbnail() { - PlanarYUVLuminanceSource source = - new PlanarYUVLuminanceSource(YUV, COLS, ROWS, 0, 0, COLS, ROWS, false); - assertArrayEquals( - new int[] { 0xFF000000, 0xFF010101, 0xFF030303, 0xFF000000, 0xFFFFFFFF, 0xFFFDFDFD }, - source.renderThumbnail()); - } - - private static void assertEquals(byte[] expected, int expectedFrom, - byte[] actual, int actualFrom, - int length) { - for (int i = 0; i < length; i++) { - assertEquals(expected[expectedFrom + i], actual[actualFrom + i]); - } - } - -} diff --git a/src/RGBLuminanceSourceTestCase.java b/src/RGBLuminanceSourceTestCase.java deleted file mode 100644 index 97f9794..0000000 --- a/src/RGBLuminanceSourceTestCase.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2014 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; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Tests {@link RGBLuminanceSource}. - */ -public final class RGBLuminanceSourceTestCase extends Assert { - - private static final RGBLuminanceSource SOURCE = new RGBLuminanceSource(3, 3, new int[] { - 0x000000, 0x7F7F7F, 0xFFFFFF, - 0xFF0000, 0x00FF00, 0x0000FF, - 0x0000FF, 0x00FF00, 0xFF0000}); - - @Test - public void testCrop() { - assertTrue(SOURCE.isCropSupported()); - LuminanceSource cropped = SOURCE.crop(1, 1, 1, 1); - assertEquals(1, cropped.getHeight()); - assertEquals(1, cropped.getWidth()); - assertArrayEquals(new byte[] { 0x7F }, cropped.getRow(0, null)); - } - - @Test - public void testMatrix() { - assertArrayEquals(new byte[] { 0x00, 0x7F, (byte) 0xFF, 0x3F, 0x7F, 0x3F, 0x3F, 0x7F, 0x3F }, - SOURCE.getMatrix()); - LuminanceSource croppedFullWidth = SOURCE.crop(0, 1, 3, 2); - assertArrayEquals(new byte[] { 0x3F, 0x7F, 0x3F, 0x3F, 0x7F, 0x3F }, - croppedFullWidth.getMatrix()); - LuminanceSource croppedCorner = SOURCE.crop(1, 1, 2, 2); - assertArrayEquals(new byte[] { 0x7F, 0x3F, 0x7F, 0x3F }, - croppedCorner.getMatrix()); - } - - @Test - public void testGetRow() { - assertArrayEquals(new byte[] { 0x3F, 0x7F, 0x3F }, SOURCE.getRow(2, new byte[3])); - } - - @Test - public void testToString() { - assertEquals("#+ \n#+#\n#+#\n", SOURCE.toString()); - } - -} diff --git a/src/common/reedsolomon/reedsolomon_decoder.rs b/src/common/reedsolomon/reedsolomon_decoder.rs index 3ec1cae..690c591 100644 --- a/src/common/reedsolomon/reedsolomon_decoder.rs +++ b/src/common/reedsolomon/reedsolomon_decoder.rs @@ -97,7 +97,9 @@ impl ReedSolomonDecoder { //for (int i = 0; i < errorLocations.length; i++) { let log_value = self.field.log(errorLocations[i] as i32)?; if log_value > received.len() as i32 - 1 { - return Ok(0); + return Err(Exceptions::ReedSolomonException( + "Bad error location".to_owned(), + )); } let position: isize = received.len() as isize - 1 - log_value as isize; if position < 0 { diff --git a/src/datamatrix/encoder/encoder_context.rs b/src/datamatrix/encoder/encoder_context.rs index b24b1ff..f4ae76b 100644 --- a/src/datamatrix/encoder/encoder_context.rs +++ b/src/datamatrix/encoder/encoder_context.rs @@ -37,7 +37,16 @@ pub struct EncoderContext<'a> { skipAtEnd: u32, } -impl EncoderContext<'_> { +impl<'a> EncoderContext<'_> { + pub fn with_symbol_info_lookup( + msg: &str, + symbol_lookup: Rc>, + ) -> Result, Exceptions> { + let mut new_self = EncoderContext::new(msg)?; + new_self.symbol_lookup = symbol_lookup.clone(); + Ok(new_self) + } + pub fn new(msg: &str) -> Result { //From this point on Strings are not Unicode anymore! // let msgBinary = ISO_8859_1_ENCODER.encode(msg, encoding::EncoderTrap::Strict).expect("encode to bytes");//msg.getBytes(StandardCharsets.ISO_8859_1); diff --git a/src/datamatrix/encoder/high_level_encode_test_case.rs b/src/datamatrix/encoder/high_level_encode_test_case.rs index 96383d6..7f7c172 100644 --- a/src/datamatrix/encoder/high_level_encode_test_case.rs +++ b/src/datamatrix/encoder/high_level_encode_test_case.rs @@ -14,6 +14,8 @@ * limitations under the License. */ +use std::rc::Rc; + use lazy_static::lazy_static; use crate::datamatrix::encoder::{SymbolInfo, SymbolShapeHint}; @@ -38,15 +40,17 @@ lazy_static! { // const SIL: SymbolInfoLookup = SymbolInfoLookup::new(); -// fn useTestSymbols(lookup: SymbolInfoLookup) -> SymbolInfoLookup { -// lookup.overrideSymbolSet(&TEST_SYMBOLS); -// lookup -// } +fn useTestSymbols(lookup: SymbolInfoLookup) -> SymbolInfoLookup { + let mut lookup = lookup; + lookup.overrideSymbolSet(&TEST_SYMBOLS); + lookup +} -// fn resetSymbols(lookup: SymbolInfoLookup) -> SymbolInfoLookup { -// lookup.overrideSymbolSet(&symbol_info::PROD_SYMBOLS); -// lookup -// } +fn resetSymbols(lookup: SymbolInfoLookup) -> SymbolInfoLookup { + let mut lookup = lookup; + lookup.overrideSymbolSet(&symbol_info::PROD_SYMBOLS); + lookup +} #[test] fn testASCIIEncodation() { @@ -110,34 +114,37 @@ fn testC40EncodationSpecExample() { #[test] fn testC40EncodationSpecialCases1() { - unimplemented!(); - // //Special tests avoiding ultra-long test strings because these tests are only used - // //with the 16x48 symbol (47 data codewords) - // useTestSymbols(); + //Special tests avoiding ultra-long test strings because these tests are only used + //with the 16x48 symbol (47 data codewords) + let substitute_symbols = SymbolInfoLookup::new(); + let substitute_symbols = useTestSymbols(substitute_symbols); - // let visualized = encodeHighLevelCompare("AIMAIMAIMAIMAIMAIM", false); - // assert_eq!("230 91 11 91 11 91 11 91 11 91 11 91 11", visualized); - // //case "a": Unlatch is not required + let sil = Rc::new(substitute_symbols.clone()); - // visualized = encodeHighLevelCompare("AIMAIMAIMAIMAIMAI", false); - // assert_eq!("230 91 11 91 11 91 11 91 11 91 11 90 241", visualized); - // //case "b": Add trailing shift 0 and Unlatch is not required + let visualized = encodeHighLevelCompareSIL("AIMAIMAIMAIMAIMAIM", false, Some(sil.clone())); + assert_eq!("230 91 11 91 11 91 11 91 11 91 11 91 11", visualized); + //case "a": Unlatch is not required - // visualized = encodeHighLevel("AIMAIMAIMAIMAIMA"); - // assert_eq!("230 91 11 91 11 91 11 91 11 91 11 254 66", visualized); - // //case "c": Unlatch and write last character in ASCII + let visualized = encodeHighLevelCompareSIL("AIMAIMAIMAIMAIMAI", false, Some(sil.clone())); + assert_eq!("230 91 11 91 11 91 11 91 11 91 11 90 241", visualized); + //case "b": Add trailing shift 0 and Unlatch is not required - // resetSymbols(); + let visualized = encodeHighLevelSIL("AIMAIMAIMAIMAIMA", sil.clone()); + assert_eq!("230 91 11 91 11 91 11 91 11 91 11 254 66", visualized); + //case "c": Unlatch and write last character in ASCII - // visualized = encodeHighLevel("AIMAIMAIMAIMAIMAI"); - // assert_eq!( - // "230 91 11 91 11 91 11 91 11 91 11 254 66 74 129 237", - // visualized - // ); + let substitute_symbols = resetSymbols(substitute_symbols); + let sil = Rc::new(substitute_symbols); - // visualized = encodeHighLevel("AIMAIMAIMA"); - // assert_eq!("230 91 11 91 11 91 11 66", visualized); - // //case "d": Skip Unlatch and write last character in ASCII + let visualized = encodeHighLevelSIL("AIMAIMAIMAIMAIMAI", sil.clone()); + assert_eq!( + "230 91 11 91 11 91 11 91 11 91 11 254 66 74 129 237", + visualized + ); + + let visualized = encodeHighLevelSIL("AIMAIMAIMA", sil); + assert_eq!("230 91 11 91 11 91 11 66", visualized); + //case "d": Skip Unlatch and write last character in ASCII } #[test] @@ -556,8 +563,16 @@ fn encodeHighLevel(msg: &str) -> String { encodeHighLevelCompare(msg, true) } -fn encodeHighLevelCompare(msg: &str, compareSizeToMinimalEncoder: bool) -> String { - let encoded = high_level_encoder::encodeHighLevel(msg).expect("encodes"); +fn encodeHighLevelSIL(msg: &str, sil: Rc) -> String { + encodeHighLevelCompareSIL(msg, true, Some(sil)) +} + +fn encodeHighLevelCompareSIL( + msg: &str, + compareSizeToMinimalEncoder: bool, + sil: Option>, +) -> String { + let encoded = high_level_encoder::encodeHighLevelSIL(msg, sil).expect("encodes"); let encoded2 = minimal_encoder::encodeHighLevel(msg).expect("encodes"); assert!( !compareSizeToMinimalEncoder || encoded2.chars().count() <= encoded.chars().count(), @@ -568,6 +583,10 @@ fn encodeHighLevelCompare(msg: &str, compareSizeToMinimalEncoder: bool) -> Strin visualize(&encoded) } +fn encodeHighLevelCompare(msg: &str, compareSizeToMinimalEncoder: bool) -> String { + encodeHighLevelCompareSIL(msg, compareSizeToMinimalEncoder, None) +} + /** * Convert a string of char codewords into a different string which lists each character * using its decimal value. diff --git a/src/datamatrix/encoder/high_level_encoder.rs b/src/datamatrix/encoder/high_level_encoder.rs index 503268e..635ceb4 100644 --- a/src/datamatrix/encoder/high_level_encoder.rs +++ b/src/datamatrix/encoder/high_level_encoder.rs @@ -22,7 +22,7 @@ use crate::{Dimension, Exceptions}; use super::{ ASCIIEncoder, Base256Encoder, C40Encoder, EdifactEncoder, Encoder, EncoderContext, - SymbolShapeHint, TextEncoder, X12Encoder, + SymbolInfoLookup, SymbolShapeHint, TextEncoder, X12Encoder, }; const DEFAULT_ENCODING: EncodingRef = encoding::all::ISO_8859_1; @@ -136,6 +136,27 @@ pub fn encodeHighLevel(msg: &str) -> Result { encodeHighLevelWithDimensionForceC40(msg, SymbolShapeHint::FORCE_NONE, None, None, false) } +/** + * Performs message encoding of a DataMatrix message using the algorithm described in annex P + * of ISO/IEC 16022:2000(E). + * + * @param msg the message + * @return the encoded message (the char values range from 0 to 255) + */ +pub fn encodeHighLevelSIL( + msg: &str, + symbol_lookup: Option>, +) -> Result { + encodeHighLevelWithDimensionForceC40WithSymbolInfoLookup( + msg, + SymbolShapeHint::FORCE_NONE, + None, + None, + false, + symbol_lookup, + ) +} + /** * Performs message encoding of a DataMatrix message using the algorithm described in annex P * of ISO/IEC 16022:2000(E). @@ -155,24 +176,14 @@ pub fn encodeHighLevelWithDimension( ) -> Result { encodeHighLevelWithDimensionForceC40(msg, shape, minSize, maxSize, false) } -/** - * Performs message encoding of a DataMatrix message using the algorithm described in annex P - * of ISO/IEC 16022:2000(E). - * - * @param msg the message - * @param shape requested shape. May be {@code SymbolShapeHint.FORCE_NONE}, - * {@code SymbolShapeHint.FORCE_SQUARE} or {@code SymbolShapeHint.FORCE_RECTANGLE}. - * @param minSize the minimum symbol size constraint or null for no constraint - * @param maxSize the maximum symbol size constraint or null for no constraint - * @param forceC40 enforce C40 encoding - * @return the encoded message (the char values range from 0 to 255) - */ -pub fn encodeHighLevelWithDimensionForceC40( + +pub fn encodeHighLevelWithDimensionForceC40WithSymbolInfoLookup( msg: &str, shape: SymbolShapeHint, minSize: Option, maxSize: Option, forceC40: bool, + symbol_lookup: Option>, ) -> Result { //the codewords 0..255 are encoded as Unicode characters let c40Encoder = Rc::new(C40Encoder::new()); @@ -185,7 +196,12 @@ pub fn encodeHighLevelWithDimensionForceC40( Rc::new(Base256Encoder::new()), ]; - let mut context = EncoderContext::new(msg)?; + let mut context = if let Some(symbol_table) = symbol_lookup { + EncoderContext::with_symbol_info_lookup(msg, symbol_table)? + } else { + EncoderContext::new(msg)? + }; + // let mut context = EncoderContext::new(msg)?; context.setSymbolShape(shape); context.setSizeConstraints(minSize, maxSize); @@ -241,6 +257,30 @@ pub fn encodeHighLevelWithDimensionForceC40( Ok(context.getCodewords().to_owned()) } +/** + * Performs message encoding of a DataMatrix message using the algorithm described in annex P + * of ISO/IEC 16022:2000(E). + * + * @param msg the message + * @param shape requested shape. May be {@code SymbolShapeHint.FORCE_NONE}, + * {@code SymbolShapeHint.FORCE_SQUARE} or {@code SymbolShapeHint.FORCE_RECTANGLE}. + * @param minSize the minimum symbol size constraint or null for no constraint + * @param maxSize the maximum symbol size constraint or null for no constraint + * @param forceC40 enforce C40 encoding + * @return the encoded message (the char values range from 0 to 255) + */ +pub fn encodeHighLevelWithDimensionForceC40( + msg: &str, + shape: SymbolShapeHint, + minSize: Option, + maxSize: Option, + forceC40: bool, +) -> Result { + encodeHighLevelWithDimensionForceC40WithSymbolInfoLookup( + msg, shape, minSize, maxSize, forceC40, None, + ) +} + pub fn lookAheadTest(msg: &str, startpos: u32, currentMode: u32) -> usize { let newMode = lookAheadTestIntern(msg, startpos, currentMode); if currentMode as usize == X12_ENCODATION && newMode as usize == X12_ENCODATION { diff --git a/src/datamatrix/encoder/symbol_info.rs b/src/datamatrix/encoder/symbol_info.rs index 8afbbc7..1271a8c 100644 --- a/src/datamatrix/encoder/symbol_info.rs +++ b/src/datamatrix/encoder/symbol_info.rs @@ -255,6 +255,7 @@ impl fmt::Display for SymbolInfo { } } +#[derive(Clone, Copy)] pub struct SymbolInfoLookup<'a>(Option<&'a Vec>); impl<'a> SymbolInfoLookup<'a> { pub const fn new() -> Self { diff --git a/tests/NoHintInvertedDataMatrixBlackBoxTestCase.java b/tests/negative/NoHintInvertedDataMatrixBlackBoxTestCase.java similarity index 100% rename from tests/NoHintInvertedDataMatrixBlackBoxTestCase.java rename to tests/negative/NoHintInvertedDataMatrixBlackBoxTestCase.java