Add Auto-Zoom to a Web QR Code Scanner

In the previous article, we’ve talked about how to control camera zoom on the web. In this article, we are going to add the feature to automatically zoom in to scan a tiny or distant QR code to a web QR code scanner.

Dynamsoft Barcode Reader is used to read QR codes and detect whether there are QR codes in the camera preview.

Demo video:

This article is Part 2 in a 2-Part Series.

Getting started with Dynamsoft Barcode Reader

Build a Web QR Code Scanner

First, let’s create a web QR code scanner.

  1. Create a new HTML file with the following template:

    <!DOCTYPE html>
    <html>
    <head>
      <title>QR Code Scanner with Auto-Zoom</title>
      <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />
      <style>
        #enhancerUIContainer {
          height: 480px;
          max-width: 100%;
        }
    
        .results {
          border: 1px black solid;
          margin: 10px 0;
          padding: 5px;
          height: 75px;
          overflow: auto;
        }
      </style>
    </head>
    <body>
      <h2>QR Code Scanner with Auto-Zoom</h2>
      <label>
        Camera:
        <select id="select-camera"></select>
      </label>
      <label>
        Resolution:
        <select id="select-resolution">
          <option value="640x480">640x480</option>
          <option value="1280x720">1280x720</option>
          <option value="1920x1080" selected>1920x1080</option>
          <option value="3840x2160">3840x2160</option>
        </select>
      </label>
      <button onclick="startCamera();">Start Camera</button>
      <br/>
      <div class="results">
        <div>Results:</div>
        <ol></ol>
      </div>
      <div id="enhancerUIContainer"></div>
      <script type="text/javascript">
      </script>
    </body>
    </html>
    
  2. Include libraries in the head.

    <script src="https://cdn.jsdelivr.net/npm/dynamsoft-core@3.2.10/dist/core.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/dynamsoft-license@3.2.10/dist/license.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/dynamsoft-utility@1.2.10/dist/utility.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader@10.2.10/dist/dbr.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/dynamsoft-capture-vision-router@2.2.10/dist/cvr.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/dynamsoft-camera-enhancer@4.0.2/dist/dce.js"></script>
    
  3. Initialize the license to use Dynamsoft’s SDKs. You can apply for a license here.

    let license = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="; //one-day trial license
    Dynamsoft.License.LicenseManager.initLicense(license);
    
  4. Initialize Dynamsoft Camera Enhancer for camera control.

    let cameraView = await Dynamsoft.DCE.CameraView.createInstance();
    cameraEnhancer = await Dynamsoft.DCE.CameraEnhancer.createInstance(cameraView);
    document.querySelector("#enhancerUIContainer").append(cameraView.getUIElement());
    
  5. Initialize capture vision router to call Dynamsoft Barcode Reader.

    Dynamsoft.Core.CoreModule.loadWasm(["dbr"]);
    router = await Dynamsoft.CVR.CaptureVisionRouter.createInstance();
    
  6. Set the camera enhancer as the input of the capture vision router. The capture vision router will try to get camera frames from it and read barcodes. A filter is also set so that it will verify the results based on readings of multiple frames and avoid returning duplicate barcodes too quickly.

    router.setInput(cameraEnhancer);
    
    router.addResultReceiver({ onDecodedBarcodesReceived: (result) => {
      displayResults(result);
    }});
    
    let filter = new Dynamsoft.Utility.MultiFrameResultCrossFilter();
    filter.enableResultCrossVerification("barcode", true);
    filter.enableResultDeduplication("barcode", true);
    await router.addResultFilter(filter);
    
  7. Start the selected camera and start capturing barcodes after the camera is opened.

    async function startCamera(){
      let selectedCamera = cameras[document.getElementById("select-camera").selectedIndex];
      let selectedResolution = document.getElementById("select-resolution").selectedOptions[0].value;
      let width = parseInt(selectedResolution.split("x")[0]);
      let height = parseInt(selectedResolution.split("x")[1]);
         
      await cameraEnhancer.selectCamera(selectedCamera);
      await cameraEnhancer.setResolution({width:width, height:height});
      await cameraEnhancer.open();
      await router.startCapturing("ReadSingleBarcode");
    }
    

    The results will be displayed in a container.

    function displayResults(result){
      if (result.barcodeResultItems.length > 0) {   
        let ol = document.querySelector(".results ol");
        ol.innerHTML = "";
        for (let index = 0; index < result.barcodeResultItems.length; index++) {
          const item = result.barcodeResultItems[index];
          const li = document.createElement("li");
          li.innerText = item.formatString+": "+item.text;
          ol.appendChild(li);
        }
      }
    }
    

Enable Auto-Zoom

After the web QR code scanner is done, we can enable auto-zoom to improve the scanning of a tiny or distant QR code. If there is a QR code in the camera preview that cannot be read, auto-zoom will be triggered. After zooming, if it cannot read QR codes in several seconds, it will return to the default zoom status.

This feature is included in Dynamsoft Camera Enhancer. We can enable it with the following code:

await cameraEnhancer.enableEnhancedFeatures(Dynamsoft.DCE.EnumEnhancedFeatures.EF_AUTO_ZOOM);

How Auto-Zoom Works

So how does auto-zoom work exactly?

If a QR code’s location is detected but is too small and cannot be read, we can trigger the camera zoom to get a better QR code image for reading. Dynamsoft Barcode Reader’s intermediate result feature is used to get the unread QR code’s location.

Here is the code to get the location:

const intermediateResultManager = router.getIntermediateResultManager();
const intermediateResultReceiver = new Dynamsoft.CVR.IntermediateResultReceiver();
intermediateResultReceiver.onLocalizedBarcodesReceived = (result, info) => {
  console.log(result);
};
intermediateResultManager.addResultReceiver(intermediateResultReceiver);

Then, we can calculate the zoom factor to maximize the QR code image in the camera preview.

function calculatedFactor(localizedBarcode){
  let left = localizedBarcode.location.points[0].x;
  let top = localizedBarcode.location.points[0].y;
  let video = document.getElementById("video");
  let width = video.videoWidth;
  if (left < width/2) {
    let croppedWidth = Math.max(0,left - 50);
    if (croppedWidth == 0) {
      return 1.0;
    }
    let maxCroppedWidth = top;
    croppedWidth = Math.min(maxCroppedWidth,croppedWidth);
    return width / (width - (croppedWidth * 2));
  }else{
    return 1.0;
  }
}

Source Code

Get the source code of the demos to have a try:

https://github.com/tony-xlh/Vanilla-JS-Barcode-Reader-Demos/tree/main/autozoom