Issue 512
[zxing.git] / core / src / com / google / zxing / oned / UPCEANWriter.java
1 /*
2  * Copyright 2009 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.google.zxing.oned;
18
19 import com.google.zxing.BarcodeFormat;
20 import com.google.zxing.Writer;
21 import com.google.zxing.WriterException;
22 import com.google.zxing.common.BitMatrix;
23
24 import java.util.Hashtable;
25
26 /**
27  * <p>Encapsulates functionality and implementation that is common to UPC and EAN families
28  * of one-dimensional barcodes.</p>
29  *
30  * @author aripollak@gmail.com (Ari Pollak)
31  */
32 public abstract class UPCEANWriter implements Writer {
33
34   public BitMatrix encode(String contents, BarcodeFormat format, int width, int height)
35   throws WriterException {
36     return encode(contents, format, width, height, null);
37   }
38
39   public BitMatrix encode(String contents, BarcodeFormat format, int width, int height,
40       Hashtable hints) throws WriterException {
41     if (contents == null || contents.length() == 0) {
42       throw new IllegalArgumentException("Found empty contents");
43     }
44
45     if (width < 0 || height < 0) {
46       throw new IllegalArgumentException("Requested dimensions are too small: "
47           + width + 'x' + height);
48     }
49
50     byte[] code = encode(contents);
51     return renderResult(code, width, height);
52   }
53
54   /** @return a byte array of horizontal pixels (0 = white, 1 = black) */
55   private static BitMatrix renderResult(byte[] code, int width, int height) {
56     int inputWidth = code.length;
57     // Add quiet zone on both sides
58     int fullWidth = inputWidth + (UPCEANReader.START_END_PATTERN.length << 1);
59     int outputWidth = Math.max(width, fullWidth);
60     int outputHeight = Math.max(1, height);
61
62     int multiple = outputWidth / fullWidth;
63     int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
64
65     BitMatrix output = new BitMatrix(outputWidth, outputHeight);
66     for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
67       if (code[inputX] == 1) {
68         output.setRegion(outputX, 0, multiple, outputHeight);
69       }
70     }
71     return output;
72   }
73
74
75   /**
76    * Appends the given pattern to the target array starting at pos.
77    *
78    * @param startColor
79    *          starting color - 0 for white, 1 for black
80    * @return the number of elements added to target.
81    */
82    protected static int appendPattern(byte[] target, int pos, int[] pattern, int startColor) {
83     if (startColor != 0 && startColor != 1) {
84       throw new IllegalArgumentException(
85           "startColor must be either 0 or 1, but got: " + startColor);
86     }
87
88     byte color = (byte) startColor;
89     int numAdded = 0;
90     for (int i = 0; i < pattern.length; i++) {
91       for (int j = 0; j < pattern[i]; j++) {
92         target[pos] = color;
93         pos += 1;
94         numAdded += 1;
95       }
96       color ^= 1; // flip color after each segment
97     }
98     return numAdded;
99   }
100
101   /** @return a byte array of horizontal pixels (0 = white, 1 = black) */
102   public abstract byte[] encode(String contents);
103
104 }