Node.js Barcode and QR Code Reader for Desktop and Web
Tags: node, javascript, qrcode, barcode
Published: 2022-03-25 01:25:56

There are many open source JavaScript barcode and QR code reader libraries, but few of them are suitable for enterprise use. The reason is that they do not have a road map for long-term algorithm updates and maintenance. In addition, the performance of pure JavaScript is not good enough. WebAssembly is a better choice comparing to pure JavaScript if you pursue performance. Nevertheless, for server-side programming using Node.js, it is still not the end. What is under the hood of Node.js? It is C/C++. It is no doubt that a Node.js addon with C++ has the best performance. In this article, you will see how to use Node.js barcode and QR code addon based on [Dynamsoft C++ Barcode SDK](https://www.dynamsoft.com/barcode-reader/overview/) to build desktop and web applications using JavaScript.

## Installation 
- [barcode4nodejs](https://www.npmjs.com/package/barcode4nodejs)
 
    The `barcode4nodejs` package is a Node.js addon built based on [Dynamsoft Barcode Reader](https://www.dynamsoft.com/barcode-reader/sdk-desktop-server/). We use it to scan barcode and QR code. 

    
    ```bash
    npm install barcode4nodejs
    ```
    
    Click [here](https://www.dynamsoft.com/customer/license/trialLicense/?product=dbr) to get a valid license key for SDK activation.
    
    ```javascript
    const dbr = require('barcode4nodejs');
    dbr.initLicense("LICENSE-KEY")
    ```
    
- [opencv4nodejs](https://www.npmjs.com/package/opencv4nodejs)
    
    The `opencv4nodejs` package is a Node.js addon for OpenCV. We use it to open camera and read video stream.
    
    ```bash
    npm install opencv4nodejs
    ```

## Customizing Node.js API for Reading Barcode and QR Code 
Currently, the `barcode4nodejs` package only supports a part of C++ API of Dynamsoft Barcode Reader. If the features cannot satisfy your needs, you can use the following steps to customize the JavaScript API:
1. Get the source code of barcode4nodejs.
    
    ```bash
    git clone https://github.com/Dynamsoft/nodejs-barcode
    ```
2. Download [Dynamsoft C++ Barcode SDK](https://www.dynamsoft.com/barcode-reader/downloads). Copy header files to the `src` folder and copy shared libraries to `platforms` folder. Dynamsoft Barcode Reader SDK supports `Windows`, `Linux (AMD64 and ARM64)`, and `macOS`. Theoretically, the Node.js addon can work on all desktop platforms.

3. Edit `src/dbr.cc` and `index.js` to add custom functions.
4. Build the Node.js extension:
    
    ```bash
    node-gyp configure
    node-gyp build
    ```


## Building Node.js Barcode and QR Code Reader for Desktop and Web in 5 Minutes

### Node.js Desktop Application

Create a `desktop.js` file. According to the basic tutorial of `opencv4nodejs`, we can use an infinite loop to capture webcam frames and show them in a desktop window:

```js
const cv = require('opencv4nodejs');
const vCap = new cv.VideoCapture(0);
const delay = 10;
while (true) {
  let frame = vCap.read();
  if (frame.empty) {
    vCap.reset();
    frame = vCap.read();
  }
 
  cv.imshow('OpenCV Node.js', frame);
  const key = cv.waitKey(delay); // Press ESC to quit
  if (key == 27) {break;}
}
```

However, if we invoke the asynchronous function to decode QR code and barcode continuously in the loop, the result callback function will never return. The workaround is to keep calling `setTimeout()` function as barcode and QR code are detected:

```js
const dbr = require('barcode4nodejs');
const cv = require('opencv4nodejs');
dbr.initLicense("LICENSE-KEY")
barcodeTypes = dbr.barcodeTypes
const vCap = new cv.VideoCapture(0);
const drawParams = { color: new cv.Vec(0, 255, 0), thickness: 2 }
const fontFace = cv.FONT_HERSHEY_SIMPLEX;
const fontScale = 0.5;
const textColor = new cv.Vec(255, 0, 0);
const thickness = 2;

results = null;

function getframe() {
    let img = vCap.read();
    dbr.decodeBufferAsync(img.getData(), img.cols, img.rows, img.step, barcodeTypes, function (err, msg) {
        results = msg
    }, "", 1);
    cv.imshow('Webcam', img);
    const key = cv.waitKey(10); // Press ESC to quit
    if (key != 27) {
        setTimeout(getframe, 30);
    }
}

getframe()
```

In the following code, we use OpenCV API to draw an overlay, which show the text and bounding boxes of the detected barcode and QR code. Due to the similarity of the adjacent frames, we do not need to draw a frame and its corresponding results synchronously. A little bit of delay is acceptable.

```js
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);

        img.drawLine(upperLeft, bottomLeft, drawParams);
        img.drawLine(bottomLeft, upperRight, drawParams);
        img.drawLine(upperRight, bottomRight, drawParams);
        img.drawLine(bottomRight, upperLeft, drawParams);

        img.putText(result.value, new cv.Point(result.x1, result.y1 + 10), fontFace, fontScale, textColor, thickness);
    }
}
```

![OpenCV Node.js barcode and QR code reader with webcam](https://www.dynamsoft.com/codepool/img/2020/07/nodejs-barcode-opencv-webcam.png)

### Node.js Web Application

Create a `web.js` file, in which we add the following code to launch a web server:

```javascript
var fs=require("fs");
var html = fs.readFileSync("index.htm", "utf8");

var server = http.createServer(function (req, res) {  
    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();
    }
});

server.listen(2020);

console.log('Node.js web server is running at port 2020...')
```

Copy the code used in `desktop.js` to `web.js`. Instead of using `cv.imshow()` to show the webcam image in a desktop window, we use `res.write()` to send the image data to the web client. 

The next step is to create an HTML page to display the image data:

```js
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Webcam</title>
</head>

<body>
    <img id="image" width="960" />

    <script type="text/javascript">
        var image = document.getElementById('image');
        function refresh() {
            image.src = "/image?" + new Date().getTime();
            image.onload= function(){
                setTimeout(refresh, 30);
            }
        }
        
        refresh();
    </script>

</body>
</html>
```

There is no advanced HTML5 API used but an image element. Therefore, the web application is 100% compatible with any web browser.

Now we can run the server-side barcode and QR code scanning app using Node.js. 

```bash
node web.js
```

Here is a screenshot from **Microsoft Internet Explorer**.

![OpenCV Node.js Barcode and QR code for web](https://www.dynamsoft.com/codepool/img/2020/07/opencv-nodejs-barcode-web-1000x705.png)

## Source Code

[https://github.com/yushulx/nodejs-barcode-reader](https://github.com/yushulx/nodejs-barcode-reader)