aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder
diff options
context:
space:
mode:
Diffstat (limited to 'OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder')
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java203
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataBlock.java123
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataMask.java155
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java322
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java86
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/FormatInformation.java171
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Mode.java117
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Version.java586
8 files changed, 0 insertions, 1763 deletions
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java
deleted file mode 100644
index 9d131a554..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-import com.google.zxing.FormatException;
-import com.google.zxing.common.BitMatrix;
-
-/**
- * @author Sean Owen
- */
-final class BitMatrixParser {
-
- private final BitMatrix bitMatrix;
- private Version parsedVersion;
- private FormatInformation parsedFormatInfo;
-
- /**
- * @param bitMatrix {@link BitMatrix} to parse
- * @throws FormatException if dimension is not >= 21 and 1 mod 4
- */
- BitMatrixParser(BitMatrix bitMatrix) throws FormatException {
- int dimension = bitMatrix.getHeight();
- if (dimension < 21 || (dimension & 0x03) != 1) {
- throw FormatException.getFormatInstance();
- }
- this.bitMatrix = bitMatrix;
- }
-
- /**
- * <p>Reads format information from one of its two locations within the QR Code.</p>
- *
- * @return {@link FormatInformation} encapsulating the QR Code's format info
- * @throws FormatException if both format information locations cannot be parsed as
- * the valid encoding of format information
- */
- FormatInformation readFormatInformation() throws FormatException {
-
- if (parsedFormatInfo != null) {
- return parsedFormatInfo;
- }
-
- // Read top-left format info bits
- int formatInfoBits1 = 0;
- for (int i = 0; i < 6; i++) {
- formatInfoBits1 = copyBit(i, 8, formatInfoBits1);
- }
- // .. and skip a bit in the timing pattern ...
- formatInfoBits1 = copyBit(7, 8, formatInfoBits1);
- formatInfoBits1 = copyBit(8, 8, formatInfoBits1);
- formatInfoBits1 = copyBit(8, 7, formatInfoBits1);
- // .. and skip a bit in the timing pattern ...
- for (int j = 5; j >= 0; j--) {
- formatInfoBits1 = copyBit(8, j, formatInfoBits1);
- }
-
- // Read the top-right/bottom-left pattern too
- int dimension = bitMatrix.getHeight();
- int formatInfoBits2 = 0;
- int jMin = dimension - 7;
- for (int j = dimension - 1; j >= jMin; j--) {
- formatInfoBits2 = copyBit(8, j, formatInfoBits2);
- }
- for (int i = dimension - 8; i < dimension; i++) {
- formatInfoBits2 = copyBit(i, 8, formatInfoBits2);
- }
-
- parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits1, formatInfoBits2);
- if (parsedFormatInfo != null) {
- return parsedFormatInfo;
- }
- throw FormatException.getFormatInstance();
- }
-
- /**
- * <p>Reads version information from one of its two locations within the QR Code.</p>
- *
- * @return {@link Version} encapsulating the QR Code's version
- * @throws FormatException if both version information locations cannot be parsed as
- * the valid encoding of version information
- */
- Version readVersion() throws FormatException {
-
- if (parsedVersion != null) {
- return parsedVersion;
- }
-
- int dimension = bitMatrix.getHeight();
-
- int provisionalVersion = (dimension - 17) >> 2;
- if (provisionalVersion <= 6) {
- return Version.getVersionForNumber(provisionalVersion);
- }
-
- // Read top-right version info: 3 wide by 6 tall
- int versionBits = 0;
- int ijMin = dimension - 11;
- for (int j = 5; j >= 0; j--) {
- for (int i = dimension - 9; i >= ijMin; i--) {
- versionBits = copyBit(i, j, versionBits);
- }
- }
-
- parsedVersion = Version.decodeVersionInformation(versionBits);
- if (parsedVersion != null && parsedVersion.getDimensionForVersion() == dimension) {
- return parsedVersion;
- }
-
- // Hmm, failed. Try bottom left: 6 wide by 3 tall
- versionBits = 0;
- for (int i = 5; i >= 0; i--) {
- for (int j = dimension - 9; j >= ijMin; j--) {
- versionBits = copyBit(i, j, versionBits);
- }
- }
-
- parsedVersion = Version.decodeVersionInformation(versionBits);
- if (parsedVersion != null && parsedVersion.getDimensionForVersion() == dimension) {
- return parsedVersion;
- }
- throw FormatException.getFormatInstance();
- }
-
- private int copyBit(int i, int j, int versionBits) {
- return bitMatrix.get(i, j) ? (versionBits << 1) | 0x1 : versionBits << 1;
- }
-
- /**
- * <p>Reads the bits in the {@link BitMatrix} representing the finder pattern in the
- * correct order in order to reconstitute the codewords bytes contained within the
- * QR Code.</p>
- *
- * @return bytes encoded within the QR Code
- * @throws FormatException if the exact number of bytes expected is not read
- */
- byte[] readCodewords() throws FormatException {
-
- FormatInformation formatInfo = readFormatInformation();
- Version version = readVersion();
-
- // Get the data mask for the format used in this QR Code. This will exclude
- // some bits from reading as we wind through the bit matrix.
- DataMask dataMask = DataMask.forReference((int) formatInfo.getDataMask());
- int dimension = bitMatrix.getHeight();
- dataMask.unmaskBitMatrix(bitMatrix, dimension);
-
- BitMatrix functionPattern = version.buildFunctionPattern();
-
- boolean readingUp = true;
- byte[] result = new byte[version.getTotalCodewords()];
- int resultOffset = 0;
- int currentByte = 0;
- int bitsRead = 0;
- // Read columns in pairs, from right to left
- for (int j = dimension - 1; j > 0; j -= 2) {
- if (j == 6) {
- // Skip whole column with vertical alignment pattern;
- // saves time and makes the other code proceed more cleanly
- j--;
- }
- // Read alternatingly from bottom to top then top to bottom
- for (int count = 0; count < dimension; count++) {
- int i = readingUp ? dimension - 1 - count : count;
- for (int col = 0; col < 2; col++) {
- // Ignore bits covered by the function pattern
- if (!functionPattern.get(j - col, i)) {
- // Read a bit
- bitsRead++;
- currentByte <<= 1;
- if (bitMatrix.get(j - col, i)) {
- currentByte |= 1;
- }
- // If we've made a whole byte, save it off
- if (bitsRead == 8) {
- result[resultOffset++] = (byte) currentByte;
- bitsRead = 0;
- currentByte = 0;
- }
- }
- }
- }
- readingUp ^= true; // readingUp = !readingUp; // switch directions
- }
- if (resultOffset != version.getTotalCodewords()) {
- throw FormatException.getFormatInstance();
- }
- return result;
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataBlock.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataBlock.java
deleted file mode 100644
index 12959d9c1..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataBlock.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-/**
- * <p>Encapsulates a block of data within a QR Code. QR Codes may split their data into
- * multiple blocks, each of which is a unit of data and error-correction codewords. Each
- * is represented by an instance of this class.</p>
- *
- * @author Sean Owen
- */
-final class DataBlock {
-
- private final int numDataCodewords;
- private final byte[] codewords;
-
- private DataBlock(int numDataCodewords, byte[] codewords) {
- this.numDataCodewords = numDataCodewords;
- this.codewords = codewords;
- }
-
- /**
- * <p>When QR Codes use multiple data blocks, they are actually interleaved.
- * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This
- * method will separate the data into original blocks.</p>
- *
- * @param rawCodewords bytes as read directly from the QR Code
- * @param version version of the QR Code
- * @param ecLevel error-correction level of the QR Code
- * @return DataBlocks containing original bytes, "de-interleaved" from representation in the
- * QR Code
- */
- static DataBlock[] getDataBlocks(byte[] rawCodewords,
- Version version,
- ErrorCorrectionLevel ecLevel) {
-
- if (rawCodewords.length != version.getTotalCodewords()) {
- throw new IllegalArgumentException();
- }
-
- // Figure out the number and size of data blocks used by this version and
- // error correction level
- Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);
-
- // First count the total number of data blocks
- int totalBlocks = 0;
- Version.ECB[] ecBlockArray = ecBlocks.getECBlocks();
- for (int i = 0; i < ecBlockArray.length; i++) {
- totalBlocks += ecBlockArray[i].getCount();
- }
-
- // Now establish DataBlocks of the appropriate size and number of data codewords
- DataBlock[] result = new DataBlock[totalBlocks];
- int numResultBlocks = 0;
- for (int j = 0; j < ecBlockArray.length; j++) {
- Version.ECB ecBlock = ecBlockArray[j];
- for (int i = 0; i < ecBlock.getCount(); i++) {
- int numDataCodewords = ecBlock.getDataCodewords();
- int numBlockCodewords = ecBlocks.getECCodewordsPerBlock() + numDataCodewords;
- result[numResultBlocks++] = new DataBlock(numDataCodewords, new byte[numBlockCodewords]);
- }
- }
-
- // All blocks have the same amount of data, except that the last n
- // (where n may be 0) have 1 more byte. Figure out where these start.
- int shorterBlocksTotalCodewords = result[0].codewords.length;
- int longerBlocksStartAt = result.length - 1;
- while (longerBlocksStartAt >= 0) {
- int numCodewords = result[longerBlocksStartAt].codewords.length;
- if (numCodewords == shorterBlocksTotalCodewords) {
- break;
- }
- longerBlocksStartAt--;
- }
- longerBlocksStartAt++;
-
- int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewordsPerBlock();
- // The last elements of result may be 1 element longer;
- // first fill out as many elements as all of them have
- int rawCodewordsOffset = 0;
- for (int i = 0; i < shorterBlocksNumDataCodewords; i++) {
- for (int j = 0; j < numResultBlocks; j++) {
- result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];
- }
- }
- // Fill out the last data block in the longer ones
- for (int j = longerBlocksStartAt; j < numResultBlocks; j++) {
- result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];
- }
- // Now add in error correction blocks
- int max = result[0].codewords.length;
- for (int i = shorterBlocksNumDataCodewords; i < max; i++) {
- for (int j = 0; j < numResultBlocks; j++) {
- int iOffset = j < longerBlocksStartAt ? i : i + 1;
- result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];
- }
- }
- return result;
- }
-
- int getNumDataCodewords() {
- return numDataCodewords;
- }
-
- byte[] getCodewords() {
- return codewords;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataMask.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataMask.java
deleted file mode 100644
index d29dbd47f..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataMask.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-import com.google.zxing.common.BitMatrix;
-
-/**
- * <p>Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations
- * of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix,
- * including areas used for finder patterns, timing patterns, etc. These areas should be unused
- * after the point they are unmasked anyway.</p>
- *
- * <p>Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position
- * and j is row position. In fact, as the text says, i is row position and j is column position.</p>
- *
- * @author Sean Owen
- */
-abstract class DataMask {
-
- /**
- * See ISO 18004:2006 6.8.1
- */
- private static final DataMask[] DATA_MASKS = {
- new DataMask000(),
- new DataMask001(),
- new DataMask010(),
- new DataMask011(),
- new DataMask100(),
- new DataMask101(),
- new DataMask110(),
- new DataMask111(),
- };
-
- private DataMask() {
- }
-
- /**
- * <p>Implementations of this method reverse the data masking process applied to a QR Code and
- * make its bits ready to read.</p>
- *
- * @param bits representation of QR Code bits
- * @param dimension dimension of QR Code, represented by bits, being unmasked
- */
- final void unmaskBitMatrix(BitMatrix bits, int dimension) {
- for (int i = 0; i < dimension; i++) {
- for (int j = 0; j < dimension; j++) {
- if (isMasked(i, j)) {
- bits.flip(j, i);
- }
- }
- }
- }
-
- abstract boolean isMasked(int i, int j);
-
- /**
- * @param reference a value between 0 and 7 indicating one of the eight possible
- * data mask patterns a QR Code may use
- * @return DataMask encapsulating the data mask pattern
- */
- static DataMask forReference(int reference) {
- if (reference < 0 || reference > 7) {
- throw new IllegalArgumentException();
- }
- return DATA_MASKS[reference];
- }
-
- /**
- * 000: mask bits for which (x + y) mod 2 == 0
- */
- private static class DataMask000 extends DataMask {
- boolean isMasked(int i, int j) {
- return ((i + j) & 0x01) == 0;
- }
- }
-
- /**
- * 001: mask bits for which x mod 2 == 0
- */
- private static class DataMask001 extends DataMask {
- boolean isMasked(int i, int j) {
- return (i & 0x01) == 0;
- }
- }
-
- /**
- * 010: mask bits for which y mod 3 == 0
- */
- private static class DataMask010 extends DataMask {
- boolean isMasked(int i, int j) {
- return j % 3 == 0;
- }
- }
-
- /**
- * 011: mask bits for which (x + y) mod 3 == 0
- */
- private static class DataMask011 extends DataMask {
- boolean isMasked(int i, int j) {
- return (i + j) % 3 == 0;
- }
- }
-
- /**
- * 100: mask bits for which (x/2 + y/3) mod 2 == 0
- */
- private static class DataMask100 extends DataMask {
- boolean isMasked(int i, int j) {
- return (((i >>> 1) + (j /3)) & 0x01) == 0;
- }
- }
-
- /**
- * 101: mask bits for which xy mod 2 + xy mod 3 == 0
- */
- private static class DataMask101 extends DataMask {
- boolean isMasked(int i, int j) {
- int temp = i * j;
- return (temp & 0x01) + (temp % 3) == 0;
- }
- }
-
- /**
- * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0
- */
- private static class DataMask110 extends DataMask {
- boolean isMasked(int i, int j) {
- int temp = i * j;
- return (((temp & 0x01) + (temp % 3)) & 0x01) == 0;
- }
- }
-
- /**
- * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0
- */
- private static class DataMask111 extends DataMask {
- boolean isMasked(int i, int j) {
- return ((((i + j) & 0x01) + ((i * j) % 3)) & 0x01) == 0;
- }
- }
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java
deleted file mode 100644
index ff374ac50..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-import com.google.zxing.FormatException;
-import com.google.zxing.common.BitSource;
-import com.google.zxing.common.CharacterSetECI;
-import com.google.zxing.common.DecoderResult;
-import com.google.zxing.common.StringUtils;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Hashtable;
-import java.util.Vector;
-
-/**
- * <p>QR Codes can encode text as bits in one of several modes, and can use multiple modes
- * in one QR Code. This class decodes the bits back into text.</p>
- *
- * <p>See ISO 18004:2006, 6.4.3 - 6.4.7</p>
- *
- * @author Sean Owen
- */
-final class DecodedBitStreamParser {
-
- /**
- * See ISO 18004:2006, 6.4.4 Table 5
- */
- private static final char[] ALPHANUMERIC_CHARS = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
- 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
- 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
- ' ', '$', '%', '*', '+', '-', '.', '/', ':'
- };
- private static final int GB2312_SUBSET = 1;
-
- private DecodedBitStreamParser() {
- }
-
- static DecoderResult decode(byte[] bytes, Version version, ErrorCorrectionLevel ecLevel, Hashtable hints)
- throws FormatException {
- BitSource bits = new BitSource(bytes);
- StringBuffer result = new StringBuffer(50);
- CharacterSetECI currentCharacterSetECI = null;
- boolean fc1InEffect = false;
- Vector byteSegments = new Vector(1);
- Mode mode;
- do {
- // While still another segment to read...
- if (bits.available() < 4) {
- // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here
- mode = Mode.TERMINATOR;
- } else {
- try {
- mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits
- } catch (IllegalArgumentException iae) {
- throw FormatException.getFormatInstance();
- }
- }
- if (!mode.equals(Mode.TERMINATOR)) {
- if (mode.equals(Mode.FNC1_FIRST_POSITION) || mode.equals(Mode.FNC1_SECOND_POSITION)) {
- // We do little with FNC1 except alter the parsed result a bit according to the spec
- fc1InEffect = true;
- } else if (mode.equals(Mode.STRUCTURED_APPEND)) {
- // not really supported; all we do is ignore it
- // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
- bits.readBits(16);
- } else if (mode.equals(Mode.ECI)) {
- // Count doesn't apply to ECI
- int value = parseECIValue(bits);
- currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);
- if (currentCharacterSetECI == null) {
- throw FormatException.getFormatInstance();
- }
- } else {
- // First handle Hanzi mode which does not start with character count
- if (mode.equals(Mode.HANZI)) {
- //chinese mode contains a sub set indicator right after mode indicator
- int subset = bits.readBits(4);
- int countHanzi = bits.readBits(mode.getCharacterCountBits(version));
- if (subset == GB2312_SUBSET) {
- decodeHanziSegment(bits, result, countHanzi);
- }
- } else {
- // "Normal" QR code modes:
- // How many characters will follow, encoded in this mode?
- int count = bits.readBits(mode.getCharacterCountBits(version));
- if (mode.equals(Mode.NUMERIC)) {
- decodeNumericSegment(bits, result, count);
- } else if (mode.equals(Mode.ALPHANUMERIC)) {
- decodeAlphanumericSegment(bits, result, count, fc1InEffect);
- } else if (mode.equals(Mode.BYTE)) {
- decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints);
- } else if (mode.equals(Mode.KANJI)) {
- decodeKanjiSegment(bits, result, count);
- } else {
- throw FormatException.getFormatInstance();
- }
- }
- }
- }
- } while (!mode.equals(Mode.TERMINATOR));
-
- return new DecoderResult(bytes,
- result.toString(),
- byteSegments.isEmpty() ? null : byteSegments,
- ecLevel == null ? null : ecLevel.toString());
- }
-
- /**
- * See specification GBT 18284-2000
- */
- private static void decodeHanziSegment(BitSource bits,
- StringBuffer result,
- int count) throws FormatException {
- // Don't crash trying to read more bits than we have available.
- if (count * 13 > bits.available()) {
- throw FormatException.getFormatInstance();
- }
-
- // Each character will require 2 bytes. Read the characters as 2-byte pairs
- // and decode as GB2312 afterwards
- byte[] buffer = new byte[2 * count];
- int offset = 0;
- while (count > 0) {
- // Each 13 bits encodes a 2-byte character
- int twoBytes = bits.readBits(13);
- int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060);
- if (assembledTwoBytes < 0x003BF) {
- // In the 0xA1A1 to 0xAAFE range
- assembledTwoBytes += 0x0A1A1;
- } else {
- // In the 0xB0A1 to 0xFAFE range
- assembledTwoBytes += 0x0A6A1;
- }
- buffer[offset] = (byte) ((assembledTwoBytes >> 8) & 0xFF);
- buffer[offset + 1] = (byte) (assembledTwoBytes & 0xFF);
- offset += 2;
- count--;
- }
-
- try {
- result.append(new String(buffer, StringUtils.GB2312));
- } catch (UnsupportedEncodingException uee) {
- throw FormatException.getFormatInstance();
- }
- }
-
- private static void decodeKanjiSegment(BitSource bits,
- StringBuffer result,
- int count) throws FormatException {
- // Don't crash trying to read more bits than we have available.
- if (count * 13 > bits.available()) {
- throw FormatException.getFormatInstance();
- }
-
- // Each character will require 2 bytes. Read the characters as 2-byte pairs
- // and decode as Shift_JIS afterwards
- byte[] buffer = new byte[2 * count];
- int offset = 0;
- while (count > 0) {
- // Each 13 bits encodes a 2-byte character
- int twoBytes = bits.readBits(13);
- int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0);
- if (assembledTwoBytes < 0x01F00) {
- // In the 0x8140 to 0x9FFC range
- assembledTwoBytes += 0x08140;
- } else {
- // In the 0xE040 to 0xEBBF range
- assembledTwoBytes += 0x0C140;
- }
- buffer[offset] = (byte) (assembledTwoBytes >> 8);
- buffer[offset + 1] = (byte) assembledTwoBytes;
- offset += 2;
- count--;
- }
- // Shift_JIS may not be supported in some environments:
- try {
- result.append(new String(buffer, StringUtils.SHIFT_JIS));
- } catch (UnsupportedEncodingException uee) {
- throw FormatException.getFormatInstance();
- }
- }
-
- private static void decodeByteSegment(BitSource bits,
- StringBuffer result,
- int count,
- CharacterSetECI currentCharacterSetECI,
- Vector byteSegments,
- Hashtable hints) throws FormatException {
- // Don't crash trying to read more bits than we have available.
- if (count << 3 > bits.available()) {
- throw FormatException.getFormatInstance();
- }
-
- byte[] readBytes = new byte[count];
- for (int i = 0; i < count; i++) {
- readBytes[i] = (byte) bits.readBits(8);
- }
- String encoding;
- if (currentCharacterSetECI == null) {
- // The spec isn't clear on this mode; see
- // section 6.4.5: t does not say which encoding to assuming
- // upon decoding. I have seen ISO-8859-1 used as well as
- // Shift_JIS -- without anything like an ECI designator to
- // give a hint.
- encoding = StringUtils.guessEncoding(readBytes, hints);
- } else {
- encoding = currentCharacterSetECI.getEncodingName();
- }
- try {
- result.append(new String(readBytes, encoding));
- } catch (UnsupportedEncodingException uce) {
- throw FormatException.getFormatInstance();
- }
- byteSegments.addElement(readBytes);
- }
-
- private static char toAlphaNumericChar(int value) throws FormatException {
- if (value >= ALPHANUMERIC_CHARS.length) {
- throw FormatException.getFormatInstance();
- }
- return ALPHANUMERIC_CHARS[value];
- }
-
- private static void decodeAlphanumericSegment(BitSource bits,
- StringBuffer result,
- int count,
- boolean fc1InEffect) throws FormatException {
- // Read two characters at a time
- int start = result.length();
- while (count > 1) {
- int nextTwoCharsBits = bits.readBits(11);
- result.append(toAlphaNumericChar(nextTwoCharsBits / 45));
- result.append(toAlphaNumericChar(nextTwoCharsBits % 45));
- count -= 2;
- }
- if (count == 1) {
- // special case: one character left
- result.append(toAlphaNumericChar(bits.readBits(6)));
- }
- // See section 6.4.8.1, 6.4.8.2
- if (fc1InEffect) {
- // We need to massage the result a bit if in an FNC1 mode:
- for (int i = start; i < result.length(); i++) {
- if (result.charAt(i) == '%') {
- if (i < result.length() - 1 && result.charAt(i + 1) == '%') {
- // %% is rendered as %
- result.deleteCharAt(i + 1);
- } else {
- // In alpha mode, % should be converted to FNC1 separator 0x1D
- result.setCharAt(i, (char) 0x1D);
- }
- }
- }
- }
- }
-
- private static void decodeNumericSegment(BitSource bits,
- StringBuffer result,
- int count) throws FormatException {
- // Read three digits at a time
- while (count >= 3) {
- // Each 10 bits encodes three digits
- int threeDigitsBits = bits.readBits(10);
- if (threeDigitsBits >= 1000) {
- throw FormatException.getFormatInstance();
- }
- result.append(toAlphaNumericChar(threeDigitsBits / 100));
- result.append(toAlphaNumericChar((threeDigitsBits / 10) % 10));
- result.append(toAlphaNumericChar(threeDigitsBits % 10));
- count -= 3;
- }
- if (count == 2) {
- // Two digits left over to read, encoded in 7 bits
- int twoDigitsBits = bits.readBits(7);
- if (twoDigitsBits >= 100) {
- throw FormatException.getFormatInstance();
- }
- result.append(toAlphaNumericChar(twoDigitsBits / 10));
- result.append(toAlphaNumericChar(twoDigitsBits % 10));
- } else if (count == 1) {
- // One digit left over to read
- int digitBits = bits.readBits(4);
- if (digitBits >= 10) {
- throw FormatException.getFormatInstance();
- }
- result.append(toAlphaNumericChar(digitBits));
- }
- }
-
- private static int parseECIValue(BitSource bits) {
- int firstByte = bits.readBits(8);
- if ((firstByte & 0x80) == 0) {
- // just one byte
- return firstByte & 0x7F;
- } else if ((firstByte & 0xC0) == 0x80) {
- // two bytes
- int secondByte = bits.readBits(8);
- return ((firstByte & 0x3F) << 8) | secondByte;
- } else if ((firstByte & 0xE0) == 0xC0) {
- // three bytes
- int secondThirdBytes = bits.readBits(16);
- return ((firstByte & 0x1F) << 16) | secondThirdBytes;
- }
- throw new IllegalArgumentException("Bad ECI bits starting with byte " + firstByte);
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java
deleted file mode 100644
index e8d6c2589..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-/**
- * <p>See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels
- * defined by the QR code standard.</p>
- *
- * @author Sean Owen
- */
-public final class ErrorCorrectionLevel {
-
- // No, we can't use an enum here. J2ME doesn't support it.
-
- /**
- * L = ~7% correction
- */
- public static final ErrorCorrectionLevel L = new ErrorCorrectionLevel(0, 0x01, "L");
- /**
- * M = ~15% correction
- */
- public static final ErrorCorrectionLevel M = new ErrorCorrectionLevel(1, 0x00, "M");
- /**
- * Q = ~25% correction
- */
- public static final ErrorCorrectionLevel Q = new ErrorCorrectionLevel(2, 0x03, "Q");
- /**
- * H = ~30% correction
- */
- public static final ErrorCorrectionLevel H = new ErrorCorrectionLevel(3, 0x02, "H");
-
- private static final ErrorCorrectionLevel[] FOR_BITS = {M, L, H, Q};
-
- private final int ordinal;
- private final int bits;
- private final String name;
-
- private ErrorCorrectionLevel(int ordinal, int bits, String name) {
- this.ordinal = ordinal;
- this.bits = bits;
- this.name = name;
- }
-
- public int ordinal() {
- return ordinal;
- }
-
- public int getBits() {
- return bits;
- }
-
- public String getName() {
- return name;
- }
-
- public String toString() {
- return name;
- }
-
- /**
- * @param bits int containing the two bits encoding a QR Code's error correction level
- * @return ErrorCorrectionLevel representing the encoded error correction level
- */
- public static ErrorCorrectionLevel forBits(int bits) {
- if (bits < 0 || bits >= FOR_BITS.length) {
- throw new IllegalArgumentException();
- }
- return FOR_BITS[bits];
- }
-
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/FormatInformation.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/FormatInformation.java
deleted file mode 100644
index 1b76b0de5..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/FormatInformation.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-/**
- * <p>Encapsulates a QR Code's format information, including the data mask used and
- * error correction level.</p>
- *
- * @author Sean Owen
- * @see DataMask
- * @see ErrorCorrectionLevel
- */
-final class FormatInformation {
-
- private static final int FORMAT_INFO_MASK_QR = 0x5412;
-
- /**
- * See ISO 18004:2006, Annex C, Table C.1
- */
- private static final int[][] FORMAT_INFO_DECODE_LOOKUP = {
- {0x5412, 0x00},
- {0x5125, 0x01},
- {0x5E7C, 0x02},
- {0x5B4B, 0x03},
- {0x45F9, 0x04},
- {0x40CE, 0x05},
- {0x4F97, 0x06},
- {0x4AA0, 0x07},
- {0x77C4, 0x08},
- {0x72F3, 0x09},
- {0x7DAA, 0x0A},
- {0x789D, 0x0B},
- {0x662F, 0x0C},
- {0x6318, 0x0D},
- {0x6C41, 0x0E},
- {0x6976, 0x0F},
- {0x1689, 0x10},
- {0x13BE, 0x11},
- {0x1CE7, 0x12},
- {0x19D0, 0x13},
- {0x0762, 0x14},
- {0x0255, 0x15},
- {0x0D0C, 0x16},
- {0x083B, 0x17},
- {0x355F, 0x18},
- {0x3068, 0x19},
- {0x3F31, 0x1A},
- {0x3A06, 0x1B},
- {0x24B4, 0x1C},
- {0x2183, 0x1D},
- {0x2EDA, 0x1E},
- {0x2BED, 0x1F},
- };
-
- /**
- * Offset i holds the number of 1 bits in the binary representation of i
- */
- private static final int[] BITS_SET_IN_HALF_BYTE =
- {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
-
- private final ErrorCorrectionLevel errorCorrectionLevel;
- private final byte dataMask;
-
- private FormatInformation(int formatInfo) {
- // Bits 3,4
- errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03);
- // Bottom 3 bits
- dataMask = (byte) (formatInfo & 0x07);
- }
-
- static int numBitsDiffering(int a, int b) {
- a ^= b; // a now has a 1 bit exactly where its bit differs with b's
- // Count bits set quickly with a series of lookups:
- return BITS_SET_IN_HALF_BYTE[a & 0x0F] +
- BITS_SET_IN_HALF_BYTE[(a >>> 4 & 0x0F)] +
- BITS_SET_IN_HALF_BYTE[(a >>> 8 & 0x0F)] +
- BITS_SET_IN_HALF_BYTE[(a >>> 12 & 0x0F)] +
- BITS_SET_IN_HALF_BYTE[(a >>> 16 & 0x0F)] +
- BITS_SET_IN_HALF_BYTE[(a >>> 20 & 0x0F)] +
- BITS_SET_IN_HALF_BYTE[(a >>> 24 & 0x0F)] +
- BITS_SET_IN_HALF_BYTE[(a >>> 28 & 0x0F)];
- }
-
- /**
- * @param maskedFormatInfo1 format info indicator, with mask still applied
- * @param maskedFormatInfo2 second copy of same info; both are checked at the same time
- * to establish best match
- * @return information about the format it specifies, or <code>null</code>
- * if doesn't seem to match any known pattern
- */
- static FormatInformation decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) {
- FormatInformation formatInfo = doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2);
- if (formatInfo != null) {
- return formatInfo;
- }
- // Should return null, but, some QR codes apparently
- // do not mask this info. Try again by actually masking the pattern
- // first
- return doDecodeFormatInformation(maskedFormatInfo1 ^ FORMAT_INFO_MASK_QR,
- maskedFormatInfo2 ^ FORMAT_INFO_MASK_QR);
- }
-
- private static FormatInformation doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) {
- // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing
- int bestDifference = Integer.MAX_VALUE;
- int bestFormatInfo = 0;
- for (int i = 0; i < FORMAT_INFO_DECODE_LOOKUP.length; i++) {
- int[] decodeInfo = FORMAT_INFO_DECODE_LOOKUP[i];
- int targetInfo = decodeInfo[0];
- if (targetInfo == maskedFormatInfo1 || targetInfo == maskedFormatInfo2) {
- // Found an exact match
- return new FormatInformation(decodeInfo[1]);
- }
- int bitsDifference = numBitsDiffering(maskedFormatInfo1, targetInfo);
- if (bitsDifference < bestDifference) {
- bestFormatInfo = decodeInfo[1];
- bestDifference = bitsDifference;
- }
- if (maskedFormatInfo1 != maskedFormatInfo2) {
- // also try the other option
- bitsDifference = numBitsDiffering(maskedFormatInfo2, targetInfo);
- if (bitsDifference < bestDifference) {
- bestFormatInfo = decodeInfo[1];
- bestDifference = bitsDifference;
- }
- }
- }
- // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits
- // differing means we found a match
- if (bestDifference <= 3) {
- return new FormatInformation(bestFormatInfo);
- }
- return null;
- }
-
- ErrorCorrectionLevel getErrorCorrectionLevel() {
- return errorCorrectionLevel;
- }
-
- byte getDataMask() {
- return dataMask;
- }
-
- public int hashCode() {
- return (errorCorrectionLevel.ordinal() << 3) | (int) dataMask;
- }
-
- public boolean equals(Object o) {
- if (!(o instanceof FormatInformation)) {
- return false;
- }
- FormatInformation other = (FormatInformation) o;
- return this.errorCorrectionLevel == other.errorCorrectionLevel &&
- this.dataMask == other.dataMask;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Mode.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Mode.java
deleted file mode 100644
index 3c66217d3..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Mode.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-/**
- * <p>See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which
- * data can be encoded to bits in the QR code standard.</p>
- *
- * @author Sean Owen
- */
-public final class Mode {
-
- // No, we can't use an enum here. J2ME doesn't support it.
-
- public static final Mode TERMINATOR = new Mode(new int[]{0, 0, 0}, 0x00, "TERMINATOR"); // Not really a mode...
- public static final Mode NUMERIC = new Mode(new int[]{10, 12, 14}, 0x01, "NUMERIC");
- public static final Mode ALPHANUMERIC = new Mode(new int[]{9, 11, 13}, 0x02, "ALPHANUMERIC");
- public static final Mode STRUCTURED_APPEND = new Mode(new int[]{0, 0, 0}, 0x03, "STRUCTURED_APPEND"); // Not supported
- public static final Mode BYTE = new Mode(new int[]{8, 16, 16}, 0x04, "BYTE");
- public static final Mode ECI = new Mode(null, 0x07, "ECI"); // character counts don't apply
- public static final Mode KANJI = new Mode(new int[]{8, 10, 12}, 0x08, "KANJI");
- public static final Mode FNC1_FIRST_POSITION = new Mode(null, 0x05, "FNC1_FIRST_POSITION");
- public static final Mode FNC1_SECOND_POSITION = new Mode(null, 0x09, "FNC1_SECOND_POSITION");
- /** See GBT 18284-2000; "Hanzi" is a transliteration of this mode name. */
- public static final Mode HANZI = new Mode(new int[]{8, 10, 12}, 0x0D, "HANZI");
-
- private final int[] characterCountBitsForVersions;
- private final int bits;
- private final String name;
-
- private Mode(int[] characterCountBitsForVersions, int bits, String name) {
- this.characterCountBitsForVersions = characterCountBitsForVersions;
- this.bits = bits;
- this.name = name;
- }
-
- /**
- * @param bits four bits encoding a QR Code data mode
- * @return Mode encoded by these bits
- * @throws IllegalArgumentException if bits do not correspond to a known mode
- */
- public static Mode forBits(int bits) {
- switch (bits) {
- case 0x0:
- return TERMINATOR;
- case 0x1:
- return NUMERIC;
- case 0x2:
- return ALPHANUMERIC;
- case 0x3:
- return STRUCTURED_APPEND;
- case 0x4:
- return BYTE;
- case 0x5:
- return FNC1_FIRST_POSITION;
- case 0x7:
- return ECI;
- case 0x8:
- return KANJI;
- case 0x9:
- return FNC1_SECOND_POSITION;
- case 0xD:
- // 0xD is defined in GBT 18284-2000, may not be supported in foreign country
- return HANZI;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- /**
- * @param version version in question
- * @return number of bits used, in this QR Code symbol {@link Version}, to encode the
- * count of characters that will follow encoded in this Mode
- */
- public int getCharacterCountBits(Version version) {
- if (characterCountBitsForVersions == null) {
- throw new IllegalArgumentException("Character count doesn't apply to this mode");
- }
- int number = version.getVersionNumber();
- int offset;
- if (number <= 9) {
- offset = 0;
- } else if (number <= 26) {
- offset = 1;
- } else {
- offset = 2;
- }
- return characterCountBitsForVersions[offset];
- }
-
- public int getBits() {
- return bits;
- }
-
- public String getName() {
- return name;
- }
-
- public String toString() {
- return name;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Version.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Version.java
deleted file mode 100644
index ba795de42..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Version.java
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-import com.google.zxing.FormatException;
-import com.google.zxing.common.BitMatrix;
-
-/**
- * See ISO 18004:2006 Annex D
- *
- * @author Sean Owen
- */
-public final class Version {
-
- /**
- * See ISO 18004:2006 Annex D.
- * Element i represents the raw version bits that specify version i + 7
- */
- private static final int[] VERSION_DECODE_INFO = {
- 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6,
- 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78,
- 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683,
- 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB,
- 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250,
- 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B,
- 0x2542E, 0x26A64, 0x27541, 0x28C69
- };
-
- private static final Version[] VERSIONS = buildVersions();
-
- private final int versionNumber;
- private final int[] alignmentPatternCenters;
- private final ECBlocks[] ecBlocks;
- private final int totalCodewords;
-
- private Version(int versionNumber,
- int[] alignmentPatternCenters,
- ECBlocks ecBlocks1,
- ECBlocks ecBlocks2,
- ECBlocks ecBlocks3,
- ECBlocks ecBlocks4) {
- this.versionNumber = versionNumber;
- this.alignmentPatternCenters = alignmentPatternCenters;
- this.ecBlocks = new ECBlocks[]{ecBlocks1, ecBlocks2, ecBlocks3, ecBlocks4};
- int total = 0;
- int ecCodewords = ecBlocks1.getECCodewordsPerBlock();
- ECB[] ecbArray = ecBlocks1.getECBlocks();
- for (int i = 0; i < ecbArray.length; i++) {
- ECB ecBlock = ecbArray[i];
- total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);
- }
- this.totalCodewords = total;
- }
-
- public int getVersionNumber() {
- return versionNumber;
- }
-
- public int[] getAlignmentPatternCenters() {
- return alignmentPatternCenters;
- }
-
- public int getTotalCodewords() {
- return totalCodewords;
- }
-
- public int getDimensionForVersion() {
- return 17 + 4 * versionNumber;
- }
-
- public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) {
- return ecBlocks[ecLevel.ordinal()];
- }
-
- /**
- * <p>Deduces version information purely from QR Code dimensions.</p>
- *
- * @param dimension dimension in modules
- * @return Version for a QR Code of that dimension
- * @throws FormatException if dimension is not 1 mod 4
- */
- public static Version getProvisionalVersionForDimension(int dimension) throws FormatException {
- if (dimension % 4 != 1) {
- throw FormatException.getFormatInstance();
- }
- try {
- return getVersionForNumber((dimension - 17) >> 2);
- } catch (IllegalArgumentException iae) {
- throw FormatException.getFormatInstance();
- }
- }
-
- public static Version getVersionForNumber(int versionNumber) {
- if (versionNumber < 1 || versionNumber > 40) {
- throw new IllegalArgumentException();
- }
- return VERSIONS[versionNumber - 1];
- }
-
- static Version decodeVersionInformation(int versionBits) {
- int bestDifference = Integer.MAX_VALUE;
- int bestVersion = 0;
- for (int i = 0; i < VERSION_DECODE_INFO.length; i++) {
- int targetVersion = VERSION_DECODE_INFO[i];
- // Do the version info bits match exactly? done.
- if (targetVersion == versionBits) {
- return getVersionForNumber(i + 7);
- }
- // Otherwise see if this is the closest to a real version info bit string
- // we have seen so far
- int bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion);
- if (bitsDifference < bestDifference) {
- bestVersion = i + 7;
- bestDifference = bitsDifference;
- }
- }
- // We can tolerate up to 3 bits of error since no two version info codewords will
- // differ in less than 8 bits.
- if (bestDifference <= 3) {
- return getVersionForNumber(bestVersion);
- }
- // If we didn't find a close enough match, fail
- return null;
- }
-
- /**
- * See ISO 18004:2006 Annex E
- */
- BitMatrix buildFunctionPattern() {
- int dimension = getDimensionForVersion();
- BitMatrix bitMatrix = new BitMatrix(dimension);
-
- // Top left finder pattern + separator + format
- bitMatrix.setRegion(0, 0, 9, 9);
- // Top right finder pattern + separator + format
- bitMatrix.setRegion(dimension - 8, 0, 8, 9);
- // Bottom left finder pattern + separator + format
- bitMatrix.setRegion(0, dimension - 8, 9, 8);
-
- // Alignment patterns
- int max = alignmentPatternCenters.length;
- for (int x = 0; x < max; x++) {
- int i = alignmentPatternCenters[x] - 2;
- for (int y = 0; y < max; y++) {
- if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) {
- // No alignment patterns near the three finder paterns
- continue;
- }
- bitMatrix.setRegion(alignmentPatternCenters[y] - 2, i, 5, 5);
- }
- }
-
- // Vertical timing pattern
- bitMatrix.setRegion(6, 9, 1, dimension - 17);
- // Horizontal timing pattern
- bitMatrix.setRegion(9, 6, dimension - 17, 1);
-
- if (versionNumber > 6) {
- // Version info, top right
- bitMatrix.setRegion(dimension - 11, 0, 3, 6);
- // Version info, bottom left
- bitMatrix.setRegion(0, dimension - 11, 6, 3);
- }
-
- return bitMatrix;
- }
-
- /**
- * <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will
- * use blocks of differing sizes within one version, so, this encapsulates the parameters for
- * each set of blocks. It also holds the number of error-correction codewords per block since it
- * will be the same across all blocks within one version.</p>
- */
- public static final class ECBlocks {
- private final int ecCodewordsPerBlock;
- private final ECB[] ecBlocks;
-
- ECBlocks(int ecCodewordsPerBlock, ECB ecBlocks) {
- this.ecCodewordsPerBlock = ecCodewordsPerBlock;
- this.ecBlocks = new ECB[]{ecBlocks};
- }
-
- ECBlocks(int ecCodewordsPerBlock, ECB ecBlocks1, ECB ecBlocks2) {
- this.ecCodewordsPerBlock = ecCodewordsPerBlock;
- this.ecBlocks = new ECB[]{ecBlocks1, ecBlocks2};
- }
-
- public int getECCodewordsPerBlock() {
- return ecCodewordsPerBlock;
- }
-
- public int getNumBlocks() {
- int total = 0;
- for (int i = 0; i < ecBlocks.length; i++) {
- total += ecBlocks[i].getCount();
- }
- return total;
- }
-
- public int getTotalECCodewords() {
- return ecCodewordsPerBlock * getNumBlocks();
- }
-
- public ECB[] getECBlocks() {
- return ecBlocks;
- }
- }
-
- /**
- * <p>Encapsualtes the parameters for one error-correction block in one symbol version.
- * This includes the number of data codewords, and the number of times a block with these
- * parameters is used consecutively in the QR code version's format.</p>
- */
- public static final class ECB {
- private final int count;
- private final int dataCodewords;
-
- ECB(int count, int dataCodewords) {
- this.count = count;
- this.dataCodewords = dataCodewords;
- }
-
- public int getCount() {
- return count;
- }
-
- public int getDataCodewords() {
- return dataCodewords;
- }
- }
-
- public String toString() {
- return String.valueOf(versionNumber);
- }
-
- /**
- * See ISO 18004:2006 6.5.1 Table 9
- */
- private static Version[] buildVersions() {
- return new Version[]{
- new Version(1, new int[]{},
- new ECBlocks(7, new ECB(1, 19)),
- new ECBlocks(10, new ECB(1, 16)),
- new ECBlocks(13, new ECB(1, 13)),
- new ECBlocks(17, new ECB(1, 9))),
- new Version(2, new int[]{6, 18},
- new ECBlocks(10, new ECB(1, 34)),
- new ECBlocks(16, new ECB(1, 28)),
- new ECBlocks(22, new ECB(1, 22)),
- new ECBlocks(28, new ECB(1, 16))),
- new Version(3, new int[]{6, 22},
- new ECBlocks(15, new ECB(1, 55)),
- new ECBlocks(26, new ECB(1, 44)),
- new ECBlocks(18, new ECB(2, 17)),
- new ECBlocks(22, new ECB(2, 13))),
- new Version(4, new int[]{6, 26},
- new ECBlocks(20, new ECB(1, 80)),
- new ECBlocks(18, new ECB(2, 32)),
- new ECBlocks(26, new ECB(2, 24)),
- new ECBlocks(16, new ECB(4, 9))),
- new Version(5, new int[]{6, 30},
- new ECBlocks(26, new ECB(1, 108)),
- new ECBlocks(24, new ECB(2, 43)),
- new ECBlocks(18, new ECB(2, 15),
- new ECB(2, 16)),
- new ECBlocks(22, new ECB(2, 11),
- new ECB(2, 12))),
- new Version(6, new int[]{6, 34},
- new ECBlocks(18, new ECB(2, 68)),
- new ECBlocks(16, new ECB(4, 27)),
- new ECBlocks(24, new ECB(4, 19)),
- new ECBlocks(28, new ECB(4, 15))),
- new Version(7, new int[]{6, 22, 38},
- new ECBlocks(20, new ECB(2, 78)),
- new ECBlocks(18, new ECB(4, 31)),
- new ECBlocks(18, new ECB(2, 14),
- new ECB(4, 15)),
- new ECBlocks(26, new ECB(4, 13),
- new ECB(1, 14))),
- new Version(8, new int[]{6, 24, 42},
- new ECBlocks(24, new ECB(2, 97)),
- new ECBlocks(22, new ECB(2, 38),
- new ECB(2, 39)),
- new ECBlocks(22, new ECB(4, 18),
- new ECB(2, 19)),
- new ECBlocks(26, new ECB(4, 14),
- new ECB(2, 15))),
- new Version(9, new int[]{6, 26, 46},
- new ECBlocks(30, new ECB(2, 116)),
- new ECBlocks(22, new ECB(3, 36),
- new ECB(2, 37)),
- new ECBlocks(20, new ECB(4, 16),
- new ECB(4, 17)),
- new ECBlocks(24, new ECB(4, 12),
- new ECB(4, 13))),
- new Version(10, new int[]{6, 28, 50},
- new ECBlocks(18, new ECB(2, 68),
- new ECB(2, 69)),
- new ECBlocks(26, new ECB(4, 43),
- new ECB(1, 44)),
- new ECBlocks(24, new ECB(6, 19),
- new ECB(2, 20)),
- new ECBlocks(28, new ECB(6, 15),
- new ECB(2, 16))),
- new Version(11, new int[]{6, 30, 54},
- new ECBlocks(20, new ECB(4, 81)),
- new ECBlocks(30, new ECB(1, 50),
- new ECB(4, 51)),
- new ECBlocks(28, new ECB(4, 22),
- new ECB(4, 23)),
- new ECBlocks(24, new ECB(3, 12),
- new ECB(8, 13))),
- new Version(12, new int[]{6, 32, 58},
- new ECBlocks(24, new ECB(2, 92),
- new ECB(2, 93)),
- new ECBlocks(22, new ECB(6, 36),
- new ECB(2, 37)),
- new ECBlocks(26, new ECB(4, 20),
- new ECB(6, 21)),
- new ECBlocks(28, new ECB(7, 14),
- new ECB(4, 15))),
- new Version(13, new int[]{6, 34, 62},
- new ECBlocks(26, new ECB(4, 107)),
- new ECBlocks(22, new ECB(8, 37),
- new ECB(1, 38)),
- new ECBlocks(24, new ECB(8, 20),
- new ECB(4, 21)),
- new ECBlocks(22, new ECB(12, 11),
- new ECB(4, 12))),
- new Version(14, new int[]{6, 26, 46, 66},
- new ECBlocks(30, new ECB(3, 115),
- new ECB(1, 116)),
- new ECBlocks(24, new ECB(4, 40),
- new ECB(5, 41)),
- new ECBlocks(20, new ECB(11, 16),
- new ECB(5, 17)),
- new ECBlocks(24, new ECB(11, 12),
- new ECB(5, 13))),
- new Version(15, new int[]{6, 26, 48, 70},
- new ECBlocks(22, new ECB(5, 87),
- new ECB(1, 88)),
- new ECBlocks(24, new ECB(5, 41),
- new ECB(5, 42)),
- new ECBlocks(30, new ECB(5, 24),
- new ECB(7, 25)),
- new ECBlocks(24, new ECB(11, 12),
- new ECB(7, 13))),
- new Version(16, new int[]{6, 26, 50, 74},
- new ECBlocks(24, new ECB(5, 98),
- new ECB(1, 99)),
- new ECBlocks(28, new ECB(7, 45),
- new ECB(3, 46)),
- new ECBlocks(24, new ECB(15, 19),
- new ECB(2, 20)),
- new ECBlocks(30, new ECB(3, 15),
- new ECB(13, 16))),
- new Version(17, new int[]{6, 30, 54, 78},
- new ECBlocks(28, new ECB(1, 107),
- new ECB(5, 108)),
- new ECBlocks(28, new ECB(10, 46),
- new ECB(1, 47)),
- new ECBlocks(28, new ECB(1, 22),
- new ECB(15, 23)),
- new ECBlocks(28, new ECB(2, 14),
- new ECB(17, 15))),
- new Version(18, new int[]{6, 30, 56, 82},
- new ECBlocks(30, new ECB(5, 120),
- new ECB(1, 121)),
- new ECBlocks(26, new ECB(9, 43),
- new ECB(4, 44)),
- new ECBlocks(28, new ECB(17, 22),
- new ECB(1, 23)),
- new ECBlocks(28, new ECB(2, 14),
- new ECB(19, 15))),
- new Version(19, new int[]{6, 30, 58, 86},
- new ECBlocks(28, new ECB(3, 113),
- new ECB(4, 114)),
- new ECBlocks(26, new ECB(3, 44),
- new ECB(11, 45)),
- new ECBlocks(26, new ECB(17, 21),
- new ECB(4, 22)),
- new ECBlocks(26, new ECB(9, 13),
- new ECB(16, 14))),
- new Version(20, new int[]{6, 34, 62, 90},
- new ECBlocks(28, new ECB(3, 107),
- new ECB(5, 108)),
- new ECBlocks(26, new ECB(3, 41),
- new ECB(13, 42)),
- new ECBlocks(30, new ECB(15, 24),
- new ECB(5, 25)),
- new ECBlocks(28, new ECB(15, 15),
- new ECB(10, 16))),
- new Version(21, new int[]{6, 28, 50, 72, 94},
- new ECBlocks(28, new ECB(4, 116),
- new ECB(4, 117)),
- new ECBlocks(26, new ECB(17, 42)),
- new ECBlocks(28, new ECB(17, 22),
- new ECB(6, 23)),
- new ECBlocks(30, new ECB(19, 16),
- new ECB(6, 17))),
- new Version(22, new int[]{6, 26, 50, 74, 98},
- new ECBlocks(28, new ECB(2, 111),
- new ECB(7, 112)),
- new ECBlocks(28, new ECB(17, 46)),
- new ECBlocks(30, new ECB(7, 24),
- new ECB(16, 25)),
- new ECBlocks(24, new ECB(34, 13))),
- new Version(23, new int[]{6, 30, 54, 78, 102},
- new ECBlocks(30, new ECB(4, 121),
- new ECB(5, 122)),
- new ECBlocks(28, new ECB(4, 47),
- new ECB(14, 48)),
- new ECBlocks(30, new ECB(11, 24),
- new ECB(14, 25)),
- new ECBlocks(30, new ECB(16, 15),
- new ECB(14, 16))),
- new Version(24, new int[]{6, 28, 54, 80, 106},
- new ECBlocks(30, new ECB(6, 117),
- new ECB(4, 118)),
- new ECBlocks(28, new ECB(6, 45),
- new ECB(14, 46)),
- new ECBlocks(30, new ECB(11, 24),
- new ECB(16, 25)),
- new ECBlocks(30, new ECB(30, 16),
- new ECB(2, 17))),
- new Version(25, new int[]{6, 32, 58, 84, 110},
- new ECBlocks(26, new ECB(8, 106),
- new ECB(4, 107)),
- new ECBlocks(28, new ECB(8, 47),
- new ECB(13, 48)),
- new ECBlocks(30, new ECB(7, 24),
- new ECB(22, 25)),
- new ECBlocks(30, new ECB(22, 15),
- new ECB(13, 16))),
- new Version(26, new int[]{6, 30, 58, 86, 114},
- new ECBlocks(28, new ECB(10, 114),
- new ECB(2, 115)),
- new ECBlocks(28, new ECB(19, 46),
- new ECB(4, 47)),
- new ECBlocks(28, new ECB(28, 22),
- new ECB(6, 23)),
- new ECBlocks(30, new ECB(33, 16),
- new ECB(4, 17))),
- new Version(27, new int[]{6, 34, 62, 90, 118},
- new ECBlocks(30, new ECB(8, 122),
- new ECB(4, 123)),
- new ECBlocks(28, new ECB(22, 45),
- new ECB(3, 46)),
- new ECBlocks(30, new ECB(8, 23),
- new ECB(26, 24)),
- new ECBlocks(30, new ECB(12, 15),
- new ECB(28, 16))),
- new Version(28, new int[]{6, 26, 50, 74, 98, 122},
- new ECBlocks(30, new ECB(3, 117),
- new ECB(10, 118)),
- new ECBlocks(28, new ECB(3, 45),
- new ECB(23, 46)),
- new ECBlocks(30, new ECB(4, 24),
- new ECB(31, 25)),
- new ECBlocks(30, new ECB(11, 15),
- new ECB(31, 16))),
- new Version(29, new int[]{6, 30, 54, 78, 102, 126},
- new ECBlocks(30, new ECB(7, 116),
- new ECB(7, 117)),
- new ECBlocks(28, new ECB(21, 45),
- new ECB(7, 46)),
- new ECBlocks(30, new ECB(1, 23),
- new ECB(37, 24)),
- new ECBlocks(30, new ECB(19, 15),
- new ECB(26, 16))),
- new Version(30, new int[]{6, 26, 52, 78, 104, 130},
- new ECBlocks(30, new ECB(5, 115),
- new ECB(10, 116)),
- new ECBlocks(28, new ECB(19, 47),
- new ECB(10, 48)),
- new ECBlocks(30, new ECB(15, 24),
- new ECB(25, 25)),
- new ECBlocks(30, new ECB(23, 15),
- new ECB(25, 16))),
- new Version(31, new int[]{6, 30, 56, 82, 108, 134},
- new ECBlocks(30, new ECB(13, 115),
- new ECB(3, 116)),
- new ECBlocks(28, new ECB(2, 46),
- new ECB(29, 47)),
- new ECBlocks(30, new ECB(42, 24),
- new ECB(1, 25)),
- new ECBlocks(30, new ECB(23, 15),
- new ECB(28, 16))),
- new Version(32, new int[]{6, 34, 60, 86, 112, 138},
- new ECBlocks(30, new ECB(17, 115)),
- new ECBlocks(28, new ECB(10, 46),
- new ECB(23, 47)),
- new ECBlocks(30, new ECB(10, 24),
- new ECB(35, 25)),
- new ECBlocks(30, new ECB(19, 15),
- new ECB(35, 16))),
- new Version(33, new int[]{6, 30, 58, 86, 114, 142},
- new ECBlocks(30, new ECB(17, 115),
- new ECB(1, 116)),
- new ECBlocks(28, new ECB(14, 46),
- new ECB(21, 47)),
- new ECBlocks(30, new ECB(29, 24),
- new ECB(19, 25)),
- new ECBlocks(30, new ECB(11, 15),
- new ECB(46, 16))),
- new Version(34, new int[]{6, 34, 62, 90, 118, 146},
- new ECBlocks(30, new ECB(13, 115),
- new ECB(6, 116)),
- new ECBlocks(28, new ECB(14, 46),
- new ECB(23, 47)),
- new ECBlocks(30, new ECB(44, 24),
- new ECB(7, 25)),
- new ECBlocks(30, new ECB(59, 16),
- new ECB(1, 17))),
- new Version(35, new int[]{6, 30, 54, 78, 102, 126, 150},
- new ECBlocks(30, new ECB(12, 121),
- new ECB(7, 122)),
- new ECBlocks(28, new ECB(12, 47),
- new ECB(26, 48)),
- new ECBlocks(30, new ECB(39, 24),
- new ECB(14, 25)),
- new ECBlocks(30, new ECB(22, 15),
- new ECB(41, 16))),
- new Version(36, new int[]{6, 24, 50, 76, 102, 128, 154},
- new ECBlocks(30, new ECB(6, 121),
- new ECB(14, 122)),
- new ECBlocks(28, new ECB(6, 47),
- new ECB(34, 48)),
- new ECBlocks(30, new ECB(46, 24),
- new ECB(10, 25)),
- new ECBlocks(30, new ECB(2, 15),
- new ECB(64, 16))),
- new Version(37, new int[]{6, 28, 54, 80, 106, 132, 158},
- new ECBlocks(30, new ECB(17, 122),
- new ECB(4, 123)),
- new ECBlocks(28, new ECB(29, 46),
- new ECB(14, 47)),
- new ECBlocks(30, new ECB(49, 24),
- new ECB(10, 25)),
- new ECBlocks(30, new ECB(24, 15),
- new ECB(46, 16))),
- new Version(38, new int[]{6, 32, 58, 84, 110, 136, 162},
- new ECBlocks(30, new ECB(4, 122),
- new ECB(18, 123)),
- new ECBlocks(28, new ECB(13, 46),
- new ECB(32, 47)),
- new ECBlocks(30, new ECB(48, 24),
- new ECB(14, 25)),
- new ECBlocks(30, new ECB(42, 15),
- new ECB(32, 16))),
- new Version(39, new int[]{6, 26, 54, 82, 110, 138, 166},
- new ECBlocks(30, new ECB(20, 117),
- new ECB(4, 118)),
- new ECBlocks(28, new ECB(40, 47),
- new ECB(7, 48)),
- new ECBlocks(30, new ECB(43, 24),
- new ECB(22, 25)),
- new ECBlocks(30, new ECB(10, 15),
- new ECB(67, 16))),
- new Version(40, new int[]{6, 30, 58, 86, 114, 142, 170},
- new ECBlocks(30, new ECB(19, 118),
- new ECB(6, 119)),
- new ECBlocks(28, new ECB(18, 47),
- new ECB(31, 48)),
- new ECBlocks(30, new ECB(34, 24),
- new ECB(34, 25)),
- new ECBlocks(30, new ECB(20, 15),
- new ECB(61, 16)))
- };
- }
-
-}