84 lines
3.3 KiB
JavaScript
84 lines
3.3 KiB
JavaScript
import { BrowserMultiFormatReader } from '@zxing/browser';
|
|
import { DecodeHintType, NotFoundException } from '@zxing/library';
|
|
import { nativeToZxingFormat, zxingToNativeFormat } from './constants';
|
|
export class BarcodeDetector {
|
|
reader;
|
|
constructor(options) {
|
|
const hints = new Map([
|
|
[DecodeHintType.TRY_HARDER, true],
|
|
[
|
|
DecodeHintType.POSSIBLE_FORMATS,
|
|
options
|
|
? options.formats.map((f) => nativeToZxingFormat[f])
|
|
: Object.values(nativeToZxingFormat),
|
|
],
|
|
]);
|
|
this.reader = new BrowserMultiFormatReader(hints);
|
|
}
|
|
static getSupportedFormats() {
|
|
return Promise.resolve(Object.values(zxingToNativeFormat));
|
|
}
|
|
async detect(imageSource) {
|
|
try {
|
|
let result;
|
|
if (imageSource instanceof HTMLVideoElement || imageSource instanceof HTMLImageElement) {
|
|
result = await this.reader.scanOneResult(imageSource, false);
|
|
}
|
|
else if (imageSource instanceof HTMLCanvasElement) {
|
|
result = this.reader.decodeFromCanvas(imageSource);
|
|
}
|
|
else if (imageSource instanceof Blob) {
|
|
const image = await this.blobToImage(imageSource);
|
|
result = await this.reader.scanOneResult(image, false);
|
|
}
|
|
else if (imageSource instanceof ImageBitmap
|
|
|| imageSource instanceof ImageData
|
|
|| imageSource instanceof VideoFrame) {
|
|
result = this.reader.decodeFromCanvas(this.imageDataSourceToCanvas(imageSource));
|
|
}
|
|
else {
|
|
throw new TypeError('Image source is not supported');
|
|
}
|
|
return [{
|
|
rawValue: result.getText(),
|
|
format: zxingToNativeFormat[result.getBarcodeFormat()],
|
|
boundingBox: new DOMRectReadOnly(), // TODO: think of a way to map this in a meaningful way
|
|
cornerPoints: result.getResultPoints().map((p) => ({ x: p.getX(), y: p.getY() })),
|
|
}];
|
|
}
|
|
catch (err) {
|
|
if (err && !(err instanceof NotFoundException)) {
|
|
throw err;
|
|
}
|
|
return [];
|
|
}
|
|
}
|
|
async blobToImage(blob) {
|
|
return new Promise((resolve, reject) => {
|
|
const imageObjUrl = URL.createObjectURL(blob);
|
|
const image = new Image();
|
|
image.onload = () => {
|
|
URL.revokeObjectURL(imageObjUrl);
|
|
resolve(image);
|
|
};
|
|
image.onerror = () => reject();
|
|
image.src = imageObjUrl;
|
|
});
|
|
}
|
|
imageDataSourceToCanvas(source) {
|
|
const canvas = document.createElement('canvas');
|
|
const ctx = canvas.getContext('2d');
|
|
const width = source instanceof VideoFrame ? source.displayWidth : source.width;
|
|
const height = source instanceof VideoFrame ? source.displayHeight : source.height;
|
|
if (ctx) {
|
|
if (source instanceof ImageData) {
|
|
ctx.putImageData(source, width, height);
|
|
}
|
|
else {
|
|
ctx.drawImage(source, width, height);
|
|
}
|
|
}
|
|
return canvas;
|
|
}
|
|
}
|
|
//# sourceMappingURL=BarcodeDetector.js.map
|