BarcodeDecoder Class

Reads linear barcodes from their modules or from scan lines: Code 39, Code 93, Code 128, GS1-128, EAN-8, EAN-13, UPC-A, UPC-E (with their add-ons), Codabar, ITF, and GS1 DataBar (Omnidirectional, Stacked, Stacked Omnidirectional, Limited, Expanded and Expanded Stacked).

public static class BarcodeDecoder

Remarks

The decoder works on the widths of the bars and spaces, not on pixels. To read the barcodes of an image, use the ReadBarcodes methods of the Meziantou.Framework.Imaging.Barcodes package, which scan its pixels.

Methods

NameDescription
Decode(Barcode)Reads a barcode.
Decode(bool[,])Reads a barcode from its modules.
DecodeScanLines(IReadOnlyList<int[]>)Reads the linear barcodes that scan lines cross.
TryDecode(bool[,], BarcodeDecodeResult?)Tries to read a barcode from its modules.

Decode overloads

Decode(Barcode)

BarcodeDecoder.cs

Reads a barcode.

public static BarcodeDecodeResult Decode(Barcode barcode)
Parameters
barcode Barcode
The barcode.
Returns

BarcodeDecodeResult The barcode that was read.

Exceptions
ArgumentNullException
barcode is null.
Example
var barcode = Barcode.CreateCode128("SKU-123456");

var result = BarcodeDecoder.Decode(barcode);

Assert.Equal((BarcodeType.Code128, "SKU-123456"), (result.Type, result.Text));

Decode(bool[,])

BarcodeDecoder.cs

Reads a barcode from its modules.

public static BarcodeDecodeResult Decode(bool[,] modules)
Parameters
modules bool[,]
The modules, true for dark, indexed by row then column, without quiet zone: one row for a linear barcode, the rows of a stacked GS1 DataBar symbol (separators included) for a stacked one.
Returns

BarcodeDecodeResult The barcode that was read.

Exceptions
ArgumentNullException
modules is null.
FormatException
The modules are not a barcode that the decoder can read.

DecodeScanLines(IReadOnlyList<int[]>)

BarcodeDecoder.cs

Reads the linear barcodes that scan lines cross.

public static IReadOnlyList<BarcodeDecodeResult> DecodeScanLines(IReadOnlyList<int[]> scanLines)

Parameters

scanLines IReadOnlyList<int[]>
The scan lines: each is the widths of its alternating light and dark runs, in any unit (pixels), starting with a light run (which can be 0 wide). The lines of a stacked GS1 DataBar symbol are in order from the top.

Returns

IReadOnlyList<BarcodeDecodeResult> The barcodes found, each once even when several lines cross it.

Exceptions

ArgumentNullException
scanLines is null or contains null.

Remarks

A barcode can be read from either end, and must have its quiet zones. A symbology without check character, such as ITF or Codabar, can be misread from a damaged line: require that several lines agree (BarcodeDecodeResult.FirstScanLine and BarcodeDecodeResult.LastScanLine).

Example

// A scan line: the widths of its light and dark runs, starting with a light run, here 3 pixels per module
var barcode = Barcode.CreateEan13("590123412345");
var runs = new List<int> { 30 };
for (var column = 0; column < barcode.Width; column++)
{
    if (barcode[0, column] != (runs.Count % 2 == 0))
    {
        runs.Add(0);
    }

    runs[^1] += 3;
}

// The quiet zone after the last bar
runs.Add(30);

var results = BarcodeDecoder.DecodeScanLines([runs.ToArray()]);

var result = Assert.Single(results);
Assert.Equal((BarcodeType.Ean13, "5901234123457"), (result.Type, result.Text));
Assert.Equal((30, 30 + (95 * 3)), (result.Start, result.End));

TryDecode(bool[,], BarcodeDecodeResult?)

BarcodeDecoder.cs

Tries to read a barcode from its modules.

public static bool TryDecode(bool[,] modules, out BarcodeDecodeResult? result)

Parameters

modules bool[,]
The modules, true for dark, indexed by row then column, without quiet zone.
result BarcodeDecodeResult?
When this method returns true, the barcode that was read.

Returns

bool true if a barcode could be read; otherwise, false.

Exceptions

ArgumentNullException
modules is null.