Unify handling of Mode too
[zxing.git] / core / src / com / google / zxing / qrcode / encoder / QRCode.java
1 /*
2  * Copyright 2008 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.qrcode.encoder;
18
19 import com.google.zxing.common.ByteMatrix;
20 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
21 import com.google.zxing.qrcode.decoder.Mode;
22
23 /**
24  * @author satorux@google.com (Satoru Takabayashi) - creator
25  * @author dswitkin@google.com (Daniel Switkin) - ported from C++
26  */
27 public final class QRCode {
28
29   // Magic numbers.
30   private static final int MIN_VERSION = 1;
31   private static final int MAX_VERSION = 40;
32   // For matrix width, see 7.3.1 of JISX0510:2004 (p.5).
33   private static final int MIN_MATRIX_WIDTH = 21;  // Version 1
34   private static final int MAX_MATRIX_WIDTH = 177;  // Version 40 (21 + 4 * (40 -1)).
35   public static final int NUM_MASK_PATTERNS = 8;
36
37   private Mode mode;
38   private ErrorCorrectionLevel ecLevel;
39   private int version;
40   private int matrixWidth;
41   private int maskPattern;
42   private int numTotalBytes;
43   private int numDataBytes;
44   private int numECBytes;
45   private int numRSBlocks;
46   private ByteMatrix matrix;
47
48   public QRCode() {
49     mode = null;
50     ecLevel = null;
51     version = -1;
52     matrixWidth = -1;
53     maskPattern = -1;
54     numTotalBytes = -1;
55     numDataBytes = -1;
56     numECBytes = -1;
57     numRSBlocks = -1;
58     matrix = null;
59   }
60
61   // Mode of the QR Code.
62   public Mode getMode() {
63     return mode;
64   }
65
66   // Error correction level of the QR Code.
67   public ErrorCorrectionLevel getECLevel() {
68     return ecLevel;
69   }
70
71   // Version of the QR Code.  The bigger size, the bigger version.
72   public int getVersion() {
73     return version;
74   }
75
76   // ByteMatrix width of the QR Code.
77   public int getMatrixWidth() {
78     return matrixWidth;
79   }
80
81   // Mask pattern of the QR Code.
82   public int getMaskPattern() {
83     return maskPattern;
84   }
85
86   // Number of total bytes in the QR Code.
87   public int getNumTotalBytes() {
88     return numTotalBytes;
89   }
90
91   // Number of data bytes in the QR Code.
92   public int getNumDataBytes() {
93     return numDataBytes;
94   }
95
96   // Number of error correction bytes in the QR Code.
97   public int getNumECBytes() {
98     return numECBytes;
99   }
100
101   // Number of Reedsolomon blocks in the QR Code.
102   public int getNumRSBlocks() {
103     return numRSBlocks;
104   }
105
106   // ByteMatrix data of the QR Code.
107   public final ByteMatrix getMatrix() {
108     return matrix;
109   }
110   
111
112   // Return the value of the module (cell) pointed by "x" and "y" in the matrix of the QR Code. They
113   // call cells in the matrix "modules". 1 represents a black cell, and 0 represents a white cell.
114   public int at(int x, int y) {
115     // The value must be zero or one.
116     int value = matrix.get(y, x);
117     if (!(value == 0 || value == 1)) {
118       // this is really like an assert... not sure what better exception to use?
119       throw new RuntimeException("Bad value");
120     }
121     return value;
122   }
123
124   // Checks all the member variables are set properly. Returns true on success. Otherwise, returns
125   // false.
126   public boolean isValid() {
127     return
128         // First check if all version are not uninitialized.
129         mode != null &&
130         ecLevel != null &&
131         version != -1 &&
132         matrixWidth != -1 &&
133         maskPattern != -1 &&
134         numTotalBytes != -1 &&
135         numDataBytes != -1 &&
136         numECBytes != -1 &&
137         numRSBlocks != -1 &&
138         // Then check them in other ways..
139         isValidVersion(version) &&
140         isValidMatrixWidth(matrixWidth) &&
141         isValidMaskPattern(maskPattern) &&
142         numTotalBytes == numDataBytes + numECBytes &&
143         // ByteMatrix stuff.
144         matrix != null &&
145         matrixWidth == matrix.width() &&
146         // See 7.3.1 of JISX0510:2004 (p.5).
147         matrixWidth == MIN_MATRIX_WIDTH + (version - 1) * 4 &&
148         matrix.width() == matrix.height(); // Must be square.
149   }
150
151   // Return debug String.
152   public String toString() {
153     StringBuffer result = new StringBuffer();
154     result.append("<<\n");
155     result.append(" mode: ");
156     result.append(mode);
157     result.append("\n ecLevel: ");
158     result.append(ecLevel);
159     result.append("\n version: ");
160     result.append(version);
161     result.append("\n matrixWidth: ");
162     result.append(matrixWidth);
163     result.append("\n maskPattern: ");
164     result.append(maskPattern);
165     result.append("\n numTotalBytes: ");
166     result.append(numTotalBytes);
167     result.append("\n numDataBytes: ");
168     result.append(numDataBytes);
169     result.append("\n numECBytes: ");
170     result.append(numECBytes);
171     result.append("\n numRSBlocks: ");
172     result.append(numRSBlocks);
173     if (matrix == null) {
174       result.append("\n matrix: null\n");
175     } else {
176       result.append("\n matrix:\n");
177       result.append(matrix.toString());
178     }
179     result.append(">>\n");
180     return result.toString();
181   }
182
183   public void setMode(Mode value) {
184     mode = value;
185   }
186
187   public void setECLevel(ErrorCorrectionLevel value) {
188     ecLevel = value;
189   }
190
191   public void setVersion(int value) {
192     version = value;
193   }
194
195   public void setMatrixWidth(int value) {
196     matrixWidth = value;
197   }
198
199   public void setMaskPattern(int value) {
200     maskPattern = value;
201   }
202
203   public void setNumTotalBytes(int value) {
204     numTotalBytes = value;
205   }
206
207   public void setNumDataBytes(int value) {
208     numDataBytes = value;
209   }
210
211   public void setNumECBytes(int value) {
212     numECBytes = value;
213   }
214
215   public void setNumRSBlocks(int value) {
216     numRSBlocks = value;
217   }
218
219   // This takes ownership of the 2D array.
220   public void setMatrix(ByteMatrix value) {
221     matrix = value;
222   }
223
224   // Check if "version" is valid.
225   public static boolean isValidVersion(final int version) {
226     return version >= MIN_VERSION && version <= MAX_VERSION;
227   }
228
229   // Check if "width" is valid.
230   public static boolean isValidMatrixWidth(int width) {
231     return width >= MIN_MATRIX_WIDTH && width <= MAX_MATRIX_WIDTH;
232   }
233
234   // Check if "mask_pattern" is valid.
235   public static boolean isValidMaskPattern(int maskPattern) {
236     return maskPattern >= 0 && maskPattern < NUM_MASK_PATTERNS;
237   }
238
239   // Return true if the all values in the matrix are binary numbers.
240   //
241   // JAVAPORT: This is going to be super expensive and unnecessary, we should not call this in
242   // production. I'm leaving it because it may be useful for testing. It should be removed entirely
243   // if ByteMatrix is changed never to contain a -1.
244   /*
245   private static boolean EverythingIsBinary(final ByteMatrix matrix) {
246     for (int y = 0; y < matrix.height(); ++y) {
247       for (int x = 0; x < matrix.width(); ++x) {
248         int value = matrix.get(y, x);
249         if (!(value == 0 || value == 1)) {
250           // Found non zero/one value.
251           return false;
252         }
253       }
254     }
255     return true;
256   }
257    */
258
259 }