From 5d47b0f8d03c7a0bf3d45270e4c9f85c0e772f2c Mon Sep 17 00:00:00 2001 From: srowen Date: Wed, 2 Nov 2011 13:57:49 +0000 Subject: [PATCH] Issue 1026 PDF417 encoding improvements git-svn-id: https://zxing.googlecode.com/svn/trunk@2006 59b500cc-1b3d-0410-9834-0bbf25fbcc57 --- .../zxing/pdf417/encoder/Compaction.java | 26 ++++++ .../google/zxing/pdf417/encoder/PDF417.java | 36 +++++---- .../encoder/PDF417HighLevelEncoder.java | 81 ++++++++----------- .../zxing/pdf417/encoder/PDF417Writer.java | 4 +- 4 files changed, 83 insertions(+), 64 deletions(-) create mode 100644 core/src/com/google/zxing/pdf417/encoder/Compaction.java diff --git a/core/src/com/google/zxing/pdf417/encoder/Compaction.java b/core/src/com/google/zxing/pdf417/encoder/Compaction.java new file mode 100644 index 000000000..d0a85d600 --- /dev/null +++ b/core/src/com/google/zxing/pdf417/encoder/Compaction.java @@ -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 + +} diff --git a/core/src/com/google/zxing/pdf417/encoder/PDF417.java b/core/src/com/google/zxing/pdf417/encoder/PDF417.java index 7f9a82814..e10c2022d 100644 --- a/core/src/com/google/zxing/pdf417/encoder/PDF417.java +++ b/core/src/com/google/zxing/pdf417/encoder/PDF417.java @@ -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; } /** diff --git a/core/src/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoder.java b/core/src/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoder.java index 2cb32e1cf..a77bb00bd 100644 --- a/core/src/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoder.java +++ b/core/src/com/google/zxing/pdf417/encoder/PDF417HighLevelEncoder.java @@ -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); + + } else if (compaction == Compaction.BYTE) { + encodingMode = BYTE_COMPACTION; + bytes = getBytesForMessage(msg); + 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); - if (bytes == null) { - 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; - } } else { while (p < len) { int n = determineConsecutiveDigitCount(msg, p); @@ -373,33 +362,33 @@ 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; - while ((startpos + count - idx) >= 6) { - long t = 0; - for (int i = 0; i < 6; i++) { - t <<= 8; - t += bytes[idx + i] & 0xff; + // 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++) { + t <<= 8; + t += bytes[idx + i] & 0xff; + } + for (int i = 0; i < 5; i++) { + chars[i] = (char) (t % 900); + t /= 900; + } + for (int i = chars.length - 1; i >= 0; i--) { + sb.append(chars[i]); + } + idx += 6; } - for (int i = 0; i < 5; i++) { - chars[i] = (char) (t % 900); - t /= 900; - } - for (int i = chars.length - 1; i >= 0; i--) { - sb.append(chars[i]); - } - 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); diff --git a/core/src/com/google/zxing/pdf417/encoder/PDF417Writer.java b/core/src/com/google/zxing/pdf417/encoder/PDF417Writer.java index f44b4c262..8d03401ac 100644 --- a/core/src/com/google/zxing/pdf417/encoder/PDF417Writer.java +++ b/core/src/com/google/zxing/pdf417/encoder/PDF417Writer.java @@ -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); }