win32、c/c++生成二维码图片,qrencode的编译和使用

来源:赵克立博客 分类: C/C++ 标签:C/C++发布时间:2017-12-06 15:26:24最后更新:2017-12-07 11:30:19浏览:8154
版权声明:
本文为博主原创文章,转载请声明原文链接...谢谢。o_0。
更新时间:
2017-12-07 11:30:19
温馨提示:
学无止境,技术类文章有它的时效性,请留意文章更新时间,如发现内容有误请留言指出,防止别人"踩坑",我会及时更新文章

编译qrencode

下载源码 https://fukuchi.org/works/qrencode/

最新的是4.0.0 。。这里不需要最新所以下载的是3.4.4版本

image.png

下载后解压到文件压中,然后使用vs2015创建一个win32静态空项目,打开解压的目录把 *.c、*.h的文件都复制到项目目录,如下

image.png

然后删除掉里面的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。之后就可以编译啦


项目中使用

已经生成静态库使用的时候直接引用就可以。


qrencode.zip

#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;

后记:在Debug模式下编译没有问题,但是release模式下要加入忽略的库才能编译通过,如下

image.png


微信号:kelicom QQ群:215861553 紧急求助须知
Win32/PHP/JS/Android/Python