@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.
Files changed (275) hide show
  1. package/CHANGELOG.md +295 -1
  2. package/CITATION.cff +1 -1
  3. package/README.md +7 -6
  4. package/SECURITY.md +1 -1
  5. package/THIRD_PARTY.md +18 -0
  6. package/dist/capture/c2pa-embed.d.ts +116 -0
  7. package/dist/capture/c2pa-embed.js +493 -0
  8. package/dist/capture/c2pa-embed.js.map +1 -0
  9. package/dist/capture/dng-import.d.ts +73 -8
  10. package/dist/capture/dng-import.js +315 -80
  11. package/dist/capture/dng-import.js.map +1 -1
  12. package/dist/capture/dng-lens-correction-opcodes.d.ts +2 -2
  13. package/dist/capture/dng-lens-correction-opcodes.js +2 -2
  14. package/dist/capture/dng-lens-correction-opcodes.js.map +1 -1
  15. package/dist/capture/dng-opcodes.d.ts +96 -0
  16. package/dist/capture/dng-opcodes.js +391 -0
  17. package/dist/capture/dng-opcodes.js.map +1 -0
  18. package/dist/capture/dng-profile-maps.d.ts +99 -0
  19. package/dist/capture/dng-profile-maps.js +381 -0
  20. package/dist/capture/dng-profile-maps.js.map +1 -0
  21. package/dist/capture/dng-stage-image.d.ts +23 -0
  22. package/dist/capture/dng-stage-image.js +65 -0
  23. package/dist/capture/dng-stage-image.js.map +1 -0
  24. package/dist/capture/exposure-build-up-stage.d.ts +16 -0
  25. package/dist/capture/exposure-build-up-stage.js +4 -0
  26. package/dist/capture/exposure-build-up-stage.js.map +1 -0
  27. package/dist/capture/jpeg-xl-tiles.d.ts +22 -0
  28. package/dist/capture/jpeg-xl-tiles.js +151 -0
  29. package/dist/capture/jpeg-xl-tiles.js.map +1 -0
  30. package/dist/capture/lossy-jpeg.d.ts +17 -0
  31. package/dist/capture/lossy-jpeg.js +369 -0
  32. package/dist/capture/lossy-jpeg.js.map +1 -0
  33. package/dist/capture/native-environment-lean.d.ts +2 -1
  34. package/dist/capture/native-environment-lean.js +41 -73
  35. package/dist/capture/native-environment-lean.js.map +1 -1
  36. package/dist/capture/native-environment-tabulated.js +4 -3
  37. package/dist/capture/native-environment-tabulated.js.map +1 -1
  38. package/dist/capture/native-raw-development.d.ts +2 -1
  39. package/dist/capture/native-raw-development.js.map +1 -1
  40. package/dist/capture/native-raw.d.ts +3 -2
  41. package/dist/capture/native-raw.js +5 -4
  42. package/dist/capture/native-raw.js.map +1 -1
  43. package/dist/capture/sensor-raw-producer.d.ts +4 -1
  44. package/dist/capture/sensor-raw-producer.js +12 -3
  45. package/dist/capture/sensor-raw-producer.js.map +1 -1
  46. package/dist/color/neighbor-highlight-reconstruction.d.ts +66 -0
  47. package/dist/color/neighbor-highlight-reconstruction.js +234 -0
  48. package/dist/color/neighbor-highlight-reconstruction.js.map +1 -0
  49. package/dist/color/sensor-color-development.d.ts +5 -0
  50. package/dist/color/sensor-color-development.js +7 -1
  51. package/dist/color/sensor-color-development.js.map +1 -1
  52. package/dist/color/spectral-spikiness.d.ts +11 -0
  53. package/dist/color/spectral-spikiness.js +23 -0
  54. package/dist/color/spectral-spikiness.js.map +1 -0
  55. package/dist/core/execution-error.d.ts +21 -0
  56. package/dist/core/execution-error.js +12 -0
  57. package/dist/core/execution-error.js.map +1 -0
  58. package/dist/core/version.d.ts +1 -1
  59. package/dist/core/version.js +1 -1
  60. package/dist/core/version.js.map +1 -1
  61. package/dist/equipment/generic-lens-catalogue.d.ts +3 -2
  62. package/dist/equipment/generic-lens-catalogue.js +18 -5
  63. package/dist/equipment/generic-lens-catalogue.js.map +1 -1
  64. package/dist/equipment/generic-tier-assets.d.ts +32 -0
  65. package/dist/equipment/generic-tier-assets.js +16 -11
  66. package/dist/equipment/generic-tier-assets.js.map +1 -1
  67. package/dist/equipment/sensor-profile-body.d.ts +78 -0
  68. package/dist/equipment/sensor-profile-body.js +77 -0
  69. package/dist/equipment/sensor-profile-body.js.map +1 -0
  70. package/dist/equipment/sensor-profiles.d.ts +8 -0
  71. package/dist/equipment/sensor-profiles.js +82 -0
  72. package/dist/equipment/sensor-profiles.js.map +1 -0
  73. package/dist/facade/catalogue-lens-signal.d.ts +28 -3
  74. package/dist/facade/catalogue-lens-signal.js +83 -78
  75. package/dist/facade/catalogue-lens-signal.js.map +1 -1
  76. package/dist/facade/chart-radiance-batch.js +2 -1
  77. package/dist/facade/chart-radiance-batch.js.map +1 -1
  78. package/dist/facade/defocus-image-space-provider.d.ts +7 -0
  79. package/dist/facade/defocus-image-space-provider.js +64 -76
  80. package/dist/facade/defocus-image-space-provider.js.map +1 -1
  81. package/dist/facade/diffraction-provider.d.ts +1 -1
  82. package/dist/facade/diffraction-provider.js +4 -4
  83. package/dist/facade/diffraction-provider.js.map +1 -1
  84. package/dist/facade/display-view-gpu-session.js +39 -5
  85. package/dist/facade/display-view-gpu-session.js.map +1 -1
  86. package/dist/facade/display-view-gpu.d.ts +19 -6
  87. package/dist/facade/display-view-gpu.js.map +1 -1
  88. package/dist/facade/display-view-lens-signal.js +25 -23
  89. package/dist/facade/display-view-lens-signal.js.map +1 -1
  90. package/dist/facade/display-view-normal.d.ts +15 -0
  91. package/dist/facade/display-view-normal.js +44 -0
  92. package/dist/facade/display-view-normal.js.map +1 -0
  93. package/dist/facade/display-view-rendering.d.ts +97 -0
  94. package/dist/facade/display-view-rendering.js +598 -0
  95. package/dist/facade/display-view-rendering.js.map +1 -0
  96. package/dist/facade/display-view.d.ts +37 -65
  97. package/dist/facade/display-view.js +152 -499
  98. package/dist/facade/display-view.js.map +1 -1
  99. package/dist/facade/expected-signal-setup.d.ts +3 -1
  100. package/dist/facade/expected-signal-setup.js +3 -3
  101. package/dist/facade/expected-signal-setup.js.map +1 -1
  102. package/dist/facade/expected-signal.d.ts +47 -14
  103. package/dist/facade/expected-signal.js +117 -112
  104. package/dist/facade/expected-signal.js.map +1 -1
  105. package/dist/facade/exposure-build-up.d.ts +70 -0
  106. package/dist/facade/exposure-build-up.js +164 -0
  107. package/dist/facade/exposure-build-up.js.map +1 -0
  108. package/dist/facade/fast-methods.d.ts +1 -1
  109. package/dist/facade/fast-methods.js +46 -9
  110. package/dist/facade/fast-methods.js.map +1 -1
  111. package/dist/facade/generic-lens-capture.d.ts +3 -3
  112. package/dist/facade/generic-lens-capture.js +3 -3
  113. package/dist/facade/generic-lens-capture.js.map +1 -1
  114. package/dist/facade/image-plane-enable.d.ts +7 -0
  115. package/dist/facade/image-plane-enable.js +17 -0
  116. package/dist/facade/image-plane-enable.js.map +1 -0
  117. package/dist/facade/image-plane-lattice-data.d.ts +6 -0
  118. package/dist/facade/image-plane-lattice-data.js +10 -0
  119. package/dist/facade/image-plane-lattice-data.js.map +1 -0
  120. package/dist/facade/image-plane-support.d.ts +33 -0
  121. package/dist/facade/image-plane-support.js +11 -0
  122. package/dist/facade/image-plane-support.js.map +1 -0
  123. package/dist/facade/image-plane.d.ts +36 -0
  124. package/dist/facade/image-plane.js +384 -0
  125. package/dist/facade/image-plane.js.map +1 -0
  126. package/dist/facade/mixed-illumination.d.ts +108 -0
  127. package/dist/facade/mixed-illumination.js +174 -0
  128. package/dist/facade/mixed-illumination.js.map +1 -0
  129. package/dist/facade/on-demand-kits.d.ts +14 -0
  130. package/dist/facade/on-demand-kits.js +36 -0
  131. package/dist/facade/on-demand-kits.js.map +1 -0
  132. package/dist/facade/opt-in-kit.d.ts +9 -0
  133. package/dist/facade/opt-in-kit.js +11 -0
  134. package/dist/facade/opt-in-kit.js.map +1 -0
  135. package/dist/facade/quality-kit.d.ts +21 -0
  136. package/dist/facade/quality-kit.js +23 -0
  137. package/dist/facade/quality-kit.js.map +1 -0
  138. package/dist/facade/quality-paths.d.ts +22 -0
  139. package/dist/facade/quality-paths.js +44 -0
  140. package/dist/facade/quality-paths.js.map +1 -0
  141. package/dist/facade/representative-light-sources.d.ts +72 -0
  142. package/dist/facade/representative-light-sources.js +124 -0
  143. package/dist/facade/representative-light-sources.js.map +1 -0
  144. package/dist/facade/scene-radiance.d.ts +145 -4
  145. package/dist/facade/scene-radiance.js +50 -13
  146. package/dist/facade/scene-radiance.js.map +1 -1
  147. package/dist/facade/simulate-capture.d.ts +68 -20
  148. package/dist/facade/simulate-capture.js +399 -146
  149. package/dist/facade/simulate-capture.js.map +1 -1
  150. package/dist/facade/simulate-display-view.d.ts +10 -12
  151. package/dist/facade/simulate-display-view.js +70 -53
  152. package/dist/facade/simulate-display-view.js.map +1 -1
  153. package/dist/gpu/chart-composite-gpu.d.ts +13 -1
  154. package/dist/gpu/chart-composite-gpu.js +48 -9
  155. package/dist/gpu/chart-composite-gpu.js.map +1 -1
  156. package/dist/gpu/chart-radiance-gpu.js +4 -30
  157. package/dist/gpu/chart-radiance-gpu.js.map +1 -1
  158. package/dist/gpu/display-view-composite-material-module.d.ts +10 -4
  159. package/dist/gpu/display-view-composite-material-module.js +39 -13
  160. package/dist/gpu/display-view-composite-material-module.js.map +1 -1
  161. package/dist/gpu/display-view-gpu-renderer.d.ts +43 -0
  162. package/dist/gpu/display-view-gpu-renderer.js +134 -0
  163. package/dist/gpu/display-view-gpu-renderer.js.map +1 -0
  164. package/dist/gpu/display-view-image-material-module.d.ts +87 -0
  165. package/dist/gpu/display-view-image-material-module.js +361 -0
  166. package/dist/gpu/display-view-image-material-module.js.map +1 -0
  167. package/dist/gpu/display-view-image-quality.d.ts +87 -0
  168. package/dist/gpu/display-view-image-quality.js +625 -0
  169. package/dist/gpu/display-view-image-quality.js.map +1 -0
  170. package/dist/gpu/display-view-quality-gpu.d.ts +80 -65
  171. package/dist/gpu/display-view-quality-gpu.js +187 -445
  172. package/dist/gpu/display-view-quality-gpu.js.map +1 -1
  173. package/dist/gpu/display-view-speed-gpu.d.ts +67 -19
  174. package/dist/gpu/display-view-speed-gpu.js +181 -105
  175. package/dist/gpu/display-view-speed-gpu.js.map +1 -1
  176. package/dist/gpu/image-kernel-accelerator.js +3 -0
  177. package/dist/gpu/image-kernel-accelerator.js.map +1 -1
  178. package/dist/gpu/image-kernel-execution.d.ts +2 -13
  179. package/dist/gpu/image-kernel-execution.js +2 -10
  180. package/dist/gpu/image-kernel-execution.js.map +1 -1
  181. package/dist/gpu/wgsl-display-view-coupled-stub.d.ts +8 -0
  182. package/dist/gpu/wgsl-display-view-coupled-stub.js +21 -0
  183. package/dist/gpu/wgsl-display-view-coupled-stub.js.map +1 -0
  184. package/dist/gpu/wgsl-display-view-coupled.d.ts +88 -0
  185. package/dist/gpu/wgsl-display-view-coupled.js +353 -0
  186. package/dist/gpu/wgsl-display-view-coupled.js.map +1 -0
  187. package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +33 -24
  188. package/dist/gpu/wgsl-display-view-quality-kernel.js +166 -146
  189. package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
  190. package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +19 -44
  191. package/dist/gpu/wgsl-display-view-speed-kernel.js +116 -18
  192. package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
  193. package/dist/gpu/wgsl-exact-sum.d.ts +20 -0
  194. package/dist/gpu/wgsl-exact-sum.js +42 -0
  195. package/dist/gpu/wgsl-exact-sum.js.map +1 -0
  196. package/dist/index.d.ts +22 -6
  197. package/dist/index.js +16 -2
  198. package/dist/index.js.map +1 -1
  199. package/dist/motion/subject-motion.d.ts +66 -0
  200. package/dist/motion/subject-motion.js +52 -0
  201. package/dist/motion/subject-motion.js.map +1 -0
  202. package/dist/optics/generic-lens-lateral-color.d.ts +83 -0
  203. package/dist/optics/generic-lens-lateral-color.js +77 -0
  204. package/dist/optics/generic-lens-lateral-color.js.map +1 -0
  205. package/dist/optics/generic-lens-psf.js +54 -46
  206. package/dist/optics/generic-lens-psf.js.map +1 -1
  207. package/dist/optics/lens-psf-profile.d.ts +7 -0
  208. package/dist/optics/lens-psf-profile.js +2 -1
  209. package/dist/optics/lens-psf-profile.js.map +1 -1
  210. package/dist/output/camera-channel-response.d.ts +50 -0
  211. package/dist/output/camera-channel-response.js +69 -0
  212. package/dist/output/camera-channel-response.js.map +1 -0
  213. package/dist/output/developed-lens-corrections.d.ts +19 -5
  214. package/dist/output/developed-lens-corrections.js +28 -9
  215. package/dist/output/developed-lens-corrections.js.map +1 -1
  216. package/dist/output/generic-lens-corrections.d.ts +41 -5
  217. package/dist/output/generic-lens-corrections.js +52 -8
  218. package/dist/output/generic-lens-corrections.js.map +1 -1
  219. package/dist/output/native-capture-sdr.js +5 -2
  220. package/dist/output/native-capture-sdr.js.map +1 -1
  221. package/dist/output/print-plan.d.ts +41 -5
  222. package/dist/output/print-plan.js +59 -14
  223. package/dist/output/print-plan.js.map +1 -1
  224. package/dist/output/sdr-rendering.d.ts +18 -1
  225. package/dist/output/sdr-rendering.js +39 -2
  226. package/dist/output/sdr-rendering.js.map +1 -1
  227. package/dist/sensor/binomial-sample.d.ts +3 -0
  228. package/dist/sensor/binomial-sample.js +86 -0
  229. package/dist/sensor/binomial-sample.js.map +1 -0
  230. package/dist/sensor/native-sensor-report.d.ts +10 -0
  231. package/dist/sensor/native-sensor-report.js +16 -0
  232. package/dist/sensor/native-sensor-report.js.map +1 -0
  233. package/dist/sensor/sensor-characteristics.d.ts +91 -13
  234. package/dist/sensor/sensor-characteristics.js +30 -15
  235. package/dist/sensor/sensor-characteristics.js.map +1 -1
  236. package/docs/AGENT_GUIDE.md +1 -0
  237. package/docs/API_REFERENCE.md +214 -4
  238. package/docs/QUICK_START.md +162 -8
  239. package/docs/USAGE.md +195 -22
  240. package/docs/api/capture-c2pa-embed.md +177 -0
  241. package/docs/api/capture-dng-import.md +86 -10
  242. package/docs/api/capture-dng-opcodes.md +93 -0
  243. package/docs/api/capture-dng-profile-maps.md +141 -0
  244. package/docs/api/capture-dng-stage-image.md +43 -0
  245. package/docs/api/capture-jpeg-xl-tiles.md +33 -0
  246. package/docs/api/capture-lossy-jpeg.md +41 -0
  247. package/docs/api/capture-native-raw-development.md +2 -1
  248. package/docs/api/core-execution-error.md +43 -0
  249. package/docs/api/core-version.md +1 -1
  250. package/docs/api/equipment-generic-lens-catalogue.md +10 -5
  251. package/docs/api/equipment-sensor-profile-body.md +64 -0
  252. package/docs/api/equipment-sensor-profiles.md +86 -0
  253. package/docs/api/exports.json +460 -5
  254. package/docs/api/facade-display-view-gpu.md +5 -2
  255. package/docs/api/facade-display-view.md +11 -15
  256. package/docs/api/facade-exposure-build-up.md +105 -0
  257. package/docs/api/facade-fast-methods.md +47 -10
  258. package/docs/api/facade-image-plane-enable.md +16 -0
  259. package/docs/api/facade-mixed-illumination.md +67 -0
  260. package/docs/api/facade-quality-paths.md +24 -0
  261. package/docs/api/facade-representative-light-sources.md +131 -0
  262. package/docs/api/facade-scene-radiance.md +54 -3
  263. package/docs/api/facade-simulate-capture.md +48 -11
  264. package/docs/api/facade-simulate-display-view.md +10 -12
  265. package/docs/api/gpu-image-kernel-execution.md +0 -36
  266. package/docs/api/motion-subject-motion.md +23 -0
  267. package/docs/api/optics-generic-lens-lateral-color.md +79 -0
  268. package/docs/api/output-camera-channel-response.md +55 -0
  269. package/docs/api/output-developed-lens-corrections.md +10 -1
  270. package/docs/api/output-generic-lens-corrections.md +40 -4
  271. package/docs/api/output-print-plan.md +35 -1
  272. package/docs/api/output-sdr-rendering.md +6 -1
  273. package/docs/api/sensor-sensor-characteristics.md +54 -2
  274. package/llms.txt +3 -0
  275. package/package.json +6 -5
