Permalink
Browse files

Improve support for Macro PDF417 (#973)

* Improve support for Macro PDF417

* cleanup and move license to it's proper place

* add .editorconfig + proper indentation / add optionalFields array

* rename variables and use Arrays instead of System

* replaced length with to

* restore spaces & switch to package private
  • Loading branch information...
gitu authored and srowen committed Mar 15, 2018
1 parent a3bbebc commit dbfd5520e9b53de492cc4ff8f8c55a440f0d6b5d
View
@@ -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
@@ -23,9 +23,21 @@
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;
private int[] optionalData;
/**
* 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 +46,11 @@ 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 +59,27 @@ public void setFileId(String fileId) {
this.fileId = fileId;
}
/**
* @return always null
* @deprecated use dedicated already parsed fields
*/
@Deprecated
public int[] getOptionalData() {
return optionalData;
}
/**
* @deprecated parse and use new fields
*/
@Deprecated
public void setOptionalData(int[] optionalData) {
this.optionalData = optionalData;
}
/**
* @return true if it is the last segment
*/
public boolean isLastSegment() {
return lastSegment;
}
@@ -58,4 +88,83 @@ 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;
}
}
@@ -57,6 +57,14 @@
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;
@@ -76,6 +84,7 @@
* This is used in the numeric compaction decode algorithm.
*/
private static final BigInteger[] EXP900;
static {
EXP900 = new BigInteger[16];
EXP900[0] = BigInteger.ONE;
@@ -124,7 +133,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);
@@ -155,7 +164,7 @@ static DecoderResult decode(int[] codewords, String ecLevel) throws FormatExcept
return decoderResult;
}
private static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417ResultMetadata resultMetadata)
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 +181,72 @@ 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;
int optionalFieldsStart = -1;
if (codewords[codeIndex] == BEGIN_MACRO_PDF417_OPTIONAL_FIELD) {
optionalFieldsStart = codeIndex + 1;
}
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);
codeIndex++;
end = true;
break;
default:
throw FormatException.getFormatInstance();
}
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();
}
}
resultMetadata.setOptionalData(Arrays.copyOf(additionalOptionCodeWords, additionalOptionCodeWordsIndex));
break;
case MACRO_PDF417_TERMINATOR:
resultMetadata.setLastSegment(true);
codeIndex++;
break;
break;
case MACRO_PDF417_TERMINATOR:
codeIndex++;
resultMetadata.setLastSegment(true);
break;
default:
throw FormatException.getFormatInstance();
}
}
// copy optional fields to additional options
if (optionalFieldsStart != -1) {
int optionalFieldsLength = codeIndex - optionalFieldsStart;
if (resultMetadata.isLastSegment()) {
// do not include terminator
optionalFieldsLength--;
}
resultMetadata.setOptionalData(Arrays.copyOfRange(codewords, optionalFieldsStart, optionalFieldsStart + optionalFieldsLength));
}
return codeIndex;
@@ -24,8 +24,8 @@
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);
}
}
@@ -64,7 +64,7 @@
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
Oops, something went wrong.

0 comments on commit dbfd552

Please sign in to comment.