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 CHANGED
@@ -1,4 +1,4 @@
1
- # QuadQR Format v5
1
+ # QuadQR Format v6
2
2
 
3
3
  ## Status
4
4
 
@@ -50,7 +50,7 @@ Three 7×7 black/white finder structures are placed at top-left, top-right, and
50
50
 
51
51
  ## Alignment patterns
52
52
 
53
- QuadQR always keeps exactly three primary 7×7 finder patterns. Larger versions do **not** add more primary finders. Instead, versions 2 through 40 use distributed black/white alignment markers following the same center-position schedule used by standard QR Code versions. Exactly one bottom-right **primary alignment marker remains 5×5**. Every additional distributed alignment marker is **3×3**, encoded as a black outer ring with a white center.
53
+ QuadQR always keeps exactly three primary 7×7 finder patterns. Larger versions do **not** add more primary finders. Instead, versions 2 through 40 use distributed black/white alignment markers following the same center-position schedule used by standard QR Code versions. **Format v6 uses a full 5×5 nested black/white/black alignment eye at every scheduled alignment position**, matching the strong structural signature used by proven QR detectors.
54
54
 
55
55
  The three alignment positions that would overlap the primary finder corners are omitted. This produces progressively more alignment references as the matrix grows. Examples:
56
56
 
@@ -64,7 +64,7 @@ v40 -> 46 alignment patterns
64
64
 
65
65
  Version 1 is a QuadQR-specific exception. Standard QR v1 has no alignment pattern, but QuadQR keeps one legacy 5×5 bottom-right bootstrap alignment marker with a one-cell white separator so the camera scanner still has a fourth projective reference point.
66
66
 
67
- For versions 2 through 40, the scanner uses the 5×5 bottom-right member of the distributed alignment grid as the primary fourth homography reference and then scores the full expected grid, including the 3×3 secondary markers, to strengthen version/geometry validation.
67
+ For versions 2 through 40, the scanner uses the bottom-right 5×5 member of the distributed alignment grid as the primary fourth homography reference, then scores and refines against the full 5×5 alignment grid. A fast nested-eye locator is attempted before broader template recovery so perspective geometry can be established as soon as the three primary finder eyes are visible.
68
68
 
69
69
  ## Timing structures
70
70
 
@@ -411,7 +411,7 @@ Matrix decoding tries 0°, 90°, 180°, and 270° rotations.
411
411
 
412
412
  ## Compatibility
413
413
 
414
- Format v5 is intentionally incompatible with standard QR scanners and with the project's older ternary prototypes. The current encoder writes codeword cells using spectral-spatial placement. The current decoder also tries the pre-interleaver physical order as a compatibility fallback for older RGBW QuadQR matrices. Version 5 keeps the distributed alignment-center schedule introduced in v4, but shrinks every non-primary alignment marker from 5×5 to 3×3 while retaining the bottom-right primary marker at 5×5. Because reserved-cell geometry changed, v4 and v5 large-symbol matrices are not wire-compatible.
414
+ Format v6 is intentionally incompatible with standard QR scanners and with the project's older ternary prototypes. The current encoder writes codeword cells using spectral-spatial placement and uses 5×5 nested alignment eyes at every scheduled alignment position. Format v5 used compact 3×3 secondary alignment markers while retaining the bottom-right primary marker at 5×5. The current decoder keeps a legacy Format v5 alignment-profile fallback, so existing v5 RGBW QuadQR symbols remain readable. The decoder also retains the pre-interleaver physical-order fallback for older RGBW matrices.
415
415
 
416
416
  ## Rendering profiles are not part of the wire format
417
417
 
@@ -419,7 +419,7 @@ The canonical QuadQR matrix is independent of presentation style. Renderers may
419
419
 
420
420
  ## Compression and signature flags
421
421
 
422
- Format v5 keeps the physical matrix and ECC framing unchanged while reserving two protected-header flags for optional internal payload metadata:
422
+ Format v6 keeps the physical matrix and ECC framing unchanged while reserving two protected-header flags for optional internal payload metadata:
423
423
 
