id-scanner-lib 1.2.2 → 1.3.2
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/LICENSE +1 -1
- package/README.md +375 -363
- package/dist/id-scanner-core.esm.js +427 -221
- package/dist/id-scanner-core.esm.js.map +1 -1
- package/dist/id-scanner-core.js +427 -221
- package/dist/id-scanner-core.js.map +1 -1
- package/dist/id-scanner-core.min.js +1 -9
- package/dist/id-scanner-core.min.js.map +1 -1
- package/dist/id-scanner-ocr.esm.js +451 -276
- package/dist/id-scanner-ocr.esm.js.map +1 -1
- package/dist/id-scanner-ocr.js +451 -276
- package/dist/id-scanner-ocr.js.map +1 -1
- package/dist/id-scanner-ocr.min.js +1 -9
- package/dist/id-scanner-ocr.min.js.map +1 -1
- package/dist/id-scanner-qr.esm.js +483 -233
- package/dist/id-scanner-qr.esm.js.map +1 -1
- package/dist/id-scanner-qr.js +482 -232
- package/dist/id-scanner-qr.js.map +1 -1
- package/dist/id-scanner-qr.min.js +1 -9
- package/dist/id-scanner-qr.min.js.map +1 -1
- package/dist/id-scanner.js +2138 -358
- package/dist/id-scanner.js.map +1 -1
- package/dist/id-scanner.min.js +1 -9
- package/dist/id-scanner.min.js.map +1 -1
- package/package.json +27 -7
- package/src/demo/demo.ts +178 -62
- package/src/id-recognition/anti-fake-detector.ts +317 -0
- package/src/id-recognition/id-detector.ts +184 -155
- package/src/id-recognition/ocr-processor.ts +193 -146
- package/src/id-recognition/ocr-worker.ts +82 -72
- package/src/index-umd.ts +347 -110
- package/src/index.ts +866 -91
- package/src/ocr-module.ts +108 -60
- package/src/qr-module.ts +104 -54
- package/src/scanner/barcode-scanner.ts +145 -58
- package/src/scanner/qr-scanner.ts +86 -47
- package/src/utils/image-processing.ts +479 -294
- package/dist/core.d.ts +0 -77
- package/dist/demo/demo.d.ts +0 -14
- package/dist/id-recognition/data-extractor.d.ts +0 -105
- package/dist/id-recognition/id-detector.d.ts +0 -100
- package/dist/id-recognition/ocr-processor.d.ts +0 -64
- package/dist/id-scanner.esm.js +0 -94656
- package/dist/id-scanner.esm.js.map +0 -1
- package/dist/index-umd.d.ts +0 -96
- package/dist/index.d.ts +0 -78
- package/dist/ocr-module.d.ts +0 -67
- package/dist/qr-module.d.ts +0 -68
- package/dist/scanner/barcode-scanner.d.ts +0 -90
- package/dist/scanner/qr-scanner.d.ts +0 -80
- package/dist/types/core.d.ts +0 -77
- package/dist/types/demo/demo.d.ts +0 -14
- package/dist/types/id-recognition/data-extractor.d.ts +0 -105
- package/dist/types/id-recognition/id-detector.d.ts +0 -100
- package/dist/types/id-recognition/ocr-processor.d.ts +0 -64
- package/dist/types/index-umd.d.ts +0 -96
- package/dist/types/index.d.ts +0 -78
- package/dist/types/ocr-module.d.ts +0 -67
- package/dist/types/qr-module.d.ts +0 -68
- package/dist/types/scanner/barcode-scanner.d.ts +0 -90
- package/dist/types/scanner/qr-scanner.d.ts +0 -80
- package/dist/types/utils/camera.d.ts +0 -81
- package/dist/types/utils/image-processing.d.ts +0 -75
- package/dist/types/utils/types.d.ts +0 -65
- package/dist/utils/camera.d.ts +0 -81
- package/dist/utils/image-processing.d.ts +0 -75
- package/dist/utils/types.d.ts +0 -65
|
@@ -4,29 +4,29 @@
|
|
|
4
4
|
* @module BarcodeScanner
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { Camera } from
|
|
8
|
-
import { ImageProcessor } from
|
|
7
|
+
import { Camera } from "../utils/camera"
|
|
8
|
+
import { ImageProcessor } from "../utils/image-processing"
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* 条形码扫描器配置选项
|
|
12
|
-
*
|
|
12
|
+
*
|
|
13
13
|
* @interface BarcodeScannerOptions
|
|
14
14
|
* @property {number} [scanInterval] - 扫描间隔时间(毫秒),默认为200ms
|
|
15
15
|
* @property {Function} [onScan] - 扫描成功回调函数
|
|
16
16
|
* @property {Function} [onError] - 错误处理回调函数
|
|
17
17
|
*/
|
|
18
18
|
export interface BarcodeScannerOptions {
|
|
19
|
-
scanInterval?: number
|
|
20
|
-
onScan?: (result: string) => void
|
|
21
|
-
onError?: (error: Error) => void
|
|
19
|
+
scanInterval?: number
|
|
20
|
+
onScan?: (result: string) => void
|
|
21
|
+
onError?: (error: Error) => void
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* 条形码扫描器类
|
|
26
|
-
*
|
|
26
|
+
*
|
|
27
27
|
* 提供实时扫描和识别摄像头中的条形码的功能
|
|
28
28
|
* 注意:当前实现是简化版,实际项目中建议集成专门的条形码识别库如ZXing或Quagga.js
|
|
29
|
-
*
|
|
29
|
+
*
|
|
30
30
|
* @example
|
|
31
31
|
* ```typescript
|
|
32
32
|
* // 创建条形码扫描器
|
|
@@ -39,126 +39,213 @@ export interface BarcodeScannerOptions {
|
|
|
39
39
|
* console.error('扫描错误:', error);
|
|
40
40
|
* }
|
|
41
41
|
* });
|
|
42
|
-
*
|
|
42
|
+
*
|
|
43
43
|
* // 启动扫描
|
|
44
44
|
* const videoElement = document.getElementById('video') as HTMLVideoElement;
|
|
45
45
|
* await barcodeScanner.start(videoElement);
|
|
46
|
-
*
|
|
46
|
+
*
|
|
47
47
|
* // 停止扫描
|
|
48
48
|
* barcodeScanner.stop();
|
|
49
49
|
* ```
|
|
50
50
|
*/
|
|
51
51
|
export class BarcodeScanner {
|
|
52
|
-
private camera: Camera
|
|
53
|
-
private scanning = false
|
|
54
|
-
private scanTimer: number | null = null
|
|
55
|
-
|
|
52
|
+
private camera: Camera
|
|
53
|
+
private scanning = false
|
|
54
|
+
private scanTimer: number | null = null
|
|
55
|
+
|
|
56
56
|
/**
|
|
57
57
|
* 创建条形码扫描器实例
|
|
58
|
-
*
|
|
58
|
+
*
|
|
59
59
|
* @param {BarcodeScannerOptions} [options] - 扫描器配置选项
|
|
60
60
|
*/
|
|
61
61
|
constructor(private options: BarcodeScannerOptions = {}) {
|
|
62
62
|
this.options = {
|
|
63
63
|
scanInterval: 200,
|
|
64
|
-
...options
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
this.camera = new Camera()
|
|
64
|
+
...options,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this.camera = new Camera()
|
|
68
68
|
}
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
/**
|
|
71
71
|
* 启动条形码扫描
|
|
72
|
-
*
|
|
72
|
+
*
|
|
73
73
|
* 初始化相机并开始连续扫描视频帧中的条形码
|
|
74
|
-
*
|
|
74
|
+
*
|
|
75
75
|
* @param {HTMLVideoElement} videoElement - 用于显示相机画面的video元素
|
|
76
76
|
* @returns {Promise<void>} 启动完成的Promise
|
|
77
77
|
* @throws 如果无法访问相机,将通过onError回调报告错误
|
|
78
78
|
*/
|
|
79
79
|
async start(videoElement: HTMLVideoElement): Promise<void> {
|
|
80
80
|
try {
|
|
81
|
-
await this.camera.initialize(videoElement)
|
|
82
|
-
this.scanning = true
|
|
83
|
-
this.scan()
|
|
81
|
+
await this.camera.initialize(videoElement)
|
|
82
|
+
this.scanning = true
|
|
83
|
+
this.scan()
|
|
84
84
|
} catch (error) {
|
|
85
85
|
if (this.options.onError) {
|
|
86
|
-
this.options.onError(
|
|
86
|
+
this.options.onError(
|
|
87
|
+
error instanceof Error ? error : new Error(String(error))
|
|
88
|
+
)
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
|
-
|
|
92
|
+
|
|
91
93
|
/**
|
|
92
94
|
* 执行一次条形码扫描
|
|
93
|
-
*
|
|
95
|
+
*
|
|
94
96
|
* 内部方法,捕获当前视频帧并尝试识别其中的条形码
|
|
95
|
-
*
|
|
97
|
+
*
|
|
96
98
|
* @private
|
|
97
99
|
*/
|
|
98
100
|
private scan(): void {
|
|
99
|
-
if (!this.scanning) return
|
|
100
|
-
|
|
101
|
-
const imageData = this.camera.captureFrame()
|
|
102
|
-
|
|
101
|
+
if (!this.scanning) return
|
|
102
|
+
|
|
103
|
+
const imageData = this.camera.captureFrame()
|
|
104
|
+
|
|
103
105
|
if (imageData) {
|
|
104
106
|
try {
|
|
105
107
|
// 图像预处理,提高识别率
|
|
106
108
|
const enhancedImage = ImageProcessor.adjustBrightnessContrast(
|
|
107
109
|
ImageProcessor.toGrayscale(imageData),
|
|
108
110
|
10, // 亮度
|
|
109
|
-
20
|
|
110
|
-
)
|
|
111
|
-
|
|
111
|
+
20 // 对比度
|
|
112
|
+
)
|
|
113
|
+
|
|
112
114
|
// 这里实际项目中可以集成第三方条形码扫描库
|
|
113
115
|
// 如 ZXing 或 QuaggaJS
|
|
114
116
|
// 简化实现,这里仅为示例
|
|
115
|
-
this.detectBarcode(enhancedImage)
|
|
117
|
+
this.detectBarcode(enhancedImage)
|
|
116
118
|
} catch (error) {
|
|
117
|
-
console.error(
|
|
119
|
+
console.error("条形码扫描错误:", error)
|
|
118
120
|
}
|
|
119
121
|
}
|
|
120
|
-
|
|
121
|
-
this.scanTimer = window.setTimeout(
|
|
122
|
+
|
|
123
|
+
this.scanTimer = window.setTimeout(
|
|
124
|
+
() => this.scan(),
|
|
125
|
+
this.options.scanInterval
|
|
126
|
+
)
|
|
122
127
|
}
|
|
123
|
-
|
|
128
|
+
|
|
124
129
|
/**
|
|
125
130
|
* 条形码检测方法
|
|
126
|
-
*
|
|
131
|
+
*
|
|
127
132
|
* 注意:这是一个简化实现,实际需要集成专门的条形码识别库
|
|
128
|
-
*
|
|
133
|
+
*
|
|
129
134
|
* @private
|
|
130
135
|
* @param {ImageData} imageData - 要检测条形码的图像数据
|
|
131
136
|
*/
|
|
132
137
|
private detectBarcode(imageData: ImageData): void {
|
|
133
138
|
// 这里应集成条形码识别库
|
|
134
139
|
// 如 ZXing 或 QuaggaJS
|
|
135
|
-
|
|
140
|
+
|
|
136
141
|
// 简化示例,实际项目中请替换为真实实现
|
|
137
|
-
console.log(
|
|
138
|
-
|
|
142
|
+
console.log("正在扫描条形码...")
|
|
143
|
+
|
|
139
144
|
// 模拟找到条形码
|
|
140
145
|
if (Math.random() > 0.95) {
|
|
141
|
-
const mockResult =
|
|
142
|
-
|
|
146
|
+
const mockResult = "6901234567890" // 模拟条形码结果
|
|
147
|
+
|
|
143
148
|
if (this.options.onScan) {
|
|
144
|
-
this.options.onScan(mockResult)
|
|
149
|
+
this.options.onScan(mockResult)
|
|
145
150
|
}
|
|
146
151
|
}
|
|
147
152
|
}
|
|
148
|
-
|
|
153
|
+
|
|
149
154
|
/**
|
|
150
155
|
* 停止条形码扫描
|
|
151
|
-
*
|
|
156
|
+
*
|
|
152
157
|
* 停止扫描循环并释放相机资源
|
|
153
158
|
*/
|
|
154
159
|
stop(): void {
|
|
155
|
-
this.scanning = false
|
|
156
|
-
|
|
160
|
+
this.scanning = false
|
|
161
|
+
|
|
157
162
|
if (this.scanTimer) {
|
|
158
|
-
clearTimeout(this.scanTimer)
|
|
159
|
-
this.scanTimer = null
|
|
163
|
+
clearTimeout(this.scanTimer)
|
|
164
|
+
this.scanTimer = null
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
this.camera.release()
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 处理图像数据中的条形码
|
|
172
|
+
*
|
|
173
|
+
* @param {ImageData} imageData - 要处理的图像数据
|
|
174
|
+
* @returns {string | null} 识别到的条形码内容,如未识别到则返回null
|
|
175
|
+
*/
|
|
176
|
+
processImageData(imageData: ImageData): string | null {
|
|
177
|
+
try {
|
|
178
|
+
if (
|
|
179
|
+
!imageData ||
|
|
180
|
+
!imageData.data ||
|
|
181
|
+
imageData.width <= 0 ||
|
|
182
|
+
imageData.height <= 0
|
|
183
|
+
) {
|
|
184
|
+
throw new Error("无效的图像数据")
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// 图像预处理,提高识别率
|
|
188
|
+
const enhancedImage = ImageProcessor.adjustBrightnessContrast(
|
|
189
|
+
ImageProcessor.toGrayscale(imageData),
|
|
190
|
+
10, // 亮度
|
|
191
|
+
20 // 对比度
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
// 注意:这里是简化实现
|
|
195
|
+
// 实际项目中,应该集成专门的条形码识别库如ZXing或Quagga.js
|
|
196
|
+
|
|
197
|
+
// 模拟条形码识别
|
|
198
|
+
// 在真实项目中,请替换为实际的条形码识别算法
|
|
199
|
+
const result = this.simulateBarcodeDetection(enhancedImage)
|
|
200
|
+
return result
|
|
201
|
+
} catch (error) {
|
|
202
|
+
if (this.options.onError) {
|
|
203
|
+
this.options.onError(
|
|
204
|
+
error instanceof Error ? error : new Error(String(error))
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
return null
|
|
160
208
|
}
|
|
161
|
-
|
|
162
|
-
this.camera.release();
|
|
163
209
|
}
|
|
164
|
-
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* 模拟条形码检测
|
|
213
|
+
* 仅用于演示,实际使用时应该替换为真实的条形码识别算法
|
|
214
|
+
*
|
|
215
|
+
* @private
|
|
216
|
+
* @param {ImageData} imageData - 要检测条形码的图像数据
|
|
217
|
+
* @returns {string | null} 模拟的条形码识别结果
|
|
218
|
+
*/
|
|
219
|
+
private simulateBarcodeDetection(imageData: ImageData): string | null {
|
|
220
|
+
// 这里只是模拟,真实环境中应当使用条形码识别库进行识别
|
|
221
|
+
|
|
222
|
+
// 在中间区域检测到足够多垂直边缘时,认为可能存在条形码
|
|
223
|
+
const midX = Math.floor(imageData.width / 2)
|
|
224
|
+
const midY = Math.floor(imageData.height / 2)
|
|
225
|
+
const sampleWidth = Math.min(100, Math.floor(imageData.width / 3))
|
|
226
|
+
|
|
227
|
+
let edgeCount = 0
|
|
228
|
+
let lastPixel = 0
|
|
229
|
+
|
|
230
|
+
// 简单的边缘检测,统计中心水平线上像素变化次数
|
|
231
|
+
for (let x = midX - sampleWidth / 2; x < midX + sampleWidth / 2; x++) {
|
|
232
|
+
const pixelPos = (midY * imageData.width + x) * 4
|
|
233
|
+
const pixelValue = imageData.data[pixelPos]
|
|
234
|
+
|
|
235
|
+
if (Math.abs(pixelValue - lastPixel) > 30) {
|
|
236
|
+
edgeCount++
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
lastPixel = pixelValue
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// 如果边缘变化次数在合理范围内,认为是条形码
|
|
243
|
+
// 实际的条形码具有规律的宽窄条纹
|
|
244
|
+
if (edgeCount > 10 && edgeCount < 50) {
|
|
245
|
+
// 生成一个模拟的条形码结果
|
|
246
|
+
return "690" + Math.floor(Math.random() * 10000000000)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return null
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -4,28 +4,28 @@
|
|
|
4
4
|
* @module QRScanner
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import jsQR from
|
|
8
|
-
import { Camera } from
|
|
7
|
+
import jsQR from "jsqr"
|
|
8
|
+
import { Camera } from "../utils/camera"
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* 二维码扫描器配置选项
|
|
12
|
-
*
|
|
12
|
+
*
|
|
13
13
|
* @interface QRScannerOptions
|
|
14
14
|
* @property {number} [scanInterval] - 扫描间隔时间(毫秒),默认为200ms
|
|
15
15
|
* @property {Function} [onScan] - 扫描成功回调函数
|
|
16
16
|
* @property {Function} [onError] - 错误处理回调函数
|
|
17
17
|
*/
|
|
18
18
|
export interface QRScannerOptions {
|
|
19
|
-
scanInterval?: number
|
|
20
|
-
onScan?: (result: string) => void
|
|
21
|
-
onError?: (error: Error) => void
|
|
19
|
+
scanInterval?: number
|
|
20
|
+
onScan?: (result: string) => void
|
|
21
|
+
onError?: (error: Error) => void
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* 二维码扫描器类
|
|
26
|
-
*
|
|
26
|
+
*
|
|
27
27
|
* 提供实时扫描和识别摄像头中的二维码的功能
|
|
28
|
-
*
|
|
28
|
+
*
|
|
29
29
|
* @example
|
|
30
30
|
* ```typescript
|
|
31
31
|
* // 创建二维码扫描器
|
|
@@ -38,91 +38,130 @@ export interface QRScannerOptions {
|
|
|
38
38
|
* console.error('扫描错误:', error);
|
|
39
39
|
* }
|
|
40
40
|
* });
|
|
41
|
-
*
|
|
41
|
+
*
|
|
42
42
|
* // 启动扫描
|
|
43
43
|
* const videoElement = document.getElementById('video') as HTMLVideoElement;
|
|
44
44
|
* await qrScanner.start(videoElement);
|
|
45
|
-
*
|
|
45
|
+
*
|
|
46
46
|
* // 停止扫描
|
|
47
47
|
* qrScanner.stop();
|
|
48
48
|
* ```
|
|
49
49
|
*/
|
|
50
50
|
export class QRScanner {
|
|
51
|
-
private camera: Camera
|
|
52
|
-
private scanning = false
|
|
53
|
-
private scanTimer: number | null = null
|
|
54
|
-
|
|
51
|
+
private camera: Camera
|
|
52
|
+
private scanning = false
|
|
53
|
+
private scanTimer: number | null = null
|
|
54
|
+
|
|
55
55
|
/**
|
|
56
56
|
* 创建二维码扫描器实例
|
|
57
|
-
*
|
|
57
|
+
*
|
|
58
58
|
* @param {QRScannerOptions} [options] - 扫描器配置选项
|
|
59
59
|
*/
|
|
60
60
|
constructor(private options: QRScannerOptions = {}) {
|
|
61
61
|
this.options = {
|
|
62
62
|
scanInterval: 200,
|
|
63
|
-
...options
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
this.camera = new Camera()
|
|
63
|
+
...options,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.camera = new Camera()
|
|
67
67
|
}
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
/**
|
|
70
70
|
* 启动二维码扫描
|
|
71
|
-
*
|
|
71
|
+
*
|
|
72
72
|
* 初始化相机并开始连续扫描视频帧中的二维码
|
|
73
|
-
*
|
|
73
|
+
*
|
|
74
74
|
* @param {HTMLVideoElement} videoElement - 用于显示相机画面的video元素
|
|
75
75
|
* @returns {Promise<void>} 启动完成的Promise
|
|
76
76
|
* @throws 如果无法访问相机,将通过onError回调报告错误
|
|
77
77
|
*/
|
|
78
78
|
async start(videoElement: HTMLVideoElement): Promise<void> {
|
|
79
79
|
try {
|
|
80
|
-
await this.camera.initialize(videoElement)
|
|
81
|
-
this.scanning = true
|
|
82
|
-
this.scan()
|
|
80
|
+
await this.camera.initialize(videoElement)
|
|
81
|
+
this.scanning = true
|
|
82
|
+
this.scan()
|
|
83
83
|
} catch (error) {
|
|
84
84
|
if (this.options.onError) {
|
|
85
|
-
this.options.onError(
|
|
85
|
+
this.options.onError(
|
|
86
|
+
error instanceof Error ? error : new Error(String(error))
|
|
87
|
+
)
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
|
-
|
|
91
|
+
|
|
90
92
|
/**
|
|
91
93
|
* 执行一次二维码扫描
|
|
92
|
-
*
|
|
94
|
+
*
|
|
93
95
|
* 内部方法,捕获当前视频帧并尝试识别其中的二维码
|
|
94
|
-
*
|
|
96
|
+
*
|
|
95
97
|
* @private
|
|
96
98
|
*/
|
|
97
99
|
private scan(): void {
|
|
98
|
-
if (!this.scanning) return
|
|
99
|
-
|
|
100
|
-
const imageData = this.camera.captureFrame()
|
|
101
|
-
|
|
100
|
+
if (!this.scanning) return
|
|
101
|
+
|
|
102
|
+
const imageData = this.camera.captureFrame()
|
|
103
|
+
|
|
102
104
|
if (imageData) {
|
|
103
|
-
const code = jsQR(imageData.data, imageData.width, imageData.height)
|
|
104
|
-
|
|
105
|
+
const code = jsQR(imageData.data, imageData.width, imageData.height)
|
|
106
|
+
|
|
105
107
|
if (code && this.options.onScan) {
|
|
106
|
-
this.options.onScan(code.data)
|
|
108
|
+
this.options.onScan(code.data)
|
|
107
109
|
}
|
|
108
110
|
}
|
|
109
|
-
|
|
110
|
-
this.scanTimer = window.setTimeout(
|
|
111
|
+
|
|
112
|
+
this.scanTimer = window.setTimeout(
|
|
113
|
+
() => this.scan(),
|
|
114
|
+
this.options.scanInterval
|
|
115
|
+
)
|
|
111
116
|
}
|
|
112
|
-
|
|
117
|
+
|
|
113
118
|
/**
|
|
114
119
|
* 停止二维码扫描
|
|
115
|
-
*
|
|
120
|
+
*
|
|
116
121
|
* 停止扫描循环并释放相机资源
|
|
117
122
|
*/
|
|
118
123
|
stop(): void {
|
|
119
|
-
this.scanning = false
|
|
120
|
-
|
|
124
|
+
this.scanning = false
|
|
125
|
+
|
|
121
126
|
if (this.scanTimer) {
|
|
122
|
-
clearTimeout(this.scanTimer)
|
|
123
|
-
this.scanTimer = null
|
|
127
|
+
clearTimeout(this.scanTimer)
|
|
128
|
+
this.scanTimer = null
|
|
124
129
|
}
|
|
125
|
-
|
|
126
|
-
this.camera.release()
|
|
130
|
+
|
|
131
|
+
this.camera.release()
|
|
127
132
|
}
|
|
128
|
-
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 处理图像数据中的二维码
|
|
136
|
+
*
|
|
137
|
+
* @param {ImageData} imageData - 要处理的图像数据
|
|
138
|
+
* @returns {string | null} 识别到的二维码内容,如未识别到则返回null
|
|
139
|
+
*/
|
|
140
|
+
processImageData(imageData: ImageData): string | null {
|
|
141
|
+
try {
|
|
142
|
+
if (
|
|
143
|
+
!imageData ||
|
|
144
|
+
!imageData.data ||
|
|
145
|
+
imageData.width <= 0 ||
|
|
146
|
+
imageData.height <= 0
|
|
147
|
+
) {
|
|
148
|
+
throw new Error("无效的图像数据")
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const code = jsQR(imageData.data, imageData.width, imageData.height)
|
|
152
|
+
|
|
153
|
+
if (code && code.data) {
|
|
154
|
+
return code.data
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return null
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (this.options.onError) {
|
|
160
|
+
this.options.onError(
|
|
161
|
+
error instanceof Error ? error : new Error(String(error))
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
return null
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|