PDF417 compact from Joseph Lau

git-svn-id: https://zxing.googlecode.com/svn/trunk@1911 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2011-09-16 20:44:28 +00:00
parent ea218233b9
commit a335ff5fb7
3 changed files with 159 additions and 62 deletions

View file

@ -506,16 +506,30 @@ final class PDF417 {
0x107a4, 0x107a2, 0x10396, 0x107b6, 0x187d4, 0x187d2,
0x10794, 0x10fb4, 0x10792, 0x10fb2, 0x1c7ea}};
private static final int MIN_COLS = 2;
private static final int MAX_COLS = 30;
private static final int MAX_ROWS = 30;
private static final int MIN_ROWS = 2;
private static final float DEFAULT_MODULE_WIDTH = 0.357f; //1px in mm
private static final float HEIGHT = 16.0f; //mm
private static final float HEIGHT = 2.0f; //mm
private int errorCorrectionLevel;
private BarcodeMatrix barcodeMatrix;
private boolean compact;
private boolean byteCompaction;
private int minCols;
private int maxCols;
private int maxRows;
private int minRows;
public PDF417() {
this(false);
}
public PDF417(boolean compact) {
this.compact = compact;
minCols = 2;
maxCols = 30;
maxRows = 30;
minRows = 2;
}
BarcodeMatrix getBarcodeMatrix() {
return barcodeMatrix;
}
@ -548,7 +562,7 @@ final class PDF417 {
}
return r;
}
/**
* Calculates the necessary number of rows as described in annex Q of ISO/IEC 15438:2001(E).
*
@ -650,10 +664,14 @@ final class PDF417 {
idx++;
}
pattern = CODEWORD_TABLE[cluster][right];
encodeChar(pattern, 17, logic.getCurrentRow());
encodeChar(STOP_PATTERN, 18, logic.getCurrentRow());
if (compact) {
encodeChar(STOP_PATTERN, 1, logic.getCurrentRow()); // encodes stop line for compact pdf417
} else {
pattern = CODEWORD_TABLE[cluster][right];
encodeChar(pattern, 17, logic.getCurrentRow());
encodeChar(STOP_PATTERN, 18, logic.getCurrentRow());
}
}
}
@ -666,7 +684,7 @@ final class PDF417 {
//1. step: High-level encoding
int errorCorrectionCodeWords = PDF417ErrorCorrection.getErrorCorrectionCodewordCount(errorCorrectionLevel);
String highLevel = PDF417HighLevelEncoder.encodeHighLevel(msg);
String highLevel = PDF417HighLevelEncoder.encodeHighLevel(msg, byteCompaction);
int sourceCodeWords = highLevel.length();
int[] dimension = determineDimensions(sourceCodeWords);
@ -717,15 +735,15 @@ final class PDF417 {
int[] dimension = null;
int errorCorrectionCodeWords = PDF417ErrorCorrection.getErrorCorrectionCodewordCount(errorCorrectionLevel);
for (int cols = MIN_COLS; cols <= MAX_COLS; cols++) {
for (int cols = minCols; cols <= maxCols; cols++) {
int rows = calculateNumberOfRows(sourceCodeWords, errorCorrectionCodeWords, cols);
if (rows < MIN_ROWS) {
if (rows < minRows) {
break;
}
if (rows > MAX_ROWS) {
if (rows > maxRows) {
continue;
}
@ -743,6 +761,32 @@ final class PDF417 {
return dimension;
}
/**
* Sets max/min row/col values
*/
void setDimensions(int maxCols, int minCols, int maxRows, int minRows) {
this.maxCols = maxCols;
this.minCols = minCols;
this.maxRows = maxRows;
this.minRows = minRows;
}
/**
* Sets byte compaction to be true or false
* @param byteCompaction
*/
void setByteCompaction(boolean byteCompaction) {
this.byteCompaction = byteCompaction;
}
/**
* Sets compact to be true or false
* @param compact
*/
void setCompact(boolean compact) {
this.compact = compact;
}
}

View file

