/*\r
- * Copyright 2007 Google Inc.\r
+ * Copyright 2007 ZXing authors\r
*\r
* Licensed under the Apache License, Version 2.0 (the "License");\r
* you may not use this file except in compliance with the License.\r
\r
package com.google.zxing.qrcode.decoder;\r
\r
-import com.google.zxing.ReaderException;\r
+import com.google.zxing.FormatException;\r
import com.google.zxing.common.BitMatrix;\r
\r
/**\r
* See ISO 18004:2006 Annex D\r
*\r
- * @author srowen@google.com (Sean Owen)\r
+ * @author Sean Owen\r
*/\r
public final class Version {\r
\r
* See ISO 18004:2006 Annex D.\r
* Element i represents the raw version bits that specify version i + 7\r
*/\r
- private static final int[] VERSION_DECODE_INFO = new int[]{\r
+ private static final int[] VERSION_DECODE_INFO = {\r
0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6,\r
0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78,\r
0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683,\r
this.alignmentPatternCenters = alignmentPatternCenters;\r
this.ecBlocks = new ECBlocks[]{ecBlocks1, ecBlocks2, ecBlocks3, ecBlocks4};\r
int total = 0;\r
- ECBlocks levelLECBlocks = ecBlocks1; // L,M,Q,H -- all the same total\r
- int ecCodewords = levelLECBlocks.ecCodewords;\r
- ECB[] ecbArray = levelLECBlocks.ecBlocks;\r
+ int ecCodewords = ecBlocks1.getECCodewordsPerBlock();\r
+ ECB[] ecbArray = ecBlocks1.getECBlocks();\r
for (int i = 0; i < ecbArray.length; i++) {\r
ECB ecBlock = ecbArray[i];\r
- total += ecBlock.count * (ecBlock.dataCodewords + ecCodewords);\r
+ total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);\r
}\r
this.totalCodewords = total;\r
}\r
return 17 + 4 * versionNumber;\r
}\r
\r
- ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) {\r
+ public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) {\r
return ecBlocks[ecLevel.ordinal()];\r
}\r
\r
*\r
* @param dimension dimension in modules\r
* @return {@link Version} for a QR Code of that dimension\r
- * @throws ReaderException if dimension is not 1 mod 4\r
+ * @throws FormatException if dimension is not 1 mod 4\r
*/\r
- public static Version getProvisionalVersionForDimension(int dimension) throws ReaderException {\r
+ public static Version getProvisionalVersionForDimension(int dimension) throws FormatException {\r
if (dimension % 4 != 1) {\r
- throw new ReaderException("Dimension must be 1 mod 4");\r
+ throw FormatException.getFormatInstance();\r
+ }\r
+ try {\r
+ return getVersionForNumber((dimension - 17) >> 2);\r
+ } catch (IllegalArgumentException iae) {\r
+ throw FormatException.getFormatInstance();\r
}\r
- return getVersionForNumber((dimension - 17) >> 2);\r
}\r
\r
- public static Version getVersionForNumber(int versionNumber) throws ReaderException {\r
+ public static Version getVersionForNumber(int versionNumber) {\r
if (versionNumber < 1 || versionNumber > 40) {\r
- throw new ReaderException("versionNumber must be between 1 and 40");\r
+ throw new IllegalArgumentException();\r
}\r
return VERSIONS[versionNumber - 1];\r
}\r
\r
- static Version decodeVersionInformation(int versionBits) throws ReaderException {\r
+ static Version decodeVersionInformation(int versionBits) {\r
int bestDifference = Integer.MAX_VALUE;\r
int bestVersion = 0;\r
for (int i = 0; i < VERSION_DECODE_INFO.length; i++) {\r
int bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion);\r
if (bitsDifference < bestDifference) {\r
bestVersion = i + 7;\r
+ bestDifference = bitsDifference;\r
}\r
}\r
// We can tolerate up to 3 bits of error since no two version info codewords will\r
- // differ in less than 4 bits.\r
+ // differ in less than 8 bits.\r
if (bestDifference <= 3) {\r
return getVersionForNumber(bestVersion);\r
}\r
// Top left finder pattern + separator + format\r
bitMatrix.setRegion(0, 0, 9, 9);\r
// Top right finder pattern + separator + format\r
- bitMatrix.setRegion(0, dimension - 8, 9, 8);\r
- // Bottom left finder pattern + separator + format\r
bitMatrix.setRegion(dimension - 8, 0, 8, 9);\r
+ // Bottom left finder pattern + separator + format\r
+ bitMatrix.setRegion(0, dimension - 8, 9, 8);\r
\r
// Alignment patterns\r
int max = alignmentPatternCenters.length;\r
// No alignment patterns near the three finder paterns\r
continue;\r
}\r
- bitMatrix.setRegion(i, alignmentPatternCenters[y] - 2, 5, 5);\r
+ bitMatrix.setRegion(alignmentPatternCenters[y] - 2, i, 5, 5);\r
}\r
}\r
\r
// Vertical timing pattern\r
- bitMatrix.setRegion(9, 6, dimension - 17, 1);\r
- // Horizontal timing pattern\r
bitMatrix.setRegion(6, 9, 1, dimension - 17);\r
+ // Horizontal timing pattern\r
+ bitMatrix.setRegion(9, 6, dimension - 17, 1);\r
\r
if (versionNumber > 6) {\r
// Version info, top right\r
- bitMatrix.setRegion(0, dimension - 11, 6, 3);\r
- // Version info, bottom left\r
bitMatrix.setRegion(dimension - 11, 0, 3, 6);\r
+ // Version info, bottom left\r
+ bitMatrix.setRegion(0, dimension - 11, 6, 3);\r
}\r
\r
return bitMatrix;\r
* each set of blocks. It also holds the number of error-correction codewords per block since it\r
* will be the same across all blocks within one version.</p>\r
*/\r
- static final class ECBlocks {\r
- private int ecCodewords;\r
- private ECB[] ecBlocks;\r
+ public static final class ECBlocks {\r
+ private final int ecCodewordsPerBlock;\r
+ private final ECB[] ecBlocks;\r
\r
- private ECBlocks(int ecCodewords, ECB ecBlocks) {\r
- this.ecCodewords = ecCodewords;\r
+ ECBlocks(int ecCodewordsPerBlock, ECB ecBlocks) {\r
+ this.ecCodewordsPerBlock = ecCodewordsPerBlock;\r
this.ecBlocks = new ECB[]{ecBlocks};\r
}\r
\r
- private ECBlocks(int ecCodewords, ECB ecBlocks1, ECB ecBlocks2) {\r
- this.ecCodewords = ecCodewords;\r
+ ECBlocks(int ecCodewordsPerBlock, ECB ecBlocks1, ECB ecBlocks2) {\r
+ this.ecCodewordsPerBlock = ecCodewordsPerBlock;\r
this.ecBlocks = new ECB[]{ecBlocks1, ecBlocks2};\r
}\r
\r
- int getECCodewords() {\r
- return ecCodewords;\r
+ public int getECCodewordsPerBlock() {\r
+ return ecCodewordsPerBlock;\r
+ }\r
+\r
+ public int getNumBlocks() {\r
+ int total = 0;\r
+ for (int i = 0; i < ecBlocks.length; i++) {\r
+ total += ecBlocks[i].getCount();\r
+ }\r
+ return total;\r
+ }\r
+\r
+ public int getTotalECCodewords() {\r
+ return ecCodewordsPerBlock * getNumBlocks();\r
}\r
\r
- ECB[] getECBlocks() {\r
+ public ECB[] getECBlocks() {\r
return ecBlocks;\r
}\r
}\r
* This includes the number of data codewords, and the number of times a block with these\r
* parameters is used consecutively in the QR code version's format.</p>\r
*/\r
- static final class ECB {\r
- private int count;\r
- private int dataCodewords;\r
+ public static final class ECB {\r
+ private final int count;\r
+ private final int dataCodewords;\r
\r
- private ECB(int count, int dataCodewords) {\r
+ ECB(int count, int dataCodewords) {\r
this.count = count;\r
this.dataCodewords = dataCodewords;\r
}\r
\r
- int getCount() {\r
+ public int getCount() {\r
return count;\r
}\r
\r
- int getDataCodewords() {\r
+ public int getDataCodewords() {\r
return dataCodewords;\r
}\r
}\r
new ECBlocks(30, new ECB(7, 24),\r
new ECB(16, 25)),\r
new ECBlocks(24, new ECB(34, 13))),\r
- new Version(23, new int[]{6, 30, 54, 74, 102},\r
+ new Version(23, new int[]{6, 30, 54, 78, 102},\r
new ECBlocks(30, new ECB(4, 121),\r
new ECB(5, 122)),\r
new ECBlocks(28, new ECB(4, 47),\r