Data encoding for 2D barcodes

Overview

2D barcodes allow to add description or machine reading tag to any object of real world. The description can be any, but, in most cases, can be split into three different types of encoded data:

  • alphanumeric English characters data with punctuation like ISO/IEC 646;
  • binary of raw bytes stream encoding;
  • Unicode symbols encoding.

2D barcode types, like DataMatrix, Aztec, MaxiCode, PDF417, DotCode, Han Xin code or QR code family, have special embedded modes for alphanumeric English characters encoding with compactification around 4 bits on character for digits and 6 bits on character for English text. The worst situation with QR code family, they use 8 bits on character for lowercase English text.

Every 2D barcode can effectively encode raw bytes stream. Main problem for Aspose.BarCode users was in byte array or stream conversion into CodeText. At this time, problem is fixed and the data can be converted with SetCodeText method.

Unicode encoding in 2D barcodes is slightly tricky. Some of the 2D barcodes like Han Xin code or QR code family have embedded modes which allows to natively encode Chinese or UTF8 characters for Han Xin code or kanji (JIS X 0208) encoding, which supports Japanese, Greek, Cyrillic characters, for QR code family. But in most cases 2D barcodes cannot directly encode Unicode characters and can encode only byte stream.

Of course, you can directly encode Unicode text into byte array with proper Encoding and decode it on reader side. Main problem hire is knowledge about Encoding which was used to encode current text. Some encodings are legacy and can be detected by many readers, like UTF8 encoding, some encodings are only for internal usage. To avoid this problem, Extended Channel Interpretation (ECI) was developed to add special mark of used encoding for current data portions. In this way, the reader has knowledge which encoding should be used to decode current portion of data into Unicode characters.

Aspose.BarCode encoding modes and variables

Aspose.BarCode supports encoding of these three main cases of data encoding. It uses two main variables from groups where each group manage encoding for separate barcode type like: DataMatrix, DotCode, Pdf417, QR, MaxiCode, Aztec, HanXin. These variables are:

  • BarcodeType_EncodeMode, as an example DataMatrixEncodeMode. The variable controls CodeText encoding mode and contains four main modes: Auto, Binary, ECI and Extended.
  • ECIEncoding – controls default characters encoding and Extended Channel Interpretation (ECI) designator which can be used to encode Unicode characters in the desribed upper modes.

BarcodeType_EncodeMode, as an example DataMatrixEncodeMode, contains the following encoding modes:

Mode Description
Auto The mode is suitable for all three cases and allows to encode alphanumeric, binary or Unicode data in the optimized way. Auto mode selects the best embedded encoding method for alphanumeric and binary data. If it finds Unicode symbols, it tries to encode them with Unicode methods, embedded into barcode specification. If it cannot encode Unicode symbols with the embedded methods, it encodes Unicode chain with ECI designator and encoding which is selected in ECIEncoding field and proceeds other parts of CodeText.
Binary The mode works in the same way as Auto but it does not support Unicode symbols. If it finds Unicode in CodeText it throws the Exception. It is recommended to use SetCodeText method to set byte stream. Binary mode selects the best embedded encoding methods for alphanumeric and binary data. TwoDDisplayText property can replace human readable text.
ECI The mode encodes whole provided CodeText with encoding from ECIEncoding field, adds ECI designator and tries to optimize encode byte stream with embedded encoding methods for alphanumeric and binary data.
Extended The mode allows to select manually multiple ECI modes for every chunk of text or encode data in special embedded into barcode symbology modes. The mode should be used only by advanced users who know the barcode specification. To replace human readable text, you should use TwoDDisplayText property.
Special Special modes are specific to symbology embedded encoding modes like C40 for DataMatrixEncodeMode or URI for HanXinEncodeMode. It should be used for special industrial requirements and should not be used for other encodings.

Encode alphanumeric data

You can encode alphanumeric data in Auto encoding mode and set the alphanumeric text to CodeText field. The Aspose.BarCode selects the best encoding method for the data.

using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.DataMatrix, "Aspose 2002-2024"))
{
    gen.Parameters.Barcode.XDimension.Pixels = 8;
    gen.Parameters.Barcode.DataMatrix.DataMatrixEncodeMode = DataMatrixEncodeMode.Auto;
    gen.Save($"{path}Encoding2DAlphanumeric.png", BarCodeImageFormat.Png);

    using (BarCodeReader reader = new BarCodeReader(gen.GenerateBarCodeImage(), DecodeType.DataMatrix))
        foreach (BarCodeResult result in reader.ReadBarCodes())
            Console.WriteLine($"CodeText:{result.CodeText}");
}

Encode binary bytes data

You can encode bytes array in Auto or Binary mode. Binary mode checks provided CodeText on Unicode symbols and throws exception if they are found. SetCodeText function was added to helps automatically convert binary data into CodeText. TwoDDisplayText property helps to replace visible CodeText to human readable text.

Encode byte array