424
424
  ```text
425
425
  bit 4 = internal payload-extension metadata present
package/README.md CHANGED
@@ -440,7 +440,7 @@ QuadQR currently uses:
440
440
  - square modules;
441
441
  - three 7×7 black-and-white finder patterns;
442
442
  - black-and-white timing structures;
443
- - one 5×5 primary alignment reference plus compact 3×3 secondary alignment markers on larger symbols;
443
+ - distributed 5×5 nested alignment eyes on versions that use alignment patterns;
444
444
  - RGB calibration swatches;
445
445
  - structural black/white references;
446
446
  - a two-column zig-zag physical data-position path;
@@ -453,7 +453,7 @@ QuadQR currently uses:
453
453
 
454
454
  White is a valid data state.
455
455
 
456
- QuadQR still uses exactly three large finder patterns, just like standard QR. Starting at version 2, alignment markers follow the standard QR version-dependent center schedule. The bottom-right alignment reference remains a full 5×5 marker and is used as the fourth homography reference; additional distributed markers are compact 3×3 black rings with white centers. Version 1 keeps one QuadQR-specific 5×5 bottom-right bootstrap marker because it otherwise would have no fourth projective reference.
456
+ QuadQR still uses exactly three large finder patterns, just like standard QR. Starting at version 2, Format v6 alignment markers follow the standard QR version-dependent center schedule and every scheduled alignment marker is a full 5×5 nested black/white/black eye. These distributed references give the detector stronger anchors for high-version and projectively distorted symbols. Version 1 keeps one QuadQR-specific 5×5 bottom-right bootstrap marker because it otherwise would have no fourth projective reference. The decoder retains the compact 3×3 secondary-marker profile used by Format v5 so existing v5 symbols remain readable.
457
457
 
458
458
  The decoder does not treat a white-looking area as automatically empty. It reconstructs the matrix geometry first and then determines whether a sampled position is structural or data.
459
459
 
@@ -481,7 +481,7 @@ White → (255, 255, 255)
481
481
 
482
482
  Real camera input is not expected to match those exact values.
483
483
 
484
- QuadQR includes calibration and nearest-color classification so the scanner can work with observed colors after lighting, camera processing, perspective changes, and other image transformations. The clean-frame path stays fast: QuadQR tries the normal detected geometry and observed palette first. Dense versions can refine an imperfect four-point homography with reliable secondary alignment markers already present in the matrix, without reserving any new cells. If a steep angle leaves exactly two strong finder patterns, a bounded looser third-finder pass runs before heavier color recovery. Only after geometry/color decoding still fails does QuadQR progressively try stronger recovery, including white balancing, a 3×4 affine color-calibration model learned from the known black/white/R/G/B references, spatial normalization, Auto Tone / Auto Contrast / QuadQR Auto Color-style enhancement, and bounded sub-module geometry refinement. For live video, QuadQR scans the CSS-visible `object-fit: cover` camera region instead of the hidden full sensor frame, so the code keeps the same apparent size/resolution the user sees in the guide. When a dense frame already exposes at least two finders, the camera scanner can also retry the visible ROI at up to 1600 px before expensive color recovery. If finder geometry is already strong but color decoding fails, a QR-only rectified pixel enhancement retry is performed immediately; whole-frame enhancement remains reserved for harder locator failures.
484
+ QuadQR includes calibration and nearest-color classification so the scanner can work with observed colors after lighting, camera processing, perspective changes, and other image transformations. The clean-frame path starts with a streaming 1:1:3:1:1 finder detector on the RGB value channel, direct cross-checks, local-threshold fallback, and directional module-size/version estimation. Once the three finder eyes form a valid geometry, QuadQR immediately tries the highest-ranked perspective candidate instead of waiting for every lower-ranked geometry. Near-front-facing symbols can use a three-finder affine fast path, while projectively distorted symbols continue through the full homography/alignment solver. Format v6 distributed 5×5 alignment eyes provide stronger local perspective anchors, and a cheap nested-eye locator is tried before the broader alignment search. If a steep angle leaves exactly two strong finder patterns, the bounded looser third-finder pass still runs before heavier color recovery. Only after geometry/color decoding still fails does QuadQR progressively try the existing stronger recovery, including white balancing, a 3×4 affine color-calibration model learned from the known black/white/R/G/B references, spatial normalization, Auto Tone / Auto Contrast / QuadQR Auto Color-style enhancement, soft-decision ECC, and bounded sub-module geometry refinement. For live video, normal detection works from the CSS-visible `object-fit: cover` camera region at a 640 px working dimension. A bounded 960 px retry is reserved for difficult dense frames that already show useful finder evidence, rather than being part of the ordinary camera loop. If finder geometry is already strong but color decoding fails, a QR-only rectified pixel enhancement retry is performed immediately; whole-frame enhancement remains reserved for harder locator failures.
485
485
 
486
486
  ---
487
487
 
@@ -782,7 +782,7 @@ console.log(result.text);
782
782
  The `quadqr-js` package can be loaded directly from npm-backed CDNs:
783
783
 
784
784
  ```html
