Node.js 条形码识别程序构建思路详解


Posted in Javascript onFebruary 14, 2016

在这篇文章中,我们将展示一个非常简单的方法构建一个自定义的 Node 模块,该模块封装了Dynamsoft Barcode Reader SDK ,支持 Windows、Linux 和 OS X,同时我们将演示如何集成这块模块实现一个在线的条形码读取应用。

越来越多的 Web 开发者选择 Node 来构建网站,因为使用 JavaScript 来开发复杂的服务器端 Web 应用越来越便利。为了扩展在不同平台下的 Node 的功能,Node 允许开发者使用 C/C++ 来创建扩展。

介绍

Dynamsoft Barcode Reader 为 Windows、Linux 和 OS X 提供条形码解析的 C/C++ 共享库。其最大的优势是适用于多种高级编程语言,包括 JavaScript, Python, Java, Ruby, PHP 等,只要可以封装 C/C++ API 作为一个扩展就可以使用。不管是什么编程语言,最终只需要简单几行代码即可完成条形码的解析。

支持 1D/2D 条形码类型

Code 39, Code 93, Code 128, Codabar, Interleaved 2 of 5, EAN-8, EAN-13, UPC-A, UPC-E,Industrial 2 of 5
QRCode
DataMatrix
PDF417

支持图像类型

BMP, JPEG, PNG, GIF, TIFF, PDF

运行环境

Windows, Linux & Mac
Node v5.5.0

Node.js 条形码扩展

Node.js 扩展使用 C/C++ 编写的动态链接的共享对象。如果你没有接触过这方面的技术,可以阅读 官方教程 。

创建扩展

创建名为 dbr.cc 的文件,并添加方法 DecodeFile:

#include <node.h>
#include <string.h>
#include "If_DBR.h"
#include "BarcodeFormat.h"
#include "BarcodeStructs.h"
#include "ErrorCode.h"
using namespace v8;
void DecodeFile(const FunctionCallbackInfo<Value>& args) {
}
void Init(Handle<Object> exports) {
NODE_SET_METHOD(exports, "decodeFile", DecodeFile);
}
NODE_MODULE(dbr, Init)

解析来自 JavaScript 传递过来的参数

Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
String::Utf8Value license(args[0]->ToString());
String::Utf8Value fileName(args[1]->ToString());
char *pFileName = *fileName;
char *pszLicense = *license;
__int64 llFormat = args[2]->IntegerValue();
Local<Function> cb = Local<Function>::Cast(args[3]);

解析条形码图像:

int iMaxCount = 0x7FFFFFFF;
ReaderOptions ro = {0};
pBarcodeResultArray pResults = NULL;
ro.llBarcodeFormat = llFormat;
ro.iMaxBarcodesNumPerPage = iMaxCount;
DBR_InitLicense(pszLicense);
// Decode barcode image
int ret = DBR_DecodeFile(pFileName, &ro, &pResults);

将条形码转成字符串:

const char * GetFormatStr(__int64 format)
{
if (format == CODE_39)
return "CODE_39";
if (format == CODE_128)
return "CODE_128";
if (format == CODE_93)
return "CODE_93";
if (format == CODABAR)
return "CODABAR";
if (format == ITF)
return "ITF";
if (format == UPC_A)
return "UPC_A";
if (format == UPC_E)
return "UPC_E";
if (format == EAN_13)
return "EAN_13";
if (format == EAN_8)
return "EAN_8";
if (format == INDUSTRIAL_25)
return "INDUSTRIAL_25";
if (format == QR_CODE)
return "QR_CODE";
if (format == PDF417)
return "PDF417";
if (format == DATAMATRIX)
return "DATAMATRIX";

return "UNKNOWN";
}

将结果转成 v8 对象:

Local<Array> barcodeResults = Array::New(isolate);
for (int i = 0; i < count; i++)
{
tmp = ppBarcodes[i];
Local<Object> result = Object::New(isolate);
result->Set(String::NewFromUtf8(isolate, "format"), String::NewFromUtf8(isolate, GetFormatStr(tmp->llFormat)));
result->Set(String::NewFromUtf8(isolate, "value"), String::NewFromUtf8(isolate, tmp->pBarcodeData));
barcodeResults->Set(Number::New(isolate, i), result);
}

