From: srowen Date: Sat, 15 Nov 2008 13:50:18 +0000 (+0000) Subject: Add to result the raw, but parsed, bytes of byte segments in 2D barcodes X-Git-Url: http://git.rot13.org/?p=zxing.git;a=commitdiff_plain;h=67bb87dea0eb848f80814f0353196079023a7aaf Add to result the raw, but parsed, bytes of byte segments in 2D barcodes git-svn-id: http://zxing.googlecode.com/svn/trunk@708 59b500cc-1b3d-0410-9834-0bbf25fbcc57 --- diff --git a/core/build.xml b/core/build.xml index 0f9102ff..633d81b3 100644 --- a/core/build.xml +++ b/core/build.xml @@ -127,6 +127,7 @@ + @@ -148,6 +149,7 @@ + diff --git a/core/src/com/google/zxing/ResultMetadataType.java b/core/src/com/google/zxing/ResultMetadataType.java index 2b7e266d..fd8c29f4 100644 --- a/core/src/com/google/zxing/ResultMetadataType.java +++ b/core/src/com/google/zxing/ResultMetadataType.java @@ -40,6 +40,17 @@ public final class ResultMetadataType { */ public static final ResultMetadataType ORIENTATION = new ResultMetadataType(); + /** + *

2D barcode formats typically encode text, but allow for a sort of 'byte mode' + * which is sometimes used to encode binary data. While {@link Result} makes available + * the complete raw bytes in the barcode for these formats, it does not offer the bytes + * from the byte segments alone.

+ * + *

This maps to a {@link java.util.Vector} of {@link byte[]}s corresponding to the + * raw bytes in the byte segments in the barcode, in order.

