@photivra/engine 2.15.0 → 2.17.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 +102 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +38 -0
- package/dist/camera/lens-projection.d.ts +5 -0
- package/dist/camera/lens-projection.js +10 -0
- package/dist/camera/lens-projection.js.map +1 -1
- package/dist/capture/native-environment-lean.js +1 -1
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-raw-development.d.ts +15 -0
- package/dist/capture/native-raw-development.js +12 -6
- package/dist/capture/native-raw-development.js.map +1 -1
- package/dist/capture/raw-development-kernel.d.ts +10 -3
- package/dist/capture/raw-development-kernel.js +25 -6
- package/dist/capture/raw-development-kernel.js.map +1 -1
- package/dist/core/internal-radiance-evaluator.d.ts +5 -2
- package/dist/core/internal-radiance-evaluator.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/equipment/generic-lens-catalogue.d.ts +227 -0
- package/dist/equipment/generic-lens-catalogue.js +243 -0
- package/dist/equipment/generic-lens-catalogue.js.map +1 -0
- package/dist/facade/defocus-bokeh-zones.d.ts +33 -0
- package/dist/facade/defocus-bokeh-zones.js +53 -0
- package/dist/facade/defocus-bokeh-zones.js.map +1 -0
- package/dist/facade/defocus-image-space-provider.d.ts +118 -0
- package/dist/facade/defocus-image-space-provider.js +448 -0
- package/dist/facade/defocus-image-space-provider.js.map +1 -0
- package/dist/facade/diffraction-provider.d.ts +45 -0
- package/dist/facade/diffraction-provider.js +120 -14
- package/dist/facade/diffraction-provider.js.map +1 -1
- package/dist/facade/display-view-gpu-session.js +4 -0
- package/dist/facade/display-view-gpu-session.js.map +1 -1
- package/dist/facade/display-view-gpu.d.ts +10 -0
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view-lens-signal.d.ts +30 -0
- package/dist/facade/display-view-lens-signal.js +427 -0
- package/dist/facade/display-view-lens-signal.js.map +1 -0
- package/dist/facade/display-view.d.ts +21 -0
- package/dist/facade/display-view.js +66 -8
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/expected-signal-setup.d.ts +7 -0
- package/dist/facade/expected-signal-setup.js +12 -2
- package/dist/facade/expected-signal-setup.js.map +1 -1
- package/dist/facade/expected-signal.d.ts +8 -0
- package/dist/facade/expected-signal.js +150 -0
- package/dist/facade/expected-signal.js.map +1 -1
- package/dist/facade/generic-lens-capture.d.ts +6 -0
- package/dist/facade/generic-lens-capture.js +8 -0
- package/dist/facade/generic-lens-capture.js.map +1 -0
- package/dist/facade/large-defocus-lattice.d.ts +39 -0
- package/dist/facade/large-defocus-lattice.js +64 -0
- package/dist/facade/large-defocus-lattice.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +5 -0
- package/dist/facade/scene-radiance.js +5 -2
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +148 -6
- package/dist/facade/simulate-capture.js +521 -88
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.js +29 -19
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +2 -9
- package/dist/gpu/display-view-quality-gpu.js +63 -13
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.d.ts +2 -0
- package/dist/gpu/display-view-speed-gpu.js +47 -16
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/image-kernel-accelerator.js +3 -0
- package/dist/gpu/image-kernel-accelerator.js.map +1 -1
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +4 -0
- package/dist/gpu/wgsl-display-view-quality-kernel.js +53 -2
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +15 -0
- package/dist/gpu/wgsl-display-view-speed-kernel.js +42 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/optics/defocus-bokeh-kernel.d.ts +207 -0
- package/dist/optics/defocus-bokeh-kernel.js +380 -0
- package/dist/optics/defocus-bokeh-kernel.js.map +1 -0
- package/dist/optics/defocus-disc-kernel.d.ts +44 -21
- package/dist/optics/defocus-disc-kernel.js +47 -25
- package/dist/optics/defocus-disc-kernel.js.map +1 -1
- package/dist/optics/generic-lens-psf.d.ts +68 -0
- package/dist/optics/generic-lens-psf.js +337 -0
- package/dist/optics/generic-lens-psf.js.map +1 -0
- package/dist/optics/illumination-vignetting.d.ts +6 -0
- package/dist/optics/illumination-vignetting.js +24 -7
- package/dist/optics/illumination-vignetting.js.map +1 -1
- package/dist/optics/sensor-environment-query.d.ts +37 -0
- package/dist/optics/sensor-environment-query.js +58 -19
- package/dist/optics/sensor-environment-query.js.map +1 -1
- package/dist/optics/site-kernel-runs.d.ts +77 -0
- package/dist/optics/site-kernel-runs.js +200 -0
- package/dist/optics/site-kernel-runs.js.map +1 -0
- package/dist/output/generic-lens-corrections.d.ts +24 -0
- package/dist/output/generic-lens-corrections.js +51 -0
- package/dist/output/generic-lens-corrections.js.map +1 -0
- package/dist/processing/development-detail.d.ts +132 -0
- package/dist/processing/development-detail.js +325 -0
- package/dist/processing/development-detail.js.map +1 -0
- package/docs/AGENT_GUIDE.md +1 -0
- package/docs/API_REFERENCE.md +54 -1
- package/docs/QUICK_START.md +444 -26
- package/docs/USAGE.md +71 -8
- package/docs/api/capture-native-raw-development.md +16 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-lens-catalogue.md +281 -0
- package/docs/api/exports.json +162 -2
- package/docs/api/facade-simulate-capture.md +151 -5
- package/docs/api/optics-defocus-bokeh-kernel.md +145 -0
- package/docs/api/optics-defocus-disc-kernel.md +25 -17
- package/docs/api/optics-sensor-environment-query.md +6 -0
- package/docs/api/output-generic-lens-corrections.md +39 -0
- package/llms.txt +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display-view-lens-signal.js","sourceRoot":"","sources":["../../src/facade/display-view-lens-signal.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * The display view's expected signal with a lens field mapping (`lens.projection`, `lens.distortion`), `lens.vignetting` or\n * camera rotation (#563), in focus and with `lens.defocus` out of focus. Loaded on demand (a dynamic import in `runCapture`),\n * so a display view without these options, and a bundle that never asks for them, does not load it.\n *\n * What it computes. The capture's environment chain forms, for site (i, j) of CFA channel c,\n * μ_c(i, j) = Σ_o w_o · (1/T) Σ_t Σ_λ A_c(λ) Σ_k K_λ(k) · F(s) · L(D_t(s), λ), s = q_o(i, j) − k·p,\n * with q_o the query point of offset o (pixel-aperture node minus anti-aliasing split), K_λ the site kernel (diffraction, the\n * defocus disc or both; a single unit tap without them), D_t the scene ray of sensor point s at temporal midpoint t (inverse\n * distortion, the declared projection, the camera rotation at t), F = T·A its field factor (vignetting throughput × distortion\n * area factor) and A_c(λ) the electrons per unit spectral radiance on the axis (the display view's channel response, ideal\n * optics). In focus with a kernel this is the environment PSF quadrature (the field factor applied once at the source point,\n * before the PSF spreads the light); out of focus it is #548's image-space disc, the same sum in another order\n * (`defocus-image-space-provider.ts`); without a kernel it is the environment's own per-query sum. Only the scene access changes:\n * the readout, the estimators, the demosaic and the development run unchanged on these site values.\n *\n * Scene points. Without a kernel each query point is formed with the environment's own arithmetic (the site centre, aperture node\n * and split offset of `native-environment-lean.ts`), then `lookOf` (the environment's mapping, rotation and field factor,\n * #548) and the planar provider's plane-point arithmetic, so a point exactly on a chart boundary resolves as in the capture.\n * With a kernel the sources are the site lattice of each fractional offset, with #548's lattice formula. Kernels, materials and\n * per-material sums are the display view's own tables (`displayViewSignalTables`), shared with the rectilinear path.\n *\n * Caches (memory only, never values): site values in a ring of native rows across windows, and with a kernel each lattice\n * point's material (or radiance at each node) and field factor per lattice group and temporal midpoint, in a two-dimensional\n * ring tagged with the point, sized from the window and capped at LATTICE_CACHE_LIMIT entries (beyond it, points are\n * evaluated as they are read).\n *\n * Large defocus kernels (#564, `input.largeKernel`, radius above 64 sites). The image-space disc D is the same at every lattice\n * group, spectral node and temporal midpoint, so it commutes with those sums as in the rectilinear signal (`expected-signal.ts`):\n * μ_c(x) = Σ_s D(s)·E_c(x − s), with E_c(x) the sum above through the in-focus kernels (each node's diffraction kernel, or a unit\n * tap) at site position x for channel c, whatever x's own channel. E is computed in fixed 64-site tiles (all three channels, each\n * group's lattice points mapped once per tile and midpoint), and D ⊛ E_c by runs (`site-kernel-runs.ts`) in fixed 128-site tiles,\n * each site taking its own channel: every value depends only on its site, so regions and parts equal the whole view.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { createSiteKernelRunsLattice, type SiteKernelRunsRowPattern } from \"../optics/site-kernel-runs.js\";\nimport type { PreparedDefocusImageSpaceGeometry } from \"./defocus-image-space-provider.js\";\nimport { displayViewSignalTables, type DisplayViewExpectedSignal, type DisplayViewExpectedSignalInput } from \"./expected-signal.js\";\n\n/** What the lens signal needs from the resolved request. */\nexport interface DisplayViewLensSetup {\n geometry: PreparedDefocusImageSpaceGeometry;\n /** Temporal midpoints, seconds from exposure start: (i + 0.5)·shutter/T with camera rotation, [0] without. */\n times: readonly number[];\n /** The planar provider's plane distance and frame-unit scale. */\n distanceM: number;\n metresPerFrameUnit: number;\n pitch: number;\n imagingArea: { widthMm: number; heightMm: number };\n boxSamples: number;\n /** Anti-aliasing split spots (or one zero spot), in the order of the expected signal's offsets within each aperture node. */\n spots: readonly { offsetMicrometers: { x: number; y: number } }[];\n}\n\n/** Largest lattice cache, in entries over all lattice groups and temporal midpoints (times the spectral nodes for radiance scenes). */\nconst LATTICE_CACHE_LIMIT = 1 << 22;\n\nconst pow2 = (n: number): number => { let p = 1; while (p < n) p *= 2; return p; };\n\n/**\n * Checks that the mapping and the vignetting profile cover the farthest source point the view reads, (W/2 + reachSites, H/2 + reachSites)\n * sites from the axis at each corner (reachSites: the kernel radius plus the largest query offset, less the half site to the outer site\n * centre), and returns the factory of the view's expected signal for this request.\n */\nexport function prepareDisplayViewLensSignal(lens: DisplayViewLensSetup, nativeWidth: number, nativeHeight: number, reachSites: number, options: string):\n (input: DisplayViewExpectedSignalInput, spanColumns?: number) => DisplayViewExpectedSignal {\n const xMm = (nativeWidth / 2 + reachSites) * lens.pitch / 1000, yMm = (nativeHeight / 2 + reachSites) * lens.pitch / 1000;\n for (const t of lens.times) for (const [x, y] of [[-xMm, -yMm], [xMm, -yMm], [-xMm, yMm], [xMm, yMm]] as const) {\n try { if (!(lens.geometry.lookOf(x, y, t).z > 0)) throw new InvalidConfigurationError(\"its ray does not point toward the scene plane.\"); } catch (error) {\n throw new InvalidConfigurationError(\"simulateDisplayView with \" + options + \" reads the scene through the lens up to \" + (reachSites + 0.5) + \" sites beyond the native \" +\n \"raster's outer site centres (the kernel radius and the query offsets), and there (\" + Math.hypot(x, y).toFixed(3) + \" mm from the axis) \" + (error as Error).message);\n }\n }\n return (input, spanColumns = Infinity) => createLensSignal(lens, input, spanColumns);\n}\n\nfunction createLensSignal(lens: DisplayViewLensSetup, input: DisplayViewExpectedSignalInput, spanColumns: number): DisplayViewExpectedSignal {\n const W = input.nativeWidth, H = input.nativeHeight, nodes = input.wavelengthsNm.length, T = lens.times.length, times = lens.times;\n const { geometry, distanceM: distance, metresPerFrameUnit: scale, pitch, imagingArea } = lens;\n const mmPerSite = pitch / 1000, scene = input.scene, offsets = input.offsets, A = input.electronsPerRadiance, channelAt = input.channelAt;\n const materials = scene.kind === \"materials\" ? scene : undefined, radianceAt = scene.kind === \"radiance\" ? scene.radianceAt : undefined;\n const { reflectance, spectralIndex, neutralDirect, spectralDirect, groups } = displayViewSignalTables(input);\n const kernels = input.kernels, R = kernels ? kernels.radius : 0;\n let lookups = 0;\n // The plane point (frame units) and field factor of native sensor point (x, y) mm at time t: the environment's mapping (lookOf) and\n // the planar provider's own arithmetic for the outgoing direction −look.\n let pu = 0, pv = 0, pf = 0;\n const map = (xMm: number, yMm: number, t: number): void => {\n const look = geometry.lookOf(xMm, yMm, t);\n if (!(look.z > 0)) throw new InvalidConfigurationError(\"simulateDisplayView: a query ray does not point toward the scene plane.\");\n const s = distance / look.z;\n pu = look.x * s / scale; pv = look.y * s / scale; pf = look.factor;\n };\n const materialOf = (m: number): number => { if (spectralIndex[m] === undefined) throw new InvalidConfigurationError(\"Unknown chart material.\"); return m; };\n // Without a kernel: the environment's query point of offset o of site (x, y) (native-environment-lean.ts, as buildExpectedSignalInput's queryPoint).\n const box = lens.boxSamples, siteWidthMm = pitch / 1000;\n const phases = offsets.map((_, o) => {\n const node = Math.floor(o / lens.spots.length), spot = lens.spots[o % lens.spots.length]!.offsetMicrometers;\n return { xPhase: (node % box + 0.5) / box, yPhase: (Math.floor(node / box) + 0.5) / box, aaX: spot.x / 1000, aaY: spot.y / 1000 };\n });\n function directSite(x: number, y: number): number {\n const c = channelAt(x, y), centerX = -imagingArea.widthMm / 2 + (pitch / 2 + x * pitch + 0) / 1000, centerY = -imagingArea.heightMm / 2 + (pitch / 2 + y * pitch + 0) / 1000;\n let total = 0;\n for (let ti = 0; ti < T; ti++) {\n let sum = 0;\n for (let o = 0; o < offsets.length; o++) {\n const node = phases[o]!;\n map((centerX - siteWidthMm / 2 + node.xPhase * siteWidthMm) - node.aaX, (centerY - siteWidthMm / 2 + node.yPhase * siteWidthMm) - node.aaY, times[ti]!);\n let value: number;\n if (materials) {\n const m = materialOf(materials.materialAt(pu, pv)), si = spectralIndex[m]!;\n value = si < 0 ? reflectance[m]! * neutralDirect[c]! : spectralDirect[c]![si]!; lookups++;\n } else { value = 0; for (let n = 0; n < nodes; n++) value += A[c]![n]! * radianceAt!(pu, pv, input.wavelengthsNm[n]!); lookups += nodes; }\n sum += offsets[o]!.weight * (pf * value);\n }\n total += sum;\n }\n return total / T;\n }\n // With a kernel: lattice point (p, q) of group g at time t, #548's lattice formula, cached in a ring tagged with (p, q).\n const G = groups.length, slots = G * T, per = materials ? 1 : nodes;\n let cacheRows = 0, cacheCols = 0, tagQ = new Int32Array(0), tagP = new Int32Array(0), cacheMaterial = new Int32Array(0), cacheFactor = new Float64Array(0), cacheRadiance = new Float64Array(0);\n const radiance = new Float64Array(nodes);\n let lm = 0, lf = 0;\n function lattice(g: number, ti: number, p: number, q: number): void {\n let k = -1;\n if (cacheRows > 0) {\n k = ((g * T + ti) * cacheRows + (q & (cacheRows - 1))) * cacheCols + (p & (cacheCols - 1));\n if (tagQ[k] === q && tagP[k] === p) {\n lf = cacheFactor[k]!;\n if (materials) lm = cacheMaterial[k]!; else for (let n = 0; n < nodes; n++) radiance[n] = cacheRadiance[k * nodes + n]!;\n return;\n }\n }\n const group = groups[g]!;\n map((p + 0.5 + group.fx - W / 2) * mmPerSite, (q + 0.5 + group.fy - H / 2) * mmPerSite, times[ti]!);\n lf = pf;\n if (materials) { lm = materialOf(materials.materialAt(pu, pv)); lookups++; }\n else { for (let n = 0; n < nodes; n++) radiance[n] = radianceAt!(pu, pv, input.wavelengthsNm[n]!); lookups += nodes; }\n if (k >= 0) {\n tagQ[k] = q; tagP[k] = p; cacheFactor[k] = lf;\n if (materials) cacheMaterial[k] = lm; else for (let n = 0; n < nodes; n++) cacheRadiance[k * nodes + n] = radiance[n]!;\n }\n }\n function kernelSite(x: number, y: number): number {\n const c = channelAt(x, y), rowMask = cacheRows - 1, colMask = cacheCols - 1;\n let total = 0;\n for (let ti = 0; ti < T; ti++) {\n let sum = 0;\n for (let g = 0; g < G; g++) {\n const group = groups[g]!, p0 = x + group.minIx - R, q0 = y + group.minIy - R, cw = group.cw, ch = group.ch;\n if (materials) {\n const nk = group.neutral[c]!, sk = group.spectral[c]!;\n for (let dy = 0, t = 0; dy < ch; dy++) {\n // The cache row of lattice row q (read inline: the common case is a hit).\n const q = q0 + dy, row = cacheRows > 0 ? ((g * T + ti) * cacheRows + (q & rowMask)) * cacheCols : -1;\n for (let dx = 0; dx < cw; dx++, t++) {\n const p = p0 + dx, k = row + (p & colMask);\n if (row >= 0 && tagQ[k] === q && tagP[k] === p) { lm = cacheMaterial[k]!; lf = cacheFactor[k]!; } else lattice(g, ti, p, q);\n const si = spectralIndex[lm]!;\n sum += lf * (si < 0 ? reflectance[lm]! * nk[t]! : sk[si]![t]!);\n }\n }\n } else for (let dy = 0, t = 0; dy < ch; dy++) for (let dx = 0; dx < cw; dx++, t++) {\n lattice(g, ti, p0 + dx, q0 + dy);\n let value = 0;\n for (let n = 0; n < nodes; n++) value += group.perNode[n]![c]![t]! * radiance[n]!;\n sum += lf * value;\n }\n }\n total += sum;\n }\n return total / T;\n }\n const pilotNode = input.wavelengthsNm[Math.floor(nodes / 2)]!;\n if (input.largeKernel) return createLargeLensSignal(input, inFocusLensTile, () => lookups, pilot);\n /** E_c (#564) of the native site positions [x0, x0 + T) × [y0, y0 + T) for the three channels: kernelSite's sum for each channel. */\n function inFocusLensTile(x0: number, y0: number, TS: number): Float64Array[] {\n const out = [0, 1, 2].map(() => new Float64Array(TS * TS));\n // A fixed tile reaches past the raster: positions more than the disc's radius beyond it feed no site, so they stay 0 and are never\n // mapped (the lens profiles are checked only up to the view's reach).\n const D = input.largeKernel!.radius;\n if (x0 + TS <= -D || x0 >= W + D || y0 + TS <= -D || y0 >= H + D) return out;\n if (x0 < -D || x0 + TS > W + D || y0 < -D || y0 + TS > H + D) {\n const xa = Math.max(x0, -D), xb = Math.min(x0 + TS, W + D), ya = Math.max(y0, -D), yb = Math.min(y0 + TS, H + D);\n const part = inFocusLensRect(xa, ya, xb - xa, yb - ya);\n for (let c = 0; c < 3; c++) for (let y = ya; y < yb; y++) out[c]!.set(part[c]!.subarray((y - ya) * (xb - xa), (y - ya + 1) * (xb - xa)), (y - y0) * TS + xa - x0);\n return out;\n }\n return inFocusLensRect(x0, y0, TS, TS);\n }\n /** E_c of the native site positions [x0, x0 + w) × [y0, y0 + h), row-major, for the three channels. */\n function inFocusLensRect(x0: number, y0: number, TW: number, TH: number): Float64Array[] {\n const out = [0, 1, 2].map(() => new Float64Array(TW * TH)), sum = [0, 1, 2].map(() => new Float64Array(TW * TH));\n for (let ti = 0; ti < T; ti++) {\n for (const e of sum) e.fill(0);\n for (const group of groups) {\n const cw = group.cw, ch = group.ch, gw = TW + cw - 1, gh = TH + ch - 1, p0 = x0 + group.minIx - R, q0 = y0 + group.minIy - R;\n const factor = new Float64Array(gw * gh), material = materials ? new Int32Array(gw * gh) : undefined, values = materials ? undefined : new Float64Array(gw * gh * nodes);\n for (let j = 0; j < gh; j++) for (let i = 0; i < gw; i++) {\n const k = j * gw + i;\n map((p0 + i + 0.5 + group.fx - W / 2) * mmPerSite, (q0 + j + 0.5 + group.fy - H / 2) * mmPerSite, times[ti]!);\n factor[k] = pf;\n if (material) material[k] = materialOf(materials!.materialAt(pu, pv));\n else for (let n = 0; n < nodes; n++) values![k * nodes + n] = radianceAt!(pu, pv, input.wavelengthsNm[n]!);\n }\n lookups += material ? gw * gh : gw * gh * nodes;\n for (let c = 0; c < 3; c++) {\n const e = sum[c]!, nk = group.neutral[c], sk = group.spectral[c];\n for (let y = 0; y < TH; y++) for (let x = 0; x < TW; x++) {\n let v = 0;\n for (let dy = 0, t = 0; dy < ch; dy++) for (let dx = 0; dx < cw; dx++, t++) {\n const k = (y + dy) * gw + x + dx;\n if (material) { const m = material[k]!, si = spectralIndex[m]!; v += factor[k]! * (si < 0 ? reflectance[m]! * nk![t]! : sk![si]![t]!); }\n else { let r = 0; for (let n = 0; n < nodes; n++) r += group.perNode[n]![c]![t]! * values![k * nodes + n]!; v += factor[k]! * r; }\n }\n e[y * TW + x] = e[y * TW + x]! + v;\n }\n }\n }\n for (let c = 0; c < 3; c++) { const o = out[c]!, e = sum[c]!; for (let k = 0; k < o.length; k++) o[k] = o[k]! + e[k]!; }\n }\n for (const o of out) for (let k = 0; k < o.length; k++) o[k] = o[k]! / T;\n return out;\n }\n // Site values persist across windows in a ring of native rows (a site's value does not depend on the window).\n let ringRows = 0, ring = new Float64Array(0), ringRowId = new Int32Array(0), ringOn = false;\n const compute = kernels ? kernelSite : directSite;\n return {\n get lookups(): number { return lookups; },\n uniformMaterial: -1,\n tracksMaterial: false,\n get cachesSites(): boolean { return ringOn; },\n marksReads: false,\n markReads(): void { /* never called: marksReads is false */ },\n window(x0: number, y0: number, x1: number, y1: number): void {\n const sw = Math.max(0, x1 - x0), sh = Math.max(0, y1 - y0);\n if (sh > 0 && ringRows < 2 * sh) {\n const rows = pow2(2 * sh);\n if (rows * W <= LATTICE_CACHE_LIMIT) { ringRows = rows; ring = new Float64Array(rows * W).fill(NaN); ringRowId = new Int32Array(rows).fill(-1); }\n }\n ringOn = sh > 0 && ringRows >= 2 * sh;\n if (!kernels || sw === 0) return;\n // The lattice rectangle the window's sites read, per group; the cache keeps two such heights and the columns the render's windows span.\n let cw = 0, ch = 0;\n for (const group of groups) { cw = Math.max(cw, group.cw); ch = Math.max(ch, group.ch); }\n const height = sh + ch - 1, width = sw + cw - 1;\n let rows = pow2(2 * height), cols = pow2(Math.min(W + 2 * (R + cw), Math.max(width, (Number.isFinite(spanColumns) ? spanColumns : W) + width)));\n if (slots * per * rows * cols > LATTICE_CACHE_LIMIT) rows = pow2(height);\n if (slots * per * rows * cols > LATTICE_CACHE_LIMIT) cols = pow2(width);\n if (slots * per * rows * cols > LATTICE_CACHE_LIMIT) { cacheRows = 0; return; }\n if (rows > cacheRows || cols > cacheCols) {\n rows = Math.max(rows, cacheRows); cols = Math.max(cols, cacheCols);\n if (slots * per * rows * cols > LATTICE_CACHE_LIMIT) { rows = pow2(height); cols = pow2(width); }\n cacheRows = rows; cacheCols = cols;\n const size = slots * rows * cols;\n tagQ = new Int32Array(size).fill(-2147483648); tagP = new Int32Array(size); cacheFactor = new Float64Array(size);\n if (materials) cacheMaterial = new Int32Array(size); else cacheRadiance = new Float64Array(size * nodes);\n }\n },\n site(x: number, y: number): number {\n if (!ringOn) return compute(x, y);\n const slot = y & (ringRows - 1), k = slot * W + x;\n if (ringRowId[slot] === y) { const v = ring[k]!; if (v === v) return v; }\n else { ringRowId[slot] = y; ring.fill(NaN, slot * W, (slot + 1) * W); }\n const v = compute(x, y);\n ring[k] = v;\n return v;\n },\n pilot\n };\n /**\n * The renderer's pilot point is a rectilinear plane point of the native raster: back to the sensor point, then through the lens at\n * every temporal midpoint. A point whose scene value differs between the instants (motion) counts as detail (NaN equals nothing).\n */\n function pilot(u: number, v: number): number {\n const g = 2 / input.outputWidth, xMm = u / g * mmPerSite, yMm = -v / g * mmPerSite;\n let first = NaN;\n try {\n for (let ti = 0; ti < T; ti++) {\n map(xMm, yMm, times[ti]!);\n const value = materials ? materials.materialAt(pu, pv) : radianceAt!(pu, pv, pilotNode);\n lookups++;\n if (ti === 0) first = value; else if (value !== first) return NaN;\n }\n } catch { return NaN; }\n return first;\n }\n}\n\n/** #564: tile sides of the large-kernel lens signal (the in-focus E and the convolved sites) and the bytes each tile cache keeps. */\nconst LARGE_E_TILE = 64, LARGE_OUTPUT_TILE = 128, LARGE_CACHE_BYTES = 32 * 1048576;\n\n/** #564: the lens signal with a defocus kernel above 64 sites: D ⊛ E_c by runs over the in-focus tiles (see the module comment). */\nfunction createLargeLensSignal(input: DisplayViewExpectedSignalInput, inFocusTile: (x0: number, y0: number, T: number) => Float64Array[], lookups: () => number,\n pilot: (u: number, v: number) => number): DisplayViewExpectedSignal {\n const runs = input.largeKernel!, channelAt = input.channelAt, TE = LARGE_E_TILE;\n // At least the in-focus tiles one output tile's source spans plus one more row of them, so the next output tile of a row reuses them.\n const span = Math.ceil((LARGE_OUTPUT_TILE + 2 * runs.radius) / TE) + 1;\n const inFocus = new Map<number, Float64Array[]>(), capacity = Math.max(span * (span + 1), Math.floor(LARGE_CACHE_BYTES / (3 * TE * TE * 8)));\n const tileAt = (tx: number, ty: number): Float64Array[] => {\n const key = (ty + 1048576) * 2097152 + tx + 1048576;\n let tile = inFocus.get(key);\n if (tile) { inFocus.delete(key); inFocus.set(key, tile); }\n else {\n tile = inFocusTile(tx * TE, ty * TE, TE);\n inFocus.set(key, tile);\n if (inFocus.size > capacity) inFocus.delete(inFocus.keys().next().value!);\n }\n return tile;\n };\n // Which sites of a tile row hold channel c: the CFA's 2 × 2 period (tile origins are even).\n const phase = [0, 1].map((py) => [0, 1].map((px) => channelAt(px, py)));\n const patterns: SiteKernelRunsRowPattern[] = [0, 1, 2].map((c) => (row: number) => {\n const p = phase[row & 1]!, even = p[0] === c, odd = p[1] === c;\n return even && odd ? { start: 0, step: 1 } : even ? { start: 0, step: 2 } : odd ? { start: 1, step: 2 } : null;\n });\n const lattice = createSiteKernelRunsLattice({ runs, tile: LARGE_OUTPUT_TILE, fields: 3, capacityBytes: LARGE_CACHE_BYTES, pattern: (c) => patterns[c],\n source: (x0, y0, width, height) => (c: number): Float64Array => {\n const samples = new Float64Array(width * height);\n for (let ty = Math.floor(y0 / TE); ty * TE < y0 + height; ty++) for (let tx = Math.floor(x0 / TE); tx * TE < x0 + width; tx++) {\n const tile = tileAt(tx, ty)[c]!, ax = Math.max(x0, tx * TE), bx = Math.min(x0 + width, (tx + 1) * TE), ay = Math.max(y0, ty * TE), by = Math.min(y0 + height, (ty + 1) * TE);\n for (let y = ay; y < by; y++) samples.set(tile.subarray((y - ty * TE) * TE + ax - tx * TE, (y - ty * TE) * TE + bx - tx * TE), (y - y0) * width + ax - x0);\n }\n return samples;\n } });\n return {\n get lookups(): number { return lookups(); },\n uniformMaterial: -1,\n tracksMaterial: false,\n cachesSites: false,\n marksReads: false,\n markReads(): void { /* never called: marksReads is false */ },\n window(): void { /* the tiles are fixed and kept for the signal; a window changes nothing */ },\n site(x: number, y: number): number { return lattice.valueAt(channelAt(x, y), x, y); },\n pilot\n };\n}\n"]}
|
|
@@ -129,6 +129,16 @@ export interface DisplayViewRenderResult {
|
|
|
129
129
|
* overlap weight (views where a footprint holds at most K² real pixels); "stratified-monte-carlo" otherwise.
|
|
130
130
|
*/
|
|
131
131
|
estimation: "exact-area-mean" | "stratified-monte-carlo";
|
|
132
|
+
/**
|
|
133
|
+
* #533: per display pixel (region row-major), the expected number of the real capture's output pixels in its rectangle that
|
|
134
|
+
* have at least one clipped contributing site (`simulateCapture`'s `diagnostics.highlight.saturatedPixelCount`, counted on
|
|
135
|
+
* the capture's one noise sample): Σ_j w_j·P_j, w_j the area of real pixel j inside the rectangle and P_j the probability,
|
|
136
|
+
* under the view's site model, that a site j's demosaic reads is at or above the white level. Estimated as the expected value
|
|
137
|
+
* is (exact area mean or stratified Monte Carlo); it never changes a sample.
|
|
138
|
+
*/
|
|
139
|
+
saturated: Float64Array;
|
|
140
|
+
/** #533: Σ of `saturated` in region row-major order: the region's expected saturated-pixel count (additive over regions). */
|
|
141
|
+
saturatedPixelCount: number;
|
|
132
142
|
}
|
|
133
143
|
/** One tap of a linear demosaic kernel: the site at (dx, dy) from the pixel, and its weight. */
|
|
134
144
|
export interface DisplayViewKernelTap {
|
|
@@ -149,6 +159,17 @@ export declare function overlaps(start: number, end: number, limit: number): {
|
|
|
149
159
|
first: number;
|
|
150
160
|
w: Float64Array;
|
|
151
161
|
};
|
|
162
|
+
/**
|
|
163
|
+
* Internal (#533, the GPU renderers' host): the saturated-pixel share `renderDisplayView` gives a display pixel on the exact path
|
|
164
|
+
* when every real pixel's saturation probability is exactly 0 or 1: bit j·nx + i of the 36-bit mask (`low` bits 0–31, `high` bits
|
|
165
|
+
* 32–35) is 1 for P = 1, nx the columns' overlap count. The arithmetic is the render's own (Σ_j a_j·P_j in its order, a_j = w_x·w_y / A,
|
|
166
|
+
* then times A), so the value has the reference's bits.
|
|
167
|
+
*/
|
|
168
|
+
export declare function displayViewDecidedSaturation(columns: {
|
|
169
|
+
w: Float64Array;
|
|
170
|
+
}, rows: {
|
|
171
|
+
w: Float64Array;
|
|
172
|
+
}, area: number, low: number, high: number): number;
|
|
152
173
|
/**
|
|
153
174
|
* Internal (exported for tests). Footprint sums along one axis, for the closed-form B_c (docs/DISPLAY_VIEW.md, "Demosaic correlation"). Native
|
|
154
175
|
* coordinate parity decides the CFA: red columns/rows are even, blue odd. With w(k) the overlap of real column k:
|
|
@@ -226,6 +226,22 @@ export function overlaps(start, end, limit) {
|
|
|
226
226
|
w[k - first] = Math.min(end, k + 1) - Math.max(start, k);
|
|
227
227
|
return { first, w };
|
|
228
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Internal (#533, the GPU renderers' host): the saturated-pixel share `renderDisplayView` gives a display pixel on the exact path
|
|
231
|
+
* when every real pixel's saturation probability is exactly 0 or 1: bit j·nx + i of the 36-bit mask (`low` bits 0–31, `high` bits
|
|
232
|
+
* 32–35) is 1 for P = 1, nx the columns' overlap count. The arithmetic is the render's own (Σ_j a_j·P_j in its order, a_j = w_x·w_y / A,
|
|
233
|
+
* then times A), so the value has the reference's bits.
|
|
234
|
+
*/
|
|
235
|
+
export function displayViewDecidedSaturation(columns, rows, area, low, high) {
|
|
236
|
+
const nx = columns.w.length;
|
|
237
|
+
let sat = 0;
|
|
238
|
+
for (let j = 0; j < rows.w.length; j++)
|
|
239
|
+
for (let i = 0; i < nx; i++) {
|
|
240
|
+
const bit = j * nx + i, set = bit < 32 ? (low >>> bit) & 1 : (high >>> (bit - 32)) & 1;
|
|
241
|
+
sat += columns.w[i] * rows.w[j] / area * (set === 1 ? 1 : 0);
|
|
242
|
+
}
|
|
243
|
+
return (sat / 1) * area;
|
|
244
|
+
}
|
|
229
245
|
export function axisSums(start, end, limit, margin) {
|
|
230
246
|
const { first, w } = overlaps(start, end, limit);
|
|
231
247
|
const at = (k) => (k >= first && k < first + w.length ? w[k - first] : 0);
|
|
@@ -482,9 +498,10 @@ function correctionStates(key) {
|
|
|
482
498
|
/**
|
|
483
499
|
* Recorded terms of a one-material sample: [0, 3) the channel site variances csv; [3, 21) per candidate d and channel c the
|
|
484
500
|
* linear slopes a (3 + (3d + c)·3); [21, 27) per candidate the residual terms; [27, 30) the expected-value sums; [30, 33) the
|
|
485
|
-
* AHD choice terms; 33 a 1 when the AHD correction applies and [34, 37) its values
|
|
501
|
+
* AHD choice terms; 33 a 1 when the AHD correction applies and [34, 37) its values; 37 the real pixel's saturation probability
|
|
502
|
+
* (#533: the probability that at least one site its demosaic reads is clipped at the white level).
|
|
486
503
|
*/
|
|
487
|
-
const MEMO_SIZE =
|
|
504
|
+
const MEMO_SIZE = 38;
|
|
488
505
|
/** Most real pixels a display pixel's footprint may have for the per-real-pixel memo (#392); larger footprints rarely repeat a real pixel. */
|
|
489
506
|
const PIXEL_MEMO_LIMIT = 1 << 16;
|
|
490
507
|
/**
|
|
@@ -793,7 +810,8 @@ export async function renderDisplayView(setup) {
|
|
|
793
810
|
const maximum = setup.bitDepth === 8 ? 255 : 65535, step = 1 / maximum;
|
|
794
811
|
const pixelCount = region.width * region.height;
|
|
795
812
|
const samples = setup.bitDepth === 8 ? new Uint8Array(pixelCount * 3) : new Uint16Array(pixelCount * 3);
|
|
796
|
-
const expected = new Float64Array(pixelCount * 3), noiseStd = new Float64Array(pixelCount * 3);
|
|
813
|
+
const expected = new Float64Array(pixelCount * 3), noiseStd = new Float64Array(pixelCount * 3), saturated = new Float64Array(pixelCount);
|
|
814
|
+
let saturatedTotal = 0;
|
|
797
815
|
const columns = Array.from({ length: region.width }, (_, i) => axisSums((region.x + i) * sx, (region.x + i + 1) * sx, frameWidth, margin));
|
|
798
816
|
const M = setup.matrix, m00 = M[0][0], m01 = M[0][1], m02 = M[0][2], m10 = M[1][0], m11 = M[1][1], m12 = M[1][2], m20 = M[2][0], m21 = M[2][1], m22 = M[2][2];
|
|
799
817
|
const g0 = setup.gains[0], g1 = setup.gains[1], g2 = setup.gains[2], L = setup.clipLevel, reinhard = setup.toneCurve === "positive-reinhard-per-channel";
|
|
@@ -804,6 +822,8 @@ export async function renderDisplayView(setup) {
|
|
|
804
822
|
const reach = Math.max(1, ...candidates.flat(3).map((t) => Math.max(Math.abs(t.dx), Math.abs(t.dy)))), side = 2 * reach + 1, slotsCount = side * side;
|
|
805
823
|
const slotOf = (t) => (t.dy + reach) * side + t.dx + reach;
|
|
806
824
|
const { dx: slotDx, dy: slotDy } = displayViewSlotOffsets(reach);
|
|
825
|
+
/** The raster index of native site (x, y) read reflect-101, as the sample loop reads it. */
|
|
826
|
+
const reflectedSite = (x, y) => (y < 0 ? -y : y >= nativeHeight ? 2 * nativeHeight - 2 - y : y) * nativeWidth + (x < 0 ? -x : x >= nativeWidth ? 2 * nativeWidth - 2 - x : x);
|
|
807
827
|
// Per phase: the bilinear kernels (for the site variance of each channel), the candidates, and the slots they read.
|
|
808
828
|
const phaseSlots = [], phaseWeights = [], phaseW2 = [], phaseList = [];
|
|
809
829
|
const candidateSlots = [], candidateWeights = [], candidateDense = [], candidateList = [];
|
|
@@ -826,7 +846,7 @@ export async function renderDisplayView(setup) {
|
|
|
826
846
|
}
|
|
827
847
|
// The same tables flat (phase·2 + candidate, ·3 + channel), read by the sample loop below.
|
|
828
848
|
const { count: candidateCount, denseAt, listAt, slotsAt, weightsAt } = flatDisplayViewCandidateTables(candidateSlots, candidateWeights, candidateDense, candidateList);
|
|
829
|
-
const siteElectrons = new Float64Array(slotsCount), siteMean = new Float64Array(slotsCount), siteVar = new Float64Array(slotsCount), siteThird = new Float64Array(slotsCount), siteChannel = new Int32Array(slotsCount), clip = new Float64Array(3), B = new Float64Array(4), C = new Float64Array(9);
|
|
849
|
+
const siteElectrons = new Float64Array(slotsCount), siteClip = new Float64Array(slotsCount), siteMean = new Float64Array(slotsCount), siteVar = new Float64Array(slotsCount), siteThird = new Float64Array(slotsCount), siteChannel = new Int32Array(slotsCount), clip = new Float64Array(3), B = new Float64Array(4), C = new Float64Array(9);
|
|
830
850
|
const cm = new Float64Array(3), cv = new Float64Array(3), csv = new Float64Array(3), bm = new Float64Array(3), bv = new Float64Array(3), bs = new Float64Array(3);
|
|
831
851
|
const hm = new Float64Array(3), hv = new Float64Array(3), hs = new Float64Array(3), an = new Float64Array(9);
|
|
832
852
|
const reach2 = CLIP_REACH_SIGMA * CLIP_REACH_SIGMA;
|
|
@@ -847,7 +867,7 @@ export async function renderDisplayView(setup) {
|
|
|
847
867
|
const siteMask = siteRows - 1, ringCapacity = siteRows * siteW, ringUsable = exactView && ringCapacity <= SITE_RING_LIMIT;
|
|
848
868
|
// Allocated at the first display pixel that uses the ring (a render whose windows never fill allocates nothing).
|
|
849
869
|
let ringStamp = new Int32Array(0), ringStatStamp = ringStamp, ringMat = ringStamp, siteSlotQ = ringStamp, siteSlotStamp = ringStamp, markX = ringStamp, markY = ringStamp, markM = ringStamp;
|
|
850
|
-
let ringV = new Float64Array(0), ringMean = ringV, ringVar = ringV, ringThird = ringV, markV = ringV;
|
|
870
|
+
let ringV = new Float64Array(0), ringMean = ringV, ringVar = ringV, ringThird = ringV, ringClip = ringV, markV = ringV;
|
|
851
871
|
// (No closure assigns them, so they stay locals of the render loop.)
|
|
852
872
|
// AHD low-signal correction: an 11 × 11 noisy neighbourhood (AHD reads up to 5 sites away) and the local AHD steps.
|
|
853
873
|
const ahdCorrection = setup.ahdCorrection, windowReach = ahdCorrection ? Math.max(reach, AHD_REACH) : reach;
|
|
@@ -911,14 +931,17 @@ export async function renderDisplayView(setup) {
|
|
|
911
931
|
const c = siteChannel[slot], e = siteElectrons[slot], kc = k[c], mean = kc * e, variance = kc * kc * e + c0[c], gap = 1 - mean;
|
|
912
932
|
// Third cumulant of the normalized value: Poisson electrons have κ₃ = e (read and rounding noise add none).
|
|
913
933
|
siteThird[slot] = kc * kc * kc * e;
|
|
934
|
+
// #533: the clip probability P(value ≥ 1) is 1 − P(value < 1), the clip's own slope (0 where the clip is out of reach).
|
|
914
935
|
if (gap > 0 && gap * gap > reach2 * variance) {
|
|
915
936
|
siteMean[slot] = mean;
|
|
916
937
|
siteVar[slot] = variance;
|
|
938
|
+
siteClip[slot] = 0;
|
|
917
939
|
}
|
|
918
940
|
else {
|
|
919
941
|
upperClip(mean, variance, 1, clip);
|
|
920
942
|
siteMean[slot] = clip[0];
|
|
921
943
|
siteVar[slot] = clip[1];
|
|
944
|
+
siteClip[slot] = 1 - clip[2];
|
|
922
945
|
}
|
|
923
946
|
}
|
|
924
947
|
let siteCount = 0, sampleCount = 0, detail = 0, uniform = 0, lastYield = Date.now();
|
|
@@ -1003,6 +1026,7 @@ export async function renderDisplayView(setup) {
|
|
|
1003
1026
|
ringMean = new Float64Array(ringCapacity);
|
|
1004
1027
|
ringVar = new Float64Array(ringCapacity);
|
|
1005
1028
|
ringThird = new Float64Array(ringCapacity);
|
|
1029
|
+
ringClip = new Float64Array(ringCapacity);
|
|
1006
1030
|
siteSlotQ = new Int32Array(slotsCount);
|
|
1007
1031
|
siteSlotStamp = new Int32Array(slotsCount);
|
|
1008
1032
|
markX = new Int32Array(slotsCount);
|
|
@@ -1023,7 +1047,7 @@ export async function renderDisplayView(setup) {
|
|
|
1023
1047
|
}
|
|
1024
1048
|
pixelGeneration++;
|
|
1025
1049
|
}
|
|
1026
|
-
let s0 = 0, s1 = 0, s2 = 0, c00 = 0, c01 = 0, c02 = 0, c11 = 0, c12 = 0, c22 = 0, r0 = 0, r1 = 0, r2 = 0, pixelVariance = 0, corrected = false;
|
|
1050
|
+
let s0 = 0, s1 = 0, s2 = 0, c00 = 0, c01 = 0, c02 = 0, c11 = 0, c12 = 0, c22 = 0, r0 = 0, r1 = 0, r2 = 0, pixelVariance = 0, corrected = false, sat = 0;
|
|
1027
1051
|
for (let n = 0; n < sampleTotal; n++) {
|
|
1028
1052
|
// A sample's weights: 1 for the stratified estimator (its sums are divided by Q below); a_j for the expected value and
|
|
1029
1053
|
// linear covariance and a_j² for the independent residual on the exact path. Multiplying by 1 leaves every value's bits.
|
|
@@ -1113,28 +1137,33 @@ export async function renderDisplayView(setup) {
|
|
|
1113
1137
|
siteMean[slot] = ringMean[q];
|
|
1114
1138
|
siteVar[slot] = ringVar[q];
|
|
1115
1139
|
siteThird[slot] = ringThird[q];
|
|
1140
|
+
siteClip[slot] = ringClip[q];
|
|
1116
1141
|
continue;
|
|
1117
1142
|
}
|
|
1118
1143
|
// As siteStatistics, written out here for the untracked (Speed) path.
|
|
1119
1144
|
const kc = k[c], mean = kc * e, variance = kc * kc * e + c0[c], gap = 1 - mean, third = kc * kc * kc * e;
|
|
1120
|
-
let sm, sv;
|
|
1145
|
+
let sm, sv, sp;
|
|
1121
1146
|
if (gap > 0 && gap * gap > reach2 * variance) {
|
|
1122
1147
|
sm = mean;
|
|
1123
1148
|
sv = variance;
|
|
1149
|
+
sp = 0;
|
|
1124
1150
|
}
|
|
1125
1151
|
else {
|
|
1126
1152
|
upperClip(mean, variance, 1, clip);
|
|
1127
1153
|
sm = clip[0];
|
|
1128
1154
|
sv = clip[1];
|
|
1155
|
+
sp = 1 - clip[2];
|
|
1129
1156
|
}
|
|
1130
1157
|
siteMean[slot] = sm;
|
|
1131
1158
|
siteVar[slot] = sv;
|
|
1132
1159
|
siteThird[slot] = third;
|
|
1160
|
+
siteClip[slot] = sp;
|
|
1133
1161
|
if (q >= 0) {
|
|
1134
1162
|
ringStatStamp[q] = rowStamp;
|
|
1135
1163
|
ringMean[q] = sm;
|
|
1136
1164
|
ringVar[q] = sv;
|
|
1137
1165
|
ringThird[q] = third;
|
|
1166
|
+
ringClip[q] = sp;
|
|
1138
1167
|
}
|
|
1139
1168
|
}
|
|
1140
1169
|
if (marks > 0)
|
|
@@ -1176,11 +1205,13 @@ export async function renderDisplayView(setup) {
|
|
|
1176
1205
|
if (gap > 0 && gap * gap > reach2 * variance) {
|
|
1177
1206
|
siteMean[slot] = mean;
|
|
1178
1207
|
siteVar[slot] = variance;
|
|
1208
|
+
siteClip[slot] = 0;
|
|
1179
1209
|
}
|
|
1180
1210
|
else {
|
|
1181
1211
|
upperClip(mean, variance, 1, clip);
|
|
1182
1212
|
siteMean[slot] = clip[0];
|
|
1183
1213
|
siteVar[slot] = clip[1];
|
|
1214
|
+
siteClip[slot] = 1 - clip[2];
|
|
1184
1215
|
}
|
|
1185
1216
|
}
|
|
1186
1217
|
if (!tracking)
|
|
@@ -1225,6 +1256,7 @@ export async function renderDisplayView(setup) {
|
|
|
1225
1256
|
s2 += wE * memo[mo + 36];
|
|
1226
1257
|
corrected = true;
|
|
1227
1258
|
}
|
|
1259
|
+
sat += wE * memo[mo + 37];
|
|
1228
1260
|
continue;
|
|
1229
1261
|
}
|
|
1230
1262
|
// The terms are written where they are kept: the real pixel's memo slot, or (for the first sample of a one-material key)
|
|
@@ -1262,6 +1294,7 @@ export async function renderDisplayView(setup) {
|
|
|
1262
1294
|
siteMean[slot] = ringMean[q];
|
|
1263
1295
|
siteVar[slot] = ringVar[q];
|
|
1264
1296
|
siteThird[slot] = ringThird[q];
|
|
1297
|
+
siteClip[slot] = ringClip[q];
|
|
1265
1298
|
continue;
|
|
1266
1299
|
}
|
|
1267
1300
|
siteStatistics(slot);
|
|
@@ -1270,6 +1303,7 @@ export async function renderDisplayView(setup) {
|
|
|
1270
1303
|
ringMean[q] = siteMean[slot];
|
|
1271
1304
|
ringVar[q] = siteVar[slot];
|
|
1272
1305
|
ringThird[q] = siteThird[slot];
|
|
1306
|
+
ringClip[q] = siteClip[slot];
|
|
1273
1307
|
}
|
|
1274
1308
|
}
|
|
1275
1309
|
// Site variance of each channel through the bilinear kernels (for B_c), then the demosaic's own pixel statistics: the
|
|
@@ -1441,6 +1475,26 @@ export async function renderDisplayView(setup) {
|
|
|
1441
1475
|
rt[ro + 28] = e1;
|
|
1442
1476
|
rt[ro + 29] = e2;
|
|
1443
1477
|
}
|
|
1478
|
+
// #533: the real pixel's saturation probability, 1 − Π_k (1 − p_k) over the distinct sites its demosaic reads (the
|
|
1479
|
+
// capture counts a pixel with at least one clipped contributing site; the sites' noises are independent). A site read
|
|
1480
|
+
// twice through the mirrored border counts once.
|
|
1481
|
+
let unclipped = 1;
|
|
1482
|
+
if (inside)
|
|
1483
|
+
for (let li = 0; li < list.length; li++)
|
|
1484
|
+
unclipped *= 1 - siteClip[list[li]];
|
|
1485
|
+
else
|
|
1486
|
+
for (let li = 0; li < list.length; li++) {
|
|
1487
|
+
const slot = list[li], at = reflectedSite(x + slotDx[slot], y + slotDy[slot]);
|
|
1488
|
+
let repeated = false;
|
|
1489
|
+
for (let lj = 0; lj < li && !repeated; lj++)
|
|
1490
|
+
repeated = reflectedSite(x + slotDx[list[lj]], y + slotDy[list[lj]]) === at;
|
|
1491
|
+
if (!repeated)
|
|
1492
|
+
unclipped *= 1 - siteClip[slot];
|
|
1493
|
+
}
|
|
1494
|
+
const saturation = 1 - unclipped;
|
|
1495
|
+
sat += wE * saturation;
|
|
1496
|
+
if (rt)
|
|
1497
|
+
rt[ro + 37] = saturation;
|
|
1444
1498
|
if (count === 2) {
|
|
1445
1499
|
// AHD's per-pixel choice between the candidates adds independent variance: with a noise-driven choice each pixel
|
|
1446
1500
|
// deviates from the candidates' average by ±½(H − V), variance ¼·Var(H − V) (linear in the sites, at the last
|
|
@@ -1495,6 +1549,10 @@ export async function renderDisplayView(setup) {
|
|
|
1495
1549
|
correctedPixels++;
|
|
1496
1550
|
// Stratified: means over Q samples. Exact: the weights already sum to 1 (Σ a_j = 1) and the residual carries Σ a_j²·r_j.
|
|
1497
1551
|
const Qd = exactView ? 1 : Q, mean0 = s0 / Qd, mean1 = s1 / Qd, mean2 = s2 / Qd, pixels = B[3];
|
|
1552
|
+
// #533: the expected saturated real pixels of the rectangle (A real pixels): A·Σ_j a_j·P_j, or A times the samples' mean.
|
|
1553
|
+
const saturatedHere = (sat / Qd) * area;
|
|
1554
|
+
saturated[ry * region.width + rx] = saturatedHere;
|
|
1555
|
+
saturatedTotal += saturatedHere;
|
|
1498
1556
|
// The real pixels' output rounding (Δ²/12 in the encoded domain), mapped to linear light at the mean.
|
|
1499
1557
|
const q0 = quantizationVariance(mean0, step), q1 = quantizationVariance(mean1, step), q2 = quantizationVariance(mean2, step);
|
|
1500
1558
|
// Covariance in linear light: the linear part plus the independent per-pixel residuals and rounding.
|
|
@@ -1527,7 +1585,7 @@ export async function renderDisplayView(setup) {
|
|
|
1527
1585
|
}
|
|
1528
1586
|
}
|
|
1529
1587
|
return { samples, expected, noiseStd, sampleCount, siteCount, detailPixelCount: detail, uniformPixelCount: uniform, ahdCorrectedPixelCount: correctedPixels,
|
|
1530
|
-
estimation: exactView ? "exact-area-mean" : "stratified-monte-carlo" };
|
|
1588
|
+
estimation: exactView ? "exact-area-mean" : "stratified-monte-carlo", saturated, saturatedPixelCount: saturatedTotal };
|
|
1531
1589
|
}
|
|
1532
1590
|
/**
|
|
1533
1591
|
* The centre c of a normal of variance v whose clip to [0, 1] has mean `target` (bisection; c = target when the noise does
|