Created the base Writer object for all barcode encoding, then wrote a QR Code version...
[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
21 /**
22  * @author satorux@google.com (Satoru Takabayashi) - creator
23  * @author dswitkin@google.com (Daniel Switkin) - ported from C++
24  */
25 public final class QRCode {
26
27   // Magic numbers.
28   public static final int kMinVersion = 1;
29   public static final int kMaxVersion = 40;
30   // For matrix width, see 7.3.1 of JISX0510:2004 (p.5).
31   public static final int kMinMatrixWidth = 21;  // Version 1
32   public static final int kMaxMatrixWidth = 177;  // Version 40 (21 + 4 * (40 -1)).
33   public static final int kNumMaskPatterns = 8;
34
35   // See table 3 of JISX0510:2004 (p.16)
36   private static final int kNumBitsTable[][] = {
37       // NUMERIC  ALPHANUMERIC  8BIT_BYTE  KANJI
38       {       10,            9,         8,     8 },  // Version 1-9
39       {       12,           11,        16,    10 },  // Version 10-26
40       {       14,           13,        16,    12 },  // Version 27-40
41   };
42
43   // JAVAPORT: Do not remove trailing slashes yet. There are very likely conflicts with local
44   // variables and parameters which will introduce insidious bugs.
45   private int mode_;
46   private int ec_level_;
47   private int version_;
48   private int matrix_width_;
49   private int mask_pattern_;
50   private int num_total_bytes_;
51   private int num_data_bytes_;
52   private int num_ec_bytes_;
53   private int num_rs_blocks_;
54   private ByteMatrix matrix_;
55
56
57   // They call encoding "mode". The modes are defined in 8.3 of JISX0510:2004 (p.14). It's unlikely
58   // (probably we will not support complicated modes) but if you add an item to this, please also
59   // add it to ModeToString(), GetModeCode(), GetNumBitsForLength(), Encoder.AppendBytes(), and
60   // Encoder.ChooseMode().
61   //
62   // JAVAPORT: These used to be C++ enums, but the code evaluates them as integers, and requires
63   // negative values. I don't want to take the ParsedResultType approach of a class full of statics
64   // of that class's type. The best compromise here is integer constants.
65   //
66   // Formerly enum Mode
67   public static final int MODE_UNDEFINED = -1;
68   public static final int MODE_NUMERIC = 0;
69   public static final int MODE_ALPHANUMERIC = 1;
70   public static final int MODE_8BIT_BYTE = 2;
71   public static final int MODE_KANJI = 3;  // Shift_JIS
72   // The following modes are unimplemented.
73   // MODE_ECI,
74   // MODE_MIXED,
75   // MODE_CONCATENATED,
76   // MODE_FNC1,
77   public static final int NUM_MODES = 4;
78
79   // The error correction levels are defined in the table 22 of JISX0510:2004 (p.45). It's very
80   // unlikely (we've already covered all of them!)  but if you add an item to this, please also add
81   // it to ECLevelToString() and GetECLevelCode().
82   //
83   // Formerly enum ECLevel
84   public static final int EC_LEVEL_UNDEFINED  = -1;
85   // They don't have names in the standard!
86   public static final int EC_LEVEL_L = 0;  //  7% of corruption can be recovered.
87   public static final int EC_LEVEL_M = 1;  // 15%
88   public static final int EC_LEVEL_Q = 2;  // 25%
89   public static final int EC_LEVEL_H = 3;  // 30%
90   public static final int NUM_EC_LEVELS = 4;
91
92   public QRCode() {
93     mode_ = MODE_UNDEFINED;
94     ec_level_ = EC_LEVEL_UNDEFINED;
95     version_ = -1;
96     matrix_width_ = -1;
97     mask_pattern_ = -1;
98     num_total_bytes_ = -1;
99     num_data_bytes_ = -1;
100     num_ec_bytes_ = -1;
101     num_rs_blocks_ = -1;
102     matrix_ = null;
103   }
104
105   // Mode of the QR Code.
106   public int mode() { return mode_; }
107   // Error correction level of the QR Code.
108   public int ec_level() { return ec_level_; }
109   // Version of the QR Code.  The bigger size, the bigger version.
110   public int version() { return version_; }
111   // ByteMatrix width of the QR Code.
112   public int matrix_width() { return matrix_width_; }
113   // Mask pattern of the QR Code.
114   public int mask_pattern() { return mask_pattern_; }
115   // Number of total bytes in the QR Code.
116   public int num_total_bytes() { return num_total_bytes_; }
117   // Number of data bytes in the QR Code.
118   public int num_data_bytes() { return num_data_bytes_; }
119   // Number of error correction bytes in the QR Code.
120   public int num_ec_bytes() { return num_ec_bytes_; }
121   // Number of Reedsolomon blocks in the QR Code.
122   public int num_rs_blocks() { return num_rs_blocks_; }
123   // ByteMatrix data of the QR Code.
124   public final ByteMatrix matrix() { return matrix_; }
125
126   // Return the value of the module (cell) pointed by "x" and "y" in the matrix of the QR Code. They
127   // call cells in the matrix "modules". 1 represents a black cell, and 0 represents a white cell.
128   public int at(int x, int y) {
129     // The value must be zero or one.
130     int value = matrix_.get(y, x);
131     Debug.DCHECK(value == 0 || value == 1);
132     return value;
133   }
134
135   // Checks all the member variables are set properly. Returns true on success. Otherwise, returns
136   // false.
137   // JAVAPORT: Do not call EverythingIsBinary(matrix_) here as it is very expensive.
138   public boolean IsValid() {
139     return (
140         // First check if all version are not uninitialized.
141         mode_ != MODE_UNDEFINED &&
142             ec_level_ != EC_LEVEL_UNDEFINED &&
143             version_ != -1 &&
144             matrix_width_ != -1 &&
145             mask_pattern_ != -1 &&
146             num_total_bytes_ != -1 &&
147             num_data_bytes_ != -1 &&
148             num_ec_bytes_ != -1 &&
149             num_rs_blocks_ != -1 &&
150             // Then check them in other ways..
151             IsValidVersion(version_) &&
152             IsValidMode(mode_) &&
153             IsValidECLevel(ec_level_) &&
154             IsValidMatrixWidth(matrix_width_) &&
155             IsValidMaskPattern(mask_pattern_) &&
156             num_total_bytes_ == num_data_bytes_ + num_ec_bytes_ &&
157             // ByteMatrix stuff.
158             matrix_ != null &&
159             matrix_width_ == matrix_.width() &&
160             // See 7.3.1 of JISX0510:2004 (p.5).
161             matrix_width_ == kMinMatrixWidth + (version_ - 1) * 4 &&
162             matrix_.width() == matrix_.height()); // Must be square.
163   }
164
165   // Return debug String.
166   public String toString() {
167     StringBuffer result = new StringBuffer();
168     result.append("<<QRCode\n");
169     result.append(" mode: ");
170     result.append(ModeToString(mode_));
171     result.append("\n ec_level: ");
172     result.append(ECLevelToString(ec_level_));
173     result.append("\n version: ");
174     result.append(version_);
175     result.append("\n matrix_width: ");
176     result.append(matrix_width_);
177     result.append("\n mask_pattern: ");
178     result.append(mask_pattern_);
179     result.append("\n num_total_bytes_: ");
180     result.append(num_total_bytes_);
181     result.append("\n num_data_bytes: ");
182     result.append(num_data_bytes_);
183     result.append("\n num_ec_bytes: ");
184     result.append(num_ec_bytes_);
185     result.append("\n num_rs_blocks: ");
186     result.append(num_rs_blocks_);
187     if (matrix_ == null) {
188       result.append("\n matrix: null");
189     } else {
190       result.append("\n matrix:");
191       result.append(matrix_.toString());
192     }
193     result.append("\n>>\n");
194     return result.toString();
195   }
196
197   public void set_mode(int value) {
198     mode_ = value;
199   }
200
201   public void set_ec_level(int value) {
202     ec_level_ = value;
203   }
204
205   public void set_version(int value) {
206     version_ = value;
207   }
208
209   public void set_matrix_width(int value) {
210     matrix_width_ = value;
211   }
212
213   public void set_mask_pattern(int value) {
214     mask_pattern_ = value;
215   }
216
217   public void set_num_total_bytes(int value) {
218     num_total_bytes_ = value;
219   }
220
221   public void set_num_data_bytes(int value) {
222     num_data_bytes_ = value;
223   }
224
225   public void set_num_ec_bytes(int value) {
226     num_ec_bytes_ = value;
227   }
228
229   public void set_num_rs_blocks(int value) {
230     num_rs_blocks_ = value;
231   }
232
233   // This takes ownership of the 2D array.  The 2D array will be
234   // deleted in the destructor of the class.
235   public void set_matrix(ByteMatrix value) {
236     matrix_ = value;
237   }
238
239   // Check if "version" is valid.
240   public static boolean IsValidVersion(final int version) {
241     return version >= kMinVersion && version <= kMaxVersion;
242   }
243
244   // Check if "mask_pattern" is valid.
245   public static boolean IsValidECLevel(int ec_level) {
246     return ec_level >= 0 && ec_level < NUM_EC_LEVELS;
247   }
248
249   // Check if "mode" is valid.
250   public static boolean IsValidMode(final int mode) {
251     return mode >= 0 && mode < NUM_MODES;
252   }
253
254   // Check if "width" is valid.
255   public static boolean IsValidMatrixWidth(int width) {
256     return width >= kMinMatrixWidth && width <= kMaxMatrixWidth;
257   }
258
259   // Check if "mask_pattern" is valid.
260   public static boolean IsValidMaskPattern(int mask_pattern) {
261     return mask_pattern >= 0 && mask_pattern < kNumMaskPatterns;
262   }
263
264   // Convert "ec_level" to String for debugging.
265   public static final String ECLevelToString(int ec_level) {
266     switch (ec_level) {
267       case QRCode.EC_LEVEL_UNDEFINED:
268         return "UNDEFINED";
269       case QRCode.EC_LEVEL_L:
270         return "L";
271       case QRCode.EC_LEVEL_M:
272         return "M";
273       case QRCode.EC_LEVEL_Q:
274         return "Q";
275       case QRCode.EC_LEVEL_H:
276         return "H";
277       default:
278         break;
279     }
280     return "UNKNOWN";
281   }
282
283   // Convert "mode" to String for debugging.
284   public static final String ModeToString(int mode) {
285     switch (mode) {
286       case QRCode.MODE_UNDEFINED:
287         return "UNDEFINED";
288       case QRCode.MODE_NUMERIC:
289         return "NUMERIC";
290       case QRCode.MODE_ALPHANUMERIC:
291         return "ALPHANUMERIC";
292       case QRCode.MODE_8BIT_BYTE:
293         return "8BIT_BYTE";
294       case QRCode.MODE_KANJI:
295         return "KANJI";
296       default:
297         break;
298     }
299     return "UNKNOWN";
300   }
301
302   // Return the code of error correction level. On error, return -1. The codes of error correction
303   // levels are defined in the table 22 of JISX0510:2004 (p.45).
304   public static int GetECLevelCode(final int ec_level) {
305     switch (ec_level) {
306       case QRCode.EC_LEVEL_L:
307         return 1;
308       case QRCode.EC_LEVEL_M:
309         return 0;
310       case QRCode.EC_LEVEL_Q:
311         return 3;
312       case QRCode.EC_LEVEL_H:
313         return 2;
314       default:
315         break;
316     }
317     return -1;  // Unknown error correction level.
318   }
319
320   // Return the code of mode. On error, return -1. The codes of modes are defined in the table 2 of
321   // JISX0510:2004 (p.16).
322   public static int GetModeCode(final int mode) {
323     switch (mode) {
324       case QRCode.MODE_NUMERIC:
325         return 1;
326       case QRCode.MODE_ALPHANUMERIC:
327         return 2;
328       case QRCode.MODE_8BIT_BYTE:
329         return 4;
330       case QRCode.MODE_KANJI:
331         return 8;
332       default:
333         break;
334     }
335     return -1;  // Unknown mode.
336   }
337
338   // Return the number of bits needed for representing the length info of QR Code with "version" and
339   // "mode". On error, return -1.
340   public static int GetNumBitsForLength(int version, int mode) {
341     if (!IsValidVersion(version)) {
342       Debug.LOG_ERROR("Invalid version: " + version);
343       return -1;
344     }
345     if (!IsValidMode(mode)) {
346       Debug.LOG_ERROR("Invalid mode: " + mode);
347       return -1;
348     }
349     if (version >= 1 && version <= 9) {
350       return kNumBitsTable[0][mode];
351     } else if (version >= 10 && version <= 26) {
352       return kNumBitsTable[1][mode];
353     } else if (version >= 27 && version <= 40) {
354       return kNumBitsTable[2][mode];
355     } else {
356       Debug.LOG_ERROR("Should not reach");
357     }
358     return -1;
359   }
360
361   // Return true if the all values in the matrix are binary numbers. Otherwise, return false.
362   //
363   // JAVAPORT: This is going to be super expensive and unnecessary, we should not call this in
364   // production. I'm leaving it because it may be useful for testing. It should be removed entirely
365   // if ByteMatrix is changed never to contain a -1.
366   private static boolean EverythingIsBinary(final ByteMatrix matrix) {
367     for (int y = 0; y < matrix.height(); ++y) {
368       for (int x = 0; x < matrix.width(); ++x) {
369         int value = matrix.get(y, x);
370         if (!(value == 0 || value == 1)) {
371           // Found non zero/one value.
372           return false;
373         }
374       }
375     }
376     return true;
377   }
378
379 }