Zint: Manual

5. Using the API

Zint has been written using the C language and has an API for use with C/C++ language programs. A Qt interface is available in the "backend_qt" sub-directory, and a Tcl interface is available in the "backend_tcl" sub-directory.

The libzint API has been designed to be very similar to that used by the GNU Barcode package. This allows easy migration from GNU Barcode to Zint. Zint, however, uses none of the same function names or option names as GNU Barcode. This allows you to use both packages in your application without conflict if you wish.

5.1 Creating and Deleting Symbols

The symbols manipulated by Zint are held in a zint_symbol structure defined in "zint.h". These symbols are created with the ZBarcode_Create() function and deleted using the ZBarcode_Delete() function. For example the following code creates and then deletes a symbol:

#include <zint.h>
#include <stdio.h>
int main()
{
    struct zint_symbol *my_symbol;
    my_symbol = ZBarcode_Create();
    if (my_symbol != NULL) {
        printf("Symbol successfully created!\n");
    }
    ZBarcode_Delete(my_symbol);
    return 0;
}

When compiling this code it will need to be linked with the libzint library using the -lzint option:

gcc -o simple simple.c -lzint

5.2 Encoding and Saving to File

To encode data in a barcode use the ZBarcode_Encode() function. To write the symbol to a file use the ZBarcode_Print() function. For example the following code takes a string from the command line and outputs a Code 128 symbol in a PNG file named "out.png" (or a GIF file called "out.gif" if libpng is not present) in the current working directory:

#include <zint.h>
int main(int argc, char **argv)
{
    struct zint_symbol *my_symbol;
    my_symbol = ZBarcode_Create();
    ZBarcode_Encode(my_symbol, argv[1], 0);
    ZBarcode_Print(my_symbol, 0);
    ZBarcode_Delete(my_symbol);
    return 0;
}

This can also be done in one stage using the ZBarcode_Encode_and_Print() function as shown in the next example:

#include <zint.h>
int main(int argc, char **argv)
{
    struct zint_symbol *my_symbol;
    my_symbol = ZBarcode_Create();
    ZBarcode_Encode_and_Print(my_symbol, argv[1], 0, 0);
    ZBarcode_Delete(my_symbol);
    return 0;
}

Note that when using the API, the input data is assumed to be 8-bit binary unless the input_mode variable in the zint_symbol structure is set - see 5.10 Setting the Input Mode for details.

5.3 Encoding and Printing Functions in Depth

The functions for encoding and printing barcodes are defined as:

int ZBarcode_Encode(struct zint_symbol *symbol,
      const unsigned char *source, int length);

int ZBarcode_Encode_File(struct zint_symbol *symbol,
      const char *filename);

int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle);

int ZBarcode_Encode_and_Print(struct zint_symbol *symbol,
      const unsigned char *source, int length, int rotate_angle);

int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol,
      const char *filename, int rotate_angle);

In these definitions length can be used to set the length of the input string. This allows the encoding of NUL (ASCII 0) characters in those symbologies which allow this. A value of 0 will disable this usage and Zint will encode data up to the first NUL character in the input string, which must be present.

The rotate_angle value can be used to rotate the image when outputting. Valid values are 0, 90, 180 and 270.

The ZBarcode_Encode_File() and ZBarcode_Encode_File_and_Print() functions can be used to encode data read directly from a text file where the filename is given in the NUL-terminated filename string.

If printing more than one barcode, the zint_symbol structure may be re-used by calling the ZBarcode_Clear() function after each barcode to free any output buffers allocated. The zint_symbol input variables must be reset.

5.4 Buffering Symbols in Memory (raster)

In addition to saving barcode images to file Zint allows you to access a representation of the resulting bitmap image in memory. The following functions allow you to do this:

int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle);

int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol,
      const unsigned char *source, int length, int rotate_angle);

int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol,
      const char *filename, int rotate_angle);

