forked from mebjas/html5-qrcode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
code-decoder.ts
127 lines (113 loc) · 4.17 KB
/
code-decoder.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/**
* @fileoverview
* Shim layer for providing the decoding library.
*
* @author mebjas <[email protected]>
*
* The word "QR Code" is registered trademark of DENSO WAVE INCORPORATED
* http://www.denso-wave.com/qrcode/faqpatent-e.html
*/
import {
QrcodeResult,
Html5QrcodeSupportedFormats,
Logger,
QrcodeDecoderAsync,
RobustQrcodeDecoderAsync,
} from "./core";
import { ZXingHtml5QrcodeDecoder } from "./zxing-html5-qrcode-decoder";
import { BarcodeDetectorDelegate } from "./native-bar-code-detector";
/**
* Shim layer for {@interface QrcodeDecoder}.
*
* Currently uses {@class ZXingHtml5QrcodeDecoder}, can be replace with another library.
*/
export class Html5QrcodeShim implements RobustQrcodeDecoderAsync {
private verbose: boolean;
private primaryDecoder: QrcodeDecoderAsync;
private secondaryDecoder: QrcodeDecoderAsync | undefined;
private readonly EXECUTIONS_TO_REPORT_PERFORMANCE = 100;
private executions: number = 0;
private executionResults: Array<number> = [];
private wasPrimaryDecoderUsedInLastDecode = false;
public constructor(
requestedFormats: Array<Html5QrcodeSupportedFormats>,
useBarCodeDetectorIfSupported: boolean,
verbose: boolean,
logger: Logger) {
this.verbose = verbose;
// Use BarcodeDetector library if enabled by config and is supported.
if (useBarCodeDetectorIfSupported
&& BarcodeDetectorDelegate.isSupported()) {
this.primaryDecoder = new BarcodeDetectorDelegate(
requestedFormats, verbose, logger);
// If 'BarcodeDetector' is supported, the library will alternate
// between 'BarcodeDetector' and 'zxing-js' to compensate for
// quality gaps between the two.
this.secondaryDecoder = new ZXingHtml5QrcodeDecoder(
requestedFormats, verbose, logger);
} else {
this.primaryDecoder = new ZXingHtml5QrcodeDecoder(
requestedFormats, verbose, logger);
}
}
async decodeAsync(canvas: HTMLCanvasElement): Promise<QrcodeResult> {
let startTime = performance.now();
try {
return await this.getDecoder().decodeAsync(canvas);
} finally {
this.possiblyLogPerformance(startTime);
}
}
async decodeRobustlyAsync(canvas: HTMLCanvasElement)
: Promise<QrcodeResult> {
let startTime = performance.now();
try {
return await this.primaryDecoder.decodeAsync(canvas);
} catch(error) {
if (this.secondaryDecoder) {
// Try fallback.
return this.secondaryDecoder.decodeAsync(canvas);
}
throw error;
} finally {
this.possiblyLogPerformance(startTime);
}
}
private getDecoder(): QrcodeDecoderAsync {
if (!this.secondaryDecoder) {
return this.primaryDecoder;
}
if (this.wasPrimaryDecoderUsedInLastDecode === false) {
this.wasPrimaryDecoderUsedInLastDecode = true;
return this.primaryDecoder;
}
this.wasPrimaryDecoderUsedInLastDecode = false;
return this.secondaryDecoder;
}
private possiblyLogPerformance(startTime: number) {
if (!this.verbose) {
return;
}
let executionTime = performance.now() - startTime;
this.executionResults.push(executionTime);
this.executions++;
this.possiblyFlushPerformanceReport();
}
// Dumps mean decoding latency to console for last
// EXECUTIONS_TO_REPORT_PERFORMANCE runs.
// TODO(mebjas): Can we automate instrumentation runs?
possiblyFlushPerformanceReport() {
if (this.executions < this.EXECUTIONS_TO_REPORT_PERFORMANCE) {
return;
}
let sum:number = 0;
for (let executionTime of this.executionResults) {
sum += executionTime;
}
let mean = sum / this.executionResults.length;
// eslint-disable-next-line no-console
console.log(`${mean} ms for ${this.executionResults.length} last runs.`);
this.executions = 0;
this.executionResults = [];
}
}