Specifying the PDF417 parameters
| Chapter 25. PDF417 (2D-Barcode) |

## Specifying the PDF417 parameters

### Note

The following section is not meant as a general introduction to the way PDF417 barcode is specified. It assumes that the reader has a basic understanding of the nature of PDF417 encoding. This section will focus on how to make use of the methods in the library to specify the various settings for the PDF417 barcodes.

### Specifying encoding and input data

The absolute simplest way of encoding data is simply to create a simple string representing the data to be encoded and then pass that string as the first argument to the `Stroke()` method in the backend. The encoder will then analyze the input data and choose the most efficient space saving encoding schema for this data.

The PDF417 standard allows 3 different compaction schema that can be used to minimize the number of codewords used for a particular data string. This also means that a particular data string may have several different valid barcodes that visually looks different.

The available compaction modes are:

- Alpha compaction mode (also known as Text compaction mode). Efficient encoding of ASCII 32-126, (inclusively) i.e. the normal alphabet including numbers. Encodes 1.8 characters per codeword.

- Numeric compaction mode. Efficient encoding of numeric data. For long consecutive strings of digits this gives a better compaction than the alpha mode. Numeric compaction encodes about 2.9 digits per codeword.

- Byte compaction mode. The least efficient encoding. Used only when there is a need to encode byte values as is, i.e. values in the range 0-255. Please note that many barcode readers, especially those with a keyboard wedge, don't send back the proper encoding for ASCII values lower than 32 or higher than 126. Byte compaction mode encodes roughly 1.2 byte per codeword.

When the automatic encoding is chosen this will create an optimum encoding (from a size perspective) of the supplied data. This includes shifting encoding method in the middle of the data one or several time depending on the structure of the data.

It is also possible to manually control the exact encodation of the input data. This is done by supplying one or more data tuples where the first entry in the tuple is the compaction schema and the second the data. To encode the data manually the following structure must then be followed:

Figure 25.9. Structure for manually specified encodation schema

    $data = array( array( <encoding_mode1> , <data1> ),
                   array( <encoding_mode2> , <data2> ),
                             ...
                   array( <encoding_modeN> , <dataN> ));

The encoding mode is specified as one of three symbolic constants

- `USE_TC`, (short for USE-TextCompaction) Use Text compaction schema

- `USE_NC`, (short for USE-Numerical-Compaction) Use Numeric compaction schema

- `USE_BC`, (short for USE-ByteCompaction) Use Byte compaction schema

and the data is specified as a regular text string. Each section of data must therefore have the compaction mode specified.

Example 1:

In the following example we will assume that we want to encode the data string

    1
    $data="1234567890"

To use automatic encoding then there is nothing more than specifying this data to the `Backend::Stroke()` method as

    1
    $backend->Stroke($data);

If instead we wanted to make sure that only alpha mode (text) compaction schema is used the input data would have to be changed to

    1
    2
    3
    4
    5
    6
    <?php
    $data="1234567890"
    $newdata = array(array( USE_TC, $data ));
    ...
    $backend->Stroke($newdata);
    ?>

this will then force the input string to be encoded using only the text compaction schema.

If instead we wanted to enforce only numeric compaction the code would have to be changed to

    1
    2
    3
    4
    5
    6
    <?php
    $data="1234567890"
    $newdata = array(array( USE_NC, $data ));
    ...
    $backend->Stroke($newdata);
    ?>

this will then force the input data string to be encoded using numeric compaction schema. ∎

In the above example we just used a single compaction schema to use multiple encodation schema we just need to split our data for each of the compaction mode we want to use and create an input array. An example will make this clear.

Example 2:

We will assume that we want to encode the string `"1234abc567"` by using numeric compaction for the first 4 digits, then use text compaction for the three letters and finally go back to numeric compaction schema for the last three digits. For this to work we would have to create an input array as shown below.

    1
    2
    3
    4
    5
    6
    7
    <?php
    $newdata = array(array( USE_NC, '1234'),
                     array( USE_TC, 'abc'),
                     array( USE_NC, '567'));
    ...
    $backend->Stroke($newdata);
    ?>

∎

### Note

Normally there are very few reasons to specify the encodation schema manually and it is therefore better to let the library determine the optimum encoding by itself.

#### Using byte compaction mode

Using byte compaction mode is however slightly more complex. The reason is that we need, for technical reasons, specify if the size (length) of the data to be encoded is an even multiple of 6 or not.

Hence, there are actually two Byte code compaction schema

1. `USE_BC_E6` (for even multiples of 6)

2. `USE_BC_O6` (for odd data).

So to encode data using byte compaction mode the following template should be used to determine the proper byte compaction variant.

    1
    2
    3
    4
    5
    6
    <?php
    $even6 = ( strlen($data) % 6 === 0 );
    $newdata = array(array( $even6 ? USE_BC_E6 : USE_BC_O6, $data));
    ...
    $backend->Stroke($newdata);
    ?>

