Online QR Code Scanner in HTML5 and JavaScript

Originally designed for the automotive industry1, QR code (abbreviated from Quick Response code) has become popular in various usage scenarios. QR codes can encode richer content than 1D barcodes, from website URLs to even a small image. They can be displayed on screens and printed on posters, package boxes, etc. People can easily scan them with their mobile phones.

dynamsoft qr code scanner

Dynamsoft Barcode Reader (DBR) has good support for QR codes. It has a JavaScript package since May 25th, 2017. It is easy to use DBR to create a web QR code scanner with high speed and accuracy. Since it is HTML5-based, users don’t have to download and install apps, and it’s easy to integrate the qr code engine into your applications on different platforms.

There is an out-of-the-box mobile web demo that runs purely on the client-side. It can scan with the built-in camera or read barcodes from the image gallery.

The Hello World Example - An Online QR Code Scanner

Creating your mobile web scanner is simple. There are many samples in this GitHub repo. Some samples demonstrate how to use DBR with Vue, React, and Angular. Some are designed as PWA or hybrid apps. You can start with a basic sample: helloworld.html.

Let’s explore it in detail. It first loads DBR by loading its JS file.

<!-- Please visit https://www.dynamsoft.com/customer/license/trialLicense to get a trial license. -->
<script src="https://cdn.jsdelivr.net/npm/dynamsoft-javascript-barcode@9.0.0/dist/dbr.js"></script>

<script>
Dynamsoft.DBR.BarcodeReader.license = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==";
</script>

The page contains a button to show the scanner and a button to choose local images to decode.

HTML:

<div id="status">Initializing...</div>
Choose image(s) to decode:
<input id="ipt-file" type="file" multiple accept="image/png,image/jpeg,image/bmp,image/gif" disabled>
<br><br>
<button id="btn-show-scanner" disabled>show scanner</button>

A reader instance and a scanner instance are created when the page is loaded.

// reader for decoding picture
let reader = null;
// scanner for decoding video
let scanner = null;
window.onload = async function() {
    reader = await Dynamsoft.DBR.BarcodeReader.createInstance();
    if (reader) {
        document.getElementById('ipt-file').disabled = "";
    }
    scanner = await Dynamsoft.DBR.BarcodeScanner.createInstance();
    if (scanner) {
        document.getElementById('btn-show-scanner').disabled = "";
    }
    
    if (reader!= null || scanner!=null) {
        document.getElementById('status').remove();
    }
}

The following demonstrates how to use the reader to decode statc images and the scanner to do a live scan.

Scan from images

JavaScript for decoding pictures:

// decode input picture
document.getElementById('ipt-file').addEventListener('change', async function(){
    let resultsToAlert = [];
    for(let i = 0; i < this.files.length; ++i){
        let file = this.files[i];
        resultsToAlert.push(i + '. ' + file.name + ":");
        let results = await reader.decode(file);
        console.log(results);
        for(let result of results){
            resultsToAlert.push(result.barcodeText);
        }
    }
    alert(resultsToAlert.join('\n'));
    this.value = '';
});

Scan from live video

JavaScript for live scan:

// decode video from camera
document.getElementById('btn-show-scanner').addEventListener('click', async () => {
    /** 
     * onFrameRead is triggered after the library finishes reading a frame image.
     * There can be multiple barcodes on one image.
     */
    scanner.onFrameRead = results => {
        if(results.length){
            console.log(results);
        }
    };
    /**
     * onUniqueRead is triggered only when a 'new' barcode is found.
     * The amount of time that the library 'remembers' a barcode is defined by 
     * "duplicateForgetTime" in "ScanSettings". By default it is set to 3000 ms.
     */
    scanner.onUniqueRead = (txt, result) => {
        alert(result.barcodeFormatString + ': ' + txt);
    };
    await scanner.show();
});

PS: The BarcodeScanner class has all the methods of BarcodeReader. It can also be used to decode images.

Customize the UI

The UI of the scanner is defined in dist/dbr.ui.html2:

You can copy its content to your HTML file, customize it and load it with this line of code:

scanner.setUIElement(scannerElement);

Run the demo

You can try the helloworld online demo here.

Runtime Settings for Decoding QR Codes

We can customize and optimize DBR’s runtime settings3 for different usage scenarios to improve the scanning performance. For example, if we only want to scan one single QR code, we can modify the settings with the updateRuntimeSettings method:

let settings = await scanner.getRuntimeSettings();
settings.expectedBarcodesCount=1;
settings.barcodeFormatIds=Dynamsoft.DBR.EnumBarcodeFormat.BF_QR_CODE;
await scanner.updateRuntimeSettings(settings);

