Using BarcodeDecoder in javascript
- Important notes
- The Barcode Detection API
- How to use
- Supported formats
- Compatiblity
- Support in @mebjas/html5-qrcode
- Performance
- Embedded Demo
- Conclusion
- References
In the past the APIs like MediaDevices.getUserMedia(), local file reading API made it fairly easy
to capture images and process them. This made libraries like @mebjas/html5-qrcode
possible - which today allows developers to easily integrate QR code or bar code
scanning capabilities to their web applications. Several developers have used
the library to build Android applications using Cordova. Now the Web Platform
Incubator Community Group has come with
a draft for shape detector APIs
which aims at providing access to accelearated shape detectors (like human faces,
QR codes, bar codes, etc) for still images and live image feeds. This is
particularly exciting for mobile devices which today comes with hardware chips
which are highly performant at certain tasks like detecting faces, barcodes, texts etc.
In this article, I have explained how to use the new BarcodeDetector
library and how
it can be used directly with html5-qrcode and
what kind of performance improvement we see when compared to ZXingJS
library.
Figure: QR Code scanning is used extensively in the post Covid19 world to enable, contact less information sharing.
This new API is part of the new capabilities project. Barcode detection has launched in Chrome 83
. If the APIs evolve in future this article would be updated.
Important notes
The Shape detector APIs
are still in draft and not a W3C standard
not it is
on the W3C Standards Track. The feature can still be turned on in the library
as it’d fallback to using ZXing
based detector if BarcodeDectector
library
is not available.
The Barcode Detection API
BarcodeDetector
represents an underlying accelerated platform’s component for detection of linear or two-dimensional barcodes in images. It provides a singledetect()
operation on anImageBitmapSource
which result is aPromise
.
Source: wicg.github.io/shape-detection-api/
The draft proposal expects core system APIs like com.google.android.gms.vision.barcode, CIQRCodeFeature or VNDetectBarcodesRequest to act as underlying components.
By providing high-performance shape detection capabilities this interface allows developers to run image analysis tasks on the local device. This offers a privacy advantage over offloading computation to a remote system. Developers should consider the results returned by this interface as privacy sensitive as the original image from which they were derived.
How to use
The BarcodeDetector
API has following interface (based on documentation):
enum BarcodeFormat {
"aztec",
"code_128",
"code_39",
"code_93",
"codabar",
"data_matrix",
"ean_13",
"ean_8",
"itf",
"pdf417",
"qr_code",
"unknown",
"upc_a",
"upc_e"
};
/** Config to create instance of {@code BarcodeDetector}. */
interface BarcodeDetectorConfig {
formats: Array<string>;
}
interface BarcodeDetectorResult {
/**
* A DOMRectReadOnly, which returns the dimensions of a rectangle
* representing the extent of a detected barcode, aligned with the image.
*/
boundingBox: DOMRectReadOnly;
/**
* The x and y co-ordinates of the four corner points of the detected
* barcode relative to the image, starting with the top left and working
* clockwise. This may not be square due to perspective distortions within
* the image.
*/
cornerPoints: Array<Point2D>;
/** The detected barcode format. */
format: BarcodeFormat;
/** A String decoded from the barcode data. */
rawValue: string;
}
class BarcodeDetector {
constructor(config: BarcodeDetectorConfig) {}
/** Async decoding API. */
async decode(source: ImageBitmapSource): Promise<BarcodeDetectorResult> {}
/** Returns list of supported formats as string. */
static getSupportedFormats(): Array<string> {}
}
An example usage in Javascript would look like this:
// Get supported formats:
let supportedFormats = new BarcodeDetector.getSupportedFormats();
let barcodeDetector = new BarcodeDetector({ formats: supportedFormats });
try {
let detector = await barcodeDetector.detect(canvas);
barcodes.forEach(barcode => {
// Handle barcode of format BarcodeDetectorResult
});
} catch (error) {
console.error(error);
}
Supported formats
The library specification has a support for variety of 2D and 1D code formats like
QR Code
, Aztec
, code_128
, code_39
, etc. A full list of all supported formats
is listed here.
Important: While the specification defines formats API support, the actual
support depends on browser and device implementations. The supported format
list should always be first queried using BarcodeDetector.getSupportedFormats()
API.
Compatiblity
Compatibility as of 20th June 2020
Figure: Compatibility of the API, source - developer.mozilla.org
Support in @mebjas/html5-qrcode
I learned about this API when AlfonsoML@
filed a feature request #195 in the project to add support for BarcodeDetector
API.
Is your feature request related to a problem? Please describe.
Chromium has added native support to detect barcodes, so using it would be interesting as it can lead to better performance in the long term.
…
As an author of the project it was very exciting to see web coming with support
for hardware acceleration to boost performance of a very common usecase in todays
world. Current ZXing
based decoder takes ~350+ms
to scan a single feed,
which leads to less than ideal real time performance. And, also it’s a shame, if
the web applications cannot make use of exact support availabe in the hardware.
With pull request #238 I have
added support for using BarcodeDetector
API if supported by the browser after
doing performance investigations (see results below). It’s supported both in
Html5Qrcode &
Html5QrcodeScanner
classes (read more on how to use Html5Qrcode to scan QR & bar codes in javascript
with few lines of code).
Using this API is now supported in the library as an experimental feature. An experimental feature is one that is:
- Supported in the library, can be turned on using certain config
- Is not directly documented, but some context exists here
- Is not recommeded for production usage yet
- Can be migrated to full scale feature set if the feature is well tested and has wider compatibility.
How to use this in the library
It can be turned on using new config called useBarCodeDetectorIfSupported
added to experimentalFeatures
config group. It’s off (value = false
) by
default. If set to on (value = true
) and the BarcodeDetector
is supported
by the browser, it’ll be used for scanning all the kind of 1D and 2D codes.
Html5Qrcode class
function onScanSuccess(decodedText, decodedResult) {
/** Handle success condition. */
}
let html5qrcode = new Html5Qrcode("reader", {
// Use this flag to turn on the feature.
experimentalFeatures: {
useBarCodeDetectorIfSupported: true
}
});
const scanConfig = { fps: 10, qrbox: 250 };
// If you want to prefer front camera
html5qrcode.start({ facingMode: "user" }, scanConfig, onScanSuccess);
Html5QrcodeScanner class
function onScanSuccess(decodedText, decodedResult) {
/** Handle success condition. */
}
let html5QrcodeScanner = new Html5QrcodeScanner(
"reader",
{
fps: 10,
qrbox: 250,
// Use this flag to turn on the feature.
experimentalFeatures: {
useBarCodeDetectorIfSupported: true
}
});
html5QrcodeScanner.render(onScanSuccess);
Performance
I conducted the performance test on different devices to see how BarcodeDecoder
API performed as compared to non accelerated ZXingJS
based library. Numbers below
are the average time it took for decoding any given image feed for supported QR code
or bar codes in milli seconds.
Device | With ZXing | With BarcodeDecoder |
---|---|---|
Macbook Pro 16, Google Chrome | 21 ms | 10 ms |
Pixel 4 Google Chrome | 56 ms | 23 ms |
Pixel 4a Google Chrome | 92 ms | 47.3 ms |
(low end) Android Device Google Chrome | 373 ms | 77.5 ms |
Across devices & browsers where it was supported (example Safari on Macbook pro
Big Sur doesn’t support this API yet), the BarcodeDetector
API performed better
than ZXing
based library.
Embedded Demo
See full scale demo at qrcode.minhazav.dev
Conclusion
BarcodeDetector
is easy to use WIP library, and it would be super useful to both developers and users in the future.- If this API starts to get wider adoption across browers and hardware, I am happy to migrate this from experimental to more well tested and documented feature set.
Happy to hear what you think about this in the comment section!
References
- mebjas/html5-qrcode - end to end QR & bar code scannign library in javascript
- MediaDevices.getUserMedia()
- The Shape Detection API: a picture is worth a thousand words, faces, and barcodes
- BarcodeDetector - developer.mozilla.org
Want to read more such similar contents?
I like to write articles on topic less covered on internet. They revolve around writing fast algorithms, image processing as well as general software engineering.
I publish many of them on Medium.
If you are already on medium - Please join 4200+ other members and Subscribe to my articles to get updates as I publish.
If you are not on Medium - Medium has millions of amazing articles from 100K+ authors. To get access to those, please join using my referral link. This will give you access to all the benefits of Medium and Medium shall pay me a piece to support my writing!
Thanks!