### Caution

Remember that `strlen()` is not multi byte character encodation safe. If multi-byte characters should be encoded then the `mb_strlen()` should be used.

### Caution

Note that several keyboard wedge barcode scanners do not handle byte values < 32 or > 127 properly.

### Encoder option: Adjusting the number of data columns

PDF417 barcode is made up of a number of rows and columns. The library allows the specification of the number of columns and it will then determine the necessary number of rows to hold all the given data + the error correction information.

Since each row has some overhead (start/stop and sync codewords) the overall area taken by the barcode will be minimized by trying to use as many columns as possible. The standards allow for up to 30 columns (and 90 rows). The most practical limit is how wide data the scanner is able to handle. Most hand hold scanner will usually not work very reliable with barcodes which are more than ~10cm wide.

### Encoder option: Adjusting the error level

All PDF417 barcodes have a minimum of two error detection codewords. Above that the user is free to specify a higher level which will allow not only error detection but also (some) error correction.

The error level determines how much redundancy is added in the barcode label. A high level of redundancy ensures that a partially damaged barcode can still be correctly read by the barcode scanner. The downside is that the higher the error level the larger the barcode gets and since the total number of codewords in a PDF417 barcode has a maximum limit of 928 also less real data. Table 25.1. Available error levels shows the available error levels and how that will impact the maximum data payload. Table 25.1. Available error levels also shows the error correcting capacity. For example using error level 4 means that 15 of the codewords can have errors and still be corrected.

Table 25.1. Available error levels

Error level | Error correction codewords | Error correction capacity | Maximum payload
--- | --- | --- | ---
0 | 2 | 0 | 923
1 | 4 | 1 | 921
2 | 8 | 3 | 917
3 | 16 | 7 | 909
4 | 32 | 15 | 893
5 | 64 | 31 | 861
6 | 128 | 63 | 797
7 | 256 | 127 | 669
8 | 512 | 255 | 413

The recommended minimum error level is a dependent on the payload size and is given below.

Table 25.2. Recommended error levels

Data codewords | Recommended error level
--- | ---
1 to 40 | 2
41 to 160 | 3
161 to 320 | 4
321 to 863 | 5

Note that the number of codewords is not the same thing as, for example, the number of digits or letters in a string to be encoded. Depending on the chosen encoding the number of symbols per codeword is always > 1. For example in numeric compaction mode (encoding) each codewords encode, on average, 2.93 digits.

The error level is specified as an integer in the range [0-8] inclusively and can be specified when creating a particular encoder. For example the code below uses the default error correction (2).

    1
    2
    3
    4
    5
    6
    7
    <?php
    // Use 10-columns for data
    $columns =10;

    // Create a new encode using the default error correction
    $encoder = new PDF417Barcode ($columns);
    ?>

While the following specifies an error correction level of 6

    1
    2
    3
    4
    5
    6
    7
    <?php
    $columns = 10; // Use 10-columns for data
    $errlevel = 6; // Error correction level 6

    // Create a new encode using the default error correction
    $encoder = new PDF417Barcode ($columns, $errlevel);
    ?>

In addition to specifying the number of data columns and error level in the creation of the encoder it is also possible to adjust them afterwards.

For example, it might be necessary to create the encoder in the beginning of a script and then use the same encoder with different settings controlled by, for example, entries in a DB.

The two encoder methods

- `Encoder::SetErrLevel($aErrLevel)`

- `Encoder::SetColumns($aColumns)`

are used for this purpose. The code snippet below does the exact same things as the code snippet above but using these two methods after the encoder has been instantiated instead.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php
    $columns = 10; // Use 10-columns for data
    $errlevel = 6; // Error correction level 6

    // Create a new encode using the default error correction
    $encoder = new PDF417Barcode();
    $encoder->SetColumns($columns);
    $encoder->SetErrLevel($errlevel);
    ?>

### Truncated PDF417

### Warning

Not all PDF417 barcode readers can handle truncated PDF417

In situations where the physical size of the label is restricted one might use the truncated version of the PDF417 code.

This works by simply stripping of some redundant information on the right side of the barcode. This will also make the barcode more sensible for damage.

The two images below shows a normal version together with the truncated version (both barcodes encode the same information).

Figure 25.10. Normal PDF417 | Figure 25.11. Truncated PDF417

To use the truncated version the method the following encoder method is used

- `Encoder::SetTruncated($aFlg=true)`

The following code snippet shows how this can be used

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php
    $columns = 10; // Use 10-columns for data
    $errlevel = 4; // Error correction level 4
    $truncated = true;

    // Create a new encode using the default error correction
    $encoder = new PDF417Barcode();
    $encoder->SetTruncated($truncated);
    $encoder->SetColumns($columns);
    $encoder->SetErrLevel($errlevel);
    ?>

| Up |
| Home |