QR code二维码简介及Qrencode库的移植与使用

现在生活中,二维码可以说是无处不在,微信扫码支付,支付宝扫码支付,就连贴小广告的都带上了二维码了。之前一直想去了解一下,还是太懒了,就没去,现在项目中需要用到这东西,正好借此机会了解一下。

 

 

上网一查,原来二维码的还有很多种。下表是一个简单的介绍:


二维码的优点突出,所以大有取代条形码的趋势,二维码的特点:

1、高密度,容量大,可容纳多达1850个大写字母(字符)或2710个数字,支持最高1108个字节的数据存储,比一维码信息容量高几十倍。

2、 范围广,支持对图片、声音、文字、签字、指纹等各类可以数字化信息的编码,还可以表示多种语言文字和图像数据。

3、 容错能力强,具有纠错功能,当二维码因穿孔、污损等引起局部损坏时,照样可以正常识别,损毁面积达50%仍可恢复。

4、 成本低,易制作,持久耐用

 

 

本次开发使用的是QRcode,因为它目前使用的较为广泛,微信支付,扫码加好友等等都可以是QRcode

 

下面对QR Code做个详细的了解:

QR Code码,是由Denso公司于19949月研制的一种矩阵二维码符号,它具有一维条码及其它二维条码所具有的信息容量大、可靠性高、可表示汉字及图象多种文字信息、保密防伪性强等优点,是目前较为常用的二维条码。

基本特性

编辑

符号规格

