Issue 1026 PDF417 encoding improvements

git-svn-id: https://zxing.googlecode.com/svn/trunk@2006 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2011-11-02 13:57:49 +00:00
parent d148e9ff9d
commit 5d47b0f8d0
4 changed files with 83 additions and 64 deletions

View file

@ -0,0 +1,26 @@
/*
* Copyright 2011 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.pdf417.encoder;
public enum Compaction {
AUTO,
TEXT,
BYTE,
NUMERIC
}

View file

@ -510,10 +510,9 @@ final class PDF417 {
private static final float DEFAULT_MODULE_WIDTH = 0.357f; //1px in mm
private static final float HEIGHT = 2.0f; //mm
private int errorCorrectionLevel;
private BarcodeMatrix barcodeMatrix;
private boolean compact;
private boolean byteCompaction;
private Compaction compaction;
private int minCols;
private int maxCols;
private int maxRows;
@ -525,6 +524,7 @@ final class PDF417 {
PDF417(boolean compact) {
this.compact = compact;
compaction = Compaction.AUTO;
minCols = 2;
maxCols = 30;
maxRows = 30;
@ -639,8 +639,6 @@ final class PDF417 {
int errorCorrectionLevel,
BarcodeMatrix logic) {
this.errorCorrectionLevel = errorCorrectionLevel;
int idx = 0;
for (int y = 0; y < r; y++) {
int cluster = y % 3;
@ -689,10 +687,10 @@ final class PDF417 {
//1. step: High-level encoding
int errorCorrectionCodeWords = PDF417ErrorCorrection.getErrorCorrectionCodewordCount(errorCorrectionLevel);
String highLevel = PDF417HighLevelEncoder.encodeHighLevel(msg, byteCompaction);
String highLevel = PDF417HighLevelEncoder.encodeHighLevel(msg, compaction);
int sourceCodeWords = highLevel.length();
int[] dimension = determineDimensions(sourceCodeWords);
int[] dimension = determineDimensions(sourceCodeWords, errorCorrectionCodeWords);
int cols = dimension[0];
int rows = dimension[1];
@ -700,12 +698,11 @@ final class PDF417 {
int pad = getNumberOfPadCodewords(sourceCodeWords, errorCorrectionCodeWords, cols, rows);
//2. step: construct data codewords
int n = getNumberOfDataCodewords(sourceCodeWords, errorCorrectionLevel, cols);
if (n > 929) {
if (sourceCodeWords + errorCorrectionCodeWords + 1 > 929) { // +1 for symbol length CW
throw new WriterException(
"Encoded message contains to many code words, message to big (" + msg.length() + " bytes)");
}
int n = sourceCodeWords + pad + 1;
StringBuilder sb = new StringBuilder(n);
sb.append((char) n);
sb.append(highLevel);
@ -728,13 +725,12 @@ final class PDF417 {
* codewords.
*
* @param sourceCodeWords number of code words
* @param errorCorrectionCodeWords number of error correction code words
* @return dimension object containing cols as width and rows as height
*/
int[] determineDimensions(int sourceCodeWords) throws WriterException {
int[] determineDimensions(int sourceCodeWords, int errorCorrectionCodeWords) throws WriterException {
float ratio = 0.0f;
int[] dimension = null;
int errorCorrectionCodeWords = PDF417ErrorCorrection.getErrorCorrectionCodewordCount(errorCorrectionLevel);
for (int cols = minCols; cols <= maxCols; cols++) {
@ -759,9 +755,18 @@ final class PDF417 {
dimension = new int[] {cols, rows};
}
// Handle case when min values were larger than necessary
if (dimension == null) {
int rows = calculateNumberOfRows(sourceCodeWords, errorCorrectionCodeWords, minCols);
if (rows < minRows) {
dimension = new int[]{minCols, minRows};
}
}
if (dimension == null) {
throw new WriterException("Unable to fit message in columns");
}
return dimension;
}
@ -776,11 +781,10 @@ final class PDF417 {
}
/**
* Sets byte compaction to be true or false
* @param byteCompaction
* Sets compaction to values stored in {@link Compaction} enum
*/
void setByteCompaction(boolean byteCompaction) {
this.byteCompaction = byteCompaction;
void setCompaction(Compaction compaction) {
this.compaction = compaction;
}
/**

View file

@ -148,7 +148,7 @@ final class PDF417HighLevelEncoder {
* @param msg the message
* @return the encoded message (the char values range from 0 to 928)
*/
static String encodeHighLevel(String msg, boolean byteCompaction) throws WriterException {
static String encodeHighLevel(String msg, Compaction compaction) throws WriterException {
byte[] bytes = null; //Fill later and only if needed
//the codewords 0..928 are encoded as Unicode characters
@ -159,31 +159,20 @@ final class PDF417HighLevelEncoder {
int encodingMode = TEXT_COMPACTION; //Default mode, see 4.4.2.1
int textSubMode = SUBMODE_ALPHA;
if (byteCompaction) { // Can choose only byte compaction
encodingMode = BYTE_COMPACTION;
while (p < len) {
// User selected encoding mode
if (compaction == Compaction.TEXT) {
encodeText(msg, p, len, sb, textSubMode);
if (bytes == null) {
} else if (compaction == Compaction.BYTE) {
encodingMode = BYTE_COMPACTION;
bytes = getBytesForMessage(msg);
}
int b = determineConsecutiveBinaryCount(msg, bytes, p);
if (b == 0) {
b = 1;
}
// I don't see how this ever takes value TEXT_COMPACTION?
//if (b == 1 && encodingMode == TEXT_COMPACTION) {
if (b == 1) {
//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);
// ... so this is redundant?
//encodingMode = BYTE_COMPACTION;
//textSubMode = SUBMODE_ALPHA; //Reset after latch
}
p += b;
}
encodeBinary(bytes, p, bytes.length, encodingMode, sb);
} else if (compaction == Compaction.NUMERIC) {
encodingMode = NUMERIC_COMPACTION;
sb.append((char) LATCH_TO_NUMERIC);
encodeNumeric(msg, p, len, sb);
} else {
while (p < len) {
int n = determineConsecutiveDigitCount(msg, p);
@ -373,17 +362,13 @@ final class PDF417HighLevelEncoder {
StringBuilder sb) {
if (count == 1 && startmode == TEXT_COMPACTION) {
sb.append((char) SHIFT_TO_BYTE);
} else {
boolean sixpack = (count % 6) == 0;
if (sixpack) {
sb.append((char) LATCH_TO_BYTE);
} else {
sb.append((char) LATCH_TO_BYTE_PADDED);
}
}
char[] chars = new char[5];
int idx = startpos;
// Encode sixpacks
if (count >= 6) {
sb.append((char) LATCH_TO_BYTE);
char[] chars = new char[5];
while ((startpos + count - idx) >= 6) {
long t = 0;
for (int i = 0; i < 6; i++) {
@ -399,7 +384,11 @@ final class PDF417HighLevelEncoder {
}
idx += 6;
}
}
//Encode rest (remaining n<5 bytes if any)
if (idx < startpos + count) {
sb.append((char) LATCH_TO_BYTE_PADDED);
}
for (int i = idx; i < startpos + count; i++) {
int ch = bytes[i] & 0xff;
sb.append((char) ch);

View file

@ -56,12 +56,12 @@ public final class PDF417Writer implements Writer {
int maxCols,
int minRows,
int maxRows,
boolean byteCompaction) throws WriterException {
Compaction compaction) throws WriterException {
PDF417 encoder = initializeEncoder(format, compact);
// Set options: dimensions and byte compaction
encoder.setDimensions(maxCols, minCols, maxRows, minRows);
encoder.setByteCompaction(byteCompaction);
encoder.setCompaction(compaction);
return bitMatrixFromEncoder(encoder, contents, width, height);
}