@photivra/engine 2.20.0 → 2.22.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 +295 -1
- package/CITATION.cff +1 -1
- package/README.md +7 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +18 -0
- package/dist/capture/c2pa-embed.d.ts +116 -0
- package/dist/capture/c2pa-embed.js +493 -0
- package/dist/capture/c2pa-embed.js.map +1 -0
- package/dist/capture/dng-import.d.ts +73 -8
- package/dist/capture/dng-import.js +315 -80
- package/dist/capture/dng-import.js.map +1 -1
- package/dist/capture/dng-lens-correction-opcodes.d.ts +2 -2
- package/dist/capture/dng-lens-correction-opcodes.js +2 -2
- package/dist/capture/dng-lens-correction-opcodes.js.map +1 -1
- package/dist/capture/dng-opcodes.d.ts +96 -0
- package/dist/capture/dng-opcodes.js +391 -0
- package/dist/capture/dng-opcodes.js.map +1 -0
- package/dist/capture/dng-profile-maps.d.ts +99 -0
- package/dist/capture/dng-profile-maps.js +381 -0
- package/dist/capture/dng-profile-maps.js.map +1 -0
- package/dist/capture/dng-stage-image.d.ts +23 -0
- package/dist/capture/dng-stage-image.js +65 -0
- package/dist/capture/dng-stage-image.js.map +1 -0
- package/dist/capture/exposure-build-up-stage.d.ts +16 -0
- package/dist/capture/exposure-build-up-stage.js +4 -0
- package/dist/capture/exposure-build-up-stage.js.map +1 -0
- package/dist/capture/jpeg-xl-tiles.d.ts +22 -0
- package/dist/capture/jpeg-xl-tiles.js +151 -0
- package/dist/capture/jpeg-xl-tiles.js.map +1 -0
- package/dist/capture/lossy-jpeg.d.ts +17 -0
- package/dist/capture/lossy-jpeg.js +369 -0
- package/dist/capture/lossy-jpeg.js.map +1 -0
- package/dist/capture/native-environment-lean.d.ts +2 -1
- package/dist/capture/native-environment-lean.js +41 -73
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-tabulated.js +4 -3
- package/dist/capture/native-environment-tabulated.js.map +1 -1
- package/dist/capture/native-raw-development.d.ts +2 -1
- package/dist/capture/native-raw-development.js.map +1 -1
- package/dist/capture/native-raw.d.ts +3 -2
- package/dist/capture/native-raw.js +5 -4
- package/dist/capture/native-raw.js.map +1 -1
- package/dist/capture/sensor-raw-producer.d.ts +4 -1
- package/dist/capture/sensor-raw-producer.js +12 -3
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/color/neighbor-highlight-reconstruction.d.ts +66 -0
- package/dist/color/neighbor-highlight-reconstruction.js +234 -0
- package/dist/color/neighbor-highlight-reconstruction.js.map +1 -0
- package/dist/color/sensor-color-development.d.ts +5 -0
- package/dist/color/sensor-color-development.js +7 -1
- package/dist/color/sensor-color-development.js.map +1 -1
- package/dist/color/spectral-spikiness.d.ts +11 -0
- package/dist/color/spectral-spikiness.js +23 -0
- package/dist/color/spectral-spikiness.js.map +1 -0
- package/dist/core/execution-error.d.ts +21 -0
- package/dist/core/execution-error.js +12 -0
- package/dist/core/execution-error.js.map +1 -0
- 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 +3 -2
- package/dist/equipment/generic-lens-catalogue.js +18 -5
- package/dist/equipment/generic-lens-catalogue.js.map +1 -1
- package/dist/equipment/generic-tier-assets.d.ts +32 -0
- package/dist/equipment/generic-tier-assets.js +16 -11
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/sensor-profile-body.d.ts +78 -0
- package/dist/equipment/sensor-profile-body.js +77 -0
- package/dist/equipment/sensor-profile-body.js.map +1 -0
- package/dist/equipment/sensor-profiles.d.ts +8 -0
- package/dist/equipment/sensor-profiles.js +82 -0
- package/dist/equipment/sensor-profiles.js.map +1 -0
- package/dist/facade/catalogue-lens-signal.d.ts +28 -3
- package/dist/facade/catalogue-lens-signal.js +83 -78
- package/dist/facade/catalogue-lens-signal.js.map +1 -1
- package/dist/facade/chart-radiance-batch.js +2 -1
- package/dist/facade/chart-radiance-batch.js.map +1 -1
- package/dist/facade/defocus-image-space-provider.d.ts +7 -0
- package/dist/facade/defocus-image-space-provider.js +64 -76
- package/dist/facade/defocus-image-space-provider.js.map +1 -1
- package/dist/facade/diffraction-provider.d.ts +1 -1
- package/dist/facade/diffraction-provider.js +4 -4
- package/dist/facade/diffraction-provider.js.map +1 -1
- package/dist/facade/display-view-gpu-session.js +39 -5
- package/dist/facade/display-view-gpu-session.js.map +1 -1
- package/dist/facade/display-view-gpu.d.ts +19 -6
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view-lens-signal.js +25 -23
- package/dist/facade/display-view-lens-signal.js.map +1 -1
- package/dist/facade/display-view-normal.d.ts +15 -0
- package/dist/facade/display-view-normal.js +44 -0
- package/dist/facade/display-view-normal.js.map +1 -0
- package/dist/facade/display-view-rendering.d.ts +97 -0
- package/dist/facade/display-view-rendering.js +598 -0
- package/dist/facade/display-view-rendering.js.map +1 -0
- package/dist/facade/display-view.d.ts +37 -65
- package/dist/facade/display-view.js +152 -499
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/expected-signal-setup.d.ts +3 -1
- package/dist/facade/expected-signal-setup.js +3 -3
- package/dist/facade/expected-signal-setup.js.map +1 -1
- package/dist/facade/expected-signal.d.ts +47 -14
- package/dist/facade/expected-signal.js +117 -112
- package/dist/facade/expected-signal.js.map +1 -1
- package/dist/facade/exposure-build-up.d.ts +70 -0
- package/dist/facade/exposure-build-up.js +164 -0
- package/dist/facade/exposure-build-up.js.map +1 -0
- package/dist/facade/fast-methods.d.ts +1 -1
- package/dist/facade/fast-methods.js +46 -9
- package/dist/facade/fast-methods.js.map +1 -1
- package/dist/facade/generic-lens-capture.d.ts +3 -3
- package/dist/facade/generic-lens-capture.js +3 -3
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/image-plane-enable.d.ts +7 -0
- package/dist/facade/image-plane-enable.js +17 -0
- package/dist/facade/image-plane-enable.js.map +1 -0
- package/dist/facade/image-plane-lattice-data.d.ts +6 -0
- package/dist/facade/image-plane-lattice-data.js +10 -0
- package/dist/facade/image-plane-lattice-data.js.map +1 -0
- package/dist/facade/image-plane-support.d.ts +33 -0
- package/dist/facade/image-plane-support.js +11 -0
- package/dist/facade/image-plane-support.js.map +1 -0
- package/dist/facade/image-plane.d.ts +36 -0
- package/dist/facade/image-plane.js +384 -0
- package/dist/facade/image-plane.js.map +1 -0
- package/dist/facade/mixed-illumination.d.ts +108 -0
- package/dist/facade/mixed-illumination.js +174 -0
- package/dist/facade/mixed-illumination.js.map +1 -0
- package/dist/facade/on-demand-kits.d.ts +14 -0
- package/dist/facade/on-demand-kits.js +36 -0
- package/dist/facade/on-demand-kits.js.map +1 -0
- package/dist/facade/opt-in-kit.d.ts +9 -0
- package/dist/facade/opt-in-kit.js +11 -0
- package/dist/facade/opt-in-kit.js.map +1 -0
- package/dist/facade/quality-kit.d.ts +21 -0
- package/dist/facade/quality-kit.js +23 -0
- package/dist/facade/quality-kit.js.map +1 -0
- package/dist/facade/quality-paths.d.ts +22 -0
- package/dist/facade/quality-paths.js +44 -0
- package/dist/facade/quality-paths.js.map +1 -0
- package/dist/facade/representative-light-sources.d.ts +72 -0
- package/dist/facade/representative-light-sources.js +124 -0
- package/dist/facade/representative-light-sources.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +145 -4
- package/dist/facade/scene-radiance.js +50 -13
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +68 -20
- package/dist/facade/simulate-capture.js +399 -146
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.d.ts +10 -12
- package/dist/facade/simulate-display-view.js +70 -53
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.d.ts +13 -1
- package/dist/gpu/chart-composite-gpu.js +48 -9
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/chart-radiance-gpu.js +4 -30
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-composite-material-module.d.ts +10 -4
- package/dist/gpu/display-view-composite-material-module.js +39 -13
- package/dist/gpu/display-view-composite-material-module.js.map +1 -1
- package/dist/gpu/display-view-gpu-renderer.d.ts +43 -0
- package/dist/gpu/display-view-gpu-renderer.js +134 -0
- package/dist/gpu/display-view-gpu-renderer.js.map +1 -0
- package/dist/gpu/display-view-image-material-module.d.ts +87 -0
- package/dist/gpu/display-view-image-material-module.js +361 -0
- package/dist/gpu/display-view-image-material-module.js.map +1 -0
- package/dist/gpu/display-view-image-quality.d.ts +87 -0
- package/dist/gpu/display-view-image-quality.js +625 -0
- package/dist/gpu/display-view-image-quality.js.map +1 -0
- package/dist/gpu/display-view-quality-gpu.d.ts +80 -65
- package/dist/gpu/display-view-quality-gpu.js +187 -445
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.d.ts +67 -19
- package/dist/gpu/display-view-speed-gpu.js +181 -105
- 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/image-kernel-execution.d.ts +2 -13
- package/dist/gpu/image-kernel-execution.js +2 -10
- package/dist/gpu/image-kernel-execution.js.map +1 -1
- package/dist/gpu/wgsl-display-view-coupled-stub.d.ts +8 -0
- package/dist/gpu/wgsl-display-view-coupled-stub.js +21 -0
- package/dist/gpu/wgsl-display-view-coupled-stub.js.map +1 -0
- package/dist/gpu/wgsl-display-view-coupled.d.ts +88 -0
- package/dist/gpu/wgsl-display-view-coupled.js +353 -0
- package/dist/gpu/wgsl-display-view-coupled.js.map +1 -0
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +33 -24
- package/dist/gpu/wgsl-display-view-quality-kernel.js +166 -146
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +19 -44
- package/dist/gpu/wgsl-display-view-speed-kernel.js +116 -18
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
- package/dist/gpu/wgsl-exact-sum.d.ts +20 -0
- package/dist/gpu/wgsl-exact-sum.js +42 -0
- package/dist/gpu/wgsl-exact-sum.js.map +1 -0
- package/dist/index.d.ts +22 -6
- package/dist/index.js +16 -2
- package/dist/index.js.map +1 -1
- package/dist/motion/subject-motion.d.ts +66 -0
- package/dist/motion/subject-motion.js +52 -0
- package/dist/motion/subject-motion.js.map +1 -0
- package/dist/optics/generic-lens-lateral-color.d.ts +83 -0
- package/dist/optics/generic-lens-lateral-color.js +77 -0
- package/dist/optics/generic-lens-lateral-color.js.map +1 -0
- package/dist/optics/generic-lens-psf.js +54 -46
- package/dist/optics/generic-lens-psf.js.map +1 -1
- package/dist/optics/lens-psf-profile.d.ts +7 -0
- package/dist/optics/lens-psf-profile.js +2 -1
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/output/camera-channel-response.d.ts +50 -0
- package/dist/output/camera-channel-response.js +69 -0
- package/dist/output/camera-channel-response.js.map +1 -0
- package/dist/output/developed-lens-corrections.d.ts +19 -5
- package/dist/output/developed-lens-corrections.js +28 -9
- package/dist/output/developed-lens-corrections.js.map +1 -1
- package/dist/output/generic-lens-corrections.d.ts +41 -5
- package/dist/output/generic-lens-corrections.js +52 -8
- package/dist/output/generic-lens-corrections.js.map +1 -1
- package/dist/output/native-capture-sdr.js +5 -2
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/output/print-plan.d.ts +41 -5
- package/dist/output/print-plan.js +59 -14
- package/dist/output/print-plan.js.map +1 -1
- package/dist/output/sdr-rendering.d.ts +18 -1
- package/dist/output/sdr-rendering.js +39 -2
- package/dist/output/sdr-rendering.js.map +1 -1
- package/dist/sensor/binomial-sample.d.ts +3 -0
- package/dist/sensor/binomial-sample.js +86 -0
- package/dist/sensor/binomial-sample.js.map +1 -0
- package/dist/sensor/native-sensor-report.d.ts +10 -0
- package/dist/sensor/native-sensor-report.js +16 -0
- package/dist/sensor/native-sensor-report.js.map +1 -0
- package/dist/sensor/sensor-characteristics.d.ts +91 -13
- package/dist/sensor/sensor-characteristics.js +30 -15
- package/dist/sensor/sensor-characteristics.js.map +1 -1
- package/docs/AGENT_GUIDE.md +1 -0
- package/docs/API_REFERENCE.md +214 -4
- package/docs/QUICK_START.md +162 -8
- package/docs/USAGE.md +195 -22
- package/docs/api/capture-c2pa-embed.md +177 -0
- package/docs/api/capture-dng-import.md +86 -10
- package/docs/api/capture-dng-opcodes.md +93 -0
- package/docs/api/capture-dng-profile-maps.md +141 -0
- package/docs/api/capture-dng-stage-image.md +43 -0
- package/docs/api/capture-jpeg-xl-tiles.md +33 -0
- package/docs/api/capture-lossy-jpeg.md +41 -0
- package/docs/api/capture-native-raw-development.md +2 -1
- package/docs/api/core-execution-error.md +43 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-lens-catalogue.md +10 -5
- package/docs/api/equipment-sensor-profile-body.md +64 -0
- package/docs/api/equipment-sensor-profiles.md +86 -0
- package/docs/api/exports.json +460 -5
- package/docs/api/facade-display-view-gpu.md +5 -2
- package/docs/api/facade-display-view.md +11 -15
- package/docs/api/facade-exposure-build-up.md +105 -0
- package/docs/api/facade-fast-methods.md +47 -10
- package/docs/api/facade-image-plane-enable.md +16 -0
- package/docs/api/facade-mixed-illumination.md +67 -0
- package/docs/api/facade-quality-paths.md +24 -0
- package/docs/api/facade-representative-light-sources.md +131 -0
- package/docs/api/facade-scene-radiance.md +54 -3
- package/docs/api/facade-simulate-capture.md +48 -11
- package/docs/api/facade-simulate-display-view.md +10 -12
- package/docs/api/gpu-image-kernel-execution.md +0 -36
- package/docs/api/motion-subject-motion.md +23 -0
- package/docs/api/optics-generic-lens-lateral-color.md +79 -0
- package/docs/api/output-camera-channel-response.md +55 -0
- package/docs/api/output-developed-lens-corrections.md +10 -1
- package/docs/api/output-generic-lens-corrections.md +40 -4
- package/docs/api/output-print-plan.md +35 -1
- package/docs/api/output-sdr-rendering.md +6 -1
- package/docs/api/sensor-sensor-characteristics.md +54 -2
- package/llms.txt +3 -0
- package/package.json +6 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-plane.js","sourceRoot":"","sources":["../../src/facade/image-plane.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * The image-plane scene (2.21, #581): a photo as a flat matte print on the scene plane. Loaded on demand (a dynamic import by\n * the facade) only when a request's scene is `{ kind: \"image-plane\" }`, so a bundle that never prints a photo does not carry\n * it or its lattice data.\n *\n * **From pixel to reflectance** (docs/IMAGE_PLANE.md):\n *\n * 1. Decode to linear sRGB: `srgb-8` and `srgb-16` through the sRGB transfer function (IEC 61966-2-1, the piecewise EOTF)\n * evaluated with the portable power (`portablePow`, within 1 ulp, the same bits in every JavaScript engine); `linear-srgb`\n * as given, clipped to [0, 1]. A pixel with alpha a is composited over the paper in linear light: c' = a·c + (1 − a).\n * 2. The print reflectance lattice: 5 × 5 × 5 nodes at the sRGB code values 0, 1/4, 1/2, 3/4, 1 per channel (their linear\n * values L₀…L₄). The node spectra on the neutral axis are flat (the node's linear value); the other 120 are Photivra's own\n * LHTSS fits (S. A. Burns, arXiv:1710.05732 v5, \"Least Hyperbolic Tangent Slope Squared (LHTSS) Method\", pp. 24–26), each\n * reproducing its node's sRGB under CIE D65 with the CIE 1931 2° observer (scripts/fit-image-plane-lattice.mjs), stored at\n * 10 nm over 380–780 nm in 16 bits and linearly interpolated between samples. A pixel's spectrum is the trilinear\n * interpolation, in linear sRGB, of the spectra of the eight nodes of its cell: a convex combination of spectra in [0, 1],\n * so it lies in [0, 1], and, XYZ being linear in the spectrum, it reproduces the pixel's sRGB under D65 to the nodes' own\n * residual (measured by the fit: CIEDE2000 at most 6.4·10⁻⁴ over a 17³ grid of sRGB codes).\n * 3. The paper: ρ = ρ_black + (ρ_white − ρ_black)·ρ_lattice, affine and so still bounded; defaults 0.90 and 0.01.\n * 4. Between pixel centers (`bilinear`, the default): the pixels' spectra weighted bilinearly, which under D65 is the bilinear\n * interpolation of the pixels' linear sRGB; `nearest` takes the pixel under the point. The print's edge pixels extend to\n * its edges (clamp to edge).\n *\n * Print-local coordinates are the chart's (cu = ±1 at the left and right edges, cv up, ±aspect at the top and bottom); the\n * pixel coordinates are X = (cu + 1)·W/2 and Y = (aspect − cv)·H/(2·aspect), with pixel centers at half-integers.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { portablePow } from \"../core/portable-math.js\";\nimport { FULL_RESOLUTION_CEILING_PIXELS, FULL_RESOLUTION_DEFAULT_PIXELS, resolveRaisedLimit } from \"../core/pixel-limits.js\";\nimport { IMAGE_PLANE_LATTICE_CODES } from \"./image-plane-lattice-data.js\";\nimport { CHART_SIZE_DEFAULT_SURROUND_REFLECTANCE, resolveChartSizeOption, type ImagePlaneLitScene, type ImagePlaneSignalScene, type ImagePlaneSpectralNodes, type ResolvedImagePlaneScene } from \"./scene-radiance.js\";\nimport type { ResolvedMixedIllumination } from \"./mixed-illumination.js\";\n\n/** Version of the print reflectance lattice and its data; a change to any node spectrum changes it. */\nexport const IMAGE_PLANE_LATTICE_VERSION = \"1.0.0\";\n/** Engine defaults of an image-plane scene. */\nexport const IMAGE_PLANE_DEFAULTS = /* @__PURE__ */ Object.freeze({ paperWhiteReflectance: 0.9, paperBlackReflectance: 0.01, interpolation: \"bilinear\" as const });\n\n/** Host bytes of the per-pixel signal rows a signal scene keeps (the direct path's query points revisit nearby pixels). */\nconst SIGNAL_ROW_CACHE_BYTES = 32 << 20;\nconst AXIS = 5, NODES = 125, SAMPLES = 41, MINIMUM_NM = 380, STEP_NM = 10, MAXIMUM_NM = MINIMUM_NM + STEP_NM * (SAMPLES - 1);\n\n/** The sRGB EOTF with the portable power. */\nfunction decodeSrgb(encoded: number): number {\n return encoded <= 0.04045 ? encoded / 12.92 : portablePow((encoded + 0.055) / 1.055, 2.4);\n}\n/** The lattice's node levels in linear sRGB. */\nconst LEVELS = /* @__PURE__ */ Float64Array.from({ length: AXIS }, (_, k) => (k === 0 ? 0 : k === AXIS - 1 ? 1 : decodeSrgb(k / (AXIS - 1))));\n\nlet nodeSpectra: Float64Array | null = null;\n/** The 125 node spectra, 41 samples each (node index r·25 + g·5 + b), decoded once from the data module. */\nfunction spectra(): Float64Array {\n if (nodeSpectra) return nodeSpectra;\n const out = new Float64Array(NODES * SAMPLES), rows = IMAGE_PLANE_LATTICE_CODES.split(\";\");\n if (rows.length !== NODES - AXIS) throw new InvalidConfigurationError(\"The image-plane lattice data is damaged.\");\n let row = 0;\n for (let node = 0; node < NODES; node++) {\n const r = Math.floor(node / 25), g = Math.floor(node / 5) % 5, b = node % 5;\n if (r === g && g === b) { out.fill(LEVELS[r]!, node * SAMPLES, (node + 1) * SAMPLES); continue; }\n const deltas = rows[row++]!.split(\",\");\n if (deltas.length !== SAMPLES) throw new InvalidConfigurationError(\"The image-plane lattice data is damaged.\");\n let code = 0;\n for (let i = 0; i < SAMPLES; i++) {\n code += parseInt(deltas[i]!, 36);\n if (!(code >= 0 && code <= 65535)) throw new InvalidConfigurationError(\"The image-plane lattice data is damaged.\");\n out[node * SAMPLES + i] = code / 65535;\n }\n }\n return (nodeSpectra = out);\n}\n\n/** Internal (for tests and docs): the node spectra as 125 rows of 41 reflectances at 380, 390, …, 780 nm. */\nexport function imagePlaneLatticeSpectra(): { levels: readonly number[]; wavelengthsNm: readonly number[]; spectra: readonly Float64Array[] } {\n const all = spectra();\n return { levels: Array.from(LEVELS), wavelengthsNm: Array.from({ length: SAMPLES }, (_, i) => MINIMUM_NM + STEP_NM * i),\n spectra: Array.from({ length: NODES }, (_, k) => all.slice(k * SAMPLES, (k + 1) * SAMPLES)) };\n}\n\n/** Every node's reflectance at one wavelength (the samples linearly interpolated). */\nfunction nodeReflectancesAt(nm: number): Float64Array {\n if (typeof nm !== \"number\" || !(nm >= MINIMUM_NM && nm <= MAXIMUM_NM)) throw new InvalidConfigurationError(\"An image-plane print is defined on \" + MINIMUM_NM + \"–\" + MAXIMUM_NM + \" nm.\");\n const all = spectra(), p = (nm - MINIMUM_NM) / STEP_NM, i = Math.min(SAMPLES - 2, Math.floor(p)), f = p - i, out = new Float64Array(NODES);\n for (let k = 0; k < NODES; k++) out[k] = all[k * SAMPLES + i]! * (1 - f) + all[k * SAMPLES + i + 1]! * f;\n return out;\n}\n\n/** The image's size, validated (the facade needs the aspect before the print's placement). */\nexport function readImagePlaneSize(value: unknown): { width: number; height: number } {\n if (typeof value !== \"object\" || value === null) throw new InvalidConfigurationError(\"scene must be an object.\");\n const image = (value as { image?: unknown }).image;\n if (typeof image !== \"object\" || image === null) throw new InvalidConfigurationError(\"An image-plane scene needs image { width, height, channels, encoding, data }.\");\n const { width, height } = image as Record<string, unknown>;\n for (const [name, v] of [[\"width\", width], [\"height\", height]] as const)\n if (typeof v !== \"number\" || !Number.isSafeInteger(v) || v < 1 || v > 65_536) throw new InvalidConfigurationError(\"scene.image.\" + name + \" must be an integer from 1 to 65536.\");\n return { width: width as number, height: height as number };\n}\n\n/**\n * Validates an image-plane scene and prepares it on a print of aspect `aspect` (height / width): the digest of its data, the\n * count of clipped `linear-srgb` samples, and the decoders. The data is borrowed (read on every lookup, never written).\n */\nexport async function resolveImagePlaneScene(value: unknown, aspect: number,\n assume?: (id: string, kind: \"default\" | \"model\" | \"derived\", value: unknown, explanation: string) => void): Promise<ResolvedImagePlaneScene> {\n const record = value as Record<string, unknown>;\n for (const key of Object.keys(record)) if (![\"kind\", \"sceneId\", \"image\", \"paper\", \"interpolation\", \"maximumPixels\"].includes(key)) throw new InvalidConfigurationError(\"Unknown scene field: \" + key + \".\");\n if (typeof record.sceneId !== \"string\" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/.test(record.sceneId)) throw new InvalidConfigurationError(\"An image-plane scene needs a public sceneId.\");\n const { width, height } = readImagePlaneSize(record);\n const image = record.image as Record<string, unknown>;\n for (const key of Object.keys(image)) if (![\"width\", \"height\", \"channels\", \"encoding\", \"data\"].includes(key)) throw new InvalidConfigurationError(\"Unknown scene.image field: \" + key + \".\");\n const maximumPixels = resolveRaisedLimit(record.maximumPixels, FULL_RESOLUTION_DEFAULT_PIXELS, FULL_RESOLUTION_CEILING_PIXELS,\n \"scene.maximumPixels must be an integer from 1 to \" + FULL_RESOLUTION_CEILING_PIXELS + \".\");\n if (width * height > maximumPixels) throw new InvalidConfigurationError(\"The image has \" + width * height + \" pixels, above scene.maximumPixels (\" + maximumPixels + \").\");\n const channelsValue = image.channels, encoding = image.encoding, data = image.data;\n if (channelsValue !== 3 && channelsValue !== 4) throw new InvalidConfigurationError(\"scene.image.channels must be 3 (RGB) or 4 (RGBA).\");\n const typeOk = encoding === \"srgb-8\" ? data instanceof Uint8Array || data instanceof Uint8ClampedArray : encoding === \"srgb-16\" ? data instanceof Uint16Array :\n encoding === \"linear-srgb\" ? data instanceof Float32Array : undefined;\n if (typeOk === undefined) throw new InvalidConfigurationError(\"scene.image.encoding must be \\\"srgb-8\\\", \\\"srgb-16\\\" or \\\"linear-srgb\\\".\");\n if (!typeOk) throw new InvalidConfigurationError(\"scene.image.data must be a \" + (encoding === \"srgb-8\" ? \"Uint8Array or Uint8ClampedArray\" : encoding === \"srgb-16\" ? \"Uint16Array\" : \"Float32Array\") + \" for \" + encoding + \".\");\n const channels: 3 | 4 = channelsValue;\n const samples = data as Uint8Array | Uint8ClampedArray | Uint16Array | Float32Array;\n if (samples.length !== width * height * channels) throw new InvalidConfigurationError(\"scene.image.data must hold width × height × channels = \" + width * height * channels + \" samples.\");\n const paperRecord = record.paper;\n if (paperRecord !== undefined && (typeof paperRecord !== \"object\" || paperRecord === null)) throw new InvalidConfigurationError(\"scene.paper must be an object.\");\n const paper = (paperRecord ?? {}) as Record<string, unknown>;\n for (const key of Object.keys(paper)) if (key !== \"whiteReflectance\" && key !== \"blackReflectance\") throw new InvalidConfigurationError(\"Unknown scene.paper field: \" + key + \".\");\n const whiteValue = paper.whiteReflectance ?? IMAGE_PLANE_DEFAULTS.paperWhiteReflectance, blackValue = paper.blackReflectance ?? IMAGE_PLANE_DEFAULTS.paperBlackReflectance;\n if (typeof whiteValue !== \"number\" || typeof blackValue !== \"number\" || !(blackValue >= 0 && blackValue < whiteValue && whiteValue <= 1))\n throw new InvalidConfigurationError(\"scene.paper needs reflectances 0 ≤ blackReflectance < whiteReflectance ≤ 1.\");\n const white: number = whiteValue, black: number = blackValue;\n const interpolation = record.interpolation ?? IMAGE_PLANE_DEFAULTS.interpolation;\n if (interpolation !== \"bilinear\" && interpolation !== \"nearest\") throw new InvalidConfigurationError(\"scene.interpolation must be \\\"bilinear\\\" or \\\"nearest\\\".\");\n if (typeof aspect !== \"number\" || !(aspect > 0) || !Number.isFinite(aspect)) throw new InvalidConfigurationError(\"The print's aspect must be positive.\");\n // Linear input: every sample finite; those outside [0, 1] are clipped and counted.\n let clipped = 0;\n if (encoding === \"linear-srgb\") for (let i = 0; i < samples.length; i++) {\n const v = samples[i]!;\n if (!Number.isFinite(v)) throw new InvalidConfigurationError(\"scene.image.data must be finite (sample \" + i + \").\");\n if (v < 0 || v > 1) clipped++;\n }\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) throw new InvalidConfigurationError(\"An image-plane scene needs crypto.subtle (a secure browser context or Node 22+) to digest the image.\");\n const view = new Uint8Array(samples.buffer, samples.byteOffset, samples.byteLength);\n const digest = new Uint8Array(await subtle.digest(\"SHA-256\", (samples.buffer instanceof ArrayBuffer ? view : view.slice()) as Uint8Array<ArrayBuffer>));\n const dataSha256 = Array.from(digest, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n\n // Decoders: a table per integer encoding (the transfer function once per code), the clip for linear samples.\n const scale = encoding === \"srgb-8\" ? 255 : encoding === \"srgb-16\" ? 65535 : 1;\n const table = encoding === \"linear-srgb\" ? null : Float64Array.from({ length: scale + 1 }, (_, code) => decodeSrgb(code / scale));\n const color = table ? (i: number): number => table[samples[i]!]! : (i: number): number => { const v = samples[i]!; return v <= 0 ? 0 : v >= 1 ? 1 : v; };\n const alpha = channels === 3 ? null : encoding === \"linear-srgb\" ? color : (i: number): number => samples[i]! / scale;\n const rgb = new Float64Array(3), span = white - black;\n const cellOf = (v: number): number => (v > LEVELS[3]! ? 3 : v > LEVELS[2]! ? 2 : v > LEVELS[1]! ? 1 : 0);\n const fractions = new Float64Array(3);\n /** One pixel's lattice cell (its base node, returned) and its fractions in the cell (into `out`). */\n function pixelLattice(index: number, out: Float64Array): number {\n const base = index * channels;\n if (alpha) {\n const a = alpha(base + 3);\n for (let c = 0; c < 3; c++) rgb[c] = a * color(base + c) + (1 - a);\n } else for (let c = 0; c < 3; c++) rgb[c] = color(base + c);\n const kr = cellOf(rgb[0]!), kg = cellOf(rgb[1]!), kb = cellOf(rgb[2]!);\n out[0] = (rgb[0]! - LEVELS[kr]!) / (LEVELS[kr + 1]! - LEVELS[kr]!); out[1] = (rgb[1]! - LEVELS[kg]!) / (LEVELS[kg + 1]! - LEVELS[kg]!); out[2] = (rgb[2]! - LEVELS[kb]!) / (LEVELS[kb + 1]! - LEVELS[kb]!);\n return kr * 25 + kg * 5 + kb;\n }\n /** One pixel in node values: the trilinear weights of its linear sRGB in the lattice cell, then the paper. */\n function pixelValue(index: number, nodeValues: Float64Array, neutral: number): number {\n const n = pixelLattice(index, fractions), fr = fractions[0]!, fg = fractions[1]!, fb = fractions[2]!;\n const lattice = (1 - fr) * ((1 - fg) * ((1 - fb) * nodeValues[n]! + fb * nodeValues[n + 1]!) + fg * ((1 - fb) * nodeValues[n + 5]! + fb * nodeValues[n + 6]!)) +\n fr * ((1 - fg) * ((1 - fb) * nodeValues[n + 25]! + fb * nodeValues[n + 26]!) + fg * ((1 - fb) * nodeValues[n + 30]! + fb * nodeValues[n + 31]!));\n return black * neutral + span * lattice;\n }\n const halfW = width / 2, halfH = height / (2 * aspect);\n /** The print at a print-local point from a per-pixel value: bilinear between pixel centers (clamped to the edge) or the nearest pixel. */\n function interpolate(cu: number, cv: number, at: (index: number) => number): number {\n const X = (cu + 1) * halfW, Y = (aspect - cv) * halfH;\n if (interpolation === \"nearest\") return at(Math.min(height - 1, Math.max(0, Math.floor(Y))) * width + Math.min(width - 1, Math.max(0, Math.floor(X))));\n const sx = X - 0.5, sy = Y - 0.5, i0 = Math.floor(sx), j0 = Math.floor(sy), fx = sx - i0, fy = sy - j0;\n const ia = Math.min(width - 1, Math.max(0, i0)), ib = Math.min(width - 1, Math.max(0, i0 + 1));\n const ja = Math.min(height - 1, Math.max(0, j0)) * width, jb = Math.min(height - 1, Math.max(0, j0 + 1)) * width;\n return (1 - fy) * ((1 - fx) * at(ja + ia) + fx * at(ja + ib)) + fy * ((1 - fx) * at(jb + ia) + fx * at(jb + ib));\n }\n const sampleAt = (cu: number, cv: number, nodeValues: Float64Array, neutral: number): number => interpolate(cu, cv, (index) => pixelValue(index, nodeValues, neutral));\n // Per wavelength the node reflectances (the facade asks for a few spectral nodes many times), and (#597) each pixel's reflectance\n // there, kept by pixel row as the queries reach it: a spectrum cache (no channel value), the same value `pixelValue` gives.\n const atWavelength = new Map<number, (index: number) => number>(), spectrumRows = new Map<number, Float64Array>();\n const keptSpectrumRows = Math.max(8, Math.floor(SIGNAL_ROW_CACHE_BYTES / (width * 8)));\n function reflectanceAt(cu: number, cv: number, nm: number): number {\n let reader = atWavelength.get(nm);\n if (!reader) {\n const nodes = nodeReflectancesAt(nm), slot = atWavelength.size * height;\n const kept = atWavelength.size < 4096;\n // The two latest rows of this wavelength are held apart (a bilinear point reads two rows).\n let keyA = -1, rowA: Float64Array = new Float64Array(0), keyB = -1, rowB = rowA;\n reader = !kept ? (index: number): number => pixelValue(index, nodes, 1) : (index: number): number => {\n const j = Math.floor(index / width), key = slot + j, i = index - j * width;\n let row: Float64Array;\n if (key === keyA) row = rowA;\n else if (key === keyB) row = rowB;\n else {\n let found = spectrumRows.get(key);\n if (!found) { found = new Float64Array(width).fill(NaN); spectrumRows.set(key, found); if (spectrumRows.size > keptSpectrumRows) spectrumRows.delete(spectrumRows.keys().next().value!); }\n keyB = keyA; rowB = rowA; keyA = key; rowA = row = found;\n }\n const value = row[i]!;\n return value === value ? value : (row[i] = pixelValue(index, nodes, 1));\n };\n if (kept) atWavelength.set(nm, reader);\n }\n return interpolate(cu, cv, reader);\n }\n /**\n * One pixel's channel signals, integrated from its reconstructed spectrum (owner decision 2026-11-09): per spectral node n its\n * reflectance ρ_n (its cell's eight node spectra at λ_n blended with the trilinear weights, then the paper) times the white\n * radiance W_n, then per channel Σ_n A_c(λ_n)·ρ_n·W_n. Written to out[at..at + 2].\n */\n function pixelSignals(index: number, nodes: ImagePlaneSpectralNodes, out: Float64Array, at: number): void {\n const N = nodes.count, R = nodes.nodeSpectra, W = nodes.whiteRadiance, A0 = nodes.response[0]!, A1 = nodes.response[1]!, A2 = nodes.response[2]!;\n const base = pixelLattice(index, fractions) * N, fr = fractions[0]!, fg = fractions[1]!, fb = fractions[2]!, gb = 1 - fb;\n const a00 = (1 - fr) * (1 - fg), a01 = (1 - fr) * fg, a10 = fr * (1 - fg), a11 = fr * fg;\n const w0 = a00 * gb, w1 = a00 * fb, w5 = a01 * gb, w6 = a01 * fb, w25 = a10 * gb, w26 = a10 * fb, w30 = a11 * gb, w31 = a11 * fb;\n let s0 = 0, s1 = 0, s2 = 0;\n for (let n = 0, k = base; n < N; n++, k++) {\n const lattice = w0 * R[k]! + w1 * R[k + N]! + w5 * R[k + 5 * N]! + w6 * R[k + 6 * N]! + w25 * R[k + 25 * N]! + w26 * R[k + 26 * N]! + w30 * R[k + 30 * N]! + w31 * R[k + 31 * N]!;\n // Each channel's sum in node order (one pass over the spectrum).\n const radiance = (black + span * lattice) * W[n]!;\n s0 += A0[n]! * radiance; s1 += A1[n]! * radiance; s2 += A2[n]! * radiance;\n }\n out[at] = s0; out[at + 1] = s1; out[at + 2] = s2;\n }\n function signalScene(wavelengths: readonly number[], perNode: readonly Float64Array[], whiteRadiance: Float64Array, radianceAt: (u: number, v: number, nm: number) => number,\n scale: number, half: number, surroundReflectance: number, light?: ResolvedMixedIllumination | null): ImagePlaneSignalScene | ImagePlaneLitScene {\n // The lattice's spectra at the nodes (node k's reflectance at λ_n at k·N + n); no channel response is folded in.\n const N = wavelengths.length, spectraAt = wavelengths.map((nm) => nodeReflectancesAt(nm)), nodeSpectra = new Float64Array(NODES * N);\n for (let k = 0; k < NODES; k++) for (let n = 0; n < N; n++) nodeSpectra[k * N + n] = spectraAt[n]![k]!;\n const nodes: ImagePlaneSpectralNodes = { count: N, nodeSpectra, whiteRadiance, response: perNode };\n // The surround's channel signals, integrated from its spectrum ρ·W_n like a pixel's (no white-integral shortcut, 2.21.0).\n const surround = [0, 1, 2].map((c) => { let s = 0; for (let n = 0; n < N; n++) s += perNode[c]![n]! * (surroundReflectance * whiteRadiance[n]!); return s; }) as [number, number, number];\n // #597: under mixed light, the lit radiance alone (each site integrates it at use) and the print with the light's parts for the GPU pass.\n if (light !== undefined) return { kind: \"radiance\", radianceAt, image: { scene: resolved, nodes, surround, whiteRadiance, surroundReflectance, light: { layout: light, halfWidthM: half } } };\n // The pixels' signals as the query points reach them: rows of three values per pixel (NaN until computed), the latest rows kept.\n const rows = new Map<number, Float64Array>(), keptRows = Math.max(8, Math.floor(SIGNAL_ROW_CACHE_BYTES / (width * 24)));\n let lastJ = -1, lastRow: Float64Array = new Float64Array(0);\n const rowAt = (j: number): Float64Array => {\n if (j === lastJ) return lastRow;\n let row = rows.get(j);\n if (!row) { row = new Float64Array(width * 3).fill(NaN); rows.set(j, row); if (rows.size > keptRows) rows.delete(rows.keys().next().value!); }\n lastJ = j; lastRow = row;\n return row;\n };\n const signalOf = (row: Float64Array, j: number, i: number, c: number): number => {\n if (row[i * 3] !== row[i * 3]) pixelSignals(j * width + i, nodes, row, i * 3);\n return row[i * 3 + c]!;\n };\n return { kind: \"radiance\", radianceAt, signalAt(u: number, v: number, c: number): number {\n const cu = u * scale / half, cv = v * scale / half;\n if (!(Math.abs(cu) <= 1 && Math.abs(cv) <= aspect)) return surround[c]!;\n // As `interpolate`, reading the pixels' signals.\n const X = (cu + 1) * halfW, Y = (aspect - cv) * halfH;\n if (interpolation === \"nearest\") { const j = Math.min(height - 1, Math.max(0, Math.floor(Y))); return signalOf(rowAt(j), j, Math.min(width - 1, Math.max(0, Math.floor(X))), c); }\n const sx = X - 0.5, sy = Y - 0.5, i0 = Math.floor(sx), j0 = Math.floor(sy), fx = sx - i0, fy = sy - j0;\n const ia = Math.min(width - 1, Math.max(0, i0)), ib = Math.min(width - 1, Math.max(0, i0 + 1)), ja = Math.min(height - 1, Math.max(0, j0)), jb = Math.min(height - 1, Math.max(0, j0 + 1));\n const rowA = rowAt(ja), a0 = signalOf(rowA, ja, ia, c), a1 = signalOf(rowA, ja, ib, c), rowB = rowAt(jb);\n return (1 - fy) * ((1 - fx) * a0 + fx * a1) + fy * ((1 - fx) * signalOf(rowB, jb, ia, c) + fx * signalOf(rowB, jb, ib, c));\n }, image: { scene: resolved, nodes, surround, whiteRadiance, surroundReflectance } };\n }\n const resolved: ResolvedImagePlaneScene = Object.freeze({ kind: \"image-plane\" as const, sceneId: record.sceneId, width, height, aspect, channels, encoding: encoding as ResolvedImagePlaneScene[\"encoding\"],\n interpolation, paperWhiteReflectance: white, paperBlackReflectance: black, maximumPixels, clippedSampleCount: clipped, dataSha256,\n reflectanceAt, sampleAt, pixelValue, pixelSignals, pixelLattice, nodeReflectances: nodeReflectancesAt, signalScene: signalScene as ResolvedImagePlaneScene[\"signalScene\"], get digestForm() { return imagePlaneDigestForm(resolved); }, parameters: Object.freeze({ width, height, channels, encoding, interpolation, paperWhiteReflectance: white, paperBlackReflectance: black,\n clippedSampleCount: clipped, imageSha256: dataSha256 }) });\n if (assume) for (const [id, kind, v, explanation] of imagePlaneAssumptions(resolved, record)) assume(id, kind, v, explanation);\n return resolved;\n}\n\n/** The scene's form in the facade's source digest: the image's SHA-256 and shape, the paper, the interpolation and the lattice version. */\nexport function imagePlaneDigestForm(scene: ResolvedImagePlaneScene): Record<string, unknown> {\n return { kind: scene.kind, sceneId: scene.sceneId, image: { width: scene.width, height: scene.height, channels: scene.channels, encoding: scene.encoding, sha256: scene.dataSha256 },\n paper: { whiteReflectance: scene.paperWhiteReflectance, blackReflectance: scene.paperBlackReflectance }, interpolation: scene.interpolation, latticeVersion: IMAGE_PLANE_LATTICE_VERSION };\n}\n\n/** The assumptions an image-plane capture records: the model, the defaults taken, and the clipped linear samples. */\nexport function imagePlaneAssumptions(scene: ResolvedImagePlaneScene, record: Record<string, unknown>): [string, \"default\" | \"model\" | \"derived\", unknown, string][] {\n const out: [string, \"default\" | \"model\" | \"derived\", unknown, string][] = [];\n const paper = (record.paper ?? {}) as Record<string, unknown>;\n if (paper.whiteReflectance === undefined) out.push([\"scene.paper.whiteReflectance\", \"default\", scene.paperWhiteReflectance,\n \"Photivra's assumption, not a measurement: the paper reflects 90 % (the white of the engine's Studio Gray 1 patch), so sRGB white prints as a 0.90 flat reflectance.\"]);\n if (paper.blackReflectance === undefined) out.push([\"scene.paper.blackReflectance\", \"default\", scene.paperBlackReflectance,\n \"Photivra's assumption, not a measurement: the deepest ink reflects 1 % (an optical density of 2.0), so sRGB black prints as a 0.01 flat reflectance.\"]);\n if (record.interpolation === undefined) out.push([\"scene.interpolation\", \"default\", scene.interpolation,\n \"Bilinear between pixel centers: the four nearest pixels' reflectance spectra, bilinearly weighted (under CIE D65, the bilinear interpolation of their linear sRGB); the edge pixels extend to the print's edges.\"]);\n out.push([\"scene.imagePlane\", \"model\", { latticeVersion: IMAGE_PLANE_LATTICE_VERSION, nodesPerAxis: AXIS, method: \"lhtss-burns-2020\", wavelengthStepNanometers: STEP_NM,\n width: scene.width, height: scene.height, encoding: scene.encoding, channels: scene.channels },\n \"An approximation: a print of the image, which was already processed, clipped and blurred by the camera that took it. Each pixel is decoded to linear sRGB \" +\n (scene.encoding === \"linear-srgb\" ? \"(given linear, clipped to [0, 1])\" : \"with the sRGB transfer function (IEC 61966-2-1)\") + (scene.channels === 4 ? \", composited over the paper by its alpha,\" : \"\") +\n \" and becomes a reflectance spectrum by trilinear interpolation in a 5 × 5 × 5 lattice of smooth spectra (Burns' LHTSS method, arXiv:1710.05732 v5, fitted by Photivra against CIE D65 and the \" +\n \"CIE 1931 2° observer), which reproduces the pixel's sRGB under D65 within CIEDE2000 6.4e-4 and stays in [0, 1]; then ρ = black + (white − black)·ρ. Under other lights its colors are one plausible \" +\n \"metamer of many (docs/IMAGE_PLANE.md, measured spread). A flat matte Lambertian print: no gloss, paper texture, halftone, curl or fluorescence.\"]);\n out.push([\"scene.digest\", \"model\", \"image-data-hashed\", \"The source digest covers the image's SHA-256, size, channels and encoding, the paper, the interpolation, the lattice version and the framing.\"]);\n if (scene.clippedSampleCount > 0) out.push([\"scene.image.clippedSamples\", \"derived\", scene.clippedSampleCount,\n \"Linear samples outside [0, 1] clipped to the print's range (a print cannot be brighter than its paper or darker than its deepest ink).\"]);\n return out;\n}\n\n/** The GPU display view's image-plane module, loaded on demand by the GPU renderer (its own chunk). */\nexport function loadGpuModule(): Promise<typeof import(\"../gpu/display-view-image-material-module.js\")> {\n return import(\"../gpu/display-view-image-material-module.js\");\n}\n\n/**\n * The print's placement: `chartSize` with its height defaulting to the image's aspect, or, without it, the print fitted inside\n * the frame (centered, filling its width or height) on the default surround; records the defaults it takes.\n */\nexport function imagePlanePrint(scene: unknown, chartSize: unknown, framedWidthM: number, frameAspect: number,\n assume: (id: string, kind: \"default\", value: unknown, explanation: string) => void): ReturnType<typeof resolveChartSizeOption> {\n const size = readImagePlaneSize(scene), imageAspect = size.height / size.width;\n if (chartSize !== undefined) {\n const resolved = resolveChartSizeOption(chartSize, imageAspect);\n if (resolved.defaulted.includes(\"heightM\")) assume(\"chartSize.heightM\", \"default\", resolved.heightM, \"The print has the image's shape: height = width × image height / image width.\");\n return { ...resolved, defaulted: resolved.defaulted.filter((key) => key !== \"heightM\") };\n }\n const widthM = imageAspect > frameAspect ? framedWidthM * frameAspect / imageAspect : framedWidthM;\n const fitted = { widthM, heightM: widthM * imageAspect, surroundReflectance: CHART_SIZE_DEFAULT_SURROUND_REFLECTANCE, defaulted: [] as (\"heightM\" | \"surroundReflectance\")[] };\n assume(\"chartSize\", \"default\", { widthM: fitted.widthM, heightM: fitted.heightM, surroundReflectance: fitted.surroundReflectance },\n \"The print has the image's shape and is fitted inside the frame, centered (it fills the frame's width or height), on an 18 % neutral gray surround.\");\n return fitted;\n}\n"]}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { type CaptureIlluminant, type ResolvedCaptureIlluminant } from "./scene-radiance.js";
|
|
2
|
+
/** Most sources an `illumination` may list. */
|
|
3
|
+
export declare const MIXED_ILLUMINATION_MAX_SOURCES = 8;
|
|
4
|
+
/** Most regions a `regions` blend may list. */
|
|
5
|
+
export declare const MIXED_ILLUMINATION_MAX_REGIONS = 64;
|
|
6
|
+
/** One light source of a mixed illumination: an illuminant (as `simulateCapture` `illuminant` takes it) at an illuminance. */
|
|
7
|
+
export interface MixedIlluminationSource {
|
|
8
|
+
illuminant: CaptureIlluminant;
|
|
9
|
+
/** Illuminance this source alone gives where its weight is 1, lux, (0, 1e7]. */
|
|
10
|
+
illuminanceLux: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 2.22 (#550): a point light on the scene plane's front side: an illuminant spectrum, a position in metres (`xM`, `yM` on the plane
|
|
14
|
+
* from the optical axis, +x right and +y up as seen from the camera; `heightM` > 0 in front of the plane, toward the camera) and an
|
|
15
|
+
* intensity, either in candela or as the illuminance it gives at normal incidence at a reference distance (I = E·r²).
|
|
16
|
+
*/
|
|
17
|
+
export interface MixedIlluminationPointSource {
|
|
18
|
+
illuminant: CaptureIlluminant;
|
|
19
|
+
position: {
|
|
20
|
+
xM: number;
|
|
21
|
+
yM: number;
|
|
22
|
+
heightM: number;
|
|
23
|
+
};
|
|
24
|
+
intensity: {
|
|
25
|
+
candela: number;
|
|
26
|
+
} | {
|
|
27
|
+
illuminanceLux: number;
|
|
28
|
+
distanceM: number;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** A point in chart coordinates (see {@link MixedIllumination}). */
|
|
32
|
+
export interface MixedIlluminationPoint {
|
|
33
|
+
u: number;
|
|
34
|
+
v: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* How the sources blend across the chart. `linear-gradient` and `radial` map a point to a position t in [0, 1] (its projection
|
|
38
|
+
* onto `from` → `to`, clamped; or its distance from `center` over `radius`, clamped) and crossfade linearly between consecutive
|
|
39
|
+
* sources at their `stops` (one per source, non-decreasing in [0, 1]; default evenly spaced from 0 to 1): source 0 alone up to
|
|
40
|
+
* stops[0], the last source alone from its stop on, and two equal stops a hard edge (the later source from the stop on).
|
|
41
|
+
* `regions` gives each point the source of the first rectangle that contains it (bounds inclusive) and `outsideSource` elsewhere.
|
|
42
|
+
*/
|
|
43
|
+
export type MixedIlluminationBlend = {
|
|
44
|
+
kind: "linear-gradient";
|
|
45
|
+
from: MixedIlluminationPoint;
|
|
46
|
+
to: MixedIlluminationPoint;
|
|
47
|
+
stops?: readonly number[];
|
|
48
|
+
} | {
|
|
49
|
+
kind: "radial";
|
|
50
|
+
center?: MixedIlluminationPoint;
|
|
51
|
+
radius: number;
|
|
52
|
+
stops?: readonly number[];
|
|
53
|
+
} | {
|
|
54
|
+
kind: "regions";
|
|
55
|
+
regions: readonly {
|
|
56
|
+
source: number;
|
|
57
|
+
uMin: number;
|
|
58
|
+
uMax: number;
|
|
59
|
+
vMin: number;
|
|
60
|
+
vMax: number;
|
|
61
|
+
}[];
|
|
62
|
+
outsideSource: number;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* 2.22 (#550), `simulateCapture` `illumination`: sources blended across the chart and point sources with inverse-square falloff
|
|
66
|
+
* (docs/MIXED_ILLUMINATION.md). It replaces `illuminant` and `illuminanceLux`. `sources` lists 1 to 8 sources (with two or more, a
|
|
67
|
+
* `blend` is required; one lights the whole plane); `points` lists 1 to 8 point sources; a request needs two or more sources or at least one point. Blend
|
|
68
|
+
* coordinates are chart-local with `chartSize` and frame units without it; (0, 0) is the frame center.
|
|
69
|
+
*/
|
|
70
|
+
export interface MixedIllumination {
|
|
71
|
+
sources?: readonly MixedIlluminationSource[];
|
|
72
|
+
blend?: MixedIlluminationBlend;
|
|
73
|
+
points?: readonly MixedIlluminationPointSource[];
|
|
74
|
+
}
|
|
75
|
+
/** Internal: a validated mixed illumination with its lights resolved and scaled. */
|
|
76
|
+
export interface ResolvedMixedIllumination {
|
|
77
|
+
/**
|
|
78
|
+
* The lights, the blend's sources first and then the point sources: each with the illuminance it gives at the frame center when
|
|
79
|
+
* it lights it alone (a point source's I·cos θ/d²) and the scale k with k·S(λ) that light's irradiance there; `report` is its
|
|
80
|
+
* public form (the assumption's and the digest's).
|
|
81
|
+
*/
|
|
82
|
+
sources: readonly {
|
|
83
|
+
illuminant: ResolvedCaptureIlluminant;
|
|
84
|
+
option: CaptureIlluminant;
|
|
85
|
+
illuminanceLux: number;
|
|
86
|
+
irradianceScale: number;
|
|
87
|
+
report: Readonly<Record<string, unknown>>;
|
|
88
|
+
}[];
|
|
89
|
+
/** The blend with its defaults filled, or null (one source or none). */
|
|
90
|
+
blend: Readonly<Record<string, unknown>> | null;
|
|
91
|
+
/** Spectral irradiance at a plane point, W·m⁻²·nm⁻¹: (u, v) chart coordinates for the blend, (xM, yM) metres for the point sources. */
|
|
92
|
+
irradianceAt(u: number, v: number, xM: number, yM: number, wavelengthNanometers: number): number;
|
|
93
|
+
/**
|
|
94
|
+
* At the frame center: the illuminance, the blend's source weights, each light's illuminance there (w_i·E_i; a point's
|
|
95
|
+
* I·cos θ/d²) and the strongest light (the largest, the first on a tie; an index into `sources`).
|
|
96
|
+
*/
|
|
97
|
+
center: {
|
|
98
|
+
illuminanceLux: number;
|
|
99
|
+
weights: number[];
|
|
100
|
+
illuminancesLux: number[];
|
|
101
|
+
strongestSource: number;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Internal: validates `illumination` and resolves its sources with `resolveIlluminant` (the capture's `resolveCaptureIlluminant`, or
|
|
106
|
+
* the display view's portable one).
|
|
107
|
+
*/
|
|
108
|
+
export declare function resolveMixedIllumination(value: unknown, resolveIlluminant: (value: CaptureIlluminant) => ResolvedCaptureIlluminant): ResolvedMixedIllumination;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* 2.22 (#550): spatially varying illumination of the scene plane (mixed lighting), loaded on demand by `simulateCapture` and the
|
|
4
|
+
* display view only when a request has `illumination`, so requests without it neither load nor run it.
|
|
5
|
+
*
|
|
6
|
+
* Model: N sources (1 to {@link MIXED_ILLUMINATION_MAX_SOURCES}; one lights the whole plane), source i an illuminant spectral shape S_i(λ) scaled to
|
|
7
|
+
* `illuminanceLux` E_i exactly as the single illuminant is (`calculateIlluminantIrradianceScale`: k_i with 683 ∫ k_i S_i ȳ dλ = E_i).
|
|
8
|
+
* The plane's spectral irradiance at a point p is the declared blend E(p, λ) = Σ_i w_i(p)·k_i·S_i(λ) with weights w_i(p) ≥ 0 that
|
|
9
|
+
* sum to 1, so the illuminance at p is Σ_i w_i(p)·E_i and, where one weight is 1, the light is exactly that source's. A Lambertian
|
|
10
|
+
* reflector then has radiance ρ(λ)·E(p, λ)/π, as under one illuminant. The blend is a declared crossfade of irradiance, not a
|
|
11
|
+
* model of how light falls off from a lamp or a window (no inverse-square law, no cosine falloff, no shadows); it is exact for
|
|
12
|
+
* what it declares.
|
|
13
|
+
*
|
|
14
|
+
* Point sources (owner decision 2026-11-10, a step toward flash): source j is a point at height h_j in front of the plane above
|
|
15
|
+
* plane point (x_j, y_j) m, with luminous intensity I_j cd (the same in every direction toward the plane) and spectral shape S_j(λ),
|
|
16
|
+
* scaled so that 683 ∫ c_j S_j ȳ dλ = I_j. A point p of the plane at distance d from it receives E_j(p, λ) = c_j·S_j(λ)·cos θ/d²,
|
|
17
|
+
* with cos θ = h_j/d: the inverse-square law with Lambert's cosine law, which follows from the definitions of luminous intensity
|
|
18
|
+
* (flux per solid angle) and illuminance (flux per area) with the solid angle dΩ = dA·cos θ/d² that a plane element subtends (CIE S
|
|
19
|
+
* 017:2020 ILV, International Lighting Vocabulary, entries "luminous intensity" and "illuminance", free at e-ilv.cie.co.at; BIPM SI
|
|
20
|
+
* Brochure, 9th edition 2019, Table 4, the steradian). Exact for an ideal isotropic point; no occlusion (the camera casts no shadow),
|
|
21
|
+
* no source size and no inter-reflection. The point sources add to the blend: E(p, λ) = Σ_i w_i(p)·k_i·S_i(λ) + Σ_j E_j(p, λ).
|
|
22
|
+
*
|
|
23
|
+
* Coordinates are the chart's: a fixed-size chart's chart-local units (±1 at its left and right edges, v up on the same scale,
|
|
24
|
+
* extended linearly over the surround), or, without `chartSize`, frame units (±1 at the frame's left and right edges), which are
|
|
25
|
+
* the chart-local units of a chart that fills the frame. Both put (0, 0) at the frame center.
|
|
26
|
+
*/
|
|
27
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
28
|
+
import { requireInputObject } from "../core/record-validation.js";
|
|
29
|
+
import { calculateIlluminantIrradianceScale, tabulatedSpectrum } from "./scene-radiance.js";
|
|
30
|
+
/** Most sources an `illumination` may list. */
|
|
31
|
+
export const MIXED_ILLUMINATION_MAX_SOURCES = 8;
|
|
32
|
+
/** Most regions a `regions` blend may list. */
|
|
33
|
+
export const MIXED_ILLUMINATION_MAX_REGIONS = 64;
|
|
34
|
+
const fail = (message) => { throw new InvalidConfigurationError(message); };
|
|
35
|
+
/** A record with no other fields than these (`name` relative to `illumination`). */
|
|
36
|
+
const fields = (value, name, keys) => {
|
|
37
|
+
requireInputObject(value, "illumination" + name);
|
|
38
|
+
for (const key of Object.keys(value))
|
|
39
|
+
if (!keys.includes(key))
|
|
40
|
+
fail("Unknown illumination" + name + " field: " + key + ".");
|
|
41
|
+
return value;
|
|
42
|
+
};
|
|
43
|
+
const finite = (x, name) => (typeof x === "number" && Number.isFinite(x) && Math.abs(x) <= 1e6 ? x : fail("illumination" + name + " must be a finite number."));
|
|
44
|
+
const positive = (x, name, maximum) => (typeof x === "number" && x > 0 && x <= maximum ? x : fail("illumination" + name + " must be positive, up to " + maximum + "."));
|
|
45
|
+
const list = (value, name, what) => (value === undefined ? [] : Array.isArray(value) && value.length >= 1 && value.length <= MIXED_ILLUMINATION_MAX_SOURCES ? value :
|
|
46
|
+
fail("illumination." + name + " must list 1 to " + MIXED_ILLUMINATION_MAX_SOURCES + " " + what + "."));
|
|
47
|
+
const point = (value, name) => {
|
|
48
|
+
const r = fields(value, ".blend." + name, ["u", "v"]);
|
|
49
|
+
return { u: finite(r.u, ".blend." + name + ".u"), v: finite(r.v, ".blend." + name + ".v") };
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Internal: validates `illumination` and resolves its sources with `resolveIlluminant` (the capture's `resolveCaptureIlluminant`, or
|
|
53
|
+
* the display view's portable one).
|
|
54
|
+
*/
|
|
55
|
+
export function resolveMixedIllumination(value, resolveIlluminant) {
|
|
56
|
+
const record = fields(value, "", ["sources", "blend", "points"]), given = list(record.sources, "sources", "sources"), pointList = list(record.points, "points", "point sources");
|
|
57
|
+
if (pointList.length === 0 && given.length < 2)
|
|
58
|
+
fail("illumination needs two or more sources, or a point source; one source alone is illuminant and illuminanceLux.");
|
|
59
|
+
const sources = given.map((entry, i) => {
|
|
60
|
+
const s = fields(entry, ".sources[" + i + "]", ["illuminant", "illuminanceLux"]), option = s.illuminant, illuminant = resolveIlluminant(option);
|
|
61
|
+
return Object.freeze({ illuminant, option, illuminanceLux: s.illuminanceLux, irradianceScale: calculateIlluminantIrradianceScale(illuminant.shape, s.illuminanceLux),
|
|
62
|
+
report: Object.freeze({ illuminant: illuminant.id, illuminanceLux: s.illuminanceLux }) });
|
|
63
|
+
});
|
|
64
|
+
// Point sources: c_j with 683 ∫ c_j S_j ȳ dλ = I_j (the irradiance scale of 1 lux, times I_j), and E_j = c_j S_j(λ)·h/d³.
|
|
65
|
+
const points = pointList.map((entry, j) => {
|
|
66
|
+
const at = ".points[" + j + "]", p = fields(entry, at, ["illuminant", "position", "intensity"]), option = p.illuminant, illuminant = resolveIlluminant(option);
|
|
67
|
+
const q = fields(p.position, at + ".position", ["xM", "yM", "heightM"]), i = fields(p.intensity, at + ".intensity", ["candela", "illuminanceLux", "distanceM"]);
|
|
68
|
+
const position = { xM: finite(q.xM, at + ".position.xM"), yM: finite(q.yM, at + ".position.yM"), heightM: positive(q.heightM, at + ".position.heightM", 1e4) };
|
|
69
|
+
const candela = i.candela !== undefined ? (i.illuminanceLux === undefined && i.distanceM === undefined ? positive(i.candela, at + ".intensity.candela", 1e9) :
|
|
70
|
+
fail("illumination" + at + ".intensity takes candela or illuminanceLux and distanceM, not both.")) :
|
|
71
|
+
positive(i.illuminanceLux, at + ".intensity.illuminanceLux", 1e7) * positive(i.distanceM, at + ".intensity.distanceM", 1e4) ** 2;
|
|
72
|
+
return { illuminant, option, position, candela, scale: calculateIlluminantIrradianceScale(illuminant.shape, 1) * candela, shape: tabulatedSpectrum(illuminant.shape) };
|
|
73
|
+
});
|
|
74
|
+
/** cos θ/d² of point source j at plane point (x, y) m. */
|
|
75
|
+
const falloff = (p, x, y) => {
|
|
76
|
+
const dx = x - p.position.xM, dy = y - p.position.yM, h = p.position.heightM, d2 = dx * dx + dy * dy + h * h;
|
|
77
|
+
return h / (d2 * Math.sqrt(d2));
|
|
78
|
+
};
|
|
79
|
+
const n = sources.length, shapes = sources.map((s) => tabulatedSpectrum(s.illuminant.shape));
|
|
80
|
+
if (n < 2 && record.blend !== undefined)
|
|
81
|
+
fail("illumination.blend needs two or more sources.");
|
|
82
|
+
const b = n < 2 ? { kind: "none" } : fields(record.blend, ".blend", ["kind", "from", "to", "center", "radius", "stops", "regions", "outsideSource"]);
|
|
83
|
+
const index = (x, name) => (Number.isInteger(x) && x >= 0 && x < n ? x : fail("illumination.blend." + name + " must be a source index from 0 to " + (n - 1) + "."));
|
|
84
|
+
const unused = (keys) => { for (const key of keys)
|
|
85
|
+
if (b[key] !== undefined)
|
|
86
|
+
fail("illumination.blend." + key + " does not apply to a " + String(b.kind) + " blend."); };
|
|
87
|
+
// A point's position t on a gradient or radial blend, or its source on a regions blend.
|
|
88
|
+
let position, blend = null, stops;
|
|
89
|
+
if (b.kind === "none")
|
|
90
|
+
position = () => 0;
|
|
91
|
+
else if (b.kind === "regions") {
|
|
92
|
+
unused(["from", "to", "center", "radius", "stops"]);
|
|
93
|
+
const rects = b.regions;
|
|
94
|
+
if (!Array.isArray(rects) || rects.length < 1 || rects.length > MIXED_ILLUMINATION_MAX_REGIONS)
|
|
95
|
+
fail("illumination.blend.regions must list 1 to " + MIXED_ILLUMINATION_MAX_REGIONS + " rectangles.");
|
|
96
|
+
const regions = rects.map((entry, i) => {
|
|
97
|
+
const at = ".blend.regions[" + i + "]", r = fields(entry, at, ["source", "uMin", "uMax", "vMin", "vMax"]);
|
|
98
|
+
const region = { source: index(r.source, "regions[" + i + "].source"), uMin: finite(r.uMin, at + ".uMin"), uMax: finite(r.uMax, at + ".uMax"), vMin: finite(r.vMin, at + ".vMin"), vMax: finite(r.vMax, at + ".vMax") };
|
|
99
|
+
if (!(region.uMin <= region.uMax && region.vMin <= region.vMax))
|
|
100
|
+
fail("illumination" + at + " uMin and vMin must not exceed uMax and vMax.");
|
|
101
|
+
return region;
|
|
102
|
+
});
|
|
103
|
+
const outside = index(b.outsideSource, "outsideSource");
|
|
104
|
+
position = (u, v) => regions.find((r) => u >= r.uMin && u <= r.uMax && v >= r.vMin && v <= r.vMax)?.source ?? outside;
|
|
105
|
+
blend = { kind: "regions", regions, outsideSource: outside };
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
if (b.kind === "linear-gradient") {
|
|
109
|
+
unused(["center", "radius", "regions", "outsideSource"]);
|
|
110
|
+
const from = point(b.from, "from"), to = point(b.to, "to"), du = to.u - from.u, dv = to.v - from.v, length2 = du * du + dv * dv;
|
|
111
|
+
if (!(length2 > 0))
|
|
112
|
+
fail("illumination.blend from and to must differ.");
|
|
113
|
+
position = (u, v) => Math.min(1, Math.max(0, ((u - from.u) * du + (v - from.v) * dv) / length2));
|
|
114
|
+
blend = { kind: b.kind, from, to };
|
|
115
|
+
}
|
|
116
|
+
else if (b.kind === "radial") {
|
|
117
|
+
unused(["from", "to", "regions", "outsideSource"]);
|
|
118
|
+
const center = b.center === undefined ? { u: 0, v: 0 } : point(b.center, "center"), radius = finite(b.radius, ".blend.radius");
|
|
119
|
+
if (!(radius > 0))
|
|
120
|
+
fail("illumination.blend.radius must be positive.");
|
|
121
|
+
position = (u, v) => Math.min(1, Math.hypot(u - center.u, v - center.v) / radius);
|
|
122
|
+
blend = { kind: b.kind, center, radius };
|
|
123
|
+
}
|
|
124
|
+
else
|
|
125
|
+
return fail('illumination.blend.kind must be "linear-gradient", "radial" or "regions".');
|
|
126
|
+
const declared = b.stops;
|
|
127
|
+
if (declared !== undefined && (!Array.isArray(declared) || declared.length !== n))
|
|
128
|
+
fail("illumination.blend.stops must list one stop per source.");
|
|
129
|
+
blend.stops = stops = declared ? declared.map((x, i) => {
|
|
130
|
+
const stop = finite(x, ".blend.stops[" + i + "]");
|
|
131
|
+
return stop >= 0 && stop <= 1 && (i === 0 || stop >= declared[i - 1]) ? stop : fail("illumination.blend.stops must be non-decreasing in [0, 1].");
|
|
132
|
+
}) : sources.map((_, i) => i / (n - 1));
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* The blend at a point: the lower source i and the fraction f of source i + 1 (f = 0: source i alone). On a gradient, the segment
|
|
136
|
+
* [stops[i], stops[i + 1]) that holds t; equal stops are passed over, so the later source takes the stop.
|
|
137
|
+
*/
|
|
138
|
+
const at = (u, v) => {
|
|
139
|
+
const t = position(u, v);
|
|
140
|
+
if (!stops)
|
|
141
|
+
return [t, 0];
|
|
142
|
+
let i = 0;
|
|
143
|
+
while (i < n - 1 && t >= stops[i + 1])
|
|
144
|
+
i++;
|
|
145
|
+
return i === n - 1 || t <= stops[i] ? [i, 0] : [i, (t - stops[i]) / (stops[i + 1] - stops[i])];
|
|
146
|
+
};
|
|
147
|
+
const [i0, f0] = at(0, 0), weights = sources.map((_, i) => (i === i0 ? 1 - f0 : i === i0 + 1 ? f0 : 0));
|
|
148
|
+
// Every light at the frame center, the blend's sources first: a point source's irradiance scale there is c_j·cos θ/d².
|
|
149
|
+
const lights = [...sources, ...points.map((p) => {
|
|
150
|
+
const atCenter = falloff(p, 0, 0);
|
|
151
|
+
return Object.freeze({ illuminant: p.illuminant, option: p.option, illuminanceLux: p.candela * atCenter, irradianceScale: p.scale * atCenter,
|
|
152
|
+
report: Object.freeze({ illuminant: p.illuminant.id, position: p.position, intensityCandela: p.candela }) });
|
|
153
|
+
})];
|
|
154
|
+
const illuminancesLux = lights.map((l, i) => (i < n ? weights[i] * l.illuminanceLux : l.illuminanceLux));
|
|
155
|
+
let strongest = 0, illuminanceLux = 0;
|
|
156
|
+
illuminancesLux.forEach((e, i) => { illuminanceLux += e; if (e > illuminancesLux[strongest])
|
|
157
|
+
strongest = i; });
|
|
158
|
+
/** The blend's irradiance (k·S(λ) itself where one source has weight 1). */
|
|
159
|
+
const ambient = (u, v, nm) => {
|
|
160
|
+
if (n === 0)
|
|
161
|
+
return 0;
|
|
162
|
+
const [i, f] = at(u, v), a = sources[i].irradianceScale * shapes[i](nm);
|
|
163
|
+
return f === 0 ? a : (1 - f) * a + f * (sources[i + 1].irradianceScale * shapes[i + 1](nm));
|
|
164
|
+
};
|
|
165
|
+
return Object.freeze({ sources: Object.freeze(lights), blend: blend && Object.freeze(blend),
|
|
166
|
+
irradianceAt: points.length === 0 ? (u, v, _x, _y, nm) => ambient(u, v, nm) : (u, v, x, y, nm) => {
|
|
167
|
+
let e = ambient(u, v, nm);
|
|
168
|
+
for (const p of points)
|
|
169
|
+
e += p.scale * p.shape(nm) * falloff(p, x, y);
|
|
170
|
+
return e;
|
|
171
|
+
},
|
|
172
|
+
center: Object.freeze({ illuminanceLux, weights, illuminancesLux, strongestSource: strongest }) });
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=mixed-illumination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mixed-illumination.js","sourceRoot":"","sources":["../../src/facade/mixed-illumination.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * 2.22 (#550): spatially varying illumination of the scene plane (mixed lighting), loaded on demand by `simulateCapture` and the\n * display view only when a request has `illumination`, so requests without it neither load nor run it.\n *\n * Model: N sources (1 to {@link MIXED_ILLUMINATION_MAX_SOURCES}; one lights the whole plane), source i an illuminant spectral shape S_i(λ) scaled to\n * `illuminanceLux` E_i exactly as the single illuminant is (`calculateIlluminantIrradianceScale`: k_i with 683 ∫ k_i S_i ȳ dλ = E_i).\n * The plane's spectral irradiance at a point p is the declared blend E(p, λ) = Σ_i w_i(p)·k_i·S_i(λ) with weights w_i(p) ≥ 0 that\n * sum to 1, so the illuminance at p is Σ_i w_i(p)·E_i and, where one weight is 1, the light is exactly that source's. A Lambertian\n * reflector then has radiance ρ(λ)·E(p, λ)/π, as under one illuminant. The blend is a declared crossfade of irradiance, not a\n * model of how light falls off from a lamp or a window (no inverse-square law, no cosine falloff, no shadows); it is exact for\n * what it declares.\n *\n * Point sources (owner decision 2026-11-10, a step toward flash): source j is a point at height h_j in front of the plane above\n * plane point (x_j, y_j) m, with luminous intensity I_j cd (the same in every direction toward the plane) and spectral shape S_j(λ),\n * scaled so that 683 ∫ c_j S_j ȳ dλ = I_j. A point p of the plane at distance d from it receives E_j(p, λ) = c_j·S_j(λ)·cos θ/d²,\n * with cos θ = h_j/d: the inverse-square law with Lambert's cosine law, which follows from the definitions of luminous intensity\n * (flux per solid angle) and illuminance (flux per area) with the solid angle dΩ = dA·cos θ/d² that a plane element subtends (CIE S\n * 017:2020 ILV, International Lighting Vocabulary, entries \"luminous intensity\" and \"illuminance\", free at e-ilv.cie.co.at; BIPM SI\n * Brochure, 9th edition 2019, Table 4, the steradian). Exact for an ideal isotropic point; no occlusion (the camera casts no shadow),\n * no source size and no inter-reflection. The point sources add to the blend: E(p, λ) = Σ_i w_i(p)·k_i·S_i(λ) + Σ_j E_j(p, λ).\n *\n * Coordinates are the chart's: a fixed-size chart's chart-local units (±1 at its left and right edges, v up on the same scale,\n * extended linearly over the surround), or, without `chartSize`, frame units (±1 at the frame's left and right edges), which are\n * the chart-local units of a chart that fills the frame. Both put (0, 0) at the frame center.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireInputObject } from \"../core/record-validation.js\";\nimport { calculateIlluminantIrradianceScale, tabulatedSpectrum, type CaptureIlluminant, type ResolvedCaptureIlluminant } from \"./scene-radiance.js\";\n\n/** Most sources an `illumination` may list. */\nexport const MIXED_ILLUMINATION_MAX_SOURCES = 8;\n/** Most regions a `regions` blend may list. */\nexport const MIXED_ILLUMINATION_MAX_REGIONS = 64;\n\n/** One light source of a mixed illumination: an illuminant (as `simulateCapture` `illuminant` takes it) at an illuminance. */\nexport interface MixedIlluminationSource {\n illuminant: CaptureIlluminant;\n /** Illuminance this source alone gives where its weight is 1, lux, (0, 1e7]. */\n illuminanceLux: number;\n}\n/**\n * 2.22 (#550): a point light on the scene plane's front side: an illuminant spectrum, a position in metres (`xM`, `yM` on the plane\n * from the optical axis, +x right and +y up as seen from the camera; `heightM` > 0 in front of the plane, toward the camera) and an\n * intensity, either in candela or as the illuminance it gives at normal incidence at a reference distance (I = E·r²).\n */\nexport interface MixedIlluminationPointSource {\n illuminant: CaptureIlluminant;\n position: { xM: number; yM: number; heightM: number };\n intensity: { candela: number } | { illuminanceLux: number; distanceM: number };\n}\n/** A point in chart coordinates (see {@link MixedIllumination}). */\nexport interface MixedIlluminationPoint { u: number; v: number }\n/**\n * How the sources blend across the chart. `linear-gradient` and `radial` map a point to a position t in [0, 1] (its projection\n * onto `from` → `to`, clamped; or its distance from `center` over `radius`, clamped) and crossfade linearly between consecutive\n * sources at their `stops` (one per source, non-decreasing in [0, 1]; default evenly spaced from 0 to 1): source 0 alone up to\n * stops[0], the last source alone from its stop on, and two equal stops a hard edge (the later source from the stop on).\n * `regions` gives each point the source of the first rectangle that contains it (bounds inclusive) and `outsideSource` elsewhere.\n */\nexport type MixedIlluminationBlend =\n | { kind: \"linear-gradient\"; from: MixedIlluminationPoint; to: MixedIlluminationPoint; stops?: readonly number[] }\n | { kind: \"radial\"; center?: MixedIlluminationPoint; radius: number; stops?: readonly number[] }\n | { kind: \"regions\"; regions: readonly { source: number; uMin: number; uMax: number; vMin: number; vMax: number }[]; outsideSource: number };\n/**\n * 2.22 (#550), `simulateCapture` `illumination`: sources blended across the chart and point sources with inverse-square falloff\n * (docs/MIXED_ILLUMINATION.md). It replaces `illuminant` and `illuminanceLux`. `sources` lists 1 to 8 sources (with two or more, a\n * `blend` is required; one lights the whole plane); `points` lists 1 to 8 point sources; a request needs two or more sources or at least one point. Blend\n * coordinates are chart-local with `chartSize` and frame units without it; (0, 0) is the frame center.\n */\nexport interface MixedIllumination {\n sources?: readonly MixedIlluminationSource[];\n blend?: MixedIlluminationBlend;\n points?: readonly MixedIlluminationPointSource[];\n}\n\n/** Internal: a validated mixed illumination with its lights resolved and scaled. */\nexport interface ResolvedMixedIllumination {\n /**\n * The lights, the blend's sources first and then the point sources: each with the illuminance it gives at the frame center when\n * it lights it alone (a point source's I·cos θ/d²) and the scale k with k·S(λ) that light's irradiance there; `report` is its\n * public form (the assumption's and the digest's).\n */\n sources: readonly { illuminant: ResolvedCaptureIlluminant; option: CaptureIlluminant; illuminanceLux: number; irradianceScale: number; report: Readonly<Record<string, unknown>> }[];\n /** The blend with its defaults filled, or null (one source or none). */\n blend: Readonly<Record<string, unknown>> | null;\n /** Spectral irradiance at a plane point, W·m⁻²·nm⁻¹: (u, v) chart coordinates for the blend, (xM, yM) metres for the point sources. */\n irradianceAt(u: number, v: number, xM: number, yM: number, wavelengthNanometers: number): number;\n /**\n * At the frame center: the illuminance, the blend's source weights, each light's illuminance there (w_i·E_i; a point's\n * I·cos θ/d²) and the strongest light (the largest, the first on a tie; an index into `sources`).\n */\n center: { illuminanceLux: number; weights: number[]; illuminancesLux: number[]; strongestSource: number };\n}\n\ntype Fields = Record<string, unknown>;\nconst fail = (message: string): never => { throw new InvalidConfigurationError(message); };\n/** A record with no other fields than these (`name` relative to `illumination`). */\nconst fields = (value: unknown, name: string, keys: string[]): Fields => {\n requireInputObject(value, \"illumination\" + name);\n for (const key of Object.keys(value as object)) if (!keys.includes(key)) fail(\"Unknown illumination\" + name + \" field: \" + key + \".\");\n return value as Fields;\n};\nconst finite = (x: unknown, name: string): number => (typeof x === \"number\" && Number.isFinite(x) && Math.abs(x) <= 1e6 ? x : fail(\"illumination\" + name + \" must be a finite number.\"));\nconst positive = (x: unknown, name: string, maximum: number): number => (typeof x === \"number\" && x > 0 && x <= maximum ? x : fail(\"illumination\" + name + \" must be positive, up to \" + maximum + \".\"));\nconst list = (value: unknown, name: string, what: string): unknown[] => (value === undefined ? [] : Array.isArray(value) && value.length >= 1 && value.length <= MIXED_ILLUMINATION_MAX_SOURCES ? value :\n fail(\"illumination.\" + name + \" must list 1 to \" + MIXED_ILLUMINATION_MAX_SOURCES + \" \" + what + \".\"));\nconst point = (value: unknown, name: string): MixedIlluminationPoint => {\n const r = fields(value, \".blend.\" + name, [\"u\", \"v\"]);\n return { u: finite(r.u, \".blend.\" + name + \".u\"), v: finite(r.v, \".blend.\" + name + \".v\") };\n};\n\n/**\n * Internal: validates `illumination` and resolves its sources with `resolveIlluminant` (the capture's `resolveCaptureIlluminant`, or\n * the display view's portable one).\n */\nexport function resolveMixedIllumination(value: unknown, resolveIlluminant: (value: CaptureIlluminant) => ResolvedCaptureIlluminant): ResolvedMixedIllumination {\n const record = fields(value, \"\", [\"sources\", \"blend\", \"points\"]), given = list(record.sources, \"sources\", \"sources\"), pointList = list(record.points, \"points\", \"point sources\");\n if (pointList.length === 0 && given.length < 2) fail(\"illumination needs two or more sources, or a point source; one source alone is illuminant and illuminanceLux.\");\n const sources = given.map((entry, i) => {\n const s = fields(entry, \".sources[\" + i + \"]\", [\"illuminant\", \"illuminanceLux\"]), option = s.illuminant as CaptureIlluminant, illuminant = resolveIlluminant(option);\n return Object.freeze({ illuminant, option, illuminanceLux: s.illuminanceLux as number, irradianceScale: calculateIlluminantIrradianceScale(illuminant.shape, s.illuminanceLux as number),\n report: Object.freeze({ illuminant: illuminant.id, illuminanceLux: s.illuminanceLux }) });\n });\n // Point sources: c_j with 683 ∫ c_j S_j ȳ dλ = I_j (the irradiance scale of 1 lux, times I_j), and E_j = c_j S_j(λ)·h/d³.\n const points = pointList.map((entry, j) => {\n const at = \".points[\" + j + \"]\", p = fields(entry, at, [\"illuminant\", \"position\", \"intensity\"]), option = p.illuminant as CaptureIlluminant, illuminant = resolveIlluminant(option);\n const q = fields(p.position, at + \".position\", [\"xM\", \"yM\", \"heightM\"]), i = fields(p.intensity, at + \".intensity\", [\"candela\", \"illuminanceLux\", \"distanceM\"]);\n const position = { xM: finite(q.xM, at + \".position.xM\"), yM: finite(q.yM, at + \".position.yM\"), heightM: positive(q.heightM, at + \".position.heightM\", 1e4) };\n const candela = i.candela !== undefined ? (i.illuminanceLux === undefined && i.distanceM === undefined ? positive(i.candela, at + \".intensity.candela\", 1e9) :\n fail(\"illumination\" + at + \".intensity takes candela or illuminanceLux and distanceM, not both.\")) :\n positive(i.illuminanceLux, at + \".intensity.illuminanceLux\", 1e7) * positive(i.distanceM, at + \".intensity.distanceM\", 1e4) ** 2;\n return { illuminant, option, position, candela, scale: calculateIlluminantIrradianceScale(illuminant.shape, 1) * candela, shape: tabulatedSpectrum(illuminant.shape) };\n });\n /** cos θ/d² of point source j at plane point (x, y) m. */\n const falloff = (p: typeof points[number], x: number, y: number): number => {\n const dx = x - p.position.xM, dy = y - p.position.yM, h = p.position.heightM, d2 = dx * dx + dy * dy + h * h;\n return h / (d2 * Math.sqrt(d2));\n };\n const n = sources.length, shapes = sources.map((s) => tabulatedSpectrum(s.illuminant.shape));\n if (n < 2 && record.blend !== undefined) fail(\"illumination.blend needs two or more sources.\");\n const b = n < 2 ? { kind: \"none\" } : fields(record.blend, \".blend\", [\"kind\", \"from\", \"to\", \"center\", \"radius\", \"stops\", \"regions\", \"outsideSource\"]);\n const index = (x: unknown, name: string): number => (Number.isInteger(x) && (x as number) >= 0 && (x as number) < n ? x as number : fail(\"illumination.blend.\" + name + \" must be a source index from 0 to \" + (n - 1) + \".\"));\n const unused = (keys: string[]): void => { for (const key of keys) if (b[key] !== undefined) fail(\"illumination.blend.\" + key + \" does not apply to a \" + String(b.kind) + \" blend.\"); };\n // A point's position t on a gradient or radial blend, or its source on a regions blend.\n let position: (u: number, v: number) => number, blend: Fields | null = null, stops: number[] | undefined;\n if (b.kind === \"none\") position = (): number => 0;\n else if (b.kind === \"regions\") {\n unused([\"from\", \"to\", \"center\", \"radius\", \"stops\"]);\n const rects = b.regions as unknown[];\n if (!Array.isArray(rects) || rects.length < 1 || rects.length > MIXED_ILLUMINATION_MAX_REGIONS) fail(\"illumination.blend.regions must list 1 to \" + MIXED_ILLUMINATION_MAX_REGIONS + \" rectangles.\");\n const regions = rects.map((entry, i) => {\n const at = \".blend.regions[\" + i + \"]\", r = fields(entry, at, [\"source\", \"uMin\", \"uMax\", \"vMin\", \"vMax\"]);\n const region = { source: index(r.source, \"regions[\" + i + \"].source\"), uMin: finite(r.uMin, at + \".uMin\"), uMax: finite(r.uMax, at + \".uMax\"), vMin: finite(r.vMin, at + \".vMin\"), vMax: finite(r.vMax, at + \".vMax\") };\n if (!(region.uMin <= region.uMax && region.vMin <= region.vMax)) fail(\"illumination\" + at + \" uMin and vMin must not exceed uMax and vMax.\");\n return region;\n });\n const outside = index(b.outsideSource, \"outsideSource\");\n position = (u: number, v: number): number => regions.find((r) => u >= r.uMin && u <= r.uMax && v >= r.vMin && v <= r.vMax)?.source ?? outside;\n blend = { kind: \"regions\", regions, outsideSource: outside };\n } else {\n if (b.kind === \"linear-gradient\") {\n unused([\"center\", \"radius\", \"regions\", \"outsideSource\"]);\n const from = point(b.from, \"from\"), to = point(b.to, \"to\"), du = to.u - from.u, dv = to.v - from.v, length2 = du * du + dv * dv;\n if (!(length2 > 0)) fail(\"illumination.blend from and to must differ.\");\n position = (u: number, v: number): number => Math.min(1, Math.max(0, ((u - from.u) * du + (v - from.v) * dv) / length2));\n blend = { kind: b.kind, from, to };\n } else if (b.kind === \"radial\") {\n unused([\"from\", \"to\", \"regions\", \"outsideSource\"]);\n const center = b.center === undefined ? { u: 0, v: 0 } : point(b.center, \"center\"), radius = finite(b.radius, \".blend.radius\");\n if (!(radius > 0)) fail(\"illumination.blend.radius must be positive.\");\n position = (u: number, v: number): number => Math.min(1, Math.hypot(u - center.u, v - center.v) / radius);\n blend = { kind: b.kind, center, radius };\n } else return fail('illumination.blend.kind must be \"linear-gradient\", \"radial\" or \"regions\".');\n const declared = b.stops as unknown[] | undefined;\n if (declared !== undefined && (!Array.isArray(declared) || declared.length !== n)) fail(\"illumination.blend.stops must list one stop per source.\");\n blend!.stops = stops = declared ? declared.map((x, i) => {\n const stop = finite(x, \".blend.stops[\" + i + \"]\");\n return stop >= 0 && stop <= 1 && (i === 0 || stop >= (declared[i - 1] as number)) ? stop : fail(\"illumination.blend.stops must be non-decreasing in [0, 1].\");\n }) : sources.map((_, i) => i / (n - 1));\n }\n /**\n * The blend at a point: the lower source i and the fraction f of source i + 1 (f = 0: source i alone). On a gradient, the segment\n * [stops[i], stops[i + 1]) that holds t; equal stops are passed over, so the later source takes the stop.\n */\n const at = (u: number, v: number): [number, number] => {\n const t = position(u, v);\n if (!stops) return [t, 0];\n let i = 0;\n while (i < n - 1 && t >= stops[i + 1]!) i++;\n return i === n - 1 || t <= stops[i]! ? [i, 0] : [i, (t - stops[i]!) / (stops[i + 1]! - stops[i]!)];\n };\n const [i0, f0] = at(0, 0), weights = sources.map((_, i) => (i === i0 ? 1 - f0 : i === i0 + 1 ? f0 : 0));\n // Every light at the frame center, the blend's sources first: a point source's irradiance scale there is c_j·cos θ/d².\n const lights = [...sources, ...points.map((p) => {\n const atCenter = falloff(p, 0, 0);\n return Object.freeze({ illuminant: p.illuminant, option: p.option, illuminanceLux: p.candela * atCenter, irradianceScale: p.scale * atCenter,\n report: Object.freeze({ illuminant: p.illuminant.id, position: p.position, intensityCandela: p.candela }) });\n })];\n const illuminancesLux = lights.map((l, i) => (i < n ? weights[i]! * l.illuminanceLux : l.illuminanceLux));\n let strongest = 0, illuminanceLux = 0;\n illuminancesLux.forEach((e, i) => { illuminanceLux += e; if (e > illuminancesLux[strongest]!) strongest = i; });\n /** The blend's irradiance (k·S(λ) itself where one source has weight 1). */\n const ambient = (u: number, v: number, nm: number): number => {\n if (n === 0) return 0;\n const [i, f] = at(u, v), a = sources[i]!.irradianceScale * shapes[i]!(nm);\n return f === 0 ? a : (1 - f) * a + f * (sources[i + 1]!.irradianceScale * shapes[i + 1]!(nm));\n };\n return Object.freeze({ sources: Object.freeze(lights), blend: blend && Object.freeze(blend),\n irradianceAt: points.length === 0 ? (u: number, v: number, _x: number, _y: number, nm: number): number => ambient(u, v, nm) : (u: number, v: number, x: number, y: number, nm: number): number => {\n let e = ambient(u, v, nm);\n for (const p of points) e += p.scale * p.shape(nm) * falloff(p, x, y);\n return e;\n },\n center: Object.freeze({ illuminanceLux, weights, illuminancesLux, strongestSource: strongest }) });\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type QualityKit = typeof import("./quality-kit.js");
|
|
2
|
+
export type OptInKit = typeof import("./opt-in-kit.js");
|
|
3
|
+
/** One kit's loader: `load()` imports it once (single flight, retried after a failure); `loaded` is the module once imported. */
|
|
4
|
+
interface KitLoader<T> {
|
|
5
|
+
loaded: T | undefined;
|
|
6
|
+
load(): Promise<T>;
|
|
7
|
+
}
|
|
8
|
+
/** The CPU full-quality code (#594). */
|
|
9
|
+
export declare const qualityKit: KitLoader<QualityKit>;
|
|
10
|
+
/** The opt-in features' code (#594). */
|
|
11
|
+
export declare const optInKit: KitLoader<OptInKit>;
|
|
12
|
+
/** A kit the request loaded where it was parsed (an engine error if a code path uses it without loading it first). */
|
|
13
|
+
export declare function loadedKit<T>(kit: KitLoader<T>): T;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* 2.22.0 (#594): loads the CPU on-demand code, once per realm: the Quality kit (src/facade/quality-kit.ts) and the opt-in kit
|
|
4
|
+
* (src/facade/opt-in-kit.ts). A request loads a kit where it is parsed, before it uses any of its code, and then calls it
|
|
5
|
+
* synchronously, so results are those of a static import. Concurrent loads share one import; a failed load is not remembered,
|
|
6
|
+
* so the next request (or `prepareQualityPaths()`) tries again. A failed load rejects with `ImageKernelExecutionError` reason
|
|
7
|
+
* `quality-code-unavailable`, as the GPU Quality code's does; the CPU has no other path, so the request fails with it.
|
|
8
|
+
*/
|
|
9
|
+
import { ImageKernelExecutionError } from "../core/execution-error.js";
|
|
10
|
+
function kitLoader(name, importer) {
|
|
11
|
+
let pending = null;
|
|
12
|
+
const kit = {
|
|
13
|
+
loaded: undefined,
|
|
14
|
+
load() {
|
|
15
|
+
if (kit.loaded)
|
|
16
|
+
return Promise.resolve(kit.loaded);
|
|
17
|
+
pending ??= importer().then((module) => (kit.loaded = module), (error) => {
|
|
18
|
+
pending = null;
|
|
19
|
+
throw new ImageKernelExecutionError("quality-code-unavailable", "the engine's " + name + " code could not be loaded: " + (error instanceof Error ? error.message : String(error)));
|
|
20
|
+
});
|
|
21
|
+
return pending;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
return kit;
|
|
25
|
+
}
|
|
26
|
+
/** The CPU full-quality code (#594). */
|
|
27
|
+
export const qualityKit = kitLoader("full-quality", () => import("./quality-kit.js"));
|
|
28
|
+
/** The opt-in features' code (#594). */
|
|
29
|
+
export const optInKit = kitLoader("opt-in feature", () => import("./opt-in-kit.js"));
|
|
30
|
+
/** A kit the request loaded where it was parsed (an engine error if a code path uses it without loading it first). */
|
|
31
|
+
export function loadedKit(kit) {
|
|
32
|
+
if (!kit.loaded)
|
|
33
|
+
throw new ImageKernelExecutionError("quality-code-unavailable", "on-demand code was used before it was loaded (an engine defect; #594).");
|
|
34
|
+
return kit.loaded;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=on-demand-kits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"on-demand-kits.js","sourceRoot":"","sources":["../../src/facade/on-demand-kits.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;GAMG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAOvE,SAAS,SAAS,CAAI,IAAY,EAAE,QAA0B;IAC5D,IAAI,OAAO,GAAsB,IAAI,CAAC;IACtC,MAAM,GAAG,GAAiB;QACxB,MAAM,EAAE,SAAS;QACjB,IAAI;YACF,IAAI,GAAG,CAAC,MAAM;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACnD,OAAO,KAAK,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,KAAc,EAAE,EAAE;gBAChF,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM,IAAI,yBAAyB,CAAC,0BAA0B,EAAE,eAAe,GAAG,IAAI,GAAG,6BAA6B,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACrL,CAAC,CAAC,CAAC;YACH,OAAO,OAAO,CAAC;QACjB,CAAC;KACF,CAAC;IACF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,wCAAwC;AACxC,MAAM,CAAC,MAAM,UAAU,GAA0B,SAAS,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAC7G,wCAAwC;AACxC,MAAM,CAAC,MAAM,QAAQ,GAAwB,SAAS,CAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;AAE1G,sHAAsH;AACtH,MAAM,UAAU,SAAS,CAAI,GAAiB;IAC5C,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,MAAM,IAAI,yBAAyB,CAAC,0BAA0B,EAAE,wEAAwE,CAAC,CAAC;IAC3J,OAAO,GAAG,CAAC,MAAM,CAAC;AACpB,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * 2.22.0 (#594): loads the CPU on-demand code, once per realm: the Quality kit (src/facade/quality-kit.ts) and the opt-in kit\n * (src/facade/opt-in-kit.ts). A request loads a kit where it is parsed, before it uses any of its code, and then calls it\n * synchronously, so results are those of a static import. Concurrent loads share one import; a failed load is not remembered,\n * so the next request (or `prepareQualityPaths()`) tries again. A failed load rejects with `ImageKernelExecutionError` reason\n * `quality-code-unavailable`, as the GPU Quality code's does; the CPU has no other path, so the request fails with it.\n */\n\nimport { ImageKernelExecutionError } from \"../core/execution-error.js\";\n\nexport type QualityKit = typeof import(\"./quality-kit.js\");\nexport type OptInKit = typeof import(\"./opt-in-kit.js\");\n\n/** One kit's loader: `load()` imports it once (single flight, retried after a failure); `loaded` is the module once imported. */\ninterface KitLoader<T> { loaded: T | undefined; load(): Promise<T> }\nfunction kitLoader<T>(name: string, importer: () => Promise<T>): KitLoader<T> {\n let pending: Promise<T> | null = null;\n const kit: KitLoader<T> = {\n loaded: undefined,\n load(): Promise<T> {\n if (kit.loaded) return Promise.resolve(kit.loaded);\n pending ??= importer().then((module) => (kit.loaded = module), (error: unknown) => {\n pending = null;\n throw new ImageKernelExecutionError(\"quality-code-unavailable\", \"the engine's \" + name + \" code could not be loaded: \" + (error instanceof Error ? error.message : String(error)));\n });\n return pending;\n }\n };\n return kit;\n}\n\n/** The CPU full-quality code (#594). */\nexport const qualityKit: KitLoader<QualityKit> = kitLoader(\"full-quality\", () => import(\"./quality-kit.js\"));\n/** The opt-in features' code (#594). */\nexport const optInKit: KitLoader<OptInKit> = kitLoader(\"opt-in feature\", () => import(\"./opt-in-kit.js\"));\n\n/** A kit the request loaded where it was parsed (an engine error if a code path uses it without loading it first). */\nexport function loadedKit<T>(kit: KitLoader<T>): T {\n if (!kit.loaded) throw new ImageKernelExecutionError(\"quality-code-unavailable\", \"on-demand code was used before it was loaded (an engine defect; #594).\");\n return kit.loaded;\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 2.22.0 (#594): the opt-in features' code, one module that the capture loads on demand (`loadOptInKit`, src/facade/on-demand-kits.ts)
|
|
3
|
+
* when a request uses one of them, so a bundler that splits dynamic imports keeps it off the default path. Only re-exports:
|
|
4
|
+
* `sensor.profile` (#554: the profile parser and body builder; the catalogue itself is never imported), `illumination` (#550, with
|
|
5
|
+
* #597's lighting over a print) and `motion.subject` (#551).
|
|
6
|
+
*/
|
|
7
|
+
export { parseSensorProfile, sensorProfileBody, sensorProfileSaturationIso } from "../equipment/sensor-profile-body.js";
|
|
8
|
+
export { resolveMixedIllumination } from "./mixed-illumination.js";
|
|
9
|
+
export { createSubjectMotionProvider, subjectTravelM } from "../motion/subject-motion.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* 2.22.0 (#594): the opt-in features' code, one module that the capture loads on demand (`loadOptInKit`, src/facade/on-demand-kits.ts)
|
|
4
|
+
* when a request uses one of them, so a bundler that splits dynamic imports keeps it off the default path. Only re-exports:
|
|
5
|
+
* `sensor.profile` (#554: the profile parser and body builder; the catalogue itself is never imported), `illumination` (#550, with
|
|
6
|
+
* #597's lighting over a print) and `motion.subject` (#551).
|
|
7
|
+
*/
|
|
8
|
+
export { parseSensorProfile, sensorProfileBody, sensorProfileSaturationIso } from "../equipment/sensor-profile-body.js";
|
|
9
|
+
export { resolveMixedIllumination } from "./mixed-illumination.js";
|
|
10
|
+
export { createSubjectMotionProvider, subjectTravelM } from "../motion/subject-motion.js";
|
|
11
|
+
//# sourceMappingURL=opt-in-kit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opt-in-kit.js","sourceRoot":"","sources":["../../src/facade/opt-in-kit.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACxH,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,2BAA2B,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * 2.22.0 (#594): the opt-in features' code, one module that the capture loads on demand (`loadOptInKit`, src/facade/on-demand-kits.ts)\n * when a request uses one of them, so a bundler that splits dynamic imports keeps it off the default path. Only re-exports:\n * `sensor.profile` (#554: the profile parser and body builder; the catalogue itself is never imported), `illumination` (#550, with\n * #597's lighting over a print) and `motion.subject` (#551).\n */\n\nexport { parseSensorProfile, sensorProfileBody, sensorProfileSaturationIso } from \"../equipment/sensor-profile-body.js\";\nexport { resolveMixedIllumination } from \"./mixed-illumination.js\";\nexport { createSubjectMotionProvider, subjectTravelM } from \"../motion/subject-motion.js\";\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 2.22.0 (#594): the CPU full-quality code, one module that the capture and the display view load on demand (`loadQualityKit`,
|
|
3
|
+
* src/facade/on-demand-kits.ts) where they parse a request that asks for it, so a bundler that splits dynamic imports puts all of
|
|
4
|
+
* it in one chunk outside the default path. Only re-exports: the code, its results and its bounds are those of the modules named.
|
|
5
|
+
*
|
|
6
|
+
* - Diffraction (2.1): the Airy profile, its site kernels and their convolution.
|
|
7
|
+
* - The capture's AHD demosaic (`output.demosaic: "ahd"`).
|
|
8
|
+
* - `lens.defocus` beyond the geometric disc (owner, 2026-11-10): the bokeh shapes, the cat's eye and their field zones, the
|
|
9
|
+
* lattice of a disc above the direct radius (#564) and the image-space provider (lens projection and distortion).
|
|
10
|
+
* - The display view's coupled rendering steps (#593, #601: luminance tone curves, reconstruct, desaturation) and the neighbor
|
|
11
|
+
* highlight reconstruction (#602).
|
|
12
|
+
*/
|
|
13
|
+
export { createDiffractionLimitedPsfProfile } from "../optics/diffraction-psf-profile.js";
|
|
14
|
+
export { registerDiffractionPsfKey, siteDiffractionKernel } from "../optics/site-diffraction-kernel.js";
|
|
15
|
+
export { createAhdDemosaicTask } from "../processing/demosaic.js";
|
|
16
|
+
export { createDefocusBokehSiteKernel, resolveDefocusBokehOptions } from "../optics/defocus-bokeh-kernel.js";
|
|
17
|
+
export { planDefocusBokehZones } from "./defocus-bokeh-zones.js";
|
|
18
|
+
export { LARGE_DEFOCUS_CACHE_BYTES, createLargeDefocusNodeLattice } from "./large-defocus-lattice.js";
|
|
19
|
+
export { calculateDefocusFieldVariation, createDefocusImageSpaceProvider, prepareDefocusImageSpaceGeometry } from "./defocus-image-space-provider.js";
|
|
20
|
+
export { createDisplayViewCoupledRendering } from "./display-view-rendering.js";
|
|
21
|
+
export * as neighborHighlights from "../color/neighbor-highlight-reconstruction.js";
|