From 2f3b0424cacfb3cd895a14822fc44411d314ead1 Mon Sep 17 00:00:00 2001 From: srowen Date: Thu, 19 Jun 2008 01:37:49 +0000 Subject: [PATCH 1/1] Added, at least, parsing of ECI mode in QR Code git-svn-id: http://zxing.googlecode.com/svn/trunk@443 59b500cc-1b3d-0410-9834-0bbf25fbcc57 --- .../decoder/DecodedBitStreamParser.java | 48 ++++++++++++++----- .../com/google/zxing/qrcode/decoder/Mode.java | 6 +++ 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java b/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java index d253ef94..b6dda58f 100644 --- a/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java +++ b/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java @@ -67,18 +67,27 @@ final class DecodedBitStreamParser { mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits } if (!mode.equals(Mode.TERMINATOR)) { - // 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); - } else if (mode.equals(Mode.BYTE)) { - decodeByteSegment(bits, result, count); - } else if (mode.equals(Mode.KANJI)) { - decodeKanjiSegment(bits, result, count); + if (mode.equals(Mode.ECI)) { + // Count doesn't apply to ECI + parseECI(bits); + // We don't currently do anything with ECI, since there seems to be no reference + // defining what each value means. AIM's "Extended Channel Interpretations" does + // not define it. I have never observed a QR Code using it. So for now, we at least + // parse it but don't know how to take action on it. } else { - throw new ReaderException("Unsupported mode indicator"); + // 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); + } else if (mode.equals(Mode.BYTE)) { + decodeByteSegment(bits, result, count); + } else if (mode.equals(Mode.KANJI)) { + decodeKanjiSegment(bits, result, count); + } else { + throw new ReaderException("Unsupported mode indicator"); + } } } } while (!mode.equals(Mode.TERMINATOR)); @@ -95,6 +104,23 @@ final class DecodedBitStreamParser { return result.toString(); } + private static int parseECI(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 secondByte = bits.readBits(8); + int thirdByte = bits.readBits(8); + return ((firstByte & 0x1F) << 16) | (secondByte << 8) | thirdByte; + } + } + private static void decodeKanjiSegment(BitSource bits, StringBuffer result, int count) throws ReaderException { diff --git a/core/src/com/google/zxing/qrcode/decoder/Mode.java b/core/src/com/google/zxing/qrcode/decoder/Mode.java index bf368f89..7f1d2f93 100644 --- a/core/src/com/google/zxing/qrcode/decoder/Mode.java +++ b/core/src/com/google/zxing/qrcode/decoder/Mode.java @@ -32,6 +32,7 @@ final class Mode { static final Mode NUMERIC = new Mode(new int[]{10, 12, 14}); static final Mode ALPHANUMERIC = new Mode(new int[]{9, 11, 13}); static final Mode BYTE = new Mode(new int[]{8, 16, 16}); + static final Mode ECI = new Mode(null); // character counts don't apply static final Mode KANJI = new Mode(new int[]{8, 10, 12}); private final int[] characterCountBitsForVersions; @@ -55,6 +56,8 @@ final class Mode { return ALPHANUMERIC; case 0x4: return BYTE; + case 0x7: + return ECI; case 0x8: return KANJI; default: @@ -68,6 +71,9 @@ final class Mode { * count of characters that will follow encoded in this {@link Mode} */ int getCharacterCountBits(Version version) { + if (this == ECI) { + throw new UnsupportedOperationException("Character count doesn't apply to ECI mode"); + } int number = version.getVersionNumber(); int offset; if (number <= 9) { -- 2.20.1