构建扩展

要求:

Windows: 需要安装 DBR for Windows, visual Studio, and Python v2.7.

Linux: 安装 DBR for Linux.

Mac: 安装 DBR for Mac 和 Xcode.

安装 node-gyp:

npm install -g node-gyp

创建 binding.gyp 用于多平台编译:

{
"targets": [
{
'target_name': "dbr",
'sources': [ "dbr.cc" ],
'conditions': [
['OS=="linux"', {
'defines': [
'LINUX_DBR',
],
'include_dirs': [
"/home/xiao/Dynamsoft/BarcodeReader4.0/Include"
],
'libraries': [
"-lDynamsoftBarcodeReaderx64", "-L/home/xiao/Dynamsoft/BarcodeReader4.0/Redist"
],
'copies': [
{
'destination': 'build/Release/',
'files': [
'/home/xiao/Dynamsoft/BarcodeReader4.0/Redist/libDynamsoftBarcodeReaderx64.so'
]
}]
}],
['OS=="win"', {
'defines': [
'WINDOWS_DBR',
],
'include_dirs': [
"F:/Program Files (x86)/Dynamsoft/Barcode Reader 4.1/Components/C_C++/Include"
],
'libraries': [
"-lF:/Program Files (x86)/Dynamsoft/Barcode Reader 4.1/Components/C_C++/Lib/DBRx64.lib"
],
'copies': [
{
'destination': 'build/Release/',
'files': [
'F:/Program Files (x86)/Dynamsoft/Barcode Reader 4.1/Components/C_C++/Redist/DynamsoftBarcodeReaderx64.dll'
]
}]
}],
['OS=="mac"', {
'defines': [
'MAC_DBR',
],
'include_dirs' : [
"/Applications/Dynamsoft/Barcode/ Reader/ 4.1/Include"
],
'libraries': [
"-lDynamsoftBarcodeReader"
]
}]
]
}
]
}

将 DRB 安装目录替换成你机器上的实际目录。

配置构建环境:

node-gyp configure

可以在 Mac 上你会碰到下面的错误:

error: xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

解决办法是:

sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer

构建项目:

node-gyp build

在线条形码解析

你已经成功的构建了 Node 的条形码解析模块,现在可以创建一个简单的条形码读取应用。

安装 Express 和 Formidable:

npm install express
npm install formidable

使用 Express 创建一个简单应用:

var formidable = require('formidable');
var util = require('util');
var express = require('express');
var fs = require('fs');
var app = express();
var path = require('path');
var dbr = require('./build/Release/dbr');
var http = require('http');
fs.readFile('./license.txt', 'utf8', function(err, data) {
app.use(express.static(__dirname));
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS");
res.header("Access-Control-Allow-Headers", "X-Requested-With, content-type");
res.header("Access-Control-Allow-Credentials", true);
next();
});
var server = app.listen(2016, function() {
var host = server.address().address;
var port = server.address().port;
console.log('listening at http://%s:%s', host, port);
});
});

使用 Formidable 从表单中提取图像数据:

app.post('/upload', function(req, res) {
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
var dir = 'uploads';
fs.mkdir(dir, function(err) {
var flag = fields.uploadFlag;
var barcodeType = parseInt(fields.barcodetype);
console.log('flag: ' + flag);
if (flag === '1') { // read barcode image file
fs.readFile(files.fileToUpload.path, function(err, data) {
// save file from temp dir to new dir
var fileName = path.join(__dirname, dir, files.fileToUpload.name);
console.log(fileName);
fs.writeFile(fileName, data, function(err) {
if (err) throw err;

});
});
} else { // read barcode image url
var tmpFileName = path.join(__dirname, dir, 'tmp.jpg');
var tmp = fs.createWriteStream(tmpFileName);
var url = fields.fileToDownload;
console.log('url: ' + url);
http.get(url, function(response) {
response.pipe(tmp);
tmp.on('finish', function() {
tmp.close(function() {

});
});
});
}
});
});
});

导入条形码模块用来解析图像文件:

decodeBarcode(res, license, tmpFileName, barcodeType);

运行应用:

node server.js

访问 http://localhost:2016/index.htm:

Node.js 条形码识别程序构建思路详解

以上所述是小编给大家介绍的Node.js 条形码识别程序构建思路详解,希望对大家有所帮助。

