mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
Symbology Identifier support (#1372)
* decoder support for symbology identifier metadata Co-authored-by: Daniel Dehnhard <daniel@dehnhard.it>
This commit is contained in:
parent
3bf945e4cf
commit
ef498941bf
|
@ -94,4 +94,8 @@ public enum ResultMetadataType {
|
||||||
*/
|
*/
|
||||||
STRUCTURED_APPEND_PARITY,
|
STRUCTURED_APPEND_PARITY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Barcode Symbology Identifier.
|
||||||
|
*/
|
||||||
|
SYMBOLOGY_IDENTIFIER,
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,7 @@ public final class AztecReader implements Reader {
|
||||||
if (ecLevel != null) {
|
if (ecLevel != null) {
|
||||||
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
|
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
|
||||||
}
|
}
|
||||||
|
result.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]z" + decoderResult.getSymbologyModifier());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,12 +37,21 @@ public final class DecoderResult {
|
||||||
private Object other;
|
private Object other;
|
||||||
private final int structuredAppendParity;
|
private final int structuredAppendParity;
|
||||||
private final int structuredAppendSequenceNumber;
|
private final int structuredAppendSequenceNumber;
|
||||||
|
private final int symbologyModifier;
|
||||||
|
|
||||||
public DecoderResult(byte[] rawBytes,
|
public DecoderResult(byte[] rawBytes,
|
||||||
String text,
|
String text,
|
||||||
List<byte[]> byteSegments,
|
List<byte[]> byteSegments,
|
||||||
String ecLevel) {
|
String ecLevel) {
|
||||||
this(rawBytes, text, byteSegments, ecLevel, -1, -1);
|
this(rawBytes, text, byteSegments, ecLevel, -1, -1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DecoderResult(byte[] rawBytes,
|
||||||
|
String text,
|
||||||
|
List<byte[]> byteSegments,
|
||||||
|
String ecLevel,
|
||||||
|
int symbologyModifier) {
|
||||||
|
this(rawBytes, text, byteSegments, ecLevel, -1, -1, symbologyModifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DecoderResult(byte[] rawBytes,
|
public DecoderResult(byte[] rawBytes,
|
||||||
|
@ -51,6 +60,16 @@ public final class DecoderResult {
|
||||||
String ecLevel,
|
String ecLevel,
|
||||||
int saSequence,
|
int saSequence,
|
||||||
int saParity) {
|
int saParity) {
|
||||||
|
this(rawBytes, text, byteSegments, ecLevel, saSequence, saParity, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DecoderResult(byte[] rawBytes,
|
||||||
|
String text,
|
||||||
|
List<byte[]> byteSegments,
|
||||||
|
String ecLevel,
|
||||||
|
int saSequence,
|
||||||
|
int saParity,
|
||||||
|
int symbologyModifier) {
|
||||||
this.rawBytes = rawBytes;
|
this.rawBytes = rawBytes;
|
||||||
this.numBits = rawBytes == null ? 0 : 8 * rawBytes.length;
|
this.numBits = rawBytes == null ? 0 : 8 * rawBytes.length;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
|
@ -58,6 +77,7 @@ public final class DecoderResult {
|
||||||
this.ecLevel = ecLevel;
|
this.ecLevel = ecLevel;
|
||||||
this.structuredAppendParity = saParity;
|
this.structuredAppendParity = saParity;
|
||||||
this.structuredAppendSequenceNumber = saSequence;
|
this.structuredAppendSequenceNumber = saSequence;
|
||||||
|
this.symbologyModifier = symbologyModifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,4 +169,8 @@ public final class DecoderResult {
|
||||||
return structuredAppendSequenceNumber;
|
return structuredAppendSequenceNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSymbologyModifier() {
|
||||||
|
return symbologyModifier;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,7 @@ public final class DataMatrixReader implements Reader {
|
||||||
if (ecLevel != null) {
|
if (ecLevel != null) {
|
||||||
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
|
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
|
||||||
}
|
}
|
||||||
|
result.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]d" + decoderResult.getSymbologyModifier());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,9 @@ import com.google.zxing.common.DecoderResult;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes
|
* <p>Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes
|
||||||
|
@ -43,7 +45,8 @@ final class DecodedBitStreamParser {
|
||||||
TEXT_ENCODE,
|
TEXT_ENCODE,
|
||||||
ANSIX12_ENCODE,
|
ANSIX12_ENCODE,
|
||||||
EDIFACT_ENCODE,
|
EDIFACT_ENCODE,
|
||||||
BASE256_ENCODE
|
BASE256_ENCODE,
|
||||||
|
ECI_ENCODE
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,17 +90,20 @@ final class DecodedBitStreamParser {
|
||||||
StringBuilder result = new StringBuilder(100);
|
StringBuilder result = new StringBuilder(100);
|
||||||
StringBuilder resultTrailer = new StringBuilder(0);
|
StringBuilder resultTrailer = new StringBuilder(0);
|
||||||
List<byte[]> byteSegments = new ArrayList<>(1);
|
List<byte[]> byteSegments = new ArrayList<>(1);
|
||||||
|
int symbologyModifier = 0;
|
||||||
Mode mode = Mode.ASCII_ENCODE;
|
Mode mode = Mode.ASCII_ENCODE;
|
||||||
|
Set<Integer> fnc1Positions = new HashSet<Integer>(); // Would be replaceable by looking directly at 'bytes', if we're sure to not having to account for multi byte values.
|
||||||
|
boolean isECIencoded = false;
|
||||||
do {
|
do {
|
||||||
if (mode == Mode.ASCII_ENCODE) {
|
if (mode == Mode.ASCII_ENCODE) {
|
||||||
mode = decodeAsciiSegment(bits, result, resultTrailer);
|
mode = decodeAsciiSegment(bits, result, resultTrailer, fnc1Positions);
|
||||||
} else {
|
} else {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case C40_ENCODE:
|
case C40_ENCODE:
|
||||||
decodeC40Segment(bits, result);
|
decodeC40Segment(bits, result, fnc1Positions);
|
||||||
break;
|
break;
|
||||||
case TEXT_ENCODE:
|
case TEXT_ENCODE:
|
||||||
decodeTextSegment(bits, result);
|
decodeTextSegment(bits, result, fnc1Positions);
|
||||||
break;
|
break;
|
||||||
case ANSIX12_ENCODE:
|
case ANSIX12_ENCODE:
|
||||||
decodeAnsiX12Segment(bits, result);
|
decodeAnsiX12Segment(bits, result);
|
||||||
|
@ -108,6 +114,9 @@ final class DecodedBitStreamParser {
|
||||||
case BASE256_ENCODE:
|
case BASE256_ENCODE:
|
||||||
decodeBase256Segment(bits, result, byteSegments);
|
decodeBase256Segment(bits, result, byteSegments);
|
||||||
break;
|
break;
|
||||||
|
case ECI_ENCODE:
|
||||||
|
isECIencoded = true; // ECI detection only, atm continue decoding as ASCII
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw FormatException.getFormatInstance();
|
throw FormatException.getFormatInstance();
|
||||||
}
|
}
|
||||||
|
@ -117,7 +126,27 @@ final class DecodedBitStreamParser {
|
||||||
if (resultTrailer.length() > 0) {
|
if (resultTrailer.length() > 0) {
|
||||||
result.append(resultTrailer);
|
result.append(resultTrailer);
|
||||||
}
|
}
|
||||||
return new DecoderResult(bytes, result.toString(), byteSegments.isEmpty() ? null : byteSegments, null);
|
if (isECIencoded) {
|
||||||
|
// Examples for this numbers can be found in this documentation of a hardware barcode scanner:
|
||||||
|
// https://honeywellaidc.force.com/supportppr/s/article/List-of-barcode-symbology-AIM-Identifiers
|
||||||
|
if (fnc1Positions.contains(0) || fnc1Positions.contains(4)) {
|
||||||
|
symbologyModifier = 5;
|
||||||
|
} else if (fnc1Positions.contains(1) || fnc1Positions.contains(5)) {
|
||||||
|
symbologyModifier = 6;
|
||||||
|
} else {
|
||||||
|
symbologyModifier = 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fnc1Positions.contains(0) || fnc1Positions.contains(4)) {
|
||||||
|
symbologyModifier = 2;
|
||||||
|
} else if (fnc1Positions.contains(1) || fnc1Positions.contains(5)) {
|
||||||
|
symbologyModifier = 3;
|
||||||
|
} else {
|
||||||
|
symbologyModifier = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DecoderResult(bytes, result.toString(), byteSegments.isEmpty() ? null : byteSegments, null, symbologyModifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,7 +154,8 @@ final class DecodedBitStreamParser {
|
||||||
*/
|
*/
|
||||||
private static Mode decodeAsciiSegment(BitSource bits,
|
private static Mode decodeAsciiSegment(BitSource bits,
|
||||||
StringBuilder result,
|
StringBuilder result,
|
||||||
StringBuilder resultTrailer) throws FormatException {
|
StringBuilder resultTrailer,
|
||||||
|
Set<Integer> fnc1positions) throws FormatException {
|
||||||
boolean upperShift = false;
|
boolean upperShift = false;
|
||||||
do {
|
do {
|
||||||
int oneByte = bits.readBits(8);
|
int oneByte = bits.readBits(8);
|
||||||
|
@ -153,6 +183,7 @@ final class DecodedBitStreamParser {
|
||||||
case 231: // Latch to Base 256 encodation
|
case 231: // Latch to Base 256 encodation
|
||||||
return Mode.BASE256_ENCODE;
|
return Mode.BASE256_ENCODE;
|
||||||
case 232: // FNC1
|
case 232: // FNC1
|
||||||
|
fnc1positions.add(result.length());
|
||||||
result.append((char) 29); // translate as ASCII 29
|
result.append((char) 29); // translate as ASCII 29
|
||||||
break;
|
break;
|
||||||
case 233: // Structured Append
|
case 233: // Structured Append
|
||||||
|
@ -178,10 +209,7 @@ final class DecodedBitStreamParser {
|
||||||
case 240: // Latch to EDIFACT encodation
|
case 240: // Latch to EDIFACT encodation
|
||||||
return Mode.EDIFACT_ENCODE;
|
return Mode.EDIFACT_ENCODE;
|
||||||
case 241: // ECI Character
|
case 241: // ECI Character
|
||||||
// TODO(bbrown): I think we need to support ECI
|
return Mode.ECI_ENCODE;
|
||||||
//throw ReaderException.getInstance();
|
|
||||||
// Ignore this symbol for now
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
// Not to be used in ASCII encodation
|
// Not to be used in ASCII encodation
|
||||||
// but work around encoders that end with 254, latch back to ASCII
|
// but work around encoders that end with 254, latch back to ASCII
|
||||||
|
@ -198,7 +226,7 @@ final class DecodedBitStreamParser {
|
||||||
/**
|
/**
|
||||||
* See ISO 16022:2006, 5.2.5 and Annex C, Table C.1
|
* See ISO 16022:2006, 5.2.5 and Annex C, Table C.1
|
||||||
*/
|
*/
|
||||||
private static void decodeC40Segment(BitSource bits, StringBuilder result) throws FormatException {
|
private static void decodeC40Segment(BitSource bits, StringBuilder result, Set<Integer> fnc1positions) throws FormatException {
|
||||||
// Three C40 values are encoded in a 16-bit value as
|
// Three C40 values are encoded in a 16-bit value as
|
||||||
// (1600 * C1) + (40 * C2) + C3 + 1
|
// (1600 * C1) + (40 * C2) + C3 + 1
|
||||||
// TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time
|
// TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time
|
||||||
|
@ -258,6 +286,7 @@ final class DecodedBitStreamParser {
|
||||||
} else {
|
} else {
|
||||||
switch (cValue) {
|
switch (cValue) {
|
||||||
case 27: // FNC1
|
case 27: // FNC1
|
||||||
|
fnc1positions.add(result.length());
|
||||||
result.append((char) 29); // translate as ASCII 29
|
result.append((char) 29); // translate as ASCII 29
|
||||||
break;
|
break;
|
||||||
case 30: // Upper Shift
|
case 30: // Upper Shift
|
||||||
|
@ -288,7 +317,7 @@ final class DecodedBitStreamParser {
|
||||||
/**
|
/**
|
||||||
* See ISO 16022:2006, 5.2.6 and Annex C, Table C.2
|
* See ISO 16022:2006, 5.2.6 and Annex C, Table C.2
|
||||||
*/
|
*/
|
||||||
private static void decodeTextSegment(BitSource bits, StringBuilder result) throws FormatException {
|
private static void decodeTextSegment(BitSource bits, StringBuilder result, Set<Integer> fnc1positions) throws FormatException {
|
||||||
// Three Text values are encoded in a 16-bit value as
|
// Three Text values are encoded in a 16-bit value as
|
||||||
// (1600 * C1) + (40 * C2) + C3 + 1
|
// (1600 * C1) + (40 * C2) + C3 + 1
|
||||||
// TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time
|
// TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time
|
||||||
|
@ -348,6 +377,7 @@ final class DecodedBitStreamParser {
|
||||||
} else {
|
} else {
|
||||||
switch (cValue) {
|
switch (cValue) {
|
||||||
case 27: // FNC1
|
case 27: // FNC1
|
||||||
|
fnc1positions.add(result.length());
|
||||||
result.append((char) 29); // translate as ASCII 29
|
result.append((char) 29); // translate as ASCII 29
|
||||||
break;
|
break;
|
||||||
case 30: // Upper Shift
|
case 30: // Upper Shift
|
||||||
|
|
|
@ -20,6 +20,7 @@ import com.google.zxing.BarcodeFormat;
|
||||||
import com.google.zxing.DecodeHintType;
|
import com.google.zxing.DecodeHintType;
|
||||||
import com.google.zxing.NotFoundException;
|
import com.google.zxing.NotFoundException;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
|
import com.google.zxing.ResultMetadataType;
|
||||||
import com.google.zxing.ResultPoint;
|
import com.google.zxing.ResultPoint;
|
||||||
import com.google.zxing.common.BitArray;
|
import com.google.zxing.common.BitArray;
|
||||||
|
|
||||||
|
@ -152,13 +153,16 @@ public final class CodaBarReader extends OneDReader {
|
||||||
runningCount += counters[i];
|
runningCount += counters[i];
|
||||||
}
|
}
|
||||||
float right = runningCount;
|
float right = runningCount;
|
||||||
return new Result(
|
|
||||||
|
Result result = new Result(
|
||||||
decodeRowResult.toString(),
|
decodeRowResult.toString(),
|
||||||
null,
|
null,
|
||||||
new ResultPoint[]{
|
new ResultPoint[]{
|
||||||
new ResultPoint(left, rowNumber),
|
new ResultPoint(left, rowNumber),
|
||||||
new ResultPoint(right, rowNumber)},
|
new ResultPoint(right, rowNumber)},
|
||||||
BarcodeFormat.CODABAR);
|
BarcodeFormat.CODABAR);
|
||||||
|
result.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]F0");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validatePattern(int start) throws NotFoundException {
|
private void validatePattern(int start) throws NotFoundException {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import com.google.zxing.DecodeHintType;
|
||||||
import com.google.zxing.FormatException;
|
import com.google.zxing.FormatException;
|
||||||
import com.google.zxing.NotFoundException;
|
import com.google.zxing.NotFoundException;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
|
import com.google.zxing.ResultMetadataType;
|
||||||
import com.google.zxing.ResultPoint;
|
import com.google.zxing.ResultPoint;
|
||||||
import com.google.zxing.common.BitArray;
|
import com.google.zxing.common.BitArray;
|
||||||
|
|
||||||
|
@ -238,6 +239,8 @@ public final class Code128Reader extends OneDReader {
|
||||||
|
|
||||||
boolean convertFNC1 = hints != null && hints.containsKey(DecodeHintType.ASSUME_GS1);
|
boolean convertFNC1 = hints != null && hints.containsKey(DecodeHintType.ASSUME_GS1);
|
||||||
|
|
||||||
|
int symbologyModifier = 0;
|
||||||
|
|
||||||
int[] startPatternInfo = findStartPattern(row);
|
int[] startPatternInfo = findStartPattern(row);
|
||||||
int startCode = startPatternInfo[2];
|
int startCode = startPatternInfo[2];
|
||||||
|
|
||||||
|
@ -339,6 +342,11 @@ public final class Code128Reader extends OneDReader {
|
||||||
}
|
}
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case CODE_FNC_1:
|
case CODE_FNC_1:
|
||||||
|
if (result.length() == 0) { // FNC1 at first or second character determines the symbology
|
||||||
|
symbologyModifier = 1;
|
||||||
|
} else if (result.length() == 1) {
|
||||||
|
symbologyModifier = 2;
|
||||||
|
}
|
||||||
if (convertFNC1) {
|
if (convertFNC1) {
|
||||||
if (result.length() == 0) {
|
if (result.length() == 0) {
|
||||||
// GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code
|
// GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code
|
||||||
|
@ -351,6 +359,8 @@ public final class Code128Reader extends OneDReader {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CODE_FNC_2:
|
case CODE_FNC_2:
|
||||||
|
symbologyModifier = 4;
|
||||||
|
break;
|
||||||
case CODE_FNC_3:
|
case CODE_FNC_3:
|
||||||
// do nothing?
|
// do nothing?
|
||||||
break;
|
break;
|
||||||
|
@ -395,6 +405,11 @@ public final class Code128Reader extends OneDReader {
|
||||||
}
|
}
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case CODE_FNC_1:
|
case CODE_FNC_1:
|
||||||
|
if (result.length() == 0) { // FNC1 at first or second character determines the symbology
|
||||||
|
symbologyModifier = 1;
|
||||||
|
} else if (result.length() == 1) {
|
||||||
|
symbologyModifier = 2;
|
||||||
|
}
|
||||||
if (convertFNC1) {
|
if (convertFNC1) {
|
||||||
if (result.length() == 0) {
|
if (result.length() == 0) {
|
||||||
// GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code
|
// GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code
|
||||||
|
@ -407,6 +422,8 @@ public final class Code128Reader extends OneDReader {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CODE_FNC_2:
|
case CODE_FNC_2:
|
||||||
|
symbologyModifier = 4;
|
||||||
|
break;
|
||||||
case CODE_FNC_3:
|
case CODE_FNC_3:
|
||||||
// do nothing?
|
// do nothing?
|
||||||
break;
|
break;
|
||||||
|
@ -449,6 +466,11 @@ public final class Code128Reader extends OneDReader {
|
||||||
}
|
}
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case CODE_FNC_1:
|
case CODE_FNC_1:
|
||||||
|
if (result.length() == 0) { // FNC1 at first or second character determines the symbology
|
||||||
|
symbologyModifier = 1;
|
||||||
|
} else if (result.length() == 1) {
|
||||||
|
symbologyModifier = 2;
|
||||||
|
}
|
||||||
if (convertFNC1) {
|
if (convertFNC1) {
|
||||||
if (result.length() == 0) {
|
if (result.length() == 0) {
|
||||||
// GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code
|
// GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code
|
||||||
|
@ -460,6 +482,9 @@ public final class Code128Reader extends OneDReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CODE_FNC_2:
|
||||||
|
symbologyModifier = 4;
|
||||||
|
break;
|
||||||
case CODE_CODE_A:
|
case CODE_CODE_A:
|
||||||
codeSet = CODE_CODE_A;
|
codeSet = CODE_CODE_A;
|
||||||
break;
|
break;
|
||||||
|
@ -525,14 +550,15 @@ public final class Code128Reader extends OneDReader {
|
||||||
for (int i = 0; i < rawCodesSize; i++) {
|
for (int i = 0; i < rawCodesSize; i++) {
|
||||||
rawBytes[i] = rawCodes.get(i);
|
rawBytes[i] = rawCodes.get(i);
|
||||||
}
|
}
|
||||||
|
Result resultObject = new Result(
|
||||||
return new Result(
|
|
||||||
result.toString(),
|
result.toString(),
|
||||||
rawBytes,
|
rawBytes,
|
||||||
new ResultPoint[]{
|
new ResultPoint[]{
|
||||||
new ResultPoint(left, rowNumber),
|
new ResultPoint(left, rowNumber),
|
||||||
new ResultPoint(right, rowNumber)},
|
new ResultPoint(right, rowNumber)},
|
||||||
BarcodeFormat.CODE_128);
|
BarcodeFormat.CODE_128);
|
||||||
|
resultObject.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]C" + symbologyModifier);
|
||||||
|
return resultObject;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import com.google.zxing.DecodeHintType;
|
||||||
import com.google.zxing.FormatException;
|
import com.google.zxing.FormatException;
|
||||||
import com.google.zxing.NotFoundException;
|
import com.google.zxing.NotFoundException;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
|
import com.google.zxing.ResultMetadataType;
|
||||||
import com.google.zxing.ResultPoint;
|
import com.google.zxing.ResultPoint;
|
||||||
import com.google.zxing.common.BitArray;
|
import com.google.zxing.common.BitArray;
|
||||||
|
|
||||||
|
@ -165,14 +166,16 @@ public final class Code39Reader extends OneDReader {
|
||||||
|
|
||||||
float left = (start[1] + start[0]) / 2.0f;
|
float left = (start[1] + start[0]) / 2.0f;
|
||||||
float right = lastStart + lastPatternSize / 2.0f;
|
float right = lastStart + lastPatternSize / 2.0f;
|
||||||
return new Result(
|
|
||||||
|
Result resultObject = new Result(
|
||||||
resultString,
|
resultString,
|
||||||
null,
|
null,
|
||||||
new ResultPoint[]{
|
new ResultPoint[]{
|
||||||
new ResultPoint(left, rowNumber),
|
new ResultPoint(left, rowNumber),
|
||||||
new ResultPoint(right, rowNumber)},
|
new ResultPoint(right, rowNumber)},
|
||||||
BarcodeFormat.CODE_39);
|
BarcodeFormat.CODE_39);
|
||||||
|
resultObject.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]A0");
|
||||||
|
return resultObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] findAsteriskPattern(BitArray row, int[] counters) throws NotFoundException {
|
private static int[] findAsteriskPattern(BitArray row, int[] counters) throws NotFoundException {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import com.google.zxing.DecodeHintType;
|
||||||
import com.google.zxing.FormatException;
|
import com.google.zxing.FormatException;
|
||||||
import com.google.zxing.NotFoundException;
|
import com.google.zxing.NotFoundException;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
|
import com.google.zxing.ResultMetadataType;
|
||||||
import com.google.zxing.ResultPoint;
|
import com.google.zxing.ResultPoint;
|
||||||
import com.google.zxing.common.BitArray;
|
import com.google.zxing.common.BitArray;
|
||||||
|
|
||||||
|
@ -118,14 +119,16 @@ public final class Code93Reader extends OneDReader {
|
||||||
|
|
||||||
float left = (start[1] + start[0]) / 2.0f;
|
float left = (start[1] + start[0]) / 2.0f;
|
||||||
float right = lastStart + lastPatternSize / 2.0f;
|
float right = lastStart + lastPatternSize / 2.0f;
|
||||||
return new Result(
|
|
||||||
|
Result resultObject = new Result(
|
||||||
resultString,
|
resultString,
|
||||||
null,
|
null,
|
||||||
new ResultPoint[]{
|
new ResultPoint[]{
|
||||||
new ResultPoint(left, rowNumber),
|
new ResultPoint(left, rowNumber),
|
||||||
new ResultPoint(right, rowNumber)},
|
new ResultPoint(right, rowNumber)},
|
||||||
BarcodeFormat.CODE_93);
|
BarcodeFormat.CODE_93);
|
||||||
|
resultObject.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]G0");
|
||||||
|
return resultObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int[] findAsteriskPattern(BitArray row) throws NotFoundException {
|
private int[] findAsteriskPattern(BitArray row) throws NotFoundException {
|
||||||
|
|
|
@ -153,6 +153,7 @@ public abstract class UPCEANReader extends OneDReader {
|
||||||
|
|
||||||
ResultPointCallback resultPointCallback = hints == null ? null :
|
ResultPointCallback resultPointCallback = hints == null ? null :
|
||||||
(ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
|
(ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
|
||||||
|
int symbologyIdentifier = 0;
|
||||||
|
|
||||||
if (resultPointCallback != null) {
|
if (resultPointCallback != null) {
|
||||||
resultPointCallback.foundPossibleResultPoint(new ResultPoint(
|
resultPointCallback.foundPossibleResultPoint(new ResultPoint(
|
||||||
|
@ -239,6 +240,11 @@ public abstract class UPCEANReader extends OneDReader {
|
||||||
decodeResult.putMetadata(ResultMetadataType.POSSIBLE_COUNTRY, countryID);
|
decodeResult.putMetadata(ResultMetadataType.POSSIBLE_COUNTRY, countryID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (format == BarcodeFormat.EAN_8) {
|
||||||
|
symbologyIdentifier = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeResult.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]E" + symbologyIdentifier);
|
||||||
|
|
||||||
return decodeResult;
|
return decodeResult;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import com.google.zxing.BarcodeFormat;
|
||||||
import com.google.zxing.DecodeHintType;
|
import com.google.zxing.DecodeHintType;
|
||||||
import com.google.zxing.NotFoundException;
|
import com.google.zxing.NotFoundException;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
|
import com.google.zxing.ResultMetadataType;
|
||||||
import com.google.zxing.ResultPoint;
|
import com.google.zxing.ResultPoint;
|
||||||
import com.google.zxing.ResultPointCallback;
|
import com.google.zxing.ResultPointCallback;
|
||||||
import com.google.zxing.common.BitArray;
|
import com.google.zxing.common.BitArray;
|
||||||
|
@ -131,11 +132,13 @@ public final class RSS14Reader extends AbstractRSSReader {
|
||||||
|
|
||||||
ResultPoint[] leftPoints = leftPair.getFinderPattern().getResultPoints();
|
ResultPoint[] leftPoints = leftPair.getFinderPattern().getResultPoints();
|
||||||
ResultPoint[] rightPoints = rightPair.getFinderPattern().getResultPoints();
|
ResultPoint[] rightPoints = rightPair.getFinderPattern().getResultPoints();
|
||||||
return new Result(
|
Result result = new Result(
|
||||||
buffer.toString(),
|
buffer.toString(),
|
||||||
null,
|
null,
|
||||||
new ResultPoint[] { leftPoints[0], leftPoints[1], rightPoints[0], rightPoints[1], },
|
new ResultPoint[] { leftPoints[0], leftPoints[1], rightPoints[0], rightPoints[1], },
|
||||||
BarcodeFormat.RSS_14);
|
BarcodeFormat.RSS_14);
|
||||||
|
result.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]e0");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkChecksum(Pair leftPair, Pair rightPair) {
|
private static boolean checkChecksum(Pair leftPair, Pair rightPair) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import com.google.zxing.DecodeHintType;
|
||||||
import com.google.zxing.FormatException;
|
import com.google.zxing.FormatException;
|
||||||
import com.google.zxing.NotFoundException;
|
import com.google.zxing.NotFoundException;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
|
import com.google.zxing.ResultMetadataType;
|
||||||
import com.google.zxing.ResultPoint;
|
import com.google.zxing.ResultPoint;
|
||||||
import com.google.zxing.common.BitArray;
|
import com.google.zxing.common.BitArray;
|
||||||
import com.google.zxing.common.detector.MathUtils;
|
import com.google.zxing.common.detector.MathUtils;
|
||||||
|
@ -355,12 +356,14 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
ResultPoint[] firstPoints = pairs.get(0).getFinderPattern().getResultPoints();
|
ResultPoint[] firstPoints = pairs.get(0).getFinderPattern().getResultPoints();
|
||||||
ResultPoint[] lastPoints = pairs.get(pairs.size() - 1).getFinderPattern().getResultPoints();
|
ResultPoint[] lastPoints = pairs.get(pairs.size() - 1).getFinderPattern().getResultPoints();
|
||||||
|
|
||||||
return new Result(
|
Result result = new Result(
|
||||||
resultingString,
|
resultingString,
|
||||||
null,
|
null,
|
||||||
new ResultPoint[]{firstPoints[0], firstPoints[1], lastPoints[0], lastPoints[1]},
|
new ResultPoint[]{firstPoints[0], firstPoints[1], lastPoints[0], lastPoints[1]},
|
||||||
BarcodeFormat.RSS_EXPANDED
|
BarcodeFormat.RSS_EXPANDED
|
||||||
);
|
);
|
||||||
|
result.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]e0");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkChecksum() {
|
private boolean checkChecksum() {
|
||||||
|
|
|
@ -94,6 +94,7 @@ public final class PDF417Reader implements Reader, MultipleBarcodeReader {
|
||||||
if (pdf417ResultMetadata != null) {
|
if (pdf417ResultMetadata != null) {
|
||||||
result.putMetadata(ResultMetadataType.PDF417_EXTRA_METADATA, pdf417ResultMetadata);
|
result.putMetadata(ResultMetadataType.PDF417_EXTRA_METADATA, pdf417ResultMetadata);
|
||||||
}
|
}
|
||||||
|
result.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]L" + decoderResult.getSymbologyModifier());
|
||||||
results.add(result);
|
results.add(result);
|
||||||
}
|
}
|
||||||
return results.toArray(EMPTY_RESULT_ARRAY);
|
return results.toArray(EMPTY_RESULT_ARRAY);
|
||||||
|
|
|
@ -99,6 +99,7 @@ public class QRCodeReader implements Reader {
|
||||||
result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY,
|
result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY,
|
||||||
decoderResult.getStructuredAppendParity());
|
decoderResult.getStructuredAppendParity());
|
||||||
}
|
}
|
||||||
|
result.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]Q" + decoderResult.getSymbologyModifier());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,10 +58,13 @@ final class DecodedBitStreamParser {
|
||||||
List<byte[]> byteSegments = new ArrayList<>(1);
|
List<byte[]> byteSegments = new ArrayList<>(1);
|
||||||
int symbolSequence = -1;
|
int symbolSequence = -1;
|
||||||
int parityData = -1;
|
int parityData = -1;
|
||||||
|
int symbologyModifier = 1;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CharacterSetECI currentCharacterSetECI = null;
|
CharacterSetECI currentCharacterSetECI = null;
|
||||||
boolean fc1InEffect = false;
|
boolean fc1InEffect = false;
|
||||||
|
boolean hasFNC1first = false;
|
||||||
|
boolean hasFNC1second = false;
|
||||||
Mode mode;
|
Mode mode;
|
||||||
do {
|
do {
|
||||||
// While still another segment to read...
|
// While still another segment to read...
|
||||||
|
@ -75,7 +78,12 @@ final class DecodedBitStreamParser {
|
||||||
case TERMINATOR:
|
case TERMINATOR:
|
||||||
break;
|
break;
|
||||||
case FNC1_FIRST_POSITION:
|
case FNC1_FIRST_POSITION:
|
||||||
|
hasFNC1first = true; // symbology detection
|
||||||
|
// We do little with FNC1 except alter the parsed result a bit according to the spec
|
||||||
|
fc1InEffect = true;
|
||||||
|
break;
|
||||||
case FNC1_SECOND_POSITION:
|
case FNC1_SECOND_POSITION:
|
||||||
|
hasFNC1second = true; // symbology detection
|
||||||
// We do little with FNC1 except alter the parsed result a bit according to the spec
|
// We do little with FNC1 except alter the parsed result a bit according to the spec
|
||||||
fc1InEffect = true;
|
fc1InEffect = true;
|
||||||
break;
|
break;
|
||||||
|
@ -128,6 +136,25 @@ final class DecodedBitStreamParser {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (mode != Mode.TERMINATOR);
|
} while (mode != Mode.TERMINATOR);
|
||||||
|
|
||||||
|
if (currentCharacterSetECI != null) {
|
||||||
|
if (hasFNC1first) {
|
||||||
|
symbologyModifier = 4;
|
||||||
|
} else if (hasFNC1second) {
|
||||||
|
symbologyModifier = 6;
|
||||||
|
} else {
|
||||||
|
symbologyModifier = 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (hasFNC1first) {
|
||||||
|
symbologyModifier = 3;
|
||||||
|
} else if (hasFNC1second) {
|
||||||
|
symbologyModifier = 5;
|
||||||
|
} else {
|
||||||
|
symbologyModifier = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
// from readBits() calls
|
// from readBits() calls
|
||||||
throw FormatException.getFormatInstance();
|
throw FormatException.getFormatInstance();
|
||||||
|
@ -138,7 +165,8 @@ final class DecodedBitStreamParser {
|
||||||
byteSegments.isEmpty() ? null : byteSegments,
|
byteSegments.isEmpty() ? null : byteSegments,
|
||||||
ecLevel == null ? null : ecLevel.toString(),
|
ecLevel == null ? null : ecLevel.toString(),
|
||||||
symbolSequence,
|
symbolSequence,
|
||||||
parityData);
|
parityData,
|
||||||
|
symbologyModifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]z0
|
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]F0
|
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]C1
|
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]C0
|
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]A0
|
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]G0
|
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]d1
|
1
core/src/test/resources/blackbox/ean13-1/01.metadata.txt
Normal file
1
core/src/test/resources/blackbox/ean13-1/01.metadata.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]E0
|
1
core/src/test/resources/blackbox/ean8-1/01.metadata.txt
Normal file
1
core/src/test/resources/blackbox/ean8-1/01.metadata.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]E4
|
1
core/src/test/resources/blackbox/itf-1/01.metadata.txt
Normal file
1
core/src/test/resources/blackbox/itf-1/01.metadata.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]I0
|
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]L0
|
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]Q1
|
|
@ -0,0 +1 @@
|
||||||
|
SYMBOLOGY_IDENTIFIER=]Q1
|
Loading…
Reference in a new issue