001/* 002 * Copyright 2007 ZXing authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.itextpdf.text.pdf.qrcode; 018 019/** 020 * See ISO 18004:2006 Annex D 021 * 022 * @author Sean Owen 023 * @since 5.0.2 024 */ 025public final class Version { 026 027 /** 028 * See ISO 18004:2006 Annex D. 029 * Element i represents the raw version bits that specify version i + 7 030 */ 031 private static final int[] VERSION_DECODE_INFO = { 032 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, 033 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78, 034 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, 035 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, 036 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, 037 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B, 038 0x2542E, 0x26A64, 0x27541, 0x28C69 039 }; 040 041 private static final Version[] VERSIONS = buildVersions(); 042 043 private final int versionNumber; 044 private final int[] alignmentPatternCenters; 045 private final ECBlocks[] ecBlocks; 046 private final int totalCodewords; 047 048 private Version(int versionNumber, 049 int[] alignmentPatternCenters, 050 ECBlocks ecBlocks1, 051 ECBlocks ecBlocks2, 052 ECBlocks ecBlocks3, 053 ECBlocks ecBlocks4) { 054 this.versionNumber = versionNumber; 055 this.alignmentPatternCenters = alignmentPatternCenters; 056 this.ecBlocks = new ECBlocks[]{ecBlocks1, ecBlocks2, ecBlocks3, ecBlocks4}; 057 int total = 0; 058 int ecCodewords = ecBlocks1.getECCodewordsPerBlock(); 059 ECB[] ecbArray = ecBlocks1.getECBlocks(); 060 for (int i = 0; i < ecbArray.length; i++) { 061 ECB ecBlock = ecbArray[i]; 062 total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords); 063 } 064 this.totalCodewords = total; 065 } 066 067 public int getVersionNumber() { 068 return versionNumber; 069 } 070 071 public int[] getAlignmentPatternCenters() { 072 return alignmentPatternCenters; 073 } 074 075 public int getTotalCodewords() { 076 return totalCodewords; 077 } 078 079 public int getDimensionForVersion() { 080 return 17 + 4 * versionNumber; 081 } 082 083 public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) { 084 return ecBlocks[ecLevel.ordinal()]; 085 } 086 087 /** 088 * <p>Deduces version information purely from QR Code dimensions.</p> 089 * 090 * @param dimension dimension in modules 091 * @return {@link Version} for a QR Code of that dimension 092 * @throws FormatException if dimension is not 1 mod 4 093 */ 094 public static Version getProvisionalVersionForDimension(int dimension) { 095 if (dimension % 4 != 1) { 096 throw new IllegalArgumentException(); 097 } 098 try { 099 return getVersionForNumber((dimension - 17) >> 2); 100 } catch (IllegalArgumentException iae) { 101 throw iae; 102 } 103 } 104 105 public static Version getVersionForNumber(int versionNumber) { 106 if (versionNumber < 1 || versionNumber > 40) { 107 throw new IllegalArgumentException(); 108 } 109 return VERSIONS[versionNumber - 1]; 110 } 111 112 static Version decodeVersionInformation(int versionBits) { 113 int bestDifference = Integer.MAX_VALUE; 114 int bestVersion = 0; 115 for (int i = 0; i < VERSION_DECODE_INFO.length; i++) { 116 int targetVersion = VERSION_DECODE_INFO[i]; 117 // Do the version info bits match exactly? done. 118 if (targetVersion == versionBits) { 119 return getVersionForNumber(i + 7); 120 } 121 // Otherwise see if this is the closest to a real version info bit string 122 // we have seen so far 123 int bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion); 124 if (bitsDifference < bestDifference) { 125 bestVersion = i + 7; 126 bestDifference = bitsDifference; 127 } 128 } 129 // We can tolerate up to 3 bits of error since no two version info codewords will 130 // differ in less than 4 bits. 131 if (bestDifference <= 3) { 132 return getVersionForNumber(bestVersion); 133 } 134 // If we didn't find a close enough match, fail 135 return null; 136 } 137 138 /** 139 * See ISO 18004:2006 Annex E 140 */ 141 BitMatrix buildFunctionPattern() { 142 int dimension = getDimensionForVersion(); 143 BitMatrix bitMatrix = new BitMatrix(dimension); 144 145 // Top left finder pattern + separator + format 146 bitMatrix.setRegion(0, 0, 9, 9); 147 // Top right finder pattern + separator + format 148 bitMatrix.setRegion(dimension - 8, 0, 8, 9); 149 // Bottom left finder pattern + separator + format 150 bitMatrix.setRegion(0, dimension - 8, 9, 8); 151 152 // Alignment patterns 153 int max = alignmentPatternCenters.length; 154 for (int x = 0; x < max; x++) { 155 int i = alignmentPatternCenters[x] - 2; 156 for (int y = 0; y < max; y++) { 157 if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) { 158 // No alignment patterns near the three finder paterns 159 continue; 160 } 161 bitMatrix.setRegion(alignmentPatternCenters[y] - 2, i, 5, 5); 162 } 163 } 164 165 // Vertical timing pattern 166 bitMatrix.setRegion(6, 9, 1, dimension - 17); 167 // Horizontal timing pattern 168 bitMatrix.setRegion(9, 6, dimension - 17, 1); 169 170 if (versionNumber > 6) { 171 // Version info, top right 172 bitMatrix.setRegion(dimension - 11, 0, 3, 6); 173 // Version info, bottom left 174 bitMatrix.setRegion(0, dimension - 11, 6, 3); 175 } 176 177 return bitMatrix; 178 } 179 180 /** 181 * <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will 182 * use blocks of differing sizes within one version, so, this encapsulates the parameters for 183 * each set of blocks. It also holds the number of error-correction codewords per block since it 184 * will be the same across all blocks within one version.</p> 185 */ 186 public static final class ECBlocks { 187 private final int ecCodewordsPerBlock; 188 private final ECB[] ecBlocks; 189 190 ECBlocks(int ecCodewordsPerBlock, ECB ecBlocks) { 191 this.ecCodewordsPerBlock = ecCodewordsPerBlock; 192 this.ecBlocks = new ECB[]{ecBlocks}; 193 } 194 195 ECBlocks(int ecCodewordsPerBlock, ECB ecBlocks1, ECB ecBlocks2) { 196 this.ecCodewordsPerBlock = ecCodewordsPerBlock; 197 this.ecBlocks = new ECB[]{ecBlocks1, ecBlocks2}; 198 } 199 200 public int getECCodewordsPerBlock() { 201 return ecCodewordsPerBlock; 202 } 203 204 public int getNumBlocks() { 205 int total = 0; 206 for (int i = 0; i < ecBlocks.length; i++) { 207 total += ecBlocks[i].getCount(); 208 } 209 return total; 210 } 211 212 public int getTotalECCodewords() { 213 return ecCodewordsPerBlock * getNumBlocks(); 214 } 215 216 public ECB[] getECBlocks() { 217 return ecBlocks; 218 } 219 } 220 221 /** 222 * <p>Encapsualtes the parameters for one error-correction block in one symbol version. 223 * This includes the number of data codewords, and the number of times a block with these 224 * parameters is used consecutively in the QR code version's format.</p> 225 */ 226 public static final class ECB { 227 private final int count; 228 private final int dataCodewords; 229 230 ECB(int count, int dataCodewords) { 231 this.count = count; 232 this.dataCodewords = dataCodewords; 233 } 234 235 public int getCount() { 236 return count; 237 } 238 239 public int getDataCodewords() { 240 return dataCodewords; 241 } 242 } 243 244 public String toString() { 245 return String.valueOf(versionNumber); 246 } 247 248 /** 249 * See ISO 18004:2006 6.5.1 Table 9 250 */ 251 private static Version[] buildVersions() { 252 return new Version[]{ 253 new Version(1, new int[]{}, 254 new ECBlocks(7, new ECB(1, 19)), 255 new ECBlocks(10, new ECB(1, 16)), 256 new ECBlocks(13, new ECB(1, 13)), 257 new ECBlocks(17, new ECB(1, 9))), 258 new Version(2, new int[]{6, 18}, 259 new ECBlocks(10, new ECB(1, 34)), 260 new ECBlocks(16, new ECB(1, 28)), 261 new ECBlocks(22, new ECB(1, 22)), 262 new ECBlocks(28, new ECB(1, 16))), 263 new Version(3, new int[]{6, 22}, 264 new ECBlocks(15, new ECB(1, 55)), 265 new ECBlocks(26, new ECB(1, 44)), 266 new ECBlocks(18, new ECB(2, 17)), 267 new ECBlocks(22, new ECB(2, 13))), 268 new Version(4, new int[]{6, 26}, 269 new ECBlocks(20, new ECB(1, 80)), 270 new ECBlocks(18, new ECB(2, 32)), 271 new ECBlocks(26, new ECB(2, 24)), 272 new ECBlocks(16, new ECB(4, 9))), 273 new Version(5, new int[]{6, 30}, 274 new ECBlocks(26, new ECB(1, 108)), 275 new ECBlocks(24, new ECB(2, 43)), 276 new ECBlocks(18, new ECB(2, 15), 277 new ECB(2, 16)), 278 new ECBlocks(22, new ECB(2, 11), 279 new ECB(2, 12))), 280 new Version(6, new int[]{6, 34}, 281 new ECBlocks(18, new ECB(2, 68)), 282 new ECBlocks(16, new ECB(4, 27)), 283 new ECBlocks(24, new ECB(4, 19)), 284 new ECBlocks(28, new ECB(4, 15))), 285 new Version(7, new int[]{6, 22, 38}, 286 new ECBlocks(20, new ECB(2, 78)), 287 new ECBlocks(18, new ECB(4, 31)), 288 new ECBlocks(18, new ECB(2, 14), 289 new ECB(4, 15)), 290 new ECBlocks(26, new ECB(4, 13), 291 new ECB(1, 14))), 292 new Version(8, new int[]{6, 24, 42}, 293 new ECBlocks(24, new ECB(2, 97)), 294 new ECBlocks(22, new ECB(2, 38), 295 new ECB(2, 39)), 296 new ECBlocks(22, new ECB(4, 18), 297 new ECB(2, 19)), 298 new ECBlocks(26, new ECB(4, 14), 299 new ECB(2, 15))), 300 new Version(9, new int[]{6, 26, 46}, 301 new ECBlocks(30, new ECB(2, 116)), 302 new ECBlocks(22, new ECB(3, 36), 303 new ECB(2, 37)), 304 new ECBlocks(20, new ECB(4, 16), 305 new ECB(4, 17)), 306 new ECBlocks(24, new ECB(4, 12), 307 new ECB(4, 13))), 308 new Version(10, new int[]{6, 28, 50}, 309 new ECBlocks(18, new ECB(2, 68), 310 new ECB(2, 69)), 311 new ECBlocks(26, new ECB(4, 43), 312 new ECB(1, 44)), 313 new ECBlocks(24, new ECB(6, 19), 314 new ECB(2, 20)), 315 new ECBlocks(28, new ECB(6, 15), 316 new ECB(2, 16))), 317 new Version(11, new int[]{6, 30, 54}, 318 new ECBlocks(20, new ECB(4, 81)), 319 new ECBlocks(30, new ECB(1, 50), 320 new ECB(4, 51)), 321 new ECBlocks(28, new ECB(4, 22), 322 new ECB(4, 23)), 323 new ECBlocks(24, new ECB(3, 12), 324 new ECB(8, 13))), 325 new Version(12, new int[]{6, 32, 58}, 326 new ECBlocks(24, new ECB(2, 92), 327 new ECB(2, 93)), 328 new ECBlocks(22, new ECB(6, 36), 329 new ECB(2, 37)), 330 new ECBlocks(26, new ECB(4, 20), 331 new ECB(6, 21)), 332 new ECBlocks(28, new ECB(7, 14), 333 new ECB(4, 15))), 334 new Version(13, new int[]{6, 34, 62}, 335 new ECBlocks(26, new ECB(4, 107)), 336 new ECBlocks(22, new ECB(8, 37), 337 new ECB(1, 38)), 338 new ECBlocks(24, new ECB(8, 20), 339 new ECB(4, 21)), 340 new ECBlocks(22, new ECB(12, 11), 341 new ECB(4, 12))), 342 new Version(14, new int[]{6, 26, 46, 66}, 343 new ECBlocks(30, new ECB(3, 115), 344 new ECB(1, 116)), 345 new ECBlocks(24, new ECB(4, 40), 346 new ECB(5, 41)), 347 new ECBlocks(20, new ECB(11, 16), 348 new ECB(5, 17)), 349 new ECBlocks(24, new ECB(11, 12), 350 new ECB(5, 13))), 351 new Version(15, new int[]{6, 26, 48, 70}, 352 new ECBlocks(22, new ECB(5, 87), 353 new ECB(1, 88)), 354 new ECBlocks(24, new ECB(5, 41), 355 new ECB(5, 42)), 356 new ECBlocks(30, new ECB(5, 24), 357 new ECB(7, 25)), 358 new ECBlocks(24, new ECB(11, 12), 359 new ECB(7, 13))), 360 new Version(16, new int[]{6, 26, 50, 74}, 361 new ECBlocks(24, new ECB(5, 98), 362 new ECB(1, 99)), 363 new ECBlocks(28, new ECB(7, 45), 364 new ECB(3, 46)), 365 new ECBlocks(24, new ECB(15, 19), 366 new ECB(2, 20)), 367 new ECBlocks(30, new ECB(3, 15), 368 new ECB(13, 16))), 369 new Version(17, new int[]{6, 30, 54, 78}, 370 new ECBlocks(28, new ECB(1, 107), 371 new ECB(5, 108)), 372 new ECBlocks(28, new ECB(10, 46), 373 new ECB(1, 47)), 374 new ECBlocks(28, new ECB(1, 22), 375 new ECB(15, 23)), 376 new ECBlocks(28, new ECB(2, 14), 377 new ECB(17, 15))), 378 new Version(18, new int[]{6, 30, 56, 82}, 379 new ECBlocks(30, new ECB(5, 120), 380 new ECB(1, 121)), 381 new ECBlocks(26, new ECB(9, 43), 382 new ECB(4, 44)), 383 new ECBlocks(28, new ECB(17, 22), 384 new ECB(1, 23)), 385 new ECBlocks(28, new ECB(2, 14), 386 new ECB(19, 15))), 387 new Version(19, new int[]{6, 30, 58, 86}, 388 new ECBlocks(28, new ECB(3, 113), 389 new ECB(4, 114)), 390 new ECBlocks(26, new ECB(3, 44), 391 new ECB(11, 45)), 392 new ECBlocks(26, new ECB(17, 21), 393 new ECB(4, 22)), 394 new ECBlocks(26, new ECB(9, 13), 395 new ECB(16, 14))), 396 new Version(20, new int[]{6, 34, 62, 90}, 397 new ECBlocks(28, new ECB(3, 107), 398 new ECB(5, 108)), 399 new ECBlocks(26, new ECB(3, 41), 400 new ECB(13, 42)), 401 new ECBlocks(30, new ECB(15, 24), 402 new ECB(5, 25)), 403 new ECBlocks(28, new ECB(15, 15), 404 new ECB(10, 16))), 405 new Version(21, new int[]{6, 28, 50, 72, 94}, 406 new ECBlocks(28, new ECB(4, 116), 407 new ECB(4, 117)), 408 new ECBlocks(26, new ECB(17, 42)), 409 new ECBlocks(28, new ECB(17, 22), 410 new ECB(6, 23)), 411 new ECBlocks(30, new ECB(19, 16), 412 new ECB(6, 17))), 413 new Version(22, new int[]{6, 26, 50, 74, 98}, 414 new ECBlocks(28, new ECB(2, 111), 415 new ECB(7, 112)), 416 new ECBlocks(28, new ECB(17, 46)), 417 new ECBlocks(30, new ECB(7, 24), 418 new ECB(16, 25)), 419 new ECBlocks(24, new ECB(34, 13))), 420 new Version(23, new int[]{6, 30, 54, 74, 102}, 421 new ECBlocks(30, new ECB(4, 121), 422 new ECB(5, 122)), 423 new ECBlocks(28, new ECB(4, 47), 424 new ECB(14, 48)), 425 new ECBlocks(30, new ECB(11, 24), 426 new ECB(14, 25)), 427 new ECBlocks(30, new ECB(16, 15), 428 new ECB(14, 16))), 429 new Version(24, new int[]{6, 28, 54, 80, 106}, 430 new ECBlocks(30, new ECB(6, 117), 431 new ECB(4, 118)), 432 new ECBlocks(28, new ECB(6, 45), 433 new ECB(14, 46)), 434 new ECBlocks(30, new ECB(11, 24), 435 new ECB(16, 25)), 436 new ECBlocks(30, new ECB(30, 16), 437 new ECB(2, 17))), 438 new Version(25, new int[]{6, 32, 58, 84, 110}, 439 new ECBlocks(26, new ECB(8, 106), 440 new ECB(4, 107)), 441 new ECBlocks(28, new ECB(8, 47), 442 new ECB(13, 48)), 443 new ECBlocks(30, new ECB(7, 24), 444 new ECB(22, 25)), 445 new ECBlocks(30, new ECB(22, 15), 446 new ECB(13, 16))), 447 new Version(26, new int[]{6, 30, 58, 86, 114}, 448 new ECBlocks(28, new ECB(10, 114), 449 new ECB(2, 115)), 450 new ECBlocks(28, new ECB(19, 46), 451 new ECB(4, 47)), 452 new ECBlocks(28, new ECB(28, 22), 453 new ECB(6, 23)), 454 new ECBlocks(30, new ECB(33, 16), 455 new ECB(4, 17))), 456 new Version(27, new int[]{6, 34, 62, 90, 118}, 457 new ECBlocks(30, new ECB(8, 122), 458 new ECB(4, 123)), 459 new ECBlocks(28, new ECB(22, 45), 460 new ECB(3, 46)), 461 new ECBlocks(30, new ECB(8, 23), 462 new ECB(26, 24)), 463 new ECBlocks(30, new ECB(12, 15), 464 new ECB(28, 16))), 465 new Version(28, new int[]{6, 26, 50, 74, 98, 122}, 466 new ECBlocks(30, new ECB(3, 117), 467 new ECB(10, 118)), 468 new ECBlocks(28, new ECB(3, 45), 469 new ECB(23, 46)), 470 new ECBlocks(30, new ECB(4, 24), 471 new ECB(31, 25)), 472 new ECBlocks(30, new ECB(11, 15), 473 new ECB(31, 16))), 474 new Version(29, new int[]{6, 30, 54, 78, 102, 126}, 475 new ECBlocks(30, new ECB(7, 116), 476 new ECB(7, 117)), 477 new ECBlocks(28, new ECB(21, 45), 478 new ECB(7, 46)), 479 new ECBlocks(30, new ECB(1, 23), 480 new ECB(37, 24)), 481 new ECBlocks(30, new ECB(19, 15), 482 new ECB(26, 16))), 483 new Version(30, new int[]{6, 26, 52, 78, 104, 130}, 484 new ECBlocks(30, new ECB(5, 115), 485 new ECB(10, 116)), 486 new ECBlocks(28, new ECB(19, 47), 487 new ECB(10, 48)), 488 new ECBlocks(30, new ECB(15, 24), 489 new ECB(25, 25)), 490 new ECBlocks(30, new ECB(23, 15), 491 new ECB(25, 16))), 492 new Version(31, new int[]{6, 30, 56, 82, 108, 134}, 493 new ECBlocks(30, new ECB(13, 115), 494 new ECB(3, 116)), 495 new ECBlocks(28, new ECB(2, 46), 496 new ECB(29, 47)), 497 new ECBlocks(30, new ECB(42, 24), 498 new ECB(1, 25)), 499 new ECBlocks(30, new ECB(23, 15), 500 new ECB(28, 16))), 501 new Version(32, new int[]{6, 34, 60, 86, 112, 138}, 502 new ECBlocks(30, new ECB(17, 115)), 503 new ECBlocks(28, new ECB(10, 46), 504 new ECB(23, 47)), 505 new ECBlocks(30, new ECB(10, 24), 506 new ECB(35, 25)), 507 new ECBlocks(30, new ECB(19, 15), 508 new ECB(35, 16))), 509 new Version(33, new int[]{6, 30, 58, 86, 114, 142}, 510 new ECBlocks(30, new ECB(17, 115), 511 new ECB(1, 116)), 512 new ECBlocks(28, new ECB(14, 46), 513 new ECB(21, 47)), 514 new ECBlocks(30, new ECB(29, 24), 515 new ECB(19, 25)), 516 new ECBlocks(30, new ECB(11, 15), 517 new ECB(46, 16))), 518 new Version(34, new int[]{6, 34, 62, 90, 118, 146}, 519 new ECBlocks(30, new ECB(13, 115), 520 new ECB(6, 116)), 521 new ECBlocks(28, new ECB(14, 46), 522 new ECB(23, 47)), 523 new ECBlocks(30, new ECB(44, 24), 524 new ECB(7, 25)), 525 new ECBlocks(30, new ECB(59, 16), 526 new ECB(1, 17))), 527 new Version(35, new int[]{6, 30, 54, 78, 102, 126, 150}, 528 new ECBlocks(30, new ECB(12, 121), 529 new ECB(7, 122)), 530 new ECBlocks(28, new ECB(12, 47), 531 new ECB(26, 48)), 532 new ECBlocks(30, new ECB(39, 24), 533 new ECB(14, 25)), 534 new ECBlocks(30, new ECB(22, 15), 535 new ECB(41, 16))), 536 new Version(36, new int[]{6, 24, 50, 76, 102, 128, 154}, 537 new ECBlocks(30, new ECB(6, 121), 538 new ECB(14, 122)), 539 new ECBlocks(28, new ECB(6, 47), 540 new ECB(34, 48)), 541 new ECBlocks(30, new ECB(46, 24), 542 new ECB(10, 25)), 543 new ECBlocks(30, new ECB(2, 15), 544 new ECB(64, 16))), 545 new Version(37, new int[]{6, 28, 54, 80, 106, 132, 158}, 546 new ECBlocks(30, new ECB(17, 122), 547 new ECB(4, 123)), 548 new ECBlocks(28, new ECB(29, 46), 549 new ECB(14, 47)), 550 new ECBlocks(30, new ECB(49, 24), 551 new ECB(10, 25)), 552 new ECBlocks(30, new ECB(24, 15), 553 new ECB(46, 16))), 554 new Version(38, new int[]{6, 32, 58, 84, 110, 136, 162}, 555 new ECBlocks(30, new ECB(4, 122), 556 new ECB(18, 123)), 557 new ECBlocks(28, new ECB(13, 46), 558 new ECB(32, 47)), 559 new ECBlocks(30, new ECB(48, 24), 560 new ECB(14, 25)), 561 new ECBlocks(30, new ECB(42, 15), 562 new ECB(32, 16))), 563 new Version(39, new int[]{6, 26, 54, 82, 110, 138, 166}, 564 new ECBlocks(30, new ECB(20, 117), 565 new ECB(4, 118)), 566 new ECBlocks(28, new ECB(40, 47), 567 new ECB(7, 48)), 568 new ECBlocks(30, new ECB(43, 24), 569 new ECB(22, 25)), 570 new ECBlocks(30, new ECB(10, 15), 571 new ECB(67, 16))), 572 new Version(40, new int[]{6, 30, 58, 86, 114, 142, 170}, 573 new ECBlocks(30, new ECB(19, 118), 574 new ECB(6, 119)), 575 new ECBlocks(28, new ECB(18, 47), 576 new ECB(31, 48)), 577 new ECBlocks(30, new ECB(34, 24), 578 new ECB(34, 25)), 579 new ECBlocks(30, new ECB(20, 15), 580 new ECB(61, 16))) 581 }; 582 } 583 584}