Skip to content

Commit

Permalink
Merge pull request #15 from zxing/master
Browse files Browse the repository at this point in the history
Improve support for Macro PDF417 (zxing#973)
  • Loading branch information
shixingxing committed Mar 20, 2018
2 parents 56fa375 + dbfd552 commit bd1dcb2
Show file tree
Hide file tree
Showing 10 changed files with 309 additions and 33 deletions.
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -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
111 changes: 110 additions & 1 deletion core/src/main/java/com/google/zxing/pdf417/PDF417ResultMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,21 @@ 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;
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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,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;
Expand All @@ -76,6 +84,7 @@ private enum Mode {
* This is used in the numeric compaction decode algorithm.
*/
private static final BigInteger[] EXP900;

static {
EXP900 = new BigInteger[16];
EXP900[0] = BigInteger.ONE;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit bd1dcb2

Please sign in to comment.