mirror of
https://github.com/zxing/zxing.git
synced 2024-11-09 20:44:03 -08:00
Add ResultMetadataType.ERRORS_CORRECTED and ERASURES_CORRECTED (#1657)
* Add ResultMetadataType.ERRORS_CORRECTED and ERASURES_CORRECTED (2D barcodes) * Maintain existing constructor on AztecDetectorResult * Maintain existing ReedSolomonDecoder.decode method
This commit is contained in:
parent
57ed027468
commit
282f5ba726
|
@ -55,6 +55,18 @@ public enum ResultMetadataType {
|
|||
*/
|
||||
ERROR_CORRECTION_LEVEL,
|
||||
|
||||
/**
|
||||
* The number of errors corrected. If applicable, maps to an {@link Integer} of value
|
||||
* greater than or equal to zero.
|
||||
*/
|
||||
ERRORS_CORRECTED,
|
||||
|
||||
/**
|
||||
* The number of erasures corrected. If applicable, maps to an {@link Integer} of value
|
||||
* greater than or equal to zero.
|
||||
*/
|
||||
ERASURES_CORRECTED,
|
||||
|
||||
/**
|
||||
* For some periodicals, indicates the issue number as an {@link Integer}.
|
||||
*/
|
||||
|
@ -73,12 +85,12 @@ public enum ResultMetadataType {
|
|||
POSSIBLE_COUNTRY,
|
||||
|
||||
/**
|
||||
* For some products, the extension text
|
||||
* For some products, the extension text.
|
||||
*/
|
||||
UPC_EAN_EXTENSION,
|
||||
|
||||
/**
|
||||
* PDF417-specific metadata
|
||||
* PDF417-specific metadata.
|
||||
*/
|
||||
PDF417_EXTRA_METADATA,
|
||||
|
||||
|
|
|
@ -31,16 +31,27 @@ public final class AztecDetectorResult extends DetectorResult {
|
|||
private final boolean compact;
|
||||
private final int nbDatablocks;
|
||||
private final int nbLayers;
|
||||
private final int errorsCorrected;
|
||||
|
||||
public AztecDetectorResult(BitMatrix bits,
|
||||
ResultPoint[] points,
|
||||
boolean compact,
|
||||
int nbDatablocks,
|
||||
int nbLayers) {
|
||||
this(bits, points, compact, nbDatablocks, nbLayers, 0);
|
||||
}
|
||||
|
||||
public AztecDetectorResult(BitMatrix bits,
|
||||
ResultPoint[] points,
|
||||
boolean compact,
|
||||
int nbDatablocks,
|
||||
int nbLayers,
|
||||
int errorsCorrected) {
|
||||
super(bits, points);
|
||||
this.compact = compact;
|
||||
this.nbDatablocks = nbDatablocks;
|
||||
this.nbLayers = nbLayers;
|
||||
this.errorsCorrected = errorsCorrected;
|
||||
}
|
||||
|
||||
public int getNbLayers() {
|
||||
|
@ -55,4 +66,7 @@ public final class AztecDetectorResult extends DetectorResult {
|
|||
return compact;
|
||||
}
|
||||
|
||||
public int getErrorsCorrected() {
|
||||
return errorsCorrected;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,9 +61,11 @@ public final class AztecReader implements Reader {
|
|||
Detector detector = new Detector(image.getBlackMatrix());
|
||||
ResultPoint[] points = null;
|
||||
DecoderResult decoderResult = null;
|
||||
int errorsCorrected = 0;
|
||||
try {
|
||||
AztecDetectorResult detectorResult = detector.detect(false);
|
||||
points = detectorResult.getPoints();
|
||||
errorsCorrected = detectorResult.getErrorsCorrected();
|
||||
decoderResult = new Decoder().decode(detectorResult);
|
||||
} catch (NotFoundException e) {
|
||||
notFoundException = e;
|
||||
|
@ -74,6 +76,7 @@ public final class AztecReader implements Reader {
|
|||
try {
|
||||
AztecDetectorResult detectorResult = detector.detect(true);
|
||||
points = detectorResult.getPoints();
|
||||
errorsCorrected = detectorResult.getErrorsCorrected();
|
||||
decoderResult = new Decoder().decode(detectorResult);
|
||||
} catch (NotFoundException | FormatException e) {
|
||||
if (notFoundException != null) {
|
||||
|
@ -110,6 +113,8 @@ public final class AztecReader implements Reader {
|
|||
if (ecLevel != null) {
|
||||
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
|
||||
}
|
||||
errorsCorrected += decoderResult.getErrorsCorrected();
|
||||
result.putMetadata(ResultMetadataType.ERRORS_CORRECTED, errorsCorrected);
|
||||
result.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]z" + decoderResult.getSymbologyModifier());
|
||||
|
||||
return result;
|
||||
|
|
|
@ -87,6 +87,7 @@ public final class Decoder {
|
|||
DecoderResult decoderResult =
|
||||
new DecoderResult(rawBytes, result, null, String.format("%d%%", correctedBits.ecLevel));
|
||||
decoderResult.setNumBits(correctedBits.correctBits.length);
|
||||
decoderResult.setErrorsCorrected(correctedBits.errorsCorrected);
|
||||
return decoderResult;
|
||||
}
|
||||
|
||||
|
@ -264,10 +265,12 @@ public final class Decoder {
|
|||
|
||||
static final class CorrectedBitsResult {
|
||||
private final boolean[] correctBits;
|
||||
private final int errorsCorrected;
|
||||
private final int ecLevel;
|
||||
|
||||
CorrectedBitsResult(boolean[] correctBits, int ecLevel) {
|
||||
CorrectedBitsResult(boolean[] correctBits, int errorsCorrected, int ecLevel) {
|
||||
this.correctBits = correctBits;
|
||||
this.errorsCorrected = errorsCorrected;
|
||||
this.ecLevel = ecLevel;
|
||||
}
|
||||
}
|
||||
|
@ -308,9 +311,10 @@ public final class Decoder {
|
|||
dataWords[i] = readCode(rawbits, offset, codewordSize);
|
||||
}
|
||||
|
||||
int errorsCorrected = 0;
|
||||
try {
|
||||
ReedSolomonDecoder rsDecoder = new ReedSolomonDecoder(gf);
|
||||
rsDecoder.decode(dataWords, numCodewords - numDataCodewords);
|
||||
errorsCorrected = rsDecoder.decodeWithECCount(dataWords, numCodewords - numDataCodewords);
|
||||
} catch (ReedSolomonException ex) {
|
||||
throw FormatException.getFormatInstance(ex);
|
||||
}
|
||||
|
@ -343,7 +347,8 @@ public final class Decoder {
|
|||
}
|
||||
}
|
||||
|
||||
return new CorrectedBitsResult(correctedBits, 100 * (numCodewords - numDataCodewords) / numCodewords);
|
||||
int ecLevel = 100 * (numCodewords - numDataCodewords) / numCodewords;
|
||||
return new CorrectedBitsResult(correctedBits, errorsCorrected, ecLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -82,7 +82,7 @@ public final class Detector {
|
|||
}
|
||||
|
||||
// 3. Get the size of the matrix and other parameters from the bull's eye
|
||||
extractParameters(bullsEyeCorners);
|
||||
int errorsCorrected = extractParameters(bullsEyeCorners);
|
||||
|
||||
// 4. Sample the grid
|
||||
BitMatrix bits = sampleGrid(image,
|
||||
|
@ -94,16 +94,17 @@ public final class Detector {
|
|||
// 5. Get the corners of the matrix.
|
||||
ResultPoint[] corners = getMatrixCornerPoints(bullsEyeCorners);
|
||||
|
||||
return new AztecDetectorResult(bits, corners, compact, nbDataBlocks, nbLayers);
|
||||
return new AztecDetectorResult(bits, corners, compact, nbDataBlocks, nbLayers, errorsCorrected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the number of data layers and data blocks from the layer around the bull's eye.
|
||||
*
|
||||
* @param bullsEyeCorners the array of bull's eye corners
|
||||
* @return the number of errors corrected during parameter extraction
|
||||
* @throws NotFoundException in case of too many errors or invalid parameters
|
||||
*/
|
||||
private void extractParameters(ResultPoint[] bullsEyeCorners) throws NotFoundException {
|
||||
private int extractParameters(ResultPoint[] bullsEyeCorners) throws NotFoundException {
|
||||
if (!isValid(bullsEyeCorners[0]) || !isValid(bullsEyeCorners[1]) ||
|
||||
!isValid(bullsEyeCorners[2]) || !isValid(bullsEyeCorners[3])) {
|
||||
throw NotFoundException.getNotFoundInstance();
|
||||
|
@ -140,7 +141,8 @@ public final class Detector {
|
|||
|
||||
// Corrects parameter data using RS. Returns just the data portion
|
||||
// without the error correction.
|
||||
int correctedData = getCorrectedParameterData(parameterData, compact);
|
||||
CorrectedParameter correctedParam = getCorrectedParameterData(parameterData, compact);
|
||||
int correctedData = correctedParam.getData();
|
||||
|
||||
if (compact) {
|
||||
// 8 bits: 2 bits layers and 6 bits data blocks
|
||||
|
@ -151,6 +153,8 @@ public final class Detector {
|
|||
nbLayers = (correctedData >> 11) + 1;
|
||||
nbDataBlocks = (correctedData & 0x7FF) + 1;
|
||||
}
|
||||
|
||||
return correctedParam.getErrorsCorrected();
|
||||
}
|
||||
|
||||
private static int getRotation(int[] sides, int length) throws NotFoundException {
|
||||
|
@ -189,9 +193,11 @@ public final class Detector {
|
|||
*
|
||||
* @param parameterData parameter bits
|
||||
* @param compact true if this is a compact Aztec code
|
||||
* @return the corrected parameter
|
||||
* @throws NotFoundException if the array contains too many errors
|
||||
*/
|
||||
private static int getCorrectedParameterData(long parameterData, boolean compact) throws NotFoundException {
|
||||
private static CorrectedParameter getCorrectedParameterData(long parameterData,
|
||||
boolean compact) throws NotFoundException {
|
||||
int numCodewords;
|
||||
int numDataCodewords;
|
||||
|
||||
|
@ -209,18 +215,21 @@ public final class Detector {
|
|||
parameterWords[i] = (int) parameterData & 0xF;
|
||||
parameterData >>= 4;
|
||||
}
|
||||
|
||||
int errorsCorrected = 0;
|
||||
try {
|
||||
ReedSolomonDecoder rsDecoder = new ReedSolomonDecoder(GenericGF.AZTEC_PARAM);
|
||||
rsDecoder.decode(parameterWords, numECCodewords);
|
||||
errorsCorrected = rsDecoder.decodeWithECCount(parameterWords, numECCodewords);
|
||||
} catch (ReedSolomonException ignored) {
|
||||
throw NotFoundException.getNotFoundInstance();
|
||||
}
|
||||
|
||||
// Toss the error correction. Just return the data as an integer
|
||||
int result = 0;
|
||||
for (int i = 0; i < numDataCodewords; i++) {
|
||||
result = (result << 4) + parameterWords[i];
|
||||
}
|
||||
return result;
|
||||
return new CorrectedParameter(result, errorsCorrected);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -600,4 +609,22 @@ public final class Detector {
|
|||
return "<" + x + ' ' + y + '>';
|
||||
}
|
||||
}
|
||||
|
||||
static final class CorrectedParameter {
|
||||
private final int data;
|
||||
private final int errorsCorrected;
|
||||
|
||||
CorrectedParameter(int data, int errorsCorrected) {
|
||||
this.data = data;
|
||||
this.errorsCorrected = errorsCorrected;
|
||||
}
|
||||
|
||||
int getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
int getErrorsCorrected() {
|
||||
return errorsCorrected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,20 @@ public final class ReedSolomonDecoder {
|
|||
* @throws ReedSolomonException if decoding fails for any reason
|
||||
*/
|
||||
public void decode(int[] received, int twoS) throws ReedSolomonException {
|
||||
decodeWithECCount(received, twoS);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Decodes given set of received codewords, which include both data and error-correction
|
||||
* codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,
|
||||
* in the input.</p>
|
||||
*
|
||||
* @param received data and error-correction codewords
|
||||
* @param twoS number of error-correction codewords available
|
||||
* @return the number of errors corrected
|
||||
* @throws ReedSolomonException if decoding fails for any reason
|
||||
*/
|
||||
public int decodeWithECCount(int[] received, int twoS) throws ReedSolomonException {
|
||||
GenericGFPoly poly = new GenericGFPoly(field, received);
|
||||
int[] syndromeCoefficients = new int[twoS];
|
||||
boolean noError = true;
|
||||
|
@ -67,7 +81,7 @@ public final class ReedSolomonDecoder {
|
|||
}
|
||||
}
|
||||
if (noError) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
GenericGFPoly syndrome = new GenericGFPoly(field, syndromeCoefficients);
|
||||
GenericGFPoly[] sigmaOmega =
|
||||
|
@ -83,6 +97,7 @@ public final class ReedSolomonDecoder {
|
|||
}
|
||||
received[position] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]);
|
||||
}
|
||||
return errorLocations.length;
|
||||
}
|
||||
|
||||
private GenericGFPoly[] runEuclideanAlgorithm(GenericGFPoly a, GenericGFPoly b, int R)
|
||||
|
|
|
@ -83,6 +83,7 @@ public final class DataMatrixReader implements Reader {
|
|||
if (ecLevel != null) {
|
||||
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
|
||||
}
|
||||
result.putMetadata(ResultMetadataType.ERRORS_CORRECTED, decoderResult.getErrorsCorrected());
|
||||
result.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]d" + decoderResult.getSymbologyModifier());
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -78,13 +78,14 @@ public final class Decoder {
|
|||
}
|
||||
byte[] resultBytes = new byte[totalBytes];
|
||||
|
||||
int errorsCorrected = 0;
|
||||
int dataBlocksCount = dataBlocks.length;
|
||||
// Error-correct and copy data blocks together into a stream of bytes
|
||||
for (int j = 0; j < dataBlocksCount; j++) {
|
||||
DataBlock dataBlock = dataBlocks[j];
|
||||
byte[] codewordBytes = dataBlock.getCodewords();
|
||||
int numDataCodewords = dataBlock.getNumDataCodewords();
|
||||
correctErrors(codewordBytes, numDataCodewords);
|
||||
errorsCorrected += correctErrors(codewordBytes, numDataCodewords);
|
||||
for (int i = 0; i < numDataCodewords; i++) {
|
||||
// De-interlace data blocks.
|
||||
resultBytes[i * dataBlocksCount + j] = codewordBytes[i];
|
||||
|
@ -92,7 +93,9 @@ public final class Decoder {
|
|||
}
|
||||
|
||||
// Decode the contents of that stream of bytes
|
||||
return DecodedBitStreamParser.decode(resultBytes);
|
||||
DecoderResult result = DecodedBitStreamParser.decode(resultBytes);
|
||||
result.setErrorsCorrected(errorsCorrected);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,17 +104,19 @@ public final class Decoder {
|
|||
*
|
||||
* @param codewordBytes data and error correction codewords
|
||||
* @param numDataCodewords number of codewords that are data bytes
|
||||
* @return the number of errors corrected
|
||||
* @throws ChecksumException if error correction fails
|
||||
*/
|
||||
private void correctErrors(byte[] codewordBytes, int numDataCodewords) throws ChecksumException {
|
||||
private int correctErrors(byte[] codewordBytes, int numDataCodewords) throws ChecksumException {
|
||||
int numCodewords = codewordBytes.length;
|
||||
// First read into an array of ints
|
||||
int[] codewordsInts = new int[numCodewords];
|
||||
for (int i = 0; i < numCodewords; i++) {
|
||||
codewordsInts[i] = codewordBytes[i] & 0xFF;
|
||||
}
|
||||
int errorsCorrected = 0;
|
||||
try {
|
||||
rsDecoder.decode(codewordsInts, codewordBytes.length - numDataCodewords);
|
||||
errorsCorrected = rsDecoder.decodeWithECCount(codewordsInts, codewordBytes.length - numDataCodewords);
|
||||
} catch (ReedSolomonException ignored) {
|
||||
throw ChecksumException.getChecksumInstance();
|
||||
}
|
||||
|
@ -120,6 +125,7 @@ public final class Decoder {
|
|||
for (int i = 0; i < numDataCodewords; i++) {
|
||||
codewordBytes[i] = (byte) codewordsInts[i];
|
||||
}
|
||||
return errorsCorrected;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ public final class MaxiCodeReader implements Reader {
|
|||
BitMatrix bits = extractPureBits(image.getBlackMatrix());
|
||||
DecoderResult decoderResult = decoder.decode(bits, hints);
|
||||
Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), NO_POINTS, BarcodeFormat.MAXICODE);
|
||||
|
||||
result.putMetadata(ResultMetadataType.ERRORS_CORRECTED, decoderResult.getErrorsCorrected());
|
||||
String ecLevel = decoderResult.getECLevel();
|
||||
if (ecLevel != null) {
|
||||
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
|
||||
|
|
|
@ -54,20 +54,20 @@ public final class Decoder {
|
|||
BitMatrixParser parser = new BitMatrixParser(bits);
|
||||
byte[] codewords = parser.readCodewords();
|
||||
|
||||
correctErrors(codewords, 0, 10, 10, ALL);
|
||||
int errorsCorrected = correctErrors(codewords, 0, 10, 10, ALL);
|
||||
int mode = codewords[0] & 0x0F;
|
||||
byte[] datawords;
|
||||
switch (mode) {
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
correctErrors(codewords, 20, 84, 40, EVEN);
|
||||
correctErrors(codewords, 20, 84, 40, ODD);
|
||||
errorsCorrected += correctErrors(codewords, 20, 84, 40, EVEN);
|
||||
errorsCorrected += correctErrors(codewords, 20, 84, 40, ODD);
|
||||
datawords = new byte[94];
|
||||
break;
|
||||
case 5:
|
||||
correctErrors(codewords, 20, 68, 56, EVEN);
|
||||
correctErrors(codewords, 20, 68, 56, ODD);
|
||||
errorsCorrected += correctErrors(codewords, 20, 68, 56, EVEN);
|
||||
errorsCorrected += correctErrors(codewords, 20, 68, 56, ODD);
|
||||
datawords = new byte[78];
|
||||
break;
|
||||
default:
|
||||
|
@ -77,10 +77,12 @@ public final class Decoder {
|
|||
System.arraycopy(codewords, 0, datawords, 0, 10);
|
||||
System.arraycopy(codewords, 20, datawords, 10, datawords.length - 10);
|
||||
|
||||
return DecodedBitStreamParser.decode(datawords, mode);
|
||||
DecoderResult result = DecodedBitStreamParser.decode(datawords, mode);
|
||||
result.setErrorsCorrected(errorsCorrected);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void correctErrors(byte[] codewordBytes,
|
||||
private int correctErrors(byte[] codewordBytes,
|
||||
int start,
|
||||
int dataCodewords,
|
||||
int ecCodewords,
|
||||
|
@ -97,8 +99,9 @@ public final class Decoder {
|
|||
codewordsInts[i / divisor] = codewordBytes[i + start] & 0xFF;
|
||||
}
|
||||
}
|
||||
int errorsCorrected = 0;
|
||||
try {
|
||||
rsDecoder.decode(codewordsInts, ecCodewords / divisor);
|
||||
errorsCorrected = rsDecoder.decodeWithECCount(codewordsInts, ecCodewords / divisor);
|
||||
} catch (ReedSolomonException ignored) {
|
||||
throw ChecksumException.getChecksumInstance();
|
||||
}
|
||||
|
@ -109,6 +112,7 @@ public final class Decoder {
|
|||
codewordBytes[i + start] = (byte) codewordsInts[i / divisor];
|
||||
}
|
||||
}
|
||||
return errorsCorrected;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -90,6 +90,8 @@ public final class PDF417Reader implements Reader, MultipleBarcodeReader {
|
|||
points[6], points[7], getMinCodewordWidth(points), getMaxCodewordWidth(points));
|
||||
Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.PDF_417);
|
||||
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.getECLevel());
|
||||
result.putMetadata(ResultMetadataType.ERRORS_CORRECTED, decoderResult.getErrorsCorrected());
|
||||
result.putMetadata(ResultMetadataType.ERASURES_CORRECTED, decoderResult.getErasures());
|
||||
PDF417ResultMetadata pdf417ResultMetadata = (PDF417ResultMetadata) decoderResult.getOther();
|
||||
if (pdf417ResultMetadata != null) {
|
||||
result.putMetadata(ResultMetadataType.PDF417_EXTRA_METADATA, pdf417ResultMetadata);
|
||||
|
|
|
@ -99,6 +99,7 @@ public class QRCodeReader implements Reader {
|
|||
result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY,
|
||||
decoderResult.getStructuredAppendParity());
|
||||
}
|
||||
result.putMetadata(ResultMetadataType.ERRORS_CORRECTED, decoderResult.getErrorsCorrected());
|
||||
result.putMetadata(ResultMetadataType.SYMBOLOGY_IDENTIFIER, "]Q" + decoderResult.getSymbologyModifier());
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -146,17 +146,20 @@ public final class Decoder {
|
|||
int resultOffset = 0;
|
||||
|
||||
// Error-correct and copy data blocks together into a stream of bytes
|
||||
int errorsCorrected = 0;
|
||||
for (DataBlock dataBlock : dataBlocks) {
|
||||
byte[] codewordBytes = dataBlock.getCodewords();
|
||||
int numDataCodewords = dataBlock.getNumDataCodewords();
|
||||
correctErrors(codewordBytes, numDataCodewords);
|
||||
errorsCorrected += correctErrors(codewordBytes, numDataCodewords);
|
||||
for (int i = 0; i < numDataCodewords; i++) {
|
||||
resultBytes[resultOffset++] = codewordBytes[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the contents of that stream of bytes
|
||||
return DecodedBitStreamParser.decode(resultBytes, version, ecLevel, hints);
|
||||
DecoderResult result = DecodedBitStreamParser.decode(resultBytes, version, ecLevel, hints);
|
||||
result.setErrorsCorrected(errorsCorrected);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -165,17 +168,19 @@ public final class Decoder {
|
|||
*
|
||||
* @param codewordBytes data and error correction codewords
|
||||
* @param numDataCodewords number of codewords that are data bytes
|
||||
* @return the number of errors corrected
|
||||
* @throws ChecksumException if error correction fails
|
||||
*/
|
||||
private void correctErrors(byte[] codewordBytes, int numDataCodewords) throws ChecksumException {
|
||||
private int correctErrors(byte[] codewordBytes, int numDataCodewords) throws ChecksumException {
|
||||
int numCodewords = codewordBytes.length;
|
||||
// First read into an array of ints
|
||||
int[] codewordsInts = new int[numCodewords];
|
||||
for (int i = 0; i < numCodewords; i++) {
|
||||
codewordsInts[i] = codewordBytes[i] & 0xFF;
|
||||
}
|
||||
int errorsCorrected = 0;
|
||||
try {
|
||||
rsDecoder.decode(codewordsInts, codewordBytes.length - numDataCodewords);
|
||||
errorsCorrected = rsDecoder.decodeWithECCount(codewordsInts, codewordBytes.length - numDataCodewords);
|
||||
} catch (ReedSolomonException ignored) {
|
||||
throw ChecksumException.getChecksumInstance();
|
||||
}
|
||||
|
@ -184,6 +189,7 @@ public final class Decoder {
|
|||
for (int i = 0; i < numDataCodewords; i++) {
|
||||
codewordBytes[i] = (byte) codewordsInts[i];
|
||||
}
|
||||
return errorsCorrected;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,10 +26,10 @@ public final class AztecBlackBox1TestCase extends AbstractBlackBoxTestCase {
|
|||
|
||||
public AztecBlackBox1TestCase() {
|
||||
super("src/test/resources/blackbox/aztec-1", new AztecReader(), BarcodeFormat.AZTEC);
|
||||
addTest(14, 14, 0.0f);
|
||||
addTest(14, 14, 90.0f);
|
||||
addTest(14, 14, 180.0f);
|
||||
addTest(14, 14, 270.0f);
|
||||
addTest(15, 15, 0.0f);
|
||||
addTest(15, 15, 90.0f);
|
||||
addTest(15, 15, 180.0f);
|
||||
addTest(15, 15, 270.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -493,7 +493,7 @@ public final class EncoderTest extends Assert {
|
|||
assertEquals("Unexpected nr. of layers", layers, aztec.getLayers());
|
||||
BitMatrix matrix = aztec.getMatrix();
|
||||
AztecDetectorResult r =
|
||||
new AztecDetectorResult(matrix, NO_POINTS, aztec.isCompact(), aztec.getCodeWords(), aztec.getLayers());
|
||||
new AztecDetectorResult(matrix, NO_POINTS, aztec.isCompact(), aztec.getCodeWords(), aztec.getLayers(), 0);
|
||||
DecoderResult res = new Decoder().decode(r);
|
||||
assertEquals(data, res.getText());
|
||||
// Check error correction by introducing a few minor errors
|
||||
|
@ -502,7 +502,7 @@ public final class EncoderTest extends Assert {
|
|||
matrix.flip(random.nextInt(matrix.getWidth()), matrix.getHeight() - 2 + random.nextInt(2));
|
||||
matrix.flip(random.nextInt(2), random.nextInt(matrix.getHeight()));
|
||||
matrix.flip(matrix.getWidth() - 2 + random.nextInt(2), random.nextInt(matrix.getHeight()));
|
||||
r = new AztecDetectorResult(matrix, NO_POINTS, aztec.isCompact(), aztec.getCodeWords(), aztec.getLayers());
|
||||
r = new AztecDetectorResult(matrix, NO_POINTS, aztec.isCompact(), aztec.getCodeWords(), aztec.getLayers(), 0);
|
||||
res = new Decoder().decode(r);
|
||||
assertEquals(data, res.getText());
|
||||
}
|
||||
|
@ -527,7 +527,7 @@ public final class EncoderTest extends Assert {
|
|||
BitMatrix matrix2 = aztec.getMatrix();
|
||||
assertEquals(matrix, matrix2);
|
||||
AztecDetectorResult r =
|
||||
new AztecDetectorResult(matrix, NO_POINTS, aztec.isCompact(), aztec.getCodeWords(), aztec.getLayers());
|
||||
new AztecDetectorResult(matrix, NO_POINTS, aztec.isCompact(), aztec.getCodeWords(), aztec.getLayers(), 0);
|
||||
DecoderResult res = new Decoder().decode(r);
|
||||
assertEquals(data, res.getText());
|
||||
// Check error correction by introducing up to eccPercent/2 errors
|
||||
|
@ -543,7 +543,7 @@ public final class EncoderTest extends Assert {
|
|||
: matrix.getHeight() - 1 - random.nextInt(aztec.getLayers() * 2);
|
||||
matrix.flip(x, y);
|
||||
}
|
||||
r = new AztecDetectorResult(matrix, NO_POINTS, aztec.isCompact(), aztec.getCodeWords(), aztec.getLayers());
|
||||
r = new AztecDetectorResult(matrix, NO_POINTS, aztec.isCompact(), aztec.getCodeWords(), aztec.getLayers(), 0);
|
||||
res = new Decoder().decode(r);
|
||||
assertEquals(data, res.getText());
|
||||
}
|
||||
|
|
|
@ -165,6 +165,8 @@ public abstract class AbstractBlackBoxTestCase extends Assert {
|
|||
try (BufferedReader reader = Files.newBufferedReader(expectedMetadataFile, StandardCharsets.UTF_8)) {
|
||||
expectedMetadata.load(reader);
|
||||
}
|
||||
correctInteger(expectedMetadata, ResultMetadataType.ERRORS_CORRECTED);
|
||||
correctInteger(expectedMetadata, ResultMetadataType.ERASURES_CORRECTED);
|
||||
}
|
||||
|
||||
for (int x = 0; x < testCount; x++) {
|
||||
|
@ -249,6 +251,15 @@ public abstract class AbstractBlackBoxTestCase extends Assert {
|
|||
}
|
||||
}
|
||||
|
||||
private static void correctInteger(Properties metadata, ResultMetadataType key) {
|
||||
String skey = key.toString();
|
||||
if (metadata.containsKey(skey)) {
|
||||
String sval = metadata.getProperty(skey);
|
||||
Integer ival = Integer.parseInt(sval);
|
||||
metadata.put(skey, ival);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean decode(BinaryBitmap source,
|
||||
float rotation,
|
||||
String expectedText,
|
||||
|
|
|
@ -27,10 +27,10 @@ public final class DataMatrixBlackBox1TestCase extends AbstractBlackBoxTestCase
|
|||
|
||||
public DataMatrixBlackBox1TestCase() {
|
||||
super("src/test/resources/blackbox/datamatrix-1", new MultiFormatReader(), BarcodeFormat.DATA_MATRIX);
|
||||
addTest(21, 21, 0.0f);
|
||||
addTest(21, 21, 90.0f);
|
||||
addTest(21, 21, 180.0f);
|
||||
addTest(21, 21, 270.0f);
|
||||
addTest(22, 22, 0.0f);
|
||||
addTest(22, 22, 90.0f);
|
||||
addTest(22, 22, 180.0f);
|
||||
addTest(22, 22, 270.0f);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public final class MaxiCodeBlackBox1TestCase extends AbstractBlackBoxTestCase {
|
|||
public MaxiCodeBlackBox1TestCase() {
|
||||
super("src/test/resources/blackbox/maxicode-1", new MultiFormatReader(), BarcodeFormat.MAXICODE);
|
||||
addHint(DecodeHintType.PURE_BARCODE);
|
||||
addTest(7, 7, 0.0f);
|
||||
addTest(8, 8, 0.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public final class Maxicode1TestCase extends AbstractBlackBoxTestCase {
|
|||
|
||||
public Maxicode1TestCase() {
|
||||
super("src/test/resources/blackbox/maxicode-1", new MultiFormatReader(), BarcodeFormat.MAXICODE);
|
||||
addTest(7, 7, 0.0f);
|
||||
addTest(8, 8, 0.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,10 +29,10 @@ public final class PDF417BlackBox1TestCase extends AbstractBlackBoxTestCase {
|
|||
|
||||
public PDF417BlackBox1TestCase() {
|
||||
super("src/test/resources/blackbox/pdf417-1", new MultiFormatReader(), BarcodeFormat.PDF_417);
|
||||
addTest(12, 12, 0.0f);
|
||||
addTest(12, 12, 90.0f);
|
||||
addTest(12, 12, 180.0f);
|
||||
addTest(12, 12, 270.0f);
|
||||
addTest(13, 13, 0.0f);
|
||||
addTest(13, 13, 90.0f);
|
||||
addTest(13, 13, 180.0f);
|
||||
addTest(13, 13, 270.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,10 +27,10 @@ public final class QRCodeBlackBox2TestCase extends AbstractBlackBoxTestCase {
|
|||
|
||||
public QRCodeBlackBox2TestCase() {
|
||||
super("src/test/resources/blackbox/qrcode-2", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||
addTest(31, 31, 0.0f);
|
||||
addTest(29, 29, 90.0f);
|
||||
addTest(30, 30, 180.0f);
|
||||
addTest(30, 30, 270.0f);
|
||||
addTest(32, 32, 0.0f);
|
||||
addTest(30, 30, 90.0f);
|
||||
addTest(31, 31, 180.0f);
|
||||
addTest(31, 31, 270.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
ERRORS_CORRECTED=3
|
BIN
core/src/test/resources/blackbox/aztec-1/hello-with-errors.png
Normal file
BIN
core/src/test/resources/blackbox/aztec-1/hello-with-errors.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.2 KiB |
|
@ -0,0 +1 @@
|
|||
hello
|
|
@ -0,0 +1 @@
|
|||
ERRORS_CORRECTED=0
|
|
@ -1 +1,2 @@
|
|||
SYMBOLOGY_IDENTIFIER=]d1
|
||||
ERRORS_CORRECTED=0
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
ERRORS_CORRECTED=2
|
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
|
@ -0,0 +1 @@
|
|||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*(),./\
|
|
@ -0,0 +1 @@
|
|||
ERRORS_CORRECTED=0
|
|
@ -0,0 +1 @@
|
|||
ERRORS_CORRECTED=3
|
BIN
core/src/test/resources/blackbox/maxicode-1/with-errors.png
Normal file
BIN
core/src/test/resources/blackbox/maxicode-1/with-errors.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -0,0 +1 @@
|
|||
ABCDEFGHIJKLMNOPQRSTUVWXYZ "#$%&'()*+,-./01234:56789
|
|
@ -1 +1,3 @@
|
|||
SYMBOLOGY_IDENTIFIER=]L0
|
||||
ERRORS_CORRECTED=0
|
||||
ERASURES_CORRECTED=0
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
ERRORS_CORRECTED=4
|
||||
ERASURES_CORRECTED=3
|
BIN
core/src/test/resources/blackbox/pdf417-1/14.png
Normal file
BIN
core/src/test/resources/blackbox/pdf417-1/14.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
1
core/src/test/resources/blackbox/pdf417-1/14.txt
Normal file
1
core/src/test/resources/blackbox/pdf417-1/14.txt
Normal file
|
@ -0,0 +1 @@
|
|||
This is PDF417
|
|
@ -1 +1,2 @@
|
|||
SYMBOLOGY_IDENTIFIER=]Q1
|
||||
ERRORS_CORRECTED=0
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
ERRORS_CORRECTED=2
|
BIN
core/src/test/resources/blackbox/qrcode-2/36.png
Normal file
BIN
core/src/test/resources/blackbox/qrcode-2/36.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 964 B |
1
core/src/test/resources/blackbox/qrcode-2/36.txt
Normal file
1
core/src/test/resources/blackbox/qrcode-2/36.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Morden
|
Loading…
Reference in a new issue