mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
Added, at least, parsing of ECI mode in QR Code
git-svn-id: https://zxing.googlecode.com/svn/trunk@443 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
15f34edb52
commit
9ee69fee5a
|
@ -67,18 +67,27 @@ final class DecodedBitStreamParser {
|
||||||
mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits
|
mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits
|
||||||
}
|
}
|
||||||
if (!mode.equals(Mode.TERMINATOR)) {
|
if (!mode.equals(Mode.TERMINATOR)) {
|
||||||
// How many characters will follow, encoded in this mode?
|
if (mode.equals(Mode.ECI)) {
|
||||||
int count = bits.readBits(mode.getCharacterCountBits(version));
|
// Count doesn't apply to ECI
|
||||||
if (mode.equals(Mode.NUMERIC)) {
|
parseECI(bits);
|
||||||
decodeNumericSegment(bits, result, count);
|
// We don't currently do anything with ECI, since there seems to be no reference
|
||||||
} else if (mode.equals(Mode.ALPHANUMERIC)) {
|
// defining what each value means. AIM's "Extended Channel Interpretations" does
|
||||||
decodeAlphanumericSegment(bits, result, count);
|
// not define it. I have never observed a QR Code using it. So for now, we at least
|
||||||
} else if (mode.equals(Mode.BYTE)) {
|
// parse it but don't know how to take action on it.
|
||||||
decodeByteSegment(bits, result, count);
|
|
||||||
} else if (mode.equals(Mode.KANJI)) {
|
|
||||||
decodeKanjiSegment(bits, result, count);
|
|
||||||
} else {
|
} 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));
|
} while (!mode.equals(Mode.TERMINATOR));
|
||||||
|
@ -95,6 +104,23 @@ final class DecodedBitStreamParser {
|
||||||
return result.toString();
|
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,
|
private static void decodeKanjiSegment(BitSource bits,
|
||||||
StringBuffer result,
|
StringBuffer result,
|
||||||
int count) throws ReaderException {
|
int count) throws ReaderException {
|
||||||
|
|
|
@ -32,6 +32,7 @@ final class Mode {
|
||||||
static final Mode NUMERIC = new Mode(new int[]{10, 12, 14});
|
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 ALPHANUMERIC = new Mode(new int[]{9, 11, 13});
|
||||||
static final Mode BYTE = new Mode(new int[]{8, 16, 16});
|
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});
|
static final Mode KANJI = new Mode(new int[]{8, 10, 12});
|
||||||
|
|
||||||
private final int[] characterCountBitsForVersions;
|
private final int[] characterCountBitsForVersions;
|
||||||
|
@ -55,6 +56,8 @@ final class Mode {
|
||||||
return ALPHANUMERIC;
|
return ALPHANUMERIC;
|
||||||
case 0x4:
|
case 0x4:
|
||||||
return BYTE;
|
return BYTE;
|
||||||
|
case 0x7:
|
||||||
|
return ECI;
|
||||||
case 0x8:
|
case 0x8:
|
||||||
return KANJI;
|
return KANJI;
|
||||||
default:
|
default:
|
||||||
|
@ -68,6 +71,9 @@ final class Mode {
|
||||||
* count of characters that will follow encoded in this {@link Mode}
|
* count of characters that will follow encoded in this {@link Mode}
|
||||||
*/
|
*/
|
||||||
int getCharacterCountBits(Version version) {
|
int getCharacterCountBits(Version version) {
|
||||||
|
if (this == ECI) {
|
||||||
|
throw new UnsupportedOperationException("Character count doesn't apply to ECI mode");
|
||||||
|
}
|
||||||
int number = version.getVersionNumber();
|
int number = version.getVersionNumber();
|
||||||
int offset;
|
int offset;
|
||||||
if (number <= 9) {
|
if (number <= 9) {
|
||||||
|
|
Loading…
Reference in a new issue