Read Barcode Properties and Metadata

Overview

As a result of barcode reading, Aspose.BarCode for .NET allows not only decoding the main data stored in a barcode, but also getting information about its technical parameters, such as type, placement region, orientation angle, and metadata. The library saves this information in a specific object type called BarCodeResult so that each instance of this class corresponds to one processed barcode. Further in this article, it is explained how to get the required information about barcode properties using the functionality of Aspose.BarCode for .NET.

Getting Barcode Type and Encoded Data

To get the data encoded in a barcode and identify its type, class BarCodeResult provides the two most important fields, CodeText and CodeType, respectively. The other parameter CodeTypeName represents the text name of a barcode symbology.

The following code sample explains how to get the data encoded in a barcode and its type for the sample barcode image provided below (in this case, a QR Code label).

//create barcode
using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.QR, "Åspóse.Barcóde©"))
{
    gen.Parameters.Barcode.XDimension.Pixels = 4;
    gen.Save($"{path}QRCodetext.png", BarCodeImageFormat.Png);
}

//recognize image
Console.WriteLine("ReadExtCodetext:");
using (BarCodeReader read = new BarCodeReader($"{path}QRCodetext.png", DecodeType.QR))
{
    foreach (BarCodeResult result in read.ReadBarCodes())
    {
        Console.WriteLine($"CodeText:{result.CodeText}");
        Console.WriteLine($"CodeType:{result.CodeType.ToString()}");
        Console.WriteLine($"CodeTypeName:{result.CodeTypeName}");
    }
}

Reading Barcode Data as Byte Stream

In cases when it is necessary to get the data encoded in a barcode in the form of a byte stream, it can be read from the specific field of class BarCodeResult that is called CodeBytes.

The following code snippet illustrates how to obtain barcode data as a stream of bytes for the sample PDF417 barcode image provided below.

byte[] encodedArr = { 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9 };

//encode array to string
StringBuilder strBld = new StringBuilder(encodedArr.Length);
foreach (byte bval in encodedArr)
    strBld.Append((char)bval);

//encode array of bytes
using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.Pdf417, strBld.ToString()))
{
    gen.Parameters.Barcode.XDimension.Pixels = 2;
    gen.Parameters.Barcode.Pdf417.Pdf417CompactionMode = Pdf417CompactionMode.Binary;
    gen.Parameters.Barcode.Pdf417.Columns = 2;
    gen.Parameters.Barcode.CodeTextParameters.TwoDDisplayText = "Bytes mode";
    gen.Save($"{path}ExtCodeBytes.png", BarCodeImageFormat.Png);
}

//attempt to recognize array of bytes
Console.WriteLine("ReadExtCodeBytes:");
using (BarCodeReader read = new BarCodeReader($"{path}ExtCodeBytes.png", DecodeType.Pdf417))
    foreach (BarCodeResult result in read.ReadBarCodes())
    {
        Console.WriteLine($"CodeTypeName:{result.CodeTypeName}");
        Console.WriteLine($"CodeBytes:{BitConverter.ToString(result.CodeBytes)}");
    }

Decoding Barcode Text in Unicode

In cases when the barcode data is encoded using a particular Unicode encoding, it can be read by calling the GetCodeText method and specifying the required encoding.

The following code snippet shows how to get the data encoded in UTF8 as a result of reading a sample DataMatrix barcode given below.

//create encoded Unicode codetext
using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.DataMatrix, "Aspose常に先を行く"))
{
    gen.Parameters.Barcode.XDimension.Pixels = 4;
    gen.Parameters.Barcode.DataMatrix.CodeTextEncoding = Encoding.UTF8;
    gen.Save($"{path}ExtUnicodeCodeText.png", BarCodeImageFormat.Png);
}

//try to recognize Unicode codetext
Console.WriteLine("ReadExtUnicodeCodeText:");
using (BarCodeReader read = new BarCodeReader($"{path}ExtUnicodeCodeText.png", DecodeType.DataMatrix))
    foreach (BarCodeResult result in read.ReadBarCodes())
    {
        Console.WriteLine($"CodeTypeName:{result.CodeTypeName}");
        Console.WriteLine($"GetCodeText:{result.GetCodeText(Encoding.UTF8)}");
    }

Recognition Quality Check