+ */ + public static final ResultMetadataType BYTE_SEGMENTS = new ResultMetadataType(); + private ResultMetadataType() { } diff --git a/core/src/com/google/zxing/common/DecoderResult.java b/core/src/com/google/zxing/common/DecoderResult.java index 065fd1c7..137987ca 100644 --- a/core/src/com/google/zxing/common/DecoderResult.java +++ b/core/src/com/google/zxing/common/DecoderResult.java @@ -16,6 +16,8 @@ package com.google.zxing.common; +import java.util.Vector; + /** *

Encapsulates the result of decoding a matrix of bits. This typically * applies to 2D barcode formats. For now it contains the raw bytes obtained, @@ -27,13 +29,15 @@ public final class DecoderResult { private final byte[] rawBytes; private final String text; + private final Vector byteSegments; - public DecoderResult(byte[] rawBytes, String text) { + public DecoderResult(byte[] rawBytes, String text, Vector byteSegments) { if (rawBytes == null && text == null) { throw new IllegalArgumentException(); } this.rawBytes = rawBytes; this.text = text; + this.byteSegments = byteSegments; } public byte[] getRawBytes() { @@ -44,4 +48,8 @@ public final class DecoderResult { return text; } + public Vector getByteSegments() { + return byteSegments; + } + } \ No newline at end of file diff --git a/core/src/com/google/zxing/datamatrix/DataMatrixReader.java b/core/src/com/google/zxing/datamatrix/DataMatrixReader.java index fd597abf..1e602cd3 100644 --- a/core/src/com/google/zxing/datamatrix/DataMatrixReader.java +++ b/core/src/com/google/zxing/datamatrix/DataMatrixReader.java @@ -23,6 +23,7 @@ import com.google.zxing.Reader; import com.google.zxing.ReaderException; import com.google.zxing.Result; import com.google.zxing.ResultPoint; +import com.google.zxing.ResultMetadataType; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.DecoderResult; import com.google.zxing.common.DetectorResult; @@ -61,11 +62,15 @@ public final class DataMatrixReader implements Reader { decoderResult = decoder.decode(bits); points = NO_POINTS; } else { - DetectorResult result = new Detector(image).detect(); - decoderResult = decoder.decode(result.getBits()); - points = result.getPoints(); + DetectorResult detectorResult = new Detector(image).detect(); + decoderResult = decoder.decode(detectorResult.getBits()); + points = detectorResult.getPoints(); } - return new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.DATAMATRIX); + Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.DATAMATRIX); + if (decoderResult.getByteSegments() != null) { + result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, decoderResult.getByteSegments()); + } + return result; } /** diff --git a/core/src/com/google/zxing/datamatrix/decoder/DecodedBitStreamParser.java b/core/src/com/google/zxing/datamatrix/decoder/DecodedBitStreamParser.java index fe5c00cb..d5b0394b 100644 --- a/core/src/com/google/zxing/datamatrix/decoder/DecodedBitStreamParser.java +++ b/core/src/com/google/zxing/datamatrix/decoder/DecodedBitStreamParser.java @@ -18,6 +18,10 @@ package com.google.zxing.datamatrix.decoder; import com.google.zxing.ReaderException; import com.google.zxing.common.BitSource; +import com.google.zxing.common.DecoderResult; + +import java.util.Vector; +import java.io.UnsupportedEncodingException; /** *

Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes @@ -71,10 +75,11 @@ final class DecodedBitStreamParser { private DecodedBitStreamParser() { } - static String decode(byte[] bytes) throws ReaderException { + static DecoderResult decode(byte[] bytes) throws ReaderException { BitSource bits = new BitSource(bytes); StringBuffer result = new StringBuffer(); StringBuffer resultTrailer = new StringBuffer(0); + Vector byteSegments = new Vector(1); int mode = ASCII_ENCODE; do { if (mode == ASCII_ENCODE) { @@ -94,7 +99,7 @@ final class DecodedBitStreamParser { decodeEdifactSegment(bits, result); break; case BASE256_ENCODE: - decodeBase256Segment(bits, result); + decodeBase256Segment(bits, result, byteSegments); break; default: throw new ReaderException("Unsupported mode indicator"); @@ -105,7 +110,7 @@ final class DecodedBitStreamParser { if (resultTrailer.length() > 0) { result.append(resultTrailer); } - return result.toString(); + return new DecoderResult(bytes, result.toString(), byteSegments.isEmpty() ? null : byteSegments); } /** @@ -411,7 +416,7 @@ final class DecodedBitStreamParser { /** * See ISO 16022:2006, 5.2.9 and Annex B, B.2 */ - private static void decodeBase256Segment(BitSource bits, StringBuffer result) { + private static void decodeBase256Segment(BitSource bits, StringBuffer result, Vector byteSegments) { // Figure out how long the Base 256 Segment is. int d1 = bits.readBits(8); int count; @@ -422,19 +427,26 @@ final class DecodedBitStreamParser { } else { count = 250 * (d1 - 249) + bits.readBits(8); } + byte[] bytes = new byte[count]; for (int i = 0; i < count; i++) { - result.append(unrandomize255State(bits.readBits(8), i)); + bytes[i] = unrandomize255State(bits.readBits(8), i); + } + byteSegments.addElement(bytes); + try { + result.append(new String(bytes, "ISO8859_1")); + } catch (UnsupportedEncodingException uee) { + throw new RuntimeException("Platform does not support required encoding: " + uee); } } /** * See ISO 16022:2006, Annex B, B.2 */ - private static char unrandomize255State(int randomizedBase256Codeword, + private static byte unrandomize255State(int randomizedBase256Codeword, int base256CodewordPosition) { int pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1; int tempVariable = randomizedBase256Codeword - pseudoRandomNumber; - return tempVariable >= 0 ? (char) tempVariable : (char) (tempVariable + 256); + return (byte) (tempVariable >= 0 ? tempVariable : (tempVariable + 256)); } } diff --git a/core/src/com/google/zxing/datamatrix/decoder/Decoder.java b/core/src/com/google/zxing/datamatrix/decoder/Decoder.java index f70ae45e..5ec86d28 100644 --- a/core/src/com/google/zxing/datamatrix/decoder/Decoder.java +++ b/core/src/com/google/zxing/datamatrix/decoder/Decoder.java @@ -97,8 +97,7 @@ public final class Decoder { } // Decode the contents of that stream of bytes - String text = DecodedBitStreamParser.decode(resultBytes); - return new DecoderResult(resultBytes, text); + return DecodedBitStreamParser.decode(resultBytes); } /** diff --git a/core/src/com/google/zxing/qrcode/QRCodeReader.java b/core/src/com/google/zxing/qrcode/QRCodeReader.java index f5b0dcd2..3bef7aa6 100644 --- a/core/src/com/google/zxing/qrcode/QRCodeReader.java +++ b/core/src/com/google/zxing/qrcode/QRCodeReader.java @@ -23,6 +23,7 @@ import com.google.zxing.Reader; import com.google.zxing.ReaderException; import com.google.zxing.Result; import com.google.zxing.ResultPoint; +import com.google.zxing.ResultMetadataType; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.DecoderResult; import com.google.zxing.common.DetectorResult; @@ -61,11 +62,16 @@ public final class QRCodeReader implements Reader { decoderResult = decoder.decode(bits); points = NO_POINTS; } else { - DetectorResult result = new Detector(image).detect(hints); - decoderResult = decoder.decode(result.getBits()); - points = result.getPoints(); + DetectorResult detectorResult = new Detector(image).detect(hints); + decoderResult = decoder.decode(detectorResult.getBits()); + points = detectorResult.getPoints(); } - return new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.QR_CODE); + + Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.QR_CODE); + if (decoderResult.getByteSegments() != null) { + result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, decoderResult.getByteSegments()); + } + return result; } /** diff --git a/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java b/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java index 67f0607c..08906963 100644 --- a/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java +++ b/core/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java @@ -19,8 +19,10 @@ package com.google.zxing.qrcode.decoder; import com.google.zxing.ReaderException; import com.google.zxing.common.BitSource; import com.google.zxing.common.CharacterSetECI; +import com.google.zxing.common.DecoderResult; import java.io.UnsupportedEncodingException; +import java.util.Vector; /** *

QR Codes can encode text as bits in one of several modes, and can use multiple modes @@ -55,11 +57,12 @@ final class DecodedBitStreamParser { private DecodedBitStreamParser() { } - static String decode(byte[] bytes, Version version) throws ReaderException { + static DecoderResult decode(byte[] bytes, Version version) throws ReaderException { BitSource bits = new BitSource(bytes); StringBuffer result = new StringBuffer(); CharacterSetECI currentCharacterSetECI = null; boolean fc1InEffect = false; + Vector byteSegments = new Vector(1); Mode mode; do { // While still another segment to read... @@ -89,7 +92,7 @@ final class DecodedBitStreamParser { } else if (mode.equals(Mode.ALPHANUMERIC)) { decodeAlphanumericSegment(bits, result, count, fc1InEffect); } else if (mode.equals(Mode.BYTE)) { - decodeByteSegment(bits, result, count, currentCharacterSetECI); + decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments); } else if (mode.equals(Mode.KANJI)) { decodeKanjiSegment(bits, result, count); } else { @@ -99,16 +102,7 @@ final class DecodedBitStreamParser { } } while (!mode.equals(Mode.TERMINATOR)); - // I thought it wasn't allowed to leave extra bytes after the terminator but it happens - /* - int bitsLeft = bits.available(); - if (bitsLeft > 0) { - if (bitsLeft > 6 || bits.readBits(bitsLeft) != 0) { - throw new ReaderException("Excess bits or non-zero bits after terminator mode indicator"); - } - } - */ - return result.toString(); + return new DecoderResult(bytes, result.toString(), byteSegments.isEmpty() ? null : byteSegments); } private static void decodeKanjiSegment(BitSource bits, @@ -145,7 +139,8 @@ final class DecodedBitStreamParser { private static void decodeByteSegment(BitSource bits, StringBuffer result, int count, - CharacterSetECI currentCharacterSetECI) throws ReaderException { + CharacterSetECI currentCharacterSetECI, + Vector byteSegments) throws ReaderException { byte[] readBytes = new byte[count]; if (count << 3 > bits.available()) { throw new ReaderException("Count too large: " + count); @@ -169,6 +164,7 @@ final class DecodedBitStreamParser { } catch (UnsupportedEncodingException uce) { throw new ReaderException(uce.toString()); } + byteSegments.addElement(readBytes); } private static void decodeAlphanumericSegment(BitSource bits, diff --git a/core/src/com/google/zxing/qrcode/decoder/Decoder.java b/core/src/com/google/zxing/qrcode/decoder/Decoder.java index f1436f28..e1f34bcd 100644 --- a/core/src/com/google/zxing/qrcode/decoder/Decoder.java +++ b/core/src/com/google/zxing/qrcode/decoder/Decoder.java @@ -97,8 +97,7 @@ public final class Decoder { } // Decode the contents of that stream of bytes - String text = DecodedBitStreamParser.decode(resultBytes, version); - return new DecoderResult(resultBytes, text); + return DecodedBitStreamParser.decode(resultBytes, version); } /** diff --git a/core/test/src/com/google/zxing/datamatrix/decoder/DecodedBitStreamParserTestCase.java b/core/test/src/com/google/zxing/datamatrix/decoder/DecodedBitStreamParserTestCase.java index 340ed14c..9d215f9b 100644 --- a/core/test/src/com/google/zxing/datamatrix/decoder/DecodedBitStreamParserTestCase.java +++ b/core/test/src/com/google/zxing/datamatrix/decoder/DecodedBitStreamParserTestCase.java @@ -29,7 +29,7 @@ public final class DecodedBitStreamParserTestCase extends TestCase{ // ASCII characters 0-127 are encoded as the value + 1 byte[] bytes = {(byte) ('a' + 1), (byte) ('b' + 1), (byte) ('c' + 1), (byte) ('A' + 1), (byte) ('B' + 1), (byte) ('C' + 1)}; - String decodedString = DecodedBitStreamParser.decode(bytes); + String decodedString = DecodedBitStreamParser.decode(bytes).getText(); assertEquals("abcABC", decodedString); } @@ -37,7 +37,7 @@ public final class DecodedBitStreamParserTestCase extends TestCase{ // ASCII double digit (00 - 99) Numeric Value + 130 byte[] bytes = {(byte) 130 , (byte) ( 1 + 130), (byte) (98 + 130), (byte) (99 + 130)}; - String decodedString = DecodedBitStreamParser.decode(bytes); + String decodedString = DecodedBitStreamParser.decode(bytes).getText(); assertEquals("00019899", decodedString); } diff --git a/core/test/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParserTestCase.java b/core/test/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParserTestCase.java index 26621017..3efd8578 100644 --- a/core/test/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParserTestCase.java +++ b/core/test/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParserTestCase.java @@ -34,7 +34,7 @@ public final class DecodedBitStreamParserTestCase extends TestCase { builder.write(0xF1, 8); builder.write(0xF2, 8); builder.write(0xF3, 8); - String result = DecodedBitStreamParser.decode(builder.toByteArray(), Version.getVersionForNumber(1)); + String result = DecodedBitStreamParser.decode(builder.toByteArray(), Version.getVersionForNumber(1)).getText(); assertEquals("\u00f1\u00f2\u00f3", result); } @@ -45,7 +45,7 @@ public final class DecodedBitStreamParserTestCase extends TestCase { builder.write(0xA1, 8); builder.write(0xA2, 8); builder.write(0xA3, 8); - String result = DecodedBitStreamParser.decode(builder.toByteArray(), Version.getVersionForNumber(1)); + String result = DecodedBitStreamParser.decode(builder.toByteArray(), Version.getVersionForNumber(1)).getText(); assertEquals("\uff61\uff62\uff63", result); } @@ -58,7 +58,7 @@ public final class DecodedBitStreamParserTestCase extends TestCase { builder.write(0xA1, 8); builder.write(0xA2, 8); builder.write(0xA3, 8); - String result = DecodedBitStreamParser.decode(builder.toByteArray(), Version.getVersionForNumber(1)); + String result = DecodedBitStreamParser.decode(builder.toByteArray(), Version.getVersionForNumber(1)).getText(); assertEquals("\u00ed\u00f3\u00fa", result); }