How to properly generate a GS1-128 (formerly EAN-128) barcode in TCPDF

user1398498 picture user1398498 · Dec 2, 2015 · Viewed 7.2k times · Source

We are trying to generate correct EAN-128 codes for product labels, with TCPDF library, but our client says that the barcode scanner doesn't read the generated barcode. The original(old) barcode and string:

enter image description here

The code string is:

$codeString = "(01)08437013308045(3013)2675(15)161201(10)150518"

If we pass the string directly to the TCPDF function, like this:

$label->write1DBarcode($codeString, 'C128A', $x, $y, $w, $h);

we're getting correct output (which the scanner won't read) but the bars are more dense comparing to the original barcode which seems shorter and less dense (they say it's EAN-128): enter image description here

We found here (EAN-128 with FNC1) that adding chr(241) before the $codeString should help but if we add it, the resulting image is stripped off of everything in human readable code:

enter image description here

Since we don't own a barcode reader, we can't check the errors ourselves.

What we are missing here? We're using TCPDF version 6.2.12.

Answer

Terry Burton picture Terry Burton · Dec 2, 2015

There are a number of problems here that I'll work through.

Firstly, you have misread the text of the original barcode which contains the fixed-length Application Identifier (AI) field (3103)2775 representing net weight.

You have written a code containing (3013)2675 which is invalid. There is no AI (3013) and unfortunately this would prefix match with the legitimate AI (30) representing an item count which is a variable-length field. Therefore a decoder would continue to read the remaining data until the end of the code into AI (30) since there is no subsequent field terminator character (FNC1). That's a lot of items – more than eight digits worth in fact so the reader may indicate a fault!

The "extraction" part of this answer provides background on how GS1 data is encoding within a Code 128 barcode to produce a valid GS1-128 symbol.

Let's assume that you meant to encode the GS1 data (01)08437013308045(3103)2675(15)161201(10)150518.

The raw data that you need to encode in the Code 128 is {FNC1}0108437013308045310326751516120110150518.

This has been derived as follows:

  • The data begins with an FNC1 flag character (indicating the presence of GS1-formatted data).
  • The parentheses around the AIs have been omitted.
  • Since your data consists of only fixed-length AIs there are no instances where we have to terminate a variable-length field with an FNC1 separator character [*].

[*] Note that the list of AIs provided in the GS1 General Specifications §3.2 "GS1 Application Identifiers in Numerical Order" indicates whether they require termination by an FNC1 character when followed by additional data.

How does this knowledge translate into code for TCPDF? I've never used it sorry, but this might be helpful:

Your $codeString variable would need to be defined something like:

$codeString = chr(241).'0108437013308045310326751516120110150518';

This assumes that the linked to answer on the support forum is correct in stating that TCPDF uses ASCII ordinal 241 to indicate an FNC1 character. (There is some doubt whether this is the case.) If it works then this is a library-specific choice and you shouldn't read much into the fact that they have chosen value 241. See here for details about encoding non-data characters such as FNC1.

I also notice that you pass C128A to the type parameter of write1DBarcode which limits the symbol to mode A (numbers, uppercase letters and control characters.) This would be terribly inefficient and is likely to result in a symbol that is too wide (or too dense when rescaled) to scan with most standard equipment used for logistics applications.

Code 128 supports a mode C that provides double-density compression of digits so you should use this, probably by passing type=C128C or type=C128 (auto) assuming that TCPDF's auto-encoding is any good and future symbols that you will create may need to contain letters.

$label->write1DBarcode($codeString, 'C128', $x, $y, $w, $h);

As far as the human-readable text beneath the barcode is concerned, if this doesn't display correctly for properly encoded data then you may need to raise a bug report or feature request against TCPDF.