@wemap/camera 11.0.0 → 12.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +11 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -5,14 +5,11 @@ var __publicField = (obj, key, value) => {
|
|
|
5
5
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6
6
|
return value;
|
|
7
7
|
};
|
|
8
|
-
Object.
|
|
8
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
9
9
|
const library = require("@zxing/library");
|
|
10
10
|
const EventEmitter = require("events");
|
|
11
11
|
const Logger = require("@wemap/logger");
|
|
12
|
-
|
|
13
|
-
const EventEmitter__default = /* @__PURE__ */ _interopDefaultLegacy(EventEmitter);
|
|
14
|
-
const Logger__default = /* @__PURE__ */ _interopDefaultLegacy(Logger);
|
|
15
|
-
class SharedCameras extends EventEmitter__default.default {
|
|
12
|
+
class SharedCameras extends EventEmitter {
|
|
16
13
|
constructor() {
|
|
17
14
|
super(...arguments);
|
|
18
15
|
__publicField(this, "_list", []);
|
|
@@ -147,7 +144,7 @@ function htmlImageToCanvas(image) {
|
|
|
147
144
|
context == null ? void 0 : context.drawImage(image, 0, 0);
|
|
148
145
|
return canvas;
|
|
149
146
|
}
|
|
150
|
-
const _Camera = class extends
|
|
147
|
+
const _Camera = class _Camera extends EventEmitter {
|
|
151
148
|
constructor(container, options = {}) {
|
|
152
149
|
super();
|
|
153
150
|
__publicField(this, "_userMediaConstraints");
|
|
@@ -209,6 +206,7 @@ const _Camera = class extends EventEmitter__default.default {
|
|
|
209
206
|
height: { ideal: options.height },
|
|
210
207
|
resizeMode: "none"
|
|
211
208
|
}
|
|
209
|
+
// For resizeMode
|
|
212
210
|
};
|
|
213
211
|
this.videoContainer.style.overflow = "hidden";
|
|
214
212
|
this.videoElement = document.createElement("video");
|
|
@@ -311,7 +309,7 @@ const _Camera = class extends EventEmitter__default.default {
|
|
|
311
309
|
}
|
|
312
310
|
get currentImage() {
|
|
313
311
|
if (this._state !== "started") {
|
|
314
|
-
|
|
312
|
+
Logger.warn("Trying to access image but video is not started");
|
|
315
313
|
return Promise.resolve(null);
|
|
316
314
|
}
|
|
317
315
|
const { videoWidth: width, videoHeight: height } = this.videoElement;
|
|
@@ -323,14 +321,14 @@ const _Camera = class extends EventEmitter__default.default {
|
|
|
323
321
|
return Promise.resolve(canvas);
|
|
324
322
|
}
|
|
325
323
|
};
|
|
326
|
-
|
|
327
|
-
__publicField(Camera, "DEFAULT_OPTIONS", {
|
|
324
|
+
__publicField(_Camera, "DEFAULT_OPTIONS", {
|
|
328
325
|
width: 1024,
|
|
329
326
|
height: 768,
|
|
330
327
|
resizeOnWindowChange: false
|
|
331
328
|
});
|
|
332
|
-
__publicField(
|
|
333
|
-
|
|
329
|
+
__publicField(_Camera, "GENERIC_HARDWARE_VERTICAL_FOV", 60);
|
|
330
|
+
let Camera = _Camera;
|
|
331
|
+
const _QrCodeScanner = class _QrCodeScanner extends EventEmitter {
|
|
334
332
|
constructor(camera) {
|
|
335
333
|
super();
|
|
336
334
|
__publicField(this, "_height");
|
|
@@ -402,12 +400,12 @@ const _QrCodeScanner = class extends EventEmitter__default.default {
|
|
|
402
400
|
}
|
|
403
401
|
}
|
|
404
402
|
};
|
|
405
|
-
|
|
406
|
-
__publicField(QrCodeScanner, "DEFAULT_FORMATS", [
|
|
403
|
+
__publicField(_QrCodeScanner, "DEFAULT_FORMATS", [
|
|
407
404
|
library.BarcodeFormat.QR_CODE,
|
|
408
405
|
library.BarcodeFormat.DATA_MATRIX,
|
|
409
406
|
library.BarcodeFormat.CODABAR
|
|
410
407
|
]);
|
|
408
|
+
let QrCodeScanner = _QrCodeScanner;
|
|
411
409
|
Object.defineProperty(exports, "BarcodeFormat", {
|
|
412
410
|
enumerable: true,
|
|
413
411
|
get: () => library.BarcodeFormat
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/SharedCameras.ts","../src/CameraUtils.ts","../src/Camera.ts","../src/QrCodeScanner.ts"],"sourcesContent":["import EventEmitter from 'events';\n\nimport Camera from './Camera.js';\n\ndeclare interface SharedCameras {\n on(event: 'added', listener: (obj: CameraContainer) => void): this;\n on(event: 'removed', listener: (obj: { camera: Camera }) => void): this;\n}\n\ntype CameraContainer = { container: HTMLElement, camera: Camera };\n\nclass SharedCameras extends EventEmitter {\n\n _list: CameraContainer[] = [];\n\n _add(camera: Camera, container: HTMLElement) {\n const obj = {\n camera,\n container\n };\n this._list.push(obj);\n this.emit('added', obj);\n }\n\n _remove(camera: Camera) {\n this._list = this._list.filter(({ camera: _camera }) => _camera !== camera);\n this.emit('removed', { camera });\n }\n\n get list() {\n return this._list;\n }\n\n getCameraByContainer(container: HTMLElement) {\n return this._list.find(obj => obj.container === container)?.camera || null;\n }\n}\n\nexport default new SharedCameras();\n","export type IntrinsicParams = [number, number, number, number, number, number, number, number, number];\nexport type DistortionsParams = [number, number, number, number, number];\n\nexport type Calibration = {\n intrinsic: IntrinsicParams,\n distortions?: DistortionsParams\n}\n\nexport function convertFov(angle: number, aspectRatio: number) {\n return 2 * Math.atan(Math.tan((angle / 180 * Math.PI) / 2) * aspectRatio) * 180 / Math.PI;\n}\n\nexport function calcDisplayedFov(\n videoContainer: HTMLElement,\n videoElement: HTMLVideoElement,\n hardwareVerticalFov: number\n) {\n\n const sourceWidth = videoElement.videoWidth;\n const sourceHeight = videoElement.videoHeight;\n\n if (!sourceWidth || !sourceHeight) {\n return null;\n }\n\n const containerWidth = videoContainer.offsetWidth;\n const containerHeight = videoContainer.offsetHeight;\n\n const sourceAspect = sourceWidth / sourceHeight;\n const screenAspect = containerWidth / containerHeight;\n\n let fovV = hardwareVerticalFov;\n let fovH = convertFov(fovV, sourceAspect);\n\n if (screenAspect < sourceAspect) {\n fovH = convertFov(fovV, screenAspect);\n } else {\n fovV = convertFov(fovH, 1 / screenAspect);\n }\n\n return {\n vertical: fovV,\n horizontal: fovH\n };\n}\n\n/**\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL\n */\nexport function canvasToBase64(canvas: HTMLCanvasElement, type = 'image/png', quality: any = null) {\n return canvas\n .toDataURL(type, quality)\n .substring(('data:' + type + ';base64,').length);\n}\n\nexport function base64ToCanvas(base64: string, type = 'image/png') {\n if (type !== 'image/png') {\n throw new Error('Only image/png is supported');\n }\n const canvas = document.createElement('canvas');\n const image = new Image();\n image.src = 'data:image/png;base64,' + base64;\n canvas.width = image.width;\n canvas.height = image.height;\n canvas.getContext('2d')?.drawImage(image, 0, 0);\n return canvas;\n}\n\n/**\n * Creates a pinhole camera from dimensions and a field of view\n * Distortions are not considered\n *\n * @param {number} width the camera width\n * @param {number} height the camera height\n * @param {number} fovOfWidth the field of view along the width axis in radians\n * @returns {object} the calibration matrix\n */\nexport function createCameraCalibrationFromWidthHeightFov(\n width: number,\n height: number,\n fovOfWidth: number\n): Calibration {\n\n const fovOfHeight = 2 * Math.atan(height * Math.tan(fovOfWidth / 2) / width);\n\n const fx = width / (2 * Math.tan(0.5 * fovOfWidth));\n const fy = height / (2 * Math.tan(0.5 * fovOfHeight));\n const cx = width / 2;\n const cy = height / 2;\n\n return {\n intrinsic: [fx, 0, cx, 0, fy, cy, 0, 0, 1],\n distortions: [0, 0, 0, 0, 0]\n };\n}\n\n/**\n * @param {HTMLCanvasElement} imageCanvas\n */\nexport function convertToGrayscale(imageCanvas: HTMLCanvasElement) {\n const ctx = imageCanvas.getContext('2d');\n if (!ctx) return;\n\n const imgData = ctx.getImageData(0, 0, imageCanvas.width, imageCanvas.height);\n const pixels = imgData.data;\n for (let i = 0; i < pixels.length; i += 4) {\n\n const lightness = (pixels[i] + pixels[i + 1] + pixels[i + 2]) / 3;\n pixels[i] = lightness;\n pixels[i + 1] = lightness;\n pixels[i + 2] = lightness;\n }\n ctx.putImageData(imgData, 0, 0);\n}\n\n/**\n * Reduce image size and keep aspect ratio\n */\nexport function reduceImageSize(\n imageCanvas: HTMLCanvasElement,\n maxWidth: number,\n maxHeight?: number\n) {\n\n let newWidth = imageCanvas.width;\n let newHeight = imageCanvas.height;\n\n if (typeof maxHeight !== 'undefined') {\n if (newWidth > maxWidth) {\n newHeight *= maxWidth / newWidth;\n newWidth = maxWidth;\n }\n\n if (newHeight > maxHeight) {\n newWidth *= maxHeight / newHeight;\n newHeight = maxHeight;\n }\n } else {\n const aspectRatio = imageCanvas.width / imageCanvas.height;\n if (imageCanvas.width > imageCanvas.height) {\n if (imageCanvas.width > maxWidth) {\n newWidth = maxWidth;\n newHeight = maxWidth / aspectRatio;\n }\n } else if (imageCanvas.height > maxWidth) {\n newHeight = maxWidth;\n newWidth = maxWidth * aspectRatio;\n }\n }\n\n\n if (newWidth === imageCanvas.width\n && newHeight === imageCanvas.height) {\n return imageCanvas;\n }\n\n const newCanvas = document.createElement('canvas');\n const newContext = newCanvas.getContext('2d');\n\n newCanvas.width = newWidth;\n newCanvas.height = newHeight;\n newContext?.drawImage(imageCanvas, 0, 0, newCanvas.width, newCanvas.height);\n\n return newCanvas;\n}\n\nexport function htmlImageToCanvas(image: HTMLImageElement) {\n const canvas = document.createElement('canvas');\n canvas.width = image.width;\n canvas.height = image.height;\n const context = canvas.getContext('2d');\n context?.scale(canvas.width / image.width, canvas.height / image.height);\n context?.drawImage(image, 0, 0);\n return canvas;\n}\n","import EventEmitter from 'events';\n\nimport Logger from '@wemap/logger';\nimport SharedCameras from './SharedCameras.js';\nimport { calcDisplayedFov } from './CameraUtils.js';\n\n// Helped from https://github.com/jeromeetienne/AR.js/blob/master/three.js/src/threex/threex-artoolkitsource.js\n\n// Camera preview will fill component bounds without transformations.\n// If the component aspect ratio is different from camera aspect ratio,\n// camera preview is extended then cropped.\n\ntype CameraOptions = {\n width?: number,\n height?: number,\n resizeOnWindowChange?: boolean\n};\n\nexport type CameraState = 'stopped' | 'starting' | 'started' | 'stopping';\n\ndeclare interface Camera {\n on(event: 'starting', listener: () => void): this;\n on(event: 'started', listener: (obj: ({ videoElement: HTMLVideoElement, stream: MediaStream })) => void): this;\n on(event: 'stopping', listener: () => void): this;\n on(event: 'stopped', listener: () => void): this;\n on(event: 'fov.changed', listener: (obj: ({ vertical: number, horizontal: number })) => void): this;\n off(event: 'starting', listener: () => void): this;\n off(event: 'started', listener: (obj: ({ videoElement: HTMLVideoElement, stream: MediaStream })) => void): this;\n off(event: 'stopping', listener: () => void): this;\n off(event: 'stopped', listener: () => void): this;\n off(event: 'fov.changed', listener: (obj: ({ vertical: number, horizontal: number })) => void): this;\n}\n\n\nclass Camera extends EventEmitter {\n\n static DEFAULT_OPTIONS = {\n width: 1024,\n height: 768,\n resizeOnWindowChange: false\n };\n\n static GENERIC_HARDWARE_VERTICAL_FOV = 60;\n\n _userMediaConstraints: MediaStreamConstraints;\n videoStream: MediaStream | null = null;\n\n videoContainer: HTMLElement;\n videoElement: HTMLVideoElement;\n\n fov: {horizontal: number, vertical: number} | null = null;\n\n _state: CameraState = 'stopped';\n\n _hardwareVerticalFov = Camera.GENERIC_HARDWARE_VERTICAL_FOV;\n _resizeOnWindowChange;\n\n constructor(container: HTMLElement, options: CameraOptions = {}) {\n super();\n\n options = Object.assign({}, Camera.DEFAULT_OPTIONS, options);\n\n SharedCameras._add(this, container);\n\n this.videoContainer = container;\n\n this._resizeOnWindowChange = options.resizeOnWindowChange;\n this._userMediaConstraints = {\n audio: false,\n video: {\n facingMode: 'environment',\n width: { ideal: options.width },\n height: { ideal: options.height },\n resizeMode: 'none'\n } as any // For resizeMode\n };\n\n this.videoContainer.style.overflow = 'hidden';\n\n this.videoElement = document.createElement('video');\n this.videoElement.setAttribute('id', 'wemap-camera');\n this.videoElement.setAttribute('preload', 'none');\n this.videoElement.setAttribute('muted', '');\n this.videoElement.setAttribute('playsinline', '');\n this.videoContainer.appendChild(this.videoElement);\n }\n\n async start(videoMediaConstraints?: MediaTrackConstraints) {\n\n if (this._state === 'started' || this._state === 'starting') {\n throw new Error('Camera is already started');\n }\n\n if (this._state === 'stopping') {\n await new Promise(resolve => this.once('stopped', resolve));\n }\n\n this._state = 'starting';\n this.emit('starting');\n\n await Camera.checkAvailability();\n\n if (typeof videoMediaConstraints === 'object') {\n Object.assign(this._userMediaConstraints.video as MediaTrackConstraints,\n this._userMediaConstraints.video as MediaTrackConstraints, videoMediaConstraints);\n }\n\n const stream = await navigator.mediaDevices.getUserMedia(this._userMediaConstraints);\n\n // Listeners have to be set before srcObject assigment or they can be never called\n this.videoElement.oncanplaythrough = () => this.videoElement.play();\n const metadataPr = new Promise(resolve => (this.videoElement.onloadedmetadata = resolve));\n\n this.videoElement.srcObject = this.videoStream = stream;\n await metadataPr;\n\n this._resizeElement();\n this._computeFov();\n\n if (this._resizeOnWindowChange) {\n window.addEventListener('resize', this.notifyContainerSizeChanged);\n }\n\n this._state = 'started';\n const output = {\n videoElement: this.videoElement,\n stream\n };\n\n this.emit('started', output);\n return output;\n }\n\n async stop() {\n\n if (this._state === 'stopped') {\n throw new Error('Camera is already stopped');\n }\n\n if (this._state === 'starting') {\n await new Promise(resolve => this.once('started', resolve));\n }\n\n this._state = 'stopping';\n this.emit('stopping');\n\n if (this.videoStream) {\n this.videoStream.getVideoTracks().forEach(track => track.stop());\n }\n this.videoStream = null;\n this.videoElement.srcObject = null;\n\n if (this._resizeOnWindowChange) {\n window.removeEventListener('resize', this.notifyContainerSizeChanged);\n }\n\n this._state = 'stopped';\n this.emit('stopped');\n }\n\n release() {\n this.videoContainer.removeChild(this.videoElement);\n SharedCameras._remove(this);\n }\n\n static async checkAvailability(testUserMedia = false) {\n\n if (!navigator.mediaDevices) {\n throw new Error('navigator.mediaDevices not present in your browser');\n }\n\n if (!navigator.mediaDevices.enumerateDevices) {\n throw new Error('navigator.mediaDevices.enumerateDevices not present in your browser');\n }\n\n if (!navigator.mediaDevices.getUserMedia) {\n throw new Error('navigator.mediaDevices.getUserMedia not present in your browser');\n }\n\n const devices = await navigator.mediaDevices.enumerateDevices();\n if (!devices.find(device => device.kind === 'videoinput')) {\n throw new Error('No camera found');\n }\n\n if (testUserMedia) {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: false, video: { facingMode: 'environment' }\n });\n stream.getVideoTracks().forEach(track => track.stop());\n }\n }\n\n get state() {\n return this._state;\n }\n\n get hardwareVerticalFov() {\n return this._hardwareVerticalFov;\n }\n\n set hardwareVerticalFov(hardwareVerticalFov) {\n this._hardwareVerticalFov = hardwareVerticalFov;\n this._computeFov();\n }\n\n notifyContainerSizeChanged = () => {\n this._resizeElement();\n this._computeFov();\n }\n\n _resizeElement = () => {\n\n if (!this.videoElement) {\n throw new Error('No video element found');\n }\n\n const sourceWidth = this.videoElement.videoWidth;\n const sourceHeight = this.videoElement.videoHeight;\n\n const containerWidth = this.videoContainer.offsetWidth;\n const containerHeight = this.videoContainer.offsetHeight;\n\n const sourceAspect = sourceWidth / sourceHeight;\n const screenAspect = containerWidth / containerHeight;\n\n if (screenAspect < sourceAspect) {\n\n const newWidth = sourceAspect * containerHeight;\n this.videoElement.style.width = newWidth + 'px';\n this.videoElement.style.marginLeft = -(newWidth - containerWidth) / 2 + 'px';\n\n this.videoElement.style.height = containerHeight + 'px';\n this.videoElement.style.marginTop = '0px';\n\n } else {\n\n const newHeight = 1 / (sourceAspect / containerWidth);\n this.videoElement.style.height = newHeight + 'px';\n this.videoElement.style.marginTop = -(newHeight - containerHeight) / 2 + 'px';\n\n this.videoElement.style.width = containerWidth + 'px';\n this.videoElement.style.marginLeft = '0px';\n }\n\n }\n\n _computeFov = () => {\n\n if (['stopping', 'stopped'].includes(this.state)) {\n return;\n }\n\n this.fov = calcDisplayedFov(\n this.videoContainer,\n this.videoElement,\n this._hardwareVerticalFov\n );\n\n this.emit('fov.changed', this.fov);\n }\n\n get currentImage() {\n\n if (this._state !== 'started') {\n Logger.warn('Trying to access image but video is not started');\n return Promise.resolve(null);\n }\n\n const { videoWidth: width, videoHeight: height } = this.videoElement;\n const canvas = document.createElement('canvas');\n const context = canvas.getContext('2d');\n // context.filter = 'grayscale(100%)';\n\n canvas.width = width;\n canvas.height = height;\n\n context?.drawImage(this.videoElement, 0, 0, width, height);\n return Promise.resolve(canvas);\n }\n}\n\nexport default Camera;\n","import EventEmitter from 'events';\nimport {\n MultiFormatReader,\n BarcodeFormat,\n DecodeHintType,\n RGBLuminanceSource,\n BinaryBitmap,\n HybridBinarizer\n} from '@zxing/library';\n\nimport Camera from './Camera.js';\n\ndeclare interface QrCodeScanner {\n on(event: 'scan', listener: (result: string) => void): this;\n off(event: 'scan', listener: (result: string) => void): this;\n}\n\nclass QrCodeScanner extends EventEmitter {\n\n static DEFAULT_FORMATS: BarcodeFormat[] = [\n BarcodeFormat.QR_CODE,\n BarcodeFormat.DATA_MATRIX,\n BarcodeFormat.CODABAR\n ];\n\n _height?: number;\n _luminances?: Uint8ClampedArray;\n _width?: number;\n _camera: Camera;\n _videoElement: HTMLVideoElement;\n _canvas: HTMLCanvasElement;\n _ctx: CanvasRenderingContext2D;\n _codeReader: MultiFormatReader;\n _intervalTime: number | null = null;\n _intervalTick?: number;\n _isStarted = false;\n\n\n constructor(camera: Camera) {\n super();\n\n this._camera = camera;\n this._videoElement = camera.videoElement;\n\n this._codeReader = new MultiFormatReader();\n\n this._canvas = document.createElement('canvas');\n this._ctx = this._canvas.getContext('2d') as CanvasRenderingContext2D;\n\n this._camera.on('started', () => this._tryStart());\n this._camera.on('stopped', () => this._stop());\n }\n\n start(intervalTime = 500, formats: BarcodeFormat[] = QrCodeScanner.DEFAULT_FORMATS) {\n this._intervalTime = intervalTime;\n\n if (this._isStarted) {\n return;\n }\n this._isStarted = true;\n\n const hints = new Map();\n hints.set(DecodeHintType.POSSIBLE_FORMATS, formats);\n this._codeReader.setHints(hints);\n\n this._tryStart();\n }\n\n stop() {\n this._isStarted = false;\n this._stop();\n }\n\n _tryStart() {\n\n if (!this._isStarted || this._camera.state !== 'started') {\n return;\n }\n\n this._width = this._videoElement.videoWidth;\n this._height = this._videoElement.videoHeight;\n this._canvas.width = this._width;\n this._canvas.height = this._height;\n this._luminances = new Uint8ClampedArray(this._width * this._height);\n\n this._intervalTick = window.setInterval(() => this._onFrame(), this._intervalTime as number);\n }\n\n _stop() {\n clearInterval(this._intervalTick);\n }\n\n _onFrame() {\n\n if (!this._width || !this._height || !this._luminances) {\n return;\n }\n\n this._ctx.drawImage(this._videoElement, 0, 0, this._width, this._height);\n const img = this._ctx.getImageData(0, 0, this._width, this._height);\n\n for (let i = 0; i < this._luminances.length; i++) {\n // eslint-disable-next-line no-bitwise\n this._luminances[i] = ((img.data[i * 4] + img.data[i * 4 + 1] * 2 + img.data[i * 4 + 2]) / 4) & 0xFF;\n }\n\n const binaryBitmap = new BinaryBitmap(\n new HybridBinarizer(\n new RGBLuminanceSource(this._luminances, this._width, this._height)\n )\n );\n\n try {\n const result = this._codeReader.decodeWithState(binaryBitmap);\n this.emit('scan', result.getText());\n } catch (e) {\n // do nothing\n }\n }\n}\n\nexport default QrCodeScanner;\n"],"names":["EventEmitter","SharedCameras","Logger","MultiFormatReader","DecodeHintType","BinaryBitmap","HybridBinarizer","RGBLuminanceSource","BarcodeFormat"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/SharedCameras.ts","../src/CameraUtils.ts","../src/Camera.ts","../src/QrCodeScanner.ts"],"sourcesContent":["import EventEmitter from 'events';\n\nimport Camera from './Camera.js';\n\ndeclare interface SharedCameras {\n on(event: 'added', listener: (obj: CameraContainer) => void): this;\n on(event: 'removed', listener: (obj: { camera: Camera }) => void): this;\n}\n\ntype CameraContainer = { container: HTMLElement, camera: Camera };\n\nclass SharedCameras extends EventEmitter {\n\n _list: CameraContainer[] = [];\n\n _add(camera: Camera, container: HTMLElement) {\n const obj = {\n camera,\n container\n };\n this._list.push(obj);\n this.emit('added', obj);\n }\n\n _remove(camera: Camera) {\n this._list = this._list.filter(({ camera: _camera }) => _camera !== camera);\n this.emit('removed', { camera });\n }\n\n get list() {\n return this._list;\n }\n\n getCameraByContainer(container: HTMLElement) {\n return this._list.find(obj => obj.container === container)?.camera || null;\n }\n}\n\nexport default new SharedCameras();\n","export type IntrinsicParams = [number, number, number, number, number, number, number, number, number];\nexport type DistortionsParams = [number, number, number, number, number];\n\nexport type Calibration = {\n intrinsic: IntrinsicParams,\n distortions?: DistortionsParams\n}\n\nexport function convertFov(angle: number, aspectRatio: number) {\n return 2 * Math.atan(Math.tan((angle / 180 * Math.PI) / 2) * aspectRatio) * 180 / Math.PI;\n}\n\nexport function calcDisplayedFov(\n videoContainer: HTMLElement,\n videoElement: HTMLVideoElement,\n hardwareVerticalFov: number\n) {\n\n const sourceWidth = videoElement.videoWidth;\n const sourceHeight = videoElement.videoHeight;\n\n if (!sourceWidth || !sourceHeight) {\n return null;\n }\n\n const containerWidth = videoContainer.offsetWidth;\n const containerHeight = videoContainer.offsetHeight;\n\n const sourceAspect = sourceWidth / sourceHeight;\n const screenAspect = containerWidth / containerHeight;\n\n let fovV = hardwareVerticalFov;\n let fovH = convertFov(fovV, sourceAspect);\n\n if (screenAspect < sourceAspect) {\n fovH = convertFov(fovV, screenAspect);\n } else {\n fovV = convertFov(fovH, 1 / screenAspect);\n }\n\n return {\n vertical: fovV,\n horizontal: fovH\n };\n}\n\n/**\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL\n */\nexport function canvasToBase64(canvas: HTMLCanvasElement, type = 'image/png', quality: any = null) {\n return canvas\n .toDataURL(type, quality)\n .substring(('data:' + type + ';base64,').length);\n}\n\nexport function base64ToCanvas(base64: string, type = 'image/png') {\n if (type !== 'image/png') {\n throw new Error('Only image/png is supported');\n }\n const canvas = document.createElement('canvas');\n const image = new Image();\n image.src = 'data:image/png;base64,' + base64;\n canvas.width = image.width;\n canvas.height = image.height;\n canvas.getContext('2d')?.drawImage(image, 0, 0);\n return canvas;\n}\n\n/**\n * Creates a pinhole camera from dimensions and a field of view\n * Distortions are not considered\n *\n * @param {number} width the camera width\n * @param {number} height the camera height\n * @param {number} fovOfWidth the field of view along the width axis in radians\n * @returns {object} the calibration matrix\n */\nexport function createCameraCalibrationFromWidthHeightFov(\n width: number,\n height: number,\n fovOfWidth: number\n): Calibration {\n\n const fovOfHeight = 2 * Math.atan(height * Math.tan(fovOfWidth / 2) / width);\n\n const fx = width / (2 * Math.tan(0.5 * fovOfWidth));\n const fy = height / (2 * Math.tan(0.5 * fovOfHeight));\n const cx = width / 2;\n const cy = height / 2;\n\n return {\n intrinsic: [fx, 0, cx, 0, fy, cy, 0, 0, 1],\n distortions: [0, 0, 0, 0, 0]\n };\n}\n\n/**\n * @param {HTMLCanvasElement} imageCanvas\n */\nexport function convertToGrayscale(imageCanvas: HTMLCanvasElement) {\n const ctx = imageCanvas.getContext('2d');\n if (!ctx) return;\n\n const imgData = ctx.getImageData(0, 0, imageCanvas.width, imageCanvas.height);\n const pixels = imgData.data;\n for (let i = 0; i < pixels.length; i += 4) {\n\n const lightness = (pixels[i] + pixels[i + 1] + pixels[i + 2]) / 3;\n pixels[i] = lightness;\n pixels[i + 1] = lightness;\n pixels[i + 2] = lightness;\n }\n ctx.putImageData(imgData, 0, 0);\n}\n\n/**\n * Reduce image size and keep aspect ratio\n */\nexport function reduceImageSize(\n imageCanvas: HTMLCanvasElement,\n maxWidth: number,\n maxHeight?: number\n) {\n\n let newWidth = imageCanvas.width;\n let newHeight = imageCanvas.height;\n\n if (typeof maxHeight !== 'undefined') {\n if (newWidth > maxWidth) {\n newHeight *= maxWidth / newWidth;\n newWidth = maxWidth;\n }\n\n if (newHeight > maxHeight) {\n newWidth *= maxHeight / newHeight;\n newHeight = maxHeight;\n }\n } else {\n const aspectRatio = imageCanvas.width / imageCanvas.height;\n if (imageCanvas.width > imageCanvas.height) {\n if (imageCanvas.width > maxWidth) {\n newWidth = maxWidth;\n newHeight = maxWidth / aspectRatio;\n }\n } else if (imageCanvas.height > maxWidth) {\n newHeight = maxWidth;\n newWidth = maxWidth * aspectRatio;\n }\n }\n\n\n if (newWidth === imageCanvas.width\n && newHeight === imageCanvas.height) {\n return imageCanvas;\n }\n\n const newCanvas = document.createElement('canvas');\n const newContext = newCanvas.getContext('2d');\n\n newCanvas.width = newWidth;\n newCanvas.height = newHeight;\n newContext?.drawImage(imageCanvas, 0, 0, newCanvas.width, newCanvas.height);\n\n return newCanvas;\n}\n\nexport function htmlImageToCanvas(image: HTMLImageElement) {\n const canvas = document.createElement('canvas');\n canvas.width = image.width;\n canvas.height = image.height;\n const context = canvas.getContext('2d');\n context?.scale(canvas.width / image.width, canvas.height / image.height);\n context?.drawImage(image, 0, 0);\n return canvas;\n}\n","import EventEmitter from 'events';\n\nimport Logger from '@wemap/logger';\nimport SharedCameras from './SharedCameras.js';\nimport { calcDisplayedFov } from './CameraUtils.js';\n\n// Helped from https://github.com/jeromeetienne/AR.js/blob/master/three.js/src/threex/threex-artoolkitsource.js\n\n// Camera preview will fill component bounds without transformations.\n// If the component aspect ratio is different from camera aspect ratio,\n// camera preview is extended then cropped.\n\ntype CameraOptions = {\n width?: number,\n height?: number,\n resizeOnWindowChange?: boolean\n};\n\nexport type CameraState = 'stopped' | 'starting' | 'started' | 'stopping';\n\ndeclare interface Camera {\n on(event: 'starting', listener: () => void): this;\n on(event: 'started', listener: (obj: ({ videoElement: HTMLVideoElement, stream: MediaStream })) => void): this;\n on(event: 'stopping', listener: () => void): this;\n on(event: 'stopped', listener: () => void): this;\n on(event: 'fov.changed', listener: (obj: ({ vertical: number, horizontal: number })) => void): this;\n off(event: 'starting', listener: () => void): this;\n off(event: 'started', listener: (obj: ({ videoElement: HTMLVideoElement, stream: MediaStream })) => void): this;\n off(event: 'stopping', listener: () => void): this;\n off(event: 'stopped', listener: () => void): this;\n off(event: 'fov.changed', listener: (obj: ({ vertical: number, horizontal: number })) => void): this;\n}\n\n\nclass Camera extends EventEmitter {\n\n static DEFAULT_OPTIONS = {\n width: 1024,\n height: 768,\n resizeOnWindowChange: false\n };\n\n static GENERIC_HARDWARE_VERTICAL_FOV = 60;\n\n _userMediaConstraints: MediaStreamConstraints;\n videoStream: MediaStream | null = null;\n\n videoContainer: HTMLElement;\n videoElement: HTMLVideoElement;\n\n fov: {horizontal: number, vertical: number} | null = null;\n\n _state: CameraState = 'stopped';\n\n _hardwareVerticalFov = Camera.GENERIC_HARDWARE_VERTICAL_FOV;\n _resizeOnWindowChange;\n\n constructor(container: HTMLElement, options: CameraOptions = {}) {\n super();\n\n options = Object.assign({}, Camera.DEFAULT_OPTIONS, options);\n\n SharedCameras._add(this, container);\n\n this.videoContainer = container;\n\n this._resizeOnWindowChange = options.resizeOnWindowChange;\n this._userMediaConstraints = {\n audio: false,\n video: {\n facingMode: 'environment',\n width: { ideal: options.width },\n height: { ideal: options.height },\n resizeMode: 'none'\n } as any // For resizeMode\n };\n\n this.videoContainer.style.overflow = 'hidden';\n\n this.videoElement = document.createElement('video');\n this.videoElement.setAttribute('id', 'wemap-camera');\n this.videoElement.setAttribute('preload', 'none');\n this.videoElement.setAttribute('muted', '');\n this.videoElement.setAttribute('playsinline', '');\n this.videoContainer.appendChild(this.videoElement);\n }\n\n async start(videoMediaConstraints?: MediaTrackConstraints) {\n\n if (this._state === 'started' || this._state === 'starting') {\n throw new Error('Camera is already started');\n }\n\n if (this._state === 'stopping') {\n await new Promise(resolve => this.once('stopped', resolve));\n }\n\n this._state = 'starting';\n this.emit('starting');\n\n await Camera.checkAvailability();\n\n if (typeof videoMediaConstraints === 'object') {\n Object.assign(this._userMediaConstraints.video as MediaTrackConstraints,\n this._userMediaConstraints.video as MediaTrackConstraints, videoMediaConstraints);\n }\n\n const stream = await navigator.mediaDevices.getUserMedia(this._userMediaConstraints);\n\n // Listeners have to be set before srcObject assigment or they can be never called\n this.videoElement.oncanplaythrough = () => this.videoElement.play();\n const metadataPr = new Promise(resolve => (this.videoElement.onloadedmetadata = resolve));\n\n this.videoElement.srcObject = this.videoStream = stream;\n await metadataPr;\n\n this._resizeElement();\n this._computeFov();\n\n if (this._resizeOnWindowChange) {\n window.addEventListener('resize', this.notifyContainerSizeChanged);\n }\n\n this._state = 'started';\n const output = {\n videoElement: this.videoElement,\n stream\n };\n\n this.emit('started', output);\n return output;\n }\n\n async stop() {\n\n if (this._state === 'stopped') {\n throw new Error('Camera is already stopped');\n }\n\n if (this._state === 'starting') {\n await new Promise(resolve => this.once('started', resolve));\n }\n\n this._state = 'stopping';\n this.emit('stopping');\n\n if (this.videoStream) {\n this.videoStream.getVideoTracks().forEach(track => track.stop());\n }\n this.videoStream = null;\n this.videoElement.srcObject = null;\n\n if (this._resizeOnWindowChange) {\n window.removeEventListener('resize', this.notifyContainerSizeChanged);\n }\n\n this._state = 'stopped';\n this.emit('stopped');\n }\n\n release() {\n this.videoContainer.removeChild(this.videoElement);\n SharedCameras._remove(this);\n }\n\n static async checkAvailability(testUserMedia = false) {\n\n if (!navigator.mediaDevices) {\n throw new Error('navigator.mediaDevices not present in your browser');\n }\n\n if (!navigator.mediaDevices.enumerateDevices) {\n throw new Error('navigator.mediaDevices.enumerateDevices not present in your browser');\n }\n\n if (!navigator.mediaDevices.getUserMedia) {\n throw new Error('navigator.mediaDevices.getUserMedia not present in your browser');\n }\n\n const devices = await navigator.mediaDevices.enumerateDevices();\n if (!devices.find(device => device.kind === 'videoinput')) {\n throw new Error('No camera found');\n }\n\n if (testUserMedia) {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: false, video: { facingMode: 'environment' }\n });\n stream.getVideoTracks().forEach(track => track.stop());\n }\n }\n\n get state() {\n return this._state;\n }\n\n get hardwareVerticalFov() {\n return this._hardwareVerticalFov;\n }\n\n set hardwareVerticalFov(hardwareVerticalFov) {\n this._hardwareVerticalFov = hardwareVerticalFov;\n this._computeFov();\n }\n\n notifyContainerSizeChanged = () => {\n this._resizeElement();\n this._computeFov();\n }\n\n _resizeElement = () => {\n\n if (!this.videoElement) {\n throw new Error('No video element found');\n }\n\n const sourceWidth = this.videoElement.videoWidth;\n const sourceHeight = this.videoElement.videoHeight;\n\n const containerWidth = this.videoContainer.offsetWidth;\n const containerHeight = this.videoContainer.offsetHeight;\n\n const sourceAspect = sourceWidth / sourceHeight;\n const screenAspect = containerWidth / containerHeight;\n\n if (screenAspect < sourceAspect) {\n\n const newWidth = sourceAspect * containerHeight;\n this.videoElement.style.width = newWidth + 'px';\n this.videoElement.style.marginLeft = -(newWidth - containerWidth) / 2 + 'px';\n\n this.videoElement.style.height = containerHeight + 'px';\n this.videoElement.style.marginTop = '0px';\n\n } else {\n\n const newHeight = 1 / (sourceAspect / containerWidth);\n this.videoElement.style.height = newHeight + 'px';\n this.videoElement.style.marginTop = -(newHeight - containerHeight) / 2 + 'px';\n\n this.videoElement.style.width = containerWidth + 'px';\n this.videoElement.style.marginLeft = '0px';\n }\n\n }\n\n _computeFov = () => {\n\n if (['stopping', 'stopped'].includes(this.state)) {\n return;\n }\n\n this.fov = calcDisplayedFov(\n this.videoContainer,\n this.videoElement,\n this._hardwareVerticalFov\n );\n\n this.emit('fov.changed', this.fov);\n }\n\n get currentImage() {\n\n if (this._state !== 'started') {\n Logger.warn('Trying to access image but video is not started');\n return Promise.resolve(null);\n }\n\n const { videoWidth: width, videoHeight: height } = this.videoElement;\n const canvas = document.createElement('canvas');\n const context = canvas.getContext('2d');\n // context.filter = 'grayscale(100%)';\n\n canvas.width = width;\n canvas.height = height;\n\n context?.drawImage(this.videoElement, 0, 0, width, height);\n return Promise.resolve(canvas);\n }\n}\n\nexport default Camera;\n","import EventEmitter from 'events';\nimport {\n MultiFormatReader,\n BarcodeFormat,\n DecodeHintType,\n RGBLuminanceSource,\n BinaryBitmap,\n HybridBinarizer\n} from '@zxing/library';\n\nimport Camera from './Camera.js';\n\ndeclare interface QrCodeScanner {\n on(event: 'scan', listener: (result: string) => void): this;\n off(event: 'scan', listener: (result: string) => void): this;\n}\n\nclass QrCodeScanner extends EventEmitter {\n\n static DEFAULT_FORMATS: BarcodeFormat[] = [\n BarcodeFormat.QR_CODE,\n BarcodeFormat.DATA_MATRIX,\n BarcodeFormat.CODABAR\n ];\n\n _height?: number;\n _luminances?: Uint8ClampedArray;\n _width?: number;\n _camera: Camera;\n _videoElement: HTMLVideoElement;\n _canvas: HTMLCanvasElement;\n _ctx: CanvasRenderingContext2D;\n _codeReader: MultiFormatReader;\n _intervalTime: number | null = null;\n _intervalTick?: number;\n _isStarted = false;\n\n\n constructor(camera: Camera) {\n super();\n\n this._camera = camera;\n this._videoElement = camera.videoElement;\n\n this._codeReader = new MultiFormatReader();\n\n this._canvas = document.createElement('canvas');\n this._ctx = this._canvas.getContext('2d') as CanvasRenderingContext2D;\n\n this._camera.on('started', () => this._tryStart());\n this._camera.on('stopped', () => this._stop());\n }\n\n start(intervalTime = 500, formats: BarcodeFormat[] = QrCodeScanner.DEFAULT_FORMATS) {\n this._intervalTime = intervalTime;\n\n if (this._isStarted) {\n return;\n }\n this._isStarted = true;\n\n const hints = new Map();\n hints.set(DecodeHintType.POSSIBLE_FORMATS, formats);\n this._codeReader.setHints(hints);\n\n this._tryStart();\n }\n\n stop() {\n this._isStarted = false;\n this._stop();\n }\n\n _tryStart() {\n\n if (!this._isStarted || this._camera.state !== 'started') {\n return;\n }\n\n this._width = this._videoElement.videoWidth;\n this._height = this._videoElement.videoHeight;\n this._canvas.width = this._width;\n this._canvas.height = this._height;\n this._luminances = new Uint8ClampedArray(this._width * this._height);\n\n this._intervalTick = window.setInterval(() => this._onFrame(), this._intervalTime as number);\n }\n\n _stop() {\n clearInterval(this._intervalTick);\n }\n\n _onFrame() {\n\n if (!this._width || !this._height || !this._luminances) {\n return;\n }\n\n this._ctx.drawImage(this._videoElement, 0, 0, this._width, this._height);\n const img = this._ctx.getImageData(0, 0, this._width, this._height);\n\n for (let i = 0; i < this._luminances.length; i++) {\n // eslint-disable-next-line no-bitwise\n this._luminances[i] = ((img.data[i * 4] + img.data[i * 4 + 1] * 2 + img.data[i * 4 + 2]) / 4) & 0xFF;\n }\n\n const binaryBitmap = new BinaryBitmap(\n new HybridBinarizer(\n new RGBLuminanceSource(this._luminances, this._width, this._height)\n )\n );\n\n try {\n const result = this._codeReader.decodeWithState(binaryBitmap);\n this.emit('scan', result.getText());\n } catch (e) {\n // do nothing\n }\n }\n}\n\nexport default QrCodeScanner;\n"],"names":["SharedCameras","MultiFormatReader","DecodeHintType","BinaryBitmap","HybridBinarizer","RGBLuminanceSource","BarcodeFormat"],"mappings":";;;;;;;;;;;AAWA,MAAM,sBAAsB,aAAa;AAAA,EAAzC;AAAA;AAEI,iCAA2B,CAAA;AAAA;AAAA,EAE3B,KAAK,QAAgB,WAAwB;AACzC,UAAM,MAAM;AAAA,MACR;AAAA,MACA;AAAA,IAAA;AAEC,SAAA,MAAM,KAAK,GAAG;AACd,SAAA,KAAK,SAAS,GAAG;AAAA,EAC1B;AAAA,EAEA,QAAQ,QAAgB;AACf,SAAA,QAAQ,KAAK,MAAM,OAAO,CAAC,EAAE,QAAQ,QAAA,MAAc,YAAY,MAAM;AAC1E,SAAK,KAAK,WAAW,EAAE,OAAQ,CAAA;AAAA,EACnC;AAAA,EAEA,IAAI,OAAO;AACP,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,qBAAqB,WAAwB;;AAClC,aAAA,UAAK,MAAM,KAAK,CAAA,QAAO,IAAI,cAAc,SAAS,MAAlD,mBAAqD,WAAU;AAAA,EAC1E;AACJ;AAEA,MAAe,kBAAA,IAAI,cAAc;AC9BjB,SAAA,WAAW,OAAe,aAAqB;AAC3D,SAAO,IAAI,KAAK,KAAK,KAAK,IAAK,QAAQ,MAAM,KAAK,KAAM,CAAC,IAAI,WAAW,IAAI,MAAM,KAAK;AAC3F;AAEgB,SAAA,iBACZ,gBACA,cACA,qBACF;AAEE,QAAM,cAAc,aAAa;AACjC,QAAM,eAAe,aAAa;AAE9B,MAAA,CAAC,eAAe,CAAC,cAAc;AACxB,WAAA;AAAA,EACX;AAEA,QAAM,iBAAiB,eAAe;AACtC,QAAM,kBAAkB,eAAe;AAEvC,QAAM,eAAe,cAAc;AACnC,QAAM,eAAe,iBAAiB;AAEtC,MAAI,OAAO;AACP,MAAA,OAAO,WAAW,MAAM,YAAY;AAExC,MAAI,eAAe,cAAc;AACtB,WAAA,WAAW,MAAM,YAAY;AAAA,EAAA,OACjC;AACI,WAAA,WAAW,MAAM,IAAI,YAAY;AAAA,EAC5C;AAEO,SAAA;AAAA,IACH,UAAU;AAAA,IACV,YAAY;AAAA,EAAA;AAEpB;AAKO,SAAS,eAAe,QAA2B,OAAO,aAAa,UAAe,MAAM;AACxF,SAAA,OACF,UAAU,MAAM,OAAO,EACvB,WAAW,UAAU,OAAO,YAAY,MAAM;AACvD;AAEgB,SAAA,eAAe,QAAgB,OAAO,aAAa;;AAC/D,MAAI,SAAS,aAAa;AAChB,UAAA,IAAI,MAAM,6BAA6B;AAAA,EACjD;AACM,QAAA,SAAS,SAAS,cAAc,QAAQ;AACxC,QAAA,QAAQ,IAAI;AAClB,QAAM,MAAM,2BAA2B;AACvC,SAAO,QAAQ,MAAM;AACrB,SAAO,SAAS,MAAM;AACtB,eAAO,WAAW,IAAI,MAAtB,mBAAyB,UAAU,OAAO,GAAG;AACtC,SAAA;AACX;AAWgB,SAAA,0CACZ,OACA,QACA,YACW;AAEL,QAAA,cAAc,IAAI,KAAK,KAAK,SAAS,KAAK,IAAI,aAAa,CAAC,IAAI,KAAK;AAE3E,QAAM,KAAK,SAAS,IAAI,KAAK,IAAI,MAAM,UAAU;AACjD,QAAM,KAAK,UAAU,IAAI,KAAK,IAAI,MAAM,WAAW;AACnD,QAAM,KAAK,QAAQ;AACnB,QAAM,KAAK,SAAS;AAEb,SAAA;AAAA,IACH,WAAW,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,GAAG,CAAC;AAAA,IACzC,aAAa,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AAAA,EAAA;AAEnC;AAKO,SAAS,mBAAmB,aAAgC;AACzD,QAAA,MAAM,YAAY,WAAW,IAAI;AACvC,MAAI,CAAC;AAAK;AAEJ,QAAA,UAAU,IAAI,aAAa,GAAG,GAAG,YAAY,OAAO,YAAY,MAAM;AAC5E,QAAM,SAAS,QAAQ;AACvB,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;AAEjC,UAAA,aAAa,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAChE,WAAO,CAAC,IAAI;AACL,WAAA,IAAI,CAAC,IAAI;AACT,WAAA,IAAI,CAAC,IAAI;AAAA,EACpB;AACI,MAAA,aAAa,SAAS,GAAG,CAAC;AAClC;AAKgB,SAAA,gBACZ,aACA,UACA,WACF;AAEE,MAAI,WAAW,YAAY;AAC3B,MAAI,YAAY,YAAY;AAExB,MAAA,OAAO,cAAc,aAAa;AAClC,QAAI,WAAW,UAAU;AACrB,mBAAa,WAAW;AACb,iBAAA;AAAA,IACf;AAEA,QAAI,YAAY,WAAW;AACvB,kBAAY,YAAY;AACZ,kBAAA;AAAA,IAChB;AAAA,EAAA,OACG;AACG,UAAA,cAAc,YAAY,QAAQ,YAAY;AAChD,QAAA,YAAY,QAAQ,YAAY,QAAQ;AACpC,UAAA,YAAY,QAAQ,UAAU;AACnB,mBAAA;AACX,oBAAY,WAAW;AAAA,MAC3B;AAAA,IAAA,WACO,YAAY,SAAS,UAAU;AAC1B,kBAAA;AACZ,iBAAW,WAAW;AAAA,IAC1B;AAAA,EACJ;AAGA,MAAI,aAAa,YAAY,SACtB,cAAc,YAAY,QAAQ;AAC9B,WAAA;AAAA,EACX;AAEM,QAAA,YAAY,SAAS,cAAc,QAAQ;AAC3C,QAAA,aAAa,UAAU,WAAW,IAAI;AAE5C,YAAU,QAAQ;AAClB,YAAU,SAAS;AACnB,2CAAY,UAAU,aAAa,GAAG,GAAG,UAAU,OAAO,UAAU;AAE7D,SAAA;AACX;AAEO,SAAS,kBAAkB,OAAyB;AACjD,QAAA,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,QAAQ,MAAM;AACrB,SAAO,SAAS,MAAM;AAChB,QAAA,UAAU,OAAO,WAAW,IAAI;AAC7B,qCAAA,MAAM,OAAO,QAAQ,MAAM,OAAO,OAAO,SAAS,MAAM;AACxD,qCAAA,UAAU,OAAO,GAAG;AACtB,SAAA;AACX;AC5IA,MAAM,UAAN,MAAM,gBAAe,aAAa;AAAA,EAuB9B,YAAY,WAAwB,UAAyB,IAAI;AACvD;AAdV;AACA,uCAAkC;AAElC;AACA;AAEA,+BAAqD;AAErD,kCAAsB;AAEtB,gDAAuB,QAAO;AAC9B;AAsJA,sDAA6B,MAAM;AAC/B,WAAK,eAAe;AACpB,WAAK,YAAY;AAAA,IAAA;AAGrB,0CAAiB,MAAM;AAEf,UAAA,CAAC,KAAK,cAAc;AACd,cAAA,IAAI,MAAM,wBAAwB;AAAA,MAC5C;AAEM,YAAA,cAAc,KAAK,aAAa;AAChC,YAAA,eAAe,KAAK,aAAa;AAEjC,YAAA,iBAAiB,KAAK,eAAe;AACrC,YAAA,kBAAkB,KAAK,eAAe;AAE5C,YAAM,eAAe,cAAc;AACnC,YAAM,eAAe,iBAAiB;AAEtC,UAAI,eAAe,cAAc;AAE7B,cAAM,WAAW,eAAe;AAC3B,aAAA,aAAa,MAAM,QAAQ,WAAW;AAC3C,aAAK,aAAa,MAAM,aAAa,EAAE,WAAW,kBAAkB,IAAI;AAEnE,aAAA,aAAa,MAAM,SAAS,kBAAkB;AAC9C,aAAA,aAAa,MAAM,YAAY;AAAA,MAAA,OAEjC;AAEG,cAAA,YAAY,KAAK,eAAe;AACjC,aAAA,aAAa,MAAM,SAAS,YAAY;AAC7C,aAAK,aAAa,MAAM,YAAY,EAAE,YAAY,mBAAmB,IAAI;AAEpE,aAAA,aAAa,MAAM,QAAQ,iBAAiB;AAC5C,aAAA,aAAa,MAAM,aAAa;AAAA,MACzC;AAAA,IAAA;AAIJ,uCAAc,MAAM;AAEhB,UAAI,CAAC,YAAY,SAAS,EAAE,SAAS,KAAK,KAAK,GAAG;AAC9C;AAAA,MACJ;AAEA,WAAK,MAAM;AAAA,QACP,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MAAA;AAGJ,WAAA,KAAK,eAAe,KAAK,GAAG;AAAA,IAAA;AAtMjC,cAAU,OAAO,OAAO,CAAA,GAAI,QAAO,iBAAiB,OAAO;AAE7CA,oBAAA,KAAK,MAAM,SAAS;AAElC,SAAK,iBAAiB;AAEtB,SAAK,wBAAwB,QAAQ;AACrC,SAAK,wBAAwB;AAAA,MACzB,OAAO;AAAA,MACP,OAAO;AAAA,QACH,YAAY;AAAA,QACZ,OAAO,EAAE,OAAO,QAAQ,MAAM;AAAA,QAC9B,QAAQ,EAAE,OAAO,QAAQ,OAAO;AAAA,QAChC,YAAY;AAAA,MAChB;AAAA;AAAA,IAAA;AAGC,SAAA,eAAe,MAAM,WAAW;AAEhC,SAAA,eAAe,SAAS,cAAc,OAAO;AAC7C,SAAA,aAAa,aAAa,MAAM,cAAc;AAC9C,SAAA,aAAa,aAAa,WAAW,MAAM;AAC3C,SAAA,aAAa,aAAa,SAAS,EAAE;AACrC,SAAA,aAAa,aAAa,eAAe,EAAE;AAC3C,SAAA,eAAe,YAAY,KAAK,YAAY;AAAA,EACrD;AAAA,EAEA,MAAM,MAAM,uBAA+C;AAEvD,QAAI,KAAK,WAAW,aAAa,KAAK,WAAW,YAAY;AACnD,YAAA,IAAI,MAAM,2BAA2B;AAAA,IAC/C;AAEI,QAAA,KAAK,WAAW,YAAY;AAC5B,YAAM,IAAI,QAAQ,CAAA,YAAW,KAAK,KAAK,WAAW,OAAO,CAAC;AAAA,IAC9D;AAEA,SAAK,SAAS;AACd,SAAK,KAAK,UAAU;AAEpB,UAAM,QAAO;AAET,QAAA,OAAO,0BAA0B,UAAU;AACpC,aAAA;AAAA,QAAO,KAAK,sBAAsB;AAAA,QACrC,KAAK,sBAAsB;AAAA,QAAgC;AAAA,MAAA;AAAA,IACnE;AAEA,UAAM,SAAS,MAAM,UAAU,aAAa,aAAa,KAAK,qBAAqB;AAGnF,SAAK,aAAa,mBAAmB,MAAM,KAAK,aAAa;AAC7D,UAAM,aAAa,IAAI,QAAQ,aAAY,KAAK,aAAa,mBAAmB,OAAQ;AAEnF,SAAA,aAAa,YAAY,KAAK,cAAc;AAC3C,UAAA;AAEN,SAAK,eAAe;AACpB,SAAK,YAAY;AAEjB,QAAI,KAAK,uBAAuB;AACrB,aAAA,iBAAiB,UAAU,KAAK,0BAA0B;AAAA,IACrE;AAEA,SAAK,SAAS;AACd,UAAM,SAAS;AAAA,MACX,cAAc,KAAK;AAAA,MACnB;AAAA,IAAA;AAGC,SAAA,KAAK,WAAW,MAAM;AACpB,WAAA;AAAA,EACX;AAAA,EAEA,MAAM,OAAO;AAEL,QAAA,KAAK,WAAW,WAAW;AACrB,YAAA,IAAI,MAAM,2BAA2B;AAAA,IAC/C;AAEI,QAAA,KAAK,WAAW,YAAY;AAC5B,YAAM,IAAI,QAAQ,CAAA,YAAW,KAAK,KAAK,WAAW,OAAO,CAAC;AAAA,IAC9D;AAEA,SAAK,SAAS;AACd,SAAK,KAAK,UAAU;AAEpB,QAAI,KAAK,aAAa;AAClB,WAAK,YAAY,iBAAiB,QAAQ,CAAS,UAAA,MAAM,MAAM;AAAA,IACnE;AACA,SAAK,cAAc;AACnB,SAAK,aAAa,YAAY;AAE9B,QAAI,KAAK,uBAAuB;AACrB,aAAA,oBAAoB,UAAU,KAAK,0BAA0B;AAAA,IACxE;AAEA,SAAK,SAAS;AACd,SAAK,KAAK,SAAS;AAAA,EACvB;AAAA,EAEA,UAAU;AACD,SAAA,eAAe,YAAY,KAAK,YAAY;AACjDA,oBAAc,QAAQ,IAAI;AAAA,EAC9B;AAAA,EAEA,aAAa,kBAAkB,gBAAgB,OAAO;AAE9C,QAAA,CAAC,UAAU,cAAc;AACnB,YAAA,IAAI,MAAM,oDAAoD;AAAA,IACxE;AAEI,QAAA,CAAC,UAAU,aAAa,kBAAkB;AACpC,YAAA,IAAI,MAAM,qEAAqE;AAAA,IACzF;AAEI,QAAA,CAAC,UAAU,aAAa,cAAc;AAChC,YAAA,IAAI,MAAM,iEAAiE;AAAA,IACrF;AAEA,UAAM,UAAU,MAAM,UAAU,aAAa,iBAAiB;AAC9D,QAAI,CAAC,QAAQ,KAAK,YAAU,OAAO,SAAS,YAAY,GAAG;AACjD,YAAA,IAAI,MAAM,iBAAiB;AAAA,IACrC;AAEA,QAAI,eAAe;AACf,YAAM,SAAS,MAAM,UAAU,aAAa,aAAa;AAAA,QACrD,OAAO;AAAA,QAAO,OAAO,EAAE,YAAY,cAAc;AAAA,MAAA,CACpD;AACD,aAAO,iBAAiB,QAAQ,CAAS,UAAA,MAAM,MAAM;AAAA,IACzD;AAAA,EACJ;AAAA,EAEA,IAAI,QAAQ;AACR,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAI,sBAAsB;AACtB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAI,oBAAoB,qBAAqB;AACzC,SAAK,uBAAuB;AAC5B,SAAK,YAAY;AAAA,EACrB;AAAA,EA0DA,IAAI,eAAe;AAEX,QAAA,KAAK,WAAW,WAAW;AAC3B,aAAO,KAAK,iDAAiD;AACtD,aAAA,QAAQ,QAAQ,IAAI;AAAA,IAC/B;AAEA,UAAM,EAAE,YAAY,OAAO,aAAa,WAAW,KAAK;AAClD,UAAA,SAAS,SAAS,cAAc,QAAQ;AACxC,UAAA,UAAU,OAAO,WAAW,IAAI;AAGtC,WAAO,QAAQ;AACf,WAAO,SAAS;AAEhB,uCAAS,UAAU,KAAK,cAAc,GAAG,GAAG,OAAO;AAC5C,WAAA,QAAQ,QAAQ,MAAM;AAAA,EACjC;AACJ;AAnPI,cAFE,SAEK,mBAAkB;AAAA,EACrB,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,sBAAsB;AAAA;AAG1B,cARE,SAQK,iCAAgC;AAR3C,IAAM,SAAN;ACjBA,MAAM,iBAAN,MAAM,uBAAsB,aAAa;AAAA,EAqBrC,YAAY,QAAgB;AAClB;AAdV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yCAA+B;AAC/B;AACA,sCAAa;AAMT,SAAK,UAAU;AACf,SAAK,gBAAgB,OAAO;AAEvB,SAAA,cAAc,IAAIC,QAAAA;AAElB,SAAA,UAAU,SAAS,cAAc,QAAQ;AAC9C,SAAK,OAAO,KAAK,QAAQ,WAAW,IAAI;AAExC,SAAK,QAAQ,GAAG,WAAW,MAAM,KAAK,WAAW;AACjD,SAAK,QAAQ,GAAG,WAAW,MAAM,KAAK,OAAO;AAAA,EACjD;AAAA,EAEA,MAAM,eAAe,KAAK,UAA2B,eAAc,iBAAiB;AAChF,SAAK,gBAAgB;AAErB,QAAI,KAAK,YAAY;AACjB;AAAA,IACJ;AACA,SAAK,aAAa;AAEZ,UAAA,4BAAY;AACZ,UAAA,IAAIC,QAAAA,eAAe,kBAAkB,OAAO;AAC7C,SAAA,YAAY,SAAS,KAAK;AAE/B,SAAK,UAAU;AAAA,EACnB;AAAA,EAEA,OAAO;AACH,SAAK,aAAa;AAClB,SAAK,MAAM;AAAA,EACf;AAAA,EAEA,YAAY;AAER,QAAI,CAAC,KAAK,cAAc,KAAK,QAAQ,UAAU,WAAW;AACtD;AAAA,IACJ;AAEK,SAAA,SAAS,KAAK,cAAc;AAC5B,SAAA,UAAU,KAAK,cAAc;AAC7B,SAAA,QAAQ,QAAQ,KAAK;AACrB,SAAA,QAAQ,SAAS,KAAK;AAC3B,SAAK,cAAc,IAAI,kBAAkB,KAAK,SAAS,KAAK,OAAO;AAE9D,SAAA,gBAAgB,OAAO,YAAY,MAAM,KAAK,SAAS,GAAG,KAAK,aAAuB;AAAA,EAC/F;AAAA,EAEA,QAAQ;AACJ,kBAAc,KAAK,aAAa;AAAA,EACpC;AAAA,EAEA,WAAW;AAEH,QAAA,CAAC,KAAK,UAAU,CAAC,KAAK,WAAW,CAAC,KAAK,aAAa;AACpD;AAAA,IACJ;AAEK,SAAA,KAAK,UAAU,KAAK,eAAe,GAAG,GAAG,KAAK,QAAQ,KAAK,OAAO;AACjE,UAAA,MAAM,KAAK,KAAK,aAAa,GAAG,GAAG,KAAK,QAAQ,KAAK,OAAO;AAElE,aAAS,IAAI,GAAG,IAAI,KAAK,YAAY,QAAQ,KAAK;AAEzC,WAAA,YAAY,CAAC,KAAM,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,IAAK;AAAA,IACpG;AAEA,UAAM,eAAe,IAAIC,QAAA;AAAA,MACrB,IAAIC,QAAA;AAAA,QACA,IAAIC,QAAAA,mBAAmB,KAAK,aAAa,KAAK,QAAQ,KAAK,OAAO;AAAA,MACtE;AAAA,IAAA;AAGA,QAAA;AACA,YAAM,SAAS,KAAK,YAAY,gBAAgB,YAAY;AAC5D,WAAK,KAAK,QAAQ,OAAO,QAAS,CAAA;AAAA,aAC7B,GAAG;AAAA,IAEZ;AAAA,EACJ;AACJ;AApGI,cAFE,gBAEK,mBAAmC;AAAA,EACtCC,QAAAA,cAAc;AAAA,EACdA,QAAAA,cAAc;AAAA,EACdA,QAAAA,cAAc;AAAA;AALtB,IAAM,gBAAN;;;;;;;;;;;;;;;;"}
|
package/dist/index.mjs
CHANGED
|
@@ -143,7 +143,7 @@ function htmlImageToCanvas(image) {
|
|
|
143
143
|
context == null ? void 0 : context.drawImage(image, 0, 0);
|
|
144
144
|
return canvas;
|
|
145
145
|
}
|
|
146
|
-
const _Camera = class extends EventEmitter {
|
|
146
|
+
const _Camera = class _Camera extends EventEmitter {
|
|
147
147
|
constructor(container, options = {}) {
|
|
148
148
|
super();
|
|
149
149
|
__publicField(this, "_userMediaConstraints");
|
|
@@ -205,6 +205,7 @@ const _Camera = class extends EventEmitter {
|
|
|
205
205
|
height: { ideal: options.height },
|
|
206
206
|
resizeMode: "none"
|
|
207
207
|
}
|
|
208
|
+
// For resizeMode
|
|
208
209
|
};
|
|
209
210
|
this.videoContainer.style.overflow = "hidden";
|
|
210
211
|
this.videoElement = document.createElement("video");
|
|
@@ -319,14 +320,14 @@ const _Camera = class extends EventEmitter {
|
|
|
319
320
|
return Promise.resolve(canvas);
|
|
320
321
|
}
|
|
321
322
|
};
|
|
322
|
-
|
|
323
|
-
__publicField(Camera, "DEFAULT_OPTIONS", {
|
|
323
|
+
__publicField(_Camera, "DEFAULT_OPTIONS", {
|
|
324
324
|
width: 1024,
|
|
325
325
|
height: 768,
|
|
326
326
|
resizeOnWindowChange: false
|
|
327
327
|
});
|
|
328
|
-
__publicField(
|
|
329
|
-
|
|
328
|
+
__publicField(_Camera, "GENERIC_HARDWARE_VERTICAL_FOV", 60);
|
|
329
|
+
let Camera = _Camera;
|
|
330
|
+
const _QrCodeScanner = class _QrCodeScanner extends EventEmitter {
|
|
330
331
|
constructor(camera) {
|
|
331
332
|
super();
|
|
332
333
|
__publicField(this, "_height");
|
|
@@ -398,12 +399,12 @@ const _QrCodeScanner = class extends EventEmitter {
|
|
|
398
399
|
}
|
|
399
400
|
}
|
|
400
401
|
};
|
|
401
|
-
|
|
402
|
-
__publicField(QrCodeScanner, "DEFAULT_FORMATS", [
|
|
402
|
+
__publicField(_QrCodeScanner, "DEFAULT_FORMATS", [
|
|
403
403
|
BarcodeFormat.QR_CODE,
|
|
404
404
|
BarcodeFormat.DATA_MATRIX,
|
|
405
405
|
BarcodeFormat.CODABAR
|
|
406
406
|
]);
|
|
407
|
+
let QrCodeScanner = _QrCodeScanner;
|
|
407
408
|
export {
|
|
408
409
|
BarcodeFormat2 as BarcodeFormat,
|
|
409
410
|
Camera,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/SharedCameras.ts","../src/CameraUtils.ts","../src/Camera.ts","../src/QrCodeScanner.ts"],"sourcesContent":["import EventEmitter from 'events';\n\nimport Camera from './Camera.js';\n\ndeclare interface SharedCameras {\n on(event: 'added', listener: (obj: CameraContainer) => void): this;\n on(event: 'removed', listener: (obj: { camera: Camera }) => void): this;\n}\n\ntype CameraContainer = { container: HTMLElement, camera: Camera };\n\nclass SharedCameras extends EventEmitter {\n\n _list: CameraContainer[] = [];\n\n _add(camera: Camera, container: HTMLElement) {\n const obj = {\n camera,\n container\n };\n this._list.push(obj);\n this.emit('added', obj);\n }\n\n _remove(camera: Camera) {\n this._list = this._list.filter(({ camera: _camera }) => _camera !== camera);\n this.emit('removed', { camera });\n }\n\n get list() {\n return this._list;\n }\n\n getCameraByContainer(container: HTMLElement) {\n return this._list.find(obj => obj.container === container)?.camera || null;\n }\n}\n\nexport default new SharedCameras();\n","export type IntrinsicParams = [number, number, number, number, number, number, number, number, number];\nexport type DistortionsParams = [number, number, number, number, number];\n\nexport type Calibration = {\n intrinsic: IntrinsicParams,\n distortions?: DistortionsParams\n}\n\nexport function convertFov(angle: number, aspectRatio: number) {\n return 2 * Math.atan(Math.tan((angle / 180 * Math.PI) / 2) * aspectRatio) * 180 / Math.PI;\n}\n\nexport function calcDisplayedFov(\n videoContainer: HTMLElement,\n videoElement: HTMLVideoElement,\n hardwareVerticalFov: number\n) {\n\n const sourceWidth = videoElement.videoWidth;\n const sourceHeight = videoElement.videoHeight;\n\n if (!sourceWidth || !sourceHeight) {\n return null;\n }\n\n const containerWidth = videoContainer.offsetWidth;\n const containerHeight = videoContainer.offsetHeight;\n\n const sourceAspect = sourceWidth / sourceHeight;\n const screenAspect = containerWidth / containerHeight;\n\n let fovV = hardwareVerticalFov;\n let fovH = convertFov(fovV, sourceAspect);\n\n if (screenAspect < sourceAspect) {\n fovH = convertFov(fovV, screenAspect);\n } else {\n fovV = convertFov(fovH, 1 / screenAspect);\n }\n\n return {\n vertical: fovV,\n horizontal: fovH\n };\n}\n\n/**\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL\n */\nexport function canvasToBase64(canvas: HTMLCanvasElement, type = 'image/png', quality: any = null) {\n return canvas\n .toDataURL(type, quality)\n .substring(('data:' + type + ';base64,').length);\n}\n\nexport function base64ToCanvas(base64: string, type = 'image/png') {\n if (type !== 'image/png') {\n throw new Error('Only image/png is supported');\n }\n const canvas = document.createElement('canvas');\n const image = new Image();\n image.src = 'data:image/png;base64,' + base64;\n canvas.width = image.width;\n canvas.height = image.height;\n canvas.getContext('2d')?.drawImage(image, 0, 0);\n return canvas;\n}\n\n/**\n * Creates a pinhole camera from dimensions and a field of view\n * Distortions are not considered\n *\n * @param {number} width the camera width\n * @param {number} height the camera height\n * @param {number} fovOfWidth the field of view along the width axis in radians\n * @returns {object} the calibration matrix\n */\nexport function createCameraCalibrationFromWidthHeightFov(\n width: number,\n height: number,\n fovOfWidth: number\n): Calibration {\n\n const fovOfHeight = 2 * Math.atan(height * Math.tan(fovOfWidth / 2) / width);\n\n const fx = width / (2 * Math.tan(0.5 * fovOfWidth));\n const fy = height / (2 * Math.tan(0.5 * fovOfHeight));\n const cx = width / 2;\n const cy = height / 2;\n\n return {\n intrinsic: [fx, 0, cx, 0, fy, cy, 0, 0, 1],\n distortions: [0, 0, 0, 0, 0]\n };\n}\n\n/**\n * @param {HTMLCanvasElement} imageCanvas\n */\nexport function convertToGrayscale(imageCanvas: HTMLCanvasElement) {\n const ctx = imageCanvas.getContext('2d');\n if (!ctx) return;\n\n const imgData = ctx.getImageData(0, 0, imageCanvas.width, imageCanvas.height);\n const pixels = imgData.data;\n for (let i = 0; i < pixels.length; i += 4) {\n\n const lightness = (pixels[i] + pixels[i + 1] + pixels[i + 2]) / 3;\n pixels[i] = lightness;\n pixels[i + 1] = lightness;\n pixels[i + 2] = lightness;\n }\n ctx.putImageData(imgData, 0, 0);\n}\n\n/**\n * Reduce image size and keep aspect ratio\n */\nexport function reduceImageSize(\n imageCanvas: HTMLCanvasElement,\n maxWidth: number,\n maxHeight?: number\n) {\n\n let newWidth = imageCanvas.width;\n let newHeight = imageCanvas.height;\n\n if (typeof maxHeight !== 'undefined') {\n if (newWidth > maxWidth) {\n newHeight *= maxWidth / newWidth;\n newWidth = maxWidth;\n }\n\n if (newHeight > maxHeight) {\n newWidth *= maxHeight / newHeight;\n newHeight = maxHeight;\n }\n } else {\n const aspectRatio = imageCanvas.width / imageCanvas.height;\n if (imageCanvas.width > imageCanvas.height) {\n if (imageCanvas.width > maxWidth) {\n newWidth = maxWidth;\n newHeight = maxWidth / aspectRatio;\n }\n } else if (imageCanvas.height > maxWidth) {\n newHeight = maxWidth;\n newWidth = maxWidth * aspectRatio;\n }\n }\n\n\n if (newWidth === imageCanvas.width\n && newHeight === imageCanvas.height) {\n return imageCanvas;\n }\n\n const newCanvas = document.createElement('canvas');\n const newContext = newCanvas.getContext('2d');\n\n newCanvas.width = newWidth;\n newCanvas.height = newHeight;\n newContext?.drawImage(imageCanvas, 0, 0, newCanvas.width, newCanvas.height);\n\n return newCanvas;\n}\n\nexport function htmlImageToCanvas(image: HTMLImageElement) {\n const canvas = document.createElement('canvas');\n canvas.width = image.width;\n canvas.height = image.height;\n const context = canvas.getContext('2d');\n context?.scale(canvas.width / image.width, canvas.height / image.height);\n context?.drawImage(image, 0, 0);\n return canvas;\n}\n","import EventEmitter from 'events';\n\nimport Logger from '@wemap/logger';\nimport SharedCameras from './SharedCameras.js';\nimport { calcDisplayedFov } from './CameraUtils.js';\n\n// Helped from https://github.com/jeromeetienne/AR.js/blob/master/three.js/src/threex/threex-artoolkitsource.js\n\n// Camera preview will fill component bounds without transformations.\n// If the component aspect ratio is different from camera aspect ratio,\n// camera preview is extended then cropped.\n\ntype CameraOptions = {\n width?: number,\n height?: number,\n resizeOnWindowChange?: boolean\n};\n\nexport type CameraState = 'stopped' | 'starting' | 'started' | 'stopping';\n\ndeclare interface Camera {\n on(event: 'starting', listener: () => void): this;\n on(event: 'started', listener: (obj: ({ videoElement: HTMLVideoElement, stream: MediaStream })) => void): this;\n on(event: 'stopping', listener: () => void): this;\n on(event: 'stopped', listener: () => void): this;\n on(event: 'fov.changed', listener: (obj: ({ vertical: number, horizontal: number })) => void): this;\n off(event: 'starting', listener: () => void): this;\n off(event: 'started', listener: (obj: ({ videoElement: HTMLVideoElement, stream: MediaStream })) => void): this;\n off(event: 'stopping', listener: () => void): this;\n off(event: 'stopped', listener: () => void): this;\n off(event: 'fov.changed', listener: (obj: ({ vertical: number, horizontal: number })) => void): this;\n}\n\n\nclass Camera extends EventEmitter {\n\n static DEFAULT_OPTIONS = {\n width: 1024,\n height: 768,\n resizeOnWindowChange: false\n };\n\n static GENERIC_HARDWARE_VERTICAL_FOV = 60;\n\n _userMediaConstraints: MediaStreamConstraints;\n videoStream: MediaStream | null = null;\n\n videoContainer: HTMLElement;\n videoElement: HTMLVideoElement;\n\n fov: {horizontal: number, vertical: number} | null = null;\n\n _state: CameraState = 'stopped';\n\n _hardwareVerticalFov = Camera.GENERIC_HARDWARE_VERTICAL_FOV;\n _resizeOnWindowChange;\n\n constructor(container: HTMLElement, options: CameraOptions = {}) {\n super();\n\n options = Object.assign({}, Camera.DEFAULT_OPTIONS, options);\n\n SharedCameras._add(this, container);\n\n this.videoContainer = container;\n\n this._resizeOnWindowChange = options.resizeOnWindowChange;\n this._userMediaConstraints = {\n audio: false,\n video: {\n facingMode: 'environment',\n width: { ideal: options.width },\n height: { ideal: options.height },\n resizeMode: 'none'\n } as any // For resizeMode\n };\n\n this.videoContainer.style.overflow = 'hidden';\n\n this.videoElement = document.createElement('video');\n this.videoElement.setAttribute('id', 'wemap-camera');\n this.videoElement.setAttribute('preload', 'none');\n this.videoElement.setAttribute('muted', '');\n this.videoElement.setAttribute('playsinline', '');\n this.videoContainer.appendChild(this.videoElement);\n }\n\n async start(videoMediaConstraints?: MediaTrackConstraints) {\n\n if (this._state === 'started' || this._state === 'starting') {\n throw new Error('Camera is already started');\n }\n\n if (this._state === 'stopping') {\n await new Promise(resolve => this.once('stopped', resolve));\n }\n\n this._state = 'starting';\n this.emit('starting');\n\n await Camera.checkAvailability();\n\n if (typeof videoMediaConstraints === 'object') {\n Object.assign(this._userMediaConstraints.video as MediaTrackConstraints,\n this._userMediaConstraints.video as MediaTrackConstraints, videoMediaConstraints);\n }\n\n const stream = await navigator.mediaDevices.getUserMedia(this._userMediaConstraints);\n\n // Listeners have to be set before srcObject assigment or they can be never called\n this.videoElement.oncanplaythrough = () => this.videoElement.play();\n const metadataPr = new Promise(resolve => (this.videoElement.onloadedmetadata = resolve));\n\n this.videoElement.srcObject = this.videoStream = stream;\n await metadataPr;\n\n this._resizeElement();\n this._computeFov();\n\n if (this._resizeOnWindowChange) {\n window.addEventListener('resize', this.notifyContainerSizeChanged);\n }\n\n this._state = 'started';\n const output = {\n videoElement: this.videoElement,\n stream\n };\n\n this.emit('started', output);\n return output;\n }\n\n async stop() {\n\n if (this._state === 'stopped') {\n throw new Error('Camera is already stopped');\n }\n\n if (this._state === 'starting') {\n await new Promise(resolve => this.once('started', resolve));\n }\n\n this._state = 'stopping';\n this.emit('stopping');\n\n if (this.videoStream) {\n this.videoStream.getVideoTracks().forEach(track => track.stop());\n }\n this.videoStream = null;\n this.videoElement.srcObject = null;\n\n if (this._resizeOnWindowChange) {\n window.removeEventListener('resize', this.notifyContainerSizeChanged);\n }\n\n this._state = 'stopped';\n this.emit('stopped');\n }\n\n release() {\n this.videoContainer.removeChild(this.videoElement);\n SharedCameras._remove(this);\n }\n\n static async checkAvailability(testUserMedia = false) {\n\n if (!navigator.mediaDevices) {\n throw new Error('navigator.mediaDevices not present in your browser');\n }\n\n if (!navigator.mediaDevices.enumerateDevices) {\n throw new Error('navigator.mediaDevices.enumerateDevices not present in your browser');\n }\n\n if (!navigator.mediaDevices.getUserMedia) {\n throw new Error('navigator.mediaDevices.getUserMedia not present in your browser');\n }\n\n const devices = await navigator.mediaDevices.enumerateDevices();\n if (!devices.find(device => device.kind === 'videoinput')) {\n throw new Error('No camera found');\n }\n\n if (testUserMedia) {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: false, video: { facingMode: 'environment' }\n });\n stream.getVideoTracks().forEach(track => track.stop());\n }\n }\n\n get state() {\n return this._state;\n }\n\n get hardwareVerticalFov() {\n return this._hardwareVerticalFov;\n }\n\n set hardwareVerticalFov(hardwareVerticalFov) {\n this._hardwareVerticalFov = hardwareVerticalFov;\n this._computeFov();\n }\n\n notifyContainerSizeChanged = () => {\n this._resizeElement();\n this._computeFov();\n }\n\n _resizeElement = () => {\n\n if (!this.videoElement) {\n throw new Error('No video element found');\n }\n\n const sourceWidth = this.videoElement.videoWidth;\n const sourceHeight = this.videoElement.videoHeight;\n\n const containerWidth = this.videoContainer.offsetWidth;\n const containerHeight = this.videoContainer.offsetHeight;\n\n const sourceAspect = sourceWidth / sourceHeight;\n const screenAspect = containerWidth / containerHeight;\n\n if (screenAspect < sourceAspect) {\n\n const newWidth = sourceAspect * containerHeight;\n this.videoElement.style.width = newWidth + 'px';\n this.videoElement.style.marginLeft = -(newWidth - containerWidth) / 2 + 'px';\n\n this.videoElement.style.height = containerHeight + 'px';\n this.videoElement.style.marginTop = '0px';\n\n } else {\n\n const newHeight = 1 / (sourceAspect / containerWidth);\n this.videoElement.style.height = newHeight + 'px';\n this.videoElement.style.marginTop = -(newHeight - containerHeight) / 2 + 'px';\n\n this.videoElement.style.width = containerWidth + 'px';\n this.videoElement.style.marginLeft = '0px';\n }\n\n }\n\n _computeFov = () => {\n\n if (['stopping', 'stopped'].includes(this.state)) {\n return;\n }\n\n this.fov = calcDisplayedFov(\n this.videoContainer,\n this.videoElement,\n this._hardwareVerticalFov\n );\n\n this.emit('fov.changed', this.fov);\n }\n\n get currentImage() {\n\n if (this._state !== 'started') {\n Logger.warn('Trying to access image but video is not started');\n return Promise.resolve(null);\n }\n\n const { videoWidth: width, videoHeight: height } = this.videoElement;\n const canvas = document.createElement('canvas');\n const context = canvas.getContext('2d');\n // context.filter = 'grayscale(100%)';\n\n canvas.width = width;\n canvas.height = height;\n\n context?.drawImage(this.videoElement, 0, 0, width, height);\n return Promise.resolve(canvas);\n }\n}\n\nexport default Camera;\n","import EventEmitter from 'events';\nimport {\n MultiFormatReader,\n BarcodeFormat,\n DecodeHintType,\n RGBLuminanceSource,\n BinaryBitmap,\n HybridBinarizer\n} from '@zxing/library';\n\nimport Camera from './Camera.js';\n\ndeclare interface QrCodeScanner {\n on(event: 'scan', listener: (result: string) => void): this;\n off(event: 'scan', listener: (result: string) => void): this;\n}\n\nclass QrCodeScanner extends EventEmitter {\n\n static DEFAULT_FORMATS: BarcodeFormat[] = [\n BarcodeFormat.QR_CODE,\n BarcodeFormat.DATA_MATRIX,\n BarcodeFormat.CODABAR\n ];\n\n _height?: number;\n _luminances?: Uint8ClampedArray;\n _width?: number;\n _camera: Camera;\n _videoElement: HTMLVideoElement;\n _canvas: HTMLCanvasElement;\n _ctx: CanvasRenderingContext2D;\n _codeReader: MultiFormatReader;\n _intervalTime: number | null = null;\n _intervalTick?: number;\n _isStarted = false;\n\n\n constructor(camera: Camera) {\n super();\n\n this._camera = camera;\n this._videoElement = camera.videoElement;\n\n this._codeReader = new MultiFormatReader();\n\n this._canvas = document.createElement('canvas');\n this._ctx = this._canvas.getContext('2d') as CanvasRenderingContext2D;\n\n this._camera.on('started', () => this._tryStart());\n this._camera.on('stopped', () => this._stop());\n }\n\n start(intervalTime = 500, formats: BarcodeFormat[] = QrCodeScanner.DEFAULT_FORMATS) {\n this._intervalTime = intervalTime;\n\n if (this._isStarted) {\n return;\n }\n this._isStarted = true;\n\n const hints = new Map();\n hints.set(DecodeHintType.POSSIBLE_FORMATS, formats);\n this._codeReader.setHints(hints);\n\n this._tryStart();\n }\n\n stop() {\n this._isStarted = false;\n this._stop();\n }\n\n _tryStart() {\n\n if (!this._isStarted || this._camera.state !== 'started') {\n return;\n }\n\n this._width = this._videoElement.videoWidth;\n this._height = this._videoElement.videoHeight;\n this._canvas.width = this._width;\n this._canvas.height = this._height;\n this._luminances = new Uint8ClampedArray(this._width * this._height);\n\n this._intervalTick = window.setInterval(() => this._onFrame(), this._intervalTime as number);\n }\n\n _stop() {\n clearInterval(this._intervalTick);\n }\n\n _onFrame() {\n\n if (!this._width || !this._height || !this._luminances) {\n return;\n }\n\n this._ctx.drawImage(this._videoElement, 0, 0, this._width, this._height);\n const img = this._ctx.getImageData(0, 0, this._width, this._height);\n\n for (let i = 0; i < this._luminances.length; i++) {\n // eslint-disable-next-line no-bitwise\n this._luminances[i] = ((img.data[i * 4] + img.data[i * 4 + 1] * 2 + img.data[i * 4 + 2]) / 4) & 0xFF;\n }\n\n const binaryBitmap = new BinaryBitmap(\n new HybridBinarizer(\n new RGBLuminanceSource(this._luminances, this._width, this._height)\n )\n );\n\n try {\n const result = this._codeReader.decodeWithState(binaryBitmap);\n this.emit('scan', result.getText());\n } catch (e) {\n // do nothing\n }\n }\n}\n\nexport default QrCodeScanner;\n"],"names":["SharedCameras"],"mappings":";;;;;;;;;;AAWA,MAAM,sBAAsB,aAAa;AAAA,EAAzC;AAAA;AAEI,iCAA2B,CAAA;AAAA;AAAA,EAE3B,KAAK,QAAgB,WAAwB;AACzC,UAAM,MAAM;AAAA,MACR;AAAA,MACA;AAAA,IAAA;AAEC,SAAA,MAAM,KAAK,GAAG;AACd,SAAA,KAAK,SAAS,GAAG;AAAA,EAC1B;AAAA,EAEA,QAAQ,QAAgB;AACf,SAAA,QAAQ,KAAK,MAAM,OAAO,CAAC,EAAE,QAAQ,QAAA,MAAc,YAAY,MAAM;AAC1E,SAAK,KAAK,WAAW,EAAE,OAAQ,CAAA;AAAA,EACnC;AAAA,EAEA,IAAI,OAAO;AACP,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,qBAAqB,WAAwB;;AAClC,aAAA,UAAK,MAAM,KAAK,CAAA,QAAO,IAAI,cAAc,SAAS,MAAlD,mBAAqD,WAAU;AAAA,EAC1E;AACJ;AAEA,MAAe,kBAAA,IAAI,cAAc;AC9BjB,SAAA,WAAW,OAAe,aAAqB;AAC3D,SAAO,IAAI,KAAK,KAAK,KAAK,IAAK,QAAQ,MAAM,KAAK,KAAM,CAAC,IAAI,WAAW,IAAI,MAAM,KAAK;AAC3F;AAEgB,SAAA,iBACZ,gBACA,cACA,qBACF;AAEE,QAAM,cAAc,aAAa;AACjC,QAAM,eAAe,aAAa;AAE9B,MAAA,CAAC,eAAe,CAAC,cAAc;AACxB,WAAA;AAAA,EACX;AAEA,QAAM,iBAAiB,eAAe;AACtC,QAAM,kBAAkB,eAAe;AAEvC,QAAM,eAAe,cAAc;AACnC,QAAM,eAAe,iBAAiB;AAEtC,MAAI,OAAO;AACP,MAAA,OAAO,WAAW,MAAM,YAAY;AAExC,MAAI,eAAe,cAAc;AACtB,WAAA,WAAW,MAAM,YAAY;AAAA,EAAA,OACjC;AACI,WAAA,WAAW,MAAM,IAAI,YAAY;AAAA,EAC5C;AAEO,SAAA;AAAA,IACH,UAAU;AAAA,IACV,YAAY;AAAA,EAAA;AAEpB;AAKO,SAAS,eAAe,QAA2B,OAAO,aAAa,UAAe,MAAM;AACxF,SAAA,OACF,UAAU,MAAM,OAAO,EACvB,WAAW,UAAU,OAAO,YAAY,MAAM;AACvD;AAEgB,SAAA,eAAe,QAAgB,OAAO,aAAa;;AAC/D,MAAI,SAAS,aAAa;AAChB,UAAA,IAAI,MAAM,6BAA6B;AAAA,EACjD;AACM,QAAA,SAAS,SAAS,cAAc,QAAQ;AACxC,QAAA,QAAQ,IAAI;AAClB,QAAM,MAAM,2BAA2B;AACvC,SAAO,QAAQ,MAAM;AACrB,SAAO,SAAS,MAAM;AACtB,eAAO,WAAW,IAAI,MAAtB,mBAAyB,UAAU,OAAO,GAAG;AACtC,SAAA;AACX;AAWgB,SAAA,0CACZ,OACA,QACA,YACW;AAEL,QAAA,cAAc,IAAI,KAAK,KAAK,SAAS,KAAK,IAAI,aAAa,CAAC,IAAI,KAAK;AAE3E,QAAM,KAAK,SAAS,IAAI,KAAK,IAAI,MAAM,UAAU;AACjD,QAAM,KAAK,UAAU,IAAI,KAAK,IAAI,MAAM,WAAW;AACnD,QAAM,KAAK,QAAQ;AACnB,QAAM,KAAK,SAAS;AAEb,SAAA;AAAA,IACH,WAAW,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,GAAG,CAAC;AAAA,IACzC,aAAa,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AAAA,EAAA;AAEnC;AAKO,SAAS,mBAAmB,aAAgC;AACzD,QAAA,MAAM,YAAY,WAAW,IAAI;AACvC,MAAI,CAAC;AAAK;AAEJ,QAAA,UAAU,IAAI,aAAa,GAAG,GAAG,YAAY,OAAO,YAAY,MAAM;AAC5E,QAAM,SAAS,QAAQ;AACvB,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;AAEjC,UAAA,aAAa,OAAO,KAAK,OAAO,IAAI,KAAK,OAAO,IAAI,MAAM;AAChE,WAAO,KAAK;AACZ,WAAO,IAAI,KAAK;AAChB,WAAO,IAAI,KAAK;AAAA,EACpB;AACI,MAAA,aAAa,SAAS,GAAG,CAAC;AAClC;AAKgB,SAAA,gBACZ,aACA,UACA,WACF;AAEE,MAAI,WAAW,YAAY;AAC3B,MAAI,YAAY,YAAY;AAExB,MAAA,OAAO,cAAc,aAAa;AAClC,QAAI,WAAW,UAAU;AACrB,mBAAa,WAAW;AACb,iBAAA;AAAA,IACf;AAEA,QAAI,YAAY,WAAW;AACvB,kBAAY,YAAY;AACZ,kBAAA;AAAA,IAChB;AAAA,EAAA,OACG;AACG,UAAA,cAAc,YAAY,QAAQ,YAAY;AAChD,QAAA,YAAY,QAAQ,YAAY,QAAQ;AACpC,UAAA,YAAY,QAAQ,UAAU;AACnB,mBAAA;AACX,oBAAY,WAAW;AAAA,MAC3B;AAAA,IAAA,WACO,YAAY,SAAS,UAAU;AAC1B,kBAAA;AACZ,iBAAW,WAAW;AAAA,IAC1B;AAAA,EACJ;AAGA,MAAI,aAAa,YAAY,SACtB,cAAc,YAAY,QAAQ;AAC9B,WAAA;AAAA,EACX;AAEM,QAAA,YAAY,SAAS,cAAc,QAAQ;AAC3C,QAAA,aAAa,UAAU,WAAW,IAAI;AAE5C,YAAU,QAAQ;AAClB,YAAU,SAAS;AACnB,2CAAY,UAAU,aAAa,GAAG,GAAG,UAAU,OAAO,UAAU;AAE7D,SAAA;AACX;AAEO,SAAS,kBAAkB,OAAyB;AACjD,QAAA,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,QAAQ,MAAM;AACrB,SAAO,SAAS,MAAM;AAChB,QAAA,UAAU,OAAO,WAAW,IAAI;AAC7B,qCAAA,MAAM,OAAO,QAAQ,MAAM,OAAO,OAAO,SAAS,MAAM;AACxD,qCAAA,UAAU,OAAO,GAAG;AACtB,SAAA;AACX;AC5IA,MAAM,UAAN,cAAqB,aAAa;AAAA,EAuB9B,YAAY,WAAwB,UAAyB,IAAI;AACvD;AAdV;AACA,uCAAkC;AAElC;AACA;AAEA,+BAAqD;AAErD,kCAAsB;AAEtB,gDAAuB,QAAO;AAC9B;AAsJA,sDAA6B,MAAM;AAC/B,WAAK,eAAe;AACpB,WAAK,YAAY;AAAA,IAAA;AAGrB,0CAAiB,MAAM;AAEf,UAAA,CAAC,KAAK,cAAc;AACd,cAAA,IAAI,MAAM,wBAAwB;AAAA,MAC5C;AAEM,YAAA,cAAc,KAAK,aAAa;AAChC,YAAA,eAAe,KAAK,aAAa;AAEjC,YAAA,iBAAiB,KAAK,eAAe;AACrC,YAAA,kBAAkB,KAAK,eAAe;AAE5C,YAAM,eAAe,cAAc;AACnC,YAAM,eAAe,iBAAiB;AAEtC,UAAI,eAAe,cAAc;AAE7B,cAAM,WAAW,eAAe;AAC3B,aAAA,aAAa,MAAM,QAAQ,WAAW;AAC3C,aAAK,aAAa,MAAM,aAAa,EAAE,WAAW,kBAAkB,IAAI;AAEnE,aAAA,aAAa,MAAM,SAAS,kBAAkB;AAC9C,aAAA,aAAa,MAAM,YAAY;AAAA,MAAA,OAEjC;AAEG,cAAA,YAAY,KAAK,eAAe;AACjC,aAAA,aAAa,MAAM,SAAS,YAAY;AAC7C,aAAK,aAAa,MAAM,YAAY,EAAE,YAAY,mBAAmB,IAAI;AAEpE,aAAA,aAAa,MAAM,QAAQ,iBAAiB;AAC5C,aAAA,aAAa,MAAM,aAAa;AAAA,MACzC;AAAA,IAAA;AAIJ,uCAAc,MAAM;AAEhB,UAAI,CAAC,YAAY,SAAS,EAAE,SAAS,KAAK,KAAK,GAAG;AAC9C;AAAA,MACJ;AAEA,WAAK,MAAM;AAAA,QACP,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MAAA;AAGJ,WAAA,KAAK,eAAe,KAAK,GAAG;AAAA,IAAA;AAtMjC,cAAU,OAAO,OAAO,CAAA,GAAI,QAAO,iBAAiB,OAAO;AAE7CA,oBAAA,KAAK,MAAM,SAAS;AAElC,SAAK,iBAAiB;AAEtB,SAAK,wBAAwB,QAAQ;AACrC,SAAK,wBAAwB;AAAA,MACzB,OAAO;AAAA,MACP,OAAO;AAAA,QACH,YAAY;AAAA,QACZ,OAAO,EAAE,OAAO,QAAQ,MAAM;AAAA,QAC9B,QAAQ,EAAE,OAAO,QAAQ,OAAO;AAAA,QAChC,YAAY;AAAA,MAChB;AAAA,IAAA;AAGC,SAAA,eAAe,MAAM,WAAW;AAEhC,SAAA,eAAe,SAAS,cAAc,OAAO;AAC7C,SAAA,aAAa,aAAa,MAAM,cAAc;AAC9C,SAAA,aAAa,aAAa,WAAW,MAAM;AAC3C,SAAA,aAAa,aAAa,SAAS,EAAE;AACrC,SAAA,aAAa,aAAa,eAAe,EAAE;AAC3C,SAAA,eAAe,YAAY,KAAK,YAAY;AAAA,EACrD;AAAA,EAEA,MAAM,MAAM,uBAA+C;AAEvD,QAAI,KAAK,WAAW,aAAa,KAAK,WAAW,YAAY;AACnD,YAAA,IAAI,MAAM,2BAA2B;AAAA,IAC/C;AAEI,QAAA,KAAK,WAAW,YAAY;AAC5B,YAAM,IAAI,QAAQ,CAAA,YAAW,KAAK,KAAK,WAAW,OAAO,CAAC;AAAA,IAC9D;AAEA,SAAK,SAAS;AACd,SAAK,KAAK,UAAU;AAEpB,UAAM,QAAO;AAET,QAAA,OAAO,0BAA0B,UAAU;AACpC,aAAA;AAAA,QAAO,KAAK,sBAAsB;AAAA,QACrC,KAAK,sBAAsB;AAAA,QAAgC;AAAA,MAAA;AAAA,IACnE;AAEA,UAAM,SAAS,MAAM,UAAU,aAAa,aAAa,KAAK,qBAAqB;AAGnF,SAAK,aAAa,mBAAmB,MAAM,KAAK,aAAa;AAC7D,UAAM,aAAa,IAAI,QAAQ,aAAY,KAAK,aAAa,mBAAmB,OAAQ;AAEnF,SAAA,aAAa,YAAY,KAAK,cAAc;AAC3C,UAAA;AAEN,SAAK,eAAe;AACpB,SAAK,YAAY;AAEjB,QAAI,KAAK,uBAAuB;AACrB,aAAA,iBAAiB,UAAU,KAAK,0BAA0B;AAAA,IACrE;AAEA,SAAK,SAAS;AACd,UAAM,SAAS;AAAA,MACX,cAAc,KAAK;AAAA,MACnB;AAAA,IAAA;AAGC,SAAA,KAAK,WAAW,MAAM;AACpB,WAAA;AAAA,EACX;AAAA,EAEA,MAAM,OAAO;AAEL,QAAA,KAAK,WAAW,WAAW;AACrB,YAAA,IAAI,MAAM,2BAA2B;AAAA,IAC/C;AAEI,QAAA,KAAK,WAAW,YAAY;AAC5B,YAAM,IAAI,QAAQ,CAAA,YAAW,KAAK,KAAK,WAAW,OAAO,CAAC;AAAA,IAC9D;AAEA,SAAK,SAAS;AACd,SAAK,KAAK,UAAU;AAEpB,QAAI,KAAK,aAAa;AAClB,WAAK,YAAY,iBAAiB,QAAQ,CAAS,UAAA,MAAM,MAAM;AAAA,IACnE;AACA,SAAK,cAAc;AACnB,SAAK,aAAa,YAAY;AAE9B,QAAI,KAAK,uBAAuB;AACrB,aAAA,oBAAoB,UAAU,KAAK,0BAA0B;AAAA,IACxE;AAEA,SAAK,SAAS;AACd,SAAK,KAAK,SAAS;AAAA,EACvB;AAAA,EAEA,UAAU;AACD,SAAA,eAAe,YAAY,KAAK,YAAY;AACjDA,oBAAc,QAAQ,IAAI;AAAA,EAC9B;AAAA,EAEA,aAAa,kBAAkB,gBAAgB,OAAO;AAE9C,QAAA,CAAC,UAAU,cAAc;AACnB,YAAA,IAAI,MAAM,oDAAoD;AAAA,IACxE;AAEI,QAAA,CAAC,UAAU,aAAa,kBAAkB;AACpC,YAAA,IAAI,MAAM,qEAAqE;AAAA,IACzF;AAEI,QAAA,CAAC,UAAU,aAAa,cAAc;AAChC,YAAA,IAAI,MAAM,iEAAiE;AAAA,IACrF;AAEA,UAAM,UAAU,MAAM,UAAU,aAAa,iBAAiB;AAC9D,QAAI,CAAC,QAAQ,KAAK,YAAU,OAAO,SAAS,YAAY,GAAG;AACjD,YAAA,IAAI,MAAM,iBAAiB;AAAA,IACrC;AAEA,QAAI,eAAe;AACf,YAAM,SAAS,MAAM,UAAU,aAAa,aAAa;AAAA,QACrD,OAAO;AAAA,QAAO,OAAO,EAAE,YAAY,cAAc;AAAA,MAAA,CACpD;AACD,aAAO,iBAAiB,QAAQ,CAAS,UAAA,MAAM,MAAM;AAAA,IACzD;AAAA,EACJ;AAAA,EAEA,IAAI,QAAQ;AACR,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAI,sBAAsB;AACtB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAI,oBAAoB,qBAAqB;AACzC,SAAK,uBAAuB;AAC5B,SAAK,YAAY;AAAA,EACrB;AAAA,EA0DA,IAAI,eAAe;AAEX,QAAA,KAAK,WAAW,WAAW;AAC3B,aAAO,KAAK,iDAAiD;AACtD,aAAA,QAAQ,QAAQ,IAAI;AAAA,IAC/B;AAEA,UAAM,EAAE,YAAY,OAAO,aAAa,WAAW,KAAK;AAClD,UAAA,SAAS,SAAS,cAAc,QAAQ;AACxC,UAAA,UAAU,OAAO,WAAW,IAAI;AAGtC,WAAO,QAAQ;AACf,WAAO,SAAS;AAEhB,uCAAS,UAAU,KAAK,cAAc,GAAG,GAAG,OAAO;AAC5C,WAAA,QAAQ,QAAQ,MAAM;AAAA,EACjC;AACJ;AArPA,IAAM,SAAN;AAEI,cAFE,QAEK,mBAAkB;AAAA,EACrB,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,sBAAsB;AAAA;AAG1B,cARE,QAQK,iCAAgC;ACzB3C,MAAM,iBAAN,cAA4B,aAAa;AAAA,EAqBrC,YAAY,QAAgB;AAClB;AAdV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yCAA+B;AAC/B;AACA,sCAAa;AAMT,SAAK,UAAU;AACf,SAAK,gBAAgB,OAAO;AAEvB,SAAA,cAAc,IAAI;AAElB,SAAA,UAAU,SAAS,cAAc,QAAQ;AAC9C,SAAK,OAAO,KAAK,QAAQ,WAAW,IAAI;AAExC,SAAK,QAAQ,GAAG,WAAW,MAAM,KAAK,WAAW;AACjD,SAAK,QAAQ,GAAG,WAAW,MAAM,KAAK,OAAO;AAAA,EACjD;AAAA,EAEA,MAAM,eAAe,KAAK,UAA2B,eAAc,iBAAiB;AAChF,SAAK,gBAAgB;AAErB,QAAI,KAAK,YAAY;AACjB;AAAA,IACJ;AACA,SAAK,aAAa;AAEZ,UAAA,4BAAY;AACZ,UAAA,IAAI,eAAe,kBAAkB,OAAO;AAC7C,SAAA,YAAY,SAAS,KAAK;AAE/B,SAAK,UAAU;AAAA,EACnB;AAAA,EAEA,OAAO;AACH,SAAK,aAAa;AAClB,SAAK,MAAM;AAAA,EACf;AAAA,EAEA,YAAY;AAER,QAAI,CAAC,KAAK,cAAc,KAAK,QAAQ,UAAU,WAAW;AACtD;AAAA,IACJ;AAEK,SAAA,SAAS,KAAK,cAAc;AAC5B,SAAA,UAAU,KAAK,cAAc;AAC7B,SAAA,QAAQ,QAAQ,KAAK;AACrB,SAAA,QAAQ,SAAS,KAAK;AAC3B,SAAK,cAAc,IAAI,kBAAkB,KAAK,SAAS,KAAK,OAAO;AAE9D,SAAA,gBAAgB,OAAO,YAAY,MAAM,KAAK,SAAS,GAAG,KAAK,aAAuB;AAAA,EAC/F;AAAA,EAEA,QAAQ;AACJ,kBAAc,KAAK,aAAa;AAAA,EACpC;AAAA,EAEA,WAAW;AAEH,QAAA,CAAC,KAAK,UAAU,CAAC,KAAK,WAAW,CAAC,KAAK,aAAa;AACpD;AAAA,IACJ;AAEK,SAAA,KAAK,UAAU,KAAK,eAAe,GAAG,GAAG,KAAK,QAAQ,KAAK,OAAO;AACjE,UAAA,MAAM,KAAK,KAAK,aAAa,GAAG,GAAG,KAAK,QAAQ,KAAK,OAAO;AAElE,aAAS,IAAI,GAAG,IAAI,KAAK,YAAY,QAAQ,KAAK;AAE9C,WAAK,YAAY,MAAO,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,MAAM,IAAK;AAAA,IACpG;AAEA,UAAM,eAAe,IAAI;AAAA,MACrB,IAAI;AAAA,QACA,IAAI,mBAAmB,KAAK,aAAa,KAAK,QAAQ,KAAK,OAAO;AAAA,MACtE;AAAA,IAAA;AAGA,QAAA;AACA,YAAM,SAAS,KAAK,YAAY,gBAAgB,YAAY;AAC5D,WAAK,KAAK,QAAQ,OAAO,QAAS,CAAA;AAAA,aAC7B;IAET;AAAA,EACJ;AACJ;AAtGA,IAAM,gBAAN;AAEI,cAFE,eAEK,mBAAmC;AAAA,EACtC,cAAc;AAAA,EACd,cAAc;AAAA,EACd,cAAc;AAAA;"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/SharedCameras.ts","../src/CameraUtils.ts","../src/Camera.ts","../src/QrCodeScanner.ts"],"sourcesContent":["import EventEmitter from 'events';\n\nimport Camera from './Camera.js';\n\ndeclare interface SharedCameras {\n on(event: 'added', listener: (obj: CameraContainer) => void): this;\n on(event: 'removed', listener: (obj: { camera: Camera }) => void): this;\n}\n\ntype CameraContainer = { container: HTMLElement, camera: Camera };\n\nclass SharedCameras extends EventEmitter {\n\n _list: CameraContainer[] = [];\n\n _add(camera: Camera, container: HTMLElement) {\n const obj = {\n camera,\n container\n };\n this._list.push(obj);\n this.emit('added', obj);\n }\n\n _remove(camera: Camera) {\n this._list = this._list.filter(({ camera: _camera }) => _camera !== camera);\n this.emit('removed', { camera });\n }\n\n get list() {\n return this._list;\n }\n\n getCameraByContainer(container: HTMLElement) {\n return this._list.find(obj => obj.container === container)?.camera || null;\n }\n}\n\nexport default new SharedCameras();\n","export type IntrinsicParams = [number, number, number, number, number, number, number, number, number];\nexport type DistortionsParams = [number, number, number, number, number];\n\nexport type Calibration = {\n intrinsic: IntrinsicParams,\n distortions?: DistortionsParams\n}\n\nexport function convertFov(angle: number, aspectRatio: number) {\n return 2 * Math.atan(Math.tan((angle / 180 * Math.PI) / 2) * aspectRatio) * 180 / Math.PI;\n}\n\nexport function calcDisplayedFov(\n videoContainer: HTMLElement,\n videoElement: HTMLVideoElement,\n hardwareVerticalFov: number\n) {\n\n const sourceWidth = videoElement.videoWidth;\n const sourceHeight = videoElement.videoHeight;\n\n if (!sourceWidth || !sourceHeight) {\n return null;\n }\n\n const containerWidth = videoContainer.offsetWidth;\n const containerHeight = videoContainer.offsetHeight;\n\n const sourceAspect = sourceWidth / sourceHeight;\n const screenAspect = containerWidth / containerHeight;\n\n let fovV = hardwareVerticalFov;\n let fovH = convertFov(fovV, sourceAspect);\n\n if (screenAspect < sourceAspect) {\n fovH = convertFov(fovV, screenAspect);\n } else {\n fovV = convertFov(fovH, 1 / screenAspect);\n }\n\n return {\n vertical: fovV,\n horizontal: fovH\n };\n}\n\n/**\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL\n */\nexport function canvasToBase64(canvas: HTMLCanvasElement, type = 'image/png', quality: any = null) {\n return canvas\n .toDataURL(type, quality)\n .substring(('data:' + type + ';base64,').length);\n}\n\nexport function base64ToCanvas(base64: string, type = 'image/png') {\n if (type !== 'image/png') {\n throw new Error('Only image/png is supported');\n }\n const canvas = document.createElement('canvas');\n const image = new Image();\n image.src = 'data:image/png;base64,' + base64;\n canvas.width = image.width;\n canvas.height = image.height;\n canvas.getContext('2d')?.drawImage(image, 0, 0);\n return canvas;\n}\n\n/**\n * Creates a pinhole camera from dimensions and a field of view\n * Distortions are not considered\n *\n * @param {number} width the camera width\n * @param {number} height the camera height\n * @param {number} fovOfWidth the field of view along the width axis in radians\n * @returns {object} the calibration matrix\n */\nexport function createCameraCalibrationFromWidthHeightFov(\n width: number,\n height: number,\n fovOfWidth: number\n): Calibration {\n\n const fovOfHeight = 2 * Math.atan(height * Math.tan(fovOfWidth / 2) / width);\n\n const fx = width / (2 * Math.tan(0.5 * fovOfWidth));\n const fy = height / (2 * Math.tan(0.5 * fovOfHeight));\n const cx = width / 2;\n const cy = height / 2;\n\n return {\n intrinsic: [fx, 0, cx, 0, fy, cy, 0, 0, 1],\n distortions: [0, 0, 0, 0, 0]\n };\n}\n\n/**\n * @param {HTMLCanvasElement} imageCanvas\n */\nexport function convertToGrayscale(imageCanvas: HTMLCanvasElement) {\n const ctx = imageCanvas.getContext('2d');\n if (!ctx) return;\n\n const imgData = ctx.getImageData(0, 0, imageCanvas.width, imageCanvas.height);\n const pixels = imgData.data;\n for (let i = 0; i < pixels.length; i += 4) {\n\n const lightness = (pixels[i] + pixels[i + 1] + pixels[i + 2]) / 3;\n pixels[i] = lightness;\n pixels[i + 1] = lightness;\n pixels[i + 2] = lightness;\n }\n ctx.putImageData(imgData, 0, 0);\n}\n\n/**\n * Reduce image size and keep aspect ratio\n */\nexport function reduceImageSize(\n imageCanvas: HTMLCanvasElement,\n maxWidth: number,\n maxHeight?: number\n) {\n\n let newWidth = imageCanvas.width;\n let newHeight = imageCanvas.height;\n\n if (typeof maxHeight !== 'undefined') {\n if (newWidth > maxWidth) {\n newHeight *= maxWidth / newWidth;\n newWidth = maxWidth;\n }\n\n if (newHeight > maxHeight) {\n newWidth *= maxHeight / newHeight;\n newHeight = maxHeight;\n }\n } else {\n const aspectRatio = imageCanvas.width / imageCanvas.height;\n if (imageCanvas.width > imageCanvas.height) {\n if (imageCanvas.width > maxWidth) {\n newWidth = maxWidth;\n newHeight = maxWidth / aspectRatio;\n }\n } else if (imageCanvas.height > maxWidth) {\n newHeight = maxWidth;\n newWidth = maxWidth * aspectRatio;\n }\n }\n\n\n if (newWidth === imageCanvas.width\n && newHeight === imageCanvas.height) {\n return imageCanvas;\n }\n\n const newCanvas = document.createElement('canvas');\n const newContext = newCanvas.getContext('2d');\n\n newCanvas.width = newWidth;\n newCanvas.height = newHeight;\n newContext?.drawImage(imageCanvas, 0, 0, newCanvas.width, newCanvas.height);\n\n return newCanvas;\n}\n\nexport function htmlImageToCanvas(image: HTMLImageElement) {\n const canvas = document.createElement('canvas');\n canvas.width = image.width;\n canvas.height = image.height;\n const context = canvas.getContext('2d');\n context?.scale(canvas.width / image.width, canvas.height / image.height);\n context?.drawImage(image, 0, 0);\n return canvas;\n}\n","import EventEmitter from 'events';\n\nimport Logger from '@wemap/logger';\nimport SharedCameras from './SharedCameras.js';\nimport { calcDisplayedFov } from './CameraUtils.js';\n\n// Helped from https://github.com/jeromeetienne/AR.js/blob/master/three.js/src/threex/threex-artoolkitsource.js\n\n// Camera preview will fill component bounds without transformations.\n// If the component aspect ratio is different from camera aspect ratio,\n// camera preview is extended then cropped.\n\ntype CameraOptions = {\n width?: number,\n height?: number,\n resizeOnWindowChange?: boolean\n};\n\nexport type CameraState = 'stopped' | 'starting' | 'started' | 'stopping';\n\ndeclare interface Camera {\n on(event: 'starting', listener: () => void): this;\n on(event: 'started', listener: (obj: ({ videoElement: HTMLVideoElement, stream: MediaStream })) => void): this;\n on(event: 'stopping', listener: () => void): this;\n on(event: 'stopped', listener: () => void): this;\n on(event: 'fov.changed', listener: (obj: ({ vertical: number, horizontal: number })) => void): this;\n off(event: 'starting', listener: () => void): this;\n off(event: 'started', listener: (obj: ({ videoElement: HTMLVideoElement, stream: MediaStream })) => void): this;\n off(event: 'stopping', listener: () => void): this;\n off(event: 'stopped', listener: () => void): this;\n off(event: 'fov.changed', listener: (obj: ({ vertical: number, horizontal: number })) => void): this;\n}\n\n\nclass Camera extends EventEmitter {\n\n static DEFAULT_OPTIONS = {\n width: 1024,\n height: 768,\n resizeOnWindowChange: false\n };\n\n static GENERIC_HARDWARE_VERTICAL_FOV = 60;\n\n _userMediaConstraints: MediaStreamConstraints;\n videoStream: MediaStream | null = null;\n\n videoContainer: HTMLElement;\n videoElement: HTMLVideoElement;\n\n fov: {horizontal: number, vertical: number} | null = null;\n\n _state: CameraState = 'stopped';\n\n _hardwareVerticalFov = Camera.GENERIC_HARDWARE_VERTICAL_FOV;\n _resizeOnWindowChange;\n\n constructor(container: HTMLElement, options: CameraOptions = {}) {\n super();\n\n options = Object.assign({}, Camera.DEFAULT_OPTIONS, options);\n\n SharedCameras._add(this, container);\n\n this.videoContainer = container;\n\n this._resizeOnWindowChange = options.resizeOnWindowChange;\n this._userMediaConstraints = {\n audio: false,\n video: {\n facingMode: 'environment',\n width: { ideal: options.width },\n height: { ideal: options.height },\n resizeMode: 'none'\n } as any // For resizeMode\n };\n\n this.videoContainer.style.overflow = 'hidden';\n\n this.videoElement = document.createElement('video');\n this.videoElement.setAttribute('id', 'wemap-camera');\n this.videoElement.setAttribute('preload', 'none');\n this.videoElement.setAttribute('muted', '');\n this.videoElement.setAttribute('playsinline', '');\n this.videoContainer.appendChild(this.videoElement);\n }\n\n async start(videoMediaConstraints?: MediaTrackConstraints) {\n\n if (this._state === 'started' || this._state === 'starting') {\n throw new Error('Camera is already started');\n }\n\n if (this._state === 'stopping') {\n await new Promise(resolve => this.once('stopped', resolve));\n }\n\n this._state = 'starting';\n this.emit('starting');\n\n await Camera.checkAvailability();\n\n if (typeof videoMediaConstraints === 'object') {\n Object.assign(this._userMediaConstraints.video as MediaTrackConstraints,\n this._userMediaConstraints.video as MediaTrackConstraints, videoMediaConstraints);\n }\n\n const stream = await navigator.mediaDevices.getUserMedia(this._userMediaConstraints);\n\n // Listeners have to be set before srcObject assigment or they can be never called\n this.videoElement.oncanplaythrough = () => this.videoElement.play();\n const metadataPr = new Promise(resolve => (this.videoElement.onloadedmetadata = resolve));\n\n this.videoElement.srcObject = this.videoStream = stream;\n await metadataPr;\n\n this._resizeElement();\n this._computeFov();\n\n if (this._resizeOnWindowChange) {\n window.addEventListener('resize', this.notifyContainerSizeChanged);\n }\n\n this._state = 'started';\n const output = {\n videoElement: this.videoElement,\n stream\n };\n\n this.emit('started', output);\n return output;\n }\n\n async stop() {\n\n if (this._state === 'stopped') {\n throw new Error('Camera is already stopped');\n }\n\n if (this._state === 'starting') {\n await new Promise(resolve => this.once('started', resolve));\n }\n\n this._state = 'stopping';\n this.emit('stopping');\n\n if (this.videoStream) {\n this.videoStream.getVideoTracks().forEach(track => track.stop());\n }\n this.videoStream = null;\n this.videoElement.srcObject = null;\n\n if (this._resizeOnWindowChange) {\n window.removeEventListener('resize', this.notifyContainerSizeChanged);\n }\n\n this._state = 'stopped';\n this.emit('stopped');\n }\n\n release() {\n this.videoContainer.removeChild(this.videoElement);\n SharedCameras._remove(this);\n }\n\n static async checkAvailability(testUserMedia = false) {\n\n if (!navigator.mediaDevices) {\n throw new Error('navigator.mediaDevices not present in your browser');\n }\n\n if (!navigator.mediaDevices.enumerateDevices) {\n throw new Error('navigator.mediaDevices.enumerateDevices not present in your browser');\n }\n\n if (!navigator.mediaDevices.getUserMedia) {\n throw new Error('navigator.mediaDevices.getUserMedia not present in your browser');\n }\n\n const devices = await navigator.mediaDevices.enumerateDevices();\n if (!devices.find(device => device.kind === 'videoinput')) {\n throw new Error('No camera found');\n }\n\n if (testUserMedia) {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: false, video: { facingMode: 'environment' }\n });\n stream.getVideoTracks().forEach(track => track.stop());\n }\n }\n\n get state() {\n return this._state;\n }\n\n get hardwareVerticalFov() {\n return this._hardwareVerticalFov;\n }\n\n set hardwareVerticalFov(hardwareVerticalFov) {\n this._hardwareVerticalFov = hardwareVerticalFov;\n this._computeFov();\n }\n\n notifyContainerSizeChanged = () => {\n this._resizeElement();\n this._computeFov();\n }\n\n _resizeElement = () => {\n\n if (!this.videoElement) {\n throw new Error('No video element found');\n }\n\n const sourceWidth = this.videoElement.videoWidth;\n const sourceHeight = this.videoElement.videoHeight;\n\n const containerWidth = this.videoContainer.offsetWidth;\n const containerHeight = this.videoContainer.offsetHeight;\n\n const sourceAspect = sourceWidth / sourceHeight;\n const screenAspect = containerWidth / containerHeight;\n\n if (screenAspect < sourceAspect) {\n\n const newWidth = sourceAspect * containerHeight;\n this.videoElement.style.width = newWidth + 'px';\n this.videoElement.style.marginLeft = -(newWidth - containerWidth) / 2 + 'px';\n\n this.videoElement.style.height = containerHeight + 'px';\n this.videoElement.style.marginTop = '0px';\n\n } else {\n\n const newHeight = 1 / (sourceAspect / containerWidth);\n this.videoElement.style.height = newHeight + 'px';\n this.videoElement.style.marginTop = -(newHeight - containerHeight) / 2 + 'px';\n\n this.videoElement.style.width = containerWidth + 'px';\n this.videoElement.style.marginLeft = '0px';\n }\n\n }\n\n _computeFov = () => {\n\n if (['stopping', 'stopped'].includes(this.state)) {\n return;\n }\n\n this.fov = calcDisplayedFov(\n this.videoContainer,\n this.videoElement,\n this._hardwareVerticalFov\n );\n\n this.emit('fov.changed', this.fov);\n }\n\n get currentImage() {\n\n if (this._state !== 'started') {\n Logger.warn('Trying to access image but video is not started');\n return Promise.resolve(null);\n }\n\n const { videoWidth: width, videoHeight: height } = this.videoElement;\n const canvas = document.createElement('canvas');\n const context = canvas.getContext('2d');\n // context.filter = 'grayscale(100%)';\n\n canvas.width = width;\n canvas.height = height;\n\n context?.drawImage(this.videoElement, 0, 0, width, height);\n return Promise.resolve(canvas);\n }\n}\n\nexport default Camera;\n","import EventEmitter from 'events';\nimport {\n MultiFormatReader,\n BarcodeFormat,\n DecodeHintType,\n RGBLuminanceSource,\n BinaryBitmap,\n HybridBinarizer\n} from '@zxing/library';\n\nimport Camera from './Camera.js';\n\ndeclare interface QrCodeScanner {\n on(event: 'scan', listener: (result: string) => void): this;\n off(event: 'scan', listener: (result: string) => void): this;\n}\n\nclass QrCodeScanner extends EventEmitter {\n\n static DEFAULT_FORMATS: BarcodeFormat[] = [\n BarcodeFormat.QR_CODE,\n BarcodeFormat.DATA_MATRIX,\n BarcodeFormat.CODABAR\n ];\n\n _height?: number;\n _luminances?: Uint8ClampedArray;\n _width?: number;\n _camera: Camera;\n _videoElement: HTMLVideoElement;\n _canvas: HTMLCanvasElement;\n _ctx: CanvasRenderingContext2D;\n _codeReader: MultiFormatReader;\n _intervalTime: number | null = null;\n _intervalTick?: number;\n _isStarted = false;\n\n\n constructor(camera: Camera) {\n super();\n\n this._camera = camera;\n this._videoElement = camera.videoElement;\n\n this._codeReader = new MultiFormatReader();\n\n this._canvas = document.createElement('canvas');\n this._ctx = this._canvas.getContext('2d') as CanvasRenderingContext2D;\n\n this._camera.on('started', () => this._tryStart());\n this._camera.on('stopped', () => this._stop());\n }\n\n start(intervalTime = 500, formats: BarcodeFormat[] = QrCodeScanner.DEFAULT_FORMATS) {\n this._intervalTime = intervalTime;\n\n if (this._isStarted) {\n return;\n }\n this._isStarted = true;\n\n const hints = new Map();\n hints.set(DecodeHintType.POSSIBLE_FORMATS, formats);\n this._codeReader.setHints(hints);\n\n this._tryStart();\n }\n\n stop() {\n this._isStarted = false;\n this._stop();\n }\n\n _tryStart() {\n\n if (!this._isStarted || this._camera.state !== 'started') {\n return;\n }\n\n this._width = this._videoElement.videoWidth;\n this._height = this._videoElement.videoHeight;\n this._canvas.width = this._width;\n this._canvas.height = this._height;\n this._luminances = new Uint8ClampedArray(this._width * this._height);\n\n this._intervalTick = window.setInterval(() => this._onFrame(), this._intervalTime as number);\n }\n\n _stop() {\n clearInterval(this._intervalTick);\n }\n\n _onFrame() {\n\n if (!this._width || !this._height || !this._luminances) {\n return;\n }\n\n this._ctx.drawImage(this._videoElement, 0, 0, this._width, this._height);\n const img = this._ctx.getImageData(0, 0, this._width, this._height);\n\n for (let i = 0; i < this._luminances.length; i++) {\n // eslint-disable-next-line no-bitwise\n this._luminances[i] = ((img.data[i * 4] + img.data[i * 4 + 1] * 2 + img.data[i * 4 + 2]) / 4) & 0xFF;\n }\n\n const binaryBitmap = new BinaryBitmap(\n new HybridBinarizer(\n new RGBLuminanceSource(this._luminances, this._width, this._height)\n )\n );\n\n try {\n const result = this._codeReader.decodeWithState(binaryBitmap);\n this.emit('scan', result.getText());\n } catch (e) {\n // do nothing\n }\n }\n}\n\nexport default QrCodeScanner;\n"],"names":["SharedCameras"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"directory": "packages/camera"
|
|
13
13
|
},
|
|
14
14
|
"name": "@wemap/camera",
|
|
15
|
-
"version": "
|
|
15
|
+
"version": "12.0.0-alpha.0",
|
|
16
16
|
"bugs": {
|
|
17
17
|
"url": "https://github.com/wemap/wemap-modules-js/issues"
|
|
18
18
|
},
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"license": "ISC",
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@types/events": "^3.0.0",
|
|
32
|
-
"@wemap/logger": "^
|
|
32
|
+
"@wemap/logger": "^12.0.0-alpha.0",
|
|
33
33
|
"@zxing/library": "^0.18.4",
|
|
34
34
|
"events": "^3.3.0"
|
|
35
35
|
},
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"require": "./dist/index.js"
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "0a65e1f573e8c80ea26f3e14cf2d1f302a2c8560"
|
|
44
44
|
}
|