win32、c/c++生成二维码图片,qrencode的编译和使用
版权声明:
本文为博主原创文章,转载请声明原文链接...谢谢。o_0。
更新时间:
2017-12-07 11:30:19
温馨提示:
学无止境,技术类文章有它的时效性,请留意文章更新时间,如发现内容有误请留言指出,防止别人"踩坑",我会及时更新文章
编译qrencode
下载源码 https://fukuchi.org/works/qrencode/
最新的是4.0.0 。。这里不需要最新所以下载的是3.4.4版本
下载后解压到文件压中,然后使用vs2015创建一个win32静态空项目,打开解压的目录把 *.c、*.h的文件都复制到项目目录,如下
然后删除掉里面的qrenc.c文件,这个是帮助说明文件不用参与编译,然后把config.h.in重命名为config.h然后修改内容为如下
/* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the <inttypes.h> header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if using pthread is enabled. */ #undef HAVE_LIBPTHREAD /* Define to 1 if you have the <memory.h> header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the <stdint.h> header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the <stdlib.h> header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the <strings.h> header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the <string.h> header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strdup' function. */ //#define HAVE_STRDUP 1 #undef HAVE_STRDUP /* Define to 1 if you have the <sys/stat.h> header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the <sys/types.h> header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the <unistd.h> header file. */ #define HAVE_UNISTD_H 1 /* Major version number */ #define MAJOR_VERSION 3 /* Micro version number */ #define MICRO_VERSION 4 /* Minor version number */ #define MINOR_VERSION 4 /* Name of package */ #define PACKAGE "qrencode" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "" /* Define to the full name of this package. */ #define PACKAGE_NAME "QRencode" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "QRencode 3.4.4" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "qrencode" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "3.4.4" /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ #define VERSION "3.4.4" #define inline /* Define to 'static' if no test programs will be compiled. */ #define __STATIC static /* #undef WITH_TESTS */
然后打开split.c文件把strdup替换成mystrdup(因为编译时会跟c++中的strdup冲突),另外在预处理里面添加HAVE_CONFIG_H。之后就可以编译啦
项目中使用
已经生成静态库使用的时候直接引用就可以。
#include <windows.h> #include <iostream> #include "stdio.h" #include "qrencode/qrencode.h" using namespace std; #pragma warning(disable:4099) #ifdef _DEBUG #pragma comment(lib,"qrencode/qrencode_d.lib") #else #pragma comment(lib,"qrencode/qrencode.lib") #endif int main() { char* szSourceSring = "1255335584哈喽你好这个是二维码"; unsigned int unWidth, x, y, l, n, unWidthAdjusted, unDataBytes; unsigned char* pRGBData, *pSourceData, *pDestData; QRcode* pQRC; FILE* f; if (pQRC = QRcode_encodeString(szSourceSring, 1, QR_ECLEVEL_L, QR_MODE_8, 1)) { unWidth = pQRC->width; unWidthAdjusted = unWidth * 8 * 3; if (unWidthAdjusted % 4) unWidthAdjusted = (unWidthAdjusted / 4 + 1) * 4; unDataBytes = unWidthAdjusted * unWidth * 8; // Allocate pixels buffer if (!(pRGBData = (unsigned char*)malloc(unDataBytes))) { exit(-1); } // Preset to white memset(pRGBData, 0xff, unDataBytes); // Prepare bmp headers BITMAPFILEHEADER kFileHeader; kFileHeader.bfType = 0x4d42; // "BM" kFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + unDataBytes; kFileHeader.bfReserved1 = 0; kFileHeader.bfReserved2 = 0; kFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); BITMAPINFOHEADER kInfoHeader; kInfoHeader.biSize = sizeof(BITMAPINFOHEADER); kInfoHeader.biWidth = unWidth * 8; kInfoHeader.biHeight = -((int)unWidth * 8); kInfoHeader.biPlanes = 1; kInfoHeader.biBitCount = 24; kInfoHeader.biCompression = BI_RGB; kInfoHeader.biSizeImage = 0; kInfoHeader.biXPelsPerMeter = 0; kInfoHeader.biYPelsPerMeter = 0; kInfoHeader.biClrUsed = 0; kInfoHeader.biClrImportant = 0; // Convert QrCode bits to bmp pixels pSourceData = pQRC->data; for (y = 0; y < unWidth; y++) { pDestData = pRGBData + unWidthAdjusted * y * 8; for (x = 0; x < unWidth; x++) { if (*pSourceData & 1) { for (l = 0; l < 8; l++) { for (n = 0; n < 8; n++) { //this is qrcode color default black *(pDestData + n * 3 + unWidthAdjusted * l) = 0x00; *(pDestData + 1 + n * 3 + unWidthAdjusted * l) = 0; *(pDestData + 2 + n * 3 + unWidthAdjusted * l) = 0; } } } pDestData += 3 * 8; pSourceData++; } } //把图片字节数据copy到字节数组中 int dwSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + unDataBytes * sizeof(unsigned char); unsigned char* imgbytes = new unsigned char[dwSize] {0}; memcpy(imgbytes, &kFileHeader, sizeof(BITMAPFILEHEADER)); memcpy(imgbytes+ sizeof(BITMAPFILEHEADER), &kInfoHeader, sizeof(BITMAPINFOHEADER)); memcpy(imgbytes+ sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER), pRGBData, sizeof(unsigned char)*unDataBytes); //记得释放 delete[] imgbytes; // Output the bmp file if (!(fopen_s(&f, "temp.bmp", "wb"))) { fwrite(&kFileHeader, sizeof(BITMAPFILEHEADER), 1, f); fwrite(&kInfoHeader, sizeof(BITMAPINFOHEADER), 1, f); fwrite(pRGBData, sizeof(unsigned char), unDataBytes, f); fclose(f); } else { printf("Unable to open file"); exit(-1); } // Free data free(pRGBData); QRcode_free(pQRC); } else { printf("NULL returned"); exit(-1); } getchar(); return 0; }
extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
这个API可以直接设置要编码的字符串内容,以及对二维码的设置,如版本(即大小等级1~40)、容错等级、模式等,返回的是一个结构体指针,QRcode,它的数据data就是二维码的内容,1对应深色块,0对应浅色块。借助一些其他的画图的API就可以绘制出二维码
typedef struct { int version; ///< version of the symbol int width; ///< width of the symbol unsigned char *data; ///< symbol data } QRcode;