一維碼和二維碼開源庫zint學習
一、資源下載
zint本來是可以不需要任何其他庫(libpng和zlib)的支援,但是如果希望zint能夠生成PNG格式的圖片,那麼就需要libpng的支援,而libpng需要zlib的支援。
zint下載:https://github.com/zint/zint
libpng庫下載:https://sourceforge.net/projects/libpng/files/libpng16/
zlib下載:https://sourceforge.net/projects/zlib/
二、編譯zint
環境:Win7 64位系統,VS2015編譯平臺
2.1、依賴庫libpng和zlib的編譯
libpng版本為最新版本1.6.35,zlib版本為最新版本1.2.11。libpng資源解壓後,根目錄中會出現一個projects的資料夾,在\projects\vstudio目錄下,找到VS2010的工程檔案vstudio.sln。
2.1.1 、靜態庫zlib編譯
執行vstudio.sln工程,工程中包含7個子工程,其中zlib和libpng是我們需要編譯的。由於libpng需要zlib庫的支援,我們先要編譯zlib庫,zlib庫的配置是一個靜態庫(可以在工程的屬性中檢視得知)。
首次編譯,應該是會出現下面的錯誤:
分析上面的錯誤可知,工程的原始碼檔案在“…\zlib-1.2.8\”目錄中找不到,找不到是正常的,我們確實沒有這個資料夾以及相關的檔案,libpng庫中沒有包含zlib所需要的原始碼檔案。
將下載的zlib庫資源解壓,在根目錄下會找到上面所需要的所有原始碼檔案。刪除zint工程中不存在的那些檔案條目,然後新增我們下載的zlib庫資源中的檔案,如下圖所示,
然後再編譯,應該會成功產生一個靜態庫檔案zlib.lib。
2.1.2、libpng庫編譯
在上面的VS工程中,選中libpng子工程,直接編譯,會出現“找不到zlib.h檔案”的錯誤。需要將zlib.h的目錄包含到libpng工程中去,如下圖所示,
然後再編譯, 應該會成功產生一個libpng16.dll和libpng6.lib檔案。
2.2、zint庫編譯
zint版本為2.6.1。
解壓後,在根目錄下找到win32資料夾,開啟zint.sln工程,整個工程包含兩個子專案:zint和libzint。zint為測試專案,libzint為庫專案,我們重點關注libzint專案。
在工程中選中libzint,直接編譯。初次編譯,應該可以成功生成一個libzint.dll和libzint.lib檔案,在不需要生成PNG圖片的程式中,這個zint庫檔案就滿足要求了。但是,如果要在程式中生成PNG格式的條碼圖片時,則需要在libzint專案中加入libpng庫檔案。步驟如下,
- 去掉libzint專案中的預編譯頭NO_PNG。選中libzint屬性【配置屬性 - C/C++ - 前處理器】,前處理器定義中去掉NO_PNG條目即可;
- 新增libpng和zlib庫檔案。根據libzint專案屬性中的配置目錄,在win32的同一級別目錄中建立extern\libpng\include\、extern\libpng\lib\x86\、extern\zlib\include\,extern\zlib\lib\x86\四個資料夾,並將2.1中生成的相應的檔案拷貝進去,
extern\libpng\include\ : png.h,pngconf.h,pnglibconf.h,zconf.h
extern\libpng\lib\x86\ : libpng16.lib
extern\zlib\include\ : zlib.h
extern\zlib\lib\x86\ : zlib.lib - 將libpng16.dll放到目標檔案生成目錄中。
然後再次編譯,就會生成支援PNG的libzint.dll和libzint.lib檔案。
三、簡單示例
在程式中使用zint庫檔案,需要上面編譯生成的幾個檔案:zint.h,libzint.lib,libpng16.dll,libzint.dll
如何在程式中使用DLL?
#include "stdafx.h"
#include <iostream>
#include "zint.h"
using namespace std;
#pragma comment(lib, "libzint.lib")
int main()
{
// Create symbol
zint_symbol * pSymbol = ZBarcode_Create();
if (nullptr == pSymbol)
{
cout << "Symbol create fail !" << endl;
}
else
{
cout << "Symbol create success !" << endl;
}
cout << "zint version:" << ZBarcode_Version() << endl;
// 改變條碼前景色
strcpy(pSymbol->fgcolour, "00FF00");
// 改變條碼背景色
strcpy(pSymbol->bgcolour, "000000");
// 改變圖片路徑
strcpy(pSymbol->outfile, "images/out2.png");
pSymbol->scale = 1;
//strcpy(pSymbol->primary, "999999999840012");
//pSymbol->output_options = BARCODE_BOX | BARCODE_BIND;
//pSymbol->whitespace_width = 1;
//pSymbol->border_width = 1;
pSymbol->symbology = BARCODE_AZTEC;
pSymbol->option_1 = 2;
pSymbol->option_2 = 0; // 條碼的大小
pSymbol->option_3 = 928;
//pSymbol->option_3 = DM_SQUARE; //
// Encoding and saving to file
//char buff[1024];
//memset(buff, 0, 1024);
//cout << "請輸入條碼的內容:";
//cin >> buff;
// ZBarcode_Encode(pSymbol, (unsigned char *)buff, 0);
// ZBarcode_Print(pSymbol, 0);
// ZBarcode_Encode_and_Print(pSymbol, (unsigned char *)buff, 0, 90);
int error = 0;
error = ZBarcode_Encode_and_Print(pSymbol, (unsigned char *)"1234567", 0, 0);
if (error != 0)
{
cout << "Error: " << pSymbol->errtxt << endl;
}
if (error > ZINT_WARN_INVALID_OPTION)
{
ZBarcode_Delete(pSymbol);
getchar();
return 1;
}
// ZBarcode_Delete(pSymbol);
// ZBarcode_Encode_and_Buffer(pSymbol, (unsigned char *)buff, 0, 0);
//int i = 0;
//for (int row = 0; row < pSymbol->bitmap_height; row++)
//{
// for (int col = 0; col < pSymbol->bitmap_width; col++)
// {
// int red = pSymbol->bitmap[i];
// int green = pSymbol->bitmap[i + 1];
// int blue = pSymbol->bitmap[i + 2];
// cout << "(" << red << "," << green << "," << blue << ")" << ",";
// i += 3;
// }
// cout << endl;
//}
ZBarcode_Delete(pSymbol);
getchar();
return 0;
}
四、QT介面的zint操作工具
zint庫中,還提供了基於QT的介面操作工具原始碼。分為兩個工程,一個是靜態庫工程backend_qt,一個是exe工程frontend_qt。下面詳細講述如何編譯。
4.1、編譯backend_qt
在根目錄中,找到backend_qt資料夾,在QtCreator中開啟backend_qt.pro工程,直接編譯,會發現找不到“png.h”檔案,這個與上面的編譯錯誤是一致的,就是工程目錄配置不正確。正確配置一下即可,如下圖所示,
再次編譯,應該能夠成功產生一個靜態庫QtZint.lib檔案。
4.2、編譯frontend_qt
在根目錄中,找到frontend_qt資料夾,在QtCreator中開啟frontend_qt.pro工程,直接編譯,會出現找不到QtZint.lib庫,libpng16.lib庫、zlib.lib庫。同樣,這也是由於工程目錄配置不正確的原因,如下圖所示,
因為libpng是DLL庫,所以還需要將對應的libpng.dll放在frontend_qt目標檔案目錄中。
最後編譯可以通過,當時執行會出現CrtIsValidHeapPointer錯誤,猜測是由於DLL版本不匹配引起的,但是最終還是沒有找到原因。這裡提供一個編譯成功的exe檔案和zint開發手冊連結地址:https://pan.baidu.com/s/1ncJIod01xB0yVS6hZhK-oQ,提取碼:yev9
五、開發應用
1、zint_symbol解析
zint_symbol結構體的定義位於zint.h檔案中,詳細說明見如下表格
變數名稱 | 型別 | 含義 | 預設值 |
---|---|---|---|
symbology | integer | 條碼型別(詳細見zint.h宣告) | BARCODE_CODE128 |
height | integer | 條碼的高度 ,詳細參考注意第一點 | 50 |
whitespace_width | integer | 左右空白的寬度 | 0 |
border_width | integer | 邊框的寬度 | 0 |
output_options | integer | 條碼是否新增邊框或邊界線 | (none) |
fgcolour | character string | 條碼前景顏色,格式為RGB16進位制的字串,例如,綠色“00FF00” | “000000” |
bgcolour | character string | 條碼背景顏色,格式與fgcolour一致 | “FFFFFF” |
outfile | character string | 條碼圖片輸出的檔案路徑,包含檔名和字尾(所指定的路徑必須已經存在) | “out.png” |
option_1 | integer | 一般為校驗等級,具體見zint開發文件 | (automatic) |
option_2 | integer | 一般為版本大小,具體見zint開發文件 | (automatic) |
option_2 | integer | 具體見zint開發文件 | (automatic) |
scale | float | 條形碼尺寸的縮放因子 | 1.0 |
input_mode | integer | BINARY_MODE | |
primary | character string | 對於許多複雜的條形碼,顯示主要的資訊 | NULL |
text | unsigned character string | NULL | |
rows | integer | BARCODE_CODE128 | |
width | integer | 條碼的寬度 | 只讀 |
encoding_data | array of character string | 條碼編碼資料的描述 | 只讀 |
row_height | array of | integers | 條碼一行的高度 |
errtxt | character string | 錯誤資訊 | 只讀 |
bitmap | pointer to character array | 指向圖片中的條碼點陣圖資訊 | 只讀 |
bitmap_width | integer | 條碼點陣圖的畫素寬度 | 只讀 |
bitmap_height | integer | 條碼點陣圖的畫素高度 | 只讀 |
注意:1、當條碼型別為下面這些條碼時,忽略高度:
Australia Post 4-State Barcodes, PostNet, PLANET, USPS OneCode,RM4SCC, PDF417, Data Matrix, Maxicode, QR Code, GS1 DataBar-14 Stacked, PDF417,MicroPDF417
2、當條碼型別為Code 16k 和 ITF-14 symbols時,忽略輸出選項
3、whitespace_width,空白的寬度,只會增加條碼左右兩側的空白
4、border_width,邊框寬度。如果output_options沒有設定邊框,設定了border_width,條碼周圍也會出現空白邊框
2、錯誤資訊
返回值 | 含義 |
---|---|
WARN_INVALID_OPTION | zint_symbol結構體中某個變數設定錯誤,但是程式通過猜測變數應該是什麼內容,而去生成一個條形碼 |
ERROR_TOO_LONG | 輸入的資料過長或者過短,不會產生條碼 |
ERROR_INVALID_DATA | 輸入的資料中包含被條碼禁止的字元(比如,在EAN條形碼中輸入字母),不會產生條碼 |
ERROR_INVALID_CHECK | ISBN型別條碼中被輸入一個錯誤的校驗碼,不會產生條碼 |
ERROR_INVALID_OPTION | zint_symbol結構體中某個變數設定錯誤,程式不能猜測變數應該是什麼內容,不會產生條碼 |
ERROR_ENCODING_PROBLEM | 編碼錯誤,一般不會產生這個錯誤 |
ERROR_FILE_ACCESS | 當採用讀取檔案的方式去獲取字元時,如果zint沒有許可權去操作指定的檔案,就會出錯 |
ERROR_MEMORY | zint在操作過程中,出現記憶體洩漏問題 |