X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=core%2Fsrc%2Fcom%2Fgoogle%2Fzxing%2Fqrcode%2Fdecoder%2FDecodedBitStreamParser.java;h=b6efa2b25f41ed2cf02104908bfece154446c393;hb=d0ff60320c6b6755fbaefa710bdcb25a92c882d8;hp=917a7ff17e61c54f3752d5f90417196b4dbc3946;hpb=1170ad08b19f495ae38daf72a816ac60e5606aae;p=zxing.git diff --git a/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java b/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java index 917a7ff1..b6efa2b2 100644 --- a/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java +++ b/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java @@ -57,7 +57,7 @@ final class DecodedBitStreamParser { private DecodedBitStreamParser() { } - static DecoderResult decode(byte[] bytes, Version version) throws ReaderException { + static DecoderResult decode(byte[] bytes, Version version, ErrorCorrectionLevel ecLevel) throws ReaderException { BitSource bits = new BitSource(bytes); StringBuffer result = new StringBuffer(); CharacterSetECI currentCharacterSetECI = null; @@ -70,19 +70,26 @@ final class DecodedBitStreamParser { // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here mode = Mode.TERMINATOR; } else { - mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits + try { + mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits + } catch (IllegalArgumentException iae) { + throw ReaderException.getInstance(); + } } 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); - try { - currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value); - } catch (IllegalArgumentException iae) { - // unsupported... just continue? + currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value); + if (currentCharacterSetECI == null) { + throw ReaderException.getInstance(); } } else { // How many characters will follow, encoded in this mode? @@ -102,7 +109,7 @@ final class DecodedBitStreamParser { } } while (!mode.equals(Mode.TERMINATOR)); - return new DecoderResult(bytes, result.toString(), byteSegments.isEmpty() ? null : byteSegments); + return new DecoderResult(bytes, result.toString(), byteSegments.isEmpty() ? null : byteSegments, ecLevel); } private static void decodeKanjiSegment(BitSource bits, @@ -251,7 +258,7 @@ final class DecodedBitStreamParser { int length = bytes.length; boolean canBeISO88591 = true; boolean canBeShiftJIS = true; - boolean sawDoubleByteStart = false; + int maybeDoubleByteCount = 0; int maybeSingleByteKatakanaCount = 0; boolean sawLatin1Supplement = false; boolean lastWasPossibleDoubleByteStart = false; @@ -278,10 +285,9 @@ final class DecodedBitStreamParser { if (!lastWasPossibleDoubleByteStart && ((value >= 0xF0 && value <= 0xFF) || value == 0x80 || value == 0xA0)) { canBeShiftJIS = false; } - if (((value >= 0x81 && value <= 0x9F) || (value >= 0xE0 && value <= 0xEF)) && i < length - 1) { + if (((value >= 0x81 && value <= 0x9F) || (value >= 0xE0 && value <= 0xEF))) { // These start double-byte characters in Shift_JIS. Let's see if it's followed by a valid // second byte. - sawDoubleByteStart = true; if (lastWasPossibleDoubleByteStart) { // If we just checked this and the last byte for being a valid double-byte // char, don't check starting on this byte. If this and the last byte @@ -292,12 +298,18 @@ final class DecodedBitStreamParser { // ... otherwise do check to see if this plus the next byte form a valid // double byte pair encoding a character. lastWasPossibleDoubleByteStart = true; - int nextValue = bytes[i + 1] & 0xFF; - if (nextValue < 0x40 || nextValue > 0xFC) { + if (i >= bytes.length - 1) { canBeShiftJIS = false; + } else { + int nextValue = bytes[i + 1] & 0xFF; + if (nextValue < 0x40 || nextValue > 0xFC) { + canBeShiftJIS = false; + } else { + maybeDoubleByteCount++; + } + // There is some conflicting information out there about which bytes can follow which in + // double-byte Shift_JIS characters. The rule above seems to be the one that matches practice. } - // There is some conflicting information out there about which bytes can follow which in - // double-byte Shift_JIS characters. The rule above seems to be the one that matches practice. } } else { lastWasPossibleDoubleByteStart = false; @@ -305,10 +317,10 @@ final class DecodedBitStreamParser { } // Distinguishing Shift_JIS and ISO-8859-1 can be a little tough. The crude heuristic is: // - If we saw - // - at least one byte that starts a double-byte value (bytes that are rare in ISO-8859-1), or + // - at least three byte that starts a double-byte value (bytes that are rare in ISO-8859-1), or // - over 5% of bytes that could be single-byte Katakana (also rare in ISO-8859-1), // - and, saw no sequences that are invalid in Shift_JIS, then we conclude Shift_JIS - if (canBeShiftJIS && (sawDoubleByteStart || 20 * maybeSingleByteKatakanaCount > length)) { + if (canBeShiftJIS && (maybeDoubleByteCount >= 3 || 20 * maybeSingleByteKatakanaCount > length)) { return SHIFT_JIS; } // Otherwise, we default to ISO-8859-1 unless we know it can't be