quadqr-js 1.0.1 → 1.0.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/docs/WASM.md CHANGED
@@ -1,67 +1,67 @@
1
- # WebAssembly
2
-
3
- QuadQR includes an optional prebuilt WebAssembly module at:
4
-
5
- ```text
6
- dist/wasm/quadqr-core.wasm
7
- ```
8
-
9
- The normal JavaScript implementation works without WASM. Applications can opt in when they want to use the bundled accelerator.
10
-
11
- ## Enable WASM
12
-
13
- ```js
14
- import { initWasm } from "quadqr-js";
15
-
16
- const state = await initWasm();
17
- console.log(state);
18
- ```
19
-
20
- In QuadQR 0.7.x, the WASM module accelerates CRC-32. Once initialized, normal encode/decode operations automatically use the installed accelerator.
21
-
22
- ## Check the current state
23
-
24
- ```js
25
- import { getWasmState } from "quadqr-js";
26
-
27
- console.log(getWasmState());
28
- ```
29
-
30
- Before initialization, or after disabling WASM, the result is `null`.
31
-
32
- ## Disable WASM
33
-
34
- ```js
35
- import { disableWasm } from "quadqr-js";
36
-
37
- disableWasm();
38
- ```
39
-
40
- QuadQR immediately returns to the JavaScript implementation.
41
-
42
- ## Custom WASM URL
43
-
44
- Browser and CDN applications can override the asset location:
45
-
46
- ```js
47
- await initWasm({
48
- url: "https://example.com/assets/quadqr-core.wasm"
49
- });
50
- ```
51
-
52
- You can also provide WASM bytes directly through the `bytes` option.
53
-
54
- ## CDN behavior
55
-
56
- When the classic `quadqr.min.js` global build is loaded from a CDN, `QuadQR.initWasm()` resolves the bundled sibling WASM asset from the same package/version location.
57
-
58
- ```html
59
- <script src="https://cdn.jsdelivr.net/npm/quadqr-js@1.0.1/dist/quadqr.min.js"></script>
60
- <script>
61
- await QuadQR.initWasm();
62
- </script>
63
- ```
64
-
65
- ## Fallback behavior
66
-
67
- WASM is never required for the QuadQR wire format. If your environment cannot load WebAssembly, simply do not call `initWasm()` and continue using the JavaScript implementation.
1
+ # WebAssembly
2
+
3
+ QuadQR includes an optional prebuilt WebAssembly module at:
4
+
5
+ ```text
6
+ dist/wasm/quadqr-core.wasm
7
+ ```
8
+
9
+ The normal JavaScript implementation works without WASM. Applications can opt in when they want to use the bundled accelerator.
10
+
11
+ ## Enable WASM
12
+
13
+ ```js
14
+ import { initWasm } from "quadqr-js";
15
+
16
+ const state = await initWasm();
17
+ console.log(state);
18
+ ```
19
+
20
+ In QuadQR 0.7.x, the WASM module accelerates CRC-32. Once initialized, normal encode/decode operations automatically use the installed accelerator.
21
+
22
+ ## Check the current state
23
+
24
+ ```js
25
+ import { getWasmState } from "quadqr-js";
26
+
27
+ console.log(getWasmState());
28
+ ```
29
+
30
+ Before initialization, or after disabling WASM, the result is `null`.
31
+
32
+ ## Disable WASM
33
+
34
+ ```js
35
+ import { disableWasm } from "quadqr-js";
36
+
37
+ disableWasm();
38
+ ```
39
+
40
+ QuadQR immediately returns to the JavaScript implementation.
41
+
42
+ ## Custom WASM URL
43
+
44
+ Browser and CDN applications can override the asset location:
45
+
46
+ ```js
47
+ await initWasm({
48
+ url: "https://example.com/assets/quadqr-core.wasm"
49
+ });
50
+ ```
51
+
52
+ You can also provide WASM bytes directly through the `bytes` option.
53
+
54
+ ## CDN behavior
55
+
56
+ When the classic `quadqr.min.js` global build is loaded from a CDN, `QuadQR.initWasm()` resolves the bundled sibling WASM asset from the same package/version location.
57
+
58
+ ```html
59
+ <script src="https://cdn.jsdelivr.net/npm/quadqr-js@1.0.1/dist/quadqr.min.js"></script>
60
+ <script>
61
+ await QuadQR.initWasm();
62
+ </script>
63
+ ```
64
+
65
+ ## Fallback behavior
66
+
67
+ WASM is never required for the QuadQR wire format. If your environment cannot load WebAssembly, simply do not call `initWasm()` and continue using the JavaScript implementation.
package/package.json CHANGED
@@ -1,95 +1,95 @@
1
- {
2
- "name": "quadqr-js",
3
- "version": "1.0.1",
4
- "description": "QuadQR: experimental four-state RGBW matrix code with Spectrum ECC, browser/Node scanning, CDN builds, and optional AES-256-GCM secure payloads.",
5
- "type": "module",
6
- "main": "./dist/index.cjs",
7
- "module": "./dist/index.js",
8
- "browser": "./dist/browser.js",
9
- "types": "./types/index.d.ts",
10
- "unpkg": "./dist/quadqr.min.js",
11
- "jsdelivr": "./dist/quadqr.min.js",
12
- "exports": {
13
- ".": {
14
- "types": "./types/index.d.ts",
15
- "import": "./dist/index.js",
16
- "require": "./dist/index.cjs",
17
- "default": "./dist/index.js"
18
- },
19
- "./browser": {
20
- "types": "./types/index.d.ts",
21
- "import": "./dist/browser.js",
22
- "default": "./dist/browser.js"
23
- },
24
- "./node": {
25
- "types": "./types/node.d.ts",
26
- "import": "./dist/node.js",
27
- "require": "./dist/node.cjs",
28
- "default": "./dist/node.js"
29
- },
30
- "./benchmark": {
31
- "types": "./types/benchmark.d.ts",
32
- "import": "./dist/benchmark.js",
33
- "require": "./dist/benchmark.cjs",
34
- "default": "./dist/benchmark.js"
35
- },
36
- "./quadqr.js": "./dist/quadqr.js",
37
- "./quadqr.min.js": "./dist/quadqr.min.js",
38
- "./wasm/quadqr-core.wasm": "./dist/wasm/quadqr-core.wasm",
39
- "./package.json": "./package.json"
40
- },
41
- "files": [
42
- "dist",
43
- "types",
44
- "bin",
45
- "docs",
46
- "FORMAT.md",
47
- "README.md",
48
- "LICENSE"
49
- ],
50
- "bin": {
51
- "quadqr": "./bin/quadqr.js"
52
- },
53
- "scripts": {
54
- "build": "node scripts/build.js",
55
- "start": "node scripts/serve.js",
56
- "demo": "node scripts/serve.js",
57
- "docs": "node scripts/serve.js --docs",
58
- "test": "node tests/self-test.js && node tests/package-test.js",
59
- "benchmark": "node scripts/benchmark.js",
60
- "pack:check": "npm run build && npm pack --dry-run",
61
- "prepublishOnly": "npm run build && npm test"
62
- },
63
- "engines": {
64
- "node": ">=20.19"
65
- },
66
- "publishConfig": {
67
- "access": "public"
68
- },
69
- "repository": {
70
- "type": "git",
71
- "url": "git+https://github.com/akanshsirohi/QuadQR.git"
72
- },
73
- "bugs": {
74
- "url": "https://github.com/akanshsirohi/QuadQR/issues"
75
- },
76
- "homepage": "https://github.com/akanshsirohi/QuadQR#readme",
77
- "author": "Akansh Sirohi",
78
- "license": "AGPL-3.0-only",
79
- "keywords": [
80
- "quadqr",
81
- "qr",
82
- "rgb",
83
- "rgbw",
84
- "matrix-code",
85
- "barcode",
86
- "reed-solomon",
87
- "ecc",
88
- "scanner",
89
- "camera-scanner",
90
- "encryption",
91
- "aes-gcm",
92
- "wasm"
93
- ],
94
- "sideEffects": false
95
- }
1
+ {
2
+ "name": "quadqr-js",
3
+ "version": "1.0.2",
4
+ "description": "QuadQR: experimental four-state RGBW matrix code with Spectrum ECC, browser/Node scanning, CDN builds, and optional AES-256-GCM secure payloads.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "browser": "./dist/browser.js",
9
+ "types": "./types/index.d.ts",
10
+ "unpkg": "./dist/quadqr.min.js",
11
+ "jsdelivr": "./dist/quadqr.min.js",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./types/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "require": "./dist/index.cjs",
17
+ "default": "./dist/index.js"
18
+ },
19
+ "./browser": {
20
+ "types": "./types/index.d.ts",
21
+ "import": "./dist/browser.js",
22
+ "default": "./dist/browser.js"
23
+ },
24
+ "./node": {
25
+ "types": "./types/node.d.ts",
26
+ "import": "./dist/node.js",
27
+ "require": "./dist/node.cjs",
28
+ "default": "./dist/node.js"
29
+ },
30
+ "./benchmark": {
31
+ "types": "./types/benchmark.d.ts",
32
+ "import": "./dist/benchmark.js",
33
+ "require": "./dist/benchmark.cjs",
34
+ "default": "./dist/benchmark.js"
35
+ },
36
+ "./quadqr.js": "./dist/quadqr.js",
37
+ "./quadqr.min.js": "./dist/quadqr.min.js",
38
+ "./wasm/quadqr-core.wasm": "./dist/wasm/quadqr-core.wasm",
39
+ "./package.json": "./package.json"
40
+ },
41
+ "files": [
42
+ "dist",
43
+ "types",
44
+ "bin",
45
+ "docs",
46
+ "FORMAT.md",
47
+ "README.md",
48
+ "LICENSE"
49
+ ],
50
+ "bin": {
51
+ "quadqr": "./bin/quadqr.js"
52
+ },
53
+ "scripts": {
54
+ "build": "node scripts/build.js",
55
+ "start": "node scripts/serve.js",
56
+ "demo": "node scripts/serve.js",
57
+ "docs": "node scripts/serve.js --docs",
58
+ "test": "node tests/self-test.js && node tests/package-test.js",
59
+ "benchmark": "node scripts/benchmark.js",
60
+ "pack:check": "npm run build && npm pack --dry-run",
61
+ "prepublishOnly": "npm run build && npm test"
62
+ },
63
+ "engines": {
64
+ "node": ">=20.19"
65
+ },
66
+ "publishConfig": {
67
+ "access": "public"
68
+ },
69
+ "repository": {
70
+ "type": "git",
71
+ "url": "git+https://github.com/akanshsirohi/QuadQR.git"
72
+ },
73
+ "bugs": {
74
+ "url": "https://github.com/akanshsirohi/QuadQR/issues"
75
+ },
76
+ "homepage": "https://github.com/akanshsirohi/QuadQR#readme",
77
+ "author": "Akansh Sirohi",
78
+ "license": "AGPL-3.0-only",
79
+ "keywords": [
80
+ "quadqr",
81
+ "qr",
82
+ "rgb",
83
+ "rgbw",
84
+ "matrix-code",
85
+ "barcode",
86
+ "reed-solomon",
87
+ "ecc",
88
+ "scanner",
89
+ "camera-scanner",
90
+ "encryption",
91
+ "aes-gcm",
92
+ "wasm"
93
+ ],
94
+ "sideEffects": false
95
+ }
package/types/index.d.ts CHANGED
@@ -82,6 +82,51 @@ export interface ImageDataLike {
82
82
  data: Uint8ClampedArray | Uint8Array;
83
83
  }
