如何用C代码生成一维码
如何用C代码生成一维码
如何用C代码生成一维码
前面的文章《如何用C代码生成二维码》中已经介绍过了libzint开源库,我们也见识到了它的便捷性。本文将以如何生成一维码为核心,浅谈其他的实现方式和代码技巧。
《如何用C代码生成二维码》文章中已经介绍了,我们通过自行封装zint开源库处理的接口函数如下:
/****************************************************************************
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);
类似地,我们生成一维码的接口函数也相近,如下所示:
/****************************************************************************
Descpribe: Create Barcode API with C Code by calling zint lib.
Input : pBarCodeData, the barcode data buf
BarcodeLen, the len of barcode data, but it can be 0
pBarCodeFile, the output file name of barcode, 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 : pBarCodeFile, Must end in .png, .eps or .svg. when isn,t NULL string.
****************************************************************************/
ZINT_RET_CODE Zint_Create_BarCode(uint8_t *pBarCodeData, int BarcodeLen, char *pBarCodeFile, int *pZintRet);
两者几乎是一个模板刻出来的,可想而知,其内部实现,自然也是逻辑都是差不多的,都是调用到libzint中的:
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);
等等函数。于是,我们就在想,可以把调用libzint库中的函数封装成一个共用的功能函数,然后生成一维码和生产二维码的函数都通过传不同的参数进去,让这个共用的功能函数走不同case就可以完成相应的功能了。于是我们开始改造zint_code.c,将这个功能函数提出取出来,命名为 ZINT_RET_CODE Zint_Create_Code_File(STR_ZINT_CODE *ZintCodeObj);
通过这个功能函数的入口,我们可以知道,我们定义了一个STR_ZINT_CODE结构体,里面的成员变量如下所列:
typedef struct
{
uint8_t *pCodeData;
int CodeLen;
char *pCodeFile;
CODE_TYPE CodeType;
int MaxCodeLen;
int *pZintRet;
}STR_ZINT_CODE; //struct for create code file
这样我们就可以通过入参控制Zint_Create_Code_File函数来执行不同的生成功能了。
以下是改造后的zint_code.c和zint_code.h
1 /**************************************************************************** 2 * File : zint_code.c 3 * 4 * Copyright (c) 2011 by Li.Recan < [email protected] > 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 <string.h> 17 #include <stdio.h> 18 19 // so Library 20 #include "zint.h" 21 22 // Project Header 23 #include "zint_code.h" 24 25 26 /**************************************************************************** 27 Descpribe: Create Code file API with C Code by calling zint lib. 28 It's a common api for create barcode or qrcode. 29 Input : ZintCodeObj, the zint create code file object 30 Output : ZintCodeObj, the zint create code file object 31 Return : 0 is ok, and other values are fail. See the meanings in enum ZINT_RET_CODE 32 Notes : null 33 ****************************************************************************/ 34 ZINT_RET_CODE Zint_Create_Code_File(STR_ZINT_CODE *ZintCodeObj) 35 { 36 struct zint_symbol *pMySymbol = NULL; 37 int RetCode = 0; 38 int CodeTypeIn = 0; 39 40 if(!ZintCodeObj) //check input pointer 41 { 42 return ZINT_ERR_INV_DATA; 43 } 44 45 //check code type 46 if(ZINT_BARCODE == ZintCodeObj->CodeType) 47 { 48 CodeTypeIn = BARCODE_CODE128; 49 } 50 else if(ZINT_QRCODE == ZintCodeObj->CodeType) 51 { 52 CodeTypeIn = BARCODE_QRCODE; 53 } 54 55 if(ZintCodeObj->CodeLen == 0) 56 { 57 ZintCodeObj->CodeLen = strlen((char *)ZintCodeObj->pCodeData); 58 } 59 if(ZintCodeObj->CodeLen > ZintCodeObj->MaxCodeLen)//len is too long 60 { 61 return ZINT_ERR_TOO_LONG; 62 } 63 64 if(0 == ZBarcode_ValidID(CodeTypeIn)) 65 { 66 return ZINT_ERR_INV_CODE_ID; 67 } 68 69 pMySymbol = ZBarcode_Create(); 70 if(pMySymbol == NULL) 71 { 72 return ZINT_ERR_MEMORY; 73 } 74 75 if(ZintCodeObj->pCodeFile)//when it's NULL, outfile will be "out.png" 76 { 77 if(strstr(ZintCodeObj->pCodeFile, "png") || (strstr(ZintCodeObj->pCodeFile, "eps")) || (strstr(ZintCodeObj->pCodeFile, "svg"))) 78 { 79 strcpy(pMySymbol->outfile, ZintCodeObj->pCodeFile); 80 } 81 else 82 { 83 ZBarcode_Clear(pMySymbol); 84 ZBarcode_Delete(pMySymbol); //release memory in zint lib 85 return ZINT_ERR_FILE_NAME; 86 } 87 } 88 pMySymbol->symbology = CodeTypeIn; 89 if(BARCODE_QRCODE == CodeTypeIn) // special for qrcode 90 { 91 pMySymbol->option_1 = 3; //ECC Level.It can be large when ECC Level is larger.(value:1-4) 92 pMySymbol->scale = 4; //contorl qrcode file size, default is 1, used to be 4 93 } 94 pMySymbol->border_width = 2; //set white space width around your qrcode and 0 is for nothing 95 96 RetCode = ZBarcode_Encode_and_Print(pMySymbol, ZintCodeObj->pCodeData, ZintCodeObj->CodeLen, 0); 97 ZBarcode_Clear(pMySymbol); 98 ZBarcode_Delete(pMySymbol); //release memory in zint lib 99 100 if(ZintCodeObj->pZintRet) 101 { 102 *(ZintCodeObj->pZintRet) = RetCode; //save ret code from zint lib 103 } 104 105 return ((0 == RetCode) ? (ZINT_OK) : (ZINT_ERR_LIB_RET)); 106 } 107 108 /**************************************************************************** 109 Descpribe: Create Barcode API with C Code by calling zint lib. 110 Input : pBarCodeData, the barcode data buf 111 BarcodeLen, the len of barcode data, but it can be 0 112 pBarCodeFile, the output file name of barcode, it can be NULL 113 Output : pZintRet, to store the ret code from linzint. 114 Return : 0 is ok, and other values are fail. See the meanings in enum ZINT_RET_CODE 115 Notes : pBarCodeFile, Must end in .png, .eps or .svg. when isn,t NULL string. 116 ****************************************************************************/ 117 ZINT_RET_CODE Zint_Create_BarCode(uint8_t *pBarCodeData, int BarcodeLen, char *pBarCodeFile, int *pZintRet) 118 { 119 STR_ZINT_CODE ZintCodeObj; 120 121 memset(&ZintCodeObj, 0, sizeof(STR_ZINT_CODE)); 122 ZintCodeObj.pCodeData = pBarCodeData; 123 ZintCodeObj.CodeLen = BarcodeLen; 124 ZintCodeObj.pCodeFile = pBarCodeFile; 125 ZintCodeObj.pZintRet = pZintRet; 126 127 ZintCodeObj.CodeType = ZINT_BARCODE; 128 ZintCodeObj.MaxCodeLen = BARCODE_MAX_LEN; 129 130 return Zint_Create_Code_File(&ZintCodeObj); 131 } 132 133 /**************************************************************************** 134 Descpribe: Create Qrcode API with C Code by calling zint lib. 135 Input : pQrCodeData, the qrcode data buf 136 QrcodeLen, the len of qrcode data, but it can be 0 137 pQrCodeFile, the output file name of qrcode, it can be NULL 138 Output : pZintRet, to store the ret code from linzint. 139 Return : 0 is ok, and other values are fail. See the meanings in enum ZINT_RET_CODE 140 Notes : pQrCodeFile, Must end in .png, .eps or .svg. when isn,t NULL string. 141 ****************************************************************************/ 142 ZINT_RET_CODE Zint_Create_QrCode(uint8_t *pQrCodeData, int QrcodeLen, char *pQrCodeFile, int *pZintRet) 143 { 144 STR_ZINT_CODE ZintCodeObj; 145 146 memset(&ZintCodeObj, 0, sizeof(STR_ZINT_CODE)); 147 ZintCodeObj.pCodeData = pQrCodeData; 148 ZintCodeObj.CodeLen = QrcodeLen; 149 ZintCodeObj.pCodeFile = pQrCodeFile; 150 ZintCodeObj.pZintRet = pZintRet; 151 152 ZintCodeObj.CodeType = ZINT_QRCODE; 153 ZintCodeObj.MaxCodeLen = QRCODE_MAX_LEN; 154 155 return Zint_Create_Code_File(&ZintCodeObj); 156 }
1 /**************************************************************************** 2 * File : zint_code.h 3 * 4 * Copyright (c) 2011 by Li.Recan < [email protected] > 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 <stdint.h> 24 25 #define QRCODE_MAX_LEN 500 //max string len for creating qrcode 26 #define BARCODE_MAX_LEN 100 //max string len for creating barcode 27 28 typedef enum 29 { 30 ZINT_OK = 0, 31 ZINT_ERR_INV_DATA = -1, //input invalid data 32 ZINT_ERR_TOO_LONG = -2, //len for input data is too long 33 ZINT_ERR_INV_CODE_ID = -3,//the code type is not supported by zint 34 ZINT_ERR_MEMORY = -4, //malloc memory error in zint lib 35 ZINT_ERR_FILE_NAME = -5, //qrcode file isn'y end in .png, .eps or .svg. 36 ZINT_ERR_LIB_RET = -6, //zint lib ret error, real ret code should be zint api ret code 37 }ZINT_RET_CODE; 38 39 typedef enum 40 { 41 ZINT_BARCODE = 1, //barcode type 42 ZINT_QRCODE = 2, //qrcode type 43 }CODE_TYPE; 44 45 typedef struct 46 { 47 uint8_t *pCodeData; 48 int CodeLen; 49 char *pCodeFile; 50 CODE_TYPE CodeType; 51 int MaxCodeLen; 52 int *pZintRet; 53 }STR_ZINT_CODE; //struct for create code file 54 55 /**************************************************************************** 56 Descpribe: Create Barcode API with C Code by calling zint lib. 57 Input : pBarCodeData, the barcode data buf 58 BarcodeLen, the len of barcode data, but it can be 0 59 pBarCodeFile, the output file name of barcode, it can be NULL 60 Output : pZintRet, to store the ret code from linzint. 61 Return : 0 is ok, and other values are fail. See the meanings in enum ZINT_RET_CODE 62 Notes : pBarCodeFile, Must end in .png, .eps or .svg. when isn,t NULL string. 63 ****************************************************************************/ 64 ZINT_RET_CODE Zint_Create_BarCode(uint8_t *pBarCodeData, int BarcodeLen, char *pBarCodeFile, int *pZintRet); 65 66 /**************************************************************************** 67 Descpribe: Create Qrcode API with C Code by calling zint lib. 68 Input : pQrCodeData, the qrcode data buf 69 QrcodeLen, the len of qrcode data, but it can be 0 70 pQrCodeFile, the output file name of qrcode, it can be NULL 71 Output : pZintRet, to store the ret code from linzint. 72 Return : 0 is ok, and other values are fail. See the meanings in enum ZINT_RET_CODE 73 Notes : pQrCodeFile, Must end in .png, .eps or .svg. when isn,t NULL string. 74 ****************************************************************************/ 75 ZINT_RET_CODE Zint_Create_QrCode(uint8_t *pQrCodeData, int QrcodeLen, char *pQrCodeFile, int *pZintRet); 76 77 #define Debuging(fmt, arg...) printf("[%20s, %4d] "fmt, __FILE__, __LINE__, ##arg) 78 79 #ifdef __cplusplus 80 } 81 #endif 82 83 #endif /* __ZINT_CODE__ */
下面我们通过一个demo程序来验证下接口函数,即qrcode_test.c源程序,以下为其全部内容。
1 /**************************************************************************** 2 * File : qrcode_test.c 3 * 4 * Copyright (c) 2011 by Li.Recan < [email protected] > 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 <stdio.h> 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 char BarcodeData[] = "13430931801"; //barcode string 30 char BarcodeFile[] = "MyBarcode.png"; 31 32 //test with inputing qrcode_file name 33 ZintRet = Zint_Create_QrCode((uint8_t*)QrcodeData, 0, QrcodeFile, &ZintLibRet); 34 if(ZINT_OK != ZintRet) 35 { 36 Debuging("Create qrcode err, ZintRet = %d, ZintLibRet = %d\n", ZintRet, ZintLibRet); 37 } 38 else 39 { 40 Debuging("Create qrcode OK ! \nView qrcode file : %s in cur path. ZintRet = %d, ZintLibRet = %d\n", QrcodeFile, ZintRet, ZintLibRet); 41 } 42 43 //test without inputing qrcode_file name 44 ZintRet = Zint_Create_QrCode((uint8_t*)QrcodeDataDef, 0, NULL, &ZintLibRet); 45 if(ZINT_OK != ZintRet) 46 { 47 Debuging("Create qrcode err, ZintRet = %d, ZintLibRet = %d\n", ZintRet, ZintLibRet); 48 } 49 else 50 { 51 Debuging("Create qrcode OK ! \nView qrcode file : out.png in cur path. ZintRet = %d, ZintLibRet = %d\n", ZintRet, ZintLibRet); 52 } 53 54 //test create barcode with name "MyBarcode.png" 55 ZintRet = Zint_Create_BarCode((uint8_t*)BarcodeData, 0, BarcodeFile, &ZintLibRet); 56 if(ZINT_OK != ZintRet) 57 { 58 Debuging("Create barcode err, ZintRet = %d, ZintLibRet = %d\n", ZintRet, ZintLibRet); 59 } 60 else 61 { 62 Debuging("Create barcode OK ! \nView barcode file : %s in cur path. ZintRet = %d, ZintLibRet = %d\n", BarcodeFile, ZintRet, ZintLibRet); 63 } 64 65 return 0; 66 }
前半部分还是保留上一次测试生产二维码的代码;而新增了生成一维码的测试代码。
之后再运行demo程序,如下:
如框框所示,即为成功运行程序,生成的一维码图片。它的展示如下:
用微信等扫一扫工具,扫描结果如下:
结果正如我们代码所写,证明程序执行是没有问题的。
好了,本期如何用C代码生成一维码就介绍到这里了。有兴趣的童鞋可以私下联系,互相学习。