@@ -26,8 +26,7 @@ export interface PreparedDisplayViewRenderOptions {
26
26
  */
27
27
  export interface PreparedDisplayView {
28
28
  /**
29
- * Renders a view of the prepared request. Renders may run concurrently; they share no state except read-only setup and the
30
- * realm's AHD correction states, which never change a byte (docs/DISPLAY_VIEW.md, "AHD at low signal"). With `gpu: "auto"`
29
+ * Renders a view of the prepared request. Renders may run concurrently; they share no state except read-only setup. With `gpu: "auto"`
31
30
  * or `"require"` (#481) GPU renders of one prepared view run one at a time on its device, and `diagnostics.fast.execution`
32
31
  * says whether the GPU or the CPU reference rendered the view, and why.
33
32
  */
@@ -39,22 +38,21 @@ export interface PreparedDisplayView {
39
38
  */
40
39
  dispose(): void;
41
40
  /**
42
- * 2.10 (#447): the key of this request's AHD low-signal correction states, or null when the request has no AHD
43
- * (`output.demosaic` other than "ahd"). Every input of the key is fixed when the request is prepared; two prepared views
44
- * with the same key read the same states.
41
+ * 2.10 (#447), deprecated in 2.22.0: was the key of this request's AHD low-signal correction states. The view has no such
42
+ * states since 2.22.0 (docs/DISPLAY_VIEW.md, "AHD at low signal"), so this returns null for every request.
43
+ * @deprecated Since 2.22.0: always null. Removed in 3.0.0.
45
44
  */
46
45
  correctionKey(): string | null;
47
46
  /**
48
- * 2.10 (#447): the grid keys of every correction state a render of `view` reads (ascending, whether or not this realm holds
49
- * them), found by a render of the view's region that records the states instead of computing them. No image is returned;
50
- * it costs about one render whose states are all held. Fails with an InvalidConfigurationError when the request has no AHD.
47
+ * 2.10 (#447), deprecated in 2.22.0: was the grid keys of the correction states a render of `view` read. Since 2.22.0 it checks
48
+ * `view` as `render` does and returns `{ key: "", gridKeys }` with no grid keys, for every request; it renders nothing.
49
+ * @deprecated Since 2.22.0: returns no grid keys. Removed in 3.0.0.
51
50
  */
52
51
  collectCorrectionStates(view: SimulateDisplayViewOptions, renderOptions?: PreparedDisplayViewRenderOptions): Promise<DisplayViewCorrectionStateKeys>;
53
52
  /**
54
- * 2.10 (#447): computes the correction states of `gridKeys` (from `collectCorrectionStates`, or a share of them) as a render
55
- * would, stores them in this realm's cache and returns their values, for {@link bindDisplayViewCorrectionStates} in
56
- * another realm. States this realm holds are read, not computed. Yields and honours `signal` like `render`. Fails with an
57
- * InvalidConfigurationError when the request has no AHD or a grid key is out of range.
53
+ * 2.10 (#447), deprecated in 2.22.0: computed correction states. Since 2.22.0 it checks that `gridKeys` is an Int32Array of
54
+ * grid keys (integers in [0, 97³)) and returns `{ key: "", gridKeys, values }` with no states, for every request; it computes nothing.
55
+ * @deprecated Since 2.22.0: returns no states. Removed in 3.0.0.
58
56
  */
59
57
  computeCorrectionStates(gridKeys: Int32Array, renderOptions?: PreparedDisplayViewRenderOptions): Promise<DisplayViewCorrectionStateSet>;
60
58
  }
@@ -1,10 +1,4 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
- /**
3
- * The public entry point of the display view (`simulateDisplayView`) and its renderer. `simulate-capture.ts` resolves the
4
- * request (`runCapture`) and calls the renderer it is given, so a bundle that imports only `simulateCapture` or
5
- * `simulateIdealReference` does not contain the display view (`display-view.ts`) or the portable evaluations it uses.
6
- * The design and its error analysis are in docs/DISPLAY_VIEW.md.
7
- */
8
2
  import { ENGINE_API_VERSION } from "../core/version.js";
9
3
  import { resolvePortableColorTemperatureWhiteBalance } from "../color/white-balance.js";
10
4
  import { resolveCaptureColorModel } from "../color/capture-color.js";
@@ -13,9 +7,10 @@ import { buildExpectedSignalInput } from "./expected-signal-setup.js";
13
7
  import { resolveSensorReadoutRegime } from "../sensor/raw-readout.js";
14
8
  import { resolvePortableChartScene } from "./chart-scenes.js";
15
9
  import { resolvePortableCaptureIlluminant, calculateIlluminantIrradianceScale } from "./scene-radiance.js";
16
- import { ahdCandidateKernels, computeDisplayViewCorrectionStates, createDisplayViewExpectedSignal, displayViewCorrectionKey, renderDisplayView, EXACT_AREA_MEAN_MAX_PIXELS } from "./display-view.js";
10
+ import { ahdCandidateKernels, checkDeprecatedGridKeys, createDisplayViewExpectedSignal, renderDisplayView, EXACT_AREA_MEAN_MAX_PIXELS } from "./display-view.js";
17
11
  import { runCapture, apertureNodeOffsets, bilinearPhaseProfiles, clockMs, fail, sceneIlluminantWhiteBalance, CAMERA_TO_XYZ, CHANNELS, DARK_CURRENT_ELECTRONS_PER_SECOND, FACADE_EVIDENCE, SIMULATE_CAPTURE_FACADE_VERSION, DISPLAY_VIEW_WITHOUT_VIEW, allowKeys, parseDisplayViewOption } from "./simulate-capture.js";
18
12
  import { createHostYield } from "./host-yield.js";
13
+ import { qualityKit } from "./on-demand-kits.js";
19
14
  import { createDefocusDiscSiteKernel } from "../optics/defocus-disc-kernel.js";
20
15
  import { cpuDisplayViewExecution, parsePrepareDisplayViewOptions } from "./display-view-gpu.js";
21
16
  export { serializeDisplayViewCorrectionStates, bindDisplayViewCorrectionStates } from "./display-view.js";
@@ -54,7 +49,7 @@ export async function prepareDisplayView(options, prepareOptions) {
54
49
  const prepared = await runCapture(options, "display-view", DISPLAY_VIEW_WITHOUT_VIEW, (context) => {
55
50
  frameWidth = context.width;
56
51
  frameHeight = context.height;
57
- return Promise.resolve(prepareView(context));
52
+ return prepareView(context);
58
53
  });
59
54
  // The GPU code is loaded only when a GPU mode asks for it, so bundles on the default stay without it.
60
55
  const session = gpuOptions.gpu === "off" ? null :
@@ -70,8 +65,6 @@ export async function prepareDisplayView(options, prepareOptions) {
70
65
  checkAbort();
71
66
  return { started, viewStarted, checkAbort, yieldControl: createHostYield().yieldControl, signal };
72
67
  };
73
- const correctionOf = (caller) => prepared.correction ??
74
- fail(caller + ": the prepared request has no AHD low-signal correction (it applies with output.demosaic \"ahd\").");
75
68
  const handle = Object.freeze({
76
69
  async render(view, renderOptions) {
77
70
  const run = runOf(renderOptions);
@@ -79,15 +72,27 @@ export async function prepareDisplayView(options, prepareOptions) {
79
72
  return await prepared.render(parsed, run, undefined, session);
80
73
  },
81
74
  dispose() { session?.dispose(); },
82
- correctionKey() { return prepared.correction ? displayViewCorrectionKey(prepared.correction) : null; },
83
- async collectCorrectionStates(view, renderOptions) {
84
- const run = runOf(renderOptions), correction = correctionOf("collectCorrectionStates");
85
- const parsed = parseDisplayViewOption(view, frameWidth, frameHeight);
86
- return { key: displayViewCorrectionKey(correction), gridKeys: await prepared.collect(parsed, run) };
75
+ // Deprecated since 2.22.0 (no correction states); kept until 3.0.0.
76
+ correctionKey() { return null; },
77
+ collectCorrectionStates(view, renderOptions) {
78
+ try {
79
+ runOf(renderOptions);
80
+ parseDisplayViewOption(view, frameWidth, frameHeight);
81
+ return Promise.resolve({ key: "", gridKeys: new Int32Array(0) });
82
+ }
83
+ catch (error) {
84
+ return Promise.reject(error);
85
+ }
87
86
  },
88
- async computeCorrectionStates(gridKeys, renderOptions) {
89
- const run = runOf(renderOptions), correction = correctionOf("computeCorrectionStates");
90
- return await computeDisplayViewCorrectionStates({ ...correction, yieldControl: run.yieldControl, checkAbort: run.checkAbort }, gridKeys);
87
+ computeCorrectionStates(gridKeys, renderOptions) {
88
+ try {
89
+ runOf(renderOptions);
90
+ checkDeprecatedGridKeys(gridKeys, "computeCorrectionStates");
91
+ return Promise.resolve({ key: "", gridKeys: new Int32Array(0), values: new Float64Array(0) });
92
+ }
93
+ catch (error) {
94
+ return Promise.reject(error);
95
+ }
91
96
  }
92
97
  });
93
98
  PREPARED_INTERNALS.set(handle, async (view, renderOptions) => {
@@ -120,15 +125,14 @@ export async function simulateDisplayViewWithInternals(options, view) {
120
125
  return { result, internals: internals.value, signal: internals.signal, setup: internals.setup, signalInput: internals.signalInput };
121
126
  }
122
127
  /**
123
- * AHD low-signal correction (display view): draws per flat-neighbourhood state, and the pixel noise (linear light) above which it
124
- * applies. 2.20.0: 2048 draws are its fast method (`output.demosaic.ahd`, the view's default); exact takes 4× the draws (half
125
- * the states' common offset) at the same threshold (owner decision 2026-11-09).
128
+ * 2.22.0: the measured shift of the AHD view's expected colour that the removed low-signal correction used to cancel, in 8-bit
129
+ * codes (mean over a centred 32 × 32 block, f/8; see docs/DISPLAY_VIEW.md, "AHD at low signal"), reported in `view.demosaic`.
126
130
  */
127
- const DISPLAY_VIEW_AHD_CORRECTION_DRAWS = [8192, 2048], DISPLAY_VIEW_AHD_CORRECTION_THRESHOLD = 0.01;
131
+ const AHD_LOW_SIGNAL_BIAS_CODES = { phone1p4umIso6400Red: -4, fullFrame6umIso6400MaxAbs: 0.3, appRequest6umIso400MaxAbs: 0.01 };
128
132
  /** Renders the display view of a resolved request (the last step of `runCapture` for "display-view"). */
129
133
  async function renderDisplayViewResult(context, viewInternals) {
130
134
  const viewStarted = clockMs();
131
- return await prepareView(context).render(context.parsedView, { started: context.started, viewStarted, checkAbort: context.checkAbort, yieldControl: context.yieldControl }, viewInternals);
135
+ return await (await prepareView(context)).render(context.parsedView, { started: context.started, viewStarted, checkAbort: context.checkAbort, yieldControl: context.yieldControl }, viewInternals);
132
136
  }
133
137
  /**
134
138
  * Internal (#387): the part of a display view that depends only on the request, done once (the portable illuminant, chart and
@@ -136,14 +140,19 @@ async function renderDisplayViewResult(context, viewInternals) {
136
140
  * matrix). The returned function renders one view from it; it keeps no state between renders (each has its own expected-
137
141
  * signal caches, lookup count and assumptions), so its results are those of separate calls.
138
142
  */
139
- function prepareView(context) {
143
+ async function prepareView(context) {
140
144
  const { ahd, antiAliasing, aspect, axisChannelResponse, boxSamples, buildProvider, callerScene, chart, materialLayers, chartReport, chartSize, diffraction, diffractionPsf, fNumber, focalLengthMm, focusDistanceM, height, highlightMode, exposureGain, illuminanceLux, illuminant, illuminantOption, imagingArea, intentOf, metresPerFrameUnit, noiseSeed, outputOptions, pitch, preset, provider, regimeByChannel, resolvedIso, isoReport, standardExposureDeviationStops, standardExposureIlluminanceLux, greyCardDeviationStops, metering, sceneOption, scenePreset, shutterSeconds, subjectDistanceM, toneCurve, whiteBalanceOption, whiteBalanceState, width, margin, mode, nativeHeight, nativeWidth, sourceSha256 } = context;
141
145
  const kelvinInput = context.kelvinWhiteBalanceInput;
142
146
  // The engine's illuminant formulas (Planckian, CIE A, daylight locus) evaluated with the portable power and e^x − 1, so
143
147
  // the view's radiances, irradiance scale and scene-illuminant white balance have the same bits in every JavaScript
144
148
  // engine; they differ from the capture's own by at most a few ulps (docs/DISPLAY_VIEW.md, "Same bytes in every engine").
145
- const viewIlluminant = resolvePortableCaptureIlluminant(illuminantOption), viewIrradianceScale = calculateIlluminantIrradianceScale(viewIlluminant.shape, illuminanceLux);
146
- const viewProvider = buildProvider(viewIlluminant, viewIrradianceScale);
149
+ // #550: mixed lighting resolved with the same portable formulas; its strongest source at the frame center stands in for the illuminant.
150
+ const viewMixed = context.mixedIllumination?.(resolvePortableCaptureIlluminant), viewStrongest = viewMixed?.sources[viewMixed.center.strongestSource];
151
+ const viewIlluminant = viewStrongest ? viewStrongest.illuminant : resolvePortableCaptureIlluminant(illuminantOption);
152
+ const viewIrradianceScale = viewStrongest ? viewStrongest.irradianceScale : calculateIlluminantIrradianceScale(viewIlluminant.shape, illuminanceLux);
153
+ const stillViewProvider = buildProvider(viewIlluminant, viewIrradianceScale, viewMixed);
154
+ // #551: a moving subject is read at each temporal midpoint as radiance (no material tables).
155
+ const viewProvider = context.movingScene ? context.movingScene(stillViewProvider, viewIrradianceScale, (nm) => viewIlluminant.shape.evaluate(nm), viewMixed) : stillViewProvider;
147
156
  const viewWhiteBalanceState = whiteBalanceOption === "scene-illuminant" ? sceneIlluminantWhiteBalance(viewIlluminant) : kelvinInput ? resolvePortableColorTemperatureWhiteBalance(kelvinInput) : whiteBalanceState;
148
157
  // The chart's materials likewise (a step wedge's geometric levels use the portable power); same geometry and order.
149
158
  const viewChart = chart ? resolvePortableChartScene({ scene: sceneOption, aspect: chartSize ? chartSize.heightM / chartSize.widthM : aspect }) : undefined;
@@ -162,11 +171,12 @@ function prepareView(context) {
162
171
  const diffractionRadius = diffraction ? diffraction.kernelRadiusSamples : 0, combinedRadius = defocusKernel ? diffractionRadius + defocusKernel.radius : diffractionRadius;
163
172
  const { offsets, signalInput } = buildExpectedSignalInput({ nativeWidth, nativeHeight, width, wavelengths, perNode, apertureNodes: apertureNodeOffsets(boxSamples), boxSamples,
164
173
  antiAliasing, pitch, defocus: defocusKernel, ...(context.lensPsf ? { lensKernels: context.lensPsf.axisKernels(wavelengths) } : {}), diffraction: diffraction ? { radius: diffraction.kernelRadiusSamples, psf: diffractionPsf.configuration.psf, profileWavelengths: diffraction.profile.axes.wavelengthNm } : undefined,
165
- materials: sceneMaterials && provider.chartMaterialAt ? { materialAt: provider.chartMaterialAt,
174
+ materials: sceneMaterials && provider.chartMaterialAt && !context.movingScene ? { materialAt: provider.chartMaterialAt,
166
175
  list: [...sceneMaterials.map((m, index) => (m.kind === "neutral" ? { neutral: m.reflectance } : { radiance: (nm) => viewProvider.materialRadiance(index, nm) })),
167
176
  ...(chartSize ? [{ neutral: chartSize.surroundReflectance }] : [])],
168
177
  whiteRadiance: (nm) => viewIrradianceScale * viewIlluminant.shape.evaluate(nm) / Math.PI } : undefined,
169
- radianceAt: viewProvider.radianceAt, imagingArea, focalLengthMm, focusDistanceM, subjectDistanceM, metresPerFrameUnit, caller: "simulateDisplayView" });
178
+ radianceAt: viewProvider.radianceAt, imageSignalScene: viewProvider.imageSignalScene,
179
+ imagingArea, focalLengthMm, focusDistanceM, subjectDistanceM, metresPerFrameUnit, caller: "simulateDisplayView" });
170
180
  const kernels = signalInput.kernels, largeDefocus = signalInput.largeKernel;
171
181
  // Readout moments per channel: normalized value k·e with variance k²·(e + σ_read²) plus the ADC quantization (1/12 code², times d² before a digital gain d).
172
182
  // #556: a development exposure push G multiplies the normalized value before the per-site clip at white: k → G·k and the constant variance → G²·(…).
@@ -185,40 +195,38 @@ function prepareView(context) {
185
195
  demosaicTable[phase.phaseY * 2 + phase.phaseX] = CHANNELS.map((c) => phase.profile.kernels.find((k) => k.outputChannelId === c).contributions
186
196
  .map((t) => ({ dx: t.offsetX, dy: t.offsetY, weight: t.weight })));
187
197
  const viewIntent = intentOf(viewWhiteBalanceState), viewGains = viewIntent ? [viewIntent.channelGains.red, viewIntent.channelGains.green, viewIntent.channelGains.blue] : null;
188
- const colour = prepareSensorColorDevelopment(CAMERA_TO_XYZ, viewGains, highlightMode);
198
+ const colour = prepareSensorColorDevelopment(CAMERA_TO_XYZ, viewGains, highlightMode === "reconstruct-neighbors" ? "clip" : highlightMode);
189
199
  const toSrgb = resolveCaptureColorModel().xyzToCameraRgb, m = colour.cameraToXyz;
190
200
  const matrix = [0, 1, 2].map((r) => [0, 1, 2].map((c) => toSrgb[r][0] * m[0][c] + toSrgb[r][1] * m[1][c] + toSrgb[r][2] * m[2][c]));
191
201
  // Reach of a footprint's pixels into the scene, in sites: the demosaic (1), the largest query offset and the kernel radius.
192
202
  const reachSites = (ahd ? 3 : 1) + Math.ceil(Math.max(0, ...offsets.map((o) => Math.max(Math.abs(o.x), Math.abs(o.y))))) + (kernels ? kernels.radius : 0) + (largeDefocus ? largeDefocus.radius : 0);
193
- // The inputs of the AHD correction states (fixed here, so the correction key is too; #447).
194
203
  const gains = colour.appliedGains, clipLevel = Math.min(...colour.appliedGains), viewToneCurve = toneCurve;
195
- const ahdFast = +context.viewFast.ahd, correctionDraws = DISPLAY_VIEW_AHD_CORRECTION_DRAWS[ahdFast], correctionThreshold = DISPLAY_VIEW_AHD_CORRECTION_THRESHOLD;
196
- const ahdCorrection = ahd ? { labMatrix: CAMERA_TO_XYZ.map((row) => row.map((value, c) => value * (viewGains ? viewGains[c] : 1))), drawsPerState: correctionDraws,
197
- thresholdVariance: correctionThreshold * correctionThreshold } : undefined;
204
+ // #593, #601: the coupled rendering steps (luminance curves, reconstruct, desaturation), with the fast rules when the request is fast.
205
+ const coupledRendering = toneCurve === "extended-reinhard-luminance" || toneCurve === "naka-rushton-luminance" || highlightMode === "reconstruct" || highlightMode === "reconstruct-neighbors" || context.gamutHandling === "desaturate-to-luminance";
206
+ const rendering = coupledRendering ? { toneCurve, ...(outputOptions.toneCurveParameters === undefined ? {} : { toneCurveParameters: outputOptions.toneCurveParameters }),
207
+ highlightMode, gamutHandling: context.gamutHandling, fast: context.viewFast.rendering } : undefined;
208
+ // The coupled steps' module is loaded only for a view that asks for them (the Quality kit, #594; the default path never imports it).
209
+ const coupled = rendering ? (await qualityKit.load()).createDisplayViewCoupledRendering(rendering, colour.appliedGains, Math.min(...colour.appliedGains), matrix) : undefined;
210
+ // #457: AHD's homogeneity metric (the profile's camera → XYZ matrix times the white-balance gains) for its choice on the noise-free mosaic.
211
+ const ahdChoice = ahd ? { labMatrix: CAMERA_TO_XYZ.map((row) => row.map((value, c) => value * (viewGains ? viewGains[c] : 1))) } : undefined;
198
212
  // 2.20.0: a quarter of the samples per axis where the pilot finds no detail is the view's fast sampling; exact samples every pixel fully.
199
213
  const uniformSamplesOf = (k) => context.viewFast.uniformSampling ? Math.max(1, Math.round(k / 4)) : k;
200
214
  const ahdCandidates = ahd ? [0, 1, 2, 3].map((p) => ahdCandidateKernels(p % 2, Math.floor(p / 2))) : undefined;
201
215
  // #491: a fixed-size chart's placement for the GPU material lookup (the provider's chart-local units cu = u·m/h and the surround beyond the chart).
202
216
  const placement = chartSize ? { chartUnitsPerFrameUnit: metresPerFrameUnit / (chartSize.widthM / 2), aspect: chartSize.heightM / chartSize.widthM } : null;
203
- /** The renderer's setup of one view (with `ahdCollect`, a collect pass), and its expected signal. */
204
- const setupOf = (v, { checkAbort, yieldControl }, ahdCollect) => {
217
+ /** The renderer's setup of one view, and its expected signal. */
218
+ const setupOf = (v, { checkAbort, yieldControl }) => {
205
219
  const viewRegion = v.region ?? { x: 0, y: 0, width: v.width, height: v.height };
206
220
  // The native columns the region's windows span, beyond one window's width: a filled band need not be wider (a speed hint).
207
221
  // #563: through the lens (projection, distortion, vignetting, rotation) when the request has them.
208
222
  const signal = (context.lens ?? createDisplayViewExpectedSignal)(signalInput, Math.ceil((viewRegion.width + 2) * nativeWidth / v.width));
209
223
  return { signal, setup: { frameWidth: width, frameHeight: height, margin, nativeWidth, nativeHeight, viewWidth: v.width, viewHeight: v.height,
210
224
  region: viewRegion, samplesPerAxis: v.samplesPerAxis, uniformSamplesPerAxis: uniformSamplesOf(v.samplesPerAxis), reachSites, bitDepth: v.bitDepth, seed: noiseSeed, signal, readout, demosaic: demosaicTable,
211
- ...(ahdCandidates && ahdCorrection ? { candidates: ahdCandidates, ahdCorrection } : {}), ...(ahdCollect ? { ahdCollect } : {}),
212
- gains, clipLevel, matrix, toneCurve: viewToneCurve, yieldControl, checkAbort, gpu: { signalInput, chart: viewChart ?? null, layers: materialLayers ?? null, placement, ...(defocusKernel && !largeDefocus ? { defocusRadius: defocusKernel.radius } : {}) } } };
213
- };
214
- const correction = ahdCorrection ? { seed: noiseSeed, readout, gains, clipLevel, matrix, toneCurve: viewToneCurve, ahdCorrection } : undefined;
215
- const collect = async (v, run) => {
216
- const keys = new Set();
217
- await renderDisplayView(setupOf(v, run, keys).setup);
218
- return Int32Array.from(keys).sort();
225
+ ...(ahdCandidates && ahdChoice ? { candidates: ahdCandidates, ahdChoice } : {}),
226
+ gains, clipLevel, matrix, toneCurve: viewToneCurve, ...(rendering ? { rendering, coupled: coupled } : {}), yieldControl, checkAbort, gpu: { signalInput, chart: viewChart ?? null, layers: materialLayers ?? null, placement, ...(defocusKernel && !largeDefocus ? { defocusRadius: defocusKernel.radius } : {}) } } };
219
227
  };
220
228
  // #492: out of focus the view reads the defocus disc (its kernel in signalInput.kernels); the GPU Quality site pass gathers it (step 2c).
221
- const gpuRequest = { ahd, lens: !!context.lens, defocus: defocusKernel !== null, ...(largeDefocus ? { largeDefocus: true } : {}), diffraction: diffraction !== undefined, antiAliasing: antiAliasing !== undefined, boxSamples, toneCurve: viewToneCurve,
229
+ const gpuRequest = { ahd, lens: !!context.lens, ...(viewMixed ? { mixedIllumination: true } : {}), defocus: defocusKernel !== null, ...(largeDefocus ? { largeDefocus: true } : {}), diffraction: diffraction !== undefined, antiAliasing: antiAliasing !== undefined, boxSamples, toneCurve: viewToneCurve, ...(highlightMode === "reconstruct" || highlightMode === "reconstruct-neighbors" || context.gamutHandling === "desaturate-to-luminance" ? { coupled: true } : {}),
222
230
  scene: chart ? "chart" : materialLayers ? "material-layers" : callerScene.kind };
223
231
  const render = async (v, run, viewInternals, gpu) => {
224
232
  const { started, viewStarted } = run;
@@ -258,12 +266,11 @@ function prepareView(context) {
258
266
  assume("view.noise", "model", { method: "variance-of-the-area-mean", distribution: "normal" }, "Noise of the mean of the real pixels: the covariance of the weighted sum of independent site noises (shot, dark, read and ADC), with the demosaic correlation (B_c = Σ β², in closed form from the rectangle) and the " +
259
267
  "expected slopes of the clips and the tone curve (Stein's lemma); the variance the linearization misses and the real pixels' output rounding are added per pixel. One correlated normal draw per display pixel, seeded " +
260
268
  "by sensor.noiseSeed: the same statistics as the resized capture, not the same realization.");
261
- assume("view.demosaic", "model", ahd ? { capture: "ahd", view: "ahd-candidates-with-low-signal-correction", correctedPixels: rendered.ahdCorrectedPixelCount,
262
- correctionDrawsPerState: correctionDraws, correctionThresholdLinearStd: correctionThreshold } : { capture: "bilinear", view: "bilinear" }, ahd ? "AHD is non-linear only in its choice between two linear candidates (green along the rows or the columns, red and blue from colour differences). The view propagates both candidates' exact linear statistics " +
263
- "and averages them. Where a sampled pixel's noise exceeds " + correctionThreshold + " (linear light), the choice reacts to the noise and shifts the colour, so the pixel adds the mean " +
264
- "difference between the engine's AHD steps and the two candidates on " + correctionDraws + " drawn noisy flat neighbourhoods (Poisson electrons plus read and ADC noise) with its channel means, " +
265
- "computed once per state of a logarithmic grid (8 steps per octave of the channel means) and interpolated trilinearly, a control variate with no per-pixel sampling noise; " +
266
- "the flat-neighbourhood state is an approximation at edges (docs/DISPLAY_VIEW.md, validation)." :
269
+ assume("view.demosaic", "model", ahd ? { capture: "ahd", view: "ahd-candidates-with-noise-free-choice", lowSignalNoiseChoice: "not-modelled", scientificStatus: "approximation",
270
+ measuredBias8BitCodes: AHD_LOW_SIGNAL_BIAS_CODES } : { capture: "bilinear", view: "bilinear" }, ahd ? "AHD is non-linear only in its choice between two linear candidates (green along the rows or the columns, red and blue from colour differences). The view propagates both candidates' exact linear statistics " +
271
+ "and averages them, or takes the candidate AHD chooses on the noise-free mosaic where the scene decides the choice. An approximation: at a few electrons per site the capture's choice also reacts to the noise " +
272
+ "and shifts its colour, which the view does not model (2.22.0). Measured on a centred 32 × 32 block at f/8: a 1.4 µm sensor at ISO 6400 has its red about 4 8-bit codes above the capture's on average " +
273
+ "(up to about 7 codes in a pixel), a 6 µm sensor at ISO 6400 at most 0.3 code, and the app's 6 µm ISO 400 request at most 0.01 code (docs/DISPLAY_VIEW.md, \"AHD at low signal\")." :
267
274
  "The bilinear demosaic's linear kernels, exactly.");
268
275
  if (defocusKernel) {
269
276
  assume("view.defocus", "model", { kernel: shaped ? (diffraction ? "diffraction-convolved-with-shaped-kernel" : "shaped-kernel") : diffraction ? "diffraction-convolved-with-disc" : "disc", defocusKernelRadiusSites: defocusKernel.radius,
@@ -276,10 +283,20 @@ function prepareView(context) {
276
283
  "an approximation, because the PSF of a defocused wave is not the in-focus Airy pattern convolved with a geometric disc." :
277
284
  "The disc is the same at every spectral node (geometric optics)."));
278
285
  }
286
+ if (viewMixed)
287
+ assume("view.illumination", "model", { method: "radiance-at-every-query-point" }, "Mixed lighting (#550): the radiance at every query point, as in the capture (no material tables; exact). Not on the GPU.");
279
288
  if (execution.backend === "webgpu-f32") {
280
289
  assume("view.execution", "model", { backend: execution.backend, arithmetic: execution.arithmetic, errorBound: execution.errorBound, adapter: execution.adapter }, "Estimated on the GPU: this view was rendered by the WebGPU float32 display-view renderer, a labelled approximation of the float64 CPU reference within the a-priori " +
281
290
  "error bound reported in diagnostics.fast.execution.errorBound; it is not bit-identical to the reference. The device passed the engine's run-time conformance check first.");
282
291
  }
292
+ if (rendering)
293
+ assume("view.rendering", "model", { toneCurve, highlightMode, gamutHandling: rendering.gamutHandling, method: "coupled-moments",
294
+ luminanceTone: rendering.toneCurve === "extended-reinhard-luminance" || rendering.toneCurve === "naka-rushton-luminance" ? (rendering.fast ? "gauss-hermite-8-in-luminance-else-gauss-legendre-4x16" : "gauss-legendre-4x16-in-luminance") : null,
295
+ chainPointsPerAxis: coupled.chainPoints, fast: rendering.fast, scientificStatus: rendering.fast ? "approximation" : "exact-in-the-limit" }, "The rendering steps that couple a pixel's components act on its normal camera-channel distribution: a luminance tone curve by conditioning each developed component on the luminance " +
296
+ "(closed-form clipped-normal moments for each luminance, integrated over it" + (rendering.fast ? " with an 8-point Gauss–Hermite rule where the luminance stays positive" : " with a composite 4 × 16-point Gauss–Legendre rule") + "); " +
297
+ "highlightMode \"reconstruct\" and the desaturation, where a pixel reaches them, by integrating the whole development chain over its camera channels with a " +
298
+ coupled.chainPoints + "-point-per-axis Gauss–Hermite rule (docs/DISPLAY_VIEW.md, \"Coupled rendering\"). " +
299
+ (rendering.fast ? "The fast rules (the request resolves to fast) are a bounded approximation of the full ones." : "The full rules converge to the exact moments of the view's normal model."));
283
300
  assume("view.source", "model", { rendering: "srgb", format: v.format, ignoredCaptureOutput: ["format", "colorEncoding", "bitDepth", "gamutMapping", "jpegQuantizationStep", "dng", "metadata", "maximumPixels"].filter((k) => outputOptions[k] !== undefined) }, "The view shows the capture's sRGB rendering (its tone curve, white balance and highlight mode); the capture's file-format options do not apply to it.");
284
301
  return Object.freeze({ kind: "display-view", label: "Display view: the full-resolution capture resized to " + v.width + " × " + v.height + " (estimated); not a capture.",
285
302
  facadeVersion: SIMULATE_CAPTURE_FACADE_VERSION, engineApiVersion: ENGINE_API_VERSION,
@@ -287,11 +304,11 @@ function prepareView(context) {
287
304
  view: { width: v.width, height: v.height, frameWidth: width, frameHeight: height, scaleX, scaleY, samplesPerAxis: v.samplesPerAxis, ...(v.region ? { region: { ...v.region } } : {}) },
288
305
  exposure: { mode, settings: { fNumber, shutterSeconds, iso: resolvedIso }, ev100: Math.log2(fNumber ** 2 / shutterSeconds), ...isoReport, standardExposureDeviationStops, standardExposureIlluminanceLux, greyCardDeviationStops, metering },
289
306
  sensor: context.sensor,
290
- scene: { sceneId: chart ? "chart:" + chart.preset : callerScene.sceneId, preset: scenePreset, parameters: chart ? chart.parameters : {},
307
+ scene: { sceneId: chart ? "chart:" + chart.preset : callerScene.sceneId, preset: scenePreset, parameters: (chart ?? callerScene).parameters ?? {},
291
308
  illuminant: { id: illuminant.id, description: illuminant.description, illuminanceLux }, distanceM: subjectDistanceM,
292
309
  framedWidthM: 2 * metresPerFrameUnit, framedHeightM: 2 * metresPerFrameUnit * aspect, ...(chartReport ? { chart: chartReport } : {}), sourceSha256 },
293
310
  diagnostics: { sampleCount: rendered.sampleCount, siteEvaluations: rendered.siteCount, sceneLookups: signal.lookups, detailPixelCount: rendered.detailPixelCount,
294
- uniformPixelCount: rendered.uniformPixelCount, ahdCorrectedPixelCount: rendered.ahdCorrectedPixelCount, timingsMs: { view: viewMs, total: Date.now() - started },
311
+ uniformPixelCount: rendered.uniformPixelCount, ahdCorrectedPixelCount: 0, timingsMs: { view: viewMs, total: Date.now() - started },
295
312
  fast: Object.freeze({ ...context.fastReport, assurance: execution.backend === "webgpu-f32" ? "approximation-with-a-priori-bound" : context.fastReport.assurance, execution }),
296
313
  highlight: Object.freeze({ saturatedPixelCount: rendered.saturatedPixelCount, statistic: "expected-value" }) },
297
314
  provenance: { scientificStatus: "approximation", cameraPresetId: preset.presetId, cameraPresetVersion: preset.presetVersion, evidence: [...FACADE_EVIDENCE, ...preset.evidence],
@@ -300,6 +317,6 @@ function prepareView(context) {
300
317
  limitations: ["Estimated display view of the full-resolution capture: its expected value is a stratified Monte Carlo estimate and its noise is drawn from the variance of the area mean, so it has the resized capture's statistics, not its exact pixels; not a capture and not a measurement."] },
301
318
  assumptions: Object.freeze(assumptions.map((a) => Object.freeze(a))) });
302
319
  };
303
- return { render, collect, correction, gpuRequest };
320
+ return { render, gpuRequest };
304
321
  }
305
322
  //# sourceMappingURL=simulate-display-view.js.map