84
84
 
85
+ export interface CameraFinderDiagnostic {
86
+ x: number;
87
+ y: number;
88
+ moduleSize: number;
89
+ confirmations?: number;
90
+ score?: number;
91
+ }
92
+
93
+ export interface CameraGeometryDiagnostic {
94
+ version: number;
95
+ size: number;
96
+ score: number;
97
+ estimatedSize?: number;
98
+ alignmentScore?: number;
99
+ alignmentGridScore?: number;
100
+ finders?: {
101
+ topLeft: CameraFinderDiagnostic;
102
+ topRight: CameraFinderDiagnostic;
103
+ bottomLeft: CameraFinderDiagnostic;
104
+ };
105
+ [key: string]: unknown;
106
+ }
107
+
108
+ export interface CameraDiagnosticEvent {
109
+ type: "camera-ready" | "frame" | "method" | "success" | string;
110
+ timestamp: number;
111
+ frame: number;
112
+ state?: "trying" | "miss" | "failed" | "decoded" | string;
113
+ method?: string;
114
+ message?: string;
115
+ elapsedMs?: number;
116
+ missStreak?: number;
117
+ scanWidth?: number;
118
+ scanHeight?: number;
119
+ frameWidth?: number;
120
+ frameHeight?: number;
121
+ scanRect?: { x: number; y: number; width: number; height: number };
122
+ finderCount?: number;
123
+ finders?: CameraFinderDiagnostic[];
124
+ finderMethod?: string | null;
125
+ finderPasses?: Array<{ method: string; finderCount: number; threshold?: number; geometryCount?: number }>;
126
+ geometry?: CameraGeometryDiagnostic | null;
127
+ [key: string]: unknown;
128
+ }
129
+
85
130
  export interface RenderOptions {
86
131
  moduleSize?: number;
87
132
  quietZone?: number;
@@ -95,9 +140,86 @@ export interface ScanOptions {
95
140
  maxVersion?: number;
96
141
  perspective?: boolean;
97
142
  axisAlignedFallback?: boolean;
143
+ maxDimension?: number;
144
+ sampleRadius?: number;
145
+ robustSampleRadius?: number;
146
+ adaptiveSampling?: boolean;
147
+ spatialColorNormalization?: boolean;
148
+ structureTolerance?: number;
149
+ maxErasureConfidence?: number;
150
+ geometryRefinement?: boolean;
151
+ finderRecovery?: boolean;
152
+ finderAutoColorBlackClip?: number;
153
+ finderAutoColorWhiteClip?: number;
154
+ finderAutoColorHighlightPercentile?: number;
155
+ finderAutoColorOutputHighlight?: number;
156
+ finderAutoColorAnalysisInset?: number;
157
+ finderAutoColorAnalysisInsets?: number[];
158
+ finderAutoColorMinimumInputRange?: number;
159
+ finderAutoColorTargetSamples?: number;
160
+ autoEnhanceRecovery?: boolean;
161
+ autoEnhanceWhenNoGeometry?: boolean;
162
+ autoEnhanceBlackClip?: number;
163
+ autoEnhanceWhiteClip?: number;
164
+ autoEnhanceSaturation?: number;
165
+ autoEnhanceTargetSamples?: number;
166
+ fullFrameAutoEnhanceRecovery?: boolean;
167
+ rectifiedAutoEnhanceRecovery?: boolean;
168
+ rectifiedRecoveryModuleSize?: number;
169
+ rectifiedRecoveryRadiusRatio?: number;
170
+ rectifiedAutoEnhanceBlackClip?: number;
171
+ rectifiedAutoEnhanceWhiteClip?: number;
172
+ rectifiedAutoEnhanceSaturation?: number;
173
+ rectifiedAutoEnhanceHighlightFraction?: number;
174
+ videoCropMode?: "visible" | "full";
175
+ videoObjectFit?: string;
176
+ videoObjectPosition?: string;
177
+ videoCropInset?: number;
178
+ refinementOffset?: number;
179
+ refinementStructureThreshold?: number;
180
+ refinementDecodeThreshold?: number;
181
+ refinementDecodeCandidates?: number;
98
182
  [key: string]: unknown;
99
183
  }
100
184
 
185
+ export interface CameraFrameMeta {
186
+ frame: number;
187
+ imageData: ImageDataLike;
188
+ scanWidth: number;
189
+ scanHeight: number;
190
+ sourceRect?: { x: number; y: number; width: number; height: number; cropped?: boolean } | null;
191
+ enhancedImageData?: ImageDataLike | null;
192
+ enhancedRect?: { x: number; y: number; width: number; height: number } | null;
193
+ enhancement?: { method?: string; cropInset?: number; analysisInset?: number; [key: string]: unknown } | null;
194
+ diagnostic?: Record<string, unknown> | null;
195
+ }
196
+
197
+ export interface CameraScanOptions extends ScanOptions {
198
+ scanInterval?: number;
199
+ stopOnResult?: boolean;
200
+ multiFrame?: boolean;
201
+ multiFrameWindow?: number;
202
+ multiFrameMinFrames?: number;
203
+ cameraAutoColorRecovery?: boolean;
204
+ cameraAutoColorEvery?: number;
205
+ cameraAutoColorBlackClip?: number;
206
+ cameraAutoColorWhiteClip?: number;
207
+ cameraAutoColorHighlightPercentile?: number;
208
+ cameraAutoColorOutputHighlight?: number;
209
+ cameraAutoColorAnalysisInset?: number;
210
+ cameraAutoColorAnalysisInsets?: number[];
211
+ cameraAutoColorCropInsets?: number[];
212
+ cameraAutoColorMinimumInputRange?: number;
213
+ cameraAutoColorTargetSamples?: number;
214
+ cameraAutoEnhanceEvery?: number;
215
+ cameraFinderRecoveryEvery?: number;
216
+ constraints?: MediaStreamConstraints;
217
+ onResult?: (result: DecodeResult, frame?: CameraFrameMeta | null) => void | Promise<void>;
218
+ onDecode?: (result: DecodeResult, frame?: CameraFrameMeta | null) => void | Promise<void>;
219
+ onScanMiss?: (error: Error) => void;
220
+ onDiagnostic?: (event: CameraDiagnosticEvent) => void;
221
+ }
222
+
101
223
  export const FORMAT_VERSION: number;
102
224
  export const MIN_VERSION: number;
103
225
  export const MAX_VERSION: number;
@@ -122,7 +244,7 @@ export function renderToImageData(codeOrMatrix: QuadQRCode | number[][], options
122
244
  export function scanImageData(imageData: ImageDataLike, options?: ScanOptions): DecodeResult;
123
245
  export function scanFile(file: Blob, options?: ScanOptions): Promise<DecodeResult>;
124
246
  export function scanVideoFrame(video: HTMLVideoElement, options?: ScanOptions): DecodeResult;
125
- export function startCameraScanner(video: HTMLVideoElement, options?: ScanOptions & { onDecode?: (result: DecodeResult) => void | Promise<void>; onError?: (error: Error) => void; scanInterval?: number; constraints?: MediaStreamConstraints }): Promise<{ stop(): void; scanNow(): DecodeResult; stream: MediaStream }>;
247
+ export function startCameraScanner(video: HTMLVideoElement, options?: CameraScanOptions): Promise<{ stop(): void; scanNow(): DecodeResult; stream: MediaStream; video: HTMLVideoElement }>;
126
248
  export function rectifyDetectedCode(imageData: ImageDataLike, options?: Record<string, unknown>): ImageDataLike;
127
249
  export function rotateMatrix(matrix: number[][], quarterTurns?: number): number[][];
128
250
  export function getVersionInfo(version: number, options?: { ecc?: EccLevel }): Record<string, unknown>;