785
- <script src="https://cdn.jsdelivr.net/npm/quadqr-js@1.4.1/dist/quadqr.min.js"></script>
785
+ <script src="https://cdn.jsdelivr.net/npm/quadqr-js@1.5.1/dist/quadqr.min.js"></script>
786
786
  <script>
787
787
  const code = QuadQR.encodeText("Hello from a script tag");
788
788
  </script>
@@ -838,6 +838,16 @@ Build the distributable browser, Node.js, CDN, and WASM files:
838
838
  npm run build
839
839
  ```
840
840
 
841
+ `npm run build` verifies the checked-in WASM binary against `wasm-src/quadqr_core.c`, the WASM compiler flags, and the recorded binary hash. If everything matches, the verified prebuilt binary is reused. If the C source or build flags changed, the build automatically recompiles WASM with LLVM/Clang. If WASM is stale and `clang` is unavailable, the build fails instead of silently shipping an old binary.
842
+
843
+ To force only the WASM rebuild:
844
+
845
+ ```bash
846
+ npm run build:wasm
847
+ ```
848
+
849
+ A forced WASM rebuild requires `clang` in `PATH`. No Rust, Cargo, or Emscripten toolchain is required. The build records its verification data in `wasm/quadqr-core.build.json`.
850
+
841
851
  Start the interactive demo:
842
852
 
843
853
  ```bash
@@ -858,7 +868,7 @@ npm run benchmark
858
868
 
859
869
  ### Optional WASM acceleration
860
870
 
861
- The package ships a prebuilt WASM helper but never requires it.
871
+ The package ships a prebuilt WASM helper but never requires it. It accelerates CRC-32 plus the scanner's RGBA-to-grayscale, Otsu-threshold, and binary finder preprocessing hot path.
862
872
 
863
873
  ```js
864
874
  import { initWasm } from "quadqr-js";
@@ -866,7 +876,7 @@ import { initWasm } from "quadqr-js";
866
876
  await initWasm();
867
877
  ```
868
878
 
869
- If WASM cannot load, the normal JavaScript codec remains available.
879
+ If WASM cannot load, the normal JavaScript codec/scanner remains available. For camera or repeated image scanning, initialize WASM once during application startup.
870
880
 
871
881
  ---
872
882
 
@@ -901,7 +911,8 @@ wasm-src/
901
911
  quadqr_core.c Small portable WASM accelerator source
902
912
 
903
913
  wasm/
904
- quadqr-core.wasm Source-tree WASM build output
914
+ quadqr-core.wasm Source-tree WASM build output
915
+ quadqr-core.build.json Source/build/binary verification metadata
905
916
 
906
917
  dist/
907
918
  index.js ESM package entry
@@ -1093,7 +1104,7 @@ Scans one frame from an HTML video element. By default, if the video is displaye
1093
1104
 
1094
1105
  ### `startCameraScanner(video, options?)`
1095
1106
 
