當下因微信和支付寶等手機應用廣泛使用,而基于二維碼/一維條碼的移動支付,也借助手機移動端席卷全國,使得越來越多的人知道有“二維碼”這么一種東西。
對于普通用戶而來,一般只知道將自己的二維碼展示給別人,別人使用軟件識別這個二維碼即可完成一定的功能。比如,掃碼二維碼付款、掃碼二維碼加微信好友、掃碼二維碼訪問網頁、掃碼二維碼下載app等等。這些個功能,在日常行為中,已經很常見了,但作為程序猿的我們,我們怎么能不知道二維碼是如何生成的呢?或者說,我要自己生成一個二維碼,除了去網頁上找二維碼生成工具來生成,我可以自己編碼來實現么?
答案,當然是,必須可以。不然這文章不用寫了。
在介紹如何用代碼生成二維碼之前,就不得不先介紹一個開源庫叫zint。這個開源可謂牛叉的很,幾乎平時見過的“碼”,各式各樣的一維條碼、各式各樣的二維碼條碼都難不倒它,重要的是,它還是開源的,幾乎包含了所有常見“碼”的生成。以下是摘自官方用戶使用手冊的介紹片段。(筆者上一篇博文介紹zint的安裝時簡單介紹了一下zint庫,如何在linux平臺安裝zint開源庫 - 架構師李肯 - 博客園,它的開源項目網頁為Zint Barcode Generator download | SourceForge.net)
The Zint project aims to provide a complete cross-platform open source barcode generating solution. The package currently consists of a Qt based GUI, a command line executable and a library with an API to allow developers access to the capabilities of Zint. It is hoped that Zint provides a solution which is flexible enough for professional users while at the same time takes care of as much of the processing as possible to allow easy translation from input data to barcode image.
-----------------------------------------------------華麗麗的分割線-----------------------------------------------------
言歸正傳,說回如何使用zint庫生成二維碼。主要使用到以下幾個函數:可以從zint.h中得到api的聲明(主要是C語言的接口)。
ZINT_EXTERN struct zint_symbol* ZBarcode_Create(void);
ZINT_EXTERN void ZBarcode_Clear(struct zint_symbol *symbol);
ZINT_EXTERN void ZBarcode_Delete(struct zint_symbol *symbol);
ZINT_EXTERN int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle);
以下是個人封裝的生成二維碼的自定義接口函數:
/****************************************************************************
Descpribe: Create Qrcode API with C Code by calling zint lib.
Input : pQrCodeData, the qrcode data buf
QrcodeLen, the len of qrcode data, but it can be 0
pQrCodeFile, the output file name of qrcode, it can be NULL
Output : pZintRet, to store the ret code from linzint.
Return : 0 is ok, and other values are fail. See the meanings in enum ZINT_RET_CODE
Notes : pQrCodeFile, Must end in .png, .eps or .svg. when isn,t NULL string.
****************************************************************************/
ZINT_RET_CODE Zint_Create_QrCode(uint8_t *pQrCodeData, int QrcodeLen, char *pQrCodeFile, int *pZintRet);
這個接口定義比較簡單,上面也簡單說了各個參數的意義,其他中特別需要注意的是,如果傳入生成二維碼圖片名字不使用默認值時(pQrCodeFile != NULL),也務必保證pQrCodeFile必須是以.png, .eps or .svg.結尾的文件名。
以下是zint_code.c 和 zint_code.h的內容,里面將zint中生成二維碼的幾個函數封裝在一塊了,使用者只需關注上面定義的Zint_Create_QrCode函數,即可生成漂亮的二維碼圖片文件。
?
1 /****************************************************************************
2 * File : zint_code.c
3 *
4 * Copyright (c) 2011 by Li.Recan < 721317716@qq.com >
5 *
6 * DESCRIPTION: Demo for creating qrcode by C code.
7 *
8 * Modification history
9 * --------------------------------------------------------------------------
10 * Date Version Author History
11 * --------------------------------------------------------------------------
12 * 2016-10-15 1.0.0 Li.Recan written
13 ***************************************************************************/
14
15 // Standard Library
16 #include
17 #include
18
19 // so Library
20 #include "zint.h"
21
22 // Project Header
23 #include "zint_code.h"
24
25
26 /****************************************************************************
27 Descpribe: Create Qrcode API with C Code by calling zint lib.
28 Input : pQrCodeData, the qrcode data buf
29 QrcodeLen, the len of qrcode data, but it can be 0
30 pQrCodeFile, the output file name of qrcode, it can be NULL
31 Output : pZintRet, to store the ret code from linzint.
32 Return : 0 is ok, and other values are fail. See the meanings in enum ZINT_RET_CODE
33 Notes : pQrCodeFile, Must end in .png, .eps or .svg. when isn,t NULL string.
34 ****************************************************************************/
35 ZINT_RET_CODE Zint_Create_QrCode(uint8_t *pQrCodeData, int QrcodeLen, char *pQrCodeFile, int *pZintRet)
36 {
37 struct zint_symbol *pMySymbol = NULL;
38 int RetCode = 0;
39
40 if(!pQrCodeData) //check input pointer
41 {
42 return ZINT_ERR_INV_DATA;
43 }
44
45 if(QrcodeLen == 0)
46 {
47 QrcodeLen = strlen((char *)pQrCodeData);
48 }
49 if(QrcodeLen > QRCODE_MAX_LEN)//len is too long
50 {
51 return ZINT_ERR_TOO_LONG;
52 }
53
54 if(0 == ZBarcode_ValidID(BARCODE_QRCODE))
55 {
56 return ZINT_ERR_INV_CODE_ID;
57 }
58
59 pMySymbol = ZBarcode_Create();
60 if(pMySymbol == NULL)
61 {
62 return ZINT_ERR_MEMORY;
63 }
64
65 if(pQrCodeFile)//when it's NULL, outfile will be "out.png"
66 {
67 if(strstr(pQrCodeFile, "png") || (strstr(pQrCodeFile, "eps")) || (strstr(pQrCodeFile, "svg")))
68 {
69 strcpy(pMySymbol->outfile, pQrCodeFile);
70 }
71 else
72 {
73 ZBarcode_Clear(pMySymbol);
74 ZBarcode_Delete(pMySymbol); //release memory in zint lib
75 return ZINT_ERR_FILE_NAME;
76 }
77 }
78 pMySymbol->symbology = BARCODE_QRCODE;
79 pMySymbol->option_1 = 3; //ECC Level.It can be large when ECC Level is larger.(value:1-4)
80 pMySymbol->scale = 4; //contorl qrcode file size, default is 1, used to be 4
81 pMySymbol->border_width = 2; //set white space width around your qrcode and 0 is for nothing
82
83 RetCode = ZBarcode_Encode_and_Print(pMySymbol, pQrCodeData, QrcodeLen, 0);
84 ZBarcode_Clear(pMySymbol);
85 ZBarcode_Delete(pMySymbol); //release memory in zint lib
86
87 if(pZintRet)
88 {
89 *pZintRet = RetCode; //save ret code from zint lib
90 }
91
92 return ((0 == RetCode) ? (ZINT_OK) : (ZINT_ERR_LIB_RET));
93 }
View Code: zint_code.c
1 /****************************************************************************
2 * File : zint_code.h
3 *
4 * Copyright (c) 2011 by Li.Recan < 721317716@qq.com >
5 *
6 * DESCRIPTION: API for creating qrcode by C code.
7 *
8 * Modification history
9 * --------------------------------------------------------------------------
10 * Date Version Author History
11 * --------------------------------------------------------------------------
12 * 2016-10-15 1.0.0 Li.Recan written
13 ***************************************************************************/
14
15 #ifndef __ZINT_CODE__
16 #define __ZINT_CODE__
17
18 #ifdef __cplusplus
19 extern "C"
20 {
21 #endif
22
23 #include
24
25 #define QRCODE_MAX_LEN 500 //max string len for creating qrcode
26
27 typedef enum
28 {
29 ZINT_OK = 0,
30 ZINT_ERR_INV_DATA = -1, //input invalid data
31 ZINT_ERR_TOO_LONG = -2, //len for input data is too long
32 ZINT_ERR_INV_CODE_ID = -3,//the code type is not supported by zint
33 ZINT_ERR_MEMORY = -4, //malloc memory error in zint lib
34 ZINT_ERR_FILE_NAME = -5, //qrcode file isn'y end in .png, .eps or .svg.
35 ZINT_ERR_LIB_RET = -6, //zint lib ret error, real ret code should be zint api ret code
36 }ZINT_RET_CODE;
37
38 /****************************************************************************
39 Descpribe: Create Qrcode API with C Code by calling zint lib.
40 Input : pQrCodeData, the qrcode data buf
41 QrcodeLen, the len of qrcode data, but it can be 0
42 pQrCodeFile, the output file name of qrcode, it can be NULL
43 Output : pZintRet, to store the ret code from linzint.
44 Return : 0 is ok, and other values are fail. See the meanings in enum ZINT_RET_CODE
45 Notes : pQrCodeFile, Must end in .png, .eps or .svg. when isn,t NULL string.
46 ****************************************************************************/
47 ZINT_RET_CODE Zint_Create_QrCode(uint8_t *pQrCodeData, int QrcodeLen, char *pQrCodeFile, int *pZintRet);
48
49 #define Debuging(fmt, arg...) printf("[%20s, %4d] "fmt, __FILE__, __LINE__, ##arg)
50
51 #ifdef __cplusplus
52 }
53 #endif
54
55 #endif /* __ZINT_CODE__ */
?
在工程實踐中,只需要將這兩個文件添加到工程中,并讓他們參與工程編譯,即可完美使用zint生成二維碼了。
下面是一個簡單的demo,將會展示如何使用這個接口函數,見qrcode_test.c
/****************************************************************************
2 * File : qrcode_test.c
3 *
4 * Copyright (c) 2011 by Li.Recan < 721317716@qq.com >
5 *
6 * DESCRIPTION: Demo for creating qrcode by C code.
7 *
8 * Modification history
9 * --------------------------------------------------------------------------
10 * Date Version Author History
11 * --------------------------------------------------------------------------
12 * 2016-10-15 1.0.0 Li.Recan written
13 ***************************************************************************/
14
15 // Standard Library
16 #include
17
18 // Project Header
19 #include "zint_code.h"
20
21 int main(int argc, char *argv[])
22 {
23 int ZintLibRet = 0; //ret code from zint lib
24 ZINT_RET_CODE ZintRet = 0; //ret code from zint_code api
25 char QrcodeData[] = "I love zint lib. 測試一下gbk編碼 ...";
26 char QrcodeDataDef[] = "This's default qrcode file name : out.png ";
27 char QrcodeFile[] = "MyQrcode.png"; // Must end in .png, .eps or .svg. //zint lib ask !
28
29 //test with inputing qrcode_file name
30 ZintRet = Zint_Create_QrCode((uint8_t*)QrcodeData, 0, QrcodeFile, &ZintLibRet);
31 if(ZINT_OK != ZintRet)
32 {
33 Debuging("Create qrcode err, ZintRet = %d, ZintLibRet = %d\n", ZintRet, ZintLibRet);
34 }
35 else
36 {
37 Debuging("Create qrcode OK ! View qrcode file : %s in cur path. ZintRet = %d, ZintLibRet = %d\n", QrcodeFile, ZintRet, ZintLibRet);
38 }
39
40 //test without inputing qrcode_file name
41 ZintRet = Zint_Create_QrCode((uint8_t*)QrcodeDataDef, 0, NULL, &ZintLibRet);
42 if(ZINT_OK != ZintRet)
43 {
44 Debuging("Create qrcode err, ZintRet = %d, ZintLibRet = %d\n", ZintRet, ZintLibRet);
45 }
46 else
47 {
48 Debuging("Create qrcode OK ! View qrcode file : out.png in cur path. ZintRet = %d, ZintLibRet = %d\n", ZintRet, ZintLibRet);
49 }
50
51 return 0;
52 }
輸入完成后,使用gcc -o qrcode_test qrcode_test.c zint_code.c –lzint 即可編譯出qrcode_test的bin文件了。
等等,如果你的linux還未安裝zint庫,sorry,你將看到
那么趕緊回到上一篇博文 如何在linux平臺安裝zint開源庫 - 架構師李肯 - 博客園 把zint安裝起來吧。
準確無誤的編譯,之后,在當前目錄ls就可以看到qrcode_test的bin文件了。
我們使用./ qrcode_test運行我們編譯出來的demo程序,可以看到以下的提示:
[liluchang@localhost src]$ ./qrcode_test
./qrcode_test: error while loading shared libraries: libzint.so.2.4: cannot
open shared object file: No such file or directory
又出什么問題了,原來系統在運行這個demo程序時,沒有找到libzint.so來鏈接,那么我們只需要在運行之前告訴系統去哪里找這個so即可。使用
export LD_LIBRARY_PATH=/usr/local/lib 這個路徑是根據情況而定的。【注意這個export只對當前運行的shell生效,一旦切換一個shell,則需要重新輸入。如果需要固定告訴運行demo的時候去哪里找so鏈接,則可以在編譯的時候告訴它。這個點往后再介紹。】
之后再運行demo程序:
第一個框框里面是demo程序打印出來的調試信息,標識連個二維碼都生成成功了。
第二個框框可以看到,在當前目錄下,就已經生成了這兩個png文件,并且第二個生成的使用的是系統默認的名字out.png。
為了驗證程序生成的二維碼是否正確,我們可以使用手機去掃碼一下這兩個二維碼:
為了驗證程序生成的二維碼是否正確,我們可以使用手機去掃碼一下這兩個二維碼:
用手機掃描出來的結果如下:
?編輯
圖中顯示的掃描結果,正好如demo中寫的
證明這代碼是可行的。
好了,本篇介紹使用C語言調用zint庫生成二維碼的教程就介紹到這里。感興趣的童鞋可以評論留言或者自行閱讀zint用戶手冊或開源項目介紹網頁詳細內容。
后話,下篇文章將介紹zint庫一維條碼的生成,敬請期待。屆時,zint_code.c的接口又豐富一些了。
-
C語言
+關注
關注
180文章
7605瀏覽量
136906
發布評論請先 登錄
相關推薦
評論