序言

第一次开始写博客,在日常学习和工作当中 CSDN 给我帮助很大,因此我也在 CSDN 奉献自己的经验,借此回馈 CSDN 对我的帮助,希望自己的经验可以帮助需要的人,也方便自己后续复习之用,同时亦可以借此丰富自己和完善自己的知识体系。

介绍

Zbar 是一个二维码和条形码的开源解码库,因为有一个项目没有屏幕但有摄像头,需要解决无线网络联网问题,自然而然的就想到使用摄像头来扫描二维码实现联网。检索网络上发现 zbar 相对来说比较合适,但源码中并未集成 zbar 的 package,因此根据自己对 OpenWRT 的 Makefile 编写规则的理解,借鉴原有的 Makefile 写了一个 Makefile。

经过在 Tina 系统中实测,该 Makefile 符合 OpenWRT Makefile 编写规则,可以实现自动下载源码、解压、配置并且编译和部署相应的头文件和动静态库到编译环境中,使之第三方可以很容易的引入使用。

正文

Zbar Makefile

#**
#*****************************************************************************
# @文件        Makefile
# @版本        V1.0.0
# @日期        2019-12-05
# @概要        基于 OpenWRT 的第三方开源二维码识别库 zbar Makefile 文件, 
# @作者        lmx 
# @邮箱        lovemengx@qq.com
#*****************************************************************************
# @版权
#
# 随意修改复制哈
#
#***************************************************************************** # 这些 makefile 字文件确立软件包加入 OpenWrt 的方式和方法
include $(TOPDIR)/rules.mk # 1. 根据官方下载链接来配置下载地址、版本号、包名
# 2. 配置完成后编译系统会根据下载地址下载源码包到 dl 文件夹
# https://nchc.dl.sourceforge.net/project/zbar/zbar/0.10/zbar-0.10.tar.bz2
PKG_NAME:=zbar
PKG_VERSION:=0.10
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_VERSION:=v$(PKG_VERSION)
PKG_SOURCE_URL:=https://nchc.dl.sourceforge.net/project/zbar/zbar/$(PKG_VERSION)
PKG_BUILD_DIR:=$(COMPILE_DIR)/$(PKG_NAME)-$(PKG_VERSION) # 一般在软包的基本信息完成后再引入
include $(BUILD_DIR)/package.mk # 应用程序编译包以 "Package/" 开头,然后接着软件名(可以与软件包名不一样)
# SECTION     : 包的类型
# CATEGORY    : 包的分类,在 make menuconfig 的菜单显示的名字
# TITLE        : 用于在 make menuconfig 对该软件包的简述
# DEPENDS    : 表示依赖其他软件。即如编译或安装需要其他软件时需要说明。如果
#              存在多个依赖,则每个依赖需要用空格分开。依赖前使用+号表示默认
#              为显示,即对象沒有选中时也会显示,使用@则默认为不显示,即当依
#              赖对象选中后才显示。
define Package/libzbar
  SECTION:=utils
  CATEGORY:=zhc_application
  DEPENDS:=
  TITLE:=zbar
endef # 配置描述信息, make menuconfig 中显示
define Package/libzbar/description
  This is an open source QR code identification Library
endef # 配置编译选项, 对应 ./configure 命令
CONFIGURE_ARGS+= \
        --disable-video \
        --enable-shared \
        --enable-static \
        --without-imagemagick \
        --without-jpeg \
        --without-python \
        --without-gtk \
        --without-qt \
        --disable-video # 配置编译方法, 会生成 ipkg-install 为预安装做准备
define Build/Compile
    $(MAKE) -C $(PKG_BUILD_DIR) \
        DESTDIR="$(PKG_INSTALL_DIR)" \
        install
    # 生成    libzbar.provides 文件, 便于其他APP引用
    $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \
        all