In many cases, it is necessary to estimate whether the barcode has been recognized accurately. In Aspose.BarCode for .NET, this can be done using two specific properties of class BarCodeResult: Confidence and ReadingQuality.
As a result of barcode reading, the Confidence property returns a value from the BarCodeConfidence enumeration that corresponds to the recognition confidence level. Possible values of the BarCodeConfidence enumeration (None, Moderate, and Strong) are explained in the table below. The ReadingQuality parameter returns the estimate of recognition quality according to the identified confidence level: 0 for None; from 1 to 99; 100 for Strong.

Confidence Level Reading Quality Value Description
None 0 If the confidence level returns None, it usually means that the source barcode is incorrect and its input data has been decoded with errors. However, it is still possible to get its type and place orientation in the source image, as well as partially decode inputted data
Moderate 80 Is returned for 1D and postal barcodes with weak or missing checksum settings. In this case, it is required to analyze the value of ReadingQuality; however, even in the case of high values (close to 80), the absolute correctness of barcode recognition is not guaranteed
Strong 100 Is returned for all 2D barcode types with Reed-Solomon error correction in case the quality setting has not been set to QualitySettings.AllowIncorrectBarcodes. When this confidence level is returned, it means that barcode text has been decoded correctly, and the recognition process has been completed successfully

The following code snippet explains how to get the recognition quality estimate for a sample barcode image.

//recognize image
Console.WriteLine("ReadExtQuality:");
using (BarCodeReader read = new BarCodeReader($"{path}qr_code128.png", DecodeType.QR, DecodeType.Code128))
{
    foreach (BarCodeResult result in read.ReadBarCodes())
    {
        Console.WriteLine($"CodeType:{result.CodeTypeName}");
        Console.WriteLine($"CodeText:{result.CodeText}");
        Console.WriteLine($"Confidence:{result.Confidence.ToString()}");
        Console.WriteLine($"ReadingQuality:{result.ReadingQuality.ToString()}");
    }
}

Getting Barcode Placement Region and Orientation Angle

In some cases, developers may need to get information about the placement region of a source barcode and its orientation angle. To enable such a possibility, Aspose.BarCode for .NET provides a group of properties called RegionParameters that stores the following information:

  • Quadrangle – a quadrangle object that bounds a barcode
  • Rectangle - a rectangle object that bounds a barcode
  • Points – an array of points constituting a barcode
  • Angle – an orientation angle in degrees

The following code sample illustrates how to get the information about barcode placement region and orientation angle for the example barcode image provided below.

//recognize image
Console.WriteLine("ReadExtRegion:");
using (BarCodeReader read = new BarCodeReader($"{path}qr_code128.png", DecodeType.QR, DecodeType.Code128))
{
    foreach (BarCodeResult result in read.ReadBarCodes())
    {
        Console.WriteLine($"CodeType:{result.CodeTypeName}");
        Console.WriteLine($"CodeText:{result.CodeText}");
        Console.WriteLine($"Quadrangle:{result.Region.Quadrangle.ToString()}");
        Console.WriteLine($"Angle:{result.Region.Angle.ToString()}");
        Console.WriteLine($"Rectangle:{result.Region.Rectangle.ToString()}");
        string ptStr = "";
        foreach (Point pt in result.Region.Points)
            ptStr += pt.ToString() + "";
        Console.WriteLine($"Points:{ptStr}");
    }
}

Getting Barcode Metadata

Reading Metadata for Macro PDF417 and Macro PDF417 Standards

To read metadata from PDF417 barcodes, Aspose.BarCode for .NET provides a group of properties called Pdf417ExtendedParameters that includes various fields as listed in the table below.

PDF417 Metadata Field Description
Pdf417MacroFileID Unique identifier of a barcode series or PDF417 file
Pdf417MacroSegmentID Current segment identifier
Pdf417MacroSegmentsCount Number of barcodes in a series
Pdf417MacroFileName Name of a file
Pdf417MacroChecksum Checksum of a file that is calculated using CCITT-16 polynomial
Pdf417MacroFileSize Total size of bytes in a series
Pdf417MacroTimeStamp Time of creating/sending the file
Pdf417MacroAddressee Address of the file sender
Pdf417MacroSender Name of the file sender

The following code snippet shows how to get metadata from a sample PDF417 barcode provided below.