@ -143,12 +143,13 @@ final class PDF417HighLevelEncoder {
/**
* Performs high-level encoding of a PDF417 message using the algorithm described in annex P
* of ISO/IEC 15438:2001(E).
* of ISO/IEC 15438:2001(E). If byte compaction has been selected, then only byte compaction
* is used.
*
* @param msg the message
* @return the encoded message (the char values range from 0 to 928)
*/
static String encodeHighLevel(String msg) throws WriterException {
static String encodeHighLevel(String msg, boolean byteCompaction) throws WriterException {
byte[] bytes = null; //Fill later and only if needed
//the codewords 0..928 are encoded as Unicode characters
@ -158,42 +159,67 @@ final class PDF417HighLevelEncoder {
int p = 0;
int encodingMode = TEXT_COMPACTION; //Default mode, see 4.4.2.1
int textSubMode = SUBMODE_ALPHA;
while (p < len) {
int n = determineConsecutiveDigitCount(msg, p);
if (n >= 13) {
sb.append((char) LATCH_TO_NUMERIC);
encodingMode = NUMERIC_COMPACTION;
textSubMode = SUBMODE_ALPHA; //Reset after latch
encodeNumeric(msg, p, n, sb);
p += n;
} else {
int t = determineConsecutiveTextCount(msg, p);
if (t >= 5 || n == len) {
if (encodingMode != TEXT_COMPACTION) {
sb.append((char) LATCH_TO_TEXT);
encodingMode = TEXT_COMPACTION;
textSubMode = SUBMODE_ALPHA; //start with submode alpha after latch
}
textSubMode = encodeText(msg, p, t, sb, textSubMode);
p += t;
if (byteCompaction) { // Can choose only byte compaction
encodingMode = BYTE_COMPACTION;
while (p < len) {
if (bytes == null) {
bytes = getBytesForMessage(msg);
}
int b = determineConsecutiveBinaryCount(msg, bytes, p);
if (b == 0) {
b = 1;
}
if (b == 1 && encodingMode == TEXT_COMPACTION) {
//Switch for one byte (instead of latch)
encodeBinary(bytes, p, 1, TEXT_COMPACTION, sb);
} else {
if (bytes == null) {
bytes = getBytesForMessage(msg);
}
int b = determineConsecutiveBinaryCount(msg, bytes, p);
if (b == 0) {
b = 1;
}
if (b == 1 && encodingMode == TEXT_COMPACTION) {
//Switch for one byte (instead of latch)
encodeBinary(bytes, p, 1, TEXT_COMPACTION, sb);
//Mode latch performed by encodeBinary()
encodeBinary(bytes, p, b, encodingMode, sb);
encodingMode = BYTE_COMPACTION;
textSubMode = SUBMODE_ALPHA; //Reset after latch
}
p += b;
}
} else {
while (p < len) {
int n = determineConsecutiveDigitCount(msg, p);
if (n >= 13) {
sb.append((char) LATCH_TO_NUMERIC);
encodingMode = NUMERIC_COMPACTION;
textSubMode = SUBMODE_ALPHA; //Reset after latch
encodeNumeric(msg, p, n, sb);
p += n;
} else {
int t = determineConsecutiveTextCount(msg, p);
if (t >= 5 || n == len) {
if (encodingMode != TEXT_COMPACTION) {
sb.append((char) LATCH_TO_TEXT);
encodingMode = TEXT_COMPACTION;
textSubMode = SUBMODE_ALPHA; //start with submode alpha after latch
}
textSubMode = encodeText(msg, p, t, sb, textSubMode);
p += t;
} else {
//Mode latch performed by encodeBinary()
encodeBinary(bytes, p, b, encodingMode, sb);
encodingMode = BYTE_COMPACTION;
textSubMode = SUBMODE_ALPHA; //Reset after latch
if (bytes == null) {
bytes = getBytesForMessage(msg);
}
int b = determineConsecutiveBinaryCount(msg, bytes, p);
if (b == 0) {
b = 1;
}
if (b == 1 && encodingMode == TEXT_COMPACTION) {
//Switch for one byte (instead of latch)
encodeBinary(bytes, p, 1, TEXT_COMPACTION, sb);
} else {
//Mode latch performed by encodeBinary()
encodeBinary(bytes, p, b, encodingMode, sb);
encodingMode = BYTE_COMPACTION;
textSubMode = SUBMODE_ALPHA; //Reset after latch
}
p += b;
}
p += b;
}
}
}

View file

@ -34,25 +34,52 @@ public final class PDF417Writer implements Writer {
}
public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) throws WriterException {
PDF417 encoder = initializeEncoder(format, false);
return bitMatrixFromEncoder(encoder, contents, width, height);
}
public BitMatrix encode(String contents,
BarcodeFormat format,
boolean compact,
int width,
int height,
int minCols,
int maxCols,
int minRows,
int maxRows,
boolean byteCompaction) throws WriterException {
PDF417 encoder = initializeEncoder(format, compact);
// Set options: dimensions and byte compaction
encoder.setDimensions(maxCols, minCols, maxRows, minRows);
encoder.setByteCompaction(byteCompaction);
return bitMatrixFromEncoder(encoder, contents, width, height);
}
/**
* Initializes the encoder based on the format (whether it's compact or not)
*/
private PDF417 initializeEncoder(BarcodeFormat format, boolean compact) {
if (format != BarcodeFormat.PDF_417) {
throw new IllegalArgumentException("Can only encode PDF_417, but got " + format);
}
PDF417 encoder = new PDF417();
encoder.setCompact(compact);
return encoder;
}
//No error correction at the moment
int errorCorrectionLevel = 3;
/**
* Takes encoder, accounts for width/height, and retrieves bit matrix
*/
private BitMatrix bitMatrixFromEncoder(PDF417 encoder, String contents, int width, int height)
throws WriterException {
int errorCorrectionLevel = 2;
encoder.generateBarcodeLogic(contents, errorCorrectionLevel);
// Give it data to be encoded
//encoderExt.setData(content.getBytes());
// Find the Error correction level automatically
//encoderExt.encode();
//encoderExt.createArray();
int lineThickness = 3;
int aspectRatio = 8;
int lineThickness = 2;
int aspectRatio = 4;
byte[][] originalScale = encoder.getBarcodeMatrix().getScaledMatrix(lineThickness, aspectRatio * lineThickness);
boolean rotated = false;
if ((height > width) ^ (originalScale[0].length < originalScale.length)) {
@ -80,7 +107,7 @@ public final class PDF417Writer implements Writer {
}
return bitMatrixFrombitArray(originalScale);
}
/**
* This takes an array holding the values of the PDF 417
*