1096
- Starts a reusable live-camera scanning loop. On supported browsers it requests continuous focus/exposure/white-balance camera modes and scans the CSS-visible preview crop. A normal frame always gets the fast RGB-value finder pass first. If a miss still exposes at least two strong finder patterns, QuadQR retries the visible camera ROI at up to 1600 px by default so dense symbols retain more pixels per module. This high-resolution retry is bounded and does not run on empty frames. If it still fails, the **same captured frame** enters a QR-guide recovery path: QuadQR progressively crops away 8%, 16%, and 22% of the surrounding camera frame (then tries the full frame as a final fallback), applies the QuadQR-specific QuadQR Auto Color correction inside that code-centric region, and runs finder detection again. This matters because a live preview can contain dark room pixels, browser chrome, a monitor bezel, or other content that completely changes global QuadQR Auto Color/Otsu statistics even though a manually cropped screenshot scans instantly. Normal scanning stays unchanged and fast because these recovery paths run only after a miss. Finder-only recovery also tries multiple center-weighted QuadQR Auto Color histograms before threshold bracketing. `cameraHighResolutionMaxDimension` defaults to 1600, `cameraHighResolutionEvery` defaults to 2, and `cameraAutoColorEvery` defaults to 1. Multi-frame confidence fusion remains enabled by default with a four-frame history. Frames are kept only when their high-confidence data cells are consistent with the current tracked symbol. Per-cell evidence is weighted by confidence, frame quality, and recency, while second hypotheses are retained for Spectrum ECC 2.0. The optional `onDiagnostic(event)` callback exposes finder candidates, active locator method, crop/geometry/version hypothesis, recovery method, timing, and scan dimensions. `onResult(result, frame)` receives the exact raw decoded camera frame and, when QuadQR Auto Color was used, the enhanced recovery pixels and their crop rectangle, so UIs can keep the frozen frame and finder overlay aligned.
1107
+ Starts a reusable live-camera scanning loop. On supported browsers it requests continuous focus/exposure/white-balance camera modes and scans the CSS-visible preview crop. Modern browsers use a **dual-worker camera engine**: a lightweight fresh-frame worker continuously runs normal finder/geometry/decode attempts, while an independent recovery worker retains the complete high-resolution, Auto Color, precise-alignment, perspective, multi-frame, ECC, and damaged-code recovery stack. A slow recovery attempt therefore cannot prevent the fast worker from inspecting a newer camera frame. Finder detection remains JavaScript; optional WASM accelerates grayscale/binary preprocessing and CRC beneath the same detector. The scheduler uses `requestVideoFrameCallback()` when available and does not queue stale fast-path frames. Normal camera acquisition requests an environment camera around 1280×720 and crops/resizes the visible preview to a 640 px working bitmap **before** transferring it to the worker. Once a candidate validates structure, Spectrum ECC, and CRC, scanning returns immediately. If the fast worker misses, full recovery runs concurrently on a fresh frame at up to 960 px. Strong finder evidence dispatches recovery quickly; finder-less frames still receive periodic full recovery so severe color casts or damaged locators retain the same rescue paths. QuadQR Auto Color crop profiles, center-weighted histograms, threshold bracketing, precise alignment, projective recovery, QR-region enhancement, multi-frame confidence fusion, and soft-decision Spectrum ECC are unchanged. `cameraHighResolutionMaxDimension` defaults to 960. The optional `onDiagnostic(event)` callback exposes whether an event came from the fast or recovery worker, finder candidates, active locator method, crop/geometry/version hypothesis, recovery method, timing, and scan dimensions. `onResult(result, frame)` receives the exact frame that decoded, including enhanced recovery pixels when applicable, so UIs can keep the frozen frame and finder overlay aligned.
1097
1108
 
1098
1109
  ### `getVersionInfo(version, options?)`
1099
1110
 
package/SPECIFICATION.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  QuadQR is an experimental RGBW matrix symbology. Normal mode uses 4-state RGBW cells, while the optional **High Density Mode** is experimental and uses the 16-state Triangle16 physical layout. It is not ISO/IEC QR Code and is not intended to be decoded by standard QR readers.
6
6
 
7
- The physical matrix format remains **QuadQR Format v5**. Normal application data is always treated simply as UTF-8 text or arbitrary bytes. Compression, signatures, encryption, rendering, and diagnostics are optional features layered around that stable matrix codec.
7
+ The physical matrix format remains **QuadQR Format v6**. Normal application data is always treated simply as UTF-8 text or arbitrary bytes. Compression, signatures, encryption, rendering, and diagnostics are optional features layered around that stable matrix codec.
8
8
 
9
9
  For exact matrix geometry and Reed-Solomon framing, see [`FORMAT.md`](./FORMAT.md).
10
10
 
@@ -17,7 +17,7 @@ Application bytes / UTF-8 text
17
17
  ├─ optional Ed25519 signature metadata (internal)
18
18
  ├─ optional Secure Payload v1 (AES-256-GCM)
19
19
 
20
- └─ QuadQR Format v5
20
+ └─ QuadQR Format v6
21
21
  ├─ protected header
22
22
  ├─ CRC-32
23
23
  ├─ GF(256) Reed-Solomon Spectrum ECC
@@ -53,9 +53,9 @@ version = 1..40
53
53
 
54
54
  Three 7×7 finder patterns are always present. Version 1 has the legacy QuadQR 5×5 bottom-right alignment marker. Versions 2–40 use the distributed alignment schedule defined in `FORMAT.md`.
55
55
 
56
- ## 4. Format v5 header flags
56
+ ## 4. Format v6 header flags
57
57
 
58
- The protected Format v5 header uses:
58
+ The protected Format v6 header uses:
59
59
 
60
60
  ```text
61
61
  bit 0 UTF-8 text flag
@@ -128,7 +128,7 @@ bit 1 compressed
128
128
  bit 2 public key embedded
129
129
  ```
130
130
 
131
- The envelope contains no semantic content type. The Format v5 text flag still determines whether the recovered application payload should be decoded as UTF-8 text.
131
+ The envelope contains no semantic content type. The Format v6 text flag still determines whether the recovered application payload should be decoded as UTF-8 text.
132
132
 
133
133
  ## 7. Compression
134
134
 
@@ -167,11 +167,11 @@ lz
167
167
 
