之前在做跟华为合作的项目,需要根据字串来生成特定的二维码,特在此记录,以便查看。

二维码图样有很多种,根据项目要求,我选择了使用libqrcode库来实现,这是个开源库,使用十分方便,首先下载libqrcode源码,根据平台选择编译条件并编译成动态库so。在自己编写程序包含相应的头文件,编译链接动态库即可。

以下是我部分code,仅供参考。

qrcode.h

#ifndef _QRCODE_H_
#define _QRCODE_H_

#ifdef __cplusplus
extern \"C\"{
#endif

#include \"qrencode.h\"

enum imageType {
	PNG_TYPE,
	PNG32_TYPE,
	EPS_TYPE,
	SVG_TYPE,
	XPM_TYPE,
	ANSI_TYPE,
	ANSI256_TYPE,
	ASCII_TYPE,
	ASCIIi_TYPE,
	UTF8_TYPE,
	ANSIUTF8_TYPE,
	UTF8i_TYPE,
	ANSIUTF8i_TYPE
};

int makeQrcode(const char *SourceSring, const char *path);



#ifdef __cplusplus
}
#endif

#endif

qrcode.cpp

#include <string.h>
#include <errno.h>
//#include <conio.h>
#include <ctype.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <wchar.h>
#include <png.h>

#include \"qrcode.h\"


#pragma pack(push, 2)
#pragma pack(pop)

#define INCHES_PER_METER (100.0/2.54)

static int margin = 1;
static int size = 8;  //qrcode size
static unsigned char fg_color[4] = {0, 0, 0, 255};
static unsigned char bg_color[4] = {201, 201, 201, 255};
static int dpi = 72;

static void fillRow(unsigned char *row, int num, const unsigned char color[])
{
	int i;

	for(i = 0; i < num; i++) {
		memcpy(row, color, 4);
		row += 4;
	}
}


