dynamsoft-capture-vision-router
Version:
The Dynamsoft Capture Vision Router module is the cornerstone of the Dynamsoft Capture Vision architecture.
1,023 lines (1,005 loc) • 103 kB
JavaScript
/*!
* Dynamsoft JavaScript Library
* @product Dynamsoft Capture Vision Router JS Edition
* @website http://www.dynamsoft.com
* @copyright Copyright 2024, Dynamsoft Corporation
* @author Dynamsoft
* @version "2.4.33"
* @fileoverview Dynamsoft JavaScript Library for Capture Vision
* More info on cvr JS: https://www.dynamsoft.com/capture-vision/docs/web/programming/javascript/api-reference/capture-vision-router/capture-vision-router-module.html
*/
import { getNextTaskID, mapTaskCallBack, worker, CoreModule, workerAutoResources, mapPackageRegister, compareVersion, innerVersions, EnumCapturedResultItemType, loadWasm, handleEngineResourcePaths, EnumImagePixelFormat, EnumColourChannelUsageType, isDSImageData, requestResource, EnumIntermediateResultUnitType } from 'dynamsoft-core';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
function __classPrivateFieldGet(receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
}
function __classPrivateFieldSet(receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
const isPromiseLike = (value) => (value && "object" === typeof value && "function" === typeof value.then);
// get original `Promise`, avoid other js change the `Promise`
const Promise$1 = (async () => { })().constructor;
class MutablePromise extends Promise$1 {
get status() { return this._s; }
get isPending() { return "pending" === this._s; }
get isFulfilled() { return "fulfilled" === this._s; }
get isRejected() { return "rejected" === this._s; }
get task() { return this._task; }
set task(value) {
//if(!this.isPending){ return; }
this._task = value;
let p;
if (isPromiseLike(value)) {
p = value;
}
else if ("function" === typeof value) {
p = new Promise$1(value);
}
if (p) {
(async () => {
try {
const ret = await p;
// make sure task not change
if (value === this._task) {
this.resolve(ret);
}
}
catch (reason) {
// make sure task not change
if (value === this._task) {
this.reject(reason);
}
}
})();
}
}
get isEmpty() { return null == this._task; }
constructor(executor) {
let rs;
let rj;
const fn = (_rs, _rj) => { rs = _rs; rj = _rj; };
super(fn);
// walkaround babel which can not extend builtin class
// let _this = this;
// let then = new Promise(fn).then;
// this.then = function(){ then.apply(_this, arguments) } as any;
this._s = "pending";
this.resolve = (value) => {
if (this.isPending) {
if (isPromiseLike(value)) {
this.task = value;
}
else {
this._s = "fulfilled";
rs(value);
}
}
};
this.reject = (reason) => {
if (this.isPending) {
this._s = "rejected";
rj(reason);
}
};
this.task = executor;
}
}
class BufferedItemsManager {
constructor(cvr) {
this._cvr = cvr;
}
/**
* Gets the maximum number of buffered items.
* @returns Returns the maximum number of buffered items.
*/
async getMaxBufferedItems() {
return await new Promise((rs, rj) => {
let taskID = getNextTaskID();
mapTaskCallBack[taskID] = async (body) => {
if (body.success) {
return rs(body.count);
}
else {
let ex = new Error(body.message);
ex.stack = body.stack + '\n' + ex.stack;
return rj(ex);
}
};
worker.postMessage({
type: "cvr_getMaxBufferedItems",
id: taskID,
instanceID: this._cvr._instanceID
});
});
}
;
/**
* Sets the maximum number of buffered items.
* @param count the maximum number of buffered items
*/
async setMaxBufferedItems(count) {
return await new Promise((rs, rj) => {
let taskID = getNextTaskID();
mapTaskCallBack[taskID] = async (body) => {
if (body.success) {
return rs();
}
else {
let ex = new Error(body.message);
ex.stack = body.stack + '\n' + ex.stack;
return rj(ex);
}
};
worker.postMessage({
type: "cvr_setMaxBufferedItems",
id: taskID,
instanceID: this._cvr._instanceID,
body: {
count
}
});
});
}
;
/**
* Gets the buffered character items.
* @return the buffered character items
*/
async getBufferedCharacterItemSet() {
return await new Promise((rs, rj) => {
let taskID = getNextTaskID();
mapTaskCallBack[taskID] = async (body) => {
if (body.success) {
return rs(body.itemSet);
}
else {
let ex = new Error(body.message);
ex.stack = body.stack + '\n' + ex.stack;
return rj(ex);
}
};
worker.postMessage({
type: "cvr_getBufferedCharacterItemSet",
id: taskID,
instanceID: this._cvr._instanceID
});
});
}
;
}
var irrRegistryState = {
onTaskResultsReceived: false,
onTaskResultsReceivedForDce: false,
// section
onPredetectedRegionsReceived: false,
onLocalizedBarcodesReceived: false,
onDecodedBarcodesReceived: false,
onLocalizedTextLinesReceived: false,
onRecognizedTextLinesReceived: false,
onDetectedQuadsReceived: false,
onNormalizedImagesReceived: false,
// stage
onColourImageUnitReceived: false,
onScaledDownColourImageUnitReceived: false,
onGrayscaleImageUnitReceived: false,
onTransformedGrayscaleImageUnitReceived: false,
onEnhancedGrayscaleImageUnitReceived: false,
onBinaryImageUnitReceived: false,
onTextureDetectionResultUnitReceived: false,
onTextureRemovedGrayscaleImageUnitReceived: false,
onTextureRemovedBinaryImageUnitReceived: false,
onContoursUnitReceived: false,
onLineSegmentsUnitReceived: false,
onTextZonesUnitReceived: false,
onTextRemovedBinaryImageUnitReceived: false,
onRawTextLinesReceived: false,
onLongLinesUnitReceived: false,
onCornersUnitReceived: false,
onCandidateQuadEdgesUnitReceived: false,
onCandidateBarcodeZonesUnitReceived: false,
onScaledUpBarcodeImageUnitReceived: false,
onDeformationResistedBarcodeImageUnitReceived: false,
onComplementedBarcodeImageUnitReceived: false,
onShortLinesUnitReceived: false,
onLogicLinesReceived: false
};
const _handleIntermediateResultReceiver = (irr) => {
for (let irs in irr._irrRegistryState) {
irr._irrRegistryState[irs] = false;
}
for (let receiver of irr._intermediateResultReceiverSet) {
if (receiver.isDce || receiver.isFilter) {
irr._irrRegistryState.onTaskResultsReceivedForDce = true;
continue;
}
for (let r in receiver) {
if (!irr._irrRegistryState[r]) {
irr._irrRegistryState[r] = !!receiver[r];
}
}
}
};
class IntermediateResultManager {
constructor(cvr) {
this._irrRegistryState = irrRegistryState;
this._intermediateResultReceiverSet = new Set();
this._cvr = cvr;
}
/**
* Adds a `IntermediateResultReceiver` object as the receiver of intermediate results.
* @param receiver The receiver object, of type `IntermediateResultReceiver`.
*/
async addResultReceiver(receiver) {
if (typeof receiver !== "object")
throw new Error(`Invalid receiver.`);
this._intermediateResultReceiverSet.add(receiver);
_handleIntermediateResultReceiver(this);
let observedResultUnitTypes = -1;
let observedTaskMap = {};
if (!receiver.isDce && !receiver.isFilter) {
if (!receiver._observedResultUnitTypes || !receiver._observedTaskMap) {
throw new Error("Invalid Intermediate Result Receiver.");
}
observedResultUnitTypes = receiver._observedResultUnitTypes;
receiver._observedTaskMap.forEach((value, key) => {
observedTaskMap[key] = value;
});
receiver._observedTaskMap.clear();
}
return await new Promise((rs, rj) => {
let taskID = getNextTaskID();
mapTaskCallBack[taskID] = async (body) => {
if (body.success) {
return rs();
}
else {
let ex = new Error(body.message);
ex.stack = body.stack + '\n' + ex.stack;
return rj(ex);
}
};
worker.postMessage({
type: "cvr_setIrrRegistry",
id: taskID,
instanceID: this._cvr._instanceID,
body: {
receiverObj: this._irrRegistryState,
observedResultUnitTypes: observedResultUnitTypes.toString(),
observedTaskMap
}
});
});
}
;
/**
* Removes the specified `IntermediateResultReceiver` object.
* @param receiver The receiver object, of type `IntermediateResultReceiver`.
*/
async removeResultReceiver(receiver) {
this._intermediateResultReceiverSet.delete(receiver);
_handleIntermediateResultReceiver(this);
return await new Promise((rs, rj) => {
let taskID = getNextTaskID();
mapTaskCallBack[taskID] = async (body) => {
if (body.success) {
return rs();
}
else {
let ex = new Error(body.message);
ex.stack = body.stack + '\n' + ex.stack;
return rj(ex);
}
};
worker.postMessage({
type: "cvr_setIrrRegistry",
id: taskID,
instanceID: this._cvr._instanceID,
body: {
receiverObj: this._irrRegistryState
}
});
});
}
;
/**
* Retrieves the original image data.
*
* @returns A promise that resolves when the operation has successfully completed. It provides the original image upon resolution.
*/
getOriginalImage() {
return this._cvr._dsImage;
}
;
}
const bSSR = "undefined" == typeof self;
const isWebWorker = "function" == typeof importScripts, curScriptDir = (() => {
if (!isWebWorker) {
if (!bSSR && document.currentScript) {
let src = document.currentScript.src, idxSearch = src.indexOf("?");
if (-1 != idxSearch) src = src.substring(0, idxSearch); else {
let idxHash = src.indexOf("#");
-1 != idxHash && (src = src.substring(0, idxHash));
}
return src.substring(0, src.lastIndexOf("/") + 1);
}
return "./";
}
})(), getAbsoluteDir = value => {
if (null == value && (value = "./"), bSSR || isWebWorker) ; else {
let a = document.createElement("a");
a.href = value, value = a.href;
}
return value.endsWith("/") || (value += "/"), value;
};
var _a;
CoreModule.engineResourcePaths.cvr = { version: "2.4.33", path: curScriptDir, isInternal: true };
workerAutoResources.cvr = { js: true, wasm: true, deps: ["license", "dip"] };
mapPackageRegister.cvr = {};
const stdVersion = "1.4.21";
if ('string' != typeof CoreModule.engineResourcePaths.std && compareVersion(CoreModule.engineResourcePaths.std.version, stdVersion) < 0) {
CoreModule.engineResourcePaths.std = { version: stdVersion, path: getAbsoluteDir(curScriptDir + `../../dynamsoft-capture-vision-std@${stdVersion}/dist/`), isInternal: true };
}
const dipVersion = "2.4.31";
if (!CoreModule.engineResourcePaths.dip || 'string' != typeof CoreModule.engineResourcePaths.dip && compareVersion(CoreModule.engineResourcePaths.dip.version, dipVersion) < 0) {
CoreModule.engineResourcePaths.dip = { version: dipVersion, path: getAbsoluteDir(curScriptDir + `../../dynamsoft-image-processing@${dipVersion}/dist/`), isInternal: true };
}
class CaptureVisionRouterModule {
static getVersion() {
return this._version;
}
}
CaptureVisionRouterModule._version = `${"2.4.33"}(Worker: ${(_a = innerVersions.cvr) === null || _a === void 0 ? void 0 : _a.worker}, Wasm: loading...`;
const resultItemMapConfig = {
"barcodeResultItems": {
type: EnumCapturedResultItemType.CRIT_BARCODE,
reveiver: "onDecodedBarcodesReceived",
isNeedFilter: true
},
"textLineResultItems": {
type: EnumCapturedResultItemType.CRIT_TEXT_LINE,
reveiver: "onRecognizedTextLinesReceived",
isNeedFilter: true
},
"detectedQuadResultItems": {
type: EnumCapturedResultItemType.CRIT_DETECTED_QUAD,
reveiver: "onDetectedQuadsReceived",
isNeedFilter: false
},
"normalizedImageResultItems": {
type: EnumCapturedResultItemType.CRIT_NORMALIZED_IMAGE,
reveiver: "onNormalizedImagesReceived",
isNeedFilter: false
},
"parsedResultItems": {
type: EnumCapturedResultItemType.CRIT_PARSED_RESULT,
reveiver: "onParsedResultsReceived",
isNeedFilter: false
}
};
var EnumImageSourceState;
(function (EnumImageSourceState) {
EnumImageSourceState[EnumImageSourceState["ISS_BUFFER_EMPTY"] = 0] = "ISS_BUFFER_EMPTY";
EnumImageSourceState[EnumImageSourceState["ISS_EXHAUSTED"] = 1] = "ISS_EXHAUSTED";
})(EnumImageSourceState || (EnumImageSourceState = {}));
function convertCoordinates(item, compressRate) {
if (item && item.location) {
const points = item.location.points;
for (let point of points) {
point.x = point.x / compressRate;
point.y = point.y / compressRate;
}
convertCoordinates(item.referencedItem, compressRate);
}
}
function checkIsDisposed(cvr) {
if (cvr.disposed) {
throw new Error(`"CaptureVisionRouter" instance has been disposed`);
}
}
var _CaptureVisionRouter_isa, _CaptureVisionRouter_canvas, _CaptureVisionRouter_promiseStartScan, _CaptureVisionRouter_intermediateResultManager, _CaptureVisionRouter_bufferdItemsManager, _CaptureVisionRouter_resultReceiverSet, _CaptureVisionRouter_isaStateListenerSet, _CaptureVisionRouter_resultFilterSet, _CaptureVisionRouter_compressRate, _CaptureVisionRouter_isScanner, _CaptureVisionRouter_innerUseTag, _CaptureVisionRouter_isDestroyed;
const _intermediateResultReceiverOfFilter = {
onTaskResultsReceived: () => { },
isFilter: true
};
class CaptureVisionRouter {
constructor() {
this.maxImageSideLength = ["iPhone", "Android", "HarmonyOS"].includes(CoreModule.browserInfo.OS) ? 2048 : 4096;
this._instanceID = undefined;
this._dsImage = null;
this._isPauseScan = true;
this._isOutputOriginalImage = false;
this._isOpenDetectVerify = false;
this._isOpenNormalizeVerify = false;
this._isOpenBarcodeVerify = false;
this._isOpenLabelVerify = false;
this._minImageCaptureInterval = 0;
this._averageProcessintTimeArray = [];
this._averageFetchImageTimeArray = [];
this._currentSettings = null;
this._averageTime = 999;
_CaptureVisionRouter_isa.set(this, null);
_CaptureVisionRouter_canvas.set(this, null);
_CaptureVisionRouter_promiseStartScan.set(this, null);
_CaptureVisionRouter_intermediateResultManager.set(this, null);
_CaptureVisionRouter_bufferdItemsManager.set(this, null);
_CaptureVisionRouter_resultReceiverSet.set(this, new Set());
_CaptureVisionRouter_isaStateListenerSet.set(this, new Set());
_CaptureVisionRouter_resultFilterSet.set(this, new Set());
_CaptureVisionRouter_compressRate.set(this, 0);
_CaptureVisionRouter_isScanner.set(this, false);
_CaptureVisionRouter_innerUseTag.set(this, false);
_CaptureVisionRouter_isDestroyed.set(this, false);
this._singleFrameModeCallbackBind = this._singleFrameModeCallback.bind(this);
}
/**
* Returns whether the `CaptureVisionRouter` instance has been disposed of.
*
* @returns Boolean indicating whether the `CaptureVisionRouter` instance has been disposed of.
*/
get disposed() {
return __classPrivateFieldGet(this, _CaptureVisionRouter_isDestroyed, "f");
}
/**
* Initializes a new instance of the `CaptureVisionRouter` class.
*
* @returns A promise that resolves with the initialized `CaptureVisionRouter` instance.
*/
static async createInstance() {
if (!mapPackageRegister.license) {
throw Error('Module `license` is not existed.');
}
await mapPackageRegister.license.dynamsoft();
await loadWasm(["cvr"]);
const captureVisionRouter = new CaptureVisionRouter();
const p = new MutablePromise();
let taskID = getNextTaskID();
mapTaskCallBack[taskID] = async (body) => {
var _a;
if (body.success) {
captureVisionRouter._instanceID = body.instanceID;
captureVisionRouter._currentSettings = JSON.parse(JSON.parse(body.outputSettings).data);
CaptureVisionRouterModule._version = `${"2.4.33"}(Worker: ${(_a = innerVersions.cvr) === null || _a === void 0 ? void 0 : _a.worker}, Wasm: ${body.version})`;
__classPrivateFieldSet(captureVisionRouter, _CaptureVisionRouter_innerUseTag, true, "f");
__classPrivateFieldSet(captureVisionRouter, _CaptureVisionRouter_intermediateResultManager, captureVisionRouter.getIntermediateResultManager(), "f");
__classPrivateFieldSet(captureVisionRouter, _CaptureVisionRouter_innerUseTag, false, "f");
p.resolve(captureVisionRouter);
}
else {
const err = Error(body.message);
if (body.stack) {
err.stack = body.stack;
}
p.reject(err);
}
};
worker.postMessage({
type: 'cvr_createInstance',
id: taskID,
});
return p;
}
;
async _singleFrameModeCallback(dsImage) {
for (let receiver of __classPrivateFieldGet(this, _CaptureVisionRouter_resultReceiverSet, "f")) {
this._isOutputOriginalImage && receiver.onOriginalImageResultReceived && receiver.onOriginalImageResultReceived({ imageData: dsImage });
}
const copyDsImageData = {
bytes: new Uint8Array(dsImage.bytes),
width: dsImage.width,
height: dsImage.height,
stride: dsImage.stride,
format: dsImage.format,
tag: dsImage.tag
};
if (!this._templateName)
this._templateName = this._currentSettings.CaptureVisionTemplates[0].Name;
const result = await this.capture(copyDsImageData, this._templateName);
result.originalImageTag = dsImage.tag;
const resultCommonPart = {
originalImageHashId: result.originalImageHashId,
originalImageTag: result.originalImageTag,
errorCode: result.errorCode,
errorString: result.errorString
};
for (let receiver of __classPrivateFieldGet(this, _CaptureVisionRouter_resultReceiverSet, "f")) {
if (receiver.isDce) {
receiver.onCapturedResultReceived(result, {
isDetectVerifyOpen: false,
isNormalizeVerifyOpen: false,
isBarcodeVerifyOpen: false,
isLabelVerifyOpen: false,
});
continue;
}
for (let resultItem in resultItemMapConfig) {
const _itemType = resultItem;
const _itemConfig = resultItemMapConfig[_itemType];
receiver[_itemConfig.reveiver] && result[_itemType] && receiver[_itemConfig.reveiver](Object.assign(Object.assign({}, resultCommonPart), { [_itemType]: result[_itemType] }));
}
receiver.onCapturedResultReceived && receiver.onCapturedResultReceived(result);
}
}
/**
* Sets up an image source to provide images for continuous processing.
* @param imageSource The image source which is compliant with the `ImageSourceAdapter` interface.
*/
setInput(imageSource) {
checkIsDisposed(this);
if (!imageSource) {
__classPrivateFieldSet(this, _CaptureVisionRouter_isa, null, "f");
return;
}
__classPrivateFieldSet(this, _CaptureVisionRouter_isa, imageSource, "f");
if (imageSource.isCameraEnhancer) {
if (__classPrivateFieldGet(this, _CaptureVisionRouter_intermediateResultManager, "f")) {
__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f")._intermediateResultReceiver.isDce = true;
__classPrivateFieldGet(this, _CaptureVisionRouter_intermediateResultManager, "f").addResultReceiver(__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f")._intermediateResultReceiver);
}
const cameraView = __classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").getCameraView();
if (cameraView) {
const dceCrr = cameraView._capturedResultReceiver;
dceCrr.isDce = true;
__classPrivateFieldGet(this, _CaptureVisionRouter_resultReceiverSet, "f").add(dceCrr);
}
// TODO: think about off.
//(imageSource as any).on("singleFrameAcquired", this._singleFrameModeCallback);
}
}
;
/**
* Returns the image source object.
*/
getInput() {
return __classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f");
}
;
/**
* Adds or removes listeners for image source state change.
*/
addImageSourceStateListener(listener) {
checkIsDisposed(this);
if (typeof listener !== "object")
return console.warn(`Invalid ISA state listener.`);
if (!listener || !Object.keys(listener))
return;
__classPrivateFieldGet(this, _CaptureVisionRouter_isaStateListenerSet, "f").add(listener);
}
;
removeImageSourceStateListener(listener) {
checkIsDisposed(this);
return __classPrivateFieldGet(this, _CaptureVisionRouter_isaStateListenerSet, "f").delete(listener);
}
/**
* Adds a `CapturedResultReceiver` object as the receiver of captured results.
* @param receiver The receiver object, of type `CapturedResultReceiver`.
*/
addResultReceiver(receiver) {
checkIsDisposed(this);
if (typeof receiver !== "object")
throw new Error(`Invalid receiver.`);
if (!receiver || !Object.keys(receiver).length)
return;
__classPrivateFieldGet(this, _CaptureVisionRouter_resultReceiverSet, "f").add(receiver);
this._setCrrRegistry();
}
;
/**
* Removes the specified `CapturedResultReceiver` object.
* @param receiver The receiver object, of type `CapturedResultReceiver`.
*/
removeResultReceiver(receiver) {
checkIsDisposed(this);
__classPrivateFieldGet(this, _CaptureVisionRouter_resultReceiverSet, "f").delete(receiver);
this._setCrrRegistry();
}
async _setCrrRegistry() {
const receiver = {
onCapturedResultReceived: false,
onDecodedBarcodesReceived: false,
onRecognizedTextLinesReceived: false,
onDetectedQuadsReceived: false,
onNormalizedImagesReceived: false,
onParsedResultsReceived: false
};
for (let r of __classPrivateFieldGet(this, _CaptureVisionRouter_resultReceiverSet, "f")) {
if (r.isDce)
continue;
receiver.onCapturedResultReceived = !!r["onCapturedResultReceived"];
receiver.onDecodedBarcodesReceived = !!r["onDecodedBarcodesReceived"];
receiver.onRecognizedTextLinesReceived = !!r["onRecognizedTextLinesReceived"];
receiver.onDetectedQuadsReceived = !!r["onDetectedQuadsReceived"];
receiver.onNormalizedImagesReceived = !!r["onNormalizedImagesReceived"];
receiver.onParsedResultsReceived = !!r["onParsedResultsReceived"];
}
const p = new MutablePromise();
let taskID = getNextTaskID();
mapTaskCallBack[taskID] = async (body) => {
if (body.success) {
p.resolve();
}
else {
let ex = new Error(body.message);
ex.stack = body.stack + '\n' + ex.stack;
p.reject();
}
};
worker.postMessage({
type: "cvr_setCrrRegistry",
id: taskID,
instanceID: this._instanceID,
body: {
receiver: JSON.stringify(receiver)
}
});
return p;
}
/**
* Adds a `MultiFrameResultCrossFilter` object to filter non-essential results.
* @param filter The filter object, of type `MultiFrameResultCrossFilter`.
*
* @returns A promise that resolves when the operation has successfully completed. It does not provide any value upon resolution.
*/
async addResultFilter(filter) {
checkIsDisposed(this);
if (!filter || typeof filter !== "object" || !Object.keys(filter).length) {
return console.warn(`Invalid filter.`);
}
__classPrivateFieldGet(this, _CaptureVisionRouter_resultFilterSet, "f").add(filter);
// When cvr.addResultFilter is called, this method will automatically be invoked to batch update the filter statuses that were set before calling addResultFilter.
filter._dynamsoft();
await this._handleFilterUpdate();
}
;
/**
* Removes the specified `MultiFrameResultCrossFilter` object.
* @param filter The filter object, of type `MultiFrameResultCrossFilter`.
*
* @returns A promise that resolves when the operation has successfully completed. It does not provide any value upon resolution.
*/
async removeResultFilter(filter) {
checkIsDisposed(this);
__classPrivateFieldGet(this, _CaptureVisionRouter_resultFilterSet, "f").delete(filter);
await this._handleFilterUpdate();
}
async _handleFilterUpdate() {
/**
* Each time a "filter" is added or removed, the "filter set" will be re-traversed,
* and _intermediateResultReceiverOfFilter will be added when necessary.
* This ensures that _intermediateResultReceiverOfFilter is not left in the "filter set" when the "filter set" is empty or when no filter in the "filter set" has isLatestOverlappingEnabled set to true.
*/
__classPrivateFieldGet(this, _CaptureVisionRouter_intermediateResultManager, "f").removeResultReceiver(_intermediateResultReceiverOfFilter);
if (__classPrivateFieldGet(this, _CaptureVisionRouter_resultFilterSet, "f").size === 0) {
this._isOpenBarcodeVerify = false;
this._isOpenLabelVerify = false;
this._isOpenDetectVerify = false;
this._isOpenNormalizeVerify = false;
const _verificationEnabled = {
[EnumCapturedResultItemType.CRIT_BARCODE]: false,
[EnumCapturedResultItemType.CRIT_TEXT_LINE]: false,
[EnumCapturedResultItemType.CRIT_DETECTED_QUAD]: false,
[EnumCapturedResultItemType.CRIT_NORMALIZED_IMAGE]: false
};
const _duplicateFilterEnabled = {
[EnumCapturedResultItemType.CRIT_BARCODE]: false,
[EnumCapturedResultItemType.CRIT_TEXT_LINE]: false,
[EnumCapturedResultItemType.CRIT_DETECTED_QUAD]: false,
[EnumCapturedResultItemType.CRIT_NORMALIZED_IMAGE]: false
};
await _enableResultCrossVerification(this, _verificationEnabled);
await _enableResultDeduplication(this, _duplicateFilterEnabled);
return;
}
for (let filter of __classPrivateFieldGet(this, _CaptureVisionRouter_resultFilterSet, "f")) {
this._isOpenBarcodeVerify = filter.isResultCrossVerificationEnabled(EnumCapturedResultItemType.CRIT_BARCODE);
this._isOpenLabelVerify = filter.isResultCrossVerificationEnabled(EnumCapturedResultItemType.CRIT_TEXT_LINE);
this._isOpenDetectVerify = filter.isResultCrossVerificationEnabled(EnumCapturedResultItemType.CRIT_DETECTED_QUAD);
this._isOpenNormalizeVerify = filter.isResultCrossVerificationEnabled(EnumCapturedResultItemType.CRIT_NORMALIZED_IMAGE);
if (filter.isLatestOverlappingEnabled(EnumCapturedResultItemType.CRIT_BARCODE)) {
const _isExist = [...__classPrivateFieldGet(this, _CaptureVisionRouter_intermediateResultManager, "f")._intermediateResultReceiverSet.values()].find((receiver) => { return receiver.isFilter; });
if (!_isExist) {
__classPrivateFieldGet(this, _CaptureVisionRouter_intermediateResultManager, "f").addResultReceiver(_intermediateResultReceiverOfFilter);
}
}
await _enableResultCrossVerification(this, filter.verificationEnabled);
await _enableResultDeduplication(this, filter.duplicateFilterEnabled);
await _setDuplicateForgetTime(this, filter.duplicateForgetTime);
}
}
/**
* Initiates a capturing process based on a specified template. This process is repeated for each image fetched from the source.
* @param templateName [Optional] Specifies a "CaptureVisionTemplate" to use.
*
* @returns A promise that resolves when the capturing process has successfully started. It does not provide any value upon resolution.
*/
async startCapturing(templateName) {
var _a, _b;
checkIsDisposed(this);
if (!this._isPauseScan)
return;
if (!__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f"))
throw new Error(`'ImageSourceAdapter' is not set. call 'setInput' before 'startCapturing'`);
if (!templateName)
templateName = CaptureVisionRouter._defaultTemplate;
const tasks = await this.containsTask(templateName);
await loadWasm(tasks);
/*
* Why do we need to re-add an existing "filter" when calling "startCapturing"?
* Because there may be a situation where the corresponding wasm module has not been loaded when adding "filter",
* so after checking the required wasm module in "startCapturing", we will add "filter" again to ensure that "filter" takes effect in wasm.
*
* Why not check for the required wasm when adding the "filter"?
* Because each result type has a default value, we cannot know which wasm modules are actually needed through the passed "filter"
*
* This part of the logic has room for optimization. will do.
**/
for (let filter of __classPrivateFieldGet(this, _CaptureVisionRouter_resultFilterSet, "f")) {
await this.addResultFilter(filter);
}
if (tasks.includes("dlr") && !((_a = mapPackageRegister.dlr) === null || _a === void 0 ? void 0 : _a.bLoadConfusableCharsData)) {
const _engineResourcePaths = handleEngineResourcePaths(CoreModule.engineResourcePaths);
await ((_b = mapPackageRegister.dlr) === null || _b === void 0 ? void 0 : _b.loadRecognitionData("ConfusableChars", _engineResourcePaths.dlr));
}
if (__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").isCameraEnhancer) {
if (tasks.includes("ddn")) {
__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").setPixelFormat(EnumImagePixelFormat.IPF_ABGR_8888);
}
else {
__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").setPixelFormat(EnumImagePixelFormat.IPF_GRAYSCALED);
}
}
if (__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").singleFrameMode !== undefined && __classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").singleFrameMode !== "disabled") {
this._templateName = templateName;
__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").on("singleFrameAcquired", this._singleFrameModeCallbackBind);
return;
}
const colourChannelUsageType = __classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").getColourChannelUsageType();
if (colourChannelUsageType === EnumColourChannelUsageType.CCUT_AUTO) {
__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").setColourChannelUsageType(tasks.includes("ddn") ?
EnumColourChannelUsageType.CCUT_FULL_CHANNEL
:
EnumColourChannelUsageType.CCUT_Y_CHANNEL_ONLY);
}
if (__classPrivateFieldGet(this, _CaptureVisionRouter_promiseStartScan, "f") && __classPrivateFieldGet(this, _CaptureVisionRouter_promiseStartScan, "f").isPending)
return __classPrivateFieldGet(this, _CaptureVisionRouter_promiseStartScan, "f");
__classPrivateFieldSet(this, _CaptureVisionRouter_promiseStartScan, new MutablePromise((rs, rj) => {
if (this.disposed)
return;
let taskID = getNextTaskID();
mapTaskCallBack[taskID] = async (body) => {
if (!__classPrivateFieldGet(this, _CaptureVisionRouter_promiseStartScan, "f") || __classPrivateFieldGet(this, _CaptureVisionRouter_promiseStartScan, "f").isFulfilled)
return;
if (body.success) {
this._isPauseScan = false;
this._isOutputOriginalImage = body.isOutputOriginalImage;
this._loopReadVideoTimeoutId && clearTimeout(this._loopReadVideoTimeoutId);
this._loopReadVideoTimeoutId = setTimeout(async () => {
if (this._minImageCaptureInterval !== -1) {
__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").startFetching();
}
this._loopReadVideo(templateName);
// try {
// await this._loopReadVideo(templateName);
// } catch (ex) {
// rj(ex);
// }
rs();
}, 0);
}
else {
let ex = new Error(body.message);
ex.stack = body.stack + '\n' + ex.stack;
return rj(ex);
}
};
worker.postMessage({
type: "cvr_startCapturing",
id: taskID,
instanceID: this._instanceID,
body: { templateName }
});
}), "f");
return await __classPrivateFieldGet(this, _CaptureVisionRouter_promiseStartScan, "f");
}
/**
* Stops the capturing process.
*/
stopCapturing() {
checkIsDisposed(this);
if (!__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f"))
return;
if (__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").isCameraEnhancer) {
if (__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").singleFrameMode !== undefined && __classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").singleFrameMode !== "disabled") {
__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").off("singleFrameAcquired", this._singleFrameModeCallbackBind);
return;
}
}
_clearVerifyList(this);
__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").stopFetching();
this._averageProcessintTimeArray = [];
this._averageTime = 999;
this._isPauseScan = true;
__classPrivateFieldSet(this, _CaptureVisionRouter_promiseStartScan, null, "f");
__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").setColourChannelUsageType(EnumColourChannelUsageType.CCUT_AUTO);
}
async containsTask(templateName) {
checkIsDisposed(this);
return await new Promise((rs, rj) => {
let taskID = getNextTaskID();
mapTaskCallBack[taskID] = async (body) => {
if (body.success) {
return rs(JSON.parse(body.tasks));
}
else {
let ex = new Error(body.message);
ex.stack = body.stack + '\n' + ex.stack;
return rj(ex);
}
};
worker.postMessage({
type: "cvr_containsTask",
id: taskID,
instanceID: this._instanceID,
body: {
templateName
}
});
});
}
/**
* Video stream capture, recursive call, loop frame capture
*/
async _loopReadVideo(templateName) {
if ((this.disposed || this._isPauseScan)) {
return;
}
__classPrivateFieldSet(this, _CaptureVisionRouter_isScanner, true, "f");
if (__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").isBufferEmpty()) {
if (__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").hasNextImageToFetch()) {
for (let listener of __classPrivateFieldGet(this, _CaptureVisionRouter_isaStateListenerSet, "f")) {
listener.onImageSourceStateReceived && listener.onImageSourceStateReceived(EnumImageSourceState.ISS_BUFFER_EMPTY);
}
}
else if (!(__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").hasNextImageToFetch())) {
for (let listener of __classPrivateFieldGet(this, _CaptureVisionRouter_isaStateListenerSet, "f")) {
listener.onImageSourceStateReceived && listener.onImageSourceStateReceived(EnumImageSourceState.ISS_EXHAUSTED);
}
}
}
if (this._minImageCaptureInterval === -1 || __classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").isBufferEmpty()) {
try {
if (__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").isBufferEmpty() && CaptureVisionRouter._onLog)
CaptureVisionRouter._onLog(`buffer is empty so fetch image`);
if (CaptureVisionRouter._onLog) {
CaptureVisionRouter._onLog(`DCE: start fetching a frame: ${Date.now()}`);
}
this._dsImage = __classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").fetchImage();
if (CaptureVisionRouter._onLog) {
CaptureVisionRouter._onLog(`DCE: finish fetching a frame: ${Date.now()}`);
}
__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").setImageFetchInterval(this._averageTime);
}
catch (e) {
this._reRunCurrnetFunc(templateName);
return;
}
}
else {
__classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").setImageFetchInterval(this._averageTime - (this._dsImage && this._dsImage.tag ? this._dsImage.tag.timeSpent : 0));
this._dsImage = __classPrivateFieldGet(this, _CaptureVisionRouter_isa, "f").getImage();
if (this._dsImage.tag) {
if (Date.now() - this._dsImage.tag.timeStamp > 200) {
this._reRunCurrnetFunc(templateName);
return;
}
}
}
if (!this._dsImage) {
this._reRunCurrnetFunc(templateName);
return;
}
for (let receiver of __classPrivateFieldGet(this, _CaptureVisionRouter_resultReceiverSet, "f")) {
this._isOutputOriginalImage && receiver.onOriginalImageResultReceived && receiver.onOriginalImageResultReceived({ imageData: this._dsImage });
}
// capture
// try {
// const captureStartTime = Date.now();
// const result = await this._captureDsimage(this._dsImage, templateName);
// if (CaptureVisionRouter._onLog) CaptureVisionRouter._onLog(`no js handle time: ${Date.now() - captureStartTime}`);
// if (this._isPauseScan) {
// this._reRunCurrnetFunc(templateName);
// return;
// }
// (result as any).originalImageTag = this._dsImage.tag ? this._dsImage.tag : null;
// const resultCommonPart = {
// originalImageHashId: result.originalImageHashId,
// originalImageTag: result.originalImageTag,
// errorCode: result.errorCode,
// errorString: result.errorString
// }
// for (let receiver of this.#resultReceiverSet) {
// if ((receiver as any).isDce) {
// const drawTime = Date.now();
// (receiver as any).onCapturedResultReceived(result, {
// isDetectVerifyOpen: this._isOpenDetectVerify,
// isNormalizeVerifyOpen: this._isOpenNormalizeVerify,
// isBarcodeVerifyOpen: this._isOpenBarcodeVerify,
// isLabelVerifyOpen: this._isOpenLabelVerify,
// });
// if (CaptureVisionRouter._onLog) {
// const time = Date.now() - drawTime;
// if (time > 10) CaptureVisionRouter._onLog(`draw result time: ${time}`)
// };
// }
// receiver.onDecodedBarcodesReceived && result.barcodeResultItems && receiver.onDecodedBarcodesReceived({
// ...resultCommonPart,
// barcodeResultItems: result.barcodeResultItems.filter((item: any) => { return !item.isFilter })
// } as DecodedBarcodesResult);
// receiver.onRecognizedTextLinesReceived && result.textLineResultItems && receiver.onRecognizedTextLinesReceived({
// ...resultCommonPart,
// textLineResultItems: result.textLineResultItems.filter((item: any) => { return !item.isFilter })
// } as RecognizedTextLinesResult);
// receiver.onDetectedQuadsReceived && result.detectedQuadResultItems && receiver.onDetectedQuadsReceived({
// ...resultCommonPart,
// detectedQuadResultItems: result.detectedQuadResultItems.filter((item: any) => { return !item.isFilter })
// } as DetectedQuadsResult);
// receiver.onNormalizedImagesReceived && result.normalizedImageResultItems && receiver.onNormalizedImagesReceived({
// ...resultCommonPart,
// normalizedImageResultItems: result.normalizedImageResultItems.filter((item: any) => { return !item.isFilter })
// } as NormalizedImagesResult);
// receiver.onParsedResultsReceived && result.parsedResultItems && receiver.onParsedResultsReceived({
// ...resultCommonPart,
// parsedResultItems: result.parsedResultItems.filter((item: any) => { return !item.isFilter })
// } as ParsedResult);
// if (receiver.onCapturedResultReceived && !(receiver as any).isDce) {
// (result as any).items = result.items.filter((item: any) => { return !item.isFilter });
// if ((result as any).barcodeResultItems) (result as any).barcodeResultItems = result.barcodeResultItems.filter((item: any) => { return !item.isFilter });
// if ((result as any).textLineResultItems) (result as any).textLineResultItems = result.textLineResultItems.filter((item: any) => { return !item.isFilter });
// if ((result as any).detectedQuadResultItems) (result as any).detectedQuadResultItems = result.detectedQuadResultItems.filter((item: any) => { return !item.isFilter });
// if ((result as any).normalizedImageResultItems) (result as any).normalizedImageResultItems = result.normalizedImageResultItems.filter((item: any) => { return !item.isFilter });
// if ((result as any).parsedResultItems) (result as any).parsedResultItems = result.parsedResultItems.filter((item: any) => { return !item.isFilter });
// receiver.onCapturedResultReceived(result);
// }
// }
// const fetchImageCalculateStartTime = Date.now();
// if (this._minImageCaptureInterval > -1) {
// if (this._averageProcessintTimeArray.length === 5) this._averageProcessintTimeArray.shift();
// if (this._averageFetchImageTimeArray.length === 5) this._averageFetchImageTimeArray.shift();
// this._averageProcessintTimeArray.push(Date.now() - captureStartTime);
// //this._averageTime = this._averageProcessintTimeArray.reduce((time, value) => time + value, 0) / this._averageProcessintTimeArray.length;
// this._averageFetchImageTimeArray.push((this._dsImage && this._dsImage.tag ? (this._dsImage.tag as any).timeSpent : 0));
// this._averageTime = Math.min(...this._averageProcessintTimeArray) - Math.max(...this._averageFetchImageTimeArray);
// this._averageTime = this._averageTime > 0 ? this._averageTime : 0;
// if (CaptureVisionRouter._onLog) {
// CaptureVisionRouter._onLog(`minImageCaptureInterval: ${this._minImageCaptureInterval}`);
// CaptureVisionRouter._onLog(`averageProcessintTimeArray: ${this._averageProcessintTimeArray}`);
// CaptureVisionRouter._onLog(`averageFetchImageTimeArray: ${this._averageFetchImageTimeArray}`);
// CaptureVisionRouter._onLog(`averageTime: ${this._averageTime}`);
// };
// }
// if (CaptureVisionRouter._onLog) {
// const time = Date.now() - fetchImageCalculateStartTime;
// if (time > 10) CaptureVisionRouter._onLog(`fetch image calculate time: ${time}`)
// };
// if (CaptureVisionRouter._onLog) CaptureVisionRouter._onLog(`time finish decode: ${Date.now()}`)
// if (CaptureVisionRouter._onLog) CaptureVisionRouter._onLog(`main time: ${Date.now() - captureStartTime}`)