The arguments here are the same as above. The difference is that instead of saving the image to a file it is placed in an unsigned character array. The bitmap pointer is set to the first memory location in the array and the values barcode_width and barcode_height indicate the size of the resulting image in pixels. Rotation and colour options can be used with the buffer functions in the same way as when saving to a file. The pixel data can be extracted from the array by the method shown in the example below where render_pixel() is assumed to be a function for drawing a pixel on the screen implemented by the external application:

int row, col, i = 0;
int red, blue, green;

for (row = 0; row < my_symbol->bitmap_height; row++) {
     for (col = 0; col < my_symbol->bitmap_width; col++) {
          red = (int) my_symbol->bitmap[i];
          green = (int) my_symbol->bitmap[i + 1];
          blue = (int) my_symbol->bitmap[i + 2];
          render_pixel(row, col, red, green, blue);
          i += 3;
     }
}

Where speed is important, the buffer can be returned instead in a more compact intermediate form using the output option OUT_BUFFER_INTERMEDIATE. Here each byte is an ASCII value: '1' for foreground colour and '0' for background colour, except for Ultracode, which also uses colour codes: 'W' for white, 'C' for cyan, 'B' for blue, 'M' for magenta, 'R' for red, 'Y' for yellow, 'G' for green, and 'K' for black. The loop for accessing the data is then:

int row, col, i = 0;

for (row = 0; row < my_symbol->bitmap_height; row++) {
     for (col = 0; col < my_symbol->bitmap_width; col++) {
          render_pixel(row, col, my_symbol->bitmap[i]);
          i++;
     }
}

5.5 Buffering Symbols in Memory (vector)

Symbols can also be saved to memory in a vector representation as well as a bitmap one. The following functions, exactly analogous to the ones above, allow you to do this:

int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle);

int ZBarcode_Encode_and_Buffer_Vector(struct zint_symbol *symbol,
      const unsigned char *source, int length, int rotate_angle);

int ZBarcode_Encode_File_and_Buffer_Vector(struct zint_symbol *symbol,
      const char *filename, int rotate_angle);

Here the vector pointer is set to a header which contains pointers to lists of structures representing the various elements of the barcode: rectangles, hexagons, strings and circles. To draw the barcode, each of the element types is iterated in turn, and using the information stored is drawn by a rendering system. For instance, to draw a barcode using a rendering system with prepare_canvas(), draw_rect(), draw_hexagon(), draw_string(), and draw_circle() routines available:

struct zint_vector_rect *rect;
struct zint_vector_hexagon *hexagon;
struct zint_vector_string *string;
struct zint_vector_circle *circle;

prepare_canvas(my_symbol->vector->width, my_symbol->vector->height,
               my_symbol->scale, my_symbol->fgcolour, my_symbol->bgcolor,
               rotate_angle);

for (rect = my_symbol->vector->rectangles; rect; rect = rect->next) {
    draw_rect(rect->x, rect->y, rect->width, rect->height,
              rect->colour);
}
for (hexagon = my_symbol->vector->hexagons; hexagon; hexagon = hexagon->next) {
    draw_hexagon(hexagon->x, hexagon->y, hexagon->diameter,
                 hexagon->rotation);
}
for (string = my_symbol->vector->strings; string; string = string->next) {
    draw_string(string->x, string->y, string->fsize,
                string->rotation, string->halign,
                string->text, string->length);
}
for (circle = my_symbol->vector->circles; circle; circle = circle->next) {
    draw_circle(circle->x, circle->y, circle->diameter,
                circle->width, circle->colour);
}

5.6 Setting Options

So far our application is not very useful unless we plan to only make Code 128 symbols and we don’t mind that they only save to "out.png". As with the CLI program, of course, these options can be altered. The way this is done is by altering the contents of the zint_symbol structure between the creation and encoding stages. The zint_symbol structure consists of the following variables:

