C/C++使用Quirc库解析二维码

  • Quirc介绍
  • Quirc库使用
  • 遇到的坑
  • 整理的知识点
  • 总结

Quirc介绍

Quirc是一个基于C/C++的一个二维码库,其在码云上的官网 https://gitee.com/mirrors/quirc?_from=gitee_search对于Quirc库是这样介绍的,简单的来概括Quirc的特点就是:简单,方便移植,识别准确率高

QR codes are a type of high-density matrix barcodes, and quirc is a library for extracting and decoding them from images. It has several features which make it a good choice for this purpose:
It is fast enough to be used with realtime video: extracting and decoding from VGA frame takes about 50 ms on a modern x86 core.
It has a robust and tolerant recognition algorithm. It can correctly recognise and decode QR codes which are rotated and/or oblique to the camera. It can also distinguish and decode multiple codes within the same image.
It is easy to use, with a simple API described in a single commented header file (see below for an overview).
It is small and easily embeddable, with no dependencies other than standard C functions.
It has a very small memory footprint: one byte per image pixel, plus a few kB per decoder object.
It uses no global mutable state, and is safe to use in a multithreaded application.
BSD-licensed, with almost no restrictions regarding use and/or modification.
The distribution comes with, in addition to the library, several test programs. While the core library is very portable, these programs have some additional dependencies as documented below.

下载好的Quirc库如图所示:lib文件加里的应用Quirc库必须的文件,demo和test文件夹里是一些例子方便用户使用。

Quirc库使用

本人主要做Alios系统下的开发,但是前辈告诉我在window下调试比较方便,且比较直观,在Alios下使用GDB调试有点不方便。因此本文使用VS2019创建项目进行开发。需要导入的文件如下图所示:

下载的Quirc源码库中,tests文件夹中有一个qrtest.c文件,这是官方给出的例子,按照这个例子进行代码编写即可。以下是自己做实验的代码