The example shows how to encode binary data from byte array:

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

//encode in DataMatrix code
using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.DataMatrix))
{
    gen.Parameters.Barcode.XDimension.Pixels = 8;
    //set encode mode to binary
    gen.SetCodeText(encodedArr);
    gen.Parameters.Barcode.DataMatrix.DataMatrixEncodeMode = DataMatrixEncodeMode.Binary;
    gen.Parameters.Barcode.CodeTextParameters.TwoDDisplayText = "Binary mode";
    gen.Save($"{path}Encoding2DBinary.png", BarCodeImageFormat.Png);

    //try to recognize
    using (BarCodeReader read = new BarCodeReader(gen.GenerateBarCodeImage(), DecodeType.DataMatrix))
        foreach (BarCodeResult result in read.ReadBarCodes())
            Console.WriteLine("Encoding2DBinary:" + BitConverter.ToString(result.CodeBytes));
}

Encode data from stream

The example shows how to encode binary data from stream:

Stream encodedStream = CreateStream();
encodedStream.Position = 0;
byte[] encodedArr = new byte[encodedStream.Length];
encodedStream.Read(encodedArr, 0, encodedArr.Length);

//encode in DataMatrix code
using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.DataMatrix))
{
    gen.Parameters.Barcode.XDimension.Pixels = 8;
    //set encode mode to binary
    gen.SetCodeText(encodedArr);
    gen.Parameters.Barcode.DataMatrix.DataMatrixEncodeMode = DataMatrixEncodeMode.Binary;
    gen.Parameters.Barcode.CodeTextParameters.TwoDDisplayText = "Binary mode";
    gen.Save($"{path}Encoding2DBinaryStream.png", BarCodeImageFormat.Png);

    //try to recognize
    using (BarCodeReader read = new BarCodeReader(gen.GenerateBarCodeImage(), DecodeType.DataMatrix))
        foreach (BarCodeResult result in read.ReadBarCodes())
            Console.WriteLine("Encoding2DBinaryStream:" + BitConverter.ToString(result.CodeBytes));
}

Encode Unicode data

You can encode Unicode CodeText in 2D barcodes in three different ways:

  • Auto mode with ECIEncoding splits CodeText on Unicode and non-Unicode sequences and encode Unicode sequences with encoding from ECIEncoding property and adds ECI designator for the current chunk of data. In most cases, this is in the best way for encoding any text data.
  • ECI with ECIEncoding unconditionally converts full CodeText into byte array with encoding from ECIEncoding and adds ECI designator.
  • Manual encoding of provided text converts text into byte stream without ECI designator by SetCodeText function. Some encoding like UTF8 could be automatically recognized on reader side, but in most cases the reader does not know text encoding and can recognize barcode data as trash. TwoDDisplayText should be used to change human readable text.

Encode Unicode data in Auto mode

The example shows how to encode Unicode data in Auto mode with ECIEncoding.

using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.DataMatrix, "Aspose常に先を行"))
{
    gen.Parameters.Barcode.XDimension.Pixels = 8;
    gen.Parameters.Barcode.DataMatrix.DataMatrixEncodeMode = DataMatrixEncodeMode.Auto;
    gen.Parameters.Barcode.DataMatrix.ECIEncoding = ECIEncodings.UTF8;
    gen.Save($"{path}Encoding2DUnicodeAuto.png", BarCodeImageFormat.Png);

    using (BarCodeReader reader = new BarCodeReader(gen.GenerateBarCodeImage(), DecodeType.DataMatrix))
        foreach (BarCodeResult result in reader.ReadBarCodes())
            Console.WriteLine($"CodeText:{result.CodeText}");
}

Encode Unicode data in ECI mode

The example shows how to encode Unicode data in ECI mode with ECIEncoding.

using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.DataMatrix, "Aspose常に先を行"))
{
    gen.Parameters.Barcode.XDimension.Pixels = 8;
    gen.Parameters.Barcode.DataMatrix.DataMatrixEncodeMode = DataMatrixEncodeMode.ECI;
    gen.Parameters.Barcode.DataMatrix.ECIEncoding = ECIEncodings.UTF8;
    gen.Save($"{path}Encoding2DUnicodeECI.png", BarCodeImageFormat.Png);

    using (BarCodeReader reader = new BarCodeReader(gen.GenerateBarCodeImage(), DecodeType.DataMatrix))
        foreach (BarCodeResult result in reader.ReadBarCodes())
            Console.WriteLine($"CodeText:{result.CodeText}");
}

Encode Unicode data manually in UTF8

The example shows how to encode Unicode data manually in QR code with automatically detected UTF8 encoding. However, without ECI designator, the barcode data sometimes can be decoded incorrectly.

