add CodaBarWriter, and make separation from UPCEANWriter to OneDimensionalCodeWriter and UPCEANWriter which inherits OneDimensionalCodeWriter.
git-svn-id: https://zxing.googlecode.com/svn/trunk@1907 59b500cc-1b3d-0410-9834-0bbf25fbcc57
diff --git a/core/src/com/google/zxing/MultiFormatWriter.java b/core/src/com/google/zxing/MultiFormatWriter.java
index 4909a93..9b03d7f 100644
--- a/core/src/com/google/zxing/MultiFormatWriter.java
+++ b/core/src/com/google/zxing/MultiFormatWriter.java
@@ -17,6 +17,7 @@
package com.google.zxing;
import com.google.zxing.common.BitMatrix;
+import com.google.zxing.oned.CodaBarWriter;
import com.google.zxing.oned.Code128Writer;
import com.google.zxing.oned.Code39Writer;
import com.google.zxing.oned.EAN13Writer;
@@ -62,6 +63,8 @@
writer = new ITFWriter();
} else if (format == BarcodeFormat.PDF_417) {
writer = new PDF417Writer();
+ } else if (format == BarcodeFormat.CODABAR) {
+ writer = new CodaBarWriter();
} else {
throw new IllegalArgumentException("No encoder available for format " + format);
}
diff --git a/core/src/com/google/zxing/oned/CodaBarReader.java b/core/src/com/google/zxing/oned/CodaBarReader.java
index 3a311ef..eea8692 100644
--- a/core/src/com/google/zxing/oned/CodaBarReader.java
+++ b/core/src/com/google/zxing/oned/CodaBarReader.java
@@ -32,14 +32,14 @@
public final class CodaBarReader extends OneDReader {
private static final String ALPHABET_STRING = "0123456789-$:/.+ABCDTN";
- private static final char[] ALPHABET = ALPHABET_STRING.toCharArray();
+ protected static final char[] ALPHABET = ALPHABET_STRING.toCharArray();
/**
* These represent the encodings of characters, as patterns of wide and narrow bars. The 7 least-significant bits of
* each int correspond to the pattern of wide and narrow, with 1s representing "wide" and 0s representing narrow. NOTE
* : c is equal to the * pattern NOTE : d is equal to the e pattern
*/
- private static final int[] CHARACTER_ENCODINGS = {
+ protected static final int[] CHARACTER_ENCODINGS = {
0x003, 0x006, 0x009, 0x060, 0x012, 0x042, 0x021, 0x024, 0x030, 0x048, // 0-9
0x00c, 0x018, 0x045, 0x051, 0x054, 0x015, 0x01A, 0x029, 0x00B, 0x00E, // -$:/.+ABCD
0x01A, 0x029 //TN
@@ -208,7 +208,7 @@
throw NotFoundException.getNotFoundInstance();
}
- private static boolean arrayContains(char[] array, char key) {
+ protected static boolean arrayContains(char[] array, char key) {
if (array != null) {
for (int i = 0; i < array.length; i++) {
if (array[i] == key) {
diff --git a/core/src/com/google/zxing/oned/CodaBarWriter.java b/core/src/com/google/zxing/oned/CodaBarWriter.java
new file mode 100644
index 0000000..a33267b
--- /dev/null
+++ b/core/src/com/google/zxing/oned/CodaBarWriter.java
@@ -0,0 +1,113 @@
+/*
+ * 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.oned;
+
+import com.google.zxing.common.BitMatrix;
+
+/**
+ * This class renders CodaBar as {@link BitMatrix}.
+ *
+ * @author dsbnatut@gmail.com (Kazuki Nishiura)
+ */
+public class CodaBarWriter extends OneDimensionalCodeWriter {
+
+ public CodaBarWriter() {
+ // Super constructor requires the sum of the left and right margin length.
+ // CodaBar spec requires a side margin to be more than ten times wider than narrow space.
+ // In this implementation, narrow space has a unit length, so 20 is required minimum.
+ super(20);
+ }
+
+ /*
+ * @see com.google.zxing.oned.OneDimensionalCodeWriter#encode(java.lang.String)
+ */
+ public byte[] encode(String contents) {
+ int resultLength;
+ int position = 0;
+
+ // Verify input and calculate decoded length.
+ if (!CodaBarReader.arrayContains(
+ new char[]{'A', 'B', 'C', 'D'}, Character.toUpperCase(contents.charAt(0)))) {
+ throw new IllegalArgumentException(
+ "Codabar should start with one of the following: 'A', 'B', 'C' or 'D'");
+ }
+ if (!CodaBarReader.arrayContains(new char[]{'T', 'N', '*', 'E'},
+ Character.toUpperCase(contents.charAt(contents.length() - 1)))) {
+ throw new IllegalArgumentException(
+ "Codabar should end with one of the following: 'T', 'N', '*' or 'E'");
+ }
+ // The start character and the end character are decoded to 10 length each.
+ resultLength = 20;
+ char[] charsWhichAreTenLengthEachAfterDecoded = new char[]{'/', ':', '+', '.'};
+ for (int i = 1; i < contents.length()-1; i++) {
+ if (Character.isDigit(contents.charAt(i)) || contents.charAt(i) == '-'
+ || contents.charAt(i) == '$') {
+ resultLength += 9;
+ } else if(CodaBarReader.arrayContains(
+ charsWhichAreTenLengthEachAfterDecoded, contents.charAt(i))) {
+ resultLength += 10;
+ } else {
+ throw new IllegalArgumentException("Cannot encode : '" + contents.charAt(i) + "'");
+ }
+ }
+ // A blank is placed between each character.
+ resultLength += contents.length() - 1;
+
+ byte[] result = new byte[resultLength];
+ for (int index = 0; index < contents.length(); index++) {
+ char c = Character.toUpperCase(contents.charAt(index));
+ int code = 0;
+ if (index == contents.length() - 1){
+ // Neither * nor E are in the CodaBarReader.ALPHABET.
+ // * is equal to the c pattern, and e is equal to the d pattern
+ if (c == '*') {
+ c = 'C';
+ } else if (c == 'E') {
+ c = 'D';
+ }
+ }
+ for (int i = 0; i < CodaBarReader.ALPHABET.length; i++) {
+ // Found any, because I checked above.
+ if (c == CodaBarReader.ALPHABET[i]) {
+ code = CodaBarReader.CHARACTER_ENCODINGS[i];
+ break;
+ }
+ }
+ boolean isBlack = true;
+ byte color = 1;
+ int counter = 0;
+ int bit = 0;
+ while (bit < 7){ // A character consists of 7 digit.
+ result[position] = color;
+ position++;
+ if (((code >> (6-bit)) & 1) == 0 || counter == 1){
+ color ^= 1; // Flip the color.
+ bit++;
+ counter = 0;
+ } else {
+ counter++;
+ }
+ }
+ if (index < contents.length() - 1) {
+ result[position] = 0;
+ position++;
+ }
+ }
+ return result;
+ }
+}
+
diff --git a/core/src/com/google/zxing/oned/OneDimensionalCodeWriter.java b/core/src/com/google/zxing/oned/OneDimensionalCodeWriter.java
new file mode 100644
index 0000000..61d1a0b
--- /dev/null
+++ b/core/src/com/google/zxing/oned/OneDimensionalCodeWriter.java
@@ -0,0 +1,118 @@
+/*
+ * 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.oned;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.Writer;
+import com.google.zxing.WriterException;
+import com.google.zxing.common.BitMatrix;
+
+import java.util.Hashtable;
+
+/**
+ * <p>Encapsulates functionality and implementation that is common to one-dimensional barcodes.</p>
+ *
+ * @author dsbnatut@gmail.com (Kazuki Nishiura)
+ */
+public abstract class OneDimensionalCodeWriter implements Writer {
+ protected static int sidesMargin;
+ public OneDimensionalCodeWriter(int sidesMargin) {
+ this.sidesMargin = sidesMargin;
+ }
+
+ public BitMatrix encode(String contents, BarcodeFormat format, int width, int height)
+ throws WriterException {
+ return encode(contents, format, width, height, null);
+ }
+
+ /**
+ * Encode the contents following specified format.
+ * {@code width} and {@code height} are required size. This method may return bigger size
+ * {@code BitMatrix} when specified size is too small. The user can set both {@code width} and
+ * {@code height} to zero to get minimum size barcode. If negative value is set to {@code width}
+ * or {@code height}, {@code IllegalArgumentException} is thrown.
+ */
+ public BitMatrix encode(String contents, BarcodeFormat format, int width, int height,
+ Hashtable hints) throws WriterException {
+ if (contents == null || contents.length() == 0) {
+ throw new IllegalArgumentException("Found empty contents");
+ }
+
+ if (width < 0 || height < 0) {
+ throw new IllegalArgumentException("Negative size is not allowed. Input: "
+ + width + 'x' + height);
+ }
+
+ byte[] code = encode(contents);
+ return renderResult(code, width, height);
+ }
+
+ /** @return a byte array of horizontal pixels (0 = white, 1 = black) */
+ private static BitMatrix renderResult(byte[] code, int width, int height) {
+ int inputWidth = code.length;
+ // Add quiet zone on both sides.
+ int fullWidth = inputWidth + sidesMargin;
+ int outputWidth = Math.max(width, fullWidth);
+ int outputHeight = Math.max(1, height);
+
+ int multiple = outputWidth / fullWidth;
+ int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
+
+ BitMatrix output = new BitMatrix(outputWidth, outputHeight);
+ for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
+ if (code[inputX] == 1) {
+ output.setRegion(outputX, 0, multiple, outputHeight);
+ }
+ }
+ return output;
+ }
+
+
+ /**
+ * Appends the given pattern to the target array starting at pos.
+ *
+ * @param startColor
+ * starting color - 0 for white, 1 for black
+ * @return the number of elements added to target.
+ */
+ protected static int appendPattern(byte[] target, int pos, int[] pattern, int startColor) {
+ if (startColor != 0 && startColor != 1) {
+ throw new IllegalArgumentException(
+ "startColor must be either 0 or 1, but got: " + startColor);
+ }
+
+ byte color = (byte) startColor;
+ int numAdded = 0;
+ for (int i = 0; i < pattern.length; i++) {
+ for (int j = 0; j < pattern[i]; j++) {
+ target[pos] = color;
+ pos += 1;
+ numAdded += 1;
+ }
+ color ^= 1; // flip color after each segment
+ }
+ return numAdded;
+ }
+
+ /**
+ * Encode the contents to byte array expression of one-dimensional barcode.
+ * Start code and end code should be included in result, and side margins should not be included.
+ * @return a byte array of horizontal pixels (0 = white, 1 = black)
+ * */
+ public abstract byte[] encode(String contents);
+}
+
diff --git a/core/src/com/google/zxing/oned/UPCEANWriter.java b/core/src/com/google/zxing/oned/UPCEANWriter.java
index 68fa4a0..145f3f0 100644
--- a/core/src/com/google/zxing/oned/UPCEANWriter.java
+++ b/core/src/com/google/zxing/oned/UPCEANWriter.java
@@ -16,89 +16,17 @@
package com.google.zxing.oned;
-import com.google.zxing.BarcodeFormat;
-import com.google.zxing.Writer;
-import com.google.zxing.WriterException;
-import com.google.zxing.common.BitMatrix;
-
-import java.util.Hashtable;
/**
* <p>Encapsulates functionality and implementation that is common to UPC and EAN families
* of one-dimensional barcodes.</p>
*
* @author aripollak@gmail.com (Ari Pollak)
+ * @author dsbnatut@gmail.com (Kazuki Nishiura)
*/
-public abstract class UPCEANWriter implements Writer {
-
- public BitMatrix encode(String contents, BarcodeFormat format, int width, int height)
- throws WriterException {
- return encode(contents, format, width, height, null);
+public abstract class UPCEANWriter extends OneDimensionalCodeWriter {
+ public UPCEANWriter() {
+ super(UPCEANReader.START_END_PATTERN.length << 1);
}
-
- public BitMatrix encode(String contents, BarcodeFormat format, int width, int height,
- Hashtable hints) throws WriterException {
- if (contents == null || contents.length() == 0) {
- throw new IllegalArgumentException("Found empty contents");
- }
-
- if (width < 0 || height < 0) {
- throw new IllegalArgumentException("Requested dimensions are too small: "
- + width + 'x' + height);
- }
-
- byte[] code = encode(contents);
- return renderResult(code, width, height);
- }
-
- /** @return a byte array of horizontal pixels (0 = white, 1 = black) */
- private static BitMatrix renderResult(byte[] code, int width, int height) {
- int inputWidth = code.length;
- // Add quiet zone on both sides
- int fullWidth = inputWidth + (UPCEANReader.START_END_PATTERN.length << 1);
- int outputWidth = Math.max(width, fullWidth);
- int outputHeight = Math.max(1, height);
-
- int multiple = outputWidth / fullWidth;
- int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
-
- BitMatrix output = new BitMatrix(outputWidth, outputHeight);
- for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
- if (code[inputX] == 1) {
- output.setRegion(outputX, 0, multiple, outputHeight);
- }
- }
- return output;
- }
-
-
- /**
- * Appends the given pattern to the target array starting at pos.
- *
- * @param startColor
- * starting color - 0 for white, 1 for black
- * @return the number of elements added to target.
- */
- protected static int appendPattern(byte[] target, int pos, int[] pattern, int startColor) {
- if (startColor != 0 && startColor != 1) {
- throw new IllegalArgumentException(
- "startColor must be either 0 or 1, but got: " + startColor);
- }
-
- byte color = (byte) startColor;
- int numAdded = 0;
- for (int i = 0; i < pattern.length; i++) {
- for (int j = 0; j < pattern[i]; j++) {
- target[pos] = color;
- pos += 1;
- numAdded += 1;
- }
- color ^= 1; // flip color after each segment
- }
- return numAdded;
- }
-
- /** @return a byte array of horizontal pixels (0 = white, 1 = black) */
- public abstract byte[] encode(String contents);
-
}
+
diff --git a/core/test/src/com/google/zxing/oned/CodaBarWriterTestCase.java b/core/test/src/com/google/zxing/oned/CodaBarWriterTestCase.java
new file mode 100644
index 0000000..fc9c6b7
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/CodaBarWriterTestCase.java
@@ -0,0 +1,44 @@
+/*
+ * 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.oned;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.WriterException;
+import com.google.zxing.common.BitMatrix;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author dsbnatut@gmail.com (Kazuki Nishiura)
+ */
+public final class CodaBarWriterTestCase extends Assert {
+
+ @Test
+ public void testEncode() throws WriterException {
+ // 1001001011 0 110101001 0 101011001 0 110101001 0 101001101 0 110010101 0 1101101011 0
+ // 1001001011
+ String resultStr = "0000000000" +
+ "1001001011011010100101010110010110101001010100110101100101010110110101101001001011"
+ + "0000000000";
+ BitMatrix result = new CodaBarWriter().encode(
+"B515-3/N", BarcodeFormat.CODABAR, resultStr.length(), 0);
+ for (int i = 0; i < resultStr.length(); i++) {
+ assertEquals("Element " + i, resultStr.charAt(i) == '1', result.get(i, 0));
+ }
+ }
+
+}