Zint 教程及示例
Introduction
Zint 是一款优秀的开源的条码生成工具,它跨平台,它支持超过50种条码,囊括目前市场上主流的条码类型,包括 QR、PDF417 等等。Zint 的源码你可以在其 官网首页 找到下载链接。除了源码,你还可以下载到带 Qt 界面的和命令行运行的 zint。我把这些都打包在 这里 了,快来下载啊。
Zint 的编译请参看我上一篇文章 在 Win vs2017 下编译 zint。再重申一遍,Zint本身并不依赖 libpng 和 zlib,除非你想将生成的条码保存为 PNG 格式的图片,否则不需要对 libpng 和 zlib 进行编译,只需要打开 zint 的工程文件,右键生成即可对 zint 进行编译(非常简单,这也说明 zint 对额外的库依赖非常少,这非常棒)。Zint 除了 PNG 格式外,还支持 BMP、SVG、ESP 图片格式。最近做的内容就完全没有用到 libpng 和 zlib,只是利用 zint 生成条码,然后将生成的位图转成 Opencv 的 Mat,对其做一些处理。保存什么的,完全交给 Opencv 了,因此也就不要 ligpng 和 zlib。
开始介绍 Zint 之前,我们先了解下 Zint 中使用到的一些术语,详细内容请看 Terms of Reference,本人对条码技术并不了解,这些术语好几个看不懂,下面只说个人认为比较重要的几个词:
1. Symbol,可以看成是编码之后生成的一张图
2. Symbology,代表一种编码方法。每种条码都有自己的编码标准。
3. Linear,应该是长条状的码,例如条形码。
4. Stacked,包含多个长条状码的码,例如 PDF417
5. Matrix,二维码,包括 QR、Maxicode 等等
6. x-dimension,最小模块的大小,通常是最小模块的宽,因为条码的模块大小有固定的长宽比,通过宽就能计算出长。对于条形码来说,x-dimension 表示一列的宽(像素大小);对于二维码来说,x-dimension 表示一个模块的宽(像素大小)
Show Me the Code
下面介绍 Zint 中常用的 API,以及各种设置
创建和删除Symbol
Symbol 作为 Zint 中最为重要的结构体,它包含所有的设置以及编码后的比特流。注意创建后一定记得要释放。创建和删除方法如下:
int CreateAndDeleteSymbol()
{struct zint_symbol *my_symbol; my_symbol = ZBarcode_Create();if (my_symbol != nullptr){printf("Symbol successfully created!\n");}ZBarcode_Delete(my_symbol);return 0;
}
编码并保存为图片
Zint 支持将编码后的数据保存为图片,利用的 API 主要是下面这些:
// 将 input 前 length 个字符进行编码int ZBarcode_Encode(struct zint_symbol *symbol, unsigned char *input, int length);// 对 filename 中的数据进行编码
int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename);// 将 symbol 中编码后的数据旋转 rotate_angle 度,然后保存为图片
int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle);// 编码、保存一步到位
int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle);// 读取文件、编码、保存一步到位
int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, char *filename, int rotate_angle);
其中, 如果 length=0,那么将编码整个字符串;rotate_angle 有效的角度为 0,90,180,270
因此,编码和保存有多种方法可以选择,具体代码如下:
int EncodingAndSavingToFile()
{struct zint_symbol *my_symbol;my_symbol = ZBarcode_Create();// Set output file namestrcpy_s(my_symbol->outfile, "output.bmp");// Set encode datastring encode_data("hello world");ZBarcode_Encode(my_symbol, (unsigned char*)encode_data.c_str(), 0);int error_num = ZBarcode_Print(my_symbol, 0);if (error_num != 0){/* some error occurred */printf("%s\n", my_symbol->errtxt);}ZBarcode_Delete(my_symbol);return 0;
}
ZBarcode_Encode_File
int Test_ZBarcode_Encode_File()
{struct zint_symbol *my_symbol; my_symbol = ZBarcode_Create();my_symbol->symbology = BARCODE_QRCODE;strcpy_s(my_symbol->outfile, "Test_ZBarcode_Encode_File.bmp");char filename[256] = "hello.txt";int error_num = ZBarcode_Encode_File(my_symbol, filename);if (error_num != 0){/* some error occurred */printf("%s\n", my_symbol->errtxt);}error_num = ZBarcode_Print(my_symbol, 90);if (error_num != 0){/* some error occurred */printf("%s\n", my_symbol->errtxt);}ZBarcode_Delete(my_symbol);return error_num;
}
获取位图
除了将编码后的数据保存为图片外,Zint 还允许我们对这些数据进行像素级别的访问。利用下面几个 API 可以生成位图:
int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle);
int ZBarcide_Encode_and_Buffer(struct zint_symbol *symbol, unsigned char *input,
int length, int rotate_angle);
int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, char *filename,
int rotate_angle);
注意 ZBarcode_Print 和 ZBarcode_Buffer 只能用其中一个,否则 ZBarcode_Delete 会出现异常。搞不懂这算是 Bug 还是规定。
int BufferingSymbolsInMemory()
{struct zint_symbol *my_symbol;my_symbol = ZBarcode_Create();my_symbol->symbology = BARCODE_QRCODE;strcpy_s(my_symbol->outfile, "BufferingSymbolsInMemory.bmp");string encode_data("BufferingSymbolsInMemory");int error_num = ZBarcode_Encode_and_Buffer(my_symbol, (unsigned char*)encode_data.c_str(), 0, 0);int r, g, b;int i = 0;for (int row = 0; row < my_symbol->bitmap_height; ++row){for (int col = 0; col < my_symbol->bitmap_width; ++col){r = my_symbol->bitmap[i];g = my_symbol->bitmap[i + 1];b = my_symbol->bitmap[i + 2];i += 3;if (r == 0 && g == 0 & b == 0){printf("■");}else{printf("□");}}printf("\n");}ZBarcode_Delete(my_symbol);return 0;
}
将位图转换为 Opencv 的 Mat 也非常简单,一句话搞定:
cv::Mat mat(my_symbol->bitmap_height, my_symbol->bitmap_width, CV_8UC3, my_symbol->bitmap)
设置前景色后景色
int Test_fg_bg_color()
{struct zint_symbol *my_symbol;my_symbol = ZBarcode_Create();my_symbol->symbology = BARCODE_QRCODE;strcpy_s(my_symbol->fgcolour, "00ff00");strcpy_s(my_symbol->bgcolour, "f0f00f");strcpy_s(my_symbol->outfile, "Test_fg_bg_color.bmp");string encode_data("Test_fg_bg_color");int error_num = ZBarcode_Encode(my_symbol, (unsigned char*)encode_data.c_str(), 0);error_num = ZBarcode_Print(my_symbol, 0);ZBarcode_Delete(my_symbol);return 0;
}
设置边缘留白
边缘留白有两种:border_width 和 whitespace_width。区别在于 border_width 为上下左右统统留白,whitespace_width只留两边。此外,其单位是 x-dimension。
int Test_whitespace_width()
{struct zint_symbol *my_symbol;my_symbol = ZBarcode_Create();my_symbol->symbology = BARCODE_QRCODE;my_symbol->border_width = 20; // 20 个 x-dimension 大小strcpy_s(my_symbol->outfile, "Test_whitespace_width.bmp");// Set encode datastring encode_data("Test_whitespace_width");ZBarcode_Encode(my_symbol, (unsigned char*)encode_data.c_str(), 0);int error_num = ZBarcode_Print(my_symbol, 0);if (error_num != 0){/* some error occurred */printf("%s\n", my_symbol->errtxt);}ZBarcode_Delete(my_symbol);return 0;
}
放大(设置模块大小)
Zint 生成图片的大小不能直接指定,而是通过对最小模块的尺寸调整,等到不同大小的图片。设置 scale 可以对模块大小进行放大或者缩小。
int Test_scale()
{struct zint_symbol *my_symbol;my_symbol = ZBarcode_Create();my_symbol->symbology = BARCODE_QRCODE;my_symbol->scale = 5;strcpy_s(my_symbol->outfile, "Test_scale.bmp");string encode_data("Test_scale");int error_num = ZBarcode_Encode(my_symbol, (unsigned char*)encode_data.c_str(), 0);error_num = ZBarcode_Print(my_symbol, 0);ZBarcode_Delete(my_symbol);return 0;
}
其他
以上为常用功能,更多设置请参考官网设置,或者下载 Zint开发手册,进行查看。
开发手册详细的说明针对不同码,进行不同的设置,例如对于 QR 码,可以进行设置纠错等级,设置版本等等。