]> Pileus Git - ~andy/freeotp/blob - src/com/google/zxing/qrcode/decoder/Version.java
Add native camera support
[~andy/freeotp] / src / com / google / zxing / qrcode / decoder / Version.java
1 /*
2  * Copyright 2007 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.decoder;
18
19 import com.google.zxing.FormatException;
20 import com.google.zxing.common.BitMatrix;
21
22 /**
23  * See ISO 18004:2006 Annex D
24  *
25  * @author Sean Owen
26  */
27 public final class Version {
28
29   /**
30    * See ISO 18004:2006 Annex D.
31    * Element i represents the raw version bits that specify version i + 7
32    */
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   /**
86    * <p>Deduces version information purely from QR Code dimensions.</p>
87    *
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
91    */
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) >> 2);
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       // Do the version info bits match exactly? done.
116       if (targetVersion == versionBits) {
117         return getVersionForNumber(i + 7);
118       }
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) {
123         bestVersion = i + 7;
124         bestDifference = bitsDifference;
125       }
126     }
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);
131     }
132     // If we didn't find a close enough match, fail
133     return null;
134   }
135
136   /**
137    * See ISO 18004:2006 Annex E
138    */
139   BitMatrix buildFunctionPattern() {
140     int dimension = getDimensionForVersion();
141     BitMatrix bitMatrix = new BitMatrix(dimension);
142
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);
149
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
157           continue;
158         }
159         bitMatrix.setRegion(alignmentPatternCenters[y] - 2, i, 5, 5);
160       }
161     }
162
163     // Vertical timing pattern
164     bitMatrix.setRegion(6, 9, 1, dimension - 17);
165     // Horizontal timing pattern
166     bitMatrix.setRegion(9, 6, dimension - 17, 1);
167
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);
173     }
174
175     return bitMatrix;
176   }
177
178   /**
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>
183    */
184   public static final class ECBlocks {
185     private final int ecCodewordsPerBlock;
186     private final ECB[] ecBlocks;
187
188     ECBlocks(int ecCodewordsPerBlock, ECB... ecBlocks) {
189       this.ecCodewordsPerBlock = ecCodewordsPerBlock;
190       this.ecBlocks = ecBlocks;
191     }
192
193     public int getECCodewordsPerBlock() {
194       return ecCodewordsPerBlock;
195     }
196
197     public int getNumBlocks() {
198       int total = 0;
199       for (ECB ecBlock : ecBlocks) {
200         total += ecBlock.getCount();
201       }
202       return total;
203     }
204
205     public int getTotalECCodewords() {
206       return ecCodewordsPerBlock * getNumBlocks();
207     }
208
209     public ECB[] getECBlocks() {
210       return ecBlocks;
211     }
212   }
213
214   /**
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>
218    */
219   public static final class ECB {
220     private final int count;
221     private final int dataCodewords;
222
223     ECB(int count, int dataCodewords) {
224       this.count = count;
225       this.dataCodewords = dataCodewords;
226     }
227
228     public int getCount() {
229       return count;
230     }
231
232     public int getDataCodewords() {
233       return dataCodewords;
234     }
235   }
236
237   @Override
238   public String toString() {
239     return String.valueOf(versionNumber);
240   }
241
242   /**
243    * See ISO 18004:2006 6.5.1 Table 9
244    */
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),
271                 new ECB(2, 16)),
272             new ECBlocks(22, new ECB(2, 11),
273                 new ECB(2, 12))),
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),
283                 new ECB(4, 15)),
284             new ECBlocks(26, new ECB(4, 13),
285                 new ECB(1, 14))),
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),
289                 new ECB(2, 39)),
290             new ECBlocks(22, new ECB(4, 18),
291                 new ECB(2, 19)),
292             new ECBlocks(26, new ECB(4, 14),
293                 new ECB(2, 15))),
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),
297                 new ECB(2, 37)),
298             new ECBlocks(20, new ECB(4, 16),
299                 new ECB(4, 17)),
300             new ECBlocks(24, new ECB(4, 12),
301                 new ECB(4, 13))),
302         new Version(10, new int[]{6, 28, 50},
303             new ECBlocks(18, new ECB(2, 68),
304                 new ECB(2, 69)),
305             new ECBlocks(26, new ECB(4, 43),
306                 new ECB(1, 44)),
307             new ECBlocks(24, new ECB(6, 19),
308                 new ECB(2, 20)),
309             new ECBlocks(28, new ECB(6, 15),
310                 new ECB(2, 16))),
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),
314                 new ECB(4, 51)),
315             new ECBlocks(28, new ECB(4, 22),
316                 new ECB(4, 23)),
317             new ECBlocks(24, new ECB(3, 12),
318                 new ECB(8, 13))),
319         new Version(12, new int[]{6, 32, 58},
320             new ECBlocks(24, new ECB(2, 92),
321                 new ECB(2, 93)),
322             new ECBlocks(22, new ECB(6, 36),
323                 new ECB(2, 37)),
324             new ECBlocks(26, new ECB(4, 20),
325                 new ECB(6, 21)),
326             new ECBlocks(28, new ECB(7, 14),
327                 new ECB(4, 15))),
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),
331                 new ECB(1, 38)),
332             new ECBlocks(24, new ECB(8, 20),
333                 new ECB(4, 21)),
334             new ECBlocks(22, new ECB(12, 11),
335                 new ECB(4, 12))),
336         new Version(14, new int[]{6, 26, 46, 66},
337             new ECBlocks(30, new ECB(3, 115),
338                 new ECB(1, 116)),
339             new ECBlocks(24, new ECB(4, 40),
340                 new ECB(5, 41)),
341             new ECBlocks(20, new ECB(11, 16),
342                 new ECB(5, 17)),
343             new ECBlocks(24, new ECB(11, 12),
344                 new ECB(5, 13))),
345         new Version(15, new int[]{6, 26, 48, 70},
346             new ECBlocks(22, new ECB(5, 87),
347                 new ECB(1, 88)),
348             new ECBlocks(24, new ECB(5, 41),
349                 new ECB(5, 42)),
350             new ECBlocks(30, new ECB(5, 24),
351                 new ECB(7, 25)),
352             new ECBlocks(24, new ECB(11, 12),
353                 new ECB(7, 13))),
354         new Version(16, new int[]{6, 26, 50, 74},
355             new ECBlocks(24, new ECB(5, 98),
356                 new ECB(1, 99)),
357             new ECBlocks(28, new ECB(7, 45),
358                 new ECB(3, 46)),
359             new ECBlocks(24, new ECB(15, 19),
360                 new ECB(2, 20)),
361             new ECBlocks(30, new ECB(3, 15),
362                 new ECB(13, 16))),
363         new Version(17, new int[]{6, 30, 54, 78},
364             new ECBlocks(28, new ECB(1, 107),
365                 new ECB(5, 108)),
366             new ECBlocks(28, new ECB(10, 46),
367                 new ECB(1, 47)),
368             new ECBlocks(28, new ECB(1, 22),
369                 new ECB(15, 23)),
370             new ECBlocks(28, new ECB(2, 14),
371                 new ECB(17, 15))),
372         new Version(18, new int[]{6, 30, 56, 82},
373             new ECBlocks(30, new ECB(5, 120),
374                 new ECB(1, 121)),
375             new ECBlocks(26, new ECB(9, 43),
376                 new ECB(4, 44)),
377             new ECBlocks(28, new ECB(17, 22),
378                 new ECB(1, 23)),
379             new ECBlocks(28, new ECB(2, 14),
380                 new ECB(19, 15))),
381         new Version(19, new int[]{6, 30, 58, 86},
382             new ECBlocks(28, new ECB(3, 113),
383                 new ECB(4, 114)),
384             new ECBlocks(26, new ECB(3, 44),
385                 new ECB(11, 45)),
386             new ECBlocks(26, new ECB(17, 21),
387                 new ECB(4, 22)),
388             new ECBlocks(26, new ECB(9, 13),
389                 new ECB(16, 14))),
390         new Version(20, new int[]{6, 34, 62, 90},
391             new ECBlocks(28, new ECB(3, 107),
392                 new ECB(5, 108)),
393             new ECBlocks(26, new ECB(3, 41),
394                 new ECB(13, 42)),
395             new ECBlocks(30, new ECB(15, 24),
396                 new ECB(5, 25)),
397             new ECBlocks(28, new ECB(15, 15),
398                 new ECB(10, 16))),
399         new Version(21, new int[]{6, 28, 50, 72, 94},
400             new ECBlocks(28, new ECB(4, 116),
401                 new ECB(4, 117)),
402             new ECBlocks(26, new ECB(17, 42)),
403             new ECBlocks(28, new ECB(17, 22),
404                 new ECB(6, 23)),
405             new ECBlocks(30, new ECB(19, 16),
406                 new ECB(6, 17))),
407         new Version(22, new int[]{6, 26, 50, 74, 98},
408             new ECBlocks(28, new ECB(2, 111),
409                 new ECB(7, 112)),
410             new ECBlocks(28, new ECB(17, 46)),
411             new ECBlocks(30, new ECB(7, 24),
412                 new ECB(16, 25)),
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),
416                 new ECB(5, 122)),
417             new ECBlocks(28, new ECB(4, 47),
418                 new ECB(14, 48)),
419             new ECBlocks(30, new ECB(11, 24),
420                 new ECB(14, 25)),
421             new ECBlocks(30, new ECB(16, 15),
422                 new ECB(14, 16))),
423         new Version(24, new int[]{6, 28, 54, 80, 106},
424             new ECBlocks(30, new ECB(6, 117),
425                 new ECB(4, 118)),
426             new ECBlocks(28, new ECB(6, 45),
427                 new ECB(14, 46)),
428             new ECBlocks(30, new ECB(11, 24),
429                 new ECB(16, 25)),
430             new ECBlocks(30, new ECB(30, 16),
431                 new ECB(2, 17))),
432         new Version(25, new int[]{6, 32, 58, 84, 110},
433             new ECBlocks(26, new ECB(8, 106),
434                 new ECB(4, 107)),
435             new ECBlocks(28, new ECB(8, 47),
436                 new ECB(13, 48)),
437             new ECBlocks(30, new ECB(7, 24),
438                 new ECB(22, 25)),
439             new ECBlocks(30, new ECB(22, 15),
440                 new ECB(13, 16))),
441         new Version(26, new int[]{6, 30, 58, 86, 114},
442             new ECBlocks(28, new ECB(10, 114),
443                 new ECB(2, 115)),
444             new ECBlocks(28, new ECB(19, 46),
445                 new ECB(4, 47)),
446             new ECBlocks(28, new ECB(28, 22),
447                 new ECB(6, 23)),
448             new ECBlocks(30, new ECB(33, 16),
449                 new ECB(4, 17))),
450         new Version(27, new int[]{6, 34, 62, 90, 118},
451             new ECBlocks(30, new ECB(8, 122),
452                 new ECB(4, 123)),
453             new ECBlocks(28, new ECB(22, 45),
454                 new ECB(3, 46)),
455             new ECBlocks(30, new ECB(8, 23),
456                 new ECB(26, 24)),
457             new ECBlocks(30, new ECB(12, 15),
458                 new ECB(28, 16))),
459         new Version(28, new int[]{6, 26, 50, 74, 98, 122},
460             new ECBlocks(30, new ECB(3, 117),
461                 new ECB(10, 118)),
462             new ECBlocks(28, new ECB(3, 45),
463                 new ECB(23, 46)),
464             new ECBlocks(30, new ECB(4, 24),
465                 new ECB(31, 25)),
466             new ECBlocks(30, new ECB(11, 15),
467                 new ECB(31, 16))),
468         new Version(29, new int[]{6, 30, 54, 78, 102, 126},
469             new ECBlocks(30, new ECB(7, 116),
470                 new ECB(7, 117)),
471             new ECBlocks(28, new ECB(21, 45),
472                 new ECB(7, 46)),
473             new ECBlocks(30, new ECB(1, 23),
474                 new ECB(37, 24)),
475             new ECBlocks(30, new ECB(19, 15),
476                 new ECB(26, 16))),
477         new Version(30, new int[]{6, 26, 52, 78, 104, 130},
478             new ECBlocks(30, new ECB(5, 115),
479                 new ECB(10, 116)),
480             new ECBlocks(28, new ECB(19, 47),
481                 new ECB(10, 48)),
482             new ECBlocks(30, new ECB(15, 24),
483                 new ECB(25, 25)),
484             new ECBlocks(30, new ECB(23, 15),
485                 new ECB(25, 16))),
486         new Version(31, new int[]{6, 30, 56, 82, 108, 134},
487             new ECBlocks(30, new ECB(13, 115),
488                 new ECB(3, 116)),
489             new ECBlocks(28, new ECB(2, 46),
490                 new ECB(29, 47)),
491             new ECBlocks(30, new ECB(42, 24),
492                 new ECB(1, 25)),
493             new ECBlocks(30, new ECB(23, 15),
494                 new ECB(28, 16))),
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),
498                 new ECB(23, 47)),
499             new ECBlocks(30, new ECB(10, 24),
500                 new ECB(35, 25)),
501             new ECBlocks(30, new ECB(19, 15),
502                 new ECB(35, 16))),
503         new Version(33, new int[]{6, 30, 58, 86, 114, 142},
504             new ECBlocks(30, new ECB(17, 115),
505                 new ECB(1, 116)),
506             new ECBlocks(28, new ECB(14, 46),
507                 new ECB(21, 47)),
508             new ECBlocks(30, new ECB(29, 24),
509                 new ECB(19, 25)),
510             new ECBlocks(30, new ECB(11, 15),
511                 new ECB(46, 16))),
512         new Version(34, new int[]{6, 34, 62, 90, 118, 146},
513             new ECBlocks(30, new ECB(13, 115),
514                 new ECB(6, 116)),
515             new ECBlocks(28, new ECB(14, 46),
516                 new ECB(23, 47)),
517             new ECBlocks(30, new ECB(44, 24),
518                 new ECB(7, 25)),
519             new ECBlocks(30, new ECB(59, 16),
520                 new ECB(1, 17))),
521         new Version(35, new int[]{6, 30, 54, 78, 102, 126, 150},
522             new ECBlocks(30, new ECB(12, 121),
523                 new ECB(7, 122)),
524             new ECBlocks(28, new ECB(12, 47),
525                 new ECB(26, 48)),
526             new ECBlocks(30, new ECB(39, 24),
527                 new ECB(14, 25)),
528             new ECBlocks(30, new ECB(22, 15),
529                 new ECB(41, 16))),
530         new Version(36, new int[]{6, 24, 50, 76, 102, 128, 154},
531             new ECBlocks(30, new ECB(6, 121),
532                 new ECB(14, 122)),
533             new ECBlocks(28, new ECB(6, 47),
534                 new ECB(34, 48)),
535             new ECBlocks(30, new ECB(46, 24),
536                 new ECB(10, 25)),
537             new ECBlocks(30, new ECB(2, 15),
538                 new ECB(64, 16))),
539         new Version(37, new int[]{6, 28, 54, 80, 106, 132, 158},
540             new ECBlocks(30, new ECB(17, 122),
541                 new ECB(4, 123)),
542             new ECBlocks(28, new ECB(29, 46),
543                 new ECB(14, 47)),
544             new ECBlocks(30, new ECB(49, 24),
545                 new ECB(10, 25)),
546             new ECBlocks(30, new ECB(24, 15),
547                 new ECB(46, 16))),
548         new Version(38, new int[]{6, 32, 58, 84, 110, 136, 162},
549             new ECBlocks(30, new ECB(4, 122),
550                 new ECB(18, 123)),
551             new ECBlocks(28, new ECB(13, 46),
552                 new ECB(32, 47)),
553             new ECBlocks(30, new ECB(48, 24),
554                 new ECB(14, 25)),
555             new ECBlocks(30, new ECB(42, 15),
556                 new ECB(32, 16))),
557         new Version(39, new int[]{6, 26, 54, 82, 110, 138, 166},
558             new ECBlocks(30, new ECB(20, 117),
559                 new ECB(4, 118)),
560             new ECBlocks(28, new ECB(40, 47),
561                 new ECB(7, 48)),
562             new ECBlocks(30, new ECB(43, 24),
563                 new ECB(22, 25)),
564             new ECBlocks(30, new ECB(10, 15),
565                 new ECB(67, 16))),
566         new Version(40, new int[]{6, 30, 58, 86, 114, 142, 170},
567             new ECBlocks(30, new ECB(19, 118),
568                 new ECB(6, 119)),
569             new ECBlocks(28, new ECB(18, 47),
570                 new ECB(31, 48)),
571             new ECBlocks(30, new ECB(34, 24),
572                 new ECB(34, 25)),
573             new ECBlocks(30, new ECB(20, 15),
574                 new ECB(61, 16)))
575     };
576   }
577
578 }