Issue 849, adjusted fix to Code128Writer

git-svn-id: https://zxing.googlecode.com/svn/trunk@1803 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2011-05-30 18:50:56 +00:00
parent 2d17cf4491
commit e9d5024e46

View file

@ -16,7 +16,10 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import java.util.Enumeration;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Vector;
import com.google.zxing.BarcodeFormat; import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException; import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix; import com.google.zxing.common.BitMatrix;
@ -28,6 +31,12 @@ import com.google.zxing.common.BitMatrix;
*/ */
public final class Code128Writer extends UPCEANWriter { public final class Code128Writer extends UPCEANWriter {
private static final int CODE_START_B = 104;
private static final int CODE_START_C = 105;
private static final int CODE_CODE_B = 100;
private static final int CODE_CODE_C = 99;
private static final int CODE_STOP = 106;
public BitMatrix encode(String contents, public BitMatrix encode(String contents,
BarcodeFormat format, BarcodeFormat format,
int width, int width,
@ -41,72 +50,112 @@ public final class Code128Writer extends UPCEANWriter {
public byte[] encode(String contents) { public byte[] encode(String contents) {
int length = contents.length(); int length = contents.length();
if (length > 80) { // Check length
if (length < 1 || length > 80) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Requested contents should be less than 80 digits long, but got " + length); "Contents length should be between 1 and 80 characters, but got " + length);
} }
// Check content
//Determine which code we should use (C or B)
boolean useCodeC = true;
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
char c = contents.charAt(i); char c = contents.charAt(i);
if (c < '0' || c > '9') { if (c < ' ' || c > '~') {
useCodeC = false; throw new IllegalArgumentException("Contents should only contain characters between ' ' and '~'");
break;
} }
} }
int codeWidth = 11 + 11 + 13; //start plus check plus stop character Vector patterns = new Vector(); // temporary storage for patterns
byte[] result; int checkSum = 0;
int pos; int checkWeight = 1;
int check; int codeSet = 0; // selected code (CODE_CODE_B or CODE_CODE_C)
int position = 0; // position in contents
if (useCodeC) { while (position < length) {
//Optionnaly add "0" to have pairs //Select code to use
if (length % 2 != 0) { int requiredDigitCount = codeSet == CODE_CODE_C ? 2 : 4;
contents = '0' + contents; int newCodeSet;
length++; if (length - position >= requiredDigitCount && isDigits(contents, position, requiredDigitCount)) {
newCodeSet = CODE_CODE_C;
} else {
newCodeSet = CODE_CODE_B;
} }
//get total code width for this barcode
for (int i = 0; i < length; i += 2){ //Get the pattern index
int[] patterns = Code128Reader.CODE_PATTERNS[Integer.parseInt(contents.substring(i, i + 2))]; int patternIndex;
for (int j = 0; j < patterns.length; j++) { if (newCodeSet == codeSet) {
codeWidth += patterns[j]; // Encode the current character
} if (codeSet == CODE_CODE_B) {
} patternIndex = contents.charAt(position) - ' ';
result = new byte[codeWidth]; position += 1;
pos = appendPattern(result, 0, Code128Reader.CODE_PATTERNS[105], 1); } else { // CODE_CODE_C
check = 105; patternIndex = Integer.parseInt(contents.substring(position, position + 2));
//append next character to bytematrix position += 2;
for (int i = 0; i < length; i += 2) {
int pair = Integer.parseInt(contents.substring(i, i + 2));
check += pair * (i / 2 + 1);
pos += appendPattern(result, pos, Code128Reader.CODE_PATTERNS[pair],1);
} }
} else { } else {
//get total code width for this barcode // Should we change the current code?
for (int i = 0; i < length; i++) { // Do we have a code set?
int[] patterns = Code128Reader.CODE_PATTERNS[contents.charAt(i) - ' ']; if (codeSet == 0) {
for (int j = 0; j < patterns.length; j++) { // No, we don't have a code set
codeWidth += patterns[j]; if (newCodeSet == CODE_CODE_B) {
patternIndex = CODE_START_B;
} else {
// CODE_CODE_C
patternIndex = CODE_START_C;
} }
} else {
// Yes, we have a code set
patternIndex = newCodeSet;
} }
result = new byte[codeWidth]; codeSet = newCodeSet;
pos = appendPattern(result, 0, Code128Reader.CODE_PATTERNS[104], 1); }
check = 104;
//append next character to bytematrix // Get the pattern
for (int i = 0; i < length; i++) { patterns.addElement(Code128Reader.CODE_PATTERNS[patternIndex]);
check += (contents.charAt(i) - ' ') * (i + 1);
pos += appendPattern(result, pos, Code128Reader.CODE_PATTERNS[contents.charAt(i) - ' '],1); // Compute checksum
checkSum += patternIndex * checkWeight;
if (position != 0) {
checkWeight++;
} }
} }
//compute checksum and append it along with end character and quiet space // Compute and append checksum
check %= 103; checkSum %= 103;
pos += appendPattern(result,pos,Code128Reader.CODE_PATTERNS[check],1); patterns.addElement(Code128Reader.CODE_PATTERNS[checkSum]);
pos += appendPattern(result,pos,Code128Reader.CODE_PATTERNS[106],1);
// Append stop code
patterns.addElement(Code128Reader.CODE_PATTERNS[CODE_STOP]);
// Compute code width
int codeWidth = 0;
Enumeration patternEnumeration = patterns.elements();
while (patternEnumeration.hasMoreElements()) {
int[] pattern = (int[]) patternEnumeration.nextElement();
for (int i = 0; i < pattern.length; i++) {
codeWidth += pattern[i];
}
}
// Compute result
byte[] result = new byte[codeWidth];
patternEnumeration = patterns.elements();
int pos = 0;
while (patternEnumeration.hasMoreElements()) {
int[] pattern = (int[]) patternEnumeration.nextElement();
pos += appendPattern(result, pos, pattern, 1);
}
return result; return result;
} }
private static boolean isDigits(String value, int start, int length) {
int end = start + length;
for (int i = start; i < end; i++) {
char c = value.charAt(i);
if (c < '0' || c > '9') {
return false;
}
}
return true;
}
} }