1
16
17 package com.google.zxing.qrcode.decoder;
18
19 import com.google.zxing.FormatException;
20 import com.google.zxing.common.BitMatrix;
21
22
27 public final class Version {
28
29
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
41 };
42
43 private static final Version[] VERSIONS = buildVersions();
44
45 private final int versionNumber;
46 private final int[] alignmentPatternCenters;
47 private final ECBlocks[] ecBlocks;
48 private final int totalCodewords;
49
50 private Version(int versionNumber,
51 int[] alignmentPatternCenters,
52 ECBlocks... ecBlocks) {
53 this.versionNumber = versionNumber;
54 this.alignmentPatternCenters = alignmentPatternCenters;
55 this.ecBlocks = ecBlocks;
56 int total = 0;
57 int ecCodewords = ecBlocks[0].getECCodewordsPerBlock();
58 ECB[] ecbArray = ecBlocks[0].getECBlocks();
59 for (ECB ecBlock : ecbArray) {
60 total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);
61 }
62 this.totalCodewords = total;
63 }
64
65 public int getVersionNumber() {
66 return versionNumber;
67 }
68
69 public int[] getAlignmentPatternCenters() {
70 return alignmentPatternCenters;
71 }
72
73 public int getTotalCodewords() {
74 return totalCodewords;
75 }
76
77 public int getDimensionForVersion() {
78 return 17 + 4 * versionNumber;
79 }
80
81 public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) {
82 return ecBlocks[ecLevel.ordinal()];
83 }
84
85
92 public static Version getProvisionalVersionForDimension(int dimension) throws FormatException {
93 if (dimension % 4 != 1) {
94 throw FormatException.getFormatInstance();
95 }
96 try {
97 return getVersionForNumber((dimension - 17) / 4);
98 } catch (IllegalArgumentException ignored) {
99 throw FormatException.getFormatInstance();
100 }
101 }
102
103 public static Version getVersionForNumber(int versionNumber) {
104 if (versionNumber < 1 || versionNumber > 40) {
105 throw new IllegalArgumentException();
106 }
107 return VERSIONS[versionNumber - 1];
108 }
109
110 static Version decodeVersionInformation(int versionBits) {
111 int bestDifference = Integer.MAX_VALUE;
112 int bestVersion = 0;
113 for (int i = 0; i < VERSION_DECODE_INFO.length; i++) {
114 int targetVersion = VERSION_DECODE_INFO[i];
115
116 if (targetVersion == versionBits) {
117 return getVersionForNumber(i + 7);
118 }
119
120
121 int bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion);
122 if (bitsDifference < bestDifference) {
123 bestVersion = i + 7;
124 bestDifference = bitsDifference;
125 }
126 }
127
128
129 if (bestDifference <= 3) {
130 return getVersionForNumber(bestVersion);
131 }
132
133 return null;
134 }
135
136
139 BitMatrix buildFunctionPattern() {
140 int dimension = getDimensionForVersion();
141 BitMatrix bitMatrix = new BitMatrix(dimension);
142
143
144 bitMatrix.setRegion(0, 0, 9, 9);
145
146 bitMatrix.setRegion(dimension - 8, 0, 8, 9);
147
148 bitMatrix.setRegion(0, dimension - 8, 9, 8);
149
150
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 bitMatrix.setRegion(alignmentPatternCenters[y] - 2, i, 5, 5);
157 }
158
159 }
160 }
161
162
163 bitMatrix.setRegion(6, 9, 1, dimension - 17);
164
165 bitMatrix.setRegion(9, 6, dimension - 17, 1);
166
167 if (versionNumber > 6) {
168
169 bitMatrix.setRegion(dimension - 11, 0, 3, 6);
170
171 bitMatrix.setRegion(0, dimension - 11, 6, 3);
172 }
173
174 return bitMatrix;
175 }
176
177
183 public static final class ECBlocks {
184 private final int ecCodewordsPerBlock;
185 private final ECB[] ecBlocks;
186
187 ECBlocks(int ecCodewordsPerBlock, ECB... ecBlocks) {
188 this.ecCodewordsPerBlock = ecCodewordsPerBlock;
189 this.ecBlocks = ecBlocks;
190 }
191
192 public int getECCodewordsPerBlock() {
193 return ecCodewordsPerBlock;
194 }
195
196 public int getNumBlocks() {
197 int total = 0;
198 for (ECB ecBlock : ecBlocks) {
199 total += ecBlock.getCount();
200 }
201 return total;
202 }
203
204 public int getTotalECCodewords() {
205 return ecCodewordsPerBlock * getNumBlocks();
206 }
207
208 public ECB[] getECBlocks() {
209 return ecBlocks;
210 }
211 }
212
213
218 public static final class ECB {
219 private final int count;
220 private final int dataCodewords;
221
222 ECB(int count, int dataCodewords) {
223 this.count = count;
224 this.dataCodewords = dataCodewords;
225 }
226
227 public int getCount() {
228 return count;
229 }
230
231 public int getDataCodewords() {
232 return dataCodewords;
233 }
234 }
235
236 @Override
237 public String toString() {
238 return String.valueOf(versionNumber);
239 }
240
241
244 private static Version[] buildVersions() {
245 return new Version[]{
246 new Version(1, new int[]{},
247 new ECBlocks(7, new ECB(1, 19)),
248 new ECBlocks(10, new ECB(1, 16)),
249 new ECBlocks(13, new ECB(1, 13)),
250 new ECBlocks(17, new ECB(1, 9))),
251 new Version(2, new int[]{6, 18},
252 new ECBlocks(10, new ECB(1, 34)),
253 new ECBlocks(16, new ECB(1, 28)),
254 new ECBlocks(22, new ECB(1, 22)),
255 new ECBlocks(28, new ECB(1, 16))),
256 new Version(3, new int[]{6, 22},
257 new ECBlocks(15, new ECB(1, 55)),
258 new ECBlocks(26, new ECB(1, 44)),
259 new ECBlocks(18, new ECB(2, 17)),
260 new ECBlocks(22, new ECB(2, 13))),
261 new Version(4, new int[]{6, 26},
262 new ECBlocks(20, new ECB(1, 80)),
263 new ECBlocks(18, new ECB(2, 32)),
264 new ECBlocks(26, new ECB(2, 24)),
265 new ECBlocks(16, new ECB(4, 9))),
266 new Version(5, new int[]{6, 30},
267 new ECBlocks(26, new ECB(1, 108)),
268 new ECBlocks(24, new ECB(2, 43)),
269 new ECBlocks(18, new ECB(2, 15),
270 new ECB(2, 16)),
271 new ECBlocks(22, new ECB(2, 11),
272 new ECB(2, 12))),
273 new Version(6, new int[]{6, 34},
274 new ECBlocks(18, new ECB(2, 68)),
275 new ECBlocks(16, new ECB(4, 27)),
276 new ECBlocks(24, new ECB(4, 19)),
277 new ECBlocks(28, new ECB(4, 15))),
278 new Version(7, new int[]{6, 22, 38},
279 new ECBlocks(20, new ECB(2, 78)),
280 new ECBlocks(18, new ECB(4, 31)),
281 new ECBlocks(18, new ECB(2, 14),
282 new ECB(4, 15)),
283 new ECBlocks(26, new ECB(4, 13),
284 new ECB(1, 14))),
285 new Version(8, new int[]{6, 24, 42},
286 new ECBlocks(24, new ECB(2, 97)),
287 new ECBlocks(22, new ECB(2, 38),
288 new ECB(2, 39)),
289 new ECBlocks(22, new ECB(4, 18),
290 new ECB(2, 19)),
291 new ECBlocks(26, new ECB(4, 14),
292 new ECB(2, 15))),
293 new Version(9, new int[]{6, 26, 46},
294 new ECBlocks(30, new ECB(2, 116)),
295 new ECBlocks(22, new ECB(3, 36),
296 new ECB(2, 37)),
297 new ECBlocks(20, new ECB(4, 16),
298 new ECB(4, 17)),
299 new ECBlocks(24, new ECB(4, 12),
300 new ECB(4, 13))),
301 new Version(10, new int[]{6, 28, 50},
302 new ECBlocks(18, new ECB(2, 68),
303 new ECB(2, 69)),
304 new ECBlocks(26, new ECB(4, 43),
305 new ECB(1, 44)),
306 new ECBlocks(24, new ECB(6, 19),
307 new ECB(2, 20)),
308 new ECBlocks(28, new ECB(6, 15),
309 new ECB(2, 16))),
310 new Version(11, new int[]{6, 30, 54},
311 new ECBlocks(20, new ECB(4, 81)),
312 new ECBlocks(30, new ECB(1, 50),
313 new ECB(4, 51)),
314 new ECBlocks(28, new ECB(4, 22),
315 new ECB(4, 23)),
316 new ECBlocks(24, new ECB(3, 12),
317 new ECB(8, 13))),
318 new Version(12, new int[]{6, 32, 58},
319 new ECBlocks(24, new ECB(2, 92),
320 new ECB(2, 93)),
321 new ECBlocks(22, new ECB(6, 36),
322 new ECB(2, 37)),
323 new ECBlocks(26, new ECB(4, 20),
324 new ECB(6, 21)),
325 new ECBlocks(28, new ECB(7, 14),
326 new ECB(4, 15))),
327 new Version(13, new int[]{6, 34, 62},
328 new ECBlocks(26, new ECB(4, 107)),
329 new ECBlocks(22, new ECB(8, 37),
330 new ECB(1, 38)),
331 new ECBlocks(24, new ECB(8, 20),
332 new ECB(4, 21)),
333 new ECBlocks(22, new ECB(12, 11),
334 new ECB(4, 12))),
335 new Version(14, new int[]{6, 26, 46, 66},
336 new ECBlocks(30, new ECB(3, 115),
337 new ECB(1, 116)),
338 new ECBlocks(24, new ECB(4, 40),
339 new ECB(5, 41)),
340 new ECBlocks(20, new ECB(11, 16),
341 new ECB(5, 17)),
342 new ECBlocks(24, new ECB(11, 12),
343 new ECB(5, 13))),
344 new Version(15, new int[]{6, 26, 48, 70},
345 new ECBlocks(22, new ECB(5, 87),
346 new ECB(1, 88)),
347 new ECBlocks(24, new ECB(5, 41),
348 new ECB(5, 42)),
349 new ECBlocks(30, new ECB(5, 24),
350 new ECB(7, 25)),
351 new ECBlocks(24, new ECB(11, 12),
352 new ECB(7, 13))),
353 new Version(16, new int[]{6, 26, 50, 74},
354 new ECBlocks(24, new ECB(5, 98),
355 new ECB(1, 99)),
356 new ECBlocks(28, new ECB(7, 45),
357 new ECB(3, 46)),
358 new ECBlocks(24, new ECB(15, 19),
359 new ECB(2, 20)),
360 new ECBlocks(30, new ECB(3, 15),
361 new ECB(13, 16))),
362 new Version(17, new int[]{6, 30, 54, 78},
363 new ECBlocks(28, new ECB(1, 107),
364 new ECB(5, 108)),
365 new ECBlocks(28, new ECB(10, 46),
366 new ECB(1, 47)),
367 new ECBlocks(28, new ECB(1, 22),
368 new ECB(15, 23)),
369 new ECBlocks(28, new ECB(2, 14),
370 new ECB(17, 15))),
371 new Version(18, new int[]{6, 30, 56, 82},
372 new ECBlocks(30, new ECB(5, 120),
373 new ECB(1, 121)),
374 new ECBlocks(26, new ECB(9, 43),
375 new ECB(4, 44)),
376 new ECBlocks(28, new ECB(17, 22),
377 new ECB(1, 23)),
378 new ECBlocks(28, new ECB(2, 14),
379 new ECB(19, 15))),
380 new Version(19, new int[]{6, 30, 58, 86},
381 new ECBlocks(28, new ECB(3, 113),
382 new ECB(4, 114)),
383 new ECBlocks(26, new ECB(3, 44),
384 new ECB(11, 45)),
385 new ECBlocks(26, new ECB(17, 21),
386 new ECB(4, 22)),
387 new ECBlocks(26, new ECB(9, 13),
388 new ECB(16, 14))),
389 new Version(20, new int[]{6, 34, 62, 90},
390 new ECBlocks(28, new ECB(3, 107),
391 new ECB(5, 108)),
392 new ECBlocks(26, new ECB(3, 41),
393 new ECB(13, 42)),
394 new ECBlocks(30, new ECB(15, 24),
395 new ECB(5, 25)),
396 new ECBlocks(28, new ECB(15, 15),
397 new ECB(10, 16))),
398 new Version(21, new int[]{6, 28, 50, 72, 94},
399 new ECBlocks(28, new ECB(4, 116),
400 new ECB(4, 117)),
401 new ECBlocks(26, new ECB(17, 42)),
402 new ECBlocks(28, new ECB(17, 22),
403 new ECB(6, 23)),
404 new ECBlocks(30, new ECB(19, 16),
405 new ECB(6, 17))),
406 new Version(22, new int[]{6, 26, 50, 74, 98},
407 new ECBlocks(28, new ECB(2, 111),
408 new ECB(7, 112)),
409 new ECBlocks(28, new ECB(17, 46)),
410 new ECBlocks(30, new ECB(7, 24),
411 new ECB(16, 25)),
412 new ECBlocks(24, new ECB(34, 13))),
413 new Version(23, new int[]{6, 30, 54, 78, 102},
414 new ECBlocks(30, new ECB(4, 121),
415 new ECB(5, 122)),
416 new ECBlocks(28, new ECB(4, 47),
417 new ECB(14, 48)),
418 new ECBlocks(30, new ECB(11, 24),
419 new ECB(14, 25)),
420 new ECBlocks(30, new ECB(16, 15),
421 new ECB(14, 16))),
422 new Version(24, new int[]{6, 28, 54, 80, 106},
423 new ECBlocks(30, new ECB(6, 117),
424 new ECB(4, 118)),
425 new ECBlocks(28, new ECB(6, 45),
426 new ECB(14, 46)),
427 new ECBlocks(30, new ECB(11, 24),
428 new ECB(16, 25)),
429 new ECBlocks(30, new ECB(30, 16),
430 new ECB(2, 17))),
431 new Version(25, new int[]{6, 32, 58, 84, 110},
432 new ECBlocks(26, new ECB(8, 106),
433 new ECB(4, 107)),
434 new ECBlocks(28, new ECB(8, 47),
435 new ECB(13, 48)),
436 new ECBlocks(30, new ECB(7, 24),
437 new ECB(22, 25)),
438 new ECBlocks(30, new ECB(22, 15),
439 new ECB(13, 16))),
440 new Version(26, new int[]{6, 30, 58, 86, 114},
441 new ECBlocks(28, new ECB(10, 114),
442 new ECB(2, 115)),
443 new ECBlocks(28, new ECB(19, 46),
444 new ECB(4, 47)),
445 new ECBlocks(28, new ECB(28, 22),
446 new ECB(6, 23)),
447 new ECBlocks(30, new ECB(33, 16),
448 new ECB(4, 17))),
449 new Version(27, new int[]{6, 34, 62, 90, 118},
450 new ECBlocks(30, new ECB(8, 122),
451 new ECB(4, 123)),
452 new ECBlocks(28, new ECB(22, 45),
453 new ECB(3, 46)),
454 new ECBlocks(30, new ECB(8, 23),
455 new ECB(26, 24)),
456 new ECBlocks(30, new ECB(12, 15),
457 new ECB(28, 16))),
458 new Version(28, new int[]{6, 26, 50, 74, 98, 122},
459 new ECBlocks(30, new ECB(3, 117),
460 new ECB(10, 118)),
461 new ECBlocks(28, new ECB(3, 45),
462 new ECB(23, 46)),
463 new ECBlocks(30, new ECB(4, 24),
464 new ECB(31, 25)),
465 new ECBlocks(30, new ECB(11, 15),
466 new ECB(31, 16))),
467 new Version(29, new int[]{6, 30, 54, 78, 102, 126},
468 new ECBlocks(30, new ECB(7, 116),
469 new ECB(7, 117)),
470 new ECBlocks(28, new ECB(21, 45),
471 new ECB(7, 46)),
472 new ECBlocks(30, new ECB(1, 23),
473 new ECB(37, 24)),
474 new ECBlocks(30, new ECB(19, 15),
475 new ECB(26, 16))),
476 new Version(30, new int[]{6, 26, 52, 78, 104, 130},
477 new ECBlocks(30, new ECB(5, 115),
478 new ECB(10, 116)),
479 new ECBlocks(28, new ECB(19, 47),
480 new ECB(10, 48)),
481 new ECBlocks(30, new ECB(15, 24),
482 new ECB(25, 25)),
483 new ECBlocks(30, new ECB(23, 15),
484 new ECB(25, 16))),
485 new Version(31, new int[]{6, 30, 56, 82, 108, 134},
486 new ECBlocks(30, new ECB(13, 115),
487 new ECB(3, 116)),
488 new ECBlocks(28, new ECB(2, 46),
489 new ECB(29, 47)),
490 new ECBlocks(30, new ECB(42, 24),
491 new ECB(1, 25)),
492 new ECBlocks(30, new ECB(23, 15),
493 new ECB(28, 16))),
494 new Version(32, new int[]{6, 34, 60, 86, 112, 138},
495 new ECBlocks(30, new ECB(17, 115)),
496 new ECBlocks(28, new ECB(10, 46),
497 new ECB(23, 47)),
498 new ECBlocks(30, new ECB(10, 24),
499 new ECB(35, 25)),
500 new ECBlocks(30, new ECB(19, 15),
501 new ECB(35, 16))),
502 new Version(33, new int[]{6, 30, 58, 86, 114, 142},
503 new ECBlocks(30, new ECB(17, 115),
504 new ECB(1, 116)),
505 new ECBlocks(28, new ECB(14, 46),
506 new ECB(21, 47)),
507 new ECBlocks(30, new ECB(29, 24),
508 new ECB(19, 25)),
509 new ECBlocks(30, new ECB(11, 15),
510 new ECB(46, 16))),
511 new Version(34, new int[]{6, 34, 62, 90, 118, 146},
512 new ECBlocks(30, new ECB(13, 115),
513 new ECB(6, 116)),
514 new ECBlocks(28, new ECB(14, 46),
515 new ECB(23, 47)),
516 new ECBlocks(30, new ECB(44, 24),
517 new ECB(7, 25)),
518 new ECBlocks(30, new ECB(59, 16),
519 new ECB(1, 17))),
520 new Version(35, new int[]{6, 30, 54, 78, 102, 126, 150},
521 new ECBlocks(30, new ECB(12, 121),
522 new ECB(7, 122)),
523 new ECBlocks(28, new ECB(12, 47),
524 new ECB(26, 48)),
525 new ECBlocks(30, new ECB(39, 24),
526 new ECB(14, 25)),
527 new ECBlocks(30, new ECB(22, 15),
528 new ECB(41, 16))),
529 new Version(36, new int[]{6, 24, 50, 76, 102, 128, 154},
530 new ECBlocks(30, new ECB(6, 121),
531 new ECB(14, 122)),
532 new ECBlocks(28, new ECB(6, 47),
533 new ECB(34, 48)),
534 new ECBlocks(30, new ECB(46, 24),
535 new ECB(10, 25)),
536 new ECBlocks(30, new ECB(2, 15),
537 new ECB(64, 16))),
538 new Version(37, new int[]{6, 28, 54, 80, 106, 132, 158},
539 new ECBlocks(30, new ECB(17, 122),
540 new ECB(4, 123)),
541 new ECBlocks(28, new ECB(29, 46),
542 new ECB(14, 47)),
543 new ECBlocks(30, new ECB(49, 24),
544 new ECB(10, 25)),
545 new ECBlocks(30, new ECB(24, 15),
546 new ECB(46, 16))),
547 new Version(38, new int[]{6, 32, 58, 84, 110, 136, 162},
548 new ECBlocks(30, new ECB(4, 122),
549 new ECB(18, 123)),
550 new ECBlocks(28, new ECB(13, 46),
551 new ECB(32, 47)),
552 new ECBlocks(30, new ECB(48, 24),
553 new ECB(14, 25)),
554 new ECBlocks(30, new ECB(42, 15),
555 new ECB(32, 16))),
556 new Version(39, new int[]{6, 26, 54, 82, 110, 138, 166},
557 new ECBlocks(30, new ECB(20, 117),
558 new ECB(4, 118)),
559 new ECBlocks(28, new ECB(40, 47),
560 new ECB(7, 48)),
561 new ECBlocks(30, new ECB(43, 24),
562 new ECB(22, 25)),
563 new ECBlocks(30, new ECB(10, 15),
564 new ECB(67, 16))),
565 new Version(40, new int[]{6, 30, 58, 86, 114, 142, 170},
566 new ECBlocks(30, new ECB(19, 118),
567 new ECB(6, 119)),
568 new ECBlocks(28, new ECB(18, 47),
569 new ECB(31, 48)),
570 new ECBlocks(30, new ECB(34, 24),
571 new ECB(34, 25)),
572 new ECBlocks(30, new ECB(20, 15),
573 new ECB(61, 16)))
574 };
575 }
576
577 }
578