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;