Skip to content

Commit

Permalink
port SHA-1: 282f5ba726dfe3ff770b0abdcaf7cfce9700758e
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
micjahn committed Oct 22, 2023
1 parent 50975ea commit ec30735
Show file tree
Hide file tree
Showing 41 changed files with 221 additions and 79 deletions.
2 changes: 1 addition & 1 deletion Source/lib/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
#if NETFX_CORE && !WINDOWS_UWP
[assembly: AssemblyTitle("zxing.net for windows rt")]
#endif
[assembly: AssemblyDescription("port of the java based barcode scanning library for .net (java zxing 29.05.2023 02:10:32)")]
[assembly: AssemblyDescription("port of the java based barcode scanning library for .net (java zxing 26.06.2023 00:30:21)")]
[assembly: AssemblyCompany("ZXing.Net Development")]
[assembly: AssemblyProduct("ZXing.Net")]
[assembly: AssemblyCopyright("Copyright © 2012")]
Expand Down
30 changes: 21 additions & 9 deletions Source/lib/ResultMetadataType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,25 @@ namespace ZXing
public enum ResultMetadataType
{
/// <summary>
/// Unspecified, application-specific metadata. Maps to an unspecified {@link Object}.
/// Unspecified, application-specific metadata. Maps to an unspecified <see cref="System.Object"/>.
/// </summary>
OTHER,

/// <summary>
/// Denotes the likely approximate orientation of the barcode in the image. This value
/// is given as degrees rotated clockwise from the normal, upright orientation.
/// For example a 1D barcode which was found by reading top-to-bottom would be
/// said to have orientation "90". This key maps to an {@link Integer} whose
/// said to have orientation "90". This key maps to an <see cref="System.Int32"/> whose
/// value is in the range [0,360).
/// </summary>
ORIENTATION,

/// <summary>
/// <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
/// which is sometimes used to encode binary data. While <see cref="ZXing.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.List} of byte arrays corresponding to the
/// <p>This maps to a <see cref="System.Collections.IList"/> of byte arrays corresponding to the
/// raw bytes in the byte segments in the barcode, in order.</p>
/// </summary>
BYTE_SEGMENTS,
Expand All @@ -54,24 +54,36 @@ public enum ResultMetadataType
ERROR_CORRECTION_LEVEL,

/// <summary>
/// For some periodicals, indicates the issue number as an {@link Integer}.
/// The number of errors corrected. If applicable, maps to an <see cref="System.Int32"/> of value
/// greater than or equal to zero.
/// </summary>
ERRORS_CORRECTED,

/// <summary>
/// The number of erasures corrected. If applicable, maps to an <see cref="System.Int32"/> of value
/// greater than or equal to zero.
/// </summary>
ERASURES_CORRECTED,

/// <summary>
/// For some periodicals, indicates the issue number as an <see cref="System.Int32"/>.
/// </summary>
ISSUE_NUMBER,

/// <summary>
/// For some products, indicates the suggested retail price in the barcode as a
/// formatted {@link String}.
/// formatted <see cref="System.String"/>.
/// </summary>
SUGGESTED_PRICE,

/// <summary>
/// For some products, the possible country of manufacture as a {@link String} denoting the
/// For some products, the possible country of manufacture as a <see cref="System.String"/> denoting the
/// ISO country code. Some map to multiple possible countries, like "US/CA".
/// </summary>
POSSIBLE_COUNTRY,

/// <summary>
/// For some products, the extension text
/// For some products, the extension text.
/// </summary>
UPC_EAN_EXTENSION,

Expand All @@ -90,7 +102,7 @@ public enum ResultMetadataType
STRUCTURED_APPEND_PARITY,

/// <summary>
/// PDF417-specific metadata
/// PDF417-specific metadata.
/// </summary>
PDF417_EXTRA_METADATA,

Expand Down
18 changes: 17 additions & 1 deletion Source/lib/aztec/AztecDetectorResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

using System;
using ZXing.Common;

namespace ZXing.Aztec.Internal
Expand All @@ -39,6 +40,10 @@ public class AztecDetectorResult : DetectorResult
/// Gets the nb layers.
/// </summary>
public int NbLayers { get; private set; }
/// <summary>
/// Gets the number of corrected errors.
/// </summary>
public int ErrorsCorrected { get; private set; }

/// <summary>
/// Initializes a new instance of the <see cref="AztecDetectorResult"/> class.
Expand All @@ -53,11 +58,22 @@ public AztecDetectorResult(BitMatrix bits,
bool compact,
int nbDatablocks,
int nbLayers)
: base(bits, points)
: this(bits, points, compact, nbDatablocks, nbLayers, 0)
{
}

public AztecDetectorResult(BitMatrix bits,
ResultPoint[] points,
bool compact,
int nbDatablocks,
int nbLayers,
int errorsCorrected)
: base(bits, points)
{
Compact = compact;
NbDatablocks = nbDatablocks;
NbLayers = nbLayers;
ErrorsCorrected = errorsCorrected;
}
}
}
6 changes: 6 additions & 0 deletions Source/lib/aztec/AztecReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,13 @@ public Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hin
Detector detector = new Detector(blackmatrix);
ResultPoint[] points = null;
DecoderResult decoderResult = null;
int errorsCorrected = 0;