By using these settings, only QR codes will be recognized. This will improve the decoding speed as well. Decoding speed is very important for real-time video stream scanning.

In some cases, the QR codes might be incomplete or deformed. These kinds of codes can be found on plastic bags, ripped receipts, etc. DBR has built-in code complement and deform-resist algorithms to restore these QR codes.

Scan Incomplete QR Codes

DBR offers the capability to auto-restore missing portions of a QR code from poor printing or damage.

Incomplete QR Code

For the incomplete QR code above, we can add the BarcodeComplementModes parameter to the template to successfully decode the barcode.

Note: There are two ways to modify the runtime settings. One is using code as in the example above and the other is using a JSON template as below (usage).

{
    "Version":"3.0",
    "ImageParameter": 
    {
        "Name": "default",
        "ExpectedBarcodesCount": 1,
        "MaxAlgorithmThreadCount": 4,
        "BarcodeFormatIds": [ "BF_QR_CODE" ],
        "BarcodeComplementModes": [
          {
            "Mode": "BCM_SKIP"
          },
          {
            "LibraryFileName": "",
            "LibraryParameters": "",
            "Mode": "BCM_GENERAL"
          }
        ]
    }
}

Scan Deformed QR Codes

DBR comes with a sophisticated algorithm to improve the decoding success rate for wrinkled and deformed QR codes.

Deformed QR Code

For the deformed QR code above, we can include the DeformationResistingModes parameter in the template.

{
    "Version":"3.0",
    "ImageParameter": 
    {
        "Name": "default",
        "ExpectedBarcodesCount": 1,
        "MaxAlgorithmThreadCount": 4,
        "BarcodeFormatIds": [ "BF_QR_CODE" ],
        "DeformationResistingModes": [
          {
            "Mode": "DRM_SKIP"
          },
          {
            "Level": 5,
            "LibraryFileName": "",
            "LibraryParameters": "",
            "Mode": "DRM_GENERAL"
          }
        ]
    }
}

Read QR Codes from a Specific Region

Another useful setting is to specify an area/region to read:

let settings = await scanner.getRuntimeSettings();
/*
 * 1 means true
 * Using a percentage is easier
 * The following code shrinks the decoding region by 25% on all sides
 */
settings.region.regionMeasuredByPercentage = 1;
settings.region.regionLeft = 25;
settings.region.regionTop = 25;
settings.region.regionRight = 75;
settings.region.regionBottom = 75;
await scanner.updateRuntimeSettings(settings);

A viewfinder box would appear on the video stream and users can then align the QR code within the box to read it. A better alignment would also speed up the decoding process.

Specific region

Scan Multiple QR Codes in One Shot

DBR has the ability to read a large number of QR codes in one shot.

Multiple QR Codes

Variations of QR Codes

Other variations of QR code (Micro QR Code and Model 1) are also supported.

Micro QR code (demo created by the author)

More about Dynamsoft Barcode Reader

Built-in Templates

DBR JS has four built-in templates: speed, balance, coverage and single.

  • The speed template is a good fit if you want to do a live scan. But if there are many QR codes to decode or the image is complex, it may miss some of them.
  • Then the coverage template is a better choice, though it needs more time computing.
  • The balance template takes both speed and coverage into consideration.
  • The single template is optimized for scanning one barcode.

To use one of the built-in templates, use this line of code:

await scanner.updateRuntimeSettings("<template>"); // template: single, speed, balance, coverage

Create Your Own Templates

You can create your own template for your specific use cases. Our online demo is convenient to try out the different parameters.

A JSON template looks like this:

{
    "Version":"3.0",
    "ImageParameter": 
    {
        "Name": "default",
        "ExpectedBarcodesCount": 1,
        "BarcodeFormatIds": [ "BF_QR_CODE" ]
    }
}

A template can be stored in a text area. E.g., we can load it with the following code:

await scanner.initRuntimeSettingsWithString(templateString);

Getting Started

Download Dynamsoft Barcode Reader SDK to try it on your own.

Ionic Demo

Here is a post illustrating how to build an Ionic mobile QR Code scanner: https://www.dynamsoft.com/codepool/ionic-react-qr-code-scanner.html

Integration in Mobile Apps

You can also use Dynamsoft Barcode Reader JavaScript in WebView to integrate it in Android and iOS apps.

Source Code

  1. Official GitHub repo of the JavaScript Barcode Reader
  2. Official samples

References

  1. https://en.wikipedia.org/wiki/QR_code 

  2. https://github.com/Dynamsoft/javascript-barcode#customizing-the-ui 

  3. https://www.dynamsoft.com/barcode-reader/programming/javascript/user-guide/basic-customizations.html?ver=latest#configuring-scanner-settings