Spell checker fixes, narrowed scope / made less visible where possible. Little stuff
[zxing.git] / core / src / com / google / zxing / oned / AbstractUPCEANWriter.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 java.util.Hashtable;
20
21 import com.google.zxing.BarcodeFormat;
22 import com.google.zxing.WriterException;
23 import com.google.zxing.common.ByteMatrix;
24
25 /**
26  * <p>Encapsulates functionality and implementation that is common to UPC and EAN families
27  * of one-dimensional barcodes.</p>
28  *
29  * @author aripollak@gmail.com (Ari Pollak)
30  */
31 public abstract class AbstractUPCEANWriter implements UPCEANWriter {
32
33   public ByteMatrix encode(String contents, BarcodeFormat format, int width, int height)
34   throws WriterException {
35     return encode(contents, format, width, height, null);  
36   }
37
38   public ByteMatrix encode(String contents, BarcodeFormat format, int width, int height,
39       Hashtable hints) throws WriterException {
40     if (contents == null || contents.length() == 0) {
41       throw new IllegalArgumentException("Found empty contents");
42     }
43
44     if (width < 0 || height < 0) {
45       throw new IllegalArgumentException("Requested dimensions are too small: "
46           + width + 'x' + height);
47     }
48
49     byte[] code = encode(contents);
50     return renderResult(code, width, height);
51   }
52
53   /** @return a byte array of horizontal pixels (0 = white, 1 = black) */
54   private static ByteMatrix renderResult(byte[] code, int width, int height) {
55     int inputWidth = code.length;
56     // Add quiet zone on both sides
57     int fullWidth = inputWidth + (AbstractUPCEANReader.START_END_PATTERN.length << 1);
58     int outputWidth = Math.max(width, fullWidth);
59     int outputHeight = Math.max(1, height);
60
61     int multiple = outputWidth / fullWidth;
62     int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
63
64     ByteMatrix output = new ByteMatrix(outputWidth, outputHeight);
65     byte[][] outputArray = output.getArray();
66
67     byte[] row = new byte[outputWidth];
68
69     // a. Write the white pixels at the left of each row
70     for (int x = 0; x < leftPadding; x++) {
71       row[x] = (byte) 255;
72     }
73
74     // b. Write the contents of this row of the barcode
75     int offset = leftPadding;
76     for (int x = 0; x < inputWidth; x++) {
77       byte value = (code[x] == 1) ? 0 : (byte) 255;
78       for (int z = 0; z < multiple; z++) {
79         row[offset + z] = value;
80       }
81       offset += multiple;
82     }
83
84     // c. Write the white pixels at the right of each row
85     offset = leftPadding + (inputWidth * multiple);
86     for (int x = offset; x < outputWidth; x++) {
87       row[x] = (byte) 255;
88     }
89
90     // d. Write the completed row multiple times
91     for (int z = 0; z < outputHeight; z++) {
92       System.arraycopy(row, 0, outputArray[z], 0, outputWidth);
93     }
94
95     return output;
96   }
97
98
99   /**
100    * Appends the given pattern to the target array starting at pos.
101    * 
102    * @param startColor
103    *          starting color - 0 for white, 1 for black
104    * @return the number of elements added to target.
105    */
106    protected static int appendPattern(byte[] target, int pos, int[] pattern, int startColor) {
107     if (startColor != 0 && startColor != 1) {
108       throw new IllegalArgumentException(
109           "startColor must be either 0 or 1, but got: " + startColor);
110     }
111
112     byte color = (byte) startColor;
113     int numAdded = 0;
114     for (int i = 0; i < pattern.length; i++) {
115       for (int j = 0; j < pattern[i]; j++) {
116         target[pos] = color;
117         pos += 1;
118         numAdded += 1;
119       }
120       color ^= 1; // flip color after each segment
121     }
122     return numAdded;
123   }
124 }