diff --git a/packages/qr-code-scanner/rollup.config.js b/packages/qr-code-scanner/rollup.config.js index 83266356c8b804099630e5bd4e88f6b0f0855126..c0dbd55cc75ea90e600807d23b448f4ed4ca01d1 100644 --- a/packages/qr-code-scanner/rollup.config.js +++ b/packages/qr-code-scanner/rollup.config.js @@ -72,6 +72,7 @@ export default (async () => { {src: 'assets/index.html', dest: 'dist'}, {src: 'assets/favicon.ico', dest: 'dist'}, {src: await getPackagePath('dbp-common', 'assets/icons/*.svg'), dest: 'dist/local/dbp-common/icons'}, + {src: await getPackagePath('qr-scanner', 'qr-scanner-worker.*'), dest: 'dist/local/qr-code-scanner'}, ] }), (process.env.ROLLUP_WATCH === 'true') ? serve({ diff --git a/packages/qr-code-scanner/src/qr-code-scanner.js b/packages/qr-code-scanner/src/qr-code-scanner.js index f8504b21448bb48f2fc89a69f5f27a4b1ac6ca09..5b7e42f2c58a3a3106bf0fafc99f409b94a9337b 100644 --- a/packages/qr-code-scanner/src/qr-code-scanner.js +++ b/packages/qr-code-scanner/src/qr-code-scanner.js @@ -5,9 +5,11 @@ import * as commonStyles from 'dbp-common/styles'; import {ScopedElementsMixin} from '@open-wc/scoped-elements'; import {Icon, MiniSpinner} from 'dbp-common'; import {classMap} from 'lit-html/directives/class-map.js'; +import * as commonUtils from 'dbp-common/utils'; import jsQR from "jsqr"; import {getIconSVGURL} from 'dbp-common'; import {Mutex} from 'async-mutex'; +import QrScanner from 'qr-scanner'; /** @@ -98,6 +100,42 @@ async function createVideoElement(deviceId) { } +class jsQRScanner { // eslint-disable-line no-unused-vars + constructor() { + } + + async scan(canvas, x, y, width, height) { + let imageData = canvas.getContext("2d").getImageData(x, y, width, height); + const code = jsQR(imageData.data, imageData.width, imageData.height, { + inversionAttempts: "dontInvert", + }); + if (code === null) + return null; + return {'data': code.data}; + } +} + + +class QRScanner { + constructor() { + QrScanner.WORKER_PATH = commonUtils.getAssetURL('qr-code-scanner', 'qr-scanner-worker.min.js'); + this._engine = null; + this._canvas = document.createElement("canvas"); + } + + async scan(canvas, x, y, width, height) { + if (this._engine === null) { + this._engine = await QrScanner.createQrEngine(QrScanner.WORKER_PATH); + } + try { + return {data: await QrScanner.scanImage(canvas, {x: x, y: y, width: width, height: height}, this._engine, this._canvas)}; + } catch (e) { + return null; + } + } +} + + export class QrCodeScanner extends ScopedElementsMixin(DBPLitElement) { constructor() { super(); @@ -214,7 +252,9 @@ export class QrCodeScanner extends ScopedElementsMixin(DBPLitElement) { let lastCode = null; let lastSentData = null; - const tick = () => { + let detector = new QRScanner(); + + const tick = async () => { this._requestID = null; if (video.readyState === video.HAVE_ENOUGH_DATA) { this._loading = false; @@ -242,10 +282,7 @@ export class QrCodeScanner extends ScopedElementsMixin(DBPLitElement) { let shouldAnalyze = Math.abs(lastVideoScanTime - video.currentTime) >= 1/3; if (shouldAnalyze) { lastVideoScanTime = video.currentTime; - let imageData = canvas.getImageData(maskStartX, maskStartY, maskWidth, maskHeight); - code = jsQR(imageData.data, imageData.width, imageData.height, { - inversionAttempts: "dontInvert", - }); + code = await detector.scan(canvasElement, maskStartX, maskStartY, maskWidth, maskHeight); lastCode = code; } else { code = lastCode;