VintaSoft Barcode .NET SDK 16.0: Documentation for .NET developer
In This Topic
How to use Structure Append feature for distributing data message across several 2D barcodes?
In This Topic
Structure Append feature allows to distribute data message across several 2D barcodes (up to 16 DataMatrix barcodes, up to 16 QR barcodes, up to 26 Aztec barcodes, up to 99999 PDF417 barcodes, up to 9 Code16K barcodes, up to 35 DotCode barcodes) if data message cannot be stored in a single 2D barcode.

Here is C#/VB.NET code that demonstrates how to use Structure Append feature for distributing data message across several 2D barcodes.
using System;
using System.Text;

using Vintasoft.Barcode;
using Vintasoft.Barcode.BarcodeInfo;
using Vintasoft.Imaging;

/// <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, DotCode, MaxiCode, QR Code, PDF417, Micro PDF417 "+
            "symbols may be appended in a structured format.";

        // split data and generate barcodes
        VintasoftBitmap[] 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 VintasoftBitmap[] GenerateBarcodes(BarcodeType barcodeType, string value, int symbolCount)
    {
        // create an image array
        VintasoftBitmap[] result = new VintasoftBitmap[symbolCount];

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

            // 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.DotCode:
                        structureAppendCharacter =
                            NonDataFlags.CreateDotCodeStructuredAppendCharacter(i + 1, symbolCount);
                        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.GetBarcodeAsVintasoftBitmap();
            }

            return result;
        }
    }

    /// <summary>
    /// Reads barcodes and merges the results into a single value.
    /// </summary>
    private static string ReadBarcodeValue(VintasoftBitmap[] 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();
        }
    }

}

Imports System.Text

Imports Vintasoft.Barcode
Imports Vintasoft.Barcode.BarcodeInfo
Imports Vintasoft.Imaging

''' <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, DotCode, MaxiCode, QR Code, PDF417, Micro PDF417 " & _
            "symbols may be appended in a structured format."

        ' split data and generate barcodes
        Dim barcodeImages As VintasoftBitmap() = 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 VintasoftBitmap()

        ' create an image array
        Dim result As VintasoftBitmap() = New VintasoftBitmap(symbolCount - 1) {}

        ' create the barcode writer
        Using writer As New BarcodeWriter()
            ' specify that writer must generate barcode of specified type
            writer.Settings.Barcode = barcodeType__1
            writer.Settings.MinWidth = 5

            ' 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.DotCode
                        structureAppendCharacter = NonDataFlags.CreateDotCodeStructuredAppendCharacter(i + 1, symbolCount)
                        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.GetBarcodeAsVintasoftBitmap()
            Next

            Return result
        End Using
    End Function

    ''' <summary>
    ''' Reads barcodes and merges the results into a single value.
    ''' </summary>
    Private Shared Function ReadBarcodeValue(barcodeImages As VintasoftBitmap(), 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