From 8b350e0ab3ecee2ceaae434270a641cb7b8b03c9 Mon Sep 17 00:00:00 2001 From: Florian Schrag Date: Wed, 14 Mar 2018 23:57:24 +0100 Subject: [PATCH 1/6] Improve support for Macro PDF417 --- .../zxing/pdf417/PDF417ResultMetadata.java | 107 +++++++++++++++++- .../decoder/DecodedBitStreamParser.java | 82 +++++++++----- .../zxing/pdf417/PDF417BlackBox3TestCase.java | 4 +- .../zxing/pdf417/PDF417BlackBox4TestCase.java | 2 +- .../pdf417/decoder/PDF471DecoderTestCase.java | 98 ++++++++++++++++ .../test/resources/blackbox/pdf417-3/19.png | Bin 0 -> 931 bytes .../test/resources/blackbox/pdf417-3/19.txt | 1 + .../resources/blackbox/pdf417-4/04-01.png | Bin 0 -> 84268 bytes .../test/resources/blackbox/pdf417-4/04.txt | 1 + 9 files changed, 263 insertions(+), 32 deletions(-) create mode 100644 core/src/test/java/com/google/zxing/pdf417/decoder/PDF471DecoderTestCase.java create mode 100644 core/src/test/resources/blackbox/pdf417-3/19.png create mode 100644 core/src/test/resources/blackbox/pdf417-3/19.txt create mode 100644 core/src/test/resources/blackbox/pdf417-4/04-01.png create mode 100644 core/src/test/resources/blackbox/pdf417-4/04.txt diff --git a/core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java b/core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java index 2e1c4ee264..0949db6414 100644 --- a/core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java +++ b/core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java @@ -23,9 +23,19 @@ public final class PDF417ResultMetadata { private int segmentIndex; private String fileId; - private int[] optionalData; private boolean lastSegment; + private int segmentCount = -1; + private String sender; + private String addressee; + private String fileName; + private long fileSize = -1; + private long timestamp = -1; + private int checksum = -1; + /** + * The Segment ID represents the segment of the whole file distributed over different symbols. + * @return File segment index + */ public int getSegmentIndex() { return segmentIndex; } @@ -34,6 +44,10 @@ public void setSegmentIndex(int segmentIndex) { this.segmentIndex = segmentIndex; } + /** + * Is the same for each related PDF417 symbol + * @return File ID + */ public String getFileId() { return fileId; } @@ -42,14 +56,26 @@ public void setFileId(String fileId) { this.fileId = fileId; } + /** + * @deprecated use dedicated already parsed fields + * @return always null + */ + @Deprecated public int[] getOptionalData() { - return optionalData; + return null; } + /** + * @deprecated no replacement + */ + @Deprecated public void setOptionalData(int[] optionalData) { - this.optionalData = optionalData; } + + /** + * @return true if it is the last segment + */ public boolean isLastSegment() { return lastSegment; } @@ -58,4 +84,79 @@ public void setLastSegment(boolean lastSegment) { this.lastSegment = lastSegment; } + /** + * @return count of segments, -1 if not set + */ + public int getSegmentCount() { + return segmentCount; + } + + public void setSegmentCount(int segmentCount) { + this.segmentCount = segmentCount; + } + + public String getSender() { + return sender; + } + + public void setSender(String sender) { + this.sender = sender; + } + + public String getAddressee() { + return addressee; + } + + public void setAddressee(String addressee) { + this.addressee = addressee; + } + + /** + * Filename of the encoded file + * @return filename + */ + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + /** + * filesize in bytes of the encoded file + * @return filesize in bytes, -1 if not set + */ + public long getFileSize() { + return fileSize; + } + + public void setFileSize(long fileSize) { + this.fileSize = fileSize; + } + + /** + * 16-bit CRC checksum using CCITT-16 + * @return crc checksum, -1 if not set + */ + public int getChecksum() { + return checksum; + } + + public void setChecksum(int checksum) { + this.checksum = checksum; + } + + /** + * unix epock timestamp, elapsed seconds since 1970-01-01 + * @return elapsed seconds, -1 if not set + */ + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + } diff --git a/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java b/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java index 94a7b9db53..fa0b6240ff 100644 --- a/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java +++ b/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java @@ -25,7 +25,6 @@ import java.math.BigInteger; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.util.Arrays; /** *

This class contains the methods for decoding the PDF417 codewords.

@@ -57,6 +56,14 @@ private enum Mode { private static final int MODE_SHIFT_TO_BYTE_COMPACTION_MODE = 913; private static final int MAX_NUMERIC_CODEWORDS = 15; + private static final int MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME = 0; + private static final int MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT = 1; + private static final int MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP = 2; + private static final int MACRO_PDF417_OPTIONAL_FIELD_SENDER = 3; + private static final int MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE = 4; + private static final int MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE = 5; + private static final int MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM = 6; + private static final int PL = 25; private static final int LL = 27; private static final int AS = 27; @@ -155,7 +162,7 @@ static DecoderResult decode(int[] codewords, String ecLevel) throws FormatExcept return decoderResult; } - private static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417ResultMetadata resultMetadata) + protected static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417ResultMetadata resultMetadata) throws FormatException { if (codeIndex + NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) { // we must have at least two bytes left for the segment index @@ -172,35 +179,58 @@ private static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417Result codeIndex = textCompaction(codewords, codeIndex, fileId); resultMetadata.setFileId(fileId.toString()); - switch (codewords[codeIndex]) { - case BEGIN_MACRO_PDF417_OPTIONAL_FIELD: - codeIndex++; - int[] additionalOptionCodeWords = new int[codewords[0] - codeIndex]; - int additionalOptionCodeWordsIndex = 0; + while (codeIndex < codewords[0]) { + switch (codewords[codeIndex]) { + case BEGIN_MACRO_PDF417_OPTIONAL_FIELD: + codeIndex++; + switch (codewords[codeIndex]) { + case MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME: + StringBuilder fileName = new StringBuilder(); + codeIndex = textCompaction(codewords, codeIndex + 1, fileName); + resultMetadata.setFileName(fileName.toString()); + break; + case MACRO_PDF417_OPTIONAL_FIELD_SENDER: + StringBuilder sender = new StringBuilder(); + codeIndex = textCompaction(codewords, codeIndex + 1, sender); + resultMetadata.setSender(sender.toString()); + break; + case MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE: + StringBuilder addressee = new StringBuilder(); + codeIndex = textCompaction(codewords, codeIndex + 1, addressee); + resultMetadata.setAddressee(addressee.toString()); + break; + case MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT: + StringBuilder segmentCount = new StringBuilder(); + codeIndex = numericCompaction(codewords, codeIndex + 1, segmentCount); + resultMetadata.setSegmentCount(Integer.parseInt(segmentCount.toString())); + break; + case MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP: + StringBuilder timestamp = new StringBuilder(); + codeIndex = numericCompaction(codewords, codeIndex + 1, timestamp); + resultMetadata.setTimestamp(Long.parseLong(timestamp.toString())); + break; + case MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM: + StringBuilder checksum = new StringBuilder(); + codeIndex = numericCompaction(codewords, codeIndex + 1, checksum); + resultMetadata.setChecksum(Integer.parseInt(checksum.toString())); + break; + case MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE: + StringBuilder fileSize = new StringBuilder(); + codeIndex = numericCompaction(codewords, codeIndex + 1, fileSize); + resultMetadata.setFileSize(Long.parseLong(fileSize.toString())); + break; + default: + throw FormatException.getFormatInstance(); + } - boolean end = false; - while ((codeIndex < codewords[0]) && !end) { - int code = codewords[codeIndex++]; - if (code < TEXT_COMPACTION_MODE_LATCH) { - additionalOptionCodeWords[additionalOptionCodeWordsIndex++] = code; - } else { - switch (code) { - case MACRO_PDF417_TERMINATOR: - resultMetadata.setLastSegment(true); + break; + case MACRO_PDF417_TERMINATOR: codeIndex++; - end = true; + resultMetadata.setLastSegment(true); break; - default: + default: throw FormatException.getFormatInstance(); - } - } } - resultMetadata.setOptionalData(Arrays.copyOf(additionalOptionCodeWords, additionalOptionCodeWordsIndex)); - break; - case MACRO_PDF417_TERMINATOR: - resultMetadata.setLastSegment(true); - codeIndex++; - break; } return codeIndex; diff --git a/core/src/test/java/com/google/zxing/pdf417/PDF417BlackBox3TestCase.java b/core/src/test/java/com/google/zxing/pdf417/PDF417BlackBox3TestCase.java index 9c1b928a80..cd565029e7 100644 --- a/core/src/test/java/com/google/zxing/pdf417/PDF417BlackBox3TestCase.java +++ b/core/src/test/java/com/google/zxing/pdf417/PDF417BlackBox3TestCase.java @@ -24,8 +24,8 @@ public final class PDF417BlackBox3TestCase extends AbstractBlackBoxTestCase { public PDF417BlackBox3TestCase() { super("src/test/resources/blackbox/pdf417-3", new MultiFormatReader(), BarcodeFormat.PDF_417); - addTest(18, 18, 0, 0, 0.0f); - addTest(18, 18, 0, 0, 180.0f); + addTest(19, 19, 0, 0, 0.0f); + addTest(19, 19, 0, 0, 180.0f); } } diff --git a/core/src/test/java/com/google/zxing/pdf417/PDF417BlackBox4TestCase.java b/core/src/test/java/com/google/zxing/pdf417/PDF417BlackBox4TestCase.java index d15d3d1ba2..d27a22e461 100644 --- a/core/src/test/java/com/google/zxing/pdf417/PDF417BlackBox4TestCase.java +++ b/core/src/test/java/com/google/zxing/pdf417/PDF417BlackBox4TestCase.java @@ -64,7 +64,7 @@ public final class PDF417BlackBox4TestCase extends AbstractBlackBoxTestCase { public PDF417BlackBox4TestCase() { super("src/test/resources/blackbox/pdf417-4", null, BarcodeFormat.PDF_417); - testResults.add(new TestResult(2, 2, 0, 0, 0.0f)); + testResults.add(new TestResult(3, 3, 0, 0, 0.0f)); } @Test diff --git a/core/src/test/java/com/google/zxing/pdf417/decoder/PDF471DecoderTestCase.java b/core/src/test/java/com/google/zxing/pdf417/decoder/PDF471DecoderTestCase.java new file mode 100644 index 0000000000..95f6c3fd51 --- /dev/null +++ b/core/src/test/java/com/google/zxing/pdf417/decoder/PDF471DecoderTestCase.java @@ -0,0 +1,98 @@ +package com.google.zxing.pdf417.decoder; + +import com.google.zxing.FormatException; +import com.google.zxing.pdf417.PDF417ResultMetadata; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; +/* + * 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. + */ + +import static org.junit.Assert.*; + +public class PDF471DecoderTestCase { + + /** + * Tests the first sample given in ISO/IEC 15438:2015(E) - Annex H.4 + */ + @Test + public void testStandardSample1() throws FormatException { + PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); + + int[] sampleCodes = {20, 928, 111, 100, 17, 53, 923, 1, 111, 104, 923, 3, 64, 416, 34, 923, 4, 258, 446, 67, + // we should never reach these + 1000, 1000, 1000}; + DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata); + assertEquals(0, resultMetadata.getSegmentIndex()); + assertEquals("ARBX", resultMetadata.getFileId()); + assertFalse(resultMetadata.isLastSegment()); + assertEquals(4, resultMetadata.getSegmentCount()); + assertEquals("CEN BE", resultMetadata.getSender()); + assertEquals("ISO CH", resultMetadata.getAddressee()); + } + + + /** + * Tests the second given in ISO/IEC 15438:2015(E) - Annex H.4 + */ + @Test + public void testStandardSample2() throws FormatException { + PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); + + int[] sampleCodes = {11, 928, 111, 103, 17, 53, 923, 1, 111, 104, 922, + // we should never reach these + 1000, 1000, 1000}; + DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata); + assertEquals(3, resultMetadata.getSegmentIndex()); + assertEquals("ARBX", resultMetadata.getFileId()); + assertTrue(resultMetadata.isLastSegment()); + assertEquals(4, resultMetadata.getSegmentCount()); + assertNull(resultMetadata.getAddressee()); + assertNull(resultMetadata.getSender()); + } + + @Test + public void testSampleWithFilename() throws FormatException { + int[] sampleCodes = {23, 477, 928, 111, 100, 0, 252, 21, 86, 923, 0, 815, 251, 133, 12, 148, 537, 593, 599, 923, 1, 111, 102, 98, 311, 355, 522, 920, 779, 40, 628, 33, 749, 267, 506, 213, 928, 465, 248, 493, 72, 780, 699, 780, 493, 755, 84, 198, 628, 368, 156, 198, 809, 19, 113}; + PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); + DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 3, resultMetadata); + assertEquals(0, resultMetadata.getSegmentIndex()); + assertEquals("AAIMAVC ", resultMetadata.getFileId()); + assertFalse(resultMetadata.isLastSegment()); + assertEquals(2, resultMetadata.getSegmentCount()); + assertNull(resultMetadata.getAddressee()); + assertNull(resultMetadata.getSender()); + assertEquals("filename.txt", resultMetadata.getFileName()); + } + + @Test + public void testSampleWithNumericValues() throws FormatException { + + int[] sampleCodes = {25, 477, 928, 111, 100, 0, 252, 21, 86, 923, 2, 2, 0, 1, 0, 0, 0, 923, 5, 130, 923, 6, 1, 500, 13, 0}; + PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); + DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 3, resultMetadata); + + assertEquals(0, resultMetadata.getSegmentIndex()); + assertEquals("AAIMAVC ", resultMetadata.getFileId()); + assertFalse(resultMetadata.isLastSegment()); + + assertEquals(180980729000000L, resultMetadata.getTimestamp()); + assertEquals(30, resultMetadata.getFileSize()); + assertEquals(260013, resultMetadata.getChecksum()); + + } + +} \ No newline at end of file diff --git a/core/src/test/resources/blackbox/pdf417-3/19.png b/core/src/test/resources/blackbox/pdf417-3/19.png new file mode 100644 index 0000000000000000000000000000000000000000..fcf4b65823ddc241031b27f7a9c8ebae34204643 GIT binary patch literal 931 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 Date: Thu, 15 Mar 2018 00:17:17 +0100 Subject: [PATCH 2/6] cleanup and move license to it's proper place --- .../pdf417/decoder/PDF471DecoderTestCase.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/core/src/test/java/com/google/zxing/pdf417/decoder/PDF471DecoderTestCase.java b/core/src/test/java/com/google/zxing/pdf417/decoder/PDF471DecoderTestCase.java index 95f6c3fd51..54536ba58e 100644 --- a/core/src/test/java/com/google/zxing/pdf417/decoder/PDF471DecoderTestCase.java +++ b/core/src/test/java/com/google/zxing/pdf417/decoder/PDF471DecoderTestCase.java @@ -1,10 +1,3 @@ -package com.google.zxing.pdf417.decoder; - -import com.google.zxing.FormatException; -import com.google.zxing.pdf417.PDF417ResultMetadata; -import org.junit.Test; - -import java.nio.charset.StandardCharsets; /* * Copyright 2009 ZXing authors * @@ -21,6 +14,12 @@ * limitations under the License. */ +package com.google.zxing.pdf417.decoder; + +import com.google.zxing.FormatException; +import com.google.zxing.pdf417.PDF417ResultMetadata; +import org.junit.Test; + import static org.junit.Assert.*; public class PDF471DecoderTestCase { @@ -31,11 +30,12 @@ public class PDF471DecoderTestCase { @Test public void testStandardSample1() throws FormatException { PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); - int[] sampleCodes = {20, 928, 111, 100, 17, 53, 923, 1, 111, 104, 923, 3, 64, 416, 34, 923, 4, 258, 446, 67, // we should never reach these 1000, 1000, 1000}; + DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata); + assertEquals(0, resultMetadata.getSegmentIndex()); assertEquals("ARBX", resultMetadata.getFileId()); assertFalse(resultMetadata.isLastSegment()); @@ -51,11 +51,12 @@ public void testStandardSample1() throws FormatException { @Test public void testStandardSample2() throws FormatException { PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); - int[] sampleCodes = {11, 928, 111, 103, 17, 53, 923, 1, 111, 104, 922, // we should never reach these 1000, 1000, 1000}; + DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata); + assertEquals(3, resultMetadata.getSegmentIndex()); assertEquals("ARBX", resultMetadata.getFileId()); assertTrue(resultMetadata.isLastSegment()); @@ -68,7 +69,9 @@ public void testStandardSample2() throws FormatException { public void testSampleWithFilename() throws FormatException { int[] sampleCodes = {23, 477, 928, 111, 100, 0, 252, 21, 86, 923, 0, 815, 251, 133, 12, 148, 537, 593, 599, 923, 1, 111, 102, 98, 311, 355, 522, 920, 779, 40, 628, 33, 749, 267, 506, 213, 928, 465, 248, 493, 72, 780, 699, 780, 493, 755, 84, 198, 628, 368, 156, 198, 809, 19, 113}; PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); + DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 3, resultMetadata); + assertEquals(0, resultMetadata.getSegmentIndex()); assertEquals("AAIMAVC ", resultMetadata.getFileId()); assertFalse(resultMetadata.isLastSegment()); @@ -80,9 +83,9 @@ public void testSampleWithFilename() throws FormatException { @Test public void testSampleWithNumericValues() throws FormatException { - int[] sampleCodes = {25, 477, 928, 111, 100, 0, 252, 21, 86, 923, 2, 2, 0, 1, 0, 0, 0, 923, 5, 130, 923, 6, 1, 500, 13, 0}; PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); + DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 3, resultMetadata); assertEquals(0, resultMetadata.getSegmentIndex()); From 6f04279864397ef69b99fbefd861b3fd112729c7 Mon Sep 17 00:00:00 2001 From: Florian Schrag Date: Thu, 15 Mar 2018 14:37:34 +0100 Subject: [PATCH 3/6] add .editorconfig + proper indentation / add optionalFields array --- .editorconfig | 9 + .../zxing/pdf417/PDF417ResultMetadata.java | 24 ++- .../decoder/DecodedBitStreamParser.java | 129 ++++++++------ .../pdf417/decoder/PDF471DecoderTestCase.java | 159 +++++++++--------- 4 files changed, 182 insertions(+), 139 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..c6c8b36219 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java b/core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java index 0949db6414..9c51959ba2 100644 --- a/core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java +++ b/core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java @@ -31,9 +31,11 @@ public final class PDF417ResultMetadata { private long fileSize = -1; private long timestamp = -1; private int checksum = -1; + private int[] optionalData; /** * The Segment ID represents the segment of the whole file distributed over different symbols. + * * @return File segment index */ public int getSegmentIndex() { @@ -46,6 +48,7 @@ public void setSegmentIndex(int segmentIndex) { /** * Is the same for each related PDF417 symbol + * * @return File ID */ public String getFileId() { @@ -57,19 +60,20 @@ public void setFileId(String fileId) { } /** - * @deprecated use dedicated already parsed fields * @return always null + * @deprecated use dedicated already parsed fields */ @Deprecated public int[] getOptionalData() { - return null; + return optionalData; } /** - * @deprecated no replacement + * @deprecated parse and use new fields */ @Deprecated public void setOptionalData(int[] optionalData) { + this.optionalData = optionalData; } @@ -113,6 +117,7 @@ public void setAddressee(String addressee) { /** * Filename of the encoded file + * * @return filename */ public String getFileName() { @@ -125,6 +130,7 @@ public void setFileName(String fileName) { /** * filesize in bytes of the encoded file + * * @return filesize in bytes, -1 if not set */ public long getFileSize() { @@ -135,10 +141,11 @@ public void setFileSize(long fileSize) { this.fileSize = fileSize; } - /** - * 16-bit CRC checksum using CCITT-16 - * @return crc checksum, -1 if not set - */ + /** + * 16-bit CRC checksum using CCITT-16 + * + * @return crc checksum, -1 if not set + */ public int getChecksum() { return checksum; } @@ -149,10 +156,11 @@ public void setChecksum(int checksum) { /** * unix epock timestamp, elapsed seconds since 1970-01-01 + * * @return elapsed seconds, -1 if not set */ public long getTimestamp() { - return timestamp; + return timestamp; } public void setTimestamp(long timestamp) { diff --git a/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java b/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java index fa0b6240ff..2fe69cf1ac 100644 --- a/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java +++ b/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java @@ -73,16 +73,17 @@ private enum Mode { private static final int PAL = 29; private static final char[] PUNCT_CHARS = - ";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'".toCharArray(); + ";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'".toCharArray(); private static final char[] MIXED_CHARS = - "0123456789&\r\t,:#-.$/+%*=^".toCharArray(); + "0123456789&\r\t,:#-.$/+%*=^".toCharArray(); /** * Table containing values for the exponent of 900. * This is used in the numeric compaction decode algorithm. */ private static final BigInteger[] EXP900; + static { EXP900 = new BigInteger[16]; EXP900[0] = BigInteger.ONE; @@ -122,7 +123,7 @@ static DecoderResult decode(int[] codewords, String ecLevel) throws FormatExcept break; case ECI_CHARSET: CharacterSetECI charsetECI = - CharacterSetECI.getCharacterSetECIByValue(codewords[codeIndex++]); + CharacterSetECI.getCharacterSetECIByValue(codewords[codeIndex++]); encoding = Charset.forName(charsetECI.name()); break; case ECI_GENERAL_PURPOSE: @@ -131,7 +132,7 @@ static DecoderResult decode(int[] codewords, String ecLevel) throws FormatExcept break; case ECI_USER_DEFINED: // Can't do anything with user ECI; skip its 1 character - codeIndex ++; + codeIndex++; break; case BEGIN_MACRO_PDF417_CONTROL_BLOCK: codeIndex = decodeMacroBlock(codewords, codeIndex, resultMetadata); @@ -163,7 +164,7 @@ static DecoderResult decode(int[] codewords, String ecLevel) throws FormatExcept } protected static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417ResultMetadata resultMetadata) - throws FormatException { + throws FormatException { if (codeIndex + NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) { // we must have at least two bytes left for the segment index throw FormatException.getFormatInstance(); @@ -173,64 +174,80 @@ protected static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417Resu segmentIndexArray[i] = codewords[codeIndex]; } resultMetadata.setSegmentIndex(Integer.parseInt(decodeBase900toBase10(segmentIndexArray, - NUMBER_OF_SEQUENCE_CODEWORDS))); + NUMBER_OF_SEQUENCE_CODEWORDS))); StringBuilder fileId = new StringBuilder(); codeIndex = textCompaction(codewords, codeIndex, fileId); resultMetadata.setFileId(fileId.toString()); - while (codeIndex < codewords[0]) { - switch (codewords[codeIndex]) { - case BEGIN_MACRO_PDF417_OPTIONAL_FIELD: - codeIndex++; - switch (codewords[codeIndex]) { - case MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME: - StringBuilder fileName = new StringBuilder(); - codeIndex = textCompaction(codewords, codeIndex + 1, fileName); - resultMetadata.setFileName(fileName.toString()); - break; - case MACRO_PDF417_OPTIONAL_FIELD_SENDER: - StringBuilder sender = new StringBuilder(); - codeIndex = textCompaction(codewords, codeIndex + 1, sender); - resultMetadata.setSender(sender.toString()); - break; - case MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE: - StringBuilder addressee = new StringBuilder(); - codeIndex = textCompaction(codewords, codeIndex + 1, addressee); - resultMetadata.setAddressee(addressee.toString()); - break; - case MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT: - StringBuilder segmentCount = new StringBuilder(); - codeIndex = numericCompaction(codewords, codeIndex + 1, segmentCount); - resultMetadata.setSegmentCount(Integer.parseInt(segmentCount.toString())); - break; - case MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP: - StringBuilder timestamp = new StringBuilder(); - codeIndex = numericCompaction(codewords, codeIndex + 1, timestamp); - resultMetadata.setTimestamp(Long.parseLong(timestamp.toString())); - break; - case MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM: - StringBuilder checksum = new StringBuilder(); - codeIndex = numericCompaction(codewords, codeIndex + 1, checksum); - resultMetadata.setChecksum(Integer.parseInt(checksum.toString())); - break; - case MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE: - StringBuilder fileSize = new StringBuilder(); - codeIndex = numericCompaction(codewords, codeIndex + 1, fileSize); - resultMetadata.setFileSize(Long.parseLong(fileSize.toString())); - break; - default: - throw FormatException.getFormatInstance(); - } + int optionalFieldsStart = -1; + if (codewords[codeIndex] == BEGIN_MACRO_PDF417_OPTIONAL_FIELD) { + optionalFieldsStart = codeIndex + 1; + } - break; - case MACRO_PDF417_TERMINATOR: - codeIndex++; - resultMetadata.setLastSegment(true); - break; + while (codeIndex < codewords[0]) { + switch (codewords[codeIndex]) { + case BEGIN_MACRO_PDF417_OPTIONAL_FIELD: + codeIndex++; + switch (codewords[codeIndex]) { + case MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME: + StringBuilder fileName = new StringBuilder(); + codeIndex = textCompaction(codewords, codeIndex + 1, fileName); + resultMetadata.setFileName(fileName.toString()); + break; + case MACRO_PDF417_OPTIONAL_FIELD_SENDER: + StringBuilder sender = new StringBuilder(); + codeIndex = textCompaction(codewords, codeIndex + 1, sender); + resultMetadata.setSender(sender.toString()); + break; + case MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE: + StringBuilder addressee = new StringBuilder(); + codeIndex = textCompaction(codewords, codeIndex + 1, addressee); + resultMetadata.setAddressee(addressee.toString()); + break; + case MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT: + StringBuilder segmentCount = new StringBuilder(); + codeIndex = numericCompaction(codewords, codeIndex + 1, segmentCount); + resultMetadata.setSegmentCount(Integer.parseInt(segmentCount.toString())); + break; + case MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP: + StringBuilder timestamp = new StringBuilder(); + codeIndex = numericCompaction(codewords, codeIndex + 1, timestamp); + resultMetadata.setTimestamp(Long.parseLong(timestamp.toString())); + break; + case MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM: + StringBuilder checksum = new StringBuilder(); + codeIndex = numericCompaction(codewords, codeIndex + 1, checksum); + resultMetadata.setChecksum(Integer.parseInt(checksum.toString())); + break; + case MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE: + StringBuilder fileSize = new StringBuilder(); + codeIndex = numericCompaction(codewords, codeIndex + 1, fileSize); + resultMetadata.setFileSize(Long.parseLong(fileSize.toString())); + break; default: - throw FormatException.getFormatInstance(); - } + throw FormatException.getFormatInstance(); + } + break; + case MACRO_PDF417_TERMINATOR: + codeIndex++; + resultMetadata.setLastSegment(true); + break; + default: + throw FormatException.getFormatInstance(); + } + } + + // copy optional fields to additional options + if (optionalFieldsStart != -1) { + int additionalFieldsLength = codeIndex - optionalFieldsStart; + if (resultMetadata.isLastSegment()) { + // do not include terminator + additionalFieldsLength--; + } + int[] additionalOptionCodeWords = new int[additionalFieldsLength]; + System.arraycopy(codewords, optionalFieldsStart, additionalOptionCodeWords, 0, additionalFieldsLength); + resultMetadata.setOptionalData(additionalOptionCodeWords); } return codeIndex; diff --git a/core/src/test/java/com/google/zxing/pdf417/decoder/PDF471DecoderTestCase.java b/core/src/test/java/com/google/zxing/pdf417/decoder/PDF471DecoderTestCase.java index 54536ba58e..0d66a4028b 100644 --- a/core/src/test/java/com/google/zxing/pdf417/decoder/PDF471DecoderTestCase.java +++ b/core/src/test/java/com/google/zxing/pdf417/decoder/PDF471DecoderTestCase.java @@ -24,78 +24,87 @@ public class PDF471DecoderTestCase { - /** - * Tests the first sample given in ISO/IEC 15438:2015(E) - Annex H.4 - */ - @Test - public void testStandardSample1() throws FormatException { - PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); - int[] sampleCodes = {20, 928, 111, 100, 17, 53, 923, 1, 111, 104, 923, 3, 64, 416, 34, 923, 4, 258, 446, 67, - // we should never reach these - 1000, 1000, 1000}; - - DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata); - - assertEquals(0, resultMetadata.getSegmentIndex()); - assertEquals("ARBX", resultMetadata.getFileId()); - assertFalse(resultMetadata.isLastSegment()); - assertEquals(4, resultMetadata.getSegmentCount()); - assertEquals("CEN BE", resultMetadata.getSender()); - assertEquals("ISO CH", resultMetadata.getAddressee()); - } - - - /** - * Tests the second given in ISO/IEC 15438:2015(E) - Annex H.4 - */ - @Test - public void testStandardSample2() throws FormatException { - PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); - int[] sampleCodes = {11, 928, 111, 103, 17, 53, 923, 1, 111, 104, 922, - // we should never reach these - 1000, 1000, 1000}; - - DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata); - - assertEquals(3, resultMetadata.getSegmentIndex()); - assertEquals("ARBX", resultMetadata.getFileId()); - assertTrue(resultMetadata.isLastSegment()); - assertEquals(4, resultMetadata.getSegmentCount()); - assertNull(resultMetadata.getAddressee()); - assertNull(resultMetadata.getSender()); - } - - @Test - public void testSampleWithFilename() throws FormatException { - int[] sampleCodes = {23, 477, 928, 111, 100, 0, 252, 21, 86, 923, 0, 815, 251, 133, 12, 148, 537, 593, 599, 923, 1, 111, 102, 98, 311, 355, 522, 920, 779, 40, 628, 33, 749, 267, 506, 213, 928, 465, 248, 493, 72, 780, 699, 780, 493, 755, 84, 198, 628, 368, 156, 198, 809, 19, 113}; - PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); - - DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 3, resultMetadata); - - assertEquals(0, resultMetadata.getSegmentIndex()); - assertEquals("AAIMAVC ", resultMetadata.getFileId()); - assertFalse(resultMetadata.isLastSegment()); - assertEquals(2, resultMetadata.getSegmentCount()); - assertNull(resultMetadata.getAddressee()); - assertNull(resultMetadata.getSender()); - assertEquals("filename.txt", resultMetadata.getFileName()); - } - - @Test - public void testSampleWithNumericValues() throws FormatException { - int[] sampleCodes = {25, 477, 928, 111, 100, 0, 252, 21, 86, 923, 2, 2, 0, 1, 0, 0, 0, 923, 5, 130, 923, 6, 1, 500, 13, 0}; - PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); - - DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 3, resultMetadata); - - assertEquals(0, resultMetadata.getSegmentIndex()); - assertEquals("AAIMAVC ", resultMetadata.getFileId()); - assertFalse(resultMetadata.isLastSegment()); - - assertEquals(180980729000000L, resultMetadata.getTimestamp()); - assertEquals(30, resultMetadata.getFileSize()); - assertEquals(260013, resultMetadata.getChecksum()); - - } - -} \ No newline at end of file + /** + * Tests the first sample given in ISO/IEC 15438:2015(E) - Annex H.4 + */ + @Test + public void testStandardSample1() throws FormatException { + PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); + int[] sampleCodes = {20, 928, 111, 100, 17, 53, 923, 1, 111, 104, 923, 3, 64, 416, 34, 923, 4, 258, 446, 67, + // we should never reach these + 1000, 1000, 1000}; + + DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata); + + assertEquals(0, resultMetadata.getSegmentIndex()); + assertEquals("ARBX", resultMetadata.getFileId()); + assertFalse(resultMetadata.isLastSegment()); + assertEquals(4, resultMetadata.getSegmentCount()); + assertEquals("CEN BE", resultMetadata.getSender()); + assertEquals("ISO CH", resultMetadata.getAddressee()); + + int[] optionalData = resultMetadata.getOptionalData(); + assertEquals("first element of optional array should be the first field identifier", 1, optionalData[0]); + assertEquals("last element of optional array should be the last codeword of the last field", 67, optionalData[optionalData.length - 1]); + } + + + /** + * Tests the second given in ISO/IEC 15438:2015(E) - Annex H.4 + */ + @Test + public void testStandardSample2() throws FormatException { + PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); + int[] sampleCodes = {11, 928, 111, 103, 17, 53, 923, 1, 111, 104, 922, + // we should never reach these + 1000, 1000, 1000}; + + DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata); + + assertEquals(3, resultMetadata.getSegmentIndex()); + assertEquals("ARBX", resultMetadata.getFileId()); + assertTrue(resultMetadata.isLastSegment()); + assertEquals(4, resultMetadata.getSegmentCount()); + assertNull(resultMetadata.getAddressee()); + assertNull(resultMetadata.getSender()); + + + int[] optionalData = resultMetadata.getOptionalData(); + assertEquals("first element of optional array should be the first field identifier", 1, optionalData[0]); + assertEquals("last element of optional array should be the last codeword of the last field", 104, optionalData[optionalData.length - 1]); + } + + @Test + public void testSampleWithFilename() throws FormatException { + int[] sampleCodes = {23, 477, 928, 111, 100, 0, 252, 21, 86, 923, 0, 815, 251, 133, 12, 148, 537, 593, 599, 923, 1, 111, 102, 98, 311, 355, 522, 920, 779, 40, 628, 33, 749, 267, 506, 213, 928, 465, 248, 493, 72, 780, 699, 780, 493, 755, 84, 198, 628, 368, 156, 198, 809, 19, 113}; + PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); + + DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 3, resultMetadata); + + assertEquals(0, resultMetadata.getSegmentIndex()); + assertEquals("AAIMAVC ", resultMetadata.getFileId()); + assertFalse(resultMetadata.isLastSegment()); + assertEquals(2, resultMetadata.getSegmentCount()); + assertNull(resultMetadata.getAddressee()); + assertNull(resultMetadata.getSender()); + assertEquals("filename.txt", resultMetadata.getFileName()); + } + + @Test + public void testSampleWithNumericValues() throws FormatException { + int[] sampleCodes = {25, 477, 928, 111, 100, 0, 252, 21, 86, 923, 2, 2, 0, 1, 0, 0, 0, 923, 5, 130, 923, 6, 1, 500, 13, 0}; + PDF417ResultMetadata resultMetadata = new PDF417ResultMetadata(); + + DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 3, resultMetadata); + + assertEquals(0, resultMetadata.getSegmentIndex()); + assertEquals("AAIMAVC ", resultMetadata.getFileId()); + assertFalse(resultMetadata.isLastSegment()); + + assertEquals(180980729000000L, resultMetadata.getTimestamp()); + assertEquals(30, resultMetadata.getFileSize()); + assertEquals(260013, resultMetadata.getChecksum()); + + } + +} From ef6c00d8e83fedf1ac1566fdac3fd5485453119d Mon Sep 17 00:00:00 2001 From: Florian Schrag Date: Thu, 15 Mar 2018 14:57:26 +0100 Subject: [PATCH 4/6] rename variables and use Arrays instead of System --- .../zxing/pdf417/decoder/DecodedBitStreamParser.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java b/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java index 2fe69cf1ac..0b7f287253 100644 --- a/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java +++ b/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java @@ -25,6 +25,7 @@ import java.math.BigInteger; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Arrays; /** *

This class contains the methods for decoding the PDF417 codewords.

@@ -240,14 +241,12 @@ protected static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417Resu // copy optional fields to additional options if (optionalFieldsStart != -1) { - int additionalFieldsLength = codeIndex - optionalFieldsStart; + int optionalFieldsLength = codeIndex - optionalFieldsStart; if (resultMetadata.isLastSegment()) { // do not include terminator - additionalFieldsLength--; + optionalFieldsLength--; } - int[] additionalOptionCodeWords = new int[additionalFieldsLength]; - System.arraycopy(codewords, optionalFieldsStart, additionalOptionCodeWords, 0, additionalFieldsLength); - resultMetadata.setOptionalData(additionalOptionCodeWords); + resultMetadata.setOptionalData(Arrays.copyOfRange(codewords, optionalFieldsStart, optionalFieldsLength)); } return codeIndex; From d6e1319000285c8d8b09d3cca0a375d2ad0fca35 Mon Sep 17 00:00:00 2001 From: Florian Schrag Date: Thu, 15 Mar 2018 15:27:51 +0100 Subject: [PATCH 5/6] replaced length with to --- .../com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java b/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java index 0b7f287253..382be179a7 100644 --- a/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java +++ b/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java @@ -246,7 +246,7 @@ protected static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417Resu // do not include terminator optionalFieldsLength--; } - resultMetadata.setOptionalData(Arrays.copyOfRange(codewords, optionalFieldsStart, optionalFieldsLength)); + resultMetadata.setOptionalData(Arrays.copyOfRange(codewords, optionalFieldsStart, optionalFieldsStart + optionalFieldsLength)); } return codeIndex; From 929f5317c589d7220b141f86258408662e996001 Mon Sep 17 00:00:00 2001 From: Florian Schrag Date: Thu, 15 Mar 2018 19:41:40 +0100 Subject: [PATCH 6/6] restore spaces & switch to package private --- .../zxing/pdf417/decoder/DecodedBitStreamParser.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java b/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java index 382be179a7..d4dc585b35 100644 --- a/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java +++ b/core/src/main/java/com/google/zxing/pdf417/decoder/DecodedBitStreamParser.java @@ -74,10 +74,10 @@ private enum Mode { private static final int PAL = 29; private static final char[] PUNCT_CHARS = - ";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'".toCharArray(); + ";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'".toCharArray(); private static final char[] MIXED_CHARS = - "0123456789&\r\t,:#-.$/+%*=^".toCharArray(); + "0123456789&\r\t,:#-.$/+%*=^".toCharArray(); /** * Table containing values for the exponent of 900. @@ -124,7 +124,7 @@ static DecoderResult decode(int[] codewords, String ecLevel) throws FormatExcept break; case ECI_CHARSET: CharacterSetECI charsetECI = - CharacterSetECI.getCharacterSetECIByValue(codewords[codeIndex++]); + CharacterSetECI.getCharacterSetECIByValue(codewords[codeIndex++]); encoding = Charset.forName(charsetECI.name()); break; case ECI_GENERAL_PURPOSE: @@ -164,8 +164,8 @@ static DecoderResult decode(int[] codewords, String ecLevel) throws FormatExcept return decoderResult; } - protected static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417ResultMetadata resultMetadata) - throws FormatException { + static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417ResultMetadata resultMetadata) + throws FormatException { if (codeIndex + NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) { // we must have at least two bytes left for the segment index throw FormatException.getFormatInstance(); @@ -175,7 +175,7 @@ protected static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417Resu segmentIndexArray[i] = codewords[codeIndex]; } resultMetadata.setSegmentIndex(Integer.parseInt(decodeBase900toBase10(segmentIndexArray, - NUMBER_OF_SEQUENCE_CODEWORDS))); + NUMBER_OF_SEQUENCE_CODEWORDS))); StringBuilder fileId = new StringBuilder(); codeIndex = textCompaction(codewords, codeIndex, fileId);