mirror of
https://github.com/zxing/zxing.git
synced 2025-01-13 04:07:27 -08:00
Catch more weird edge cases where readBits fails on bad QR codes and just return FormatException; remove a deprecated PDF417 method
git-svn-id: https://zxing.googlecode.com/svn/trunk@2542 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
02e0dcece1
commit
cc9a55d1a2
|
@ -22,7 +22,6 @@ import com.google.zxing.Writer;
|
||||||
import com.google.zxing.WriterException;
|
import com.google.zxing.WriterException;
|
||||||
import com.google.zxing.common.BitMatrix;
|
import com.google.zxing.common.BitMatrix;
|
||||||
|
|
||||||
import java.util.EnumMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,28 +69,6 @@ public final class PDF417Writer implements Writer {
|
||||||
return encode(contents, format, width, height, null);
|
return encode(contents, format, width, height, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use {@link #encode(String, BarcodeFormat, int, int, Map)} instead, with hints to
|
|
||||||
* specify the encoding options.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public BitMatrix encode(String contents,
|
|
||||||
BarcodeFormat format,
|
|
||||||
boolean compact,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int minCols,
|
|
||||||
int maxCols,
|
|
||||||
int minRows,
|
|
||||||
int maxRows,
|
|
||||||
Compaction compaction) throws WriterException {
|
|
||||||
Map<EncodeHintType, Object> hints = new EnumMap<EncodeHintType,Object>(EncodeHintType.class);
|
|
||||||
hints.put(EncodeHintType.PDF417_COMPACT, compact);
|
|
||||||
hints.put(EncodeHintType.PDF417_COMPACTION, compaction);
|
|
||||||
hints.put(EncodeHintType.PDF417_DIMENSIONS, new Dimensions(minCols, maxCols, minRows, maxRows));
|
|
||||||
return encode(contents, format, width, height, hints);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes encoder, accounts for width/height, and retrieves bit matrix
|
* Takes encoder, accounts for width/height, and retrieves bit matrix
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -59,68 +59,69 @@ final class DecodedBitStreamParser {
|
||||||
Map<DecodeHintType,?> hints) throws FormatException {
|
Map<DecodeHintType,?> hints) throws FormatException {
|
||||||
BitSource bits = new BitSource(bytes);
|
BitSource bits = new BitSource(bytes);
|
||||||
StringBuilder result = new StringBuilder(50);
|
StringBuilder result = new StringBuilder(50);
|
||||||
CharacterSetECI currentCharacterSetECI = null;
|
|
||||||
boolean fc1InEffect = false;
|
|
||||||
List<byte[]> byteSegments = new ArrayList<byte[]>(1);
|
List<byte[]> byteSegments = new ArrayList<byte[]>(1);
|
||||||
Mode mode;
|
try {
|
||||||
do {
|
CharacterSetECI currentCharacterSetECI = null;
|
||||||
// While still another segment to read...
|
boolean fc1InEffect = false;
|
||||||
if (bits.available() < 4) {
|
Mode mode;
|
||||||
// OK, assume we're done. Really, a TERMINATOR mode should have been recorded here
|
do {
|
||||||
mode = Mode.TERMINATOR;
|
// While still another segment to read...
|
||||||
} else {
|
if (bits.available() < 4) {
|
||||||
try {
|
// OK, assume we're done. Really, a TERMINATOR mode should have been recorded here
|
||||||
mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits
|
mode = Mode.TERMINATOR;
|
||||||
} catch (IllegalArgumentException iae) {
|
|
||||||
throw FormatException.getFormatInstance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mode != Mode.TERMINATOR) {
|
|
||||||
if (mode == Mode.FNC1_FIRST_POSITION || mode == 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 == Mode.STRUCTURED_APPEND) {
|
|
||||||
if (bits.available() < 16) {
|
|
||||||
throw FormatException.getFormatInstance();
|
|
||||||
}
|
|
||||||
// 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 == Mode.ECI) {
|
|
||||||
// Count doesn't apply to ECI
|
|
||||||
int value = parseECIValue(bits);
|
|
||||||
currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);
|
|
||||||
if (currentCharacterSetECI == null) {
|
|
||||||
throw FormatException.getFormatInstance();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// First handle Hanzi mode which does not start with character count
|
mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits
|
||||||
if (mode == Mode.HANZI) {
|
}
|
||||||
//chinese mode contains a sub set indicator right after mode indicator
|
if (mode != Mode.TERMINATOR) {
|
||||||
int subset = bits.readBits(4);
|
if (mode == Mode.FNC1_FIRST_POSITION || mode == Mode.FNC1_SECOND_POSITION) {
|
||||||
int countHanzi = bits.readBits(mode.getCharacterCountBits(version));
|
// We do little with FNC1 except alter the parsed result a bit according to the spec
|
||||||
if (subset == GB2312_SUBSET) {
|
fc1InEffect = true;
|
||||||
decodeHanziSegment(bits, result, countHanzi);
|
} else if (mode == Mode.STRUCTURED_APPEND) {
|
||||||
}
|
if (bits.available() < 16) {
|
||||||
} else {
|
|
||||||
// "Normal" QR code modes:
|
|
||||||
// How many characters will follow, encoded in this mode?
|
|
||||||
int count = bits.readBits(mode.getCharacterCountBits(version));
|
|
||||||
if (mode == Mode.NUMERIC) {
|
|
||||||
decodeNumericSegment(bits, result, count);
|
|
||||||
} else if (mode == Mode.ALPHANUMERIC) {
|
|
||||||
decodeAlphanumericSegment(bits, result, count, fc1InEffect);
|
|
||||||
} else if (mode == Mode.BYTE) {
|
|
||||||
decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints);
|
|
||||||
} else if (mode == Mode.KANJI) {
|
|
||||||
decodeKanjiSegment(bits, result, count);
|
|
||||||
} else {
|
|
||||||
throw FormatException.getFormatInstance();
|
throw FormatException.getFormatInstance();
|
||||||
}
|
}
|
||||||
|
// 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 == 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 == 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 == Mode.NUMERIC) {
|
||||||
|
decodeNumericSegment(bits, result, count);
|
||||||
|
} else if (mode == Mode.ALPHANUMERIC) {
|
||||||
|
decodeAlphanumericSegment(bits, result, count, fc1InEffect);
|
||||||
|
} else if (mode == Mode.BYTE) {
|
||||||
|
decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints);
|
||||||
|
} else if (mode == Mode.KANJI) {
|
||||||
|
decodeKanjiSegment(bits, result, count);
|
||||||
|
} else {
|
||||||
|
throw FormatException.getFormatInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} while (mode != Mode.TERMINATOR);
|
||||||
} while (mode != Mode.TERMINATOR);
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// from readBits() calls
|
||||||
|
throw FormatException.getFormatInstance();
|
||||||
|
}
|
||||||
|
|
||||||
return new DecoderResult(bytes,
|
return new DecoderResult(bytes,
|
||||||
result.toString(),
|
result.toString(),
|
||||||
|
|
Loading…
Reference in a new issue