quadqr-js 1.4.2 → 1.5.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/FORMAT.md +5 -5
- package/README.md +19 -8
- package/SPECIFICATION.md +12 -12
- package/dist/camera-scanner-worker.js +793 -0
- package/dist/esm/camera-scanner-worker.js +793 -0
- package/dist/esm/geometry.js +25 -10
- package/dist/esm/quadqr.js +843 -62
- package/dist/esm/vision.js +887 -122
- package/dist/esm/wasm.js +85 -12
- package/dist/quadqr.js +1803 -198
- package/dist/quadqr.min.js +2032 -274
- package/dist/wasm/quadqr-core.wasm +0 -0
- package/docs/API.md +13 -5
- package/docs/BROWSER_CDN.md +5 -5
- package/docs/CLI.md +167 -167
- package/docs/COMPRESSION.md +170 -170
- package/docs/GETTING_STARTED.md +1 -1
- package/docs/HIGH_DENSITY_MODE.md +100 -100
- package/docs/NODE.md +159 -159
- package/docs/README.md +62 -62
- package/docs/RELIABILITY_LAB.md +64 -64
- package/docs/TRIANGLE16.md +98 -98
- package/docs/WASM.md +30 -4
- package/package.json +5 -3
package/docs/TRIANGLE16.md
CHANGED
|
@@ -1,98 +1,98 @@
|
|
|
1
|
-
# Triangle16 internals for High Density Mode
|
|
2
|
-
|
|
3
|
-
Triangle16 is the experimental physical cell layout used internally by QuadQR **High Density Mode**. It keeps the existing QuadQR geometry, finder patterns, timing pattern, alignment patterns, calibration, Spectrum ECC, CRC, security envelope, compression, and signing behavior, but changes how payload data cells are represented.
|
|
4
|
-
|
|
5
|
-
## Physical cell
|
|
6
|
-
|
|
7
|
-
A Triangle16 payload cell is split by one fixed `/` diagonal:
|
|
8
|
-
|
|
9
|
-
```text
|
|
10
|
-
+---------+
|
|
11
|
-
| AAAAAA /|
|
|
12
|
-
| AAAAA /B|
|
|
13
|
-
| AAAA /BB|
|
|
14
|
-
| AAA /BBB|
|
|
15
|
-
| AA /BBBB|
|
|
16
|
-
| A /BBBBB|
|
|
17
|
-
| /BBBBBBB|
|
|
18
|
-
+---------+
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
`A` is the upper-left triangle and `B` is the lower-right triangle. Each triangle independently uses the existing RGBW alphabet:
|
|
22
|
-
|
|
23
|
-
```text
|
|
24
|
-
R = 00
|
|
25
|
-
G = 01
|
|
26
|
-
B = 10
|
|
27
|
-
W = 11
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
The pair therefore has 16 states:
|
|
31
|
-
|
|
32
|
-
```text
|
|
33
|
-
R/R R/G R/B R/W
|
|
34
|
-
G/R G/G G/B G/W
|
|
35
|
-
B/R B/G B/B B/W
|
|
36
|
-
W/R W/G W/B W/W
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
The first triangle carries the high 2 bits and the second triangle carries the low 2 bits. One Triangle16 body cell therefore carries 4 raw bits, so one byte occupies two body cells instead of four RGBW cells.
|
|
40
|
-
|
|
41
|
-
## Protected header stays solid
|
|
42
|
-
|
|
43
|
-
The protected bootstrap/header intentionally does not use mixed-color triangles. Its normal RGBW header cells are represented as same-color pairs such as `R/R`, `G/G`, `B/B`, and `W/W`.
|
|
44
|
-
|
|
45
|
-
This uses four cells per protected header byte, exactly like RGBW, but makes it much easier for the decoder to recover the mode flag when the image is blurred, skewed, resized, or color-shifted. Header flag bit 6 declares Triangle16 for the ECC-protected body.
|
|
46
|
-
|
|
47
|
-
## Scanner sampling
|
|
48
|
-
|
|
49
|
-
The scanner does not sample the diagonal or the exact module center. Each triangle uses three protected interior sample anchors, robust aggregation, and a spatial-stability score. The weaker/less stable region lowers the cell confidence and supplies the first alternate state for Spectrum ECC 2.0 soft recovery.
|
|
50
|
-
|
|
51
|
-
The normal image and camera scanner automatically attempts Triangle16 sampling. No separate scan mode is required. If ordinary finder/alignment geometry is good enough to locate the symbol but not precise enough to decode the half-cell regions, the scanner performs one bounded **precise-alignment recovery** pass. That pass uses denser alignment-pattern probes and a finer sub-module search, then retries the same dual-triangle classifier.
|
|
52
|
-
|
|
53
|
-
## Rendering rules
|
|
54
|
-
|
|
55
|
-
Triangle16 uses exact hard-edged triangular payload cells. Decorative payload styles are intentionally bypassed in this profile because rounded, inset, soft, or depth effects can reduce the usable sampling area or contaminate the diagonal boundary. Structural modules keep the normal QuadQR rendering behavior.
|
|
56
|
-
|
|
57
|
-
PNG/ImageData, Canvas, SVG, browser, and Node rendering all support Triangle16.
|
|
58
|
-
|
|
59
|
-
## API
|
|
60
|
-
|
|
61
|
-
```js
|
|
62
|
-
import { encodeText } from "quadqr-js";
|
|
63
|
-
|
|
64
|
-
const code = encodeText("High-density QuadQR", {
|
|
65
|
-
ecc: "M",
|
|
66
|
-
highDensity: true
|
|
67
|
-
});
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
High Density Mode is disabled by default. `Triangle16` is an internal/technical name for the current experimental physical layout, not a separate public mode selector.
|
|
71
|
-
|
|
72
|
-
## Capacity
|
|
73
|
-
|
|
74
|
-
Raw body density is:
|
|
75
|
-
|
|
76
|
-
```text
|
|
77
|
-
RGBW 4 states 2 bits/body cell
|
|
78
|
-
Triangle16 16 states 4 bits/body cell
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
The protected header remains RGBW-equivalent, and ECC/CRC overhead is unchanged at the byte level, so usable payload capacity is close to but not exactly 2x for a fixed matrix version.
|
|
82
|
-
|
|
83
|
-
Use `getVersionInfo(version, { ecc, highDensity: true })` or the demo capacity calculator for the exact value.
|
|
84
|
-
|
|
85
|
-
## Reliability caveat
|
|
86
|
-
|
|
87
|
-
Triangle16 doubles raw body bits per cell, but it also halves the spatial area available to each independently classified color. Its meaningful real-world metric is not only bits per matrix cell. It is reliable payload bytes at a fixed physical size, camera distance, angle, lighting condition, resize/compression pipeline, and print quality.
|
|
88
|
-
|
|
89
|
-
The branch should therefore be stress-tested before treating Triangle16 as a stable format. Important cases include:
|
|
90
|
-
|
|
91
|
-
- perspective and partial finder degradation;
|
|
92
|
-
- defocus and motion blur;
|
|
93
|
-
- low camera pixel coverage per module;
|
|
94
|
-
- JPEG compression and repeated image resizing;
|
|
95
|
-
- shadows, glare, white-balance shifts, and saturation changes;
|
|
96
|
-
- cheap printing, ink spread, paper tint, and camera recapture.
|
|
97
|
-
|
|
98
|
-
If full 16-state reliability becomes the limiting factor, a restricted triangle alphabet can be explored later without changing the basic physical-cell experiment.
|
|
1
|
+
# Triangle16 internals for High Density Mode
|
|
2
|
+
|
|
3
|
+
Triangle16 is the experimental physical cell layout used internally by QuadQR **High Density Mode**. It keeps the existing QuadQR geometry, finder patterns, timing pattern, alignment patterns, calibration, Spectrum ECC, CRC, security envelope, compression, and signing behavior, but changes how payload data cells are represented.
|
|
4
|
+
|
|
5
|
+
## Physical cell
|
|
6
|
+
|
|
7
|
+
A Triangle16 payload cell is split by one fixed `/` diagonal:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
+---------+
|
|
11
|
+
| AAAAAA /|
|
|
12
|
+
| AAAAA /B|
|
|
13
|
+
| AAAA /BB|
|
|
14
|
+
| AAA /BBB|
|
|
15
|
+
| AA /BBBB|
|
|
16
|
+
| A /BBBBB|
|
|
17
|
+
| /BBBBBBB|
|
|
18
|
+
+---------+
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`A` is the upper-left triangle and `B` is the lower-right triangle. Each triangle independently uses the existing RGBW alphabet:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
R = 00
|
|
25
|
+
G = 01
|
|
26
|
+
B = 10
|
|
27
|
+
W = 11
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The pair therefore has 16 states:
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
R/R R/G R/B R/W
|
|
34
|
+
G/R G/G G/B G/W
|
|
35
|
+
B/R B/G B/B B/W
|
|
36
|
+
W/R W/G W/B W/W
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The first triangle carries the high 2 bits and the second triangle carries the low 2 bits. One Triangle16 body cell therefore carries 4 raw bits, so one byte occupies two body cells instead of four RGBW cells.
|
|
40
|
+
|
|
41
|
+
## Protected header stays solid
|
|
42
|
+
|
|
43
|
+
The protected bootstrap/header intentionally does not use mixed-color triangles. Its normal RGBW header cells are represented as same-color pairs such as `R/R`, `G/G`, `B/B`, and `W/W`.
|
|
44
|
+
|
|
45
|
+
This uses four cells per protected header byte, exactly like RGBW, but makes it much easier for the decoder to recover the mode flag when the image is blurred, skewed, resized, or color-shifted. Header flag bit 6 declares Triangle16 for the ECC-protected body.
|
|
46
|
+
|
|
47
|
+
## Scanner sampling
|
|
48
|
+
|
|
49
|
+
The scanner does not sample the diagonal or the exact module center. Each triangle uses three protected interior sample anchors, robust aggregation, and a spatial-stability score. The weaker/less stable region lowers the cell confidence and supplies the first alternate state for Spectrum ECC 2.0 soft recovery.
|
|
50
|
+
|
|
51
|
+
The normal image and camera scanner automatically attempts Triangle16 sampling. No separate scan mode is required. If ordinary finder/alignment geometry is good enough to locate the symbol but not precise enough to decode the half-cell regions, the scanner performs one bounded **precise-alignment recovery** pass. That pass uses denser alignment-pattern probes and a finer sub-module search, then retries the same dual-triangle classifier.
|
|
52
|
+
|
|
53
|
+
## Rendering rules
|
|
54
|
+
|
|
55
|
+
Triangle16 uses exact hard-edged triangular payload cells. Decorative payload styles are intentionally bypassed in this profile because rounded, inset, soft, or depth effects can reduce the usable sampling area or contaminate the diagonal boundary. Structural modules keep the normal QuadQR rendering behavior.
|
|
56
|
+
|
|
57
|
+
PNG/ImageData, Canvas, SVG, browser, and Node rendering all support Triangle16.
|
|
58
|
+
|
|
59
|
+
## API
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
import { encodeText } from "quadqr-js";
|
|
63
|
+
|
|
64
|
+
const code = encodeText("High-density QuadQR", {
|
|
65
|
+
ecc: "M",
|
|
66
|
+
highDensity: true
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
High Density Mode is disabled by default. `Triangle16` is an internal/technical name for the current experimental physical layout, not a separate public mode selector.
|
|
71
|
+
|
|
72
|
+
## Capacity
|
|
73
|
+
|
|
74
|
+
Raw body density is:
|
|
75
|
+
|
|
76
|
+
```text
|
|
77
|
+
RGBW 4 states 2 bits/body cell
|
|
78
|
+
Triangle16 16 states 4 bits/body cell
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The protected header remains RGBW-equivalent, and ECC/CRC overhead is unchanged at the byte level, so usable payload capacity is close to but not exactly 2x for a fixed matrix version.
|
|
82
|
+
|
|
83
|
+
Use `getVersionInfo(version, { ecc, highDensity: true })` or the demo capacity calculator for the exact value.
|
|
84
|
+
|
|
85
|
+
## Reliability caveat
|
|
86
|
+
|
|
87
|
+
Triangle16 doubles raw body bits per cell, but it also halves the spatial area available to each independently classified color. Its meaningful real-world metric is not only bits per matrix cell. It is reliable payload bytes at a fixed physical size, camera distance, angle, lighting condition, resize/compression pipeline, and print quality.
|
|
88
|
+
|
|
89
|
+
The branch should therefore be stress-tested before treating Triangle16 as a stable format. Important cases include:
|
|
90
|
+
|
|
91
|
+
- perspective and partial finder degradation;
|
|
92
|
+
- defocus and motion blur;
|
|
93
|
+
- low camera pixel coverage per module;
|
|
94
|
+
- JPEG compression and repeated image resizing;
|
|
95
|
+
- shadows, glare, white-balance shifts, and saturation changes;
|
|
96
|
+
- cheap printing, ink spread, paper tint, and camera recapture.
|
|
97
|
+
|
|
98
|
+
If full 16-state reliability becomes the limiting factor, a restricted triangle alphabet can be explored later without changing the basic physical-cell experiment.
|
package/docs/WASM.md
CHANGED
|
@@ -14,10 +14,11 @@ The normal JavaScript implementation works without WASM. Applications can opt in
|
|
|
14
14
|
import { initWasm } from "quadqr-js";
|
|
15
15
|
|
|
16
16
|
const state = await initWasm();
|
|
17
|
-
console.log(state);
|
|
17
|
+
console.log(state.accelerators);
|
|
18
|
+
// ["crc32", "scanner-preprocess"]
|
|
18
19
|
```
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
The bundled WASM module accelerates both CRC-32 and scanner preprocessing. Scanner acceleration covers the hot full-frame RGBA → grayscale conversion, Otsu threshold calculation, and binary finder image generation used by `scanImageData()` and camera scanning. **Finder-pattern detection, geometry estimation, perspective solving, color classification, and recovery orchestration remain JavaScript.** Once initialized, the existing synchronous scanner API automatically uses the accelerator with the JavaScript implementation kept as the fallback.
|
|
21
22
|
|
|
22
23
|
## Check the current state
|
|
23
24
|
|
|
@@ -56,12 +57,37 @@ You can also provide WASM bytes directly through the `bytes` option.
|
|
|
56
57
|
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
|
|
|
58
59
|
```html
|
|
59
|
-
<script src="https://cdn.jsdelivr.net/npm/quadqr-js@1.
|
|
60
|
+
<script src="https://cdn.jsdelivr.net/npm/quadqr-js@1.5.1/dist/quadqr.min.js"></script>
|
|
60
61
|
<script>
|
|
61
62
|
await QuadQR.initWasm();
|
|
62
63
|
</script>
|
|
63
64
|
```
|
|
64
65
|
|
|
66
|
+
## Building WASM from source
|
|
67
|
+
|
|
68
|
+
QuadQR keeps the generated WASM binary and its verification metadata in the repository:
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
wasm/quadqr-core.wasm
|
|
72
|
+
wasm/quadqr-core.build.json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
For normal development, run:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm run build
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The build hashes the C source, the WASM compiler flags, and the checked-in binary. If all hashes match, it reuses the verified prebuilt binary. If `wasm-src/quadqr_core.c` or the compiler flags changed, the normal build automatically recompiles WASM. A stale WASM build is never silently accepted: if recompilation is required and `clang` is not available in `PATH`, `npm run build` fails with instructions to install LLVM/Clang.
|
|
82
|
+
|
|
83
|
+
To explicitly rebuild just the WASM accelerator:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm run build:wasm
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`npm run build:wasm` always recompiles and therefore always requires LLVM/Clang. Rust, Cargo, and Emscripten are not required by the current WASM build. `npm publish` runs the normal build through `prepublishOnly`, so the same stale-WASM protection applies before publishing.
|
|
90
|
+
|
|
65
91
|
## Fallback behavior
|
|
66
92
|
|
|
67
|
-
WASM is never required for the QuadQR wire format. If
|
|
93
|
+
WASM is never required for the QuadQR wire format or scanner correctness. If WebAssembly cannot load, keep using the JavaScript scanner. For performance-sensitive browser scanning, initialize WASM once during application startup before calling `scanImageData()` repeatedly or starting the camera scanner.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quadqr-js",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"description": "QuadQR: experimental RGBW matrix code with optional experimental High Density Mode, Spectrum ECC 2.0, multi-frame camera scanning, advanced calibration, Reliability Lab, and 3D perspective recovery.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -50,11 +50,13 @@
|
|
|
50
50
|
"start": "node scripts/serve.js",
|
|
51
51
|
"demo": "node scripts/serve.js",
|
|
52
52
|
"docs": "node scripts/serve.js --docs",
|
|
53
|
-
"test": "node tests/self-test.js && node tests/package-test.js",
|
|
53
|
+
"test": "node tests/self-test.js && node tests/package-test.js && node tests/camera-worker-test.js && node tests/camera-scheduler-test.js",
|
|
54
54
|
"benchmark": "node scripts/benchmark.js",
|
|
55
55
|
"pack:check": "npm run build && npm pack --dry-run",
|
|
56
56
|
"prepublishOnly": "npm run build && npm test",
|
|
57
|
-
"test:demo": "node tests/demo-worker-test.js"
|
|
57
|
+
"test:demo": "node tests/demo-worker-test.js",
|
|
58
|
+
"build:wasm": "node scripts/build-wasm.js",
|
|
59
|
+
"test:camera": "node tests/camera-worker-test.js && node tests/camera-scheduler-test.js"
|
|
58
60
|
},
|
|
59
61
|
"engines": {
|
|
60
62
|
"node": ">=20.19"
|