21×21模块(版本1-177×177 模块(版本40

(每一规格:每边增加4个模块)

容量(指最大规格符号版本40-L级)

 

· 8位字节数据 :2,953个字符

· 汉字数据 :1,817个字符

数据表示方法

深色模块表示二进制“1”,浅色模块表示二进制“0”

纠错能力

· L级:约可纠错7%的数据码字

· M级:约可纠错15%的数据码字

· Q级:约可纠错25%的数据码字

· H级:约可纠错30%的数据码字

掩模(固有)

可以使符号中深色与浅色模块的比例接近11,使因相邻模块的排列造成译码困难的可能性降为最小。

模式

1、数字模式(numeric mode ): 0001(数字09

2、混合字符模式(alphanumeric mode) : 0010(数字09;大写字母AZ9个其他字符:space ,$, %, *, +, -, ., /, :);

3、8bit byte mode: 0100

4、日本汉字(KANJI mode) : 1000

5、中国汉字(GB2312):1101GB 2312对应的汉字和非汉字字符)

 

 

为了美观,可以在二维码上添加一张logo图片,一般放在中间。我在网上查了好久,没有找到logo的大小和二维码的等级和容错性的关系,如果大家有找到的,请告知,谢谢,我这边自己选择了长宽是二维码的20%,测试不影响识别。

 

编码阶段:

在网上找了一个第三方的库,qrencode,提供了制作二维码的API,接口很简单,

extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);

这个API可以直接设置要编码的字符串内容,以及对二维码的设置,如版本(即大小等级1~40)、容错等级、模式等,返回的是一个结构体指针,QRcode,

typedef struct {
         int version;         ///< version of the symbol
         int width;           ///< width of the symbol
         unsigned char *data; ///< symbol data
} QRcode;

它的数据data就是二维码的内容,1对应深色块,0对应浅色块。借助一些其他的画图的API就可以绘制出二维码。哭的详细介绍请参考:点击打开链接

 

我使用的是QT+VS 和QT+Linux,做的是嵌入式开发,所以需要涉及到一些交叉编译等。

 

由于qrencode 在我们项目中作为一个第三方库,只需要它的基础功能,后面不会持续去更新,所以,决定将其编译成静态库。如果想编译成动态库,可以参考http://blog.csdn.net/u010977122/article/details/52959098

这个是我开始编译成动态库遇到的一些问题。

静态库的编译参照了 http://blog.csdn.net/liyuanbhu/article/details/44647139 博主的配置,在此感谢。

将博主的一些东西搬过来,从而让本文更加完整,下面是编译windows下的静态库的过程。

建立一个 win32 项目,选择生成静态库,不使用预编译头。将 qrencode 的源文件(.c 和 .h)全部拷到vc 的项目目录中,除了 qrenc.c 。编译 qrencode 时还需要有个 config.h 文件(源码中的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  
  
/* 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 */  
     
然后在项目属性中添加预处理定义:HAVE_CONFIG_H(项目->属性->配置属性->C/C++->预处理器->预处理器定义)

config.h 中有一行:#define inline 

是因为rscode.c 文件中有个modnn的定义如下:

static inline int modnn(RS *rs, int x){  
    while (x >= rs->nn) {  
        x -= rs->nn;  
        x = (x >> rs->mm) + (x & rs->nn);  
    }  
    return x;  
}  
在用VS2012编译的时候,在split.c文件中,strdup编译不过,提示 error C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details. 将strdup改成_strdup,具体参考我的博客:http://blog.csdn.net/u010977122/article/details/53020475

点击打开链接

qrencode 本身是不依赖于 libpng 库的。所以不存在什么缺少 png.h 的问题。按照本文介绍的方法按部就班的做就能生成静态库,不存在任何问题。编译时一定要排除 qrenc.c 这个文件。这个文件是 qrencode 的一个使用例子,与这个库本身无关。


生成了libqrencode.a的一个静态库,再配qrencode.h这个头文件,就可以在项目中使用了。

在QT中使用的具体代码如下:


void HQrencodePCtrl::PaintQRcode::draw(QPainter &painter, int width, int height)  
{  
	QColor foreground(Qt::black);
	painter.setBrush(foreground);
	const int qr_width = qr->width > 0 ? qr->width : 1;  
	double scale_x = width / qr_width;  
	double scale_y = height / qr_width;  
 	for( int y = 0; y < qr_width; y ++)  
 	{  
 		for(int x = 0; x < qr_width; x++)  
 		{  
 			unsigned char b = qr->data[y * qr_width + x];  
 			if(b & 0x01)  
 			{  
 				QRectF r(int(x * scale_x), int(y * scale_y), int(scale_x), int(scale_y));  
 				painter.drawRects(&r, 1);  
 			}  
 		}  
 	} 
	if(bhavelogo)     //添加Logo的图片,绘制在二维码的中间
	{
		QPixmap picture(logoaddr.c_str());
		int logoWidth = width*0.2;
		int logoHeight = height * 0.2;
		painter.drawPixmap(width/2-logoWidth/2,height/2-logoHeight/2,logoWidth,logoHeight,picture);
	}	
}  
<pre name="code" class="cpp">void HQrencodePCtrl::PaintQRcode::setString(HString str)  
{  
	priv_string = str;  
 	if(qr != NULL)  
 	{  
 		QRcode_free(qr);  
 	}  
	qr = QRcode_encodeString(priv_string.c_str(),  
		1,  
		QR_ECLEVEL_L,  
		QR_MODE_8,  
		1);  
	update();  
}  
void HQrencodePCtrl::PaintQRcode::paint(QPainter *painter)
{
	QColor background(Qt::white);  
	painter->setBrush(background);  
	painter->setPen(Qt::NoPen);  
	//painter->drawRect(0, 0, width(), height());  


	if(qr != NULL)  
	{
		int paintWidth = int(width()/qr->width)*qr->width ;
		int paintHeight = int(height()/qr->width)*qr->width;
		painter->drawRect(0, 0, paintWidth, paintHeight); 
		draw(*painter, paintWidth,paintHeight);  
	}  
}

 


在linux下编译成库,主要是写Makefile 文件,除了将strdup改成_strdup再改回去,其他不变。下面是我的makefile文件:

TARGET = libqrencode
TARGET_DIR = ../../../lib/linux/debug/
#OBJ_DIR = ./objs
#$(CC) -o $(TARGET_DIR)/$(TARGET) $(OBJ_FILES) $(LDFLAGS)

INCLUDE = -I../../../src/ -I../../../inc/
SOURCES = ../../../src/bitstream.c ../../../src/mask.c ../../../src/mmask.c ../../../src/mqrspec.c ../../../src/qrencode.c ../../../src/qrinput.c ../../../src/qrspec.c ../../../src/rscode.c ../../../src/split.c

LIBS = -lpthread
OBJ_FILES = $(patsubst %.c, %.o, $(SOURCES))

CC = arm-poky-linux-gnueabi-g++ -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/opt/poky/1.7/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi -std=c++11 -ggdb
AR = arm-poky-linux-gnueabi-ar   #这里将编译器替换成自己需要的编译器
#CC = gcc
#AR = ar

LDFLAGS += $(LIBS) 
CPPFLAGS += $(INCLUDE)

all: check_env compile link

check_env:
	@echo "[$(TARGET)]: Build Start..."
	@mkdir -p $(TARGET_DIR)

compile: $(OBJ_FILES)

link:
	@echo "[$(TARGET)]: Linking ..."
	@$(AR) rcs $(TARGET_DIR)/$(TARGET).a $(OBJ_FILES)
	@echo "[$(TARGET)]: Build done!"	

#complie step 1:
$(OBJ_FILES): %.o: %.c
	@echo "[$(TARGET)]: Compiling  $(notdir $^) ..."
	@$(CC) -DHAVE_CONFIG_H=1 -fPIC -c $(CPPFLAGS) $< -o $@     #这里在编译的时候加上<span style="font-family: 'Times New Roman';">HAVE_CONFIG_H=1的宏定义</span>


clean:
	@rm -rf $(OBJ_FILES) $(TARGET_DIR)/$(TARGET).a
	@echo "[$(TARGET)]: Clean Finish!"

谢谢~

### 回答1: qrencode是一种二维条形码图像生成器,可以将文本、URL、电话号码等信息编码成二维条形码。它采用了非接触式扫描的方式,读取速度快,并且具有较强的纠错能力。 使用qrencode生成二维条形码非常简单。首先,我们需要安装qrencode软件包,并确保安装了必要的依赖项。然后,我们可以使用命令行工具来生成二维条形码。例如,我们可以运行以下命令来生成一个包含"Hello World"文本的二维条形码: qrencode -o barcode.png "Hello World" 这将在当前目录下生成一个名为barcode.png的文件,其中包含编码了"Hello World"文本的二维条形码。 除了文本,qrencode还可以编码其他类型的信息,如URL和电话号码。我们只需要将相应的信息作为命令行参数传递给qrencode即可。例如,我们可以使用以下命令生成一个包含URL的二维条形码: qrencode -o barcode.png "https://www.example.com" 生成的二维条形码将包含指向https://www.example.com网址的链接。 总结来说,qrencode是一个方便易用的二维条形码生成工具,可以将各种类型的信息编码成二维条形码。通过简单的命令行操作,我们可以生成包含文本、URL、电话号码等信息的二维条形码。使用qrencode可以方便地将信息存储在条形码中,并且可以通过扫描的方式将其读取出来。 ### 回答2: qrencode是一种用于生成QR码(Quick Response Code,快速响应码)的开源软件工具。QR码是一种二维条码,它可以存储更多的信息比传统的条形码。QR码可以被扫描器或手机摄像头等设备扫描,并将其中的信息解码出来。 使用qrencode生成QR码非常简单。首先,我们需要安装qrencode工具,然后通过命令行输入相关参数生成QR码。可以设置QR码的大小、纠错级别和编码内容等。生成的QR码可以保存为图片文件或直接输出到终端。该工具还支持生成多种格式的QR码,例如ASCII码、SVG矢量图等。 生成的QR码可以应用于很多场景。例如,在商业领域,QR码常用于产品标签、促销活动等。消费者可以通过扫描QR码获取产品的详细信息、价格等。在移动支付领域,QR码也被广泛使用。用户可以通过扫描商家的QR码完成支付,方便快捷。 QR码的优势在于它具有较高的容错率和大容量存储能力。即使在一部分QR码被损坏或遮挡的情况下,扫描仪仍然可以成功解码。另外,QR码可以存储几百个字符的信息,这在部分场景下非常有用。 总之,qrencode工具可以方便地生成QR码,而QR码具有高容错率和大容量存储的特点,被广泛应用于商业和移动支付等领域,以提供更优质的用户体验和便利。 ### 回答3: qrencode 是一种二维码编码方式,可以将信息编码成二维矩阵形式,并且通过扫描二维码进行解码。与传统的条形码相比,qrencode 提供了更多的存储空间和更高的纠错能力。 qrencode 的原理是将待编码的信息转化为二进制数据,在二维码矩阵中按照一定规则填充。矩阵中的黑色模块表示数据的“1”,白色模块表示数据的“0”。二维码的中心区域通常留白,用来定位和识别二维码的方向。 在使用 qrencode 编码时,可以选择不同的纠错级别,包括 L、M、Q 和 H 四个级别。纠错级别越高,二维码的纠错能力越强,但存储的数据量也会相应减少。 qrencode 可以编码各种类型的信息,例如文字、URL、电话号码等。通过扫描二维码,我们可以快速获取编码的信息,并快捷地访问对应的网页或拨打电话。 qrencode 已经广泛应用于商业领域和个人生活中。在商业领域,二维码可以作为产品标识,方便消费者获取产品信息、促销活动等。在个人生活中,二维码可以用来快速分享联系方式、社交媒体账号和个人网站等。 总之,qrencode 条形码是一种高效、可靠的二维码编码技术,可以方便快捷地存储和传递各种类型的信息。随着二维码应用的普及,qrencode 将在我们的日常生活中发挥更大的作用。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值