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 相关文章推荐
ajax上传时参数提交不更新等相关问题
Dec 11 Javascript
jQuery实现动画效果的实例代码
May 07 Javascript
js获取电脑分辨率的思路及操作
Nov 22 Javascript
基于iframe实现类似于ajax的页面无刷新
May 31 Javascript
究竟什么是Node.js?Node.js有什么好处?
May 29 Javascript
异步加载JS、CSS代码(推荐)
Jun 15 Javascript
巧用数组制作图片切换js代码
Nov 29 Javascript
AngularJS执行流程详解
Feb 17 Javascript
分分钟玩转Vue.js组件(二)
Mar 01 Javascript
详解promise.then,process.nextTick, setTimeout 以及 setImmediate的执行顺序
Nov 21 Javascript
js实现的订阅发布者模式简单示例
Mar 14 Javascript
JS JQuery获取data-*属性值方法解析
Sep 01 jQuery
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
PHP实现下载断点续传的方法
2014/11/12 PHP
PHP数据库表操作的封装类及用法实例详解
2016/07/12 PHP
PHP写API输出的时用echo的原因详解
2019/04/28 PHP
laravel 框架实现无限级分类的方法示例
2019/10/31 PHP
document.write的几点使用心得
2014/05/14 Javascript
JavaScript不刷新实现浏览器的前进后退功能
2014/11/05 Javascript
微信WeixinJSBridge API使用实例
2015/05/25 Javascript
javascript实现手机震动API代码
2015/08/05 Javascript
如何利用模板将HTML从JavaScript中抽离
2016/10/08 Javascript
解析Angular 2+ 样式绑定方式
2018/01/15 Javascript
详解js正则表达式验证时间格式xxxx-xx-xx形式
2018/02/09 Javascript
浅谈webpack devtool里的7种SourceMap模式
2019/01/14 Javascript
javascript设计模式 ? 桥接模式原理与应用实例分析
2020/04/13 Javascript
vue+element-ui表格封装tag标签使用插槽
2020/06/18 Javascript
vue中是怎样监听数组变化的
2020/10/24 Javascript
[04:10]2016国际邀请赛中国区预选赛第二日TOP10精彩集锦
2016/06/28 DOTA
python函数返回多个值的示例方法
2013/12/04 Python
python计数排序和基数排序算法实例
2014/04/25 Python
python使用cPickle模块序列化实例
2014/09/25 Python
深入解析Python编程中super关键字的用法
2016/06/24 Python
djang常用查询SQL语句的使用代码
2019/02/15 Python
Python使用Pandas库实现MySQL数据库的读写
2019/07/06 Python
Python Numpy库常见用法入门教程
2020/01/16 Python
python Shapely使用指南详解
2020/02/18 Python
Python连接Hadoop数据中遇到的各种坑(汇总)
2020/04/14 Python
pycharm2020.2 配置使用的方法详解
2020/09/16 Python
Python模块常用四种安装方式
2020/10/20 Python
机电一体化应届生求职信范文
2014/01/24 职场文书
网站创业计划书
2014/04/30 职场文书
门卫岗位职责说明书
2014/08/18 职场文书
2014年初中班主任工作总结
2014/11/08 职场文书
前台接待岗位职责范本
2015/04/03 职场文书
法制主题班会教案
2015/08/13 职场文书
2016三八妇女节慰问信
2015/11/30 职场文书
Python中字符串对象语法分享
2022/02/24 Python
postgresql之greenplum字符串去重拼接方式
2023/05/08 PostgreSQL