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:
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:
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;
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.
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.
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".