//generate Macro PDF417 with metadata
using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.MacroPdf417, "Åspóse.Barcóde©"))
{
    gen.Parameters.Barcode.XDimension.Pixels = 2;
    gen.Parameters.Barcode.Pdf417.Columns = 5;
    gen.Parameters.Barcode.Pdf417.Pdf417MacroFileID = 12345678;
    gen.Parameters.Barcode.Pdf417.Pdf417MacroSegmentID = 12;
    gen.Parameters.Barcode.Pdf417.Pdf417MacroSegmentsCount = 20;
    gen.Parameters.Barcode.Pdf417.Pdf417MacroFileName = "file01";
    //checksumm must be calculated in CCITT-16 / CRC-16-CCITT encoding
    //https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Polynomial_representations_of_cyclic_redundancy_checks
    //for the example we use random number
    gen.Parameters.Barcode.Pdf417.Pdf417MacroChecksum = 1234;
    gen.Parameters.Barcode.Pdf417.Pdf417MacroFileSize = 400000;
    gen.Parameters.Barcode.Pdf417.Pdf417MacroTimeStamp = new DateTime(2019, 11, 1);
    gen.Parameters.Barcode.Pdf417.Pdf417MacroAddressee = "street";
    gen.Parameters.Barcode.Pdf417.Pdf417MacroSender = "aspose";
    gen.Save($"{path}ExtPDF417Meta.png", BarCodeImageFormat.Png);
}

//attempt to recognize PDF417 metadata
Console.WriteLine("ReadExtPDF417Meta:");
using (BarCodeReader read = new BarCodeReader($"{path}ExtPDF417Meta.png", DecodeType.MacroPdf417))
{
    foreach (BarCodeResult result in read.ReadBarCodes())
    {
        Console.WriteLine($"CodeType:{result.CodeTypeName}");
        Console.WriteLine($"CodeText:{result.CodeText}");
        Console.WriteLine($"Pdf417MacroFileID:{result.Extended.Pdf417.MacroPdf417FileID}");
        Console.WriteLine($"Pdf417MacroSegmentID:{result.Extended.Pdf417.MacroPdf417SegmentID.ToString()}");
        Console.WriteLine($"Pdf417MacroSegmentsCount:{result.Extended.Pdf417.MacroPdf417SegmentsCount.ToString()}");
        Console.WriteLine($"Pdf417MacroFileName:{result.Extended.Pdf417.MacroPdf417FileName}");
        Console.WriteLine($"Pdf417MacroChecksum:{result.Extended.Pdf417.MacroPdf417Checksum.ToString()}");
        Console.WriteLine($"Pdf417MacroFileSize:{result.Extended.Pdf417.MacroPdf417FileSize.ToString()}");
        Console.WriteLine($"Pdf417MacroTimeStamp:{result.Extended.Pdf417.MacroPdf417TimeStamp.ToString()}");
        Console.WriteLine($"Pdf417MacroAddressee:{result.Extended.Pdf417.MacroPdf417Addressee}");
        Console.WriteLine($"Pdf417MacroSender:{result.Extended.Pdf417.MacroPdf417Sender}");
    }
}

Reading Metadata from QR Code with Structured Append

To read metadata from QR Code barcodes, it is necessary to use a group of properties called QrExtendedParameters. These properties enable reading the information about QR Code barcodes with structured append that allows combining several QR Code labels into one. This information includes the following fields:

The code snippet given below explains how to get metadata for a sample QR Code image with structured append.

//generate QR with metadata
using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.QR, "Åspóse.Barcóde©"))
{
    gen.Parameters.Barcode.XDimension.Pixels = 4;
    gen.Parameters.Barcode.QR.StructuredAppend.TotalCount = 3;
    gen.Parameters.Barcode.QR.StructuredAppend.SequenceIndicator = 1;
    gen.Parameters.Barcode.QR.StructuredAppend.ParityByte = 123;
    gen.Save($"{path}ExtQRMeta.png", BarCodeImageFormat.Png);
}

