GS1 support in a QR encoder/decoder?

5.2k views Asked by At

Very few QR encoders/decoders have (explicit) support for so-called GS1 encoding. Zint is one of the exceptions (under QR select GS-1 Data Mode), but its license prevents me from using it. Commercial offers, mainly from Tec-It, are costly, especially because I'm not interested in all other kinds of barcodes they support.

Is there a way to add GS1 support to any QR encoder/decoder without changing its source? For example, could I apply some algorithm to transform textual GTIN AI data into compatible binary? I think it should be possible, because after all, it's still QR. Please note that I am not a data coding expert - I'm just looking for a way to deal with this standard without paying a small fortune. So far, I found postscriptbarcode which does have support for it, and seems to use its own QR engine, but output quality is so-so and my PostScript skills are far too limited to figure out the algorithm.

1

There are 1 answers

7
Markus Jarderot On BEST ANSWER

As long as the library supports decoding of the FNC1 special character, it can be used to read GS1 codes. The FNC1 character is not a byte in the data-stream, but more of a formatting symbol.

The specification says that a leading FNC1-character is used to identify GS1 barcodes, and should be decoded as "]d2" (GS1 DataMatrix), "]C1" (GS1-128), "]e0" (GS1 DataBar Omnidirectional) or "]Q3" (GS1 QR Code). Any other FNC1-characters should be decoded as ASCII GS-characters (byte value 29).

Depending on the library, the leading FNC1 might be missing, or decoded as GS (not critical), or the embedded FNC1-characters might be missing (critical). The embedded FNC1-characters are used to delimit variable-length fields.

You can read the full specification here (pdf). The algorithm for decoding the data can be found under heading 7.9 Processing of Data from a GS1 Symbology using GS1 Application Identifiers (page 426).

The algorithm goes something like this:

Peek at the first character.
If it is ']',
    If string does not start with ']C1' or ']e0' or ']d2' or ']Q3',
        Not a GS1 barcode.
        Stop.
    Consume the caracters.
Else if it is <GS>,
    Consume character.
Else,
    No symbology identifier, assume GS1.
While not end of input,
    Read the first two digits.
    If they are in the table of valid codes,
        Look up the length of the AI-code.
        Read the rest of the code.
        Look up the length of the field.
        If it is variable-length,
            Read until the next <FNC1> or <GS>.
        Else,
            Read the rest if the field.
        Peek at the next character.
        If it is <FNC1> or <GS>, consume it.
        Save the read field.
    Else,
        Error: Invalid AI

The binary data in the QR Code is encoded as 4-bit tokens, with embedded data.

0111 -> Start Extended Channel Interpretation (ECI) Mode (special encodings).
0001, 0010, 0100, 1000 -> start numeric, alphanumeric, raw 8-bit, kanji encoded data.
0011 -> structured append (combine two or more QR Codes to one data-stream).
0101 -> FNC1 initial position.
1001 -> FNC1 other positions.
0000 -> End of stream (can be omitted if not enough space).

After an encoding specification comes the data-length, followed by the actual data. The meanings of the data bits depends on the encoding used. In between the data-blocks, you can squeeze FNC1 characters.

The QR Code specification (ISO/IEC 18004) unfortunately costs money (210 Franc). You might find some pirate version online though.

To create GS1 QR Codes, you need to be able to specify the FNC1-characters in the data. The library should either recognize the "]Q3" prefix and GS-characters, or allow you to write FNC1 tokens via some other method.

If you have some way to write the FNC1-characters, you can encode GS1 data as follows:

Write initial FNC1.
For each field,
    Write the AI-code as decimal digits.
    Write field data.
    If the code is a variable-length field,
        If not the last field,
            Write FNC1 to terminate the field.

If possible, you should order the fields such that a variable-length field comes last.


As noted by Terry Burton in the comments; The FNC1 symbol in a GS1 QR Code can be encoded as % in alphanumeric data, and as GS in byte mode. To encode an actual percent symbol, you write it as %%.

To encode (01) 04912345123459 (15) 970331 (30) 128 (10) ABC123, you first combine it into the data string 01049123451234591597033130128%10ABC123 (% indicator is the encoded FNC1 symbol). This string is then written as

0101 - Initial FNC1, GS1 mode indicator
0001 - QR numeric mode
0000011101 - Data length (29)
<data bits for "01049123451234591597033130128">
0010 - QR alphanumeric mode
000001001 - Data length (9)
<data bits for "%10ABC123">

(Example from the ISO 18004:2006 specification)