VintaSoft Barcode .NET SDK v9.2
How to use Structure Append feature for distributing data message across several 2D barcodes?

Structure Append feature allows to distribute data message across several 2D barcodes if data message cannot be stored in a single 2D barcode. Up to 16 (DataMatrix, QR) or 26 (Aztec) symbols may be appended in a structured format.

Example: Here is an example that shows how to use Structure Append feature for distributing data message across several 2D barcodes.

Imports System.Drawing
Imports System.Text
Imports Vintasoft.Barcode
Imports Vintasoft.Barcode.BarcodeInfo

''' <summary>
''' Test that shows how to use Structured Append feature for distributing data message across
''' several 2D barcodes.
''' </summary>
Class StructureAppendExample

        ''' <summary>
        ''' Runs the test.
        ''' </summary>
        Public Shared Sub Test()
                Dim barcodeType__1 As BarcodeType = BarcodeType.DataMatrix

                Dim symbolsCount As Integer = 5

                Dim symbolsValue As String = "In order to fit a non-square area or to handle larger messages than are practical " & "in a single symbol, a data message can be distributed across several symbols. " & "Aztec, Code 16K, DataMatrix, MaxiCode, QR Code, PDF417, Micro PDF417 " & "symbols may be appended in a structured format."

                ' split data and generate barcodes
                Dim barcodeImages As Image() = GenerateBarcodes(barcodeType__1, symbolsValue, symbolsCount)

                ' resort barcode images
                Array.Reverse(barcodeImages)
                Array.Reverse(barcodeImages, 0, barcodeImages.Length \ 2)

                ' read barcodes and merge data value
                Dim readValue As String = ReadBarcodeValue(barcodeImages, barcodeType__1)

                If readValue = symbolsValue Then
                        Console.WriteLine("Success")
                Else
                        Throw New ApplicationException()
                End If
        End Sub

        ''' <summary>
        ''' Splits value and generates symbolCount barcodes using Structured Append.
        ''' </summary>
        Public Shared Function GenerateBarcodes(barcodeType__1 As BarcodeType, value As String, symbolCount As Integer) As Image()
                ' create an image array
                Dim result As Image() = New Image(symbolCount - 1) {}

                ' create the barcode writer
                Dim writer As New BarcodeWriter()

                ' specify that writer must generate barcode of specified type
                writer.Settings.Barcode = barcodeType__1

                ' create parity data for a QR barcode value
                Dim parityData As Byte = 0
                If barcodeType__1 = BarcodeType.QR Then
                        parityData = QRStructuredAppendCharacter.CaluculateParityData(value)
                End If

                ' generate symbols(barcodes)
                Dim fragmentLength As Integer = value.Length \ symbolCount
                For i As Integer = 0 To symbolCount - 1
                        ' create Structured Append character

                        Dim structureAppendCharacter As StructuredAppendCharacter
                        Select Case barcodeType__1
                                Case BarcodeType.Aztec
                                        structureAppendCharacter = New AztecStructuredAppendCharacter(i + 1, symbolCount, "")
                                        Exit Select

                                Case BarcodeType.DataMatrix
                                        structureAppendCharacter = New DataMatrixStructuredAppendCharacter(i + 1, symbolCount, 0)
                                        Exit Select

                                Case BarcodeType.QR
                                        structureAppendCharacter = New QRStructuredAppendCharacter(i + 1, symbolCount, parityData)
                                        Exit Select

                                Case BarcodeType.Code16K
                                        structureAppendCharacter = New StructuredAppendCharacter(i + 1, symbolCount)
                                        writer.Settings.Height = 200
                                        Exit Select

                                Case BarcodeType.MaxiCode
                                        structureAppendCharacter = New StructuredAppendCharacter(i + 1, symbolCount)
                                        Exit Select

                                Case BarcodeType.MicroPDF417
                                        structureAppendCharacter = New PDF417StructuredAppendCharacter(i + 1, symbolCount, "123")
                                        Exit Select

                                Case BarcodeType.PDF417
                                        structureAppendCharacter = New PDF417StructuredAppendCharacter(i + 1, symbolCount, "123")
                                        Exit Select
                                Case Else

                                        Throw New NotSupportedException()
                        End Select

                        ' create symbol data

                        Dim symbolTextData As String
                        If i = symbolCount - 1 Then
                                symbolTextData = value.Substring(i * fragmentLength)
                        Else
                                symbolTextData = value.Substring(i * fragmentLength, fragmentLength)
                        End If

                        Dim symbolData As New TextValueItem(symbolTextData)

                        ' set the barcode value items
                        writer.Settings.ValueItems = New ValueItemBase() {structureAppendCharacter, symbolData}

                        ' create image with barcode
                        result(i) = writer.GetBarcodeAsBitmap()
                Next

                Return result
        End Function

        ''' <summary>
        ''' Reads barcodes and merges the results into a single value.
        ''' </summary>
        Private Shared Function ReadBarcodeValue(barcodeImages As Image(), barcodeType As BarcodeType) As String
                ' create the barcode reader
                Using reader As New BarcodeReader()
                        ' specify that reader must search for barcodes of specified type
                        reader.Settings.ScanBarcodeTypes = barcodeType

                        ' barcode reading results
                        Dim readingResults As IBarcodeInfo() = New IBarcodeInfo(barcodeImages.Length - 1) {}
                        ' read barcodes
                        For i As Integer = 0 To barcodeImages.Length - 1
                                ' read barcode from image
                                readingResults(i) = reader.ReadBarcodes(barcodeImages(i))(0)

                                ' dispose image
                                barcodeImages(i).Dispose()
                        Next

                        ' determine symbol count
                        Dim symbolsCount As Integer = 0
                        For i As Integer = 0 To readingResults.Length - 1
                                If TypeOf readingResults(i).ValueItems(0) Is StructuredAppendCharacter Then
                                        symbolsCount = DirectCast(readingResults(i).ValueItems(0), StructuredAppendCharacter).SymbolCount
                                        Exit For
                                End If
                        Next
                        If symbolsCount = 0 Then
                                Throw New ApplicationException("No Structured Append symbols.")
                        End If

                        ' create array of string
                        Dim resultValues As String() = New String(symbolsCount - 1) {}
                        ' fill resultValues
                        For i As Integer = 0 To readingResults.Length - 1
                                If TypeOf readingResults(i).ValueItems(0) Is StructuredAppendCharacter Then
                                        Dim structureAppendCharacter As StructuredAppendCharacter = DirectCast(readingResults(i).ValueItems(0), StructuredAppendCharacter)
                                        If structureAppendCharacter.SymbolCount = symbolsCount Then
                                                readingResults(i).ShowNonDataFlagsInValue = False
                                                resultValues(structureAppendCharacter.SymbolPosition - 1) = readingResults(i).Value
                                        End If
                                End If
                        Next

                        ' build result string
                        Dim result As New StringBuilder()
                        For i As Integer = 0 To resultValues.Length - 1
                                If resultValues(i) IsNot Nothing Then
                                        result.Append(resultValues(i))
                                Else
                                        Throw New ApplicationException(String.Format("missing symbol at position {0}", i + 1))
                                End If
                        Next

                        Return result.ToString()
                End Using
        End Function

End Class
              
using System;
using System.Drawing;
using System.Text;
using Vintasoft.Barcode;
using Vintasoft.Barcode.BarcodeInfo;

/// <summary>
/// Test that shows how to use Structured Append feature for distributing data message across
/// several 2D barcodes.
/// </summary>
class StructureAppendExample
{

    /// <summary>
    /// Runs the test.
    /// </summary>
    public static void Test()
    {
        BarcodeType barcodeType = BarcodeType.DataMatrix;

        int symbolsCount = 5;

        string symbolsValue =
            "In order to fit a non-square area or to handle larger messages than are practical " +
            "in a single symbol, a data message can be distributed across several symbols. " +
            "Aztec, Code 16K, DataMatrix, MaxiCode, QR Code, PDF417, Micro PDF417 "+
            "symbols may be appended in a structured format.";

        // split data and generate barcodes
        Image[] barcodeImages = GenerateBarcodes(barcodeType, symbolsValue, symbolsCount);

        // resort barcode images
        Array.Reverse(barcodeImages);
        Array.Reverse(barcodeImages, 0, barcodeImages.Length / 2);

        // read barcodes and merge data value
        string readValue = ReadBarcodeValue(barcodeImages, barcodeType);

        if (readValue == symbolsValue)
            Console.WriteLine("Success");
        else
            throw new ApplicationException();
    }

    /// <summary>
    /// Splits value and generates symbolCount barcodes using Structured Append.
    /// </summary>
    public static Image[] GenerateBarcodes(BarcodeType barcodeType, string value, int symbolCount)
    {
        // create an image array
        Image[] result = new Image[symbolCount];

        // create the barcode writer
        BarcodeWriter writer = new BarcodeWriter();        
        
        // specify that writer must generate barcode of specified type
        writer.Settings.Barcode = barcodeType;

        // create parity data for a QR barcode value
        byte parityData = 0;
        if (barcodeType == BarcodeType.QR)
            parityData = QRStructuredAppendCharacter.CaluculateParityData(value);

        // generate symbols(barcodes)
        int fragmentLength = value.Length / symbolCount;
        for (int i = 0; i < symbolCount; i++)
        {
            // create Structured Append character

            StructuredAppendCharacter structureAppendCharacter;
            switch (barcodeType)
            {
                case BarcodeType.Aztec:
                    structureAppendCharacter =
                        new AztecStructuredAppendCharacter(i + 1, symbolCount, "");
                    break;

                case BarcodeType.DataMatrix:
                    structureAppendCharacter =
                        new DataMatrixStructuredAppendCharacter(i + 1, symbolCount, 0);
                    break;

                case BarcodeType.QR:
                    structureAppendCharacter =
                        new QRStructuredAppendCharacter(i + 1, symbolCount, parityData);
                    break;
                
                case BarcodeType.Code16K:
                    structureAppendCharacter =
                        new StructuredAppendCharacter(i + 1, symbolCount);
                    writer.Settings.Height = 200;
                    break;

                case BarcodeType.MaxiCode:
                    structureAppendCharacter =
                        new StructuredAppendCharacter(i + 1, symbolCount);
                    break;

                case BarcodeType.MicroPDF417:
                    structureAppendCharacter =
                        new PDF417StructuredAppendCharacter(i + 1, symbolCount, "123");
                    break;

                case BarcodeType.PDF417:
                    structureAppendCharacter =
                        new PDF417StructuredAppendCharacter(i + 1, symbolCount, "123");
                    break;

                default:
                    throw new NotSupportedException();
            }

            // create symbol data

            string symbolTextData;
            if (i == symbolCount - 1)
                symbolTextData = value.Substring(i * fragmentLength);
            else
                symbolTextData = value.Substring(i * fragmentLength, fragmentLength);
            
            TextValueItem symbolData = new TextValueItem(symbolTextData);

            // set the barcode value items
            writer.Settings.ValueItems = new ValueItemBase[] { structureAppendCharacter, symbolData };
            
            // create image with barcode
            result[i] = writer.GetBarcodeAsBitmap();
        }

        return result;
    }

    /// <summary>
    /// Reads barcodes and merges the results into a single value.
    /// </summary>
    private static string ReadBarcodeValue(Image[] barcodeImages, BarcodeType barcodeType)
    {
        // create the barcode reader
        using (BarcodeReader reader = new BarcodeReader())
        {
            // specify that reader must search for barcodes of specified type
            reader.Settings.ScanBarcodeTypes = barcodeType;

            // barcode reading results
            IBarcodeInfo[] readingResults = new IBarcodeInfo[barcodeImages.Length];
            // read barcodes
            for (int i = 0; i < barcodeImages.Length; i++)
            {
                // read barcode from image
                readingResults[i] = reader.ReadBarcodes(barcodeImages[i])[0];

                // dispose image
                barcodeImages[i].Dispose();
            }

            // determine symbol count
            int symbolsCount = 0;
            for (int i = 0; i < readingResults.Length; i++)
            {
                if (readingResults[i].ValueItems[0] is StructuredAppendCharacter)
                {
                    symbolsCount = ((StructuredAppendCharacter)readingResults[i].ValueItems[0]).SymbolCount;
                    break;
                }
            }
            if (symbolsCount == 0)
                throw new ApplicationException("No Structured Append symbols.");

            // create array of string
            string[] resultValues = new string[symbolsCount];
            // fill resultValues
            for (int i = 0; i < readingResults.Length; i++)
            {
                if (readingResults[i].ValueItems[0] is StructuredAppendCharacter)
                {
                    StructuredAppendCharacter structureAppendCharacter =
                        (StructuredAppendCharacter)readingResults[i].ValueItems[0];
                    if (structureAppendCharacter.SymbolCount == symbolsCount)
                    {
                        readingResults[i].ShowNonDataFlagsInValue = false;
                        resultValues[structureAppendCharacter.SymbolPosition - 1] = readingResults[i].Value;
                    }
                }
            }

            // build result string
            StringBuilder result = new StringBuilder();
            for (int i = 0; i < resultValues.Length; i++)
            {
                if (resultValues[i] != null)
                {
                    result.Append(resultValues[i]);
                }
                else
                {
                    throw new ApplicationException(string.Format("missing symbol at position {0}", i + 1));
                }
            }

            return result.ToString();
        }
    }

}