using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.QR))
{
    gen.Parameters.Barcode.XDimension.Pixels = 8;
    gen.Parameters.Barcode.QR.QrEncodeMode = QREncodeMode.Auto;
    gen.SetCodeText("Aspose常に先を行", Encoding.UTF8);
    gen.Parameters.Barcode.CodeTextParameters.TwoDDisplayText = "Aspose常に先を行";
    gen.Save($"{path}Encoding2DUnicodeUTF8.png", BarCodeImageFormat.Png);

    using (BarCodeReader reader = new BarCodeReader(gen.GenerateBarCodeImage(), DecodeType.QR))
        foreach (BarCodeResult result in reader.ReadBarCodes())
            Console.WriteLine($"CodeText:{result.CodeText}");
}

Encode Unicode data manually in custom encoding

The example shows how to encode Unicode data manually in QR code with undetectable Windows-1253 encoding with manual decoding on reader side.

using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.QR))
{
    gen.Parameters.Barcode.XDimension.Pixels = 8;
    gen.Parameters.Barcode.QR.QrEncodeMode = QREncodeMode.Auto;
    gen.SetCodeText("AsposeΣΑΩ", Encoding.GetEncoding(1253));
    gen.Parameters.Barcode.CodeTextParameters.TwoDDisplayText = "AsposeΣΑΩ";
    gen.Save($"{path}Encoding2DUnicodeCustom.png", BarCodeImageFormat.Png);

    using (BarCodeReader reader = new BarCodeReader(gen.GenerateBarCodeImage(), DecodeType.QR))
        foreach (BarCodeResult result in reader.ReadBarCodes())
        {
            Console.WriteLine($"Undecoded CodeText:{result.CodeText}");
            Console.WriteLine($"CodeText:{result.GetCodeText(Encoding.GetEncoding(1253))}");
        }
}

Encode data in Extended mode

In this mode the data can be encoded in manual mode where special encoded modes can be set to different chunks of CodeText or data can be encoded on multiple languages with different encodings. Aspose.BarCode provides special helpers like QrExtCodetextBuilder. Also, you can change human readable description with TwoDDisplayText.

//generate extended codetext
QrExtCodetextBuilder textBuilder = new QrExtCodetextBuilder();
textBuilder.AddECICodetext(ECIEncodings.Win1251, "Слово");
textBuilder.AddECICodetext(ECIEncodings.UTF8, "常に先");
textBuilder.AddECICodetext(ECIEncodings.UTF16BE, "を行く");
textBuilder.AddPlainCodetext(@"Aspose");

using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.QR, textBuilder.GetExtendedCodetext()))
{
    gen.Parameters.Barcode.XDimension.Pixels = 8;
    gen.Parameters.Barcode.QR.QrEncodeMode = QREncodeMode.Extended;
    gen.Parameters.Barcode.CodeTextParameters.TwoDDisplayText = "Extended mode";
    gen.Save($"{path}Encoding2DExtended.png", BarCodeImageFormat.Png);

    using (BarCodeReader reader = new BarCodeReader(gen.GenerateBarCodeImage(), DecodeType.QR))
        foreach (BarCodeResult result in reader.ReadBarCodes())
            Console.WriteLine($"CodeText:{result.CodeText}");
}

Encode GS1 data

To encode GS1 data you should use GS1 versions of the 2D barcode type and set GS1 text in special format to the CodeText field. You do not need other parameters to set.

GS1 CodeText format has the following structure:

"(Application_Identifier_1)Application_Data(Application_Identifier_2)Application_Data"

As an example, we can encode the following value: “(01)12345678901231(21)ASPOSE(30)9876”.

using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.GS1QR, "(01)12345678901231(21)ASPOSE(30)9876"))
{
    gen.Parameters.Barcode.XDimension.Pixels = 8;
    gen.Save($"{path}Encoding2DGS1.png", BarCodeImageFormat.Png);

    using (BarCodeReader reader = new BarCodeReader(gen.GenerateBarCodeImage(), DecodeType.GS1QR))
        foreach (BarCodeResult result in reader.ReadBarCodes())
            Console.WriteLine($"CodeText:{result.CodeText}");
}

Encode data in Special modes

Sometimes we require to encode data in special industrial formats like C40 encoding for DataMatrix . It can encode alphanumeric data similar to ISO/IEC 646, where it spends ~5 bits on capital letter and ~11 bit on lowercase letter and punctuation.

using (BarcodeGenerator gen = new BarcodeGenerator(EncodeTypes.DataMatrix, "ASPOSE.BARCODE"))
{
    gen.Parameters.Barcode.XDimension.Pixels = 8;
    gen.Parameters.Barcode.DataMatrix.DataMatrixEncodeMode = DataMatrixEncodeMode.C40;
    gen.Save($"{path}Encoding2DSpecial.png", BarCodeImageFormat.Png);

    using (BarCodeReader reader = new BarCodeReader(gen.GenerateBarCodeImage(), DecodeType.DataMatrix))
        foreach (BarCodeResult result in reader.ReadBarCodes())
            Console.WriteLine($"CodeText:{result.CodeText}");
}