Javascript 相关文章推荐
取得一定长度的内容,处理中文
Dec 20 Javascript
用javascript实现改变TEXTAREA滚动条和按钮的颜色,以及怎样让滚动条变得扁平
Apr 20 Javascript
angular简介和其特点介绍
Jan 29 Javascript
javascript入门教程基础篇
Nov 16 Javascript
Bootstrap树形控件使用方法详解
Jan 27 Javascript
jQuery插件AjaxFileUpload实现ajax文件上传
May 05 Javascript
基于JS实现翻书效果的页面切换样式
Feb 16 Javascript
Vue中render函数的使用方法
Jan 31 Javascript
详解Vue 换肤方案验证
Aug 28 Javascript
利用d3.js制作连线动画图与编辑器的方法实例
Sep 05 Javascript
Vue实现腾讯云点播视频上传功能的实现代码
Aug 17 Javascript
vue使用Google Recaptcha验证的实现示例
Aug 23 Vue.js
jQuery插件支持同一页面被多次调用
Feb 14 #Javascript
JavaScript中通过提示框跳转页面的方法
Feb 14 #Javascript
JavaScript中关联原型链属性特性
Feb 13 #Javascript
JavaScript操作class和style样式代码详解
Feb 13 #Javascript
javascript实现查找数组中最大值方法汇总
Feb 13 #Javascript
JavaScript常用数组算法小结
Feb 13 #Javascript
Javascript 字符串模板的简单实现
Feb 13 #Javascript
You might like
mysql_fetch_row,mysql_fetch_array,mysql_fetch_assoc的区别
2009/04/24 PHP
PHP GD 图像处理组件的常用函数总结
2010/04/28 PHP
ThinkPHP实现将SESSION存入MYSQL的方法
2014/07/22 PHP
php微信公众平台开发(一) 配置接口
2016/12/06 PHP
PHP从数组中删除元素的四种方法实例
2017/05/12 PHP
thinkphp5.0整合phpsocketio完整攻略(绕坑)
2018/10/12 PHP
使用composer安装使用thinkphp6.0框架问题【视频教程】
2019/10/01 PHP
jquery向上向下取整适合分页查询
2014/09/06 Javascript
node.js中的fs.createWriteStream方法使用说明
2014/12/17 Javascript
轮播图组件js代码
2016/08/08 Javascript
浅谈Angular2 模块懒加载的方法
2017/10/04 Javascript
JavaScript继承定义与用法实践分析
2018/05/28 Javascript
浅谈layui 数据表格前后台传值的问题
2019/09/12 Javascript
微信小程序实现同时上传多张图片
2020/02/03 Javascript
[45:14]Optic vs VP 2018国际邀请赛淘汰赛BO3 第二场 8.24
2018/08/25 DOTA
Python3 socket同步通信简单示例
2017/06/07 Python
python使用邻接矩阵构造图代码示例
2017/11/10 Python
pandas series序列转化为星期几的实例
2018/04/11 Python
详谈python3中用for循环删除列表中元素的坑
2018/04/19 Python
基于Python开发chrome插件的方法分析
2018/07/07 Python
Python 控制终端输出文字的实例
2019/07/12 Python
Django文件存储 默认存储系统解析
2019/08/02 Python
Python爬虫实现使用beautifulSoup4爬取名言网功能案例
2019/09/15 Python
如何基于Python获取图片的物理尺寸
2019/11/25 Python
Python守护进程实现过程详解
2020/02/10 Python
Django用户身份验证完成示例代码
2020/04/03 Python
HTML5 HTMLCollection和NodeList的区别详解
2020/04/29 HTML / CSS
英国助听器购物网站:Hearing Direct
2018/08/21 全球购物
Bluebella德国官网:英国性感内衣和睡衣品牌
2019/11/08 全球购物
项目经理岗位职责
2013/11/11 职场文书
士力架广告词
2014/03/20 职场文书
医院护士见习期自我鉴定
2014/09/15 职场文书
幼儿园法制宣传日活动总结
2014/11/01 职场文书
工作表扬信
2015/01/17 职场文书
pycharm debug 断点调试心得分享
2021/04/16 Python
梳理总结Python开发中需要摒弃的18个坏习惯
2022/01/22 Python