@gueshbzh-perso/scanner 0.5.1 → 0.7.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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -14
  3. package/dist/camera.d.ts.map +1 -1
  4. package/dist/camera.js +5 -2
  5. package/dist/camera.js.map +1 -1
  6. package/dist/core.d.ts +28 -10
  7. package/dist/core.d.ts.map +1 -1
  8. package/dist/core.js +92 -42
  9. package/dist/core.js.map +1 -1
  10. package/dist/engine.d.ts +26 -3
  11. package/dist/engine.d.ts.map +1 -1
  12. package/dist/engine.js +159 -51
  13. package/dist/engine.js.map +1 -1
  14. package/dist/grabber.d.ts +28 -0
  15. package/dist/grabber.d.ts.map +1 -1
  16. package/dist/grabber.js +81 -3
  17. package/dist/grabber.js.map +1 -1
  18. package/dist/index.d.ts +0 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +0 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/overlay.d.ts.map +1 -1
  23. package/dist/overlay.js +12 -11
  24. package/dist/overlay.js.map +1 -1
  25. package/dist/protocol.d.ts +9 -13
  26. package/dist/protocol.d.ts.map +1 -1
  27. package/dist/reader.d.ts +33 -3
  28. package/dist/reader.d.ts.map +1 -1
  29. package/dist/reader.js +113 -25
  30. package/dist/reader.js.map +1 -1
  31. package/dist/types.d.ts +11 -5
  32. package/dist/types.d.ts.map +1 -1
  33. package/dist/wasm/THIRD_PARTY_LICENSES.md +3879 -0
  34. package/dist/wasm/scanner_wasm.d.ts +52 -0
  35. package/dist/wasm/scanner_wasm.js +87 -0
  36. package/dist/wasm/scanner_wasm_bg.wasm +0 -0
  37. package/dist/wasm/scanner_wasm_bg.wasm.d.ts +6 -0
  38. package/dist/worker.js +15 -17
  39. package/dist/worker.js.map +1 -1
  40. package/package.json +6 -3
  41. package/src/camera.ts +107 -0
  42. package/src/core.ts +189 -0
  43. package/src/engine.ts +348 -0
  44. package/src/feedback.ts +50 -0
  45. package/src/geometry.ts +55 -0
  46. package/src/grabber.ts +385 -0
  47. package/src/index.ts +20 -0
  48. package/src/overlay.ts +225 -0
  49. package/src/protocol.ts +38 -0
  50. package/src/reader.ts +474 -0
  51. package/src/scan-image.ts +88 -0
  52. package/src/types.ts +155 -0
  53. package/src/worker.ts +57 -0
  54. package/dist/wasm/scanner_wasm_simd_bg.wasm +0 -0
