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