<batchtest>
<fileset dir="test/src">
<include name="**/${subdir}/*BlackBox*TestCase.java"/>
+ <exclude name="**/Abstract*.java"/>
</fileset>
</batchtest>
</junit>
<fileset dir="test/src">
<include name="**/*TestCase.java"/>
<exclude name="**/*BlackBox*TestCase.java"/>
+ <exclude name="**/Abstract*.java"/>
</fileset>
</batchtest>
</junit>
*/
public static final ResultMetadataType ORIENTATION = new ResultMetadataType();
+ /**
+ * <p>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.</p>
+ *
+ * <p>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.</p>
+ */
+ public static final ResultMetadataType BYTE_SEGMENTS = new ResultMetadataType();
+
private ResultMetadataType() {
}
package com.google.zxing.common;
+import java.util.Vector;
+
/**
* <p>Encapsulates the result of decoding a matrix of bits. This typically
* applies to 2D barcode formats. For now it contains the raw bytes obtained,
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() {
return text;
}
+ public Vector getByteSegments() {
+ return byteSegments;
+ }
+
}
\ No newline at end of file
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;
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;
}
/**
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;
/**
* <p>Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes
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) {
decodeEdifactSegment(bits, result);
break;
case BASE256_ENCODE:
- decodeBase256Segment(bits, result);
+ decodeBase256Segment(bits, result, byteSegments);
break;
default:
throw new ReaderException("Unsupported mode indicator");
if (resultTrailer.length() > 0) {
result.append(resultTrailer);
}
- return result.toString();
+ return new DecoderResult(bytes, result.toString(), byteSegments.isEmpty() ? null : byteSegments);
}
/**
/**
* 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;
} 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));
}
}
}\r
\r
// Decode the contents of that stream of bytes\r
- String text = DecodedBitStreamParser.decode(resultBytes);\r
- return new DecoderResult(resultBytes, text);\r
+ return DecodedBitStreamParser.decode(resultBytes);\r
}\r
\r
/**\r
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;
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;
}
/**
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;
/**
* <p>QR Codes can encode text as bits in one of several modes, and can use multiple modes
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...
} 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 {
}
} 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,
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);
} catch (UnsupportedEncodingException uce) {
throw new ReaderException(uce.toString());
}
+ byteSegments.addElement(readBytes);
}
private static void decodeAlphanumericSegment(BitSource bits,
}\r
\r
// Decode the contents of that stream of bytes\r
- String text = DecodedBitStreamParser.decode(resultBytes, version);\r
- return new DecoderResult(resultBytes, text);\r
+ return DecodedBitStreamParser.decode(resultBytes, version);\r
}\r
\r
/**\r
// 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);
}
// 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);
}
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);
}
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);
}
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);
}