API Structure zint_symbol $
Variable Name Type Meaning Default Value
symbology integer Symbol to use (see 5.8 Specifying a Symbology). BARCODE_CODE128
height float Symbol height, excluding fixed width-to-height symbols.6 Symbol dependent
scale float Scale factor for adjusting size of image. 1.0
whitespace_width integer Horizontal whitespace width. 0
whitespace_height integer Vertical whitespace height. 0
border_width integer Border width. 0
output_options integer Set various output file parameters (see 5.9 Adjusting Other Output Options). 0 (none)
fgcolour character string Foreground (ink) colour as RGB/RGBA hexadecimal string. Must be 6 or 8 characters followed by a terminating NUL. "000000"
bgcolour character string Background (paper) colour as RGB/RGBA hexadecimal string. Must be 6 or 8 characters followed by a terminating NUL. "ffffff"
fgcolor pointer Points to fgcolour allowing alternate spelling.
bgcolor pointer Points to bgcolour allowing alternate spelling.
outfile character string Contains the name of the file to output a resulting barcode symbol to. Must end in .png, .gif, .bmp, .emf, .eps, .pcx, .svg, .tif or .txt followed by a terminating NUL. "out.png"
primary character string Primary message data for more complex symbols, with a terminating NUL. "" (empty)
option_1 integer Symbol specific options. -1
option_2 integer Symbol specific options. 0
option_3 integer Symbol specific options. 0
show_hrt integer Set to 0 to hide text. 1
input_mode integer Set encoding of input data (see 5.10 Setting the Input Mode). DATA_MODE
eci integer Extended Channel Interpretation code. 0 (none)
dot_size float Diameter of dots used in dotty mode. 4.0 / 5.0
guard_descent float Height of guard bar descent (EAN/UPC only). 5.0
structapp Structured Append structure Mark a symbol as part of a sequence of symbols. count 0 (disabled)
warn_level integer Affects error/warning value returned by Zint API (see 5.7 Handling Errors). WARN_DEFAULT
text unsigned character string Human Readable Text, which usually consists of input data plus one more check digit. Uses UTF-8 formatting, with a terminating NUL. "" (empty) (output only)
rows integer Number of rows used by the symbol. (output only)
width integer Width of the generated symbol. (output only)
encoding_data array of unsigned character arrays Representation of the encoded data. (output only)
row_height array of floats Representation of the height of a row. (output only)
errtxt character string Error message in the event that an error occurred, with a terminating NUL. (output only)
bitmap pointer to unsigned character array Pointer to stored bitmap image. (output only)
bitmap_width integer Width of stored bitmap image (in pixels). (output only)
bitmap_height integer Height of stored bitmap image (in pixels). (output only)
alphamap pointer to unsigned character array Pointer to array representing alpha channel (or NULL if no alpha channel needed). (output only)
bitmap_byte_length integer Size of BMP bitmap data. (output only)
vector pointer to vector structure Pointer to vector header containing pointers to vector elements. (output only)

To alter these values use the syntax shown in the example below. This code has the same result as the previous example except the output is now taller and plotted in green.

#include <zint.h>
#include <string.h>
int main(int argc, char **argv)
{
    struct zint_symbol *my_symbol;
    my_symbol = ZBarcode_Create();
    strcpy(my_symbol->fgcolour, "00ff00");
    my_symbol->height = 400.0f;
    ZBarcode_Encode_and_Print(my_symbol, argv[1], 0, 0);
    ZBarcode_Delete(my_symbol);
    return 0;
}

Background removal for EMF, EPS, GIF, PNG, SVG and TIF files can be achieved by setting the background alpha to "00" where the values for R, G and B will be ignored:

strcpy(my_symbol->bgcolour, "55555500");

5.7 Handling Errors

If errors occur during encoding a non-zero integer value is passed back to the calling application. In addition the errtxt variable is used to give a message detailing the nature of the error. The errors generated by Zint are given in the table below:

API Warning and Error Return Values
Return Value Meaning
ZINT_WARN_INVALID_OPTION One of the values in zint_struct was set incorrectly but Zint has made a guess at what it should have been and generated a barcode accordingly.
ZINT_WARN_USES_ECI Zint has automatically inserted an ECI character. The symbol may not be readable with some readers.
ZINT_WARN_NONCOMPLIANT The symbol was created but is not compliant with certain standards set in its specification (e.g. height, GS1 AI data lengths).
ZINT_ERROR Marks the divide between warnings and errors. For return values greater than or equal to this no symbol (or only an incomplete symbol) is generated.
ZINT_ERROR_TOO_LONG The input data is too long or too short for the selected symbology. No symbol has been generated.
ZINT_ERROR_INVALID_DATA The data to be encoded includes characters which are not permitted by the selected symbology (e.g. alphabetic characters in an EAN symbol). No symbol has been generated.
ZINT_ERROR_INVALID_CHECK Data with an incorrect check digit has been entered. No symbol has been generated.
ZINT_ERROR_INVALID_OPTION One of the values in zint_struct was set incorrectly and Zint was unable to guess what it should have been. No symbol has been generated.
ZINT_ERROR_ENCODING_PROBLEM A problem has occurred during encoding of the data. This should never happen. Please contact the developer if you encounter this error.
ZINT_ERROR_FILE_ACCESS Zint was unable to open the requested output file. This is usually a file permissions problem.
ZINT_ERROR_MEMORY Zint ran out of memory. This should only be a problem with legacy systems.
ZINT_ERROR_FILE_WRITE Zint failed to write all contents to the requested output file. This should only occur if the output device becomes full.
ZINT_ERROR_USES_ECI Returned if warn_level set to WARN_FAIL_ALL and ZINT_WARN_USES_ECI occurs.
ZINT_ERROR_NONCOMPLIANT Returned if warn_level set to WARN_FAIL_ALL and ZINT_WARN_NONCOMPLIANT occurs.

To catch errors use an integer variable as shown in the code below:

#include <zint.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
    struct zint_symbol *my_symbol;
    int error;
    my_symbol = ZBarcode_Create();
    strcpy(my_symbol->fgcolour, "nonsense");
    error = ZBarcode_Encode_and_Print(my_symbol, argv[1], 0, 0);
    if (error != 0) {
        /* some warning or error occurred */
        printf("%s\n", my_symbol->errtxt);
    }
    if (error >= ZINT_ERROR) {
        /* stop now */
        ZBarcode_Delete(my_symbol);
        return 1;
    }
    /* otherwise carry on with the rest of the application */
    ZBarcode_Delete(my_symbol);
    return 0;
}

This code will exit with the appropriate message:

Error 653: Malformed foreground colour 'NONSENSE' (hexadecimal only)

To treat all warnings as errors, set symbol->warn_level to WARN_FAIL_ALL.

5.8 Specifying a Symbology

Symbologies can be specified by number or by name as shown in the Table. For example

symbol->symbology = BARCODE_LOGMARS;

means the same as

symbol->symbology = 50;

5.9 Adjusting Other Output Options

The output_options variable can be used to adjust various aspects of the output file. To select more than one option from the table below simply OR them together when adjusting this value:

my_symbol->output_options |= BARCODE_BIND | READER_INIT;
API output_options $
Value Effect
0 No options selected.
BARCODE_BIND Boundary bars above and below the symbol and between rows if stacking multiple symbols.7
BARCODE_BOX Add a box surrounding the symbol and whitespace.
BARCODE_STDOUT Output the file to stdout.
READER_INIT Create as a Reader Initialisation (Programming) symbol.
SMALL_TEXT Use a smaller font for the Human Readable Text.
BOLD_TEXT Embolden the Human Readable Text.
CMYK_COLOUR Select the CMYK colour space option for Encapsulated PostScript and TIF files.
BARCODE_DOTTY_MODE Plot a matrix symbol using dots rather than squares.
GS1_GS_SEPARATOR Use GS instead of FNC1 as GS1 separator (Data Matrix only).
OUT_BUFFER_INTERMEDIATE Return the bitmap buffer as ASCII values instead of separate colour channels (OUT_BUFFER only).
BARCODE_QUIET_ZONES Add compliant quiet zones (additional to any specified whitespace).8
BARCODE_NO_QUIET_ZONES Disable quiet zones, notably those with defaults.
COMPLIANT_HEIGHT Warn if height not compliant and use standard height (if any) as default.

