如何在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中的執行效果:

視訊

重播
播放
00:00 / 00:00 正在直播
00:00
進入全屏

50

點選按住可拖動視訊

原始碼

https://github.com/yushulx/nodejs-barcode-reader