Added, at least, parsing of ECI mode in QR Code
authorsrowen <srowen@59b500cc-1b3d-0410-9834-0bbf25fbcc57>
Thu, 19 Jun 2008 01:37:49 +0000 (01:37 +0000)
committersrowen <srowen@59b500cc-1b3d-0410-9834-0bbf25fbcc57>
Thu, 19 Jun 2008 01:37:49 +0000 (01:37 +0000)
git-svn-id: http://zxing.googlecode.com/svn/trunk@443 59b500cc-1b3d-0410-9834-0bbf25fbcc57

core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java
core/src/com/google/zxing/qrcode/decoder/Mode.java

index d253ef9..b6dda58 100644 (file)
@@ -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 {
index bf368f8..7f1d2f9 100644 (file)
@@ -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) {