var detectorResult = detector.detect(false);
if (detectorResult != null)
{
points = detectorResult.Points;
errorsCorrected = detectorResult.ErrorsCorrected;

decoderResult = new Decoder().decode(detectorResult);
}
Expand All @@ -74,6 +76,8 @@ public Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hin
return null;

points = detectorResult.Points;
errorsCorrected = detectorResult.ErrorsCorrected;

decoderResult = new Decoder().decode(detectorResult);
if (decoderResult == null)
return null;
Expand Down Expand Up @@ -104,6 +108,8 @@ public Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hin
{
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
}
errorsCorrected += decoderResult.ErrorsCorrected;
result.putMetadata(ResultMetadataType.ERRORS_CORRECTED, errorsCorrected);

result.putMetadata(ResultMetadataType.AZTEC_EXTRA_METADATA,
new AztecResultMetadata(detectorResult.Compact, detectorResult.NbDatablocks, detectorResult.NbLayers));
Expand Down
12 changes: 8 additions & 4 deletions Source/lib/aztec/decoder/Decoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public DecoderResult decode(AztecDetectorResult detectorResult)

var rawBytes = convertBoolArrayToByteArray(correctedBits.correctBits);

var decoderResult = new DecoderResult(rawBytes, correctedBits.correctBits.Length, result, null, String.Format("{0}", correctedBits.ecLevel));
var decoderResult = new DecoderResult(rawBytes, correctedBits.correctBits.Length, result, null, String.Format("{0}", correctedBits.ecLevel), null, null, null, correctedBits.errorsCorrected);
return decoderResult;
}

Expand Down Expand Up @@ -316,11 +316,13 @@ private static String getCharacter(String[] table, int code)
internal sealed class CorrectedBitsResult
{
public bool[] correctBits;
public int errorsCorrected;
public int ecLevel;

public CorrectedBitsResult(bool[] correctBits, int ecLevel)
public CorrectedBitsResult(bool[] correctBits, int errorsCorrected, int ecLevel)
{
this.correctBits = correctBits;
this.errorsCorrected = errorsCorrected;
this.ecLevel = ecLevel;
}
}
Expand Down Expand Up @@ -370,8 +372,9 @@ private CorrectedBitsResult correctBits(bool[] rawbits)
dataWords[i] = readCode(rawbits, offset, codewordSize);
}

var errorsCorrected = 0;
var rsDecoder = new ReedSolomonDecoder(gf);
if (!rsDecoder.decode(dataWords, numECCodewords))
if (!rsDecoder.decodeWithECCount(dataWords, numECCodewords, out errorsCorrected))
return null;

// Now perform the unstuffing operation.
Expand Down Expand Up @@ -414,7 +417,8 @@ private CorrectedBitsResult correctBits(bool[] rawbits)
if (index != correctedBits.Length)
return null;