static int writePNG(const QRcode *qrcode, const char *outfile, enum imageType type)
{
	static FILE *fp; // avoid clobbering by setjmp.
	png_structp png_ptr;
	png_infop info_ptr;
	png_colorp palette = NULL;
	png_byte alpha_values[2];
	unsigned char *row, *p, *q;
	int x, y, xx, yy, bit;
	int realwidth;

	realwidth = (qrcode->width + margin * 2) * size;
	if(type == PNG_TYPE) {
		row = (unsigned char *)malloc((realwidth + 7) / 8);
	} else if(type == PNG32_TYPE) {
		row = (unsigned char *)malloc(realwidth * 4);
	} else {
		fprintf(stderr, \"Internal error.\\n\");
		return -1;
	}
	if(row == NULL) {
		fprintf(stderr, \"Failed to allocate memory.\\n\");
		return -1;
	}

	if(outfile[0] == \'-\' && outfile[1] == \'\\0\') {
		fp = stdout;
	} else {
		fp = fopen(outfile, \"wb\");
		if(fp == NULL) {
			fprintf(stderr, \"Failed to create file: %s\\n\", outfile);
			perror(NULL);
			return -1;
		}
	}

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if(png_ptr == NULL) {
		fprintf(stderr, \"Failed to initialize PNG writer.\\n\");
		return -1;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if(info_ptr == NULL) {
		fprintf(stderr, \"Failed to initialize PNG write.\\n\");
		return -1;
	}

	if(setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fprintf(stderr, \"Failed to write PNG image.\\n\");
		return -1;
	}

	if(type == PNG_TYPE) {
		palette = (png_colorp) malloc(sizeof(png_color) * 2);
		if(palette == NULL) {
			fprintf(stderr, \"Failed to allocate memory.\\n\");
			exit(EXIT_FAILURE);
		}
		palette[0].red   = fg_color[0];
		palette[0].green = fg_color[1];
		palette[0].blue  = fg_color[2];
		palette[1].red   = bg_color[0];
		palette[1].green = bg_color[1];
		palette[1].blue  = bg_color[2];
		alpha_values[0] = fg_color[3];
		alpha_values[1] = bg_color[3];
		png_set_PLTE(png_ptr, info_ptr, palette, 2);
		png_set_tRNS(png_ptr, info_ptr, alpha_values, 2, NULL);
	}

	png_init_io(png_ptr, fp);
	if(type == PNG_TYPE) {
		png_set_IHDR(png_ptr, info_ptr,
				realwidth, realwidth,
				1,
				PNG_COLOR_TYPE_PALETTE,
				PNG_INTERLACE_NONE,
				PNG_COMPRESSION_TYPE_DEFAULT,
				PNG_FILTER_TYPE_DEFAULT);
	} else {
		png_set_IHDR(png_ptr, info_ptr,
				realwidth, realwidth,
				8,
				PNG_COLOR_TYPE_RGB_ALPHA,
				PNG_INTERLACE_NONE,
				PNG_COMPRESSION_TYPE_DEFAULT,
				PNG_FILTER_TYPE_DEFAULT);
	}
	png_set_pHYs(png_ptr, info_ptr,
			dpi * INCHES_PER_METER,
			dpi * INCHES_PER_METER,
			PNG_RESOLUTION_METER);
	png_write_info(png_ptr, info_ptr);

	if(type == PNG_TYPE) {
	/* top margin */
		memset(row, 0xff, (realwidth + 7) / 8);
		for(y = 0; y < margin * size; y++) {
			png_write_row(png_ptr, row);
		}

		/* data */
		p = qrcode->data;
		for(y = 0; y < qrcode->width; y++) {
			memset(row, 0xff, (realwidth + 7) / 8);
			q = row;
			q += margin * size / 8;
			bit = 7 - (margin * size % 8);
			for(x = 0; x < qrcode->width; x++) {
				for(xx = 0; xx < size; xx++) {
					*q ^= (*p & 1) << bit;
					bit--;
					if(bit < 0) {
						q++;
						bit = 7;
					}
				}
				p++;
			}
			for(yy = 0; yy < size; yy++) {
				png_write_row(png_ptr, row);
			}
		}
		/* bottom margin */
		memset(row, 0xff, (realwidth + 7) / 8);
		for(y = 0; y < margin * size; y++) {
			png_write_row(png_ptr, row);
		}
	} else {
	/* top margin */
		fillRow(row, realwidth, bg_color);
		for(y = 0; y < margin * size; y++) {
			png_write_row(png_ptr, row);
		}

		/* data */
		p = qrcode->data;
		for(y = 0; y < qrcode->width; y++) {
			fillRow(row, realwidth, bg_color);
			for(x = 0; x < qrcode->width; x++) {
				for(xx = 0; xx < size; xx++) {
					if(*p & 1) {
						memcpy(&row[((margin + x) * size + xx) * 4], fg_color, 4);
					}
				}
				p++;
			}
			for(yy = 0; yy < size; yy++) {
				png_write_row(png_ptr, row);
			}
		}
		/* bottom margin */
		fillRow(row, realwidth, bg_color);
		for(y = 0; y < margin * size; y++) {
			png_write_row(png_ptr, row);
		}
	}

	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);

	fclose(fp);
	free(row);
	free(palette);

	return 0;
}

int makeQrcode(const char *SourceSring, const char *path)
{
	if(!SourceSring || !path)
	{
		printf(\"args error[%p:%p]\\n\", SourceSring, path);
		return -1;
	}

	QRcode* 		pQRC;

	//	QRCode
	if (pQRC = QRcode_encodeString(SourceSring, 2, QR_ECLEVEL_M, QR_MODE_8, 1))
	{
		writePNG(pQRC, (char *)path, PNG_TYPE);
		QRcode_free(pQRC);
	}
	else
	{
		printf(\"NULL returned\");
		return -1;
	}

	return 0;
	
}



最后我把生成的二维码保存成png格式的图片,因为保存png需要用到 libpng库,所以事先需要安装libpng,具体如何 libpng 来实现功能,有兴趣的朋友可以参考下我前面的文章(https://blog.csdn.net/wang93IT/article/details/85003730)。

\"\"

收藏 打印