2 * Copyright 2007 ZXing authors
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.google.zxing.qrcode.decoder;
19 import com.google.zxing.FormatException;
20 import com.google.zxing.common.BitMatrix;
23 * See ISO 18004:2006 Annex D
27 public final class Version {
30 * See ISO 18004:2006 Annex D.
31 * Element i represents the raw version bits that specify version i + 7
33 private static final int[] VERSION_DECODE_INFO = {
34 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6,
35 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78,
36 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683,
37 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB,
38 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250,
39 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B,
40 0x2542E, 0x26A64, 0x27541, 0x28C69
43 private static final Version[] VERSIONS = buildVersions();
45 private final int versionNumber;
46 private final int[] alignmentPatternCenters;
47 private final ECBlocks[] ecBlocks;
48 private final int totalCodewords;
50 private Version(int versionNumber,
51 int[] alignmentPatternCenters,
52 ECBlocks... ecBlocks) {
53 this.versionNumber = versionNumber;
54 this.alignmentPatternCenters = alignmentPatternCenters;
55 this.ecBlocks = ecBlocks;
57 int ecCodewords = ecBlocks[0].getECCodewordsPerBlock();
58 ECB[] ecbArray = ecBlocks[0].getECBlocks();
59 for (ECB ecBlock : ecbArray) {
60 total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);
62 this.totalCodewords = total;
65 public int getVersionNumber() {
69 public int[] getAlignmentPatternCenters() {
70 return alignmentPatternCenters;
73 public int getTotalCodewords() {
74 return totalCodewords;
77 public int getDimensionForVersion() {
78 return 17 + 4 * versionNumber;
81 public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) {
82 return ecBlocks[ecLevel.ordinal()];
86 * <p>Deduces version information purely from QR Code dimensions.</p>
88 * @param dimension dimension in modules
89 * @return Version for a QR Code of that dimension
90 * @throws FormatException if dimension is not 1 mod 4
92 public static Version getProvisionalVersionForDimension(int dimension) throws FormatException {
93 if (dimension % 4 != 1) {
94 throw FormatException.getFormatInstance();
97 return getVersionForNumber((dimension - 17) >> 2);
98 } catch (IllegalArgumentException ignored) {
99 throw FormatException.getFormatInstance();
103 public static Version getVersionForNumber(int versionNumber) {
104 if (versionNumber < 1 || versionNumber > 40) {
105 throw new IllegalArgumentException();
107 return VERSIONS[versionNumber - 1];
110 static Version decodeVersionInformation(int versionBits) {
111 int bestDifference = Integer.MAX_VALUE;
113 for (int i = 0; i < VERSION_DECODE_INFO.length; i++) {
114 int targetVersion = VERSION_DECODE_INFO[i];
115 // Do the version info bits match exactly? done.
116 if (targetVersion == versionBits) {
117 return getVersionForNumber(i + 7);
119 // Otherwise see if this is the closest to a real version info bit string
120 // we have seen so far
121 int bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion);
122 if (bitsDifference < bestDifference) {
124 bestDifference = bitsDifference;
127 // We can tolerate up to 3 bits of error since no two version info codewords will
128 // differ in less than 8 bits.
129 if (bestDifference <= 3) {
130 return getVersionForNumber(bestVersion);
132 // If we didn't find a close enough match, fail
137 * See ISO 18004:2006 Annex E
139 BitMatrix buildFunctionPattern() {
140 int dimension = getDimensionForVersion();
141 BitMatrix bitMatrix = new BitMatrix(dimension);
143 // Top left finder pattern + separator + format
144 bitMatrix.setRegion(0, 0, 9, 9);
145 // Top right finder pattern + separator + format
146 bitMatrix.setRegion(dimension - 8, 0, 8, 9);
147 // Bottom left finder pattern + separator + format
148 bitMatrix.setRegion(0, dimension - 8, 9, 8);
150 // Alignment patterns
151 int max = alignmentPatternCenters.length;
152 for (int x = 0; x < max; x++) {
153 int i = alignmentPatternCenters[x] - 2;
154 for (int y = 0; y < max; y++) {
155 if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) {
156 // No alignment patterns near the three finder paterns
159 bitMatrix.setRegion(alignmentPatternCenters[y] - 2, i, 5, 5);
163 // Vertical timing pattern
164 bitMatrix.setRegion(6, 9, 1, dimension - 17);
165 // Horizontal timing pattern
166 bitMatrix.setRegion(9, 6, dimension - 17, 1);
168 if (versionNumber > 6) {
169 // Version info, top right
170 bitMatrix.setRegion(dimension - 11, 0, 3, 6);
171 // Version info, bottom left
172 bitMatrix.setRegion(0, dimension - 11, 6, 3);
179 * <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will
180 * use blocks of differing sizes within one version, so, this encapsulates the parameters for
181 * each set of blocks. It also holds the number of error-correction codewords per block since it
182 * will be the same across all blocks within one version.</p>
184 public static final class ECBlocks {
185 private final int ecCodewordsPerBlock;
186 private final ECB[] ecBlocks;
188 ECBlocks(int ecCodewordsPerBlock, ECB... ecBlocks) {
189 this.ecCodewordsPerBlock = ecCodewordsPerBlock;
190 this.ecBlocks = ecBlocks;
193 public int getECCodewordsPerBlock() {
194 return ecCodewordsPerBlock;
197 public int getNumBlocks() {
199 for (ECB ecBlock : ecBlocks) {
200 total += ecBlock.getCount();
205 public int getTotalECCodewords() {
206 return ecCodewordsPerBlock * getNumBlocks();
209 public ECB[] getECBlocks() {
215 * <p>Encapsualtes the parameters for one error-correction block in one symbol version.
216 * This includes the number of data codewords, and the number of times a block with these
217 * parameters is used consecutively in the QR code version's format.</p>
219 public static final class ECB {
220 private final int count;
221 private final int dataCodewords;
223 ECB(int count, int dataCodewords) {
225 this.dataCodewords = dataCodewords;
228 public int getCount() {
232 public int getDataCodewords() {
233 return dataCodewords;
238 public String toString() {
239 return String.valueOf(versionNumber);
243 * See ISO 18004:2006 6.5.1 Table 9
245 private static Version[] buildVersions() {
246 return new Version[]{
247 new Version(1, new int[]{},
248 new ECBlocks(7, new ECB(1, 19)),
249 new ECBlocks(10, new ECB(1, 16)),
250 new ECBlocks(13, new ECB(1, 13)),
251 new ECBlocks(17, new ECB(1, 9))),
252 new Version(2, new int[]{6, 18},
253 new ECBlocks(10, new ECB(1, 34)),
254 new ECBlocks(16, new ECB(1, 28)),
255 new ECBlocks(22, new ECB(1, 22)),
256 new ECBlocks(28, new ECB(1, 16))),
257 new Version(3, new int[]{6, 22},
258 new ECBlocks(15, new ECB(1, 55)),
259 new ECBlocks(26, new ECB(1, 44)),
260 new ECBlocks(18, new ECB(2, 17)),
261 new ECBlocks(22, new ECB(2, 13))),
262 new Version(4, new int[]{6, 26},
263 new ECBlocks(20, new ECB(1, 80)),
264 new ECBlocks(18, new ECB(2, 32)),
265 new ECBlocks(26, new ECB(2, 24)),
266 new ECBlocks(16, new ECB(4, 9))),
267 new Version(5, new int[]{6, 30},
268 new ECBlocks(26, new ECB(1, 108)),
269 new ECBlocks(24, new ECB(2, 43)),
270 new ECBlocks(18, new ECB(2, 15),
272 new ECBlocks(22, new ECB(2, 11),
274 new Version(6, new int[]{6, 34},
275 new ECBlocks(18, new ECB(2, 68)),
276 new ECBlocks(16, new ECB(4, 27)),
277 new ECBlocks(24, new ECB(4, 19)),
278 new ECBlocks(28, new ECB(4, 15))),
279 new Version(7, new int[]{6, 22, 38},
280 new ECBlocks(20, new ECB(2, 78)),
281 new ECBlocks(18, new ECB(4, 31)),
282 new ECBlocks(18, new ECB(2, 14),
284 new ECBlocks(26, new ECB(4, 13),
286 new Version(8, new int[]{6, 24, 42},
287 new ECBlocks(24, new ECB(2, 97)),
288 new ECBlocks(22, new ECB(2, 38),
290 new ECBlocks(22, new ECB(4, 18),
292 new ECBlocks(26, new ECB(4, 14),
294 new Version(9, new int[]{6, 26, 46},
295 new ECBlocks(30, new ECB(2, 116)),
296 new ECBlocks(22, new ECB(3, 36),
298 new ECBlocks(20, new ECB(4, 16),
300 new ECBlocks(24, new ECB(4, 12),
302 new Version(10, new int[]{6, 28, 50},
303 new ECBlocks(18, new ECB(2, 68),
305 new ECBlocks(26, new ECB(4, 43),
307 new ECBlocks(24, new ECB(6, 19),
309 new ECBlocks(28, new ECB(6, 15),
311 new Version(11, new int[]{6, 30, 54},
312 new ECBlocks(20, new ECB(4, 81)),
313 new ECBlocks(30, new ECB(1, 50),
315 new ECBlocks(28, new ECB(4, 22),
317 new ECBlocks(24, new ECB(3, 12),
319 new Version(12, new int[]{6, 32, 58},
320 new ECBlocks(24, new ECB(2, 92),
322 new ECBlocks(22, new ECB(6, 36),
324 new ECBlocks(26, new ECB(4, 20),
326 new ECBlocks(28, new ECB(7, 14),
328 new Version(13, new int[]{6, 34, 62},
329 new ECBlocks(26, new ECB(4, 107)),
330 new ECBlocks(22, new ECB(8, 37),
332 new ECBlocks(24, new ECB(8, 20),
334 new ECBlocks(22, new ECB(12, 11),
336 new Version(14, new int[]{6, 26, 46, 66},
337 new ECBlocks(30, new ECB(3, 115),
339 new ECBlocks(24, new ECB(4, 40),
341 new ECBlocks(20, new ECB(11, 16),
343 new ECBlocks(24, new ECB(11, 12),
345 new Version(15, new int[]{6, 26, 48, 70},
346 new ECBlocks(22, new ECB(5, 87),
348 new ECBlocks(24, new ECB(5, 41),
350 new ECBlocks(30, new ECB(5, 24),
352 new ECBlocks(24, new ECB(11, 12),
354 new Version(16, new int[]{6, 26, 50, 74},
355 new ECBlocks(24, new ECB(5, 98),
357 new ECBlocks(28, new ECB(7, 45),
359 new ECBlocks(24, new ECB(15, 19),
361 new ECBlocks(30, new ECB(3, 15),
363 new Version(17, new int[]{6, 30, 54, 78},
364 new ECBlocks(28, new ECB(1, 107),
366 new ECBlocks(28, new ECB(10, 46),
368 new ECBlocks(28, new ECB(1, 22),
370 new ECBlocks(28, new ECB(2, 14),
372 new Version(18, new int[]{6, 30, 56, 82},
373 new ECBlocks(30, new ECB(5, 120),
375 new ECBlocks(26, new ECB(9, 43),
377 new ECBlocks(28, new ECB(17, 22),
379 new ECBlocks(28, new ECB(2, 14),
381 new Version(19, new int[]{6, 30, 58, 86},
382 new ECBlocks(28, new ECB(3, 113),
384 new ECBlocks(26, new ECB(3, 44),
386 new ECBlocks(26, new ECB(17, 21),
388 new ECBlocks(26, new ECB(9, 13),
390 new Version(20, new int[]{6, 34, 62, 90},
391 new ECBlocks(28, new ECB(3, 107),
393 new ECBlocks(26, new ECB(3, 41),
395 new ECBlocks(30, new ECB(15, 24),
397 new ECBlocks(28, new ECB(15, 15),
399 new Version(21, new int[]{6, 28, 50, 72, 94},
400 new ECBlocks(28, new ECB(4, 116),
402 new ECBlocks(26, new ECB(17, 42)),
403 new ECBlocks(28, new ECB(17, 22),
405 new ECBlocks(30, new ECB(19, 16),
407 new Version(22, new int[]{6, 26, 50, 74, 98},
408 new ECBlocks(28, new ECB(2, 111),
410 new ECBlocks(28, new ECB(17, 46)),
411 new ECBlocks(30, new ECB(7, 24),
413 new ECBlocks(24, new ECB(34, 13))),
414 new Version(23, new int[]{6, 30, 54, 78, 102},
415 new ECBlocks(30, new ECB(4, 121),
417 new ECBlocks(28, new ECB(4, 47),
419 new ECBlocks(30, new ECB(11, 24),
421 new ECBlocks(30, new ECB(16, 15),
423 new Version(24, new int[]{6, 28, 54, 80, 106},
424 new ECBlocks(30, new ECB(6, 117),
426 new ECBlocks(28, new ECB(6, 45),
428 new ECBlocks(30, new ECB(11, 24),
430 new ECBlocks(30, new ECB(30, 16),
432 new Version(25, new int[]{6, 32, 58, 84, 110},
433 new ECBlocks(26, new ECB(8, 106),
435 new ECBlocks(28, new ECB(8, 47),
437 new ECBlocks(30, new ECB(7, 24),
439 new ECBlocks(30, new ECB(22, 15),
441 new Version(26, new int[]{6, 30, 58, 86, 114},
442 new ECBlocks(28, new ECB(10, 114),
444 new ECBlocks(28, new ECB(19, 46),
446 new ECBlocks(28, new ECB(28, 22),
448 new ECBlocks(30, new ECB(33, 16),
450 new Version(27, new int[]{6, 34, 62, 90, 118},
451 new ECBlocks(30, new ECB(8, 122),
453 new ECBlocks(28, new ECB(22, 45),
455 new ECBlocks(30, new ECB(8, 23),
457 new ECBlocks(30, new ECB(12, 15),
459 new Version(28, new int[]{6, 26, 50, 74, 98, 122},
460 new ECBlocks(30, new ECB(3, 117),
462 new ECBlocks(28, new ECB(3, 45),
464 new ECBlocks(30, new ECB(4, 24),
466 new ECBlocks(30, new ECB(11, 15),
468 new Version(29, new int[]{6, 30, 54, 78, 102, 126},
469 new ECBlocks(30, new ECB(7, 116),
471 new ECBlocks(28, new ECB(21, 45),
473 new ECBlocks(30, new ECB(1, 23),
475 new ECBlocks(30, new ECB(19, 15),
477 new Version(30, new int[]{6, 26, 52, 78, 104, 130},
478 new ECBlocks(30, new ECB(5, 115),
480 new ECBlocks(28, new ECB(19, 47),
482 new ECBlocks(30, new ECB(15, 24),
484 new ECBlocks(30, new ECB(23, 15),
486 new Version(31, new int[]{6, 30, 56, 82, 108, 134},
487 new ECBlocks(30, new ECB(13, 115),
489 new ECBlocks(28, new ECB(2, 46),
491 new ECBlocks(30, new ECB(42, 24),
493 new ECBlocks(30, new ECB(23, 15),
495 new Version(32, new int[]{6, 34, 60, 86, 112, 138},
496 new ECBlocks(30, new ECB(17, 115)),
497 new ECBlocks(28, new ECB(10, 46),
499 new ECBlocks(30, new ECB(10, 24),
501 new ECBlocks(30, new ECB(19, 15),
503 new Version(33, new int[]{6, 30, 58, 86, 114, 142},
504 new ECBlocks(30, new ECB(17, 115),
506 new ECBlocks(28, new ECB(14, 46),
508 new ECBlocks(30, new ECB(29, 24),
510 new ECBlocks(30, new ECB(11, 15),
512 new Version(34, new int[]{6, 34, 62, 90, 118, 146},
513 new ECBlocks(30, new ECB(13, 115),
515 new ECBlocks(28, new ECB(14, 46),
517 new ECBlocks(30, new ECB(44, 24),
519 new ECBlocks(30, new ECB(59, 16),
521 new Version(35, new int[]{6, 30, 54, 78, 102, 126, 150},
522 new ECBlocks(30, new ECB(12, 121),
524 new ECBlocks(28, new ECB(12, 47),
526 new ECBlocks(30, new ECB(39, 24),
528 new ECBlocks(30, new ECB(22, 15),
530 new Version(36, new int[]{6, 24, 50, 76, 102, 128, 154},
531 new ECBlocks(30, new ECB(6, 121),
533 new ECBlocks(28, new ECB(6, 47),
535 new ECBlocks(30, new ECB(46, 24),
537 new ECBlocks(30, new ECB(2, 15),
539 new Version(37, new int[]{6, 28, 54, 80, 106, 132, 158},
540 new ECBlocks(30, new ECB(17, 122),
542 new ECBlocks(28, new ECB(29, 46),
544 new ECBlocks(30, new ECB(49, 24),
546 new ECBlocks(30, new ECB(24, 15),
548 new Version(38, new int[]{6, 32, 58, 84, 110, 136, 162},
549 new ECBlocks(30, new ECB(4, 122),
551 new ECBlocks(28, new ECB(13, 46),
553 new ECBlocks(30, new ECB(48, 24),
555 new ECBlocks(30, new ECB(42, 15),
557 new Version(39, new int[]{6, 26, 54, 82, 110, 138, 166},
558 new ECBlocks(30, new ECB(20, 117),
560 new ECBlocks(28, new ECB(40, 47),
562 new ECBlocks(30, new ECB(43, 24),
564 new ECBlocks(30, new ECB(10, 15),
566 new Version(40, new int[]{6, 30, 58, 86, 114, 142, 170},
567 new ECBlocks(30, new ECB(19, 118),
569 new ECBlocks(28, new ECB(18, 47),
571 new ECBlocks(30, new ECB(34, 24),
573 new ECBlocks(30, new ECB(20, 15),