@photivra/engine 2.22.0 → 2.23.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.
- package/CHANGELOG.md +33 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/dist/color/neighbor-highlight-reconstruction.d.ts +12 -2
- package/dist/color/neighbor-highlight-reconstruction.js +26 -3
- package/dist/color/neighbor-highlight-reconstruction.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/facade/display-view-rendering.d.ts +5 -0
- package/dist/facade/display-view-rendering.js +57 -22
- package/dist/facade/display-view-rendering.js.map +1 -1
- package/dist/facade/fast-methods.js +2 -2
- package/dist/facade/fast-methods.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.js +22 -18
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.js +15 -10
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/wgsl-display-view-coupled-stub.d.ts +6 -1
- package/dist/gpu/wgsl-display-view-coupled-stub.js +9 -1
- package/dist/gpu/wgsl-display-view-coupled-stub.js.map +1 -1
- package/dist/gpu/wgsl-display-view-coupled.d.ts +3 -0
- package/dist/gpu/wgsl-display-view-coupled.js +16 -4
- package/dist/gpu/wgsl-display-view-coupled.js.map +1 -1
- package/dist/gpu/wgsl-display-view-neighbors.d.ts +46 -0
- package/dist/gpu/wgsl-display-view-neighbors.js +114 -0
- package/dist/gpu/wgsl-display-view-neighbors.js.map +1 -0
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +2 -0
- package/dist/gpu/wgsl-display-view-quality-kernel.js +5 -3
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.js +3 -3
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
- package/docs/API_REFERENCE.md +1 -1
- package/docs/USAGE.md +2 -1
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +2 -2
- package/docs/api/facade-fast-methods.md +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 2.
|
|
3
|
+
## 2.23.0 — unreleased (prepared November 12, 2026)
|
|
4
|
+
|
|
5
|
+
A minor release: neighbor highlight reconstruction on the WebGPU display view (#605), with the CPU region order and the full method's relaxation factor it needed, and the #604 research report. See the [2.23.0 release record](https://github.com/Photivra/photivra/blob/main/docs/RELEASE_2_23_0.md).
|
|
6
|
+
|
|
7
|
+
- **GPU:** `output.highlightMode: "reconstruct-neighbors"` (#602) runs in the WebGPU display view's Speed and Quality kernels, fast
|
|
8
|
+
(ring average) and full (harmonic fill), instead of falling back to the CPU (#605). The host finds each clipped region's ratios with
|
|
9
|
+
the reference's own code and uploads them in the band's flag buffer (no binding is added); the kernels rebuild each clipped
|
|
10
|
+
channel inside the coupled chain in float32, within documented first-order bounds (docs/WEBGPU.md, "Neighbor highlight
|
|
11
|
+
reconstruction (#605)"). Registered in the fast-methods registry (`output.highlightMode.reconstruct-neighbors/region-ratios`).
|
|
12
|
+
- **Display view (CPU):** a clipped region's members are taken in raster order, so its ratios no longer depend on which pixel
|
|
13
|
+
reached the region first; a region render, the GPU host and the whole view agree bit for bit (#605). A region above the search
|
|
14
|
+
cap (65,536 pixels fast, 262,144 full) is solved per tile of 256 × 256 or 512 × 512 pixels (2.22.0 took the part found from the
|
|
15
|
+
first pixel that reached it, which depended on the render's order).
|
|
16
|
+
- **Full method's SOR (captures and the display view):** the relaxation factor is the optimal ω of each region's bounding
|
|
17
|
+
rectangle (`neighborHighlightOmega`) instead of 1.8, at the same 10⁻⁹ tolerance: 3.2–4.9× faster on 68–132 px regions and
|
|
18
|
+
35–76× closer to the converged fill (`test/neighbor-highlight-sor.test.ts`). Full-method results change below the old
|
|
19
|
+
tolerance's error (at most 2 × 10⁻⁷ in a ratio on the measured regions).
|
|
20
|
+
- **Size measurement:** `test/capture-bundle.test.ts` bundles the shader literals minified, as the published package ships them
|
|
21
|
+
(`npm run build` strips WGSL comments and indentation; owner decision 2026-11-11), for every row. On 2.22.0's tree that reads
|
|
22
|
+
fast worker 333,241 B and on demand 43,456 B (the source text: 337,413 B and 46,977 B); with #605, 333,322 B (+81) and
|
|
23
|
+
45,110 B (+1,654: the GPU coupled and neighbor chunk +1,288, the CPU Quality kit +314, the GPU Quality chunk +52). No limit changed.
|
|
24
|
+
- **Research (#604, not shipped):** [docs/research/ahd-bias-correction.md](https://github.com/Photivra/photivra/blob/main/docs/research/ahd-bias-correction.md) measures per-site
|
|
25
|
+
estimators of the display view's AHD low-signal bias, computed at use with no table keyed by channel signal levels. None
|
|
26
|
+
is fast enough for the CPU view (10–20 ms per site); #604 is closed and 2.22.0's labeled approximation stays. The prototype is
|
|
27
|
+
in `scripts/research/ahd-bias/`, outside the package.
|
|
28
|
+
- **Root exports:** none added or removed (1,981; runtime exports 672).
|
|
29
|
+
- **CI capacity (owner decision 2026-11-12):** the Node test legs run in three parts (two before) and coverage in ten shards
|
|
30
|
+
(eight before) in `ci.yml` and `publish.yml`, and the SwiftShader WebGPU suite in three jobs (two before; the
|
|
31
|
+
real-GPU Quality full case in four bands of the view); #605's emulation tests are split into ten files by case, the Quality cases and the banding
|
|
32
|
+
check into bands of rows that check the same pixels, with a 900 s per-test deadline for the Quality bands. No test was removed and no job
|
|
33
|
+
time limit was raised (docs/RELEASE_2_23_0.md, "Local gates").
|
|
34
|
+
|
|
35
|
+
## 2.22.0 — published November 12, 2026
|
|
4
36
|
|
|
5
37
|
A minor release: phone DNG import with JPEG XL and lossy JPEG raw data, the DNG stage image and opcodes (#598, #600) and the channel-response helper (#591); native-photosite sensor figures (#595), read noise per photosite on the tiers (#599), mixed lighting over an image-plane print (#597), sample counts that follow the light and the output (#590) and the catalogue's fast grid (#603); the display view's luminance tone curves, highlight reconstruction and desaturation on the CPU and GPU (#593, #601, #602); the removal of the display view's AHD low-signal correction; Content Credentials writers (#165, engine half); and the full-quality and opt-in code loaded on demand (#594). See the [2.22.0 release record](https://github.com/Photivra/photivra/blob/main/docs/RELEASE_2_22_0.md).
|
|
6
38
|
|
package/CITATION.cff
CHANGED
|
@@ -9,7 +9,7 @@ abstract: "An open TypeScript engine for the science and mathematics of photogra
|
|
|
9
9
|
repository-code: "https://github.com/photivra/photivra"
|
|
10
10
|
url: "https://photivra.com"
|
|
11
11
|
license: "Apache-2.0"
|
|
12
|
-
version: "2.
|
|
12
|
+
version: "2.23.0"
|
|
13
13
|
keywords:
|
|
14
14
|
- photography
|
|
15
15
|
- camera optics
|
package/README.md
CHANGED
|
@@ -32,10 +32,10 @@ The source is licensed under Apache-2.0.
|
|
|
32
32
|
|
|
33
33
|
## Quick start
|
|
34
34
|
|
|
35
|
-
Install the published ESM package below. The [2.
|
|
35
|
+
Install the published ESM package below. The [2.23.0 release record](https://github.com/Photivra/photivra/blob/main/docs/RELEASE_2_23_0.md) and [changelog](https://github.com/Photivra/photivra/blob/main/CHANGELOG.md) describe the current release:
|
|
36
36
|
|
|
37
37
|
```sh
|
|
38
|
-
npm install @photivra/engine@2.
|
|
38
|
+
npm install @photivra/engine@2.23.0
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
Simulate a photograph of a test chart with a generic camera, then read the developed sRGB pixels:
|
|
@@ -75,7 +75,7 @@ console.log(horizontal.provenance);
|
|
|
75
75
|
|
|
76
76
|
Start with the [Developer Guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Then use the [Usage Guide](https://github.com/Photivra/photivra/blob/main/docs/USAGE.md) and the [API reference](https://github.com/Photivra/photivra/blob/main/docs/API_REFERENCE.md), which is generated from the package exports.
|
|
77
77
|
|
|
78
|
-
Repository `main` may describe newer, unreleased work. For the stable contract, use the docs bundled in the published package, or the exact `v2.
|
|
78
|
+
Repository `main` may describe newer, unreleased work. For the stable contract, use the docs bundled in the published package, or the exact `v2.23.0` tag.
|
|
79
79
|
|
|
80
80
|
## Documentation
|
|
81
81
|
|
|
@@ -363,14 +363,14 @@ The application can then use those results, while the photography calculations t
|
|
|
363
363
|
|
|
364
364
|
## Status
|
|
365
365
|
|
|
366
|
-
- Repository package version: `2.
|
|
367
|
-
- Engine API contract: `2.
|
|
366
|
+
- Repository package version: `2.23.0` (release candidate prepared November 12, 2026; publication is separate)
|
|
367
|
+
- Engine API contract: `2.23.0`
|
|
368
368
|
- Versioned generic tier reference assets: [GENERIC_TIER_PRESETS.md](https://github.com/Photivra/photivra/blob/main/docs/GENERIC_TIER_PRESETS.md).
|
|
369
369
|
- Sensor profiles from published specifications (#554, unnamed): [SENSOR_PROFILES.md](https://github.com/Photivra/photivra/blob/main/docs/SENSOR_PROFILES.md).
|
|
370
370
|
- Composed POC simulation API contract: `1.0.0`
|
|
371
371
|
- Stability: 1.0 root-package compatibility policy; bounded scientific models and independent POC contract
|
|
372
372
|
|
|
373
|
-
From 1.0.1, the package version and `ENGINE_API_VERSION` are equal. New captures/plans record 2.
|
|
373
|
+
From 1.0.1, the package version and `ENGINE_API_VERSION` are equal. New captures/plans record 2.23.0; existing archives keep their original creator identities. Schema, model and POC contract versions stay independent.
|
|
374
374
|
|
|
375
375
|
A breaking change to the root contracts now needs a new package major version. Additive and corrective changes follow [compatibility and migration](https://github.com/Photivra/photivra/blob/main/docs/RELEASE_1_3_0.md). A 1.0 package is not a claim of calibrated physical accuracy.
|
|
376
376
|
|
package/SECURITY.md
CHANGED
|
@@ -4,7 +4,7 @@ Please do not open a public issue that contains vulnerability details.
|
|
|
4
4
|
|
|
5
5
|
## Supported versions
|
|
6
6
|
|
|
7
|
-
The published 1.0.0 release started the 1.x root-package compatibility line, and 2.0.0 started the 2.x line. The current release is **2.
|
|
7
|
+
The published 1.0.0 release started the 1.x root-package compatibility line, and 2.0.0 started the 2.x line. The current release is **2.22.0**, published on November 12, 2026 (see [CHANGELOG.md](CHANGELOG.md)).
|
|
8
8
|
|
|
9
9
|
Security fixes target the current maintained development and release line. Do not assume that older 1.x releases, snapshots or pre-1.0 releases will receive fixes.
|
|
10
10
|
|
|
@@ -27,12 +27,22 @@ export declare const NEIGHBOR_HIGHLIGHT_THRESHOLD = 0.98;
|
|
|
27
27
|
export declare const NEIGHBOR_HIGHLIGHT_MARGIN = 2;
|
|
28
28
|
/** The fast method's ring width in pixels around a (widened) clipped region. */
|
|
29
29
|
export declare const NEIGHBOR_HIGHLIGHT_RING = 2;
|
|
30
|
-
/** The full method's
|
|
30
|
+
/** The full method's tolerance (the largest change of a sweep) and iteration cap; the relaxation factor is `neighborHighlightOmega`. */
|
|
31
31
|
export declare const NEIGHBOR_HIGHLIGHT_SOR: Readonly<{
|
|
32
|
-
omega: 1.8;
|
|
33
32
|
tolerance: 1e-9;
|
|
34
33
|
maximumIterations: 20000;
|
|
35
34
|
}>;
|
|
35
|
+
/**
|
|
36
|
+
* #605 (2.23.0): the relaxation factor for a region whose members span a × b pixels: the optimal ω = 2/(1 + √(1 − ρ²)) of SOR
|
|
37
|
+
* for the discrete Laplace equation on the a × b rectangle, whose Jacobi iteration has spectral radius
|
|
38
|
+
* ρ = (cos(π/(a + 1)) + cos(π/(b + 1)))/2 (Young's theory of successive over-relaxation; e.g. G. Strang, MIT OpenCourseWare
|
|
39
|
+
* 18.086, and R. J. LeVeque, "Finite Difference Methods for Ordinary and Partial Differential Equations", SIAM 2007, §4.2).
|
|
40
|
+
* A region inside the rectangle has a Jacobi radius at most that of the rectangle, so this ω is at or above its optimum (where
|
|
41
|
+
* SOR converges at the rate ω − 1). The system (each member's neighbor count times its ratio minus its neighbors') is
|
|
42
|
+
* symmetric positive definite, so SOR converges for every ω in (0, 2) (Ostrowski–Reich). 2.22.0 used ω = 1.8 for every region:
|
|
43
|
+
* 5,728 sweeps on a 260 × 260 region against about 400 (docs/DISPLAY_VIEW.md).
|
|
44
|
+
*/
|
|
45
|
+
export declare function neighborHighlightOmega(a: number, b: number): number;
|
|
36
46
|
export interface NeighborHighlightReport {
|
|
37
47
|
method: "ring-average" | "harmonic-interpolation";
|
|
38
48
|
/** Clipped pixels rebuilt, and the clipped regions. */
|
|
@@ -28,8 +28,22 @@ export const NEIGHBOR_HIGHLIGHT_THRESHOLD = 0.98;
|
|
|
28
28
|
export const NEIGHBOR_HIGHLIGHT_MARGIN = 2;
|
|
29
29
|
/** The fast method's ring width in pixels around a (widened) clipped region. */
|
|
30
30
|
export const NEIGHBOR_HIGHLIGHT_RING = 2;
|
|
31
|
-
/** The full method's
|
|
32
|
-
export const NEIGHBOR_HIGHLIGHT_SOR = /* @__PURE__ */ Object.freeze({
|
|
31
|
+
/** The full method's tolerance (the largest change of a sweep) and iteration cap; the relaxation factor is `neighborHighlightOmega`. */
|
|
32
|
+
export const NEIGHBOR_HIGHLIGHT_SOR = /* @__PURE__ */ Object.freeze({ tolerance: 1e-9, maximumIterations: 20000 });
|
|
33
|
+
/**
|
|
34
|
+
* #605 (2.23.0): the relaxation factor for a region whose members span a × b pixels: the optimal ω = 2/(1 + √(1 − ρ²)) of SOR
|
|
35
|
+
* for the discrete Laplace equation on the a × b rectangle, whose Jacobi iteration has spectral radius
|
|
36
|
+
* ρ = (cos(π/(a + 1)) + cos(π/(b + 1)))/2 (Young's theory of successive over-relaxation; e.g. G. Strang, MIT OpenCourseWare
|
|
37
|
+
* 18.086, and R. J. LeVeque, "Finite Difference Methods for Ordinary and Partial Differential Equations", SIAM 2007, §4.2).
|
|
38
|
+
* A region inside the rectangle has a Jacobi radius at most that of the rectangle, so this ω is at or above its optimum (where
|
|
39
|
+
* SOR converges at the rate ω − 1). The system (each member's neighbor count times its ratio minus its neighbors') is
|
|
40
|
+
* symmetric positive definite, so SOR converges for every ω in (0, 2) (Ostrowski–Reich). 2.22.0 used ω = 1.8 for every region:
|
|
41
|
+
* 5,728 sweeps on a 260 × 260 region against about 400 (docs/DISPLAY_VIEW.md).
|
|
42
|
+
*/
|
|
43
|
+
export function neighborHighlightOmega(a, b) {
|
|
44
|
+
const rho = (Math.cos(Math.PI / (a + 1)) + Math.cos(Math.PI / (b + 1))) / 2;
|
|
45
|
+
return 2 / (1 + Math.sqrt(Math.max(0, 1 - rho * rho)));
|
|
46
|
+
}
|
|
33
47
|
/**
|
|
34
48
|
* The region ratios of an image: per pixel the ratios ρ its rebuild uses (`ratios`, 3 per pixel; for an unclipped pixel its own),
|
|
35
49
|
* and which pixels are clipped. `clippedAt(i)` tells whether pixel i is clipped; `valueAt(i, out)` writes pixel i's u.
|
|
@@ -118,7 +132,16 @@ export function neighborHighlightRatios(width, height, clippedAt, valueAt, fast)
|
|
|
118
132
|
if (fast || count === 0)
|
|
119
133
|
continue;
|
|
120
134
|
// Full: successive over-relaxation of the discrete Laplace equation over the region, in the region's breadth-first order.
|
|
121
|
-
const {
|
|
135
|
+
const { tolerance, maximumIterations } = NEIGHBOR_HIGHLIGHT_SOR;
|
|
136
|
+
let x0 = width, x1 = -1, y0 = height, y1 = -1;
|
|
137
|
+
for (let k = 0; k < tail; k++) {
|
|
138
|
+
const p = queue[k], px = p % width, py = (p - px) / width;
|
|
139
|
+
x0 = Math.min(x0, px);
|
|
140
|
+
x1 = Math.max(x1, px);
|
|
141
|
+
y0 = Math.min(y0, py);
|
|
142
|
+
y1 = Math.max(y1, py);
|
|
143
|
+
}
|
|
144
|
+
const omega = neighborHighlightOmega(x1 - x0 + 1, y1 - y0 + 1);
|
|
122
145
|
let sweep = 0, change = Infinity;
|
|
123
146
|
while (sweep < maximumIterations && change > tolerance) {
|
|
124
147
|
change = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"neighbor-highlight-reconstruction.js","sourceRoot":"","sources":["../../src/color/neighbor-highlight-reconstruction.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * #602 (2.22.0): highlight reconstruction from neighboring pixels, `highlightMode: \"reconstruct-neighbors\"` (opt-in; an estimate,\n * not a recovery of the clipped scene signal). The engine's own method, acting on the developed, white-balanced camera values\n * u = g·c of the whole image at use (no tables):\n *\n * 1. A pixel is clipped when one of its normalized camera channels c_k reaches `NEIGHBOR_HIGHLIGHT_THRESHOLD` of white; clipped\n * pixels form regions (8-connected).\n * 2. Each unclipped pixel has the color ratios ρ = u/(u₀ + u₁ + u₂) (its chromaticity in white-balanced camera space). Pixels\n * within `NEIGHBOR_HIGHLIGHT_MARGIN` pixels of a clipped one give no ratios: their demosaic reads clipped sites, which lowers\n * the clipped channel (and noise selects them by the threshold); the regions below are the clipped pixels widened by it.\n * 3. The clipped region takes its ratios from its unclipped boundary. **Fast:** the mean of ρ over the unclipped pixels within\n * `NEIGHBOR_HIGHLIGHT_RING` pixels (Chebyshev distance) of the region. **Full:** the discrete harmonic (Laplace) interpolation\n * of ρ inward: ρ at each clipped pixel is the mean of its 4-neighbors', with the unclipped neighbors' ratios as Dirichlet\n * boundary values (pixels outside the image are left out), solved by successive over-relaxation from the fast values. A region\n * with no unclipped neighbor keeps the neutral ratios.\n * 4. A clipped pixel keeps its unclipped channels; its scale s = Σ_unclipped u_k / Σ_unclipped ρ_k, and each clipped channel\n * becomes max(u_k, s·ρ_k) (never below what was recorded). Where every channel is clipped, s = max_k u_k/ρ_k.\n * The result is not clipped at the white level: the tone curve and gamut handling then render it.\n *\n * Mathematics only, general and free: the discrete Laplace equation and its Dirichlet problem, and successive over-relaxation\n * (e.g. G. Strang, MIT OpenCourseWare 18.086, \"Mathematical Methods for Engineers II\", finite differences for Laplace's equation\n * and iterative solvers, free at https://ocw.mit.edu/courses/18-086-mathematical-methods-for-engineers-ii-spring-2006/).\n */\n\n/** Normalized channel level at which a channel counts as clipped. */\nexport const NEIGHBOR_HIGHLIGHT_THRESHOLD = 0.98;\n/** Pixels this close (Chebyshev distance) to a clipped pixel give no ratios and are filled with the region. */\nexport const NEIGHBOR_HIGHLIGHT_MARGIN = 2;\n/** The fast method's ring width in pixels around a (widened) clipped region. */\nexport const NEIGHBOR_HIGHLIGHT_RING = 2;\n/** The full method's relaxation factor, tolerance and iteration cap. */\nexport const NEIGHBOR_HIGHLIGHT_SOR = /* @__PURE__ */ Object.freeze({ omega: 1.8, tolerance: 1e-9, maximumIterations: 20000 });\n\nexport interface NeighborHighlightReport {\n method: \"ring-average\" | \"harmonic-interpolation\";\n /** Clipped pixels rebuilt, and the clipped regions. */\n reconstructedPixelCount: number;\n regionCount: number;\n /** Full method: the largest number of relaxation sweeps a region needed, and whether every region met the tolerance. */\n iterations: number;\n converged: boolean;\n}\n\n/**\n * The region ratios of an image: per pixel the ratios ρ its rebuild uses (`ratios`, 3 per pixel; for an unclipped pixel its own),\n * and which pixels are clipped. `clippedAt(i)` tells whether pixel i is clipped; `valueAt(i, out)` writes pixel i's u.\n * Pixels are i = y·width + x.\n */\nexport function neighborHighlightRatios(width: number, height: number, clippedAt: (i: number) => boolean, valueAt: (i: number, out: Float64Array) => void, fast: boolean):\n { clipped: Uint8Array; ratios: Float64Array; regionCount: number; iterations: number; converged: boolean } {\n const n = width * height, clipped = new Uint8Array(n), unknown = new Uint8Array(n), ratios = new Float64Array(3 * n), u = new Float64Array(3), D = NEIGHBOR_HIGHLIGHT_MARGIN;\n for (let i = 0; i < n; i++) if (clippedAt(i)) clipped[i] = 1;\n // The clipped pixels widened by the margin (a separable dilation).\n const rows = new Uint8Array(n);\n for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) if (clipped[y * width + x] === 1) rows.fill(1, y * width + Math.max(0, x - D), y * width + Math.min(width, x + D + 1));\n for (let x = 0; x < width; x++) for (let y = 0; y < height; y++) if (rows[y * width + x] === 1) for (let yy = Math.max(0, y - D); yy <= Math.min(height - 1, y + D); yy++) unknown[yy * width + x] = 1;\n for (let i = 0; i < n; i++) {\n if (unknown[i] === 1) continue;\n valueAt(i, u);\n const sum = u[0]! + u[1]! + u[2]!;\n if (sum > 0) { ratios[3 * i] = u[0]! / sum; ratios[3 * i + 1] = u[1]! / sum; ratios[3 * i + 2] = u[2]! / sum; }\n else { ratios[3 * i] = 1 / 3; ratios[3 * i + 1] = 1 / 3; ratios[3 * i + 2] = 1 / 3; }\n }\n const label = new Int32Array(n).fill(-1), stamp = new Int32Array(n).fill(-1), queue = new Int32Array(n);\n let regionCount = 0, iterations = 0, converged = true;\n for (let start = 0; start < n; start++) {\n if (unknown[start] === 0 || label[start]! >= 0) continue;\n // The region (8-connected), breadth first.\n const region = regionCount++;\n let head = 0, tail = 0;\n queue[tail++] = start; label[start] = region;\n while (head < tail) {\n const p = queue[head++]!, px = p % width, py = (p - px) / width;\n for (let dy = -1; dy <= 1; dy++) for (let dx = -1; dx <= 1; dx++) {\n const x = px + dx, y = py + dy;\n if (x < 0 || y < 0 || x >= width || y >= height) continue;\n const q = y * width + x;\n if (unknown[q] === 1 && label[q]! < 0) { label[q] = region; queue[tail++] = q; }\n }\n }\n // Fast: the mean ratios over the ring (each unclipped pixel once).\n let r0 = 0, r1 = 0, r2 = 0, count = 0;\n const R = NEIGHBOR_HIGHLIGHT_RING;\n for (let k = 0; k < tail; k++) {\n const p = queue[k]!, px = p % width, py = (p - px) / width;\n for (let y = Math.max(0, py - R); y <= Math.min(height - 1, py + R); y++) for (let x = Math.max(0, px - R); x <= Math.min(width - 1, px + R); x++) {\n const q = y * width + x;\n if (unknown[q] === 1 || stamp[q] === region) continue;\n stamp[q] = region; r0 += ratios[3 * q]!; r1 += ratios[3 * q + 1]!; r2 += ratios[3 * q + 2]!; count++;\n }\n }\n const m0 = count > 0 ? r0 / count : 1 / 3, m1 = count > 0 ? r1 / count : 1 / 3, m2 = count > 0 ? r2 / count : 1 / 3;\n for (let k = 0; k < tail; k++) { const p = queue[k]!; ratios[3 * p] = m0; ratios[3 * p + 1] = m1; ratios[3 * p + 2] = m2; }\n if (fast || count === 0) continue;\n // Full: successive over-relaxation of the discrete Laplace equation over the region, in the region's breadth-first order.\n const { omega, tolerance, maximumIterations } = NEIGHBOR_HIGHLIGHT_SOR;\n let sweep = 0, change = Infinity;\n while (sweep < maximumIterations && change > tolerance) {\n change = 0; sweep++;\n for (let k = 0; k < tail; k++) {\n const p = queue[k]!, px = p % width, py = (p - px) / width;\n let a0 = 0, a1 = 0, a2 = 0, m = 0;\n for (let d = 0; d < 4; d++) {\n const x = px + (d === 0 ? -1 : d === 1 ? 1 : 0), y = py + (d === 2 ? -1 : d === 3 ? 1 : 0);\n if (x < 0 || y < 0 || x >= width || y >= height) continue;\n const q = y * width + x;\n a0 += ratios[3 * q]!; a1 += ratios[3 * q + 1]!; a2 += ratios[3 * q + 2]!; m++;\n }\n if (m === 0) continue;\n for (let c = 0; c < 3; c++) {\n const old = ratios[3 * p + c]!, target = (c === 0 ? a0 : c === 1 ? a1 : a2) / m, next = old + omega * (target - old);\n ratios[3 * p + c] = next;\n const delta = Math.abs(next - old);\n if (delta > change) change = delta;\n }\n }\n }\n iterations = Math.max(iterations, sweep);\n if (change > tolerance) converged = false;\n }\n return { clipped, ratios, regionCount, iterations, converged };\n}\n\n/**\n * The rebuild of one clipped pixel (step 4) into b, with its slopes ∂b/∂c (row-major 3 × 3, a.e.) when `slopes` is given.\n * `c` are the normalized camera channels, `g` the white-balance gains, `rho` the pixel's ratios.\n */\nexport function rebuildClippedPixel(c0: number, c1: number, c2: number, g: ArrayLike<number>, rho: ArrayLike<number>, b: Float64Array | number[], slopes?: Float64Array): void {\n const H = NEIGHBOR_HIGHLIGHT_THRESHOLD, u0 = c0 * g[0]!, u1 = c1 * g[1]!, u2 = c2 * g[2]!;\n const k0 = c0 < H, k1 = c1 < H, k2 = c2 < H;\n if (slopes) slopes.fill(0);\n if (k0 && k1 && k2) {\n b[0] = u0; b[1] = u1; b[2] = u2;\n if (slopes) { slopes[0] = g[0]!; slopes[4] = g[1]!; slopes[8] = g[2]!; }\n return;\n }\n const r0 = rho[0]!, r1 = rho[1]!, r2 = rho[2]!;\n if (!k0 && !k1 && !k2) {\n const q0 = r0 > 0 ? u0 / r0 : 0, q1 = r1 > 0 ? u1 / r1 : 0, q2 = r2 > 0 ? u2 / r2 : 0, m = q0 > q1 ? (q0 > q2 ? 0 : 2) : (q1 > q2 ? 1 : 2), s = m === 0 ? q0 : m === 1 ? q1 : q2;\n b[0] = s * r0; b[1] = s * r1; b[2] = s * r2;\n if (slopes) { const rm = m === 0 ? r0 : m === 1 ? r1 : r2; if (rm > 0) for (let k = 0; k < 3; k++) slopes[k * 3 + m] = (k === 0 ? r0 : k === 1 ? r1 : r2) * g[m]! / rm; }\n return;\n }\n const su = (k0 ? u0 : 0) + (k1 ? u1 : 0) + (k2 ? u2 : 0), sr = (k0 ? r0 : 0) + (k1 ? r1 : 0) + (k2 ? r2 : 0), s = sr > 0 ? su / sr : 0;\n for (let k = 0; k < 3; k++) {\n const kept = k === 0 ? k0 : k === 1 ? k1 : k2, uk = k === 0 ? u0 : k === 1 ? u1 : u2, rk = k === 0 ? r0 : k === 1 ? r1 : r2;\n if (kept) { b[k] = uk; if (slopes) slopes[k * 4] = g[k]!; continue; }\n const estimate = s * rk;\n if (estimate > uk) {\n b[k] = estimate;\n if (slopes && sr > 0) for (let j = 0; j < 3; j++) if (j === 0 ? k0 : j === 1 ? k1 : k2) slopes[k * 3 + j] = rk * g[j]! / sr;\n } else { b[k] = uk; if (slopes) slopes[k * 4] = g[k]!; }\n }\n}\n\n/**\n * Rebuilds the clipped pixels of a white-balanced image u (3 per pixel, in place; becomes b), with the normalized channels\n * c = u/g deciding which channels are clipped.\n */\nexport function reconstructHighlightsFromNeighbors(u: Float64Array, width: number, height: number, gains: ArrayLike<number>, fast: boolean): NeighborHighlightReport {\n const H = NEIGHBOR_HIGHLIGHT_THRESHOLD, g0 = gains[0]!, g1 = gains[1]!, g2 = gains[2]!;\n const field = neighborHighlightRatios(width, height, (i) => u[3 * i]! / g0 >= H || u[3 * i + 1]! / g1 >= H || u[3 * i + 2]! / g2 >= H,\n (i, out) => { out[0] = u[3 * i]!; out[1] = u[3 * i + 1]!; out[2] = u[3 * i + 2]!; }, fast);\n const b = new Float64Array(3);\n let rebuilt = 0;\n for (let i = 0; i < width * height; i++) {\n if (field.clipped[i] === 0) continue;\n rebuildClippedPixel(u[3 * i]! / g0, u[3 * i + 1]! / g1, u[3 * i + 2]! / g2, gains, field.ratios.subarray(3 * i, 3 * i + 3), b);\n u[3 * i] = b[0]!; u[3 * i + 1] = b[1]!; u[3 * i + 2] = b[2]!;\n rebuilt++;\n }\n return { method: fast ? \"ring-average\" : \"harmonic-interpolation\", reconstructedPixelCount: rebuilt, regionCount: field.regionCount, iterations: field.iterations, converged: field.converged };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"neighbor-highlight-reconstruction.js","sourceRoot":"","sources":["../../src/color/neighbor-highlight-reconstruction.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * #602 (2.22.0): highlight reconstruction from neighboring pixels, `highlightMode: \"reconstruct-neighbors\"` (opt-in; an estimate,\n * not a recovery of the clipped scene signal). The engine's own method, acting on the developed, white-balanced camera values\n * u = g·c of the whole image at use (no tables):\n *\n * 1. A pixel is clipped when one of its normalized camera channels c_k reaches `NEIGHBOR_HIGHLIGHT_THRESHOLD` of white; clipped\n * pixels form regions (8-connected).\n * 2. Each unclipped pixel has the color ratios ρ = u/(u₀ + u₁ + u₂) (its chromaticity in white-balanced camera space). Pixels\n * within `NEIGHBOR_HIGHLIGHT_MARGIN` pixels of a clipped one give no ratios: their demosaic reads clipped sites, which lowers\n * the clipped channel (and noise selects them by the threshold); the regions below are the clipped pixels widened by it.\n * 3. The clipped region takes its ratios from its unclipped boundary. **Fast:** the mean of ρ over the unclipped pixels within\n * `NEIGHBOR_HIGHLIGHT_RING` pixels (Chebyshev distance) of the region. **Full:** the discrete harmonic (Laplace) interpolation\n * of ρ inward: ρ at each clipped pixel is the mean of its 4-neighbors', with the unclipped neighbors' ratios as Dirichlet\n * boundary values (pixels outside the image are left out), solved by successive over-relaxation from the fast values. A region\n * with no unclipped neighbor keeps the neutral ratios.\n * 4. A clipped pixel keeps its unclipped channels; its scale s = Σ_unclipped u_k / Σ_unclipped ρ_k, and each clipped channel\n * becomes max(u_k, s·ρ_k) (never below what was recorded). Where every channel is clipped, s = max_k u_k/ρ_k.\n * The result is not clipped at the white level: the tone curve and gamut handling then render it.\n *\n * Mathematics only, general and free: the discrete Laplace equation and its Dirichlet problem, and successive over-relaxation\n * (e.g. G. Strang, MIT OpenCourseWare 18.086, \"Mathematical Methods for Engineers II\", finite differences for Laplace's equation\n * and iterative solvers, free at https://ocw.mit.edu/courses/18-086-mathematical-methods-for-engineers-ii-spring-2006/).\n */\n\n/** Normalized channel level at which a channel counts as clipped. */\nexport const NEIGHBOR_HIGHLIGHT_THRESHOLD = 0.98;\n/** Pixels this close (Chebyshev distance) to a clipped pixel give no ratios and are filled with the region. */\nexport const NEIGHBOR_HIGHLIGHT_MARGIN = 2;\n/** The fast method's ring width in pixels around a (widened) clipped region. */\nexport const NEIGHBOR_HIGHLIGHT_RING = 2;\n/** The full method's tolerance (the largest change of a sweep) and iteration cap; the relaxation factor is `neighborHighlightOmega`. */\nexport const NEIGHBOR_HIGHLIGHT_SOR = /* @__PURE__ */ Object.freeze({ tolerance: 1e-9, maximumIterations: 20000 });\n\n/**\n * #605 (2.23.0): the relaxation factor for a region whose members span a × b pixels: the optimal ω = 2/(1 + √(1 − ρ²)) of SOR\n * for the discrete Laplace equation on the a × b rectangle, whose Jacobi iteration has spectral radius\n * ρ = (cos(π/(a + 1)) + cos(π/(b + 1)))/2 (Young's theory of successive over-relaxation; e.g. G. Strang, MIT OpenCourseWare\n * 18.086, and R. J. LeVeque, \"Finite Difference Methods for Ordinary and Partial Differential Equations\", SIAM 2007, §4.2).\n * A region inside the rectangle has a Jacobi radius at most that of the rectangle, so this ω is at or above its optimum (where\n * SOR converges at the rate ω − 1). The system (each member's neighbor count times its ratio minus its neighbors') is\n * symmetric positive definite, so SOR converges for every ω in (0, 2) (Ostrowski–Reich). 2.22.0 used ω = 1.8 for every region:\n * 5,728 sweeps on a 260 × 260 region against about 400 (docs/DISPLAY_VIEW.md).\n */\nexport function neighborHighlightOmega(a: number, b: number): number {\n const rho = (Math.cos(Math.PI / (a + 1)) + Math.cos(Math.PI / (b + 1))) / 2;\n return 2 / (1 + Math.sqrt(Math.max(0, 1 - rho * rho)));\n}\n\nexport interface NeighborHighlightReport {\n method: \"ring-average\" | \"harmonic-interpolation\";\n /** Clipped pixels rebuilt, and the clipped regions. */\n reconstructedPixelCount: number;\n regionCount: number;\n /** Full method: the largest number of relaxation sweeps a region needed, and whether every region met the tolerance. */\n iterations: number;\n converged: boolean;\n}\n\n/**\n * The region ratios of an image: per pixel the ratios ρ its rebuild uses (`ratios`, 3 per pixel; for an unclipped pixel its own),\n * and which pixels are clipped. `clippedAt(i)` tells whether pixel i is clipped; `valueAt(i, out)` writes pixel i's u.\n * Pixels are i = y·width + x.\n */\nexport function neighborHighlightRatios(width: number, height: number, clippedAt: (i: number) => boolean, valueAt: (i: number, out: Float64Array) => void, fast: boolean):\n { clipped: Uint8Array; ratios: Float64Array; regionCount: number; iterations: number; converged: boolean } {\n const n = width * height, clipped = new Uint8Array(n), unknown = new Uint8Array(n), ratios = new Float64Array(3 * n), u = new Float64Array(3), D = NEIGHBOR_HIGHLIGHT_MARGIN;\n for (let i = 0; i < n; i++) if (clippedAt(i)) clipped[i] = 1;\n // The clipped pixels widened by the margin (a separable dilation).\n const rows = new Uint8Array(n);\n for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) if (clipped[y * width + x] === 1) rows.fill(1, y * width + Math.max(0, x - D), y * width + Math.min(width, x + D + 1));\n for (let x = 0; x < width; x++) for (let y = 0; y < height; y++) if (rows[y * width + x] === 1) for (let yy = Math.max(0, y - D); yy <= Math.min(height - 1, y + D); yy++) unknown[yy * width + x] = 1;\n for (let i = 0; i < n; i++) {\n if (unknown[i] === 1) continue;\n valueAt(i, u);\n const sum = u[0]! + u[1]! + u[2]!;\n if (sum > 0) { ratios[3 * i] = u[0]! / sum; ratios[3 * i + 1] = u[1]! / sum; ratios[3 * i + 2] = u[2]! / sum; }\n else { ratios[3 * i] = 1 / 3; ratios[3 * i + 1] = 1 / 3; ratios[3 * i + 2] = 1 / 3; }\n }\n const label = new Int32Array(n).fill(-1), stamp = new Int32Array(n).fill(-1), queue = new Int32Array(n);\n let regionCount = 0, iterations = 0, converged = true;\n for (let start = 0; start < n; start++) {\n if (unknown[start] === 0 || label[start]! >= 0) continue;\n // The region (8-connected), breadth first.\n const region = regionCount++;\n let head = 0, tail = 0;\n queue[tail++] = start; label[start] = region;\n while (head < tail) {\n const p = queue[head++]!, px = p % width, py = (p - px) / width;\n for (let dy = -1; dy <= 1; dy++) for (let dx = -1; dx <= 1; dx++) {\n const x = px + dx, y = py + dy;\n if (x < 0 || y < 0 || x >= width || y >= height) continue;\n const q = y * width + x;\n if (unknown[q] === 1 && label[q]! < 0) { label[q] = region; queue[tail++] = q; }\n }\n }\n // Fast: the mean ratios over the ring (each unclipped pixel once).\n let r0 = 0, r1 = 0, r2 = 0, count = 0;\n const R = NEIGHBOR_HIGHLIGHT_RING;\n for (let k = 0; k < tail; k++) {\n const p = queue[k]!, px = p % width, py = (p - px) / width;\n for (let y = Math.max(0, py - R); y <= Math.min(height - 1, py + R); y++) for (let x = Math.max(0, px - R); x <= Math.min(width - 1, px + R); x++) {\n const q = y * width + x;\n if (unknown[q] === 1 || stamp[q] === region) continue;\n stamp[q] = region; r0 += ratios[3 * q]!; r1 += ratios[3 * q + 1]!; r2 += ratios[3 * q + 2]!; count++;\n }\n }\n const m0 = count > 0 ? r0 / count : 1 / 3, m1 = count > 0 ? r1 / count : 1 / 3, m2 = count > 0 ? r2 / count : 1 / 3;\n for (let k = 0; k < tail; k++) { const p = queue[k]!; ratios[3 * p] = m0; ratios[3 * p + 1] = m1; ratios[3 * p + 2] = m2; }\n if (fast || count === 0) continue;\n // Full: successive over-relaxation of the discrete Laplace equation over the region, in the region's breadth-first order.\n const { tolerance, maximumIterations } = NEIGHBOR_HIGHLIGHT_SOR;\n let x0 = width, x1 = -1, y0 = height, y1 = -1;\n for (let k = 0; k < tail; k++) { const p = queue[k]!, px = p % width, py = (p - px) / width; x0 = Math.min(x0, px); x1 = Math.max(x1, px); y0 = Math.min(y0, py); y1 = Math.max(y1, py); }\n const omega = neighborHighlightOmega(x1 - x0 + 1, y1 - y0 + 1);\n let sweep = 0, change = Infinity;\n while (sweep < maximumIterations && change > tolerance) {\n change = 0; sweep++;\n for (let k = 0; k < tail; k++) {\n const p = queue[k]!, px = p % width, py = (p - px) / width;\n let a0 = 0, a1 = 0, a2 = 0, m = 0;\n for (let d = 0; d < 4; d++) {\n const x = px + (d === 0 ? -1 : d === 1 ? 1 : 0), y = py + (d === 2 ? -1 : d === 3 ? 1 : 0);\n if (x < 0 || y < 0 || x >= width || y >= height) continue;\n const q = y * width + x;\n a0 += ratios[3 * q]!; a1 += ratios[3 * q + 1]!; a2 += ratios[3 * q + 2]!; m++;\n }\n if (m === 0) continue;\n for (let c = 0; c < 3; c++) {\n const old = ratios[3 * p + c]!, target = (c === 0 ? a0 : c === 1 ? a1 : a2) / m, next = old + omega * (target - old);\n ratios[3 * p + c] = next;\n const delta = Math.abs(next - old);\n if (delta > change) change = delta;\n }\n }\n }\n iterations = Math.max(iterations, sweep);\n if (change > tolerance) converged = false;\n }\n return { clipped, ratios, regionCount, iterations, converged };\n}\n\n/**\n * The rebuild of one clipped pixel (step 4) into b, with its slopes ∂b/∂c (row-major 3 × 3, a.e.) when `slopes` is given.\n * `c` are the normalized camera channels, `g` the white-balance gains, `rho` the pixel's ratios.\n */\nexport function rebuildClippedPixel(c0: number, c1: number, c2: number, g: ArrayLike<number>, rho: ArrayLike<number>, b: Float64Array | number[], slopes?: Float64Array): void {\n const H = NEIGHBOR_HIGHLIGHT_THRESHOLD, u0 = c0 * g[0]!, u1 = c1 * g[1]!, u2 = c2 * g[2]!;\n const k0 = c0 < H, k1 = c1 < H, k2 = c2 < H;\n if (slopes) slopes.fill(0);\n if (k0 && k1 && k2) {\n b[0] = u0; b[1] = u1; b[2] = u2;\n if (slopes) { slopes[0] = g[0]!; slopes[4] = g[1]!; slopes[8] = g[2]!; }\n return;\n }\n const r0 = rho[0]!, r1 = rho[1]!, r2 = rho[2]!;\n if (!k0 && !k1 && !k2) {\n const q0 = r0 > 0 ? u0 / r0 : 0, q1 = r1 > 0 ? u1 / r1 : 0, q2 = r2 > 0 ? u2 / r2 : 0, m = q0 > q1 ? (q0 > q2 ? 0 : 2) : (q1 > q2 ? 1 : 2), s = m === 0 ? q0 : m === 1 ? q1 : q2;\n b[0] = s * r0; b[1] = s * r1; b[2] = s * r2;\n if (slopes) { const rm = m === 0 ? r0 : m === 1 ? r1 : r2; if (rm > 0) for (let k = 0; k < 3; k++) slopes[k * 3 + m] = (k === 0 ? r0 : k === 1 ? r1 : r2) * g[m]! / rm; }\n return;\n }\n const su = (k0 ? u0 : 0) + (k1 ? u1 : 0) + (k2 ? u2 : 0), sr = (k0 ? r0 : 0) + (k1 ? r1 : 0) + (k2 ? r2 : 0), s = sr > 0 ? su / sr : 0;\n for (let k = 0; k < 3; k++) {\n const kept = k === 0 ? k0 : k === 1 ? k1 : k2, uk = k === 0 ? u0 : k === 1 ? u1 : u2, rk = k === 0 ? r0 : k === 1 ? r1 : r2;\n if (kept) { b[k] = uk; if (slopes) slopes[k * 4] = g[k]!; continue; }\n const estimate = s * rk;\n if (estimate > uk) {\n b[k] = estimate;\n if (slopes && sr > 0) for (let j = 0; j < 3; j++) if (j === 0 ? k0 : j === 1 ? k1 : k2) slopes[k * 3 + j] = rk * g[j]! / sr;\n } else { b[k] = uk; if (slopes) slopes[k * 4] = g[k]!; }\n }\n}\n\n/**\n * Rebuilds the clipped pixels of a white-balanced image u (3 per pixel, in place; becomes b), with the normalized channels\n * c = u/g deciding which channels are clipped.\n */\nexport function reconstructHighlightsFromNeighbors(u: Float64Array, width: number, height: number, gains: ArrayLike<number>, fast: boolean): NeighborHighlightReport {\n const H = NEIGHBOR_HIGHLIGHT_THRESHOLD, g0 = gains[0]!, g1 = gains[1]!, g2 = gains[2]!;\n const field = neighborHighlightRatios(width, height, (i) => u[3 * i]! / g0 >= H || u[3 * i + 1]! / g1 >= H || u[3 * i + 2]! / g2 >= H,\n (i, out) => { out[0] = u[3 * i]!; out[1] = u[3 * i + 1]!; out[2] = u[3 * i + 2]!; }, fast);\n const b = new Float64Array(3);\n let rebuilt = 0;\n for (let i = 0; i < width * height; i++) {\n if (field.clipped[i] === 0) continue;\n rebuildClippedPixel(u[3 * i]! / g0, u[3 * i + 1]! / g1, u[3 * i + 2]! / g2, gains, field.ratios.subarray(3 * i, 3 * i + 3), b);\n u[3 * i] = b[0]!; u[3 * i + 1] = b[1]!; u[3 * i + 2] = b[2]!;\n rebuilt++;\n }\n return { method: fast ? \"ring-average\" : \"harmonic-interpolation\", reconstructedPixelCount: rebuilt, regionCount: field.regionCount, iterations: field.iterations, converged: field.converged };\n}\n"]}
|
package/dist/core/version.d.ts
CHANGED
package/dist/core/version.js
CHANGED
package/dist/core/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/core/version.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAiB,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Version of the engine release. Since 1.0.1 it equals the npm package version.\n *\n * New captures and plans record this version as their creator. Archived records keep the\n * version they were made with. Proof-of-concept (POC), schema and model contracts have their\n * own versions. Release checks confirm it matches package.json and the packed package.\n * @see docs/RELEASE_1_0_1.md\n */\nexport const ENGINE_API_VERSION = \"2.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/core/version.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAiB,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Version of the engine release. Since 1.0.1 it equals the npm package version.\n *\n * New captures and plans record this version as their creator. Archived records keep the\n * version they were made with. Proof-of-concept (POC), schema and model contracts have their\n * own versions. Release checks confirm it matches package.json and the packed package.\n * @see docs/RELEASE_1_0_1.md\n */\nexport const ENGINE_API_VERSION = \"2.23.0\" as const;\n"]}
|
|
@@ -39,6 +39,11 @@ export interface DisplayViewCoupledRendering {
|
|
|
39
39
|
bindView?(setup: DisplayViewSetup): void;
|
|
40
40
|
/** #602: the real pixel (native site coordinates) whose moments `chain` computes next. */
|
|
41
41
|
at?(x: number, y: number): void;
|
|
42
|
+
/**
|
|
43
|
+
* #605: the ratios ρ that `chain` uses at real pixel (x, y) (as `at` selects them) into out, or −1 in out[0] where the pixel
|
|
44
|
+
* takes none (the highlight step then keeps u): the GPU kernels read them from the host.
|
|
45
|
+
*/
|
|
46
|
+
ratioAt?(x: number, y: number, out: Float64Array): void;
|
|
42
47
|
/** #602: regions measured, and regions whose search stopped at the size cap (their ratios from the part found). */
|
|
43
48
|
readonly neighborRegions: {
|
|
44
49
|
measured: number;
|
|
@@ -30,7 +30,7 @@ import { portablePow } from "../core/portable-math.js";
|
|
|
30
30
|
import { CLIP_REACH_SIGMA, GL, bigPhi, phi } from "./display-view-normal.js";
|
|
31
31
|
import { desaturateToLuminance, SDR_LUMINANCE_WEIGHTS } from "../output/sdr-rendering.js";
|
|
32
32
|
import { RAW_HIGHLIGHT_RECONSTRUCTION_START } from "../color/sensor-color-development.js";
|
|
33
|
-
import { NEIGHBOR_HIGHLIGHT_MARGIN, NEIGHBOR_HIGHLIGHT_RING, NEIGHBOR_HIGHLIGHT_SOR, NEIGHBOR_HIGHLIGHT_THRESHOLD, rebuildClippedPixel } from "../color/neighbor-highlight-reconstruction.js";
|
|
33
|
+
import { NEIGHBOR_HIGHLIGHT_MARGIN, NEIGHBOR_HIGHLIGHT_RING, NEIGHBOR_HIGHLIGHT_SOR, NEIGHBOR_HIGHLIGHT_THRESHOLD, neighborHighlightOmega, rebuildClippedPixel } from "../color/neighbor-highlight-reconstruction.js";
|
|
34
34
|
/**
|
|
35
35
|
* Internal (exported for tests). The n-point Gauss–Hermite rule of the standard normal: Σ w_i f(x_i) ≈ E[f(Z)], Z ~ N(0, 1).
|
|
36
36
|
* The nodes are the eigenvalues of the Jacobi matrix of the orthonormal Hermite polynomials (zero diagonal, off-diagonal √k),
|
|
@@ -311,7 +311,7 @@ export function createDisplayViewCoupledRendering(choice, gains, clipLevel, matr
|
|
|
311
311
|
// #602: the region ratios of the bound view, found on demand (noise-free channels; see the module notes of the capture's method).
|
|
312
312
|
let rho = null, view = null;
|
|
313
313
|
const ratioOf = new Map(), channelMemo = new Map(), neighborRegions = { measured: 0, capped: 0 };
|
|
314
|
-
const H = NEIGHBOR_HIGHLIGHT_THRESHOLD, limit = choice.fast ? DISPLAY_VIEW_NEIGHBOR_REGION_LIMIT.fast : DISPLAY_VIEW_NEIGHBOR_REGION_LIMIT.full;
|
|
314
|
+
const H = NEIGHBOR_HIGHLIGHT_THRESHOLD, limit = choice.fast ? DISPLAY_VIEW_NEIGHBOR_REGION_LIMIT.fast : DISPLAY_VIEW_NEIGHBOR_REGION_LIMIT.full, tile = Math.round(Math.sqrt(limit));
|
|
315
315
|
function channelsAt(x, y) {
|
|
316
316
|
const key = y * 1048576 + x;
|
|
317
317
|
let v = channelMemo.get(key);
|
|
@@ -353,27 +353,40 @@ export function createDisplayViewCoupledRendering(choice, gains, clipLevel, matr
|
|
|
353
353
|
const key = y * 1048576 + x, known = ratioOf.get(key);
|
|
354
354
|
if (known)
|
|
355
355
|
return known;
|
|
356
|
-
// The region (8-connected), breadth first
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
for (let
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
356
|
+
// The region (8-connected), breadth first. #605: a region above the cap is solved per tile of `tile` × `tile` pixels (the
|
|
357
|
+
// tile area is the cap): its part in the pixel's tile, which does not depend on where the render reached the region.
|
|
358
|
+
const search = (tiled) => {
|
|
359
|
+
const members = [key], index = new Map([[key, 0]]), tx = Math.floor(x / tile), ty = Math.floor(y / tile);
|
|
360
|
+
let capped = false;
|
|
361
|
+
for (let head = 0; head < members.length && !capped; head++) {
|
|
362
|
+
const p = members[head], px = p % 1048576, py = (p - px) / 1048576;
|
|
363
|
+
for (let dy = -1; dy <= 1; dy++)
|
|
364
|
+
for (let dx = -1; dx <= 1; dx++) {
|
|
365
|
+
const qx = px + dx, qy = py + dy, q = qy * 1048576 + qx;
|
|
366
|
+
if (!inside(qx, qy) || index.has(q) || (tiled && (Math.floor(qx / tile) !== tx || Math.floor(qy / tile) !== ty)) || !isUnknown(qx, qy))
|
|
367
|
+
continue;
|
|
368
|
+
if (members.length >= limit) {
|
|
369
|
+
capped = true;
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
index.set(q, members.length);
|
|
373
|
+
members.push(q);
|
|
369
374
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
375
|
+
}
|
|
376
|
+
return { members, index, capped };
|
|
377
|
+
};
|
|
378
|
+
let found = search(false);
|
|
374
379
|
neighborRegions.measured++;
|
|
375
|
-
if (capped)
|
|
380
|
+
if (found.capped) {
|
|
376
381
|
neighborRegions.capped++;
|
|
382
|
+
found = search(true);
|
|
383
|
+
}
|
|
384
|
+
const { members, index } = found;
|
|
385
|
+
// #605: the members in raster order, so the ratios do not depend on which pixel found the region (a region render, the GPU
|
|
386
|
+
// host's band order and the whole view agree bit for bit).
|
|
387
|
+
members.sort((a, b) => a - b);
|
|
388
|
+
for (let i = 0; i < members.length; i++)
|
|
389
|
+
index.set(members[i], i);
|
|
377
390
|
// Fast: the ring's mean ratios (unclipped pixels within the ring width, each once).
|
|
378
391
|
const R = NEIGHBOR_HIGHLIGHT_RING, seen = new Set(), r = new Float64Array(3), mean = new Float64Array(3);
|
|
379
392
|
let count = 0;
|
|
@@ -405,7 +418,16 @@ export function createDisplayViewCoupledRendering(choice, gains, clipLevel, matr
|
|
|
405
418
|
values.set(mean, 3 * i);
|
|
406
419
|
if (!choice.fast && count > 0) {
|
|
407
420
|
// Full: successive over-relaxation of the discrete Laplace equation, Dirichlet values from the unclipped 4-neighbors.
|
|
408
|
-
const {
|
|
421
|
+
const { tolerance, maximumIterations } = NEIGHBOR_HIGHLIGHT_SOR, boundary = new Map();
|
|
422
|
+
let bx0 = Infinity, bx1 = -Infinity, by0 = Infinity, by1 = -Infinity;
|
|
423
|
+
for (const p of members) {
|
|
424
|
+
const px = p % 1048576, py = (p - px) / 1048576;
|
|
425
|
+
bx0 = Math.min(bx0, px);
|
|
426
|
+
bx1 = Math.max(bx1, px);
|
|
427
|
+
by0 = Math.min(by0, py);
|
|
428
|
+
by1 = Math.max(by1, py);
|
|
429
|
+
}
|
|
430
|
+
const omega = neighborHighlightOmega(bx1 - bx0 + 1, by1 - by0 + 1);
|
|
409
431
|
let change = Infinity;
|
|
410
432
|
for (let sweep = 0; sweep < maximumIterations && change > tolerance; sweep++) {
|
|
411
433
|
change = 0;
|
|
@@ -465,7 +487,20 @@ export function createDisplayViewCoupledRendering(choice, gains, clipLevel, matr
|
|
|
465
487
|
rho = own;
|
|
466
488
|
}
|
|
467
489
|
}
|
|
490
|
+
function ratioAt(x, y, out) {
|
|
491
|
+
at(x, y);
|
|
492
|
+
if (rho)
|
|
493
|
+
out.set(rho);
|
|
494
|
+
else
|
|
495
|
+
out[0] = -1;
|
|
496
|
+
}
|
|
497
|
+
let boundSignal = null;
|
|
468
498
|
function bindView(setup) {
|
|
499
|
+
// #605: a render of the same signal keeps the regions found (their ratios depend only on the signal and the frame): the
|
|
500
|
+
// host's recomputation of flagged pixels renders many small regions of one view.
|
|
501
|
+
if (view && setup.signal === boundSignal)
|
|
502
|
+
return;
|
|
503
|
+
boundSignal = setup.signal;
|
|
469
504
|
// The noise-free mosaic (expected normalized site values clipped at white, read reflect-101 at the raster's edges) through the
|
|
470
505
|
// bilinear kernels: the expected camera channels of each real pixel (the capture's own demosaic for AHD captures is approximated).
|
|
471
506
|
const W = setup.nativeWidth, Hh = setup.nativeHeight, k = setup.readout.map((r) => r.perElectron), dark = setup.readout.map((r) => r.darkElectrons);
|
|
@@ -593,6 +628,6 @@ export function createDisplayViewCoupledRendering(choice, gains, clipLevel, matr
|
|
|
593
628
|
}
|
|
594
629
|
return !(desaturate && reachesTop);
|
|
595
630
|
}
|
|
596
|
-
return { luminanceTone, reconstruct, neighbors, ...(neighbors ? { bindView, at } : {}), neighborRegions, desaturate, choice, chainPoints: chainRule.x.length, chainRule, luminanceRule: hermite8, ratioAtZero: ratioZero, pixel, chain, reconstructInReach, tone };
|
|
631
|
+
return { luminanceTone, reconstruct, neighbors, ...(neighbors ? { bindView, at, ratioAt } : {}), neighborRegions, desaturate, choice, chainPoints: chainRule.x.length, chainRule, luminanceRule: hermite8, ratioAtZero: ratioZero, pixel, chain, reconstructInReach, tone };
|
|
597
632
|
}
|
|
598
633
|
//# sourceMappingURL=display-view-rendering.js.map
|