//attempt to recognize QR metadata
Console.WriteLine("ReadExtQRMeta:");
using (BarCodeReader read = new BarCodeReader($"{path}ExtQRMeta.png", DecodeType.QR))
{
    foreach (BarCodeResult result in read.ReadBarCodes())
    {
        Console.WriteLine($"CodeType:{result.CodeTypeName}");
        Console.WriteLine($"CodeText:{result.CodeText}");
        Console.WriteLine($"BarCodesQuantity:{result.Extended.QR.QRStructuredAppendModeBarCodesQuantity}");
        Console.WriteLine($"BarCodeIndex:{result.Extended.QR.QRStructuredAppendModeBarCodeIndex}");
        Console.WriteLine($"ParityData:{result.Extended.QR.QRStructuredAppendModeParityData}");
    }
}

Reading Metadata from DataBar Barcodes with 2D Components

To read metadata from DataBar barcodes with 2D components, the library provides a group of properties called DataBarExtendedParameters. This property group includes a special parameter called Is2DCompositeComponent that is used to enable or disable a 2D component in DataBar barcodes.

The following code sample illustrates how to get metadata from a sample DataBar barcode with a 2D component (shown below).

//generate Databar with metadata
using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.DatabarExpandedStacked, "ASPOSE.BARCODE"))
{
    gen.Parameters.Barcode.XDimension.Pixels = 2;
    gen.Parameters.Barcode.DataBar.Rows = 2;
    gen.Parameters.Barcode.DataBar.Is2DCompositeComponent = true;
    gen.Save($"{path}ExtDataBarMeta.png", BarCodeImageFormat.Png);
}

//attempt to recognize Databar metadata
Console.WriteLine("ReadExtDataBarMeta:");
using (BarCodeReader read = new BarCodeReader($"{path}ExtDataBarMeta.png", DecodeType.DatabarExpanded, DecodeType.DatabarExpandedStacked))
{
    foreach (BarCodeResult result in read.ReadBarCodes())
    {
        Console.WriteLine($"CodeType:{result.CodeTypeName}");
        Console.WriteLine($"CodeText:{result.CodeText}");
        Console.WriteLine($"Is2DCompositeComponent:{result.Extended.DataBar.Is2DCompositeComponent}");
    }
}

Reading Metadata for 1D Symbologies

For some 1D symbologies, such as, for example, EAN 13, it is possible to separate the decoded barcode data into barcode information itself and the checksum value. This can be done using a group of properties called OneDExtendedParameters that provides the following fields: Value that stores the decoded 1D barcode text and CheckSum that contains the result of checksum calculation.

//generate EAN 13 with metadata
using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.EAN13, "1234567890128"))
{
    gen.Parameters.Barcode.XDimension.Pixels = 2;
    gen.Save($"{path}EAN13.png", BarCodeImageFormat.Png);
}

//attempt to recognize EAN 13 with the value and checksum
Console.WriteLine("ReadExtOneD:");
using (BarCodeReader read = new BarCodeReader($"{path}EAN13.png", DecodeType.EAN13))
{
    foreach (BarCodeResult result in read.ReadBarCodes())
    {
        Console.WriteLine($"CodeType:{result.CodeTypeName}");
        Console.WriteLine($"CodeText:{result.CodeText}");
        Console.WriteLine($"Value:{result.Extended.OneD.Value}");
        Console.WriteLine($"CheckSum:{result.Extended.OneD.CheckSum}");
    }
}

Getting Raw Data from Code 128 Barcodes

The input data in Code 128 barcodes can be encoded in three different modes: A, B, or C. The library provides a group of properties called Code128ExtendedParameters with a special field called Code128DataPortions that stores decoded parts of the input data together with information about their encoding mode.

//generate Code128 with metadata
using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.Code128, "Aspose1234"))
{
    gen.Parameters.Barcode.XDimension.Pixels = 2;
    gen.Save($"{path}Code128.png", BarCodeImageFormat.Png);
}

//try to recognize Code128 with data portions
Console.WriteLine("ReadExtCode128Meta:");
using (BarCodeReader read = new BarCodeReader($"{path}Code128.png", DecodeType.Code128))
{
    foreach (BarCodeResult result in read.ReadBarCodes())
    {
        Console.WriteLine($"CodeType:{result.CodeTypeName}");
        Console.WriteLine($"CodeText:{result.CodeText}");
        string data = "";
        foreach (Code128DataPortion portion in result.Extended.Code128.Code128DataPortions)
            data += "Type{" + portion.Code128SubType.ToString() +"}, Data{" + portion.Data + "};";
        Console.WriteLine($"Code128DataPortions:{data}");
    }
}