package/src/types.ts ADDED
@@ -0,0 +1,155 @@
1
+ import type { BarcodeFormat } from './wasm/scanner_wasm.js';
2
+
3
+ export type { BarcodeFormat };
4
+
5
+ /** A point in pixels. */
6
+ export interface Point {
7
+ x: number;
8
+ y: number;
9
+ }
10
+
11
+ /** A rectangle expressed as fractions (0–1) of a reference box. */
12
+ export interface Region {
13
+ x: number;
14
+ y: number;
15
+ width: number;
16
+ height: number;
17
+ }
18
+
19
+ /** A decoded barcode. */
20
+ export interface Detection {
21
+ /** Decoded text content. */
22
+ text: string;
23
+ /** Symbology, e.g. `"qr_code"`, `"ean_13"`. */
24
+ format: BarcodeFormat;
25
+ /**
26
+ * Location of the code. For camera scans: video pixels (`video.videoWidth`
27
+ * space). For `scanImage`: pixels of the source image.
28
+ */
29
+ points: Point[];
30
+ /** Raw payload bytes when the symbology provides them (binary QR codes…). */
31
+ rawBytes?: Uint8Array;
32
+ /** `Date.now()`-style timestamp of the detection. */
33
+ timestamp: number;
34
+ }
35
+
36
+ /** Options of the decoding engine, shared by the camera reader and `scanImage`. */
37
+ export interface EngineOptions {
38
+ /** Formats to look for. Default: all. Listing only what you need is much faster. */
39
+ formats?: BarcodeFormat[];
40
+ /** Enable CLAHE / binarization fallbacks for hard frames. Default: `true`. */
41
+ preprocessing?: boolean;
42
+ /** Also look for light-on-dark codes. Default: `true`. */
43
+ tryInvert?: boolean;
44
+ /** Maximum codes per frame. `> 1` enables multi-code detection (slower). Default: `1`. */
45
+ maxResults?: number;
46
+ /** Delay before the same content is reported again. Default: `1500` ms. */
47
+ duplicateIntervalMs?: number;
48
+ /**
49
+ * Agreeing reads required before a 1D code is reported. Weak 1D formats
50
+ * (Code 39/93, ITF, Codabar, UPC-E, EAN-8) need one more; 2D codes are
51
+ * reported on the first read. Default: `2`.
52
+ */
53
+ linearConfirmations?: number;
54
+ }
55
+
56
+ /** Where to load the engine from. Only needed when the bundler cannot resolve `import.meta.url`. */
57
+ export interface AssetOptions {
58
+ /** URL of `scanner_wasm_bg.wasm`. Default: next to the SDK. */
59
+ wasmUrl?: string | URL;
60
+ /** URL of the SDK `worker.js`. Default: next to the SDK. */
61
+ workerUrl?: string | URL;
62
+ /** Decode in Web Workers (recommended). Default: `true`; falls back to the main thread if workers are unavailable. */
63
+ worker?: boolean;
64
+ /**
65
+ * Number of decoding Web Workers: frames are decoded in parallel, which
66
+ * multiplies the frame rate on phones with several slow cores. Default:
67
+ * cores − 1, between 1 and 3.
68
+ */
69
+ workers?: number;
70
+ }
71
+
72
+ export type CameraResolution = 'sd' | 'hd' | 'fhd';
73
+
74
+ export interface CameraOptions {
75
+ /** Default: `'environment'` (rear camera). */
76
+ facingMode?: 'environment' | 'user';
77
+ /** Use a specific camera (see `BarcodeReader.listCameras()`). */
78
+ deviceId?: string;
79
+ /** Requested capture resolution. Default: `'hd'` (1280×720). */
80
+ resolution?: CameraResolution;
81
+ /** Remember the last selected camera in `localStorage`. Default: `true`. */
82
+ rememberDevice?: boolean;
83
+ }
84
+
85
+ export interface OverlayOptions {
86
+ /** Dim everything outside the region of interest and draw its corners. Default: `true`. */
87
+ showRegion?: boolean;
88
+ /** Highlight detected codes. Default: `true`. */
89
+ showDetections?: boolean;
90
+ /** Show a flashlight button when the camera supports it. Default: `true`. */
91
+ showTorchButton?: boolean;
92
+ /** Show a camera switch button when several cameras are available. Default: `true`. */
93
+ showCameraSwitch?: boolean;
94
+ /** Accent color. Default: `'#00d4aa'`. */
95
+ color?: string;
96
+ }
97
+
98
+ export interface FeedbackOptions {
99
+ /** Short beep on detection. Default: `true`. */
100
+ beep?: boolean;
101
+ /** Vibrate on detection (when supported). Default: `true`. */
102
+ vibrate?: boolean;
103
+ }
104
+
105
+ export interface ProcessingOptions {
106
+ /**
107
+ * Largest side, in pixels, of the image handed to the decoder. The region
108
+ * of interest is downscaled on the GPU to this size. Default: `1024`.
109
+ */
110
+ maxDimension?: number;
111
+ /** Frame pipeline. `'auto'` uses WebGL2 and falls back to Canvas 2D. Default: `'auto'`. */
112
+ backend?: 'auto' | 'webgl' | 'canvas';
113
+ }
114
+
115
+ export interface ReaderOptions extends EngineOptions, AssetOptions {
116
+ /** Element (or CSS selector) that will host the camera preview. It should have a size. */
117
+ host: HTMLElement | string;
118
+ /**
119
+ * Area of the **visible** preview that is scanned, as fractions of the host
120
+ * element. Smaller = faster. Default: `{ x: 0.1, y: 0.2, width: 0.8, height: 0.6 }`.
121
+ */
122
+ regionOfInterest?: Region;
123
+ camera?: CameraOptions;
124
+ /** UI drawn on top of the preview, or `false` to draw nothing. */
125
+ overlay?: OverlayOptions | false;
126
+ feedback?: FeedbackOptions | false;
127
+ processing?: ProcessingOptions;
128
+ }
129
+
130
+ /** Live statistics of a running reader. */
131
+ export interface ReaderStats {
132
+ /** Frames decoded per second. */
133
+ fps: number;
134
+ /** Average decode time in the engine, in ms. */
135
+ decodeMs: number;
136
+ /** Average GPU/canvas frame preparation time, in ms. */
137
+ grabMs: number;
138
+ /** Size of the image handed to the decoder. */
139
+ frameWidth: number;
140
+ frameHeight: number;
141
+ /** Active frame pipeline. */
142
+ backend: 'webgl' | 'canvas';
143
+ /** `true` when decoding runs in Web Workers. */
144
+ worker: boolean;
145
+ /** Frames decoded in parallel (number of workers, `1` on the main thread). */
146
+ workers: number;
147
+ }
148
+
149
+ export interface ReaderEvents {
150
+ /** New codes (already de-duplicated). */
151
+ detected: Detection[];
152
+ error: Error;
153
+ started: undefined;
154
+ stopped: undefined;
155
+ }
package/src/worker.ts ADDED
@@ -0,0 +1,57 @@
1
+ // Web Worker entry point: decodes frames off the main thread. Stateless: the
2
+ // scan session (scheduling, confirmations, de-duplication) lives on the main
3
+ // thread, so any number of these workers can serve one camera stream.
4
+ import { DecoderCore, loadWasm } from './core.js';
5
+ import type { WorkerRequest, WorkerResponse } from './protocol.js';
6
+
7
+ interface WorkerScope {
8
+ onmessage: ((ev: MessageEvent<WorkerRequest>) => void) | null;
9
+ postMessage(message: WorkerResponse, transfer?: Transferable[]): void;
10
+ }
11
+
12
+ const scope = self as unknown as WorkerScope;
13
+ let core: DecoderCore | null = null;
14
+
15
+ function engine(): DecoderCore {
16
+ if (!core) throw new Error('Engine not initialised');
17
+ return core;
18
+ }
19
+
20
+ scope.onmessage = async (ev) => {
21
+ const msg = ev.data;
22
+ const buffer = 'buffer' in msg ? msg.buffer : undefined;
23
+ try {
24
+ switch (msg.type) {
25
+ case 'init': {
26
+ const version = await loadWasm(msg.module);
27
+ core = new DecoderCore();
28
+ scope.postMessage({ id: msg.id, ok: true, version });
29
+ break;
30
+ }
31
+ case 'configure':
32
+ engine().configure(msg.options);
33
+ scope.postMessage({ id: msg.id, ok: true });
34
+ break;
35
+ case 'decode': {
36
+ const pixels = new Uint8Array(msg.buffer);
37
+ const report = engine().decode(pixels, msg.width, msg.height, msg.format, msg.plan);
38
+ // Hand the pixel buffer back so the main thread can reuse it.
39
+ scope.postMessage({ id: msg.id, ok: true, report, buffer: msg.buffer }, [msg.buffer]);
40
+ break;
41
+ }
42
+ case 'scan': {
43
+ const pixels = new Uint8Array(msg.buffer);
44
+ const results = engine().scan(pixels, msg.width, msg.height, msg.format, msg.options);
45
+ scope.postMessage({ id: msg.id, ok: true, results, buffer: msg.buffer }, [msg.buffer]);
46
+ break;
47
+ }
48
+ }
49
+ } catch (err) {
50
+ const error = err instanceof Error ? err.message : String(err);
51
+ // A WebAssembly trap (Rust panic) leaves the module in an undefined state:
52
+ // report it as fatal so the SDK spawns a fresh worker.
53
+ const fatal = err instanceof WebAssembly.RuntimeError;
54
+ scope.postMessage({ id: msg.id, ok: false, error, fatal, buffer }, buffer ? [buffer] : []);
55
+ if (fatal) core = null;
56
+ }
57
+ };
Binary file