5.10 Setting the Input Mode

The way in which the input data is encoded can be set using the input_mode property. Valid values are shown in the table below.

API input_mode $
Value Effect
DATA_MODE Uses full 8-bit range interpreted as binary data.
UNICODE_MODE Uses UTF-8 input.
GS1_MODE Encodes GS1 data using FNC1 characters.
The above are exclusive, the following optional and OR-ed.
ESCAPE_MODE Process input data for escape sequences.
GS1PARENS_MODE Parentheses (round brackets) used in GS1 data instead of square brackets to delimit Application Identifiers (parentheses must not otherwise occur in the data).
GS1NOCHECK_MODE Do not check GS1 data for validity, i.e. suppress checks for valid AIs and data lengths. Invalid characters (e.g. control characters, extended ASCII characters) are still checked for.
HEIGHTPERROW_MODE Interpret the height variable as per-row rather than as overall height.
FAST_MODE Use faster if less optimal encodation for symbologies that support it (currently DATAMATRIX only).

The default mode is DATA_MODE. (Note that this differs from the default for the CLI and GUI, which is UNICODE_MODE.)

DATA_MODE, UNICODE_MODE and GS1_MODE are mutually exclusive, whereas ESCAPE_MODE, GS1PARENS_MODE, GS1NOCHECK_MODE, HEIGHTPERROW_MODE and FAST_MODE are optional. So, for example, you can set

my_symbol->input_mode = UNICODE_MODE | ESCAPE_MODE;

or

my_symbol->input_mode = GS1_MODE | GS1PARENS_MODE | GS1NOCHECK_MODE;

whereas

my_symbol->input_mode = DATA_MODE | GS1_MODE;

is not valid.

Permissible escape sequences are listed in Table. An example of GS1PARENS_MODE usage is given in section 6.1.10.3 GS1-128.

GS1NOCHECK_MODE is for use with legacy systems that have data that does not conform to the current GS1 standard. Printable ASCII input is still checked for, as is the validity of GS1 data specified without AIs (e.g. linear data for GS1 DataBar Omnidirectional/Limited/etc.).

For HEIGHTPERROW_MODE, see --heightperrow in section 4.4 Adjusting Height. The height variable should be set to the desired per-row value on input (it will be set to the overall height on output).

5.11 Multiple Segments

For input data requiring multiple ECIs, the following functions may be used:

int ZBarcode_Encode_Segs(struct zint_symbol *symbol,
      const struct zint_seg segs[], const int seg_count);

int ZBarcode_Encode_Segs_and_Print(struct zint_symbol *symbol,
      const struct zint_seg segs[], const int seg_count, int rotate_angle);

int ZBarcode_Encode_Segs_and_Buffer(struct zint_symbol *symbol,
      const struct zint_seg segs[], const int seg_count, int rotate_angle);

int ZBarcode_Encode_Segs_and_Buffer_Vector(struct zint_symbol *symbol,
      const struct zint_seg segs[], const int seg_count, int rotate_angle);

These are direct analogues of the previously mentioned ZBarcode_Encode(), ZBarcode_Encode_and_Print(), ZBarcode_Encode_and_Buffer() and ZBarcode_Encode_and_Buffer_Vector() respectively, where instead of a pair consisting of "source, length", a pair consisting of "segs, seg_count" is given, with segs being an array of struct zint_seg segments and seg_count being the number of elements it contains. The zint_seg structure is of the form:

