Building HTML5 Barcode Reader with Pure JavaScript SDK

Last week, I had successfully built JavaScript and WebAssembly ZXing barcode SDK. In this post, I will use the pure JavaScript barcode SDK to create a simple client-side HTML5 barcode reader app, which works in any WebRTC supported web browsers.

Supported Barcode Formats

Check ZXing source code to see what barcode formats are supported:

const DecodeHints DecodeHints::PRODUCT_HINT(
  UPC_A_HINT |
  UPC_E_HINT |
  EAN_13_HINT |
  EAN_8_HINT |
  RSS_14_HINT
  );

const DecodeHints DecodeHints::ONED_HINT(
  CODE_39_HINT |
  CODE_93_HINT |
  CODE_128_HINT |
  ITF_HINT |
  CODABAR_HINT |
  DecodeHints::PRODUCT_HINT
  );

const DecodeHints DecodeHints::DEFAULT_HINT(
  ONED_HINT |
  QR_CODE_HINT |
  DATA_MATRIX_HINT |
  AZTEC_HINT |
  PDF_417_HINT
  );

We can use DEFAULT_HINT to read all formats:

DecodeHints hints(DecodeHints::DEFAULT_HINT);
binarizer = new HybridBinarizer(source);
binary = new BinaryBitmap(binarizer);
results = decode_any_(binary, hints);

How to Open and Select Camera using HTML5

If you have no idea about how to use HTML5 to control cameras in WebRTC supported web browsers, visit https://simpl.info/getusermedia/sources/ to learn the source code:

var videoSelect = document.querySelector('select#videoSource');

navigator.mediaDevices.enumerateDevices()
  .then(gotDevices).then(getStream).catch(handleError);

videoSelect.onchange = getStream;

function gotDevices(deviceInfos) {
  for (var i = deviceInfos.length - 1; i >= 0; --i) {
    var deviceInfo = deviceInfos[i];
    var option = document.createElement('option');
    option.value = deviceInfo.deviceId;
    if (deviceInfo.kind === 'videoinput') {
      option.text = deviceInfo.label || 'camera ' +
        (videoSelect.length + 1);
      videoSelect.appendChild(option);
    } else {455
      console.log('Found one other kind of source/device: ', deviceInfo);
    }
  }
}

function getStream() {
  buttonGo.disabled = false;
  if (window.stream) {
    window.stream.getTracks().forEach(function(track) {
      track.stop();
    });
  }

  var constraints = {
    video: {
      deviceId: {exact: videoSelect.value}
    }
  };

  navigator.mediaDevices.getUserMedia(constraints).
    then(gotStream).catch(handleError);
}

function gotStream(stream) {
  window.stream = stream; // make stream available to console
  videoElement.srcObject = stream;
}

function handleError(error) {
  console.log('Error: ', error);
}

Note: when deploying the source code to your web server, you have to bind an SSL certificate. Otherwise, the camera cannot be opened, and you will see following warnings in Chrome console:

[Deprecation] getUserMedia() no longer works on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.

Assume the web server is IIS, you can easily configure SSL certificate as follows:

SSL binding

HTML5 Barcode Reader

Basic steps

Draw video image to a temporary canvas:

  var barcodeCanvas = document.createElement("canvas");
  barcodeCanvas.width = vid.videoWidth;
  barcodeCanvas.height = vid.videoHeight;
  var barcodeContext = barcodeCanvas.getContext('2d');
  var imageWidth = vid.videoWidth, imageHeight = vid.videoHeight;
  barcodeContext.drawImage(videoElement, 0, 0, imageWidth, imageHeight);

Get image data from the canvas:

var imageData = barcodeContext.getImageData(0, 0, imageWidth, imageHeight);
var idd = imageData.data;

Copy pixels to a ZXing buffer:

var image = ZXing._resize(imageWidth, imageHeight);
  for (var i = 0, j = 0; i < idd.length; i += 4, j++) {
    ZXing.HEAPU8[image + j] = idd[i];
  }

Call ZXing._decode_any() to read barcode:

var err = ZXing._decode_any(decodePtr);

Testing Environment

Desktop Chrome 62.0.3202.94

Works for both JavaScript and WebAssembly ZXing.

Android Chrome 63.0.3239.111

Work for both JavaScript and WebAssembly ZXing.

iOS (11.2.1) Safari

iPhone does not support WebRTC well. I can successfully invoke cameras on iPad. However, WebAssembly is not supported.

Remotely Debugging HTML5 Barcode Reader

Enable USB debugging in Android developer settings.

Open Chrome on Android devices.

Connect Android devices to PC.

Open chrome://inspect in desktop Chrome:

Chrome inspect

Debug the app:

debug HTML5 barcode reader

Running HTML5 Barcode Reader in Android Chrome

Android HTML5 barcode reader

Source Code

https://github.com/yushulx/zxing-cpp-emscripten/tree/master/examples/js

https://github.com/yushulx/zxing-cpp-emscripten/tree/master/examples/wasm

  • http://www.magetricks.com/ MageTricks

    Got it, thank you!

  • http://www.dynamsoft.com/ Xiao Ling

    Seems WebRTC works on iPad not iPhone. I think the issue belongs to Apple :)

  • http://www.magetricks.com/ MageTricks

    Tested on Android with Chrome and OSX with Safari and it works very well! Tried a few other web-based barcode readers which required server-side components but I definitely prefer this one. The accuracy is 100% for me. I also tested on iPhone 6 & iPhone 8 but couldn’t get camera to display. I’m assuming WebRTC is the cause of this but not sure. Any thoughts?