Files
2026-02-17 14:58:53 -06:00

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