PDF417StructuredAppendCharacter Class
In This Topic
Contains information about the PDF417 (Macro PDF417) and Micro PDF417 Structured Append non-data character.
Object Model
Syntax
Remarks
A Structured Append character is used to indicate that the symbol is part of a Structured Append sequence.
Structured Append provides a standard mechanism for creating a distributed representation of files too large to be represented by a single PDF417 or Micro PDF417 symbol. Using Structured Append, large files are split into several file segments and encoded into individual symbols. The Structured Append character defines the file ID, the concatenation sequence and optionally other information about the file.
A Structured Append decoder uses the Structured Append character information to reconstruct the file correctly independently of symbol scanning order.
For each related Structured Append symbol, the FileID field contains the same value. The file ID is a variable length field composed of triplets. Each triplet in the file ID can have a value between 000 and 899, effectively making the file ID a series of base 900 numbers.
Structured Append character also contain a number of optional fields. Each optional field has field designator. Field designator defines field type and field encoding mode.
Pre-defined field designators:
- 0 - File Name, variable text (FileName).
- 1 - Segment Count, fixed number 0..99999 (SymbolCount).
- 2 - Time Stamp, fixed number, indicates the time stamp on the source file expressed as the elapsed time in seconds since 1970:01:01:00:00:00 GMT (TimeStamp).
- 3 - Sender, variable text (Sender).
- 4 - Addressee, variable text (Addressee).
- 5 - FileSize, variable number (FileSize).
- 6 - Checksum, fiexd number 0..65535 (Checksum).
Field designator values greater than 6 are not currently defined. However, decoder and transmit any optional fields encountered with a field designator of 7 to 34 by treating the field data as variable text.
Additional information about PDF417 Structured Append see in: ISO/IEC 24728, ISO/IEC 15438, Annex H.
Example
This C#/VB.NET code shows how to split data files into parts and reconstruct data files using PDF417 Structured Append character:
Imports System.Collections.Generic
Imports System.Text
Imports Vintasoft.Barcode
Imports Vintasoft.Barcode.BarcodeInfo
Imports Vintasoft.Imaging
Class PDF417StructuredAppendCharacterExample
''' <summary>
''' The barcode type (PDF417, PDF417Compact or MicroPDF417).
''' </summary>
Shared _barcodeType As BarcodeType = BarcodeType.PDF417
''' <summary>
''' Splits 3 files into 9 parts (each file into 3 parts), creates barcodes from 9 parts,
''' reorders barcodes, recognizes barcodes and restores content of 3 files.
''' </summary>
Public Shared Sub Test()
' count of data files
Dim fileCount As Integer = 3
' count of parts in data file
Dim symbolCount As Integer = 3
' split data files to symbols
Dim barcodeImages As New List(Of VintasoftBitmap)()
For i As Integer = 0 To fileCount - 1
' file ID - series of triplets 000..899
Dim fileId As String = (i + 1).ToString().PadLeft(3, "0"C)
' split each data file to "symbolCount" symbols
For j As Integer = 0 To symbolCount - 1
' create structured append character
Dim structureAppendCharacter As New PDF417StructuredAppendCharacter(j + 1, symbolCount, fileId)
' add FileName information to the first symbol of data file
If j = 0 Then
structureAppendCharacter.FileName = String.Format("DataFile{0}", i + 1)
End If
' barcode value
Dim symbolValue As String = String.Format("[Part {0} of file {1}]", j + 1, i + 1)
' generate barcode image
barcodeImages.Add(GenerateBarcode(structureAppendCharacter, symbolValue))
Next
Next
' resort barcode images
barcodeImages.Reverse()
barcodeImages.Reverse(0, barcodeImages.Count \ 2)
barcodeImages.Reverse(barcodeImages.Count \ 3, (barcodeImages.Count \ 3) * 2)
' recognize all barcodes and reconstruct data files
Dim dataFiles As Dictionary(Of String, String) = ReconstructDataFiles(barcodeImages)
' print reconstructed data files
Console.WriteLine("Reconstructed data files:")
For Each fileId As String In dataFiles.Keys
Console.WriteLine(String.Format("File ID : {0}", fileId))
Console.WriteLine(String.Format("Data File: {0}", dataFiles(fileId)))
Console.WriteLine()
Next
End Sub
''' <summary>
''' Generates the barcode image.
''' </summary>
''' <param name="structuredAppend">The structured append character.</param>
''' <param name="barcodeValue">The barcode value.</param>
Private Shared Function GenerateBarcode(structuredAppend As PDF417StructuredAppendCharacter, barcodeValue As String) As VintasoftBitmap
Using writer As New BarcodeWriter()
writer.Settings.Barcode = _barcodeType
writer.Settings.ValueItems = New ValueItemBase() {structuredAppend, New TextValueItem(barcodeValue)}
Return writer.GetBarcodeAsVintasoftBitmap()
End Using
End Function
''' <summary>
''' Reconstructs the data files.
''' </summary>
''' <param name="barcodeImages">The barcode images.</param>
''' <returns>Dictonary (fileId -> DataFile) that contaions recontructed data files.</returns>
Private Shared Function ReconstructDataFiles(barcodeImages As List(Of VintasoftBitmap)) As Dictionary(Of String, String)
' create barcode reader
Using reader As New BarcodeReader()
reader.Settings.ScanBarcodeTypes = _barcodeType
' Dictionary: FileId -> (symbolPosition -> barcodeValue)
Dim recognizeBarcodes As New Dictionary(Of String, Dictionary(Of Integer, String))()
' for each barcode image
For i As Integer = 0 To barcodeImages.Count - 1
' recognize barcode
Console.WriteLine(String.Format("Recognize image {0}...", i + 1))
Dim info As IBarcodeInfo = reader.ReadBarcodes(barcodeImages(i))(0)
Dim valueItems As ValueItemBase() = info.ValueItems
' structured append character
Dim saCharacter As PDF417StructuredAppendCharacter = DirectCast(valueItems(0), PDF417StructuredAppendCharacter)
' barcode value
info.ShowNonDataFlagsInValue = False
Dim barcodeValue As String = info.Value
' show information about recognized barcode
Console.WriteLine(String.Format(" Value : {0}", barcodeValue))
Console.WriteLine(String.Format(" Symbol : {0} of {1}", saCharacter.SymbolPosition, saCharacter.SymbolCount))
Console.WriteLine(String.Format(" File ID : {0}", saCharacter.FileID))
If saCharacter.FileName IsNot Nothing Then
Console.WriteLine(String.Format(" FileName: {0}", saCharacter.FileName))
End If
Console.WriteLine()
' add barcode value to recognizeBarcodes table
Dim positionsToDataFileParts As Dictionary(Of Integer, String)
If Not recognizeBarcodes.TryGetValue(saCharacter.FileID, positionsToDataFileParts) Then
positionsToDataFileParts = New Dictionary(Of Integer, String)()
recognizeBarcodes(saCharacter.FileID) = positionsToDataFileParts
End If
positionsToDataFileParts.Add(saCharacter.SymbolPosition, barcodeValue)
Next
' reconstruct data files
Dim dataFiles As New Dictionary(Of String, String)()
For Each fileId As String In recognizeBarcodes.Keys
Dim positionsToDataFileParts As Dictionary(Of Integer, String) = recognizeBarcodes(fileId)
' symbol positions
Dim positions As Integer() = New Integer(positionsToDataFileParts.Count - 1) {}
positionsToDataFileParts.Keys.CopyTo(positions, 0)
' data file parts
Dim dataFileParts As String() = New String(positionsToDataFileParts.Count - 1) {}
positionsToDataFileParts.Values.CopyTo(dataFileParts, 0)
' sort data file parts by symbol posiotions
Array.Sort(positions, dataFileParts)
' merge data file parts
Dim dataFile As New StringBuilder()
For Each dataFilePart As String In dataFileParts
dataFile.Append(dataFilePart)
Next
dataFiles(fileId) = dataFile.ToString()
Next
Return dataFiles
End Using
End Function
End Class
' This code example produces the following output:
'
'Recognize image 1...
' Value : [Part 3 of file 2]
' Symbol : 3 of 3
' File ID : 002
'
'Recognize image 2...
' Value : [Part 1 of file 3]
' Symbol : 1 of 3
' File ID : 003
' FileName: DataFile3
'
'Recognize image 3...
' Value : [Part 2 of file 3]
' Symbol : 2 of 3
' File ID : 003
'
'Recognize image 4...
' Value : [Part 1 of file 1]
' Symbol : 1 of 3
' File ID : 001
' FileName: DataFile1
'
'Recognize image 5...
' Value : [Part 2 of file 1]
' Symbol : 2 of 3
' File ID : 001
'
'Recognize image 6...
' Value : [Part 3 of file 1]
' Symbol : 3 of 3
' File ID : 001
'
'Recognize image 7...
' Value : [Part 1 of file 2]
' Symbol : 1 of 3
' File ID : 002
' FileName: DataFile2
'
'Recognize image 8...
' Value : [Part 2 of file 2]
' Symbol : 2 of 3
' File ID : 002
'
'Recognize image 9...
' Value : [Part 3 of file 3]
' Symbol : 3 of 3
' File ID : 003
'
'Reconstructed data files:
'File ID : 002
'Data File: [Part 1 of file 2][Part 2 of file 2][Part 3 of file 2]
'
'File ID : 003
'Data File: [Part 1 of file 3][Part 2 of file 3][Part 3 of file 3]
'
'File ID : 001
'Data File: [Part 1 of file 1][Part 2 of file 1][Part 3 of file 1]
'
using System;
using System.Collections.Generic;
using System.Text;
using Vintasoft.Barcode;
using Vintasoft.Barcode.BarcodeInfo;
using Vintasoft.Imaging;
class PDF417StructuredAppendCharacterExample
{
/// <summary>
/// The barcode type (PDF417, PDF417Compact or MicroPDF417).
/// </summary>
static BarcodeType _barcodeType = BarcodeType.PDF417;
/// <summary>
/// Splits 3 files into 9 parts (each file into 3 parts), creates barcodes from 9 parts,
/// reorders barcodes, recognizes barcodes and restores content of 3 files.
/// </summary>
public static void Test()
{
// count of data files
int fileCount = 3;
// count of parts in data file
int symbolCount = 3;
// split data files to symbols
List<VintasoftBitmap> barcodeImages = new List<VintasoftBitmap>();
for (int i = 0; i < fileCount; i++)
{
// file ID - series of triplets 000..899
string fileId = (i + 1).ToString().PadLeft(3, '0');
// split each data file to "symbolCount" symbols
for (int j = 0; j < symbolCount; j++)
{
// create structured append character
PDF417StructuredAppendCharacter structureAppendCharacter =
new PDF417StructuredAppendCharacter(j + 1, symbolCount, fileId);
// add FileName information to the first symbol of data file
if (j == 0)
structureAppendCharacter.FileName = string.Format("DataFile{0}", i + 1);
// barcode value
string symbolValue = string.Format("[Part {0} of file {1}]", j + 1, i + 1);
// generate barcode image
barcodeImages.Add(GenerateBarcode(structureAppendCharacter, symbolValue));
}
}
// resort barcode images
barcodeImages.Reverse();
barcodeImages.Reverse(0, barcodeImages.Count / 2);
barcodeImages.Reverse(barcodeImages.Count / 3, (barcodeImages.Count / 3) * 2);
// recognize all barcodes and reconstruct data files
Dictionary<string, string> dataFiles = ReconstructDataFiles(barcodeImages);
// print reconstructed data files
Console.WriteLine("Reconstructed data files:");
foreach (string fileId in dataFiles.Keys)
{
Console.WriteLine(string.Format("File ID : {0}", fileId));
Console.WriteLine(string.Format("Data File: {0}", dataFiles[fileId]));
Console.WriteLine();
}
}
/// <summary>
/// Generates the barcode image.
/// </summary>
/// <param name="structuredAppend">The structured append character.</param>
/// <param name="barcodeValue">The barcode value.</param>
private static VintasoftBitmap GenerateBarcode(
PDF417StructuredAppendCharacter structuredAppend,
string barcodeValue)
{
using (BarcodeWriter writer = new BarcodeWriter())
{
writer.Settings.Barcode = _barcodeType;
writer.Settings.ValueItems = new ValueItemBase[] {
structuredAppend, new TextValueItem(barcodeValue) };
return writer.GetBarcodeAsVintasoftBitmap();
}
}
/// <summary>
/// Reconstructs the data files.
/// </summary>
/// <param name="barcodeImages">The barcode images.</param>
/// <returns>Dictonary (fileId -> DataFile) that contaions recontructed data files.</returns>
private static Dictionary<string, string> ReconstructDataFiles(List<VintasoftBitmap> barcodeImages)
{
// create barcode reader
using (BarcodeReader reader = new BarcodeReader())
{
reader.Settings.ScanBarcodeTypes = _barcodeType;
// Dictionary: FileId -> (symbolPosition -> barcodeValue)
Dictionary<string, Dictionary<int, string>> recognizeBarcodes =
new Dictionary<string, Dictionary<int, string>>();
// for each barcode image
for (int i = 0; i < barcodeImages.Count; i++)
{
// recognize barcode
Console.WriteLine(string.Format("Recognize image {0}...", i + 1));
IBarcodeInfo info = reader.ReadBarcodes(barcodeImages[i])[0];
ValueItemBase[] valueItems = info.ValueItems;
// structured append character
PDF417StructuredAppendCharacter saCharacter = (PDF417StructuredAppendCharacter)valueItems[0];
// barcode value
info.ShowNonDataFlagsInValue = false;
string barcodeValue = info.Value;
// show information about recognized barcode
Console.WriteLine(string.Format(" Value : {0}", barcodeValue));
Console.WriteLine(string.Format(" Symbol : {0} of {1}", saCharacter.SymbolPosition, saCharacter.SymbolCount));
Console.WriteLine(string.Format(" File ID : {0}", saCharacter.FileID));
if (saCharacter.FileName != null)
Console.WriteLine(string.Format(" FileName: {0}", saCharacter.FileName));
Console.WriteLine();
// add barcode value to recognizeBarcodes table
Dictionary<int, string> positionsToDataFileParts;
if (!recognizeBarcodes.TryGetValue(saCharacter.FileID, out positionsToDataFileParts))
{
positionsToDataFileParts = new Dictionary<int, string>();
recognizeBarcodes[saCharacter.FileID] = positionsToDataFileParts;
}
positionsToDataFileParts.Add(saCharacter.SymbolPosition, barcodeValue);
}
// reconstruct data files
Dictionary<string, string> dataFiles = new Dictionary<string, string>();
foreach (string fileId in recognizeBarcodes.Keys)
{
Dictionary<int, string> positionsToDataFileParts = recognizeBarcodes[fileId];
// symbol positions
int[] positions = new int[positionsToDataFileParts.Count];
positionsToDataFileParts.Keys.CopyTo(positions, 0);
// data file parts
string[] dataFileParts = new string[positionsToDataFileParts.Count];
positionsToDataFileParts.Values.CopyTo(dataFileParts, 0);
// sort data file parts by symbol posiotions
Array.Sort(positions, dataFileParts);
// merge data file parts
StringBuilder dataFile = new StringBuilder();
foreach (string dataFilePart in dataFileParts)
dataFile.Append(dataFilePart);
dataFiles[fileId] = dataFile.ToString();
}
return dataFiles;
}
}
}
/* This code example produces the following output:
Recognize image 1...
Value : [Part 3 of file 2]
Symbol : 3 of 3
File ID : 002
Recognize image 2...
Value : [Part 1 of file 3]
Symbol : 1 of 3
File ID : 003
FileName: DataFile3
Recognize image 3...
Value : [Part 2 of file 3]
Symbol : 2 of 3
File ID : 003
Recognize image 4...
Value : [Part 1 of file 1]
Symbol : 1 of 3
File ID : 001
FileName: DataFile1
Recognize image 5...
Value : [Part 2 of file 1]
Symbol : 2 of 3
File ID : 001
Recognize image 6...
Value : [Part 3 of file 1]
Symbol : 3 of 3
File ID : 001
Recognize image 7...
Value : [Part 1 of file 2]
Symbol : 1 of 3
File ID : 002
FileName: DataFile2
Recognize image 8...
Value : [Part 2 of file 2]
Symbol : 2 of 3
File ID : 002
Recognize image 9...
Value : [Part 3 of file 3]
Symbol : 3 of 3
File ID : 003
Reconstructed data files:
File ID : 002
Data File: [Part 1 of file 2][Part 2 of file 2][Part 3 of file 2]
File ID : 003
Data File: [Part 1 of file 3][Part 2 of file 3][Part 3 of file 3]
File ID : 001
Data File: [Part 1 of file 1][Part 2 of file 1][Part 3 of file 1]
*/
Inheritance Hierarchy
Requirements
Target Platforms: .NET9; .NET 8; .NET 7; .NET 6; .NET Framework 4.8, 4.7, 4.6, 4.5, 4.0, 3.5
See Also