endef # 提取其它软件需要用到的头文件和静态动态连接库, 这样才能编译
define Build/InstallDev
    $(INSTALL_DIR) $(1)/usr/include
    $(INSTALL_DIR) $(1)/usr/include/zbar
    $(INSTALL_DIR) $(1)/usr/lib
    $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
    
    $(CP) $(PKG_INSTALL_DIR)/usr/include/*.h $(1)/usr/include/
    $(CP) $(PKG_INSTALL_DIR)/usr/include/zbar/*.h $(1)/usr/include/zbar/
    $(CP) $(PKG_INSTALL_DIR)/usr/lib/libzbar.{a,so*} $(1)/usr/lib/
    $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/* $(1)/usr/lib/pkgconfig/
endef # 软件包的安装方法(即执行 opkg install 命令时需要释放的文件和目录)
#    包括一系列拷贝编译好的文件到指定位置。
#    调用时会带一个参数,就是嵌入系统的镜像文件系统目录
#    因此 $(1) 表示嵌入系统的镜像目录。一般可以采用下面的方法
# INSTALL_DIR\INSTALL_BIN    : 在 $(TOPDIR)/rules.mk 定义
# INSTALL_DIR    : INSTALL_DIR :=install -d -m0755 意思是创建所属用户可读写其他用户可读可执行的目录
# INSTALL_BIN    : INSTALL_BIN :=install -m0755 意思是编译好的文件存放到镜像文件目录
define Package/libzbar/install
    $(INSTALL_DIR) $(1)/usr/lib
    $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib*.so.* $(1)/usr/lib/
endef $(eval $(call BuildPackage,libzbar))

例程:

Makefile


include $(TOPDIR)/rules.mk
include $(BUILD_DIR)/kernel.mk PKG_NAME:=zhc_zbar_demo
PKG_VERSION:=1.0.0
PKG_RELEASE:=1 PKG_BUILD_DIR := $(COMPILE_DIR)/$(PKG_NAME) include $(BUILD_DIR)/package.mk define Package/$(PKG_NAME)
SECTION:=utils
CATEGORY:=zhc_application
TITLE:=zbar demo
DEPENDS:=+libpthread +libstdcpp +libzbar
endef define Package/$(PKG_NAME)/description
this zbar demo
endef define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) -r ./src/* $(PKG_BUILD_DIR)/
endef define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR)/ \
ARCH="$(TARGET_ARCH)" \
AR="$(TARGET_AR)" \
CC="$(TARGET_CC)" \
CXX="$(TARGET_CXX)" \
CFLAGS="$(TARGET_CFLAGS)" \
LDFLAGS="$(TARGET_LDFLAGS) -lpthread -lzbar "
endef define Build/Configure
endef define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/bin/
endef $(eval $(call BuildPackage,$(PKG_NAME)))

源码

主要参考 QREnDeCode 即可,

#include <iostream>
#include <unistd.h>
#include <zbar.h>
#include <sys/stat.h>
#include <string.h> using namespace std;
using namespace zbar; class QREnDeCode
{
private: ImageScanner *m_pImageScanner = NULL;
Image *m_pImage = NULL; public: QREnDeCode();
~QREnDeCode(); bool deCode(unsigned char* pYdata, unsigned int width, unsigned int height, string &result);
}; QREnDeCode::QREnDeCode()
{
m_pImageScanner = new ImageScanner();
m_pImage = new Image();
m_pImage->set_format("Y800");
} QREnDeCode::~QREnDeCode()
{
if (m_pImage) {
delete m_pImage;
} if (m_pImageScanner) {
delete m_pImageScanner;
} } bool QREnDeCode::deCode(unsigned char* pYdata, unsigned int width, unsigned int height, string &result)
{
m_pImage->set_size(width, height);
m_pImage->set_data(pYdata, width * height); if (m_pImageScanner->scan(*m_pImage))
{
result = m_pImage->symbol_begin()->get_data();
m_pImageScanner->recycle_image(*m_pImage);
return true;
} return false;
} // argv[1]: width argv[2]: heigth argv[3]: yuvfile
int main(int argc, char *argv[])
{
unsigned int width = 0;
unsigned int heigth = 0;
unsigned char *pBuffer = NULL;
size_t size = 0;
char *pYuvFile = NULL; if(argc < 3){
printf("%s width heigth yuvfile(YUV420 planar)", argv[0]);
return -1;
} width = atoi(argv[1]);
heigth = atoi(argv[2]);
pYuvFile = argv[3]; printf("width:%d heigth:%d file:[%s]\n", width, heigth, pYuvFile); struct stat statbuff;
if(stat(pYuvFile, &statbuff) < 0){
printf("[err] get file size fail...\n");
return -2;
} if(statbuff.st_size != (width * heigth * 3 / 2)){
printf("[err] probably not yuv420(planar) file\n");
return -3;
} size = width * heigth;
pBuffer = (unsigned char *)malloc(size);
if(NULL == pBuffer){
printf("[err] malloc %d byte fail\n", size);
return -4;
} FILE *fp = fopen(pYuvFile, "rb");
if(NULL == fp){
printf("[err] open file fail\n");
return -5;
} // 取 YUV 中的 Y 数据, Zbar 只需要明亮度的数据
memset(pBuffer, 0, size);
fread(pBuffer, size, 1, fp);
fclose(fp); QREnDeCode qrDecode;
string qrResult; if(qrDecode.deCode(pBuffer, width, heigth, qrResult) == false){
printf("decode not data\n");
return -6;
} puts("---------------------------");
printf("%s", qrResult.c_str());
puts("\n---------------------------");
return 0;
}

执行结果:

root@sun8i:/tmp# zhc_zbar_demo 280 280 /mnt/UDISK/qr.yuv
width:280 heigth:280 file:[/mnt/UDISK/qr.yuv]
---------------------------
WIFI:Lovemengx
PASSWORD:1007566569
---------------------------

完整的源代码和二维码YUV文件:(资源待审核)

https://download.csdn.net/download/lovemengx/12032832

补充说明:

经过实际测试,无论是 Windows 版本还是 Linux 版本,在调用 ImageScanner ::scan (Image& image);接口存在内存泄漏的问题,简略看了下源代码,暂未找到未释放的代码,因此在实际应用过程中,如果未能解决此问题,建议将其独立一个可执行文件,以命令的方式存在,主业务逻辑来调用该命令并解析其返回的结果。

【OpenWRT】增加第三方开源库 - 二维码开源库 zbar的更多相关文章

  1. 二维码开源库zbar、zxing使用心得

    首先说明我的测试场景是“识别打印在纸上的二维码”,在扫描结果中寻找二维码并进行识别,而不是直接让摄像头对着二维码扫描. zbar和zxing用的都是自己从github上clone的c++源码/接口编译 ...

  2. C++二维码相关库编译

    一.瞎想 坐在地铁上闲来无聊,突然想到了二维码,顺手就百度了下相关的资料,目前C++二维码相关的库不多,也就zbar(开源中国上下了半天也没下载下来).zxing,不过这两个库据说都是解析二维码的,不 ...

  3. day111:MoFang:邀请好友流程&生成邀请好友二维码&第三方应用识别二维码&本地编译测试&记录邀请人信息

    目录 1.邀请业务逻辑流程图 2.邀请好友-前端 3.邀请好友-后端接口(生成二维码) 4.前端获取后端生成的二维码 5.前端长按页面,保存图片到相册 6.客户端通过第三方识别微信二维码,服务端提供对 ...

  4. 个性二维码开源专题<替换元素点>

    基础方法:ChangeFillShape //修改填充形状 ChangeFillShape(...) // 摘要: // 修改填充形状 // // 参数: // g: // 图形画板 // // Fo ...

  5. 个性二维码开源专题<替换定位点>

    基础方法: ChangeFillShape //修改填充形状 ChangeFillShape(...) // 摘要: // 修改填充形状 // // 参数: // g: // 图形画板 // // F ...

  6. 个性二维码开源专题<液化/圆角/效果>

    基础方法: ChangeFillShape //修改填充形状 ChangeFillShape(...) // 摘要: // 修改填充形状 // // 参数: // g: // 图形画板 // // F ...

  7. Android二维码开源项目zxing用例简化和生成二维码、条形码

    上一篇讲到:Android二维码开源项目zxing编译,编译出来后有一个自带的測试程序:CaptureActivity比較复杂,我仅仅要是把一些不用的东西去掉,用看起来更方便,二维码和条形码的流行性自 ...

  8. Javascript 二维码生成库:QRCode

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. 二维码开源库ZBar-吐槽篇

    前不久在网上看到一篇文章<QR-Decoder-OV5640 二维码识别> ,是某开发板的教程.记得对应的开发板以前购买过,当初只是为了看OV5640的JPG的输出效果,结果由于公司奇葩的 ...

  10. 二维码开源库ZBar-MDK STM32F429移植

    前两篇文章已经实现ZBar在Windows平台下的编译和使用,本文将介绍如何把ZBar移植到STM32F429,IDE使用MDK. 1. MDK工程设置 (1)不勾选Use MicroLIB ,使用I ...

随机推荐

  1. SpringBoot&MyBatisPlus

    5. SpringBoot 学习目标: 掌握基于SpringBoot框架的程序开发步骤 熟练使用SpringBoot配置信息修改服务器配置 基于SpringBoot完成SSM整合项目开发 5.1 入门 ...

  2. 使用 Spring Cloud LoadBalancer 实现客户端负载均衡

    使用 Spring Cloud LoadBalancer 实现客户端负载均衡 作者:Grey 原文地址: 博客园:使用 Spring Cloud LoadBalancer 实现客户端负载均衡 CSDN ...

  3. vue 过滤器时间格式化

    1.导入了一个moment.js插件,里面封装了格式化时间的方法 ①:插件的链接:https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/mom ...

  4. Shell脚本--信号发送与捕捉

    信号(Signal):信号是在软件层次上对中断机制的一种模拟,通过给一个进程发送信号,执行相 应的处理函数. 进程可以通过三种方式来响应一个信号: 忽略信号,即对信号不做任何处理,其中有两个信号不能忽 ...

  5. 第2-3-8章 分片上传和分片合并的接口开发-文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss

    目录 5.10 接口开发-分片上传 5.10.1 分片上传介绍 5.10.2 前端分片上传插件webuploader 5.10.3 后端代码实现 5.10.3.1 接口文档 5.10.3.2 代码开发 ...

  6. nestjs搭建HTTP与WebSocket服务

    最近在做一款轻量级IM产品,后端技术栈框架使用了nodejs + nestjs作为服务端.同时,还需要满足一个服务同时支持HTTP服务调用以及WebSocket服务调用,此文主要记录本次搭建过程,以及 ...

  7. SSH(二)框架配置文件

    在引入了宽假所需要的jar包后,引入相应配置文件. 一.Struts2的配置文件: 1.Struts2的黑心过滤器,在web.xml中引入: <!-- struts2框架的核心过滤器  clas ...

  8. 安装mySql 出现 one more product requirements have not been satisified

    安装mySql 出现 one more product requirements have not been satisified 原因是缺少一些依赖环境. 在弹出的对话框中点击 否. 然后点击执行, ...

  9. 笔试面试--Java基础知识

    一.基本概念 1.Java的优点 纯面向对象 平台无关性,"一次编译,到处运行(JVM上)",跨平台,可移植性 丰富类库:多线程.网络通信.垃圾回收 安全性(数组边界检测.byte ...

  10. 【java】【File】用File相关类写一个小工具,完成从指定目录下抽取指定文件并复制到新路径下完成重命名的功能

    今日份代码: import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import java.io.*; i ...