QR code二维码简介及Qrencode库的移植与使用
现在生活中,二维码可以说是无处不在,微信扫码支付,支付宝扫码支付,就连贴小广告的都带上了二维码了。之前一直想去了解一下,还是太懒了,就没去,现在项目中需要用到这东西,正好借此机会了解一下。
上网一查,原来二维码的还有很多种。下表是一个简单的介绍:
二维码的优点突出,所以大有取代条形码的趋势,二维码的特点:
1、高密度,容量大,可容纳多达1850个大写字母(字符)或2710个数字,支持最高1108个字节的数据存储,比一维码信息容量高几十倍。
2、 范围广,支持对图片、声音、文字、签字、指纹等各类可以数字化信息的编码,还可以表示多种语言文字和图像数据。
3、 容错能力强,具有纠错功能,当二维码因穿孔、污损等引起局部损坏时,照样可以正常识别,损毁面积达50%仍可恢复。
4、 成本低,易制作,持久耐用等
本次开发使用的是QRcode,因为它目前使用的较为广泛,微信支付,扫码加好友等等都可以是QRcode。
下面对QR Code做个详细的了解:
QR Code码,是由Denso公司于1994年9月研制的一种矩阵二维码符号,它具有一维条码及其它二维条码所具有的信息容量大、可靠性高、可表示汉字及图象多种文字信息、保密防伪性强等优点,是目前较为常用的二维条码。
基本特性
编辑
符号规格 |
21×21模块(版本1)-177×177 模块(版本40) |
(每一规格:每边增加4个模块) |
|
容量(指最大规格符号版本40-L级)
|
· 8位字节数据 :2,953个字符 |
· 汉字数据 :1,817个字符 |
|
数据表示方法 |
深色模块表示二进制“1”,浅色模块表示二进制“0”。 |
纠错能力 |
· L级:约可纠错7%的数据码字 |
· M级:约可纠错15%的数据码字 |
|
· Q级:约可纠错25%的数据码字 |
|
· H级:约可纠错30%的数据码字 |
|
掩模(固有) |
可以使符号中深色与浅色模块的比例接近1:1,使因相邻模块的排列造成译码困难的可能性降为最小。 |
模式 |
1、数字模式(numeric mode ): 0001(数字0~9) 2、混合字符模式(alphanumeric mode) : 0010(数字0~9;大写字母A~Z;9个其他字符:space ,$, %, *, +, -, ., /, :); 3、8bit byte mode: 0100 4、日本汉字(KANJI mode) : 1000 5、中国汉字(GB2312):1101(GB 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.cLIBS = -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 = arLDFLAGS += $(LIBS)
CPPFLAGS += $(INCLUDE)all: check_env compile linkcheck_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!"
谢谢~
QR code二维码简介及Qrencode库的移植与使用相关推荐
- QR code 二维码基础入门教程(二)
QR code 二维码基础入门教程(二) 承接上文,让我们继续下面的步骤 纠错码编码 先说说纠错容量 纠错码可以纠正两种错误: 拒读错误(错误码位置已知),是一个没有扫到或者无法译码的符号字符,需要一 ...
- QR code 二维码基础入门教程
QR code 二维码基础入门教程 本文为 QR Code Tutorial: Introduction 的总结,详细内容请查看原文 Introduction History and Informat ...
- QR Code二维码
二维码又称QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型. 在代码编制上巧妙 ...
- QR code(二维码)
QR code QR码(缩写为Quick Response code)是一种矩阵条码(或二维条码)的商标,于1994年首次为日本汽车行业设计.条形码是一种机器可读的光学标签,它包含有关所附物品的信息. ...
- QR Code二维码识别
1.QR Code概述 二维码:二维码又称二维条码,二维条形码能够在横向和纵向两个方位同时表达信息,因此能在很小的面积内表达大量的信息. QR Code(Quick Response Code)码,是 ...
- vb/java/c# 生成code128 条码/QR Code二维码 导出excel
java/c#生成条形码/二维码图片,导出excel 会用到POI/NPOI,BarcodeLib.ZXing插件. code128 如果不使用插件,也可使用下面vb/c#代码生成含有校验的条码文本, ...
- QR Code 二维码的生成与扫描
前言 现在大街小巷.各大网站都有二维码的踪迹,不管是IOS.Android.WP都有相关支持的软件. 最近因为工作需要使用相关技术,所以做了初步了解.今天主要是讲述如何使用ZXing库,在项目中要使用 ...
- 嵌入式平台QR code二维码生成
二维码生成文件下载 链接:https://pan.baidu.com/s/1PTciVTu-K_cOR6QK9OPwkg 提取码:se5e 将下载好的文件解压并加入工程(以Keil平台为例) 生成二维 ...
- QR code 二维码基础入门教程(三)
QR code 入门教程(三) 承接上文,我们已经说过了数据编码和纠错码的生成,接下来我们继续下面的步骤 结构化最终的数据 所谓的结构化(Structure),说白了就是如何把之前生成的数据排成一个比 ...
最新文章
- 用pytorch实现简易RNN
- mysql 代码执行时间_mysql 显示SQL语句执行时间的代码
- SqlServer按时间自动生成生成单据编号
- powerdesigner mysql 自增主键_PowerDesigner Mysql 主键自增、初始值、字符集
- 128.最长连续序列
- c++代码好玩_Python开源学习:60秒学会一个例子,147段简单代码助你从入门到大师 | 中文资源...
- ubuntu启动配置ftp服务端
- taro 请务必在小程序页面中完善页面基础信息_如何一人五天开发完复杂微信小程序...
- boost的时间和日期处理-(1)日期的操作
- File和IO流应用,剪切文件夹
- 显卡内存足够但是torch报错RuntimeError: CUDA out of memory
- 从零开始做量化(3)
- JDE(Towards Real-Time Multi-Object Tracking)代码训练——小白必看
- 学习笔记(07):C++网络编程进阶-IO模型之重叠Overlapped IO(基于事件通知)
- 高等代数--多项式与线性空间
- SD-WAN,让你的组网更灵活
- oracle--14触发器1
- 银海、东软.net 不能读卡
- Linux的压缩/解压缩文件命令 zip 和 tar
- typescript项目中引入汉字转拼音js