168
168
  `compression: "auto"` is the fast balanced policy. It evaluates LZ level 6, DEFLATE level 6, and Brotli quality 6 exactly once and chooses the smallest complete stored representation. For unsigned payloads that comparison includes the 16-byte extension-envelope cost, so Auto remains zero-overhead when compression is not useful.
169
169
 
170
- `compression: "smart"` is the opt-in CPU-heavy policy. It begins with the Auto candidates, computes the resulting Format v5 QuadQR version using the selected ECC/profile/version bounds, and only escalates when the next smaller matrix is plausibly reachable. The strong stage tests DEFLATE 8 and Brotli 9. If the symbol remains close to a smaller-version boundary, the maximum stage tests DEFLATE 9 and Brotli 11. With an explicitly requested fixed version, Smart does not chase a smaller matrix, but it may escalate when the balanced result does not fit and stronger compression can plausibly make that requested version fit. Signed and secure pipelines include their fixed envelope overhead when evaluating those version boundaries.
170
+ `compression: "smart"` is the opt-in CPU-heavy policy. It begins with the Auto candidates, computes the resulting Format v6 QuadQR version using the selected ECC/profile/version bounds, and only escalates when the next smaller matrix is plausibly reachable. The strong stage tests DEFLATE 8 and Brotli 9. If the symbol remains close to a smaller-version boundary, the maximum stage tests DEFLATE 9 and Brotli 11. With an explicitly requested fixed version, Smart does not chase a smaller matrix, but it may escalate when the balanced result does not fit and stronger compression can plausibly make that requested version fit. Signed and secure pipelines include their fixed envelope overhead when evaluating those version boundaries.
171
171
 
172
172
  Explicit `compression: "lz"` and `compression: "deflate"` accept `compressionLevel` `1..9` and default to 6. Explicit `compression: "brotli"` accepts `compressionLevel` `0..11` and defaults to 11. Compression levels are encoder-only parameters and are intentionally not stored in the extension envelope because LZ, RFC 1951, and Brotli decoders do not require them. Auto and Smart use LZ level 6; Smart's staged escalation remains focused on DEFLATE/Brotli.
173
173
 
174
- Compression occurs before signing, encryption, and Format v5 ECC.
174
+ Compression occurs before signing, encryption, and Format v6 ECC.
175
175
 
176
176
  ## 8. Signed QuadQR
177
177
 
@@ -211,13 +211,13 @@ application payload
211
211
  → optional compression
212
212
  → optional Ed25519 signature metadata
213
213
  → AES-256-GCM Secure Payload v1
214
- → Format v5 ECC/matrix
214
+ → Format v6 ECC/matrix
215
215
  ```
216
216
 
217
217
  After scanning:
218
218
 
219
219
  ```text
220
- Format v5 decode
220
+ Format v6 decode
221
221
  → AES-GCM authentication/decryption
222
222
  → internal compression/signature metadata processing
223
223
  → application payload
@@ -264,7 +264,7 @@ Recommended general-purpose starting module size is **0.40 mm/module**. Real pri
264
264
 
265
265
  ## 12. Logo safety
266
266
 
267
- Logos are rendering overlays and never modify Format v5 data structures.
267
+ Logos are rendering overlays and never modify Format v6 data structures.
268
268
 
269
269
  `size: "auto"` estimates a conservative logo ratio from:
270
270
 
@@ -320,7 +320,7 @@ These scores are regression/testing aids. They do not replace validation with re
320
320
 
321
321
  ## 15. Capacity planning
322
322
 
323
- Capacity is determined from the actual Format v5 layout, protected header, CRC, and Spectrum ECC plan. Compression can reduce stored payload bytes, while signatures and encryption add metadata bytes before the matrix codec.
323
+ Capacity is determined from the actual Format v6 layout, protected header, CRC, and Spectrum ECC plan. Compression can reduce stored payload bytes, while signatures and encryption add metadata bytes before the matrix codec.
324
324
 
325
325
  The benchmark helper can report:
326
326
 
@@ -340,7 +340,7 @@ Implementations should follow these rules:
340
340
 
341
341
  1. Keep RGBW mapping exactly `R=00, G=01, B=10, W=11`.
342
342
  2. Keep GF(256) Spectrum ECC and its errors+erasures behavior.
343
- 3. Preserve Format v5 decoding for normal and Secure Payload symbols.
343
+ 3. Preserve Format v5 decoding as a legacy compatibility path while encoding new symbols as Format v6.
344
344
  4. Keep application semantics outside the QuadQR codec. Do not require a growing content-type registry.
345
345
  5. Treat compression/signature metadata as internal transport metadata, not a separate user payload mode.
346
346
  6. Treat `keyId` only as an identifier. Signer trust comes from an external trusted public-key binding.