struct zint_seg {
    unsigned char *source; /* Data to encode */
    int length;            /* Length of `source`. If 0, `source` must be
                              NUL-terminated */
    int eci;               /* Extended Channel Interpretation */
};

The symbology must support ECIs (see Table ). For example:

#include <zint.h>
int main(int argc, char **argv)
{
    struct zint_seg segs[] = {
        { "Κείμενο", 0, 9 },
        { "Текст", 0, 7 },
        { "文章", 0, 20 }
    };
    struct zint_symbol *my_symbol;
    my_symbol = ZBarcode_Create();
    my_symbol->symbology = BARCODE_AZTEC;
    my_symbol->input_mode = UNICODE_MODE;
    ZBarcode_Encode_Segs(my_symbol, segs, 3);
    ZBarcode_Print(my_symbol, 0);
    ZBarcode_Delete(my_symbol);
    return 0;
}

A maximum of 256 segments may be specified. Use of multiple segments with GS1 data is not currently supported.

5.12 Verifying Symbology Availability

An additional function available in the API is:

int ZBarcode_ValidID(int symbol_id);

which allows you to check whether a given symbology is available, returning a non-zero value if so. For example:

if (ZBarcode_ValidID(BARCODE_PDF417) != 0) {
    printf("PDF417 available\n");
} else {
    printf("PDF417 not available\n");
}

Another function that may be useful is:

int ZBarcode_BarcodeName(int symbol_id, char name[32]);

which copies the name of a symbology into the supplied name buffer, which should be 32 characters in length. The name is NUL-terminated, and zero is returned on success. For instance:

char name[32];
if (ZBarcode_BarcodeName(BARCODE_PDF417, name) == 0) {
    printf("%s\n", name);
}

will print BARCODE_PDF417.

5.13 Checking Symbology Capabilities

It can be useful for frontend programs to know the capabilities of a symbology. This can be determined using another additional function:

unsigned int ZBarcode_Cap(int symbol_id, unsigned int cap_flag);

by OR-ing the flags below in the cap_flag argument and checking the return to see which are set.

API Capability Flags
Value Meaning
ZINT_CAP_HRT Can the symbology print Human Readable Text?
ZINT_CAP_STACKABLE Is the symbology stackable?
ZINT_CAP_EXTENDABLE Is the symbology extendable with add-on data? (i.e. is it EAN/UPC?)
ZINT_CAP_COMPOSITE Does the symbology support composite data? (see 6.3 GS1 Composite Symbols (ISO 24723) below)
ZINT_CAP_ECI Does the symbology support Extended Channel Interpretations?
ZINT_CAP_GS1 Does the symbology support GS1 data?
ZINT_CAP_DOTTY Can the symbology be outputted as dots?
ZINT_CAP_QUIET_ZONES Does the symbology have default quiet zones?
ZINT_CAP_FIXED_RATIO Does the symbology have a fixed width-to-height (aspect) ratio?
ZINT_CAP_READER_INIT Does the symbology support Reader Initialisation?
ZINT_CAP_FULL_MULTIBYTE Is the ZINT_FULL_MULTIBYTE option applicable?
ZINT_CAP_MASK Is mask selection applicable?
ZINT_CAP_STRUCTAPP Does the symbology support Structured Append?
ZINT_CAP_COMPLIANT_HEIGHT Does the symbology have a compliant height defined?

For example:

unsigned int cap = ZBarcode_Cap(BARCODE_PDF417, ZINT_CAP_HRT | ZINT_CAP_ECI);
if (cap & ZINT_CAP_HRT) {
    printf("PDF417 supports HRT\n");
} else {
    printf("PDF417 does not support HRT\n");
}
if (cap & ZINT_CAP_ECI) {
    printf("PDF417 supports ECI\n");
} else {
    printf("PDF417 does not support ECI\n");
}

5.14 Zint Version

Lastly, the version of the Zint library linked to is returned by:

int ZBarcode_Version();

The version parts are separated by hundreds. For instance, version "2.9.1" is returned as "20901".