2 * Copyright 2007 Google Inc.
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
17 package com.google.zxing.qrcode.decoder;
\r
19 import com.google.zxing.ReaderException;
\r
20 import com.google.zxing.common.BitMatrix;
\r
23 * See ISO 18004:2006 Annex D
\r
25 * @author srowen@google.com (Sean Owen)
\r
27 public final class Version {
\r
30 * See ISO 18004:2006 Annex D.
\r
31 * Element i represents the raw version bits that specify version i + 7
\r
33 private static final int[] VERSION_DECODE_INFO = new int[]{
\r
34 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6,
\r
35 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78,
\r
36 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683,
\r
37 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB,
\r
38 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250,
\r
39 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B,
\r
40 0x2542E, 0x26A64, 0x27541, 0x28C69
\r
43 private static final Version[] VERSIONS = buildVersions();
\r
45 private final int versionNumber;
\r
46 private final int[] alignmentPatternCenters;
\r
47 private final ECBlocks[] ecBlocks;
\r
48 private final int totalCodewords;
\r
50 private Version(int versionNumber,
\r
51 int[] alignmentPatternCenters,
\r
55 ECBlocks ecBlocks4) {
\r
56 this.versionNumber = versionNumber;
\r
57 this.alignmentPatternCenters = alignmentPatternCenters;
\r
58 this.ecBlocks = new ECBlocks[] { ecBlocks1, ecBlocks2, ecBlocks3, ecBlocks4 };
\r
60 ECBlocks levelLECBlocks = ecBlocks1; // L,M,Q,H -- all the same total
\r
61 int ecCodewords = levelLECBlocks.ecCodewords;
\r
62 ECB[] ecbArray = levelLECBlocks.ecBlocks;
\r
63 for (int i = 0; i < ecbArray.length; i++) {
\r
64 ECB ecBlock = ecbArray[i];
\r
65 total += ecBlock.count * (ecBlock.dataCodewords + ecCodewords);
\r
67 this.totalCodewords = total;
\r
70 public int getVersionNumber() {
\r
71 return versionNumber;
\r
74 public int[] getAlignmentPatternCenters() {
\r
75 return alignmentPatternCenters;
\r
78 public int getTotalCodewords() {
\r
79 return totalCodewords;
\r
82 public int getDimensionForVersion() {
\r
83 return 17 + 4 * versionNumber;
\r
86 ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) {
\r
87 return ecBlocks[ecLevel.ordinal()];
\r
90 public static Version getProvisionalVersionForDimension(int dimension)
\r
91 throws ReaderException {
\r
92 if (dimension % 4 != 1) {
\r
93 throw new ReaderException("Dimension must be 1 mod 4");
\r
95 return getVersionForNumber((dimension - 17) >> 2);
\r
98 public static Version getVersionForNumber(int versionNumber)
\r
99 throws ReaderException {
\r
100 if (versionNumber < 1 || versionNumber > 40) {
\r
101 throw new ReaderException(
\r
102 "versionNumber must be between 1 and 40");
\r
104 return VERSIONS[versionNumber - 1];
\r
107 static Version decodeVersionInformation(int versionBits)
\r
108 throws ReaderException {
\r
109 int bestDifference = Integer.MAX_VALUE;
\r
110 int bestVersion = 0;
\r
111 for (int i = 0; i < VERSION_DECODE_INFO.length; i++) {
\r
112 int targetVersion = VERSION_DECODE_INFO[i];
\r
113 if (targetVersion == versionBits) {
\r
114 return getVersionForNumber(i + 7);
\r
116 int bitsDifference =
\r
117 FormatInformation.numBitsDiffering(versionBits, targetVersion);
\r
118 if (bitsDifference < bestDifference) {
\r
119 bestVersion = i + 7;
\r
122 if (bestDifference <= 3) {
\r
123 return getVersionForNumber(bestVersion);
\r
129 * See ISO 18004:2006 Annex E
\r
131 BitMatrix buildFunctionPattern() {
\r
132 int dimension = getDimensionForVersion();
\r
133 BitMatrix bitMatrix = new BitMatrix(dimension);
\r
135 // Top left finder pattern + separator + format
\r
136 bitMatrix.setRegion(0, 0, 9, 9);
\r
137 // Top right finder pattern + separator + format
\r
138 bitMatrix.setRegion(0, dimension - 8, 9, 8);
\r
139 // Bottom left finder pattern + separator + format
\r
140 bitMatrix.setRegion(dimension - 8, 0, 8, 9);
\r
142 // Alignment patterns
\r
143 int max = alignmentPatternCenters.length;
\r
144 for (int x = 0; x < max; x++) {
\r
145 int i = alignmentPatternCenters[x] - 2;
\r
146 for (int y = 0; y < max; y++) {
\r
147 if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) {
\r
148 // No alignment patterns near the three finder paterns
\r
151 bitMatrix.setRegion(i, alignmentPatternCenters[y] - 2, 5, 5);
\r
155 // Vertical timing pattern
\r
156 bitMatrix.setRegion(9, 6, dimension - 17, 1);
\r
157 // Horizontal timing pattern
\r
158 bitMatrix.setRegion(6, 9, 1, dimension - 17);
\r
160 if (versionNumber > 6) {
\r
161 // Version info, top right
\r
162 bitMatrix.setRegion(0, dimension - 11, 6, 3);
\r
163 // Version info, bottom left
\r
164 bitMatrix.setRegion(dimension - 11, 0, 3, 6);
\r
171 * <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will
\r
172 * use blocks of differing sizes within one version, so, this encapsulates the parameters for
\r
173 * each set of blocks. It also holds the number of error-correction codewords per block since it
\r
174 * will be the same across all blocks within one version.</p>
\r
176 static final class ECBlocks {
\r
177 private int ecCodewords;
\r
178 private ECB[] ecBlocks;
\r
180 private ECBlocks(int ecCodewords, ECB ecBlocks) {
\r
181 this.ecCodewords = ecCodewords;
\r
182 this.ecBlocks = new ECB[] { ecBlocks };
\r
185 private ECBlocks(int ecCodewords, ECB ecBlocks1, ECB ecBlocks2) {
\r
186 this.ecCodewords = ecCodewords;
\r
187 this.ecBlocks = new ECB[] { ecBlocks1, ecBlocks2 };
\r
190 int getECCodewords() {
\r
191 return ecCodewords;
\r
194 ECB[] getECBlocks() {
\r
200 * <p>Encapsualtes the parameters for one error-correction block in one symbol version.
\r
201 * This includes the number of data codewords, and the number of times a block with these
\r
202 * parameters is used consecutively in the QR code version's format.</p>
\r
204 static final class ECB {
\r
206 private int dataCodewords;
\r
208 private ECB(int count, int dataCodewords) {
\r
209 this.count = count;
\r
210 this.dataCodewords = dataCodewords;
\r
217 int getDataCodewords() {
\r
218 return dataCodewords;
\r
222 public String toString() {
\r
223 return String.valueOf(versionNumber);
\r
227 * See ISO 18004:2006 6.5.1 Table 9
\r
229 private static Version[] buildVersions() {
\r
230 return new Version[]{
\r
231 new Version(1, new int[]{},
\r
232 new ECBlocks(7, new ECB(1, 19)),
\r
233 new ECBlocks(10, new ECB(1, 16)),
\r
234 new ECBlocks(13, new ECB(1, 13)),
\r
235 new ECBlocks(17, new ECB(1, 9))),
\r
236 new Version(2, new int[]{6, 18},
\r
237 new ECBlocks(10, new ECB(1, 34)),
\r
238 new ECBlocks(16, new ECB(1, 28)),
\r
239 new ECBlocks(22, new ECB(1, 22)),
\r
240 new ECBlocks(28, new ECB(1, 16))),
\r
241 new Version(3, new int[]{6, 22},
\r
242 new ECBlocks(15, new ECB(1, 55)),
\r
243 new ECBlocks(26, new ECB(1, 44)),
\r
244 new ECBlocks(18, new ECB(2, 17)),
\r
245 new ECBlocks(22, new ECB(2, 13))),
\r
246 new Version(4, new int[]{6, 26},
\r
247 new ECBlocks(20, new ECB(1, 80)),
\r
248 new ECBlocks(18, new ECB(2, 32)),
\r
249 new ECBlocks(26, new ECB(2, 24)),
\r
250 new ECBlocks(16, new ECB(4, 9))),
\r
251 new Version(5, new int[]{6, 30},
\r
252 new ECBlocks(26, new ECB(1, 108)),
\r
253 new ECBlocks(24, new ECB(2, 43)),
\r
254 new ECBlocks(18, new ECB(2, 15),
\r
256 new ECBlocks(22, new ECB(2, 11),
\r
258 new Version(6, new int[]{6, 34},
\r
259 new ECBlocks(18, new ECB(2, 68)),
\r
260 new ECBlocks(16, new ECB(4, 27)),
\r
261 new ECBlocks(24, new ECB(4, 19)),
\r
262 new ECBlocks(28, new ECB(4, 15))),
\r
263 new Version(7, new int[]{6, 22, 38},
\r
264 new ECBlocks(20, new ECB(2, 78)),
\r
265 new ECBlocks(18, new ECB(4, 31)),
\r
266 new ECBlocks(18, new ECB(2, 14),
\r
268 new ECBlocks(26, new ECB(4, 13),
\r
270 new Version(8, new int[]{6, 24, 42},
\r
271 new ECBlocks(24, new ECB(2, 97)),
\r
272 new ECBlocks(22, new ECB(2, 38),
\r
274 new ECBlocks(22, new ECB(4, 18),
\r
276 new ECBlocks(26, new ECB(4, 14),
\r
278 new Version(9, new int[]{6, 26, 46},
\r
279 new ECBlocks(30, new ECB(2, 116)),
\r
280 new ECBlocks(22, new ECB(3, 36),
\r
282 new ECBlocks(20, new ECB(4, 16),
\r
284 new ECBlocks(24, new ECB(4, 12),
\r
286 new Version(10, new int[]{6, 28, 50},
\r
287 new ECBlocks(18, new ECB(2, 68),
\r
289 new ECBlocks(26, new ECB(4, 43),
\r
291 new ECBlocks(24, new ECB(6, 19),
\r
293 new ECBlocks(28, new ECB(6, 15),
\r
295 new Version(11, new int[]{6, 30, 54},
\r
296 new ECBlocks(20, new ECB(4, 81)),
\r
297 new ECBlocks(30, new ECB(1, 50),
\r
299 new ECBlocks(28, new ECB(4, 22),
\r
301 new ECBlocks(24, new ECB(3, 12),
\r
303 new Version(12, new int[]{6, 32, 58},
\r
304 new ECBlocks(24, new ECB(2, 92),
\r
306 new ECBlocks(22, new ECB(6, 36),
\r
308 new ECBlocks(26, new ECB(4, 20),
\r
310 new ECBlocks(28, new ECB(7, 14),
\r
312 new Version(13, new int[]{6, 34, 62},
\r
313 new ECBlocks(26, new ECB(4, 107)),
\r
314 new ECBlocks(22, new ECB(8, 37),
\r
316 new ECBlocks(24, new ECB(8, 20),
\r
318 new ECBlocks(22, new ECB(12, 11),
\r
320 new Version(14, new int[]{6, 26, 46, 66},
\r
321 new ECBlocks(30, new ECB(3, 115),
\r
323 new ECBlocks(24, new ECB(4, 40),
\r
325 new ECBlocks(20, new ECB(11, 16),
\r
327 new ECBlocks(24, new ECB(11, 12),
\r
329 new Version(15, new int[]{6, 26, 48, 70},
\r
330 new ECBlocks(22, new ECB(5, 87),
\r
332 new ECBlocks(24, new ECB(5, 41),
\r
334 new ECBlocks(30, new ECB(5, 24),
\r
336 new ECBlocks(24, new ECB(11, 12),
\r
338 new Version(16, new int[]{6, 26, 50, 74},
\r
339 new ECBlocks(24, new ECB(5, 98),
\r
341 new ECBlocks(28, new ECB(7, 45),
\r
343 new ECBlocks(24, new ECB(15, 19),
\r
345 new ECBlocks(30, new ECB(3, 15),
\r
347 new Version(17, new int[]{6, 30, 54, 78},
\r
348 new ECBlocks(28, new ECB(1, 107),
\r
350 new ECBlocks(28, new ECB(10, 46),
\r
352 new ECBlocks(28, new ECB(1, 22),
\r
354 new ECBlocks(28, new ECB(2, 14),
\r
356 new Version(18, new int[]{6, 30, 56, 82},
\r
357 new ECBlocks(30, new ECB(5, 120),
\r
359 new ECBlocks(26, new ECB(9, 43),
\r
361 new ECBlocks(28, new ECB(17, 22),
\r
363 new ECBlocks(28, new ECB(2, 14),
\r
365 new Version(19, new int[]{6, 30, 58, 86},
\r
366 new ECBlocks(28, new ECB(3, 113),
\r
368 new ECBlocks(26, new ECB(3, 44),
\r
370 new ECBlocks(26, new ECB(17, 21),
\r
372 new ECBlocks(26, new ECB(9, 13),
\r
374 new Version(20, new int[]{6, 34, 62, 90},
\r
375 new ECBlocks(28, new ECB(3, 107),
\r
377 new ECBlocks(26, new ECB(3, 41),
\r
379 new ECBlocks(30, new ECB(15, 24),
\r
381 new ECBlocks(28, new ECB(15, 15),
\r
383 new Version(21, new int[]{6, 28, 50, 72, 94},
\r
384 new ECBlocks(28, new ECB(4, 116),
\r
386 new ECBlocks(26, new ECB(17, 42)),
\r
387 new ECBlocks(28, new ECB(17, 22),
\r
389 new ECBlocks(30, new ECB(19, 16),
\r
391 new Version(22, new int[]{6, 26, 50, 74, 98},
\r
392 new ECBlocks(28, new ECB(2, 111),
\r
394 new ECBlocks(28, new ECB(17, 46)),
\r
395 new ECBlocks(30, new ECB(7, 24),
\r
397 new ECBlocks(24, new ECB(34, 13))),
\r
398 new Version(23, new int[]{6, 30, 54, 74, 102},
\r
399 new ECBlocks(30, new ECB(4, 121),
\r
401 new ECBlocks(28, new ECB(4, 47),
\r
403 new ECBlocks(30, new ECB(11, 24),
\r
405 new ECBlocks(30, new ECB(16, 15),
\r
407 new Version(24, new int[]{6, 28, 54, 80, 106},
\r
408 new ECBlocks(30, new ECB(6, 117),
\r
410 new ECBlocks(28, new ECB(6, 45),
\r
412 new ECBlocks(30, new ECB(11, 24),
\r
414 new ECBlocks(30, new ECB(30, 16),
\r
416 new Version(25, new int[]{6, 32, 58, 84, 110},
\r
417 new ECBlocks(26, new ECB(8, 1061),
\r
419 new ECBlocks(28, new ECB(8, 47),
\r
421 new ECBlocks(30, new ECB(7, 24),
\r
423 new ECBlocks(30, new ECB(22, 15),
\r
425 new Version(26, new int[]{6, 30, 58, 86, 114},
\r
426 new ECBlocks(28, new ECB(10, 114),
\r
428 new ECBlocks(28, new ECB(19, 46),
\r
430 new ECBlocks(28, new ECB(28, 22),
\r
432 new ECBlocks(30, new ECB(33, 16),
\r
434 new Version(27, new int[]{6, 34, 62, 90, 118},
\r
435 new ECBlocks(30, new ECB(8, 122),
\r
437 new ECBlocks(28, new ECB(22, 45),
\r
439 new ECBlocks(30, new ECB(8, 23),
\r
441 new ECBlocks(30, new ECB(12, 15),
\r
443 new Version(28, new int[]{6, 26, 50, 74, 98, 122},
\r
444 new ECBlocks(30, new ECB(3, 117),
\r
446 new ECBlocks(28, new ECB(3, 45),
\r
448 new ECBlocks(30, new ECB(4, 24),
\r
450 new ECBlocks(30, new ECB(11, 15),
\r
452 new Version(29, new int[]{6, 30, 54, 78, 102, 126},
\r
453 new ECBlocks(30, new ECB(7, 116),
\r
455 new ECBlocks(28, new ECB(21, 45),
\r
457 new ECBlocks(30, new ECB(1, 23),
\r
459 new ECBlocks(30, new ECB(19, 15),
\r
461 new Version(30, new int[]{6, 26, 52, 78, 104, 130},
\r
462 new ECBlocks(30, new ECB(5, 115),
\r
464 new ECBlocks(28, new ECB(19, 47),
\r
466 new ECBlocks(30, new ECB(15, 24),
\r
468 new ECBlocks(30, new ECB(23, 15),
\r
470 new Version(31, new int[]{6, 30, 56, 82, 108, 134},
\r
471 new ECBlocks(30, new ECB(13, 115),
\r
473 new ECBlocks(28, new ECB(2, 46),
\r
475 new ECBlocks(30, new ECB(42, 24),
\r
477 new ECBlocks(30, new ECB(23, 15),
\r
479 new Version(32, new int[]{6, 34, 60, 86, 112, 138},
\r
480 new ECBlocks(30, new ECB(17, 115)),
\r
481 new ECBlocks(28, new ECB(10, 46),
\r
483 new ECBlocks(30, new ECB(10, 24),
\r
485 new ECBlocks(30, new ECB(19, 15),
\r
487 new Version(33, new int[]{6, 30, 58, 86, 114, 142},
\r
488 new ECBlocks(30, new ECB(17, 115),
\r
490 new ECBlocks(28, new ECB(14, 46),
\r
492 new ECBlocks(30, new ECB(29, 24),
\r
494 new ECBlocks(30, new ECB(11, 15),
\r
496 new Version(34, new int[]{6, 34, 62, 90, 118, 146},
\r
497 new ECBlocks(30, new ECB(13, 115),
\r
499 new ECBlocks(28, new ECB(14, 46),
\r
501 new ECBlocks(30, new ECB(44, 24),
\r
503 new ECBlocks(30, new ECB(59, 16),
\r
505 new Version(35, new int[]{6, 30, 54, 78, 102, 126, 150},
\r
506 new ECBlocks(30, new ECB(12, 121),
\r
508 new ECBlocks(28, new ECB(12, 47),
\r
510 new ECBlocks(30, new ECB(39, 24),
\r
512 new ECBlocks(30, new ECB(22, 15),
\r
514 new Version(36, new int[]{6, 24, 50, 76, 102, 128, 154},
\r
515 new ECBlocks(30, new ECB(6, 121),
\r
517 new ECBlocks(28, new ECB(6, 47),
\r
519 new ECBlocks(30, new ECB(46, 24),
\r
521 new ECBlocks(30, new ECB(2, 15),
\r
523 new Version(37, new int[]{6, 28, 54, 80, 106, 132, 158},
\r
524 new ECBlocks(30, new ECB(17, 122),
\r
526 new ECBlocks(28, new ECB(29, 46),
\r
528 new ECBlocks(30, new ECB(49, 24),
\r
530 new ECBlocks(30, new ECB(24, 15),
\r
532 new Version(38, new int[]{6, 32, 58, 84, 110, 136, 162},
\r
533 new ECBlocks(30, new ECB(4, 122),
\r
535 new ECBlocks(28, new ECB(13, 46),
\r
537 new ECBlocks(30, new ECB(48, 24),
\r
539 new ECBlocks(30, new ECB(42, 15),
\r
541 new Version(39, new int[]{6, 26, 54, 82, 110, 138, 166},
\r
542 new ECBlocks(30, new ECB(20, 117),
\r
544 new ECBlocks(28, new ECB(40, 47),
\r
546 new ECBlocks(30, new ECB(43, 24),
\r
548 new ECBlocks(30, new ECB(10, 15),
\r
550 new Version(40, new int[]{6, 30, 58, 86, 114, 142, 170},
\r
551 new ECBlocks(30, new ECB(19, 118),
\r
553 new ECBlocks(28, new ECB(18, 47),
\r
555 new ECBlocks(30, new ECB(34, 24),
\r
557 new ECBlocks(30, new ECB(20, 15),
\r