return new CorrectedBitsResult(correctedBits, 100 * (numCodewords - numDataCodewords) / numCodewords);
var ecLevel = 100 * (numCodewords - numDataCodewords) / numCodewords;
return new CorrectedBitsResult(correctedBits, errorsCorrected, ecLevel);
}

/// <summary>
Expand Down
35 changes: 26 additions & 9 deletions Source/lib/aztec/detector/Detector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ public AztecDetectorResult detect(bool isMirror)
}

// 3. Get the size of the matrix and other parameters from the bull's eye
if (!extractParameters(bullsEyeCorners))
var errorsCorrected = 0;
if (!extractParameters(bullsEyeCorners, out errorsCorrected))
{
return null;
}
Expand Down Expand Up @@ -121,9 +122,11 @@ public AztecDetectorResult detect(bool isMirror)
/// Extracts the number of data layers and data blocks from the layer around the bull's eye
/// </summary>
/// <param name="bullsEyeCorners">bullEyeCornerPoints the array of bull's eye corners</param>
/// <param name="errorsCorrected">the number of errors corrected during parameter extraction</param>
/// <returns></returns>
private bool extractParameters(ResultPoint[] bullsEyeCorners)
private bool extractParameters(ResultPoint[] bullsEyeCorners, out int errorsCorrected)
{
errorsCorrected = 0;
if (!isValid(bullsEyeCorners[0]) || !isValid(bullsEyeCorners[1]) ||
!isValid(bullsEyeCorners[2]) || !isValid(bullsEyeCorners[3]))
{
Expand Down Expand Up @@ -171,9 +174,10 @@ private bool extractParameters(ResultPoint[] bullsEyeCorners)

// Corrects parameter data using RS. Returns just the data portion
// without the error correction.
int correctedData = getCorrectedParameterData(parameterData, compact);
if (correctedData < 0)
var correctedParam = getCorrectedParameterData(parameterData, compact);
if (correctedParam == null)
return false;
var correctedData = correctedParam.Data;

if (compact)
{
Expand All @@ -188,6 +192,7 @@ private bool extractParameters(ResultPoint[] bullsEyeCorners)
nbDataBlocks = (correctedData & 0x7FF) + 1;
}

errorsCorrected = correctedParam.ErrorsCorrected;
return true;
}

Expand Down Expand Up @@ -231,8 +236,8 @@ private static int getRotation(int[] sides, int length)
/// </summary>
/// <param name="parameterData">paremeter bits</param>
/// <param name="compact">compact true if this is a compact Aztec code</param>
/// <returns></returns>
private static int getCorrectedParameterData(long parameterData, bool compact)
/// <returns>the corrected parameter</returns>
private static CorrectedParameter getCorrectedParameterData(long parameterData, bool compact)
{
int numCodewords;
int numDataCodewords;
Expand All @@ -257,17 +262,18 @@ private static int getCorrectedParameterData(long parameterData, bool compact)
parameterData >>= 4;
}

var errorsCorrected = 0;
var rsDecoder = new ReedSolomonDecoder(GenericGF.AZTEC_PARAM);
if (!rsDecoder.decode(parameterWords, numECCodewords))
return -1;
if (!rsDecoder.decodeWithECCount(parameterWords, numECCodewords, out errorsCorrected))
return null;

// 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);
}

