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 相关文章推荐
解决jquery中美元符号命名冲突问题
Jan 08 Javascript
JQuery中阻止事件冒泡几种方式及其区别介绍
Jan 15 Javascript
JS常用表单验证方法总结
May 22 Javascript
js 模式窗口(模式对话框和非模式对话框)的使用介绍
Jul 17 Javascript
浅析javascript的间隔调用和延时调用
Nov 12 Javascript
JavaScript 常见安全漏洞和自动化检测技术
Aug 21 Javascript
Javascript数组Array方法解读
Mar 13 Javascript
JQuery控制图片由中心点逐渐放大效果
Jun 26 Javascript
angularjs点击图片放大实现上传图片预览
Feb 24 Javascript
jquery 校验中国身份证号码实例详解
Apr 11 jQuery
react-native DatePicker日期选择组件的实现代码
Sep 12 Javascript
three.js 利用uv和ThreeBSP制作一个快递柜功能
Aug 18 Javascript
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编程语言开发动态WAP页面
2006/10/09 PHP
剖析 PHP 中的输出缓冲
2006/12/21 PHP
实用函数5
2007/11/08 PHP
使用PHP备份MYSQL数据的多种方法
2014/01/15 PHP
PHP调用VC编写的COM组件实例
2014/03/29 PHP
php数组指针操作详解
2017/02/14 PHP
php进程daemon化的正确实现方法
2018/09/06 PHP
laravel 5.3 单用户登录简单实现方法
2019/10/14 PHP
PHP常用函数之获取汉字首字母功能示例
2019/10/21 PHP
js鼠标及对象坐标控制属性详细解析
2013/12/14 Javascript
cocos2dx骨骼动画Armature源码剖析(三)
2015/09/08 Javascript
js实现点击获取验证码倒计时效果
2021/01/28 Javascript
javascript实现随机显示星星特效
2016/01/28 Javascript
HTML5 实现的一个俄罗斯方块实例代码
2016/09/19 Javascript
JavaScript实现格式化字符串函数String.format
2016/12/16 Javascript
jquery使用iscorll实现上拉、下拉加载刷新
2017/10/26 jQuery
react学习笔记之state以及setState的使用
2017/12/07 Javascript
谈谈JS中的!!
2017/12/07 Javascript
Vue动态控制input的disabled属性的方法
2018/06/26 Javascript
基于vue2的canvas时钟倒计时组件步骤解析
2018/11/05 Javascript
Vuex 使用 v-model 配合 state的方法
2018/11/13 Javascript
将Vue组件库更换为按需加载的方法步骤
2020/05/06 Javascript
解决Nuxt使用axios跨域问题
2020/07/06 Javascript
用Python删除本地目录下某一时间点之前创建的所有文件的实例
2017/12/14 Python
python中的不可变数据类型与可变数据类型详解
2018/09/16 Python
pygame实现俄罗斯方块游戏(基础篇1)
2019/10/29 Python
解决Django中checkbox复选框的传值问题
2020/03/31 Python
Django Admin后台模型列表页面如何添加自定义操作按钮
2020/11/11 Python
助人为乐表扬信范文
2014/01/14 职场文书
大学生职业规划范文:象牙塔生活的四年计划
2014/01/14 职场文书
幼儿园教师培训方案
2014/02/04 职场文书
体育专业求职信
2014/07/16 职场文书
投标人法定代表人授权委托书格式
2014/09/28 职场文书
2015年个人思想总结
2015/03/09 职场文书
伊索寓言读书笔记
2015/06/30 职场文书
vue使用v-model进行跨组件绑定的基本实现方法
2021/04/28 Vue.js