#include <stdio.h>
#include <stdlib.h>
#include "quirc.h"#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <ctype.h>
#include <setjmp.h>
#include <time.h>#define width 720
#define height 1280
#define crop_image_size 720*720*4
#define image_size width*height*4
//#define GR_size width*height
#define crop_gray_size 720*720
//#define GRAYvoid rgb32_to_luma(const uint8_t* src, int src_pitch,int w, int h,uint8_t* dst, int dst_pitch)
{int y;uint8_t* gray_buf = malloc(crop_gray_size);for (y = 0; y < h; y++) {const uint8_t* rgb32 = src + src_pitch * y;uint8_t* gray_index = gray_buf + y * dst_pitch;uint8_t* mirror = dst + dst_pitch * y;int i;for (i = 0; i < w; i++) {/* ITU-R colorspace assumed */int r = (int)rgb32[2];int g = (int)rgb32[1];int b = (int)rgb32[0];int sum = r * 59 + g * 150 + b * 29;*(gray_index++) = sum >> 8;//右移8位相当于除以256,计算sum这一步是整数运算rgb32 += 4;mirror[w-i-1] = *(gray_index-1);}}
}int main(int argc, char *argv[]) {const char *vesion;    int ret;struct quirc *qr;FILE* in_file = NULL;FILE* out_file = NULL;FILE* out_mirror_file = NULL;uint8_t* in_buf;uint8_t* rgb_buf;int num_codes;int i;qr = quirc_new();//创建一个句柄if (!qr) {printf("Failed to allocate memory");return -1;}if (quirc_resize(qr, width, 720) < 0) {perror("Failed to allocate video memory");return -2;}   //根据图片的大小设置分配内存的参数uint8_t* image = quirc_begin(qr, NULL, NULL);  //使用这个函数创建一个图片buf,处理好的图片就送入这个buf中in_file = fopen("E:\\QRcode\\qr_RGB32.raw","rb");if(in_file==NULL) {printf("cannot open!!!!! \n");}else{printf("success open !!!!\r\n");}in_buf = (uint8_t*)malloc(image_size);fread(in_buf, image_size, 1, in_file);uint8_t* image_index = in_buf + 280 * 720 * 4;  //这一句是对图片进行了切割,可以省略rgb_buf= (uint8_t*)malloc(crop_image_size);memcpy(rgb_buf, image_index, crop_image_size);rgb32_to_luma(rgb_buf, width * 4, width, 720, image, width);//将rgb32的图像转变为灰度图像,并进行镜像,放入image的buf中fclose(in_file);out_file = fopen("E:\\QRcode\\qr_out1.raw", "wb");fwrite(rgb_buf, crop_image_size, 1, out_file);fclose(out_file);out_mirror_file = fopen("E:\\QRcode\\qr_out_mirror.raw", "wb");fwrite(image, crop_gray_size, 1, out_mirror_file);fclose(out_mirror_file);quirc_end(qr);//这个函数会对图像进行处理num_codes = quirc_count(qr);//读取图片中有几个二维码printf("code is %d\r\n",num_codes);for (i = 0; i < num_codes; i++) {struct quirc_code code;struct quirc_data data;quirc_decode_error_t err;quirc_extract(qr, i, &code);err = quirc_decode(&code, &data);if (err) printf("DECODE FAILED: %s\n", quirc_strerror(err));elseprintf("Data: %s\n", data.payload);//输出读取二维码的结果}   //根据二维码的个数,进行循环处理并输出free(in_buf);free(rgb_buf);quirc_destroy(qr);return 0;
}

到此已经可以读取二维码的内容。

遇到的坑

  • VS2012环境下编译不过去
    开始自己是在VS2012上做C语言开发,但是将Quirc的代码移植到VS2012上却编译不过,报语法的错误,经查证VS2012不支持C99,有一些语法不支持,自己重新装了VS2019后,这个问题得到解决。
  • 文件IO遇到的一些问题
    自己还在慢慢学习,之前一直在做网络部分,文件IO的处理有点生疏,犯得最离谱的错就是在处理文件的时候只用了fopen()打开文件,忘记使用fread把文件读取到缓存中,贻笑大方。
    第二个是使用了feek,导致文件乱码,自己想用feek获得图片的大小,但是由于用的不熟悉导致忘记把光标复原,导致保存图片的时候,保存的不对。
  • Quirc不能处理镜像
    自己在window下可以读出网上下载下来的二维码,但是使用从嵌入式设备的摄像头中截取的图像却不能识别,自己做了一些实验,终于发现了问题,原来Quirc库不能识别镜像的二维码。
void rgb32_to_luma(const uint8_t* src, int src_pitch,int w, int h,uint8_t* dst, int dst_pitch)
{int y;uint8_t* gray_buf = malloc(crop_gray_size);for (y = 0; y < h; y++) {const uint8_t* rgb32 = src + src_pitch * y;uint8_t* gray_index = gray_buf + y * dst_pitch;uint8_t* mirror = dst + dst_pitch * y;int i;for (i = 0; i < w; i++) {/* ITU-R colorspace assumed */int r = (int)rgb32[2];int g = (int)rgb32[1];int b = (int)rgb32[0];int sum = r * 59 + g * 150 + b * 29;*(gray_index++) = sum >> 8;//右移8位相当于除以256,计算sum这一步是整数运算rgb32 += 4;mirror[w-i-1] = *(gray_index-1);//对图片进行镜像}}
}

自己在这个函数中首先对rgb32图像进行灰度化,然后使用指针对其图像进行了镜像,原理就是在一行中对图像的像素进行翻转。

  • 在Alios下开线程的时候,程序崩溃
int QRcode_thread()
{int ret;aos_task_t QRcode_task_thread;ret = aos_task_new_ext(&QRcode_task_thread, "QRcode_task", userCmdGetRGBSnapShot, NULL, 100*1024, QRcode_TASK_PRI);if (ret != 0) {printf("QRcode userCmdGetRGBSnapShot creation failed\n");return -1;}return 0;
}

原因是开线程分配的栈大小太小,导致程序崩溃,扩大线程栈的大小就可以了

整理的知识点

  • VS2019添加lib库文件

lib和普通的源码一样,只是不能看到源码,但是库里的函数是可以直接用的,就像添加.h和.cpp文件一样,把lib文件添加到工程文件列表中去.

VS中,切换到"解决方案视图",—>选中要添加lib的工程–>点击右键–>“添加”–>“现有项”–>选择lib文件–>确定.

  • VS2019添加带文件夹的项目
  • Alios中开命令行
struct cli_command_st QRcode_cli_cmd[] = {{ "QRcode", "QRcode test", QRcode_thread},{ "QRstop", "QRcode test", QRcode_stop},
};void QRcode_cli_init(void)
{cli_register_commands(QRcode_cli_cmd,2);
}

这样就可以了,然后在主线程中调用初始化,命令行就可以使用了

  • 使用git上传代码到Gitee中
    写代码的时候版本控制是很重要的,下载git软件和tortoisegit软件就可以上传了,具体过程网上很多就不再说了,但是第一次上传的时候一定要用add命令,不要用commit命令,不然会少东西,有些格式的文件用commit不会自动上传。

  • 图片格式的问题
    图片其实就是矩阵,32rgb就是有4个通道,rgba,每个8位,一共32位。24位的就是rgb,r,g,b3个通道,每个8位,共24位。灰度图就是8位,一个字节来表示,这些知识在对图片进行处理时,如本文中的对灰度图进行镜像,是有用的。

  • 代码风格的问题
    网上的代码风格很多,在这里我还是准备使用在嵌入式中常用的,下划线命名法

  • 调试思路的问题
    在查因为堆栈问题的时候,我调试没经验,用GDB一句句走的,但是前辈教我直接在开头添加打印,发现开头的打印就没出来,肯定是开线程的时候就出问题了,才发现是堆栈的问题,这里要好好吸收一下,调试的思想。

总结

本文介绍了Quirc库的使用方法以及自己这个月来学到的知识,这个月对指针有更加深刻的认识了,也更加熟悉文件IO,以及多线程操作,移植的Alios的机器上后Quirc正确率不错,但是太慢了要4秒一次,效率太低,通过查阅资料,Zbar的效率高,下一篇文章会介绍另一个条形码识别库Zbar的使用方法。

C/C++使用Quirc库解析二维码(QRcode)相关推荐

  1. JAVA利用google的zxing解析二维码QRCODE

    1.导入jar包,如果是非maven工程就去mvnrepository.com搜索zxing,下载本jar包即可 <dependency><groupId>com.google ...

  2. C# 调用摄像头解析二维码

    上次的二维码项目中,在解析的时候用的是扫码枪自动解析并以键盘形式输出,二次开发及通用性不高.本次项目使用AForge库调用摄像头采集二维码照片,再使用ZXing库解析二维码,较之前通用性更高. 一.调 ...

  3. Python解析二维码、条形码

    Python解析二维码.条形码 1 前言 2 二维码知识小科普 2.1 什么是二维码 2.2 二维码的结构 2.3 二维码的绘制过程 3 Python解析二维码 3.1 准备工作: 3.2 pyzba ...

  4. java利用zxing来生成和解析二维码,支持中文

    java在二维码的生成和解析上,网上有些人说如果要解析中文,得去修改工具包的Encoder类中的 static final String DEFAULT_BYTE_MODE_ENCODING = &q ...

  5. 加载google Z-Xing库实现二维码解析与生成,并将解析结果在另一页面显示

    1.首先需要下载Z-Xing 库项目下载文档,可在http://download.csdn.net/detail/catchingsun/8903065进行下载: 2.解析二维码,并跳转至新建Acti ...

  6. 【Python3解析二维码】翻遍全网找到 2 款库推荐给大家~

    文章目录 ⛳️ 实战场景 ⛳️ pyzbar 解析二维码 ⛳️ cv2 解析二维码 总结 ⛳️ 实战场景 上一篇博客,我们整理了 4 款 Python 二维码模块,发到社群之后,有小伙伴反馈非常棒,那 ...

  7. ZXing 二维码库之生成与解析二维码

    博主声明: 转载请在开头附加本文链接及作者信息,并标记为转载.本文由博主 威威喵 原创,请多支持与指教. 本文首发于此   博主:威威喵  |  博客主页:https://blog.csdn.net/ ...

  8. 嵌入式使用Zbar解析二维码

    引言 上篇文章介绍了使用Quirc解析二维码,Quirc是一个轻量级的二维码解析库,效率太低,不符合使用条件,作者使用Zbar来进行二维码的解析.Zbar算法是现在网上开源的条形码,二维码检测算法,这 ...

  9. 使用摄像头解析二维码,且可以生成含具体信息的二维码

    开源一份早些时候写过的代码,关于二维码在PC端的应用. 二维码的具体应用范围,这里不详述. 之前项目主要用于朋友一个牙科的平台,不过后面没有采用,也就没有往后继续开发,大家要是觉得有意思,可以自己拿去 ...

最新文章

  1. 免gre美国计算机硕士,美国硕士免GRE/GMAT的学校-计算机篇
  2. jspx格式手机打开_制作手机浏览器显示格式的HTML页面
  3. 信息学奥赛一本通 2007:【20CSPJ普及组】方格取数 | 洛谷 P7074
  4. cmd指令大全指令_数控加工中心编程技巧及指令大全,请转给需要的数控人!
  5. 搜狐-新闻页 粗略整理-自我学习
  6. GPU大百科全书 第二章 凝固生命的光栅化
  7. .NET Core跨平台:.NET Core项目部署到linux(Centos7)
  8. ZBrush建模的15个小技巧,萌新小白都用得上的干货,速看
  9. linux进入根目录的代码,Linux根目录+源代码目录
  10. 西门子atch指令详解_西门子plc指令详解
  11. Cesium开发基础篇 | 03加载矢量数据
  12. 举个栗子!Tableau 技巧(194):用参数自定义排序控件
  13. flappy+bird+c语言程序,C语言版flappy_bird实现
  14. 阿里云赵明山:详解灵活可插拔的渐进式发布框架OpenKruise Rollout
  15. ERROR: Could not build wheels for cryptography which use PEP 517 and cannot be installed directly
  16. 问题:微信小程序开发之 --- app.js文件介绍
  17. 我国20年农药年施用量增百万吨 生产方式需反思
  18. SIP(会话发起协议)
  19. 安全环保专题培训考试题
  20. 优麒麟服务器配置备忘

热门文章

  1. 聊聊 Bladed 软件
  2. 算法交易策略的成功回测
  3. char* strlen()学习
  4. 问题 G: 向右看齐
  5. Unity—“合成大西瓜”小游戏笔记
  6. Modern source-to-source transformation with Clang and libTooling
  7. 人体冷冻技术科学家称四十年内实现冷冻后复活,实现起死回生和长生不死
  8. 专访新致云田奎:行业云服务的差异化发展 初创公司上云迫在眉睫
  9. 2023最火批量getshell工具
  10. Voyager 1.2.3 发布,Laravel 后台管理扩展包