/// <summary>
Expand Down Expand Up @@ -690,4 +696,15 @@ public override String ToString()
}
}
}
internal sealed class CorrectedParameter
{
public int Data { get; private set; }
public int ErrorsCorrected { get; private set; }

public CorrectedParameter(int data, int errorsCorrected)
{
Data = data;
ErrorsCorrected = errorsCorrected;
}
}
}
36 changes: 27 additions & 9 deletions Source/lib/common/DecoderResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public bool StructuredAppend
/// <param name="byteSegments"></param>
/// <param name="ecLevel"></param>
public DecoderResult(byte[] rawBytes, String text, List<byte[]> byteSegments, String ecLevel)
: this(rawBytes, text, byteSegments, ecLevel, -1, -1, 0)
: this(rawBytes, null, text, byteSegments, ecLevel, null, null, null, null)
{

}
Expand All @@ -113,7 +113,7 @@ public DecoderResult(byte[] rawBytes, String text, List<byte[]> byteSegments, St
/// <param name="ecLevel"></param>
/// <param name="symbologyModifier"></param>
public DecoderResult(byte[] rawBytes, String text, IList<byte[]> byteSegments, String ecLevel, int symbologyModifier)
: this(rawBytes, text, byteSegments, ecLevel, -1, -1, symbologyModifier)
: this(rawBytes, null, text, byteSegments, ecLevel, null, null, symbologyModifier, null)
{
}
/// <summary>
Expand All @@ -131,7 +131,7 @@ public DecoderResult(byte[] rawBytes,
String ecLevel,
int saSequence,
int saParity)
: this(rawBytes, text, byteSegments, ecLevel, saSequence, saParity, 0)
: this(rawBytes, null, text, byteSegments, ecLevel, saSequence, saParity, null, null)
{

}
Expand All @@ -147,7 +147,7 @@ public DecoderResult(byte[] rawBytes,
/// <param name="saParity"></param>
/// <param name="symbologyModifier"></param>
public DecoderResult(byte[] rawBytes, String text, IList<byte[]> byteSegments, String ecLevel, int saSequence, int saParity, int symbologyModifier)
: this(rawBytes, rawBytes == null ? 0 : 8 * rawBytes.Length, text, byteSegments, ecLevel, saSequence, saParity, symbologyModifier)
: this(rawBytes, null, text, byteSegments, ecLevel, saSequence, saParity, symbologyModifier, null)
{
}

Expand All @@ -160,7 +160,7 @@ public DecoderResult(byte[] rawBytes, String text, IList<byte[]> byteSegments, S
/// <param name="byteSegments"></param>
/// <param name="ecLevel"></param>
public DecoderResult(byte[] rawBytes, int numBits, String text, IList<byte[]> byteSegments, String ecLevel)
: this(rawBytes, numBits, text, byteSegments, ecLevel, -1, -1, 0)
: this(rawBytes, numBits, text, byteSegments, ecLevel, null, null, null, null)
{
}

Expand All @@ -176,19 +176,37 @@ public DecoderResult(byte[] rawBytes, int numBits, String text, IList<byte[]> by
/// <param name="saParity"></param>
/// <param name="symbologyModifier"></param>
public DecoderResult(byte[] rawBytes, int numBits, String text, IList<byte[]> byteSegments, String ecLevel, int saSequence, int saParity, int symbologyModifier)
: this(rawBytes, numBits, text, byteSegments, ecLevel, saSequence, saParity, symbologyModifier, null)
{
}

/// <summary>
/// initializing constructor
/// </summary>
/// <param name="rawBytes"></param>
/// <param name="numBits"></param>
/// <param name="text"></param>
/// <param name="byteSegments"></param>
/// <param name="ecLevel"></param>
/// <param name="saSequence"></param>
/// <param name="saParity"></param>
/// <param name="symbologyModifier"></param>
/// <param name="errorsCorrected"></param>
public DecoderResult(byte[] rawBytes, int? numBits, String text, IList<byte[]> byteSegments, String ecLevel, int? saSequence, int? saParity, int? symbologyModifier, int? errorsCorrected)
{
if (rawBytes == null && text == null)
{
throw new ArgumentException();
}
RawBytes = rawBytes;
NumBits = numBits;
NumBits = numBits ?? (rawBytes == null ? 0 : 8 * rawBytes.Length);
Text = text;
ByteSegments = byteSegments;
ECLevel = ecLevel;
StructuredAppendParity = saParity;
StructuredAppendSequenceNumber = saSequence;
SymbologyModifier = symbologyModifier;
StructuredAppendParity = saParity ?? -1;
StructuredAppendSequenceNumber = saSequence ?? -1;
SymbologyModifier = symbologyModifier ?? 0;
ErrorsCorrected = errorsCorrected ?? 0;
}
}
}
Loading

0 comments on commit ec30735

Please sign in to comment.