如何在IE中開啟USB攝像頭掃描條形碼
IE不支援WebRTC,所以沒有辦法通過JS介面在瀏覽器中直接訪問USB攝像頭。解決的方法就是通過本地啟動一個服務去獲取攝像頭資料,然後傳送到IE的web頁面上,通過img元素不斷重新整理來顯示,這個在上一篇文章中已經說過。這篇文章是基於上一篇裡Node.js的程式碼,增加條形碼掃描功能。
基於C/C 的Node.js條形碼模組編譯
C/C 的封裝程式碼在
https://github.com/Dynamsoft/nodejs-barcode。
用於解碼的介面是decodeBufferAsync()。以下是相關的C/C 程式碼:
void DecodeBufferAsync(const FunctionCallbackInfo& args) { if (!createDBR()) {return;} Isolate* isolate = Isolate::GetCurrent(); Localcontext = isolate->GetCurrentContext(); // get arguments unsigned char* buffer = (unsigned char*) node::Buffer::Data(args[0]); // file stream int width = args[1]->Int32Value(context).ToChecked(); // image width int height = args[2]->Int32Value(context).ToChecked(); // image height int stride = args[3]->Int32Value(context).ToChecked(); // stride int iFormat = args[4]->Int32Value(context).ToChecked(); // barcode types Localcb = Local::Cast(args[5]); // javascript callback function String::Utf8Value templateName(isolate, args[6]); // template name char *pTemplateName = *templateName; // initialize BarcodeWorker BarcodeWorker *worker = new BarcodeWorker; worker->request.data = worker; worker->callback.Reset(isolate, cb); worker->iFormat = iFormat; worker->pResults = NULL; worker->buffer = buffer; worker->width = width; worker->height = height; worker->bufferType = RGB_BUFFER; worker->stride = stride; if (hasTemplate(pTemplateName)) { // Load the template. char szErrorMsg[256]; DBR_InitRuntimeSettingsWithString(hBarcode, pTemplateName, CM_OVERWRITE, szErrorMsg, 256); worker->useTemplate = true; } else { worker->useTemplate = false; } uv_queue_work(uv_default_loop(), &worker->request, (uv_work_cb)DetectionWorking, (uv_after_work_cb)DetectionDone); }
第一個引數是影象資料的指標,所以在JS層要通過getData() 獲取buffer:
const vCap = new cv.VideoCapture(0); var img = vCap.read(); dbr.decodeBufferAsync(img.getData(), img.cols, img.rows, img.step, barcodeTypes, function (err, msg) { results = msg }, "");
編譯的時候針對不同的平臺有一些差別。Linux上通過rpath設定相對路徑;Windows上把DLL拷貝到輸出目錄;mac上把dylib檔案拷貝到/usr/local/lib目錄下。
binding.gyp
{ "targets": [ { 'target_name': "dbr", 'sources': ["src/dbr.cc"], "cflags" : [ "-std=c 11" ], 'ldflags': [ "-Wl,-rpath,'$$ORIGIN'" ], 'include_dirs': [ "./" ], 'conditions': [ ['OS=="linux"', { 'defines': [ 'LINUX_DBR', ], 'libraries': [ "-lDynamsoftBarcodeReader", "-L../platforms/linux" ], 'copies': [ { 'destination': 'build/Release/', 'files': [ './platforms/linux/libDynamsoftBarcodeReader.so' ] } ] }], ['OS=="win"', { 'defines': [ 'WINDOWS_DBR', ], 'libraries': [ "-l../platforms/windows/DBRx64.lib" ], 'copies': [ { 'destination': 'build/Release/', 'files': [ './platforms/windows/**.*' ] } ] }], ['OS=="mac"', { 'defines': [ 'MAC_DBR', ], 'libraries': [ "-lDynamsoftBarcodeReader", "-L../platforms/macos" ], 'copies': [ { 'destination': '/usr/local/lib/', 'files': [ './platforms/macos/libDynamsoftBarcodeReader.dylib' ] } ] }] ] } ] }
包已經發布到npm上。安裝前先裝好每個平臺需要的C/C 編譯環境。然後執行下面的命令下載,編譯,安裝:
npm install -g node-gyp npm install barcode4nodejs
通過Node.js實現在IE瀏覽器中掃描條形碼
在服務端呼叫JS條形碼介面,當返回結果的時候畫到當前影象上,然後通過jpg編碼傳送給web客戶端:
function capture() { var frame = wCap.read() if (frame.empty) { wCap.reset(); frame = wCap.read(); } dbr.decodeBufferAsync(frame.getData(), frame.cols, frame.rows, frame.step, barcodeTypes, function (err, msg) { // console.log(results) results = msg }, "", 1); if (results != null) { for (index in results) { let result = results[index]; let upperLeft = new cv.Point(result.x1, result.y1) let bottomLeft = new cv.Point(result.x2, result.y2) let upperRight = new cv.Point(result.x3, result.y3) let bottomRight = new cv.Point(result.x4, result.y4) frame.drawLine( upperLeft, bottomLeft, drawParams ) frame.drawLine( bottomLeft, upperRight, drawParams ) frame.drawLine( upperRight, bottomRight, drawParams ) frame.drawLine( bottomRight, upperLeft, drawParams ) frame.putText(result.value, new cv.Point(result.x1, result.y1 10), fontFace, fontScale, textColor, thickness); } } img = cv.imencode('.jpg', frame); setTimeout(capture, 30); } capture();
var server = http.createServer(function (req, res) { //create web server if (req.url.startsWith("/image")) { res.writeHead(200, { 'Content-Type': 'image/jpeg' }); res.write(img); res.end(); } else { res.writeHead(200, { 'Content-Type': 'text/html' }); res.write(html); res.end(); } });
結果是非同步返回的,因為連續幀之間的差別很小,所以用於顯示問題不大。
以下是IE中的執行效果:
視訊
50
原始碼
https://github.com/yushulx/nodejs-barcode-reader