1. 程式人生 > >一維碼和二維碼開源庫zint學習

一維碼和二維碼開源庫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在操作過程中,出現記憶體洩漏問題