@photivra/engine 1.5.0 → 2.1.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 (1085) hide show
  1. package/CHANGELOG.md +414 -6
  2. package/CITATION.cff +1 -1
  3. package/NODE_SUPPORT.md +64 -12
  4. package/README.md +301 -182
  5. package/SECURITY.md +37 -28
  6. package/THIRD_PARTY.md +148 -4
  7. package/dist/camera/equivalent-focal-length.d.ts +13 -14
  8. package/dist/camera/equivalent-focal-length.js +15 -13
  9. package/dist/camera/equivalent-focal-length.js.map +1 -1
  10. package/dist/camera/field-of-view.d.ts +30 -19
  11. package/dist/camera/field-of-view.js +67 -18
  12. package/dist/camera/field-of-view.js.map +1 -1
  13. package/dist/camera/lens-projection.d.ts +170 -0
  14. package/dist/camera/lens-projection.js +444 -0
  15. package/dist/camera/lens-projection.js.map +1 -0
  16. package/dist/camera/projected-object-size.d.ts +10 -11
  17. package/dist/camera/projected-object-size.js +12 -10
  18. package/dist/camera/projected-object-size.js.map +1 -1
  19. package/dist/capture/capture-export-metadata.d.ts +9 -10
  20. package/dist/capture/capture-export-metadata.js +8 -5
  21. package/dist/capture/capture-export-metadata.js.map +1 -1
  22. package/dist/capture/dng-import.d.ts +91 -0
  23. package/dist/capture/dng-import.js +343 -0
  24. package/dist/capture/dng-import.js.map +1 -0
  25. package/dist/capture/environment-raw-producer.d.ts +37 -17
  26. package/dist/capture/environment-raw-producer.js +43 -19
  27. package/dist/capture/environment-raw-producer.js.map +1 -1
  28. package/dist/capture/export-jpeg.d.ts +35 -4
  29. package/dist/capture/export-jpeg.js +133 -47
  30. package/dist/capture/export-jpeg.js.map +1 -1
  31. package/dist/capture/export-tiff.d.ts +48 -24
  32. package/dist/capture/export-tiff.js +91 -31
  33. package/dist/capture/export-tiff.js.map +1 -1
  34. package/dist/capture/focus-control.d.ts +42 -65
  35. package/dist/capture/focus-control.js +56 -75
  36. package/dist/capture/focus-control.js.map +1 -1
  37. package/dist/capture/host-yield-cadence.d.ts +25 -0
  38. package/dist/capture/host-yield-cadence.js +25 -0
  39. package/dist/capture/host-yield-cadence.js.map +1 -0
  40. package/dist/capture/linear-encoding.d.ts +14 -12
  41. package/dist/capture/linear-encoding.js +14 -13
  42. package/dist/capture/linear-encoding.js.map +1 -1
  43. package/dist/capture/lossless-jpeg.d.ts +27 -0
  44. package/dist/capture/lossless-jpeg.js +237 -0
  45. package/dist/capture/lossless-jpeg.js.map +1 -0
  46. package/dist/capture/native-environment-lean.d.ts +227 -0
  47. package/dist/capture/native-environment-lean.js +974 -0
  48. package/dist/capture/native-environment-lean.js.map +1 -0
  49. package/dist/capture/native-environment-optical-stage.d.ts +97 -0
  50. package/dist/capture/native-environment-optical-stage.js +340 -0
  51. package/dist/capture/native-environment-optical-stage.js.map +1 -0
  52. package/dist/capture/native-environment-raw.d.ts +140 -6
  53. package/dist/capture/native-environment-raw.js +435 -34
  54. package/dist/capture/native-environment-raw.js.map +1 -1
  55. package/dist/capture/native-raw-development.d.ts +116 -9
  56. package/dist/capture/native-raw-development.js +221 -62
  57. package/dist/capture/native-raw-development.js.map +1 -1
  58. package/dist/capture/native-raw-dng.d.ts +60 -0
  59. package/dist/capture/native-raw-dng.js +167 -0
  60. package/dist/capture/native-raw-dng.js.map +1 -0
  61. package/dist/capture/native-raw.d.ts +65 -12
  62. package/dist/capture/native-raw.js +81 -19
  63. package/dist/capture/native-raw.js.map +1 -1
  64. package/dist/capture/packed-sensor-raw.d.ts +160 -0
  65. package/dist/capture/packed-sensor-raw.js +221 -0
  66. package/dist/capture/packed-sensor-raw.js.map +1 -0
  67. package/dist/capture/photographic-export.d.ts +58 -35
  68. package/dist/capture/photographic-export.js +177 -70
  69. package/dist/capture/photographic-export.js.map +1 -1
  70. package/dist/capture/raw-development-kernel.d.ts +52 -0
  71. package/dist/capture/raw-development-kernel.js +88 -0
  72. package/dist/capture/raw-development-kernel.js.map +1 -0
  73. package/dist/capture/raw-frame-limits.d.ts +7 -7
  74. package/dist/capture/raw-frame-limits.js +7 -6
  75. package/dist/capture/raw-frame-limits.js.map +1 -1
  76. package/dist/capture/raw-frame-reconstruction.d.ts +8 -9
  77. package/dist/capture/raw-frame-reconstruction.js +9 -8
  78. package/dist/capture/raw-frame-reconstruction.js.map +1 -1
  79. package/dist/capture/raw-white-level.d.ts +55 -0
  80. package/dist/capture/raw-white-level.js +165 -0
  81. package/dist/capture/raw-white-level.js.map +1 -0
  82. package/dist/capture/release-sequence.d.ts +5 -7
  83. package/dist/capture/release-sequence.js +15 -13
  84. package/dist/capture/release-sequence.js.map +1 -1
  85. package/dist/capture/sensor-raw-frame.d.ts +5 -6
  86. package/dist/capture/sensor-raw-frame.js +26 -9
  87. package/dist/capture/sensor-raw-frame.js.map +1 -1
  88. package/dist/capture/sensor-raw-producer.d.ts +21 -13
  89. package/dist/capture/sensor-raw-producer.js +86 -25
  90. package/dist/capture/sensor-raw-producer.js.map +1 -1
  91. package/dist/capture/simulated-capture.d.ts +15 -16
  92. package/dist/capture/simulated-capture.js +22 -12
  93. package/dist/capture/simulated-capture.js.map +1 -1
  94. package/dist/color/camera-color-matrix.d.ts +69 -0
  95. package/dist/color/camera-color-matrix.js +132 -0
  96. package/dist/color/camera-color-matrix.js.map +1 -0
  97. package/dist/color/capture-color.d.ts +17 -10
  98. package/dist/color/capture-color.js +50 -17
  99. package/dist/color/capture-color.js.map +1 -1
  100. package/dist/color/chromatic-adaptation.d.ts +63 -0
  101. package/dist/color/chromatic-adaptation.js +91 -0
  102. package/dist/color/chromatic-adaptation.js.map +1 -0
  103. package/dist/color/color-difference.d.ts +104 -0
  104. package/dist/color/color-difference.js +205 -0
  105. package/dist/color/color-difference.js.map +1 -0
  106. package/dist/color/color-matching-functions.d.ts +168 -0
  107. package/dist/color/color-matching-functions.js +309 -0
  108. package/dist/color/color-matching-functions.js.map +1 -0
  109. package/dist/color/colorimetry-math.d.ts +52 -0
  110. package/dist/color/colorimetry-math.js +144 -0
  111. package/dist/color/colorimetry-math.js.map +1 -0
  112. package/dist/color/gamut-mapping.d.ts +54 -0
  113. package/dist/color/gamut-mapping.js +107 -0
  114. package/dist/color/gamut-mapping.js.map +1 -0
  115. package/dist/color/illuminants.d.ts +182 -0
  116. package/dist/color/illuminants.js +434 -0
  117. package/dist/color/illuminants.js.map +1 -0
  118. package/dist/color/rgb-color-spaces.d.ts +79 -0
  119. package/dist/color/rgb-color-spaces.js +115 -0
  120. package/dist/color/rgb-color-spaces.js.map +1 -0
  121. package/dist/color/sensor-color-development.d.ts +33 -11
  122. package/dist/color/sensor-color-development.js +104 -30
  123. package/dist/color/sensor-color-development.js.map +1 -1
  124. package/dist/color/srgb-icc.d.ts +9 -2
  125. package/dist/color/srgb-icc.js +16 -5
  126. package/dist/color/srgb-icc.js.map +1 -1
  127. package/dist/color/srgb-transfer.d.ts +1 -2
  128. package/dist/color/srgb-transfer.js +1 -1
  129. package/dist/color/srgb-transfer.js.map +1 -1
  130. package/dist/color/white-balance.d.ts +68 -19
  131. package/dist/color/white-balance.js +168 -35
  132. package/dist/color/white-balance.js.map +1 -1
  133. package/dist/composition/image-formation-plan.d.ts +152 -128
  134. package/dist/composition/image-formation-plan.js +292 -138
  135. package/dist/composition/image-formation-plan.js.map +1 -1
  136. package/dist/composition/plan-consumer.d.ts +6 -7
  137. package/dist/composition/plan-consumer.js +14 -11
  138. package/dist/composition/plan-consumer.js.map +1 -1
  139. package/dist/core/calculation-result.d.ts +21 -14
  140. package/dist/core/calculation-result.js +209 -11
  141. package/dist/core/calculation-result.js.map +1 -1
  142. package/dist/core/canonical-json.d.ts +13 -8
  143. package/dist/core/canonical-json.js +34 -15
  144. package/dist/core/canonical-json.js.map +1 -1
  145. package/dist/core/configuration-error.d.ts +5 -4
  146. package/dist/core/configuration-error.js +5 -3
  147. package/dist/core/configuration-error.js.map +1 -1
  148. package/dist/core/evidence-provenance.d.ts +12 -12
  149. package/dist/core/evidence-provenance.js +10 -9
  150. package/dist/core/evidence-provenance.js.map +1 -1
  151. package/dist/core/image-formation.d.ts +11 -10
  152. package/dist/core/image-formation.js +11 -9
  153. package/dist/core/image-formation.js.map +1 -1
  154. package/dist/core/owned-data.d.ts +9 -17
  155. package/dist/core/owned-data.js +9 -16
  156. package/dist/core/owned-data.js.map +1 -1
  157. package/dist/core/portable-math.d.ts +15 -0
  158. package/dist/core/portable-math.js +56 -0
  159. package/dist/core/portable-math.js.map +1 -0
  160. package/dist/core/record-validation.d.ts +48 -9
  161. package/dist/core/record-validation.js +93 -19
  162. package/dist/core/record-validation.js.map +1 -1
  163. package/dist/core/scientific-assurance.d.ts +16 -14
  164. package/dist/core/scientific-assurance.js +22 -18
  165. package/dist/core/scientific-assurance.js.map +1 -1
  166. package/dist/core/spectral-composition.d.ts +13 -14
  167. package/dist/core/spectral-composition.js +30 -27
  168. package/dist/core/spectral-composition.js.map +1 -1
  169. package/dist/core/spectral.d.ts +5 -6
  170. package/dist/core/spectral.js +9 -7
  171. package/dist/core/spectral.js.map +1 -1
  172. package/dist/core/validation.d.ts +3 -6
  173. package/dist/core/validation.js +3 -5
  174. package/dist/core/validation.js.map +1 -1
  175. package/dist/core/version.d.ts +6 -6
  176. package/dist/core/version.js +6 -5
  177. package/dist/core/version.js.map +1 -1
  178. package/dist/equipment/exposure-capabilities.d.ts +10 -10
  179. package/dist/equipment/exposure-capabilities.js +40 -30
  180. package/dist/equipment/exposure-capabilities.js.map +1 -1
  181. package/dist/equipment/generic-tier-assets.d.ts +13 -6
  182. package/dist/equipment/generic-tier-assets.js +34 -15
  183. package/dist/equipment/generic-tier-assets.js.map +1 -1
  184. package/dist/equipment/generic-tier-presets.d.ts +5 -6
  185. package/dist/equipment/generic-tier-presets.js +15 -13
  186. package/dist/equipment/generic-tier-presets.js.map +1 -1
  187. package/dist/equipment/iso-capabilities.d.ts +21 -22
  188. package/dist/equipment/iso-capabilities.js +49 -44
  189. package/dist/equipment/iso-capabilities.js.map +1 -1
  190. package/dist/equipment/metering-capabilities.d.ts +5 -6
  191. package/dist/equipment/metering-capabilities.js +22 -19
  192. package/dist/equipment/metering-capabilities.js.map +1 -1
  193. package/dist/equipment/release-capabilities.d.ts +3 -4
  194. package/dist/equipment/release-capabilities.js +18 -14
  195. package/dist/equipment/release-capabilities.js.map +1 -1
  196. package/dist/exposure/exposure-duration-control.d.ts +19 -17
  197. package/dist/exposure/exposure-duration-control.js +27 -23
  198. package/dist/exposure/exposure-duration-control.js.map +1 -1
  199. package/dist/exposure/exposure-mode-resolver.d.ts +42 -39
  200. package/dist/exposure/exposure-mode-resolver.js +127 -82
  201. package/dist/exposure/exposure-mode-resolver.js.map +1 -1
  202. package/dist/exposure/exposure.d.ts +17 -16
  203. package/dist/exposure/exposure.js +22 -15
  204. package/dist/exposure/exposure.js.map +1 -1
  205. package/dist/exposure/flash-ttl.d.ts +135 -0
  206. package/dist/exposure/flash-ttl.js +193 -0
  207. package/dist/exposure/flash-ttl.js.map +1 -0
  208. package/dist/exposure/flash.d.ts +144 -36
  209. package/dist/exposure/flash.js +259 -59
  210. package/dist/exposure/flash.js.map +1 -1
  211. package/dist/exposure/metering-scene-radiance.d.ts +10 -10
  212. package/dist/exposure/metering-scene-radiance.js +42 -23
  213. package/dist/exposure/metering-scene-radiance.js.map +1 -1
  214. package/dist/exposure/metering-target.d.ts +8 -8
  215. package/dist/exposure/metering-target.js +30 -20
  216. package/dist/exposure/metering-target.js.map +1 -1
  217. package/dist/exposure/metering-temporal.d.ts +16 -15
  218. package/dist/exposure/metering-temporal.js +41 -19
  219. package/dist/exposure/metering-temporal.js.map +1 -1
  220. package/dist/exposure/metering.d.ts +64 -17
  221. package/dist/exposure/metering.js +159 -30
  222. package/dist/exposure/metering.js.map +1 -1
  223. package/dist/exposure/program-line.d.ts +5 -5
  224. package/dist/exposure/program-line.js +20 -13
  225. package/dist/exposure/program-line.js.map +1 -1
  226. package/dist/facade/camera-preset.d.ts +8 -0
  227. package/dist/facade/camera-preset.js +102 -0
  228. package/dist/facade/camera-preset.js.map +1 -0
  229. package/dist/facade/chart-radiance-batch.d.ts +57 -0
  230. package/dist/facade/chart-radiance-batch.js +121 -0
  231. package/dist/facade/chart-radiance-batch.js.map +1 -0
  232. package/dist/facade/chart-scenes.d.ts +177 -0
  233. package/dist/facade/chart-scenes.js +232 -0
  234. package/dist/facade/chart-scenes.js.map +1 -0
  235. package/dist/facade/diffraction-provider.d.ts +30 -0
  236. package/dist/facade/diffraction-provider.js +127 -0
  237. package/dist/facade/diffraction-provider.js.map +1 -0
  238. package/dist/facade/host-yield.d.ts +7 -0
  239. package/dist/facade/host-yield.js +19 -0
  240. package/dist/facade/host-yield.js.map +1 -0
  241. package/dist/facade/scene-radiance.d.ts +117 -0
  242. package/dist/facade/scene-radiance.js +205 -0
  243. package/dist/facade/scene-radiance.js.map +1 -0
  244. package/dist/facade/simulate-capture.d.ts +363 -0
  245. package/dist/facade/simulate-capture.js +1281 -0
  246. package/dist/facade/simulate-capture.js.map +1 -0
  247. package/dist/gpu/chart-radiance-gpu.d.ts +17 -0
  248. package/dist/gpu/chart-radiance-gpu.js +176 -0
  249. package/dist/gpu/chart-radiance-gpu.js.map +1 -0
  250. package/dist/gpu/image-kernel-accelerator.d.ts +132 -0
  251. package/dist/gpu/image-kernel-accelerator.js +720 -0
  252. package/dist/gpu/image-kernel-accelerator.js.map +1 -0
  253. package/dist/gpu/image-kernel-execution.d.ts +92 -0
  254. package/dist/gpu/image-kernel-execution.js +84 -0
  255. package/dist/gpu/image-kernel-execution.js.map +1 -0
  256. package/dist/gpu/sensor-stage-gpu.d.ts +44 -0
  257. package/dist/gpu/sensor-stage-gpu.js +317 -0
  258. package/dist/gpu/sensor-stage-gpu.js.map +1 -0
  259. package/dist/gpu/temporal-sum-gpu.d.ts +23 -0
  260. package/dist/gpu/temporal-sum-gpu.js +150 -0
  261. package/dist/gpu/temporal-sum-gpu.js.map +1 -0
  262. package/dist/gpu/webgpu-runtime.d.ts +63 -0
  263. package/dist/gpu/webgpu-runtime.js +215 -0
  264. package/dist/gpu/webgpu-runtime.js.map +1 -0
  265. package/dist/gpu/wgsl-chart-kernel.d.ts +30 -0
  266. package/dist/gpu/wgsl-chart-kernel.js +165 -0
  267. package/dist/gpu/wgsl-chart-kernel.js.map +1 -0
  268. package/dist/gpu/wgsl-kernels.d.ts +53 -0
  269. package/dist/gpu/wgsl-kernels.js +365 -0
  270. package/dist/gpu/wgsl-kernels.js.map +1 -0
  271. package/dist/gpu/wgsl-sensor-kernel.d.ts +64 -0
  272. package/dist/gpu/wgsl-sensor-kernel.js +409 -0
  273. package/dist/gpu/wgsl-sensor-kernel.js.map +1 -0
  274. package/dist/index.d.ts +91 -25
  275. package/dist/index.js +60 -15
  276. package/dist/index.js.map +1 -1
  277. package/dist/motion/camera-rotation.d.ts +92 -40
  278. package/dist/motion/camera-rotation.js +84 -47
  279. package/dist/motion/camera-rotation.js.map +1 -1
  280. package/dist/motion/capture-rotation-inverse-mapping.d.ts +37 -34
  281. package/dist/motion/capture-rotation-inverse-mapping.js +32 -24
  282. package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -1
  283. package/dist/motion/capture-rotation-temporal-quadrature.d.ts +39 -35
  284. package/dist/motion/capture-rotation-temporal-quadrature.js +37 -28
  285. package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -1
  286. package/dist/motion/capture-rotation-trajectory.d.ts +32 -28
  287. package/dist/motion/capture-rotation-trajectory.js +36 -26
  288. package/dist/motion/capture-rotation-trajectory.js.map +1 -1
  289. package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts +23 -21
  290. package/dist/motion/capture-translation-parallax-temporal-quadrature.js +33 -14
  291. package/dist/motion/capture-translation-parallax-temporal-quadrature.js.map +1 -1
  292. package/dist/motion/extended-object-projection.d.ts +19 -16
  293. package/dist/motion/extended-object-projection.js +38 -18
  294. package/dist/motion/extended-object-projection.js.map +1 -1
  295. package/dist/motion/projected-motion.d.ts +18 -17
  296. package/dist/motion/projected-motion.js +25 -17
  297. package/dist/motion/projected-motion.js.map +1 -1
  298. package/dist/motion/temporal-exposure-sum.d.ts +55 -0
  299. package/dist/motion/temporal-exposure-sum.js +141 -0
  300. package/dist/motion/temporal-exposure-sum.js.map +1 -0
  301. package/dist/motion/video-sequence.d.ts +111 -0
  302. package/dist/motion/video-sequence.js +179 -0
  303. package/dist/motion/video-sequence.js.map +1 -0
  304. package/dist/optics/aperture.d.ts +14 -15
  305. package/dist/optics/aperture.js +13 -11
  306. package/dist/optics/aperture.js.map +1 -1
  307. package/dist/optics/atmospheric-haze.d.ts +83 -0
  308. package/dist/optics/atmospheric-haze.js +113 -0
  309. package/dist/optics/atmospheric-haze.js.map +1 -0
  310. package/dist/optics/brown-conrady-distortion.d.ts +116 -0
  311. package/dist/optics/brown-conrady-distortion.js +291 -0
  312. package/dist/optics/brown-conrady-distortion.js.map +1 -0
  313. package/dist/optics/circle-of-confusion.d.ts +10 -10
  314. package/dist/optics/circle-of-confusion.js +15 -11
  315. package/dist/optics/circle-of-confusion.js.map +1 -1
  316. package/dist/optics/complex-pupil-psf.d.ts +64 -33
  317. package/dist/optics/complex-pupil-psf.js +190 -98
  318. package/dist/optics/complex-pupil-psf.js.map +1 -1
  319. package/dist/optics/depth-of-field.d.ts +25 -15
  320. package/dist/optics/depth-of-field.js +67 -27
  321. package/dist/optics/depth-of-field.js.map +1 -1
  322. package/dist/optics/diffraction-psf-profile.d.ts +118 -0
  323. package/dist/optics/diffraction-psf-profile.js +252 -0
  324. package/dist/optics/diffraction-psf-profile.js.map +1 -0
  325. package/dist/optics/diffraction.d.ts +14 -13
  326. package/dist/optics/diffraction.js +14 -10
  327. package/dist/optics/diffraction.js.map +1 -1
  328. package/dist/optics/focus-breathing.d.ts +88 -27
  329. package/dist/optics/focus-breathing.js +114 -23
  330. package/dist/optics/focus-breathing.js.map +1 -1
  331. package/dist/optics/focus-state.d.ts +18 -18
  332. package/dist/optics/focus-state.js +21 -15
  333. package/dist/optics/focus-state.js.map +1 -1
  334. package/dist/optics/front-of-lens-filter.d.ts +45 -14
  335. package/dist/optics/front-of-lens-filter.js +259 -88
  336. package/dist/optics/front-of-lens-filter.js.map +1 -1
  337. package/dist/optics/illumination-vignetting.d.ts +16 -17
  338. package/dist/optics/illumination-vignetting.js +40 -17
  339. package/dist/optics/illumination-vignetting.js.map +1 -1
  340. package/dist/optics/irradiance-convolution.d.ts +59 -0
  341. package/dist/optics/irradiance-convolution.js +138 -0
  342. package/dist/optics/irradiance-convolution.js.map +1 -0
  343. package/dist/optics/lateral-chromatic-aberration.d.ts +33 -30
  344. package/dist/optics/lateral-chromatic-aberration.js +33 -23
  345. package/dist/optics/lateral-chromatic-aberration.js.map +1 -1
  346. package/dist/optics/lens-psf-kernels.d.ts +89 -0
  347. package/dist/optics/lens-psf-kernels.js +175 -0
  348. package/dist/optics/lens-psf-kernels.js.map +1 -0
  349. package/dist/optics/lens-psf-profile.d.ts +78 -46
  350. package/dist/optics/lens-psf-profile.js +335 -124
  351. package/dist/optics/lens-psf-profile.js.map +1 -1
  352. package/dist/optics/longitudinal-chromatic-aberration.d.ts +102 -0
  353. package/dist/optics/longitudinal-chromatic-aberration.js +210 -0
  354. package/dist/optics/longitudinal-chromatic-aberration.js.map +1 -0
  355. package/dist/optics/polygon-diffraction.d.ts +80 -23
  356. package/dist/optics/polygon-diffraction.js +130 -25
  357. package/dist/optics/polygon-diffraction.js.map +1 -1
  358. package/dist/optics/profile-contract.d.ts +5 -6
  359. package/dist/optics/profile-contract.js +14 -11
  360. package/dist/optics/profile-contract.js.map +1 -1
  361. package/dist/optics/psf-foundation.d.ts +23 -23
  362. package/dist/optics/psf-foundation.js +24 -21
  363. package/dist/optics/psf-foundation.js.map +1 -1
  364. package/dist/optics/pupil-vignetting.d.ts +118 -0
  365. package/dist/optics/pupil-vignetting.js +264 -0
  366. package/dist/optics/pupil-vignetting.js.map +1 -0
  367. package/dist/optics/radial-distortion.d.ts +34 -33
  368. package/dist/optics/radial-distortion.js +37 -30
  369. package/dist/optics/radial-distortion.js.map +1 -1
  370. package/dist/optics/scene-to-sensor-irradiance.d.ts +47 -33
  371. package/dist/optics/scene-to-sensor-irradiance.js +73 -45
  372. package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
  373. package/dist/optics/scene-to-sensor-quadrature.d.ts +23 -18
  374. package/dist/optics/scene-to-sensor-quadrature.js +16 -11
  375. package/dist/optics/scene-to-sensor-quadrature.js.map +1 -1
  376. package/dist/optics/sensor-aperture-rays.d.ts +20 -4
  377. package/dist/optics/sensor-aperture-rays.js +32 -14
  378. package/dist/optics/sensor-aperture-rays.js.map +1 -1
  379. package/dist/optics/sensor-environment-query.d.ts +81 -16
  380. package/dist/optics/sensor-environment-query.js +145 -12
  381. package/dist/optics/sensor-environment-query.js.map +1 -1
  382. package/dist/optics/sensor-psf-quadrature.d.ts +12 -10
  383. package/dist/optics/sensor-psf-quadrature.js +18 -11
  384. package/dist/optics/sensor-psf-quadrature.js.map +1 -1
  385. package/dist/optics/sensor-psf-support.d.ts +8 -6
  386. package/dist/optics/sensor-psf-support.js +8 -5
  387. package/dist/optics/sensor-psf-support.js.map +1 -1
  388. package/dist/optics/stray-light.d.ts +22 -19
  389. package/dist/optics/stray-light.js +18 -12
  390. package/dist/optics/stray-light.js.map +1 -1
  391. package/dist/optics/thin-lens.d.ts +10 -9
  392. package/dist/optics/thin-lens.js +12 -8
  393. package/dist/optics/thin-lens.js.map +1 -1
  394. package/dist/optics/zernike-wavefront.d.ts +154 -0
  395. package/dist/optics/zernike-wavefront.js +352 -0
  396. package/dist/optics/zernike-wavefront.js.map +1 -0
  397. package/dist/output/capture-corrected-sdr.d.ts +16 -8
  398. package/dist/output/capture-corrected-sdr.js +16 -8
  399. package/dist/output/capture-corrected-sdr.js.map +1 -1
  400. package/dist/output/capture-geometry.d.ts +34 -36
  401. package/dist/output/capture-geometry.js +52 -32
  402. package/dist/output/capture-geometry.js.map +1 -1
  403. package/dist/output/capture-sdr.d.ts +7 -6
  404. package/dist/output/capture-sdr.js +11 -8
  405. package/dist/output/capture-sdr.js.map +1 -1
  406. package/dist/output/crop.d.ts +22 -6
  407. package/dist/output/crop.js +40 -6
  408. package/dist/output/crop.js.map +1 -1
  409. package/dist/output/geometric-transforms.d.ts +60 -23
  410. package/dist/output/geometric-transforms.js +111 -24
  411. package/dist/output/geometric-transforms.js.map +1 -1
  412. package/dist/output/lens-corrections.d.ts +27 -19
  413. package/dist/output/lens-corrections.js +29 -13
  414. package/dist/output/lens-corrections.js.map +1 -1
  415. package/dist/output/native-capture-sdr.d.ts +71 -16
  416. package/dist/output/native-capture-sdr.js +190 -33
  417. package/dist/output/native-capture-sdr.js.map +1 -1
  418. package/dist/output/png-encoder.d.ts +65 -0
  419. package/dist/output/png-encoder.js +461 -0
  420. package/dist/output/png-encoder.js.map +1 -0
  421. package/dist/output/print-contrast-reference.d.ts +10 -9
  422. package/dist/output/print-contrast-reference.js +10 -8
  423. package/dist/output/print-contrast-reference.js.map +1 -1
  424. package/dist/output/print-detail.d.ts +18 -17
  425. package/dist/output/print-detail.js +12 -10
  426. package/dist/output/print-detail.js.map +1 -1
  427. package/dist/output/print-jpeg.d.ts +26 -5
  428. package/dist/output/print-jpeg.js +117 -50
  429. package/dist/output/print-jpeg.js.map +1 -1
  430. package/dist/output/print-plan.d.ts +19 -19
  431. package/dist/output/print-plan.js +11 -10
  432. package/dist/output/print-plan.js.map +1 -1
  433. package/dist/output/print-region-statistics.d.ts +14 -15
  434. package/dist/output/print-region-statistics.js +11 -11
  435. package/dist/output/print-region-statistics.js.map +1 -1
  436. package/dist/output/sdr-rendering.d.ts +48 -10
  437. package/dist/output/sdr-rendering.js +114 -25
  438. package/dist/output/sdr-rendering.js.map +1 -1
  439. package/dist/output/subject-framing-crop.d.ts +6 -10
  440. package/dist/output/subject-framing-crop.js +23 -13
  441. package/dist/output/subject-framing-crop.js.map +1 -1
  442. package/dist/processing/demosaic.d.ts +90 -0
  443. package/dist/processing/demosaic.js +275 -0
  444. package/dist/processing/demosaic.js.map +1 -0
  445. package/dist/processing/denoise.d.ts +68 -0
  446. package/dist/processing/denoise.js +214 -0
  447. package/dist/processing/denoise.js.map +1 -0
  448. package/dist/processing/focus-stacking.d.ts +17 -0
  449. package/dist/processing/focus-stacking.js +80 -0
  450. package/dist/processing/focus-stacking.js.map +1 -0
  451. package/dist/processing/hdr.d.ts +54 -0
  452. package/dist/processing/hdr.js +172 -0
  453. package/dist/processing/hdr.js.map +1 -0
  454. package/dist/processing/image-ops.d.ts +66 -0
  455. package/dist/processing/image-ops.js +192 -0
  456. package/dist/processing/image-ops.js.map +1 -0
  457. package/dist/processing/panorama.d.ts +51 -0
  458. package/dist/processing/panorama.js +305 -0
  459. package/dist/processing/panorama.js.map +1 -0
  460. package/dist/processing/processing-task.d.ts +85 -0
  461. package/dist/processing/processing-task.js +164 -0
  462. package/dist/processing/processing-task.js.map +1 -0
  463. package/dist/processing/tone-mapping.d.ts +69 -0
  464. package/dist/processing/tone-mapping.js +310 -0
  465. package/dist/processing/tone-mapping.js.map +1 -0
  466. package/dist/schema/camera.d.ts +5 -4
  467. package/dist/schema/illumination-spectral.d.ts +13 -19
  468. package/dist/schema/illumination-spectral.js +23 -19
  469. package/dist/schema/illumination-spectral.js.map +1 -1
  470. package/dist/schema/illumination-temporal.d.ts +12 -15
  471. package/dist/schema/illumination-temporal.js +43 -28
  472. package/dist/schema/illumination-temporal.js.map +1 -1
  473. package/dist/schema/illumination.d.ts +5 -4
  474. package/dist/schema/illumination.js +55 -20
  475. package/dist/schema/illumination.js.map +1 -1
  476. package/dist/schema/scene-radiance-temporal.d.ts +9 -11
  477. package/dist/schema/scene-radiance-temporal.js +26 -23
  478. package/dist/schema/scene-radiance-temporal.js.map +1 -1
  479. package/dist/schema/scene-radiance.d.ts +17 -17
  480. package/dist/schema/scene-radiance.js +56 -34
  481. package/dist/schema/scene-radiance.js.map +1 -1
  482. package/dist/schema/scene.d.ts +14 -13
  483. package/dist/schema/validation.d.ts +0 -1
  484. package/dist/schema/validation.js +17 -15
  485. package/dist/schema/validation.js.map +1 -1
  486. package/dist/sensor/accumulated-charge.d.ts +45 -64
  487. package/dist/sensor/accumulated-charge.js +41 -47
  488. package/dist/sensor/accumulated-charge.js.map +1 -1
  489. package/dist/sensor/architecture.d.ts +22 -25
  490. package/dist/sensor/architecture.js +17 -16
  491. package/dist/sensor/architecture.js.map +1 -1
  492. package/dist/sensor/camera-saturation-capacity.d.ts +21 -28
  493. package/dist/sensor/camera-saturation-capacity.js +36 -34
  494. package/dist/sensor/camera-saturation-capacity.js.map +1 -1
  495. package/dist/sensor/capture-color-sampling-binding.d.ts +46 -51
  496. package/dist/sensor/capture-color-sampling-binding.js +39 -41
  497. package/dist/sensor/capture-color-sampling-binding.js.map +1 -1
  498. package/dist/sensor/capture-mode-timing.d.ts +8 -9
  499. package/dist/sensor/capture-mode-timing.js +24 -21
  500. package/dist/sensor/capture-mode-timing.js.map +1 -1
  501. package/dist/sensor/capture-mode.d.ts +28 -30
  502. package/dist/sensor/capture-mode.js +33 -31
  503. package/dist/sensor/capture-mode.js.map +1 -1
  504. package/dist/sensor/color-sampling.d.ts +30 -33
  505. package/dist/sensor/color-sampling.js +32 -37
  506. package/dist/sensor/color-sampling.js.map +1 -1
  507. package/dist/sensor/constant-rate-temporal-integration.d.ts +19 -23
  508. package/dist/sensor/constant-rate-temporal-integration.js +28 -26
  509. package/dist/sensor/constant-rate-temporal-integration.js.map +1 -1
  510. package/dist/sensor/dark-current.d.ts +53 -49
  511. package/dist/sensor/dark-current.js +87 -46
  512. package/dist/sensor/dark-current.js.map +1 -1
  513. package/dist/sensor/environment-photo-signal.d.ts +71 -30
  514. package/dist/sensor/environment-photo-signal.js +127 -46
  515. package/dist/sensor/environment-photo-signal.js.map +1 -1
  516. package/dist/sensor/eqe-electron-rate.d.ts +14 -13
  517. package/dist/sensor/eqe-electron-rate.js +34 -14
  518. package/dist/sensor/eqe-electron-rate.js.map +1 -1
  519. package/dist/sensor/eqe-local-exposure.d.ts +24 -24
  520. package/dist/sensor/eqe-local-exposure.js +15 -11
  521. package/dist/sensor/eqe-local-exposure.js.map +1 -1
  522. package/dist/sensor/eqe-temporal-exposure.d.ts +11 -11
  523. package/dist/sensor/eqe-temporal-exposure.js +15 -10
  524. package/dist/sensor/eqe-temporal-exposure.js.map +1 -1
  525. package/dist/sensor/exposure-window.d.ts +48 -34
  526. package/dist/sensor/exposure-window.js +77 -36
  527. package/dist/sensor/exposure-window.js.map +1 -1
  528. package/dist/sensor/fixed-pattern-noise.d.ts +108 -0
  529. package/dist/sensor/fixed-pattern-noise.js +166 -0
  530. package/dist/sensor/fixed-pattern-noise.js.map +1 -0
  531. package/dist/sensor/iso-gain.d.ts +44 -0
  532. package/dist/sensor/iso-gain.js +119 -0
  533. package/dist/sensor/iso-gain.js.map +1 -0
  534. package/dist/sensor/iso-signal-chain.d.ts +25 -48
  535. package/dist/sensor/iso-signal-chain.js +52 -66
  536. package/dist/sensor/iso-signal-chain.js.map +1 -1
  537. package/dist/sensor/local-exposure-binding.d.ts +21 -21
  538. package/dist/sensor/local-exposure-binding.js +22 -18
  539. package/dist/sensor/local-exposure-binding.js.map +1 -1
  540. package/dist/sensor/optical-stack.d.ts +36 -40
  541. package/dist/sensor/optical-stack.js +34 -37
  542. package/dist/sensor/optical-stack.js.map +1 -1
  543. package/dist/sensor/photon-energy.d.ts +22 -28
  544. package/dist/sensor/photon-energy.js +42 -34
  545. package/dist/sensor/photon-energy.js.map +1 -1
  546. package/dist/sensor/physical-charge-capacity.d.ts +20 -30
  547. package/dist/sensor/physical-charge-capacity.js +35 -36
  548. package/dist/sensor/physical-charge-capacity.js.map +1 -1
  549. package/dist/sensor/pixel-pitch.d.ts +2 -3
  550. package/dist/sensor/pixel-pitch.js +4 -2
  551. package/dist/sensor/pixel-pitch.js.map +1 -1
  552. package/dist/sensor/radiometry-readiness.d.ts +13 -15
  553. package/dist/sensor/radiometry-readiness.js +20 -17
  554. package/dist/sensor/radiometry-readiness.js.map +1 -1
  555. package/dist/sensor/raw-readout.d.ts +173 -83
  556. package/dist/sensor/raw-readout.js +425 -160
  557. package/dist/sensor/raw-readout.js.map +1 -1
  558. package/dist/sensor/raw-reconstruction.d.ts +112 -44
  559. package/dist/sensor/raw-reconstruction.js +200 -47
  560. package/dist/sensor/raw-reconstruction.js.map +1 -1
  561. package/dist/sensor/readout-exposure-linkage.d.ts +103 -34
  562. package/dist/sensor/readout-exposure-linkage.js +125 -27
  563. package/dist/sensor/readout-exposure-linkage.js.map +1 -1
  564. package/dist/sensor/readout-timing.d.ts +43 -44
  565. package/dist/sensor/readout-timing.js +38 -30
  566. package/dist/sensor/readout-timing.js.map +1 -1
  567. package/dist/sensor/response-application-compatibility.d.ts +21 -28
  568. package/dist/sensor/response-application-compatibility.js +35 -34
  569. package/dist/sensor/response-application-compatibility.js.map +1 -1
  570. package/dist/sensor/response-operating-range.d.ts +26 -35
  571. package/dist/sensor/response-operating-range.js +40 -39
  572. package/dist/sensor/response-operating-range.js.map +1 -1
  573. package/dist/sensor/responsivity-photocurrent.d.ts +21 -29
  574. package/dist/sensor/responsivity-photocurrent.js +57 -40
  575. package/dist/sensor/responsivity-photocurrent.js.map +1 -1
  576. package/dist/sensor/sampling-aperture.d.ts +21 -25
  577. package/dist/sensor/sampling-aperture.js +29 -28
  578. package/dist/sensor/sampling-aperture.js.map +1 -1
  579. package/dist/sensor/scene-eqe-temporal-exposure.d.ts +14 -12
  580. package/dist/sensor/scene-eqe-temporal-exposure.js +13 -8
  581. package/dist/sensor/scene-eqe-temporal-exposure.js.map +1 -1
  582. package/dist/sensor/sensor-geometry.d.ts +28 -32
  583. package/dist/sensor/sensor-geometry.js +35 -20
  584. package/dist/sensor/sensor-geometry.js.map +1 -1
  585. package/dist/sensor/signal-noise.d.ts +14 -16
  586. package/dist/sensor/signal-noise.js +15 -13
  587. package/dist/sensor/signal-noise.js.map +1 -1
  588. package/dist/sensor/spatial-sample-reduction.d.ts +45 -60
  589. package/dist/sensor/spatial-sample-reduction.js +39 -48
  590. package/dist/sensor/spatial-sample-reduction.js.map +1 -1
  591. package/dist/sensor/spatial-sampling-quadrature.d.ts +46 -54
  592. package/dist/sensor/spatial-sampling-quadrature.js +31 -36
  593. package/dist/sensor/spatial-sampling-quadrature.js.map +1 -1
  594. package/dist/sensor/spatio-spectral-reduction.d.ts +32 -42
  595. package/dist/sensor/spatio-spectral-reduction.js +24 -29
  596. package/dist/sensor/spatio-spectral-reduction.js.map +1 -1
  597. package/dist/sensor/spectral-coverage.d.ts +6 -9
  598. package/dist/sensor/spectral-coverage.js +9 -6
  599. package/dist/sensor/spectral-coverage.js.map +1 -1
  600. package/dist/sensor/spectral-quadrature.d.ts +46 -60
  601. package/dist/sensor/spectral-quadrature.js +38 -48
  602. package/dist/sensor/spectral-quadrature.js.map +1 -1
  603. package/dist/sensor/spectral-response.d.ts +53 -41
  604. package/dist/sensor/spectral-response.js +80 -47
  605. package/dist/sensor/spectral-response.js.map +1 -1
  606. package/dist/sensor/stochastic-seed.d.ts +50 -0
  607. package/dist/sensor/stochastic-seed.js +123 -0
  608. package/dist/sensor/stochastic-seed.js.map +1 -0
  609. package/dist/sensor/temporal-eqe-sum.d.ts +2 -4
  610. package/dist/sensor/temporal-eqe-sum.js +5 -6
  611. package/dist/sensor/temporal-eqe-sum.js.map +1 -1
  612. package/dist/sensor/temporal-photo-signal.d.ts +5 -6
  613. package/dist/sensor/temporal-photo-signal.js +11 -10
  614. package/dist/sensor/temporal-photo-signal.js.map +1 -1
  615. package/dist/sensor/temporal-sample-binding.d.ts +1 -2
  616. package/dist/sensor/temporal-sample-binding.js +3 -3
  617. package/dist/sensor/temporal-sample-binding.js.map +1 -1
  618. package/dist/simulation/poc-simulation.d.ts +16 -16
  619. package/dist/simulation/poc-simulation.js +20 -15
  620. package/dist/simulation/poc-simulation.js.map +1 -1
  621. package/dist/stabilization/camera-shake.d.ts +42 -18
  622. package/dist/stabilization/camera-shake.js +43 -20
  623. package/dist/stabilization/camera-shake.js.map +1 -1
  624. package/dist/stabilization/system.d.ts +44 -41
  625. package/dist/stabilization/system.js +196 -108
  626. package/dist/stabilization/system.js.map +1 -1
  627. package/docs/AGENT_GUIDE.md +183 -0
  628. package/docs/API_REFERENCE.md +777 -2
  629. package/docs/QUICK_START.md +663 -0
  630. package/docs/USAGE.md +1719 -714
  631. package/docs/api/camera-equivalent-focal-length.md +6 -7
  632. package/docs/api/camera-field-of-view.md +16 -8
  633. package/docs/api/camera-lens-projection.md +246 -0
  634. package/docs/api/camera-projected-object-size.md +6 -5
  635. package/docs/api/capture-capture-export-metadata.md +10 -10
  636. package/docs/api/capture-dng-import.md +134 -0
  637. package/docs/api/capture-environment-raw-producer.md +17 -11
  638. package/docs/api/capture-export-jpeg.md +16 -0
  639. package/docs/api/capture-focus-control.md +25 -47
  640. package/docs/api/capture-linear-encoding.md +21 -12
  641. package/docs/api/capture-lossless-jpeg.md +49 -0
  642. package/docs/api/capture-native-environment-optical-stage.md +75 -0
  643. package/docs/api/capture-native-environment-raw.md +161 -4
  644. package/docs/api/capture-native-raw-development.md +69 -8
  645. package/docs/api/capture-native-raw-dng.md +84 -0
  646. package/docs/api/capture-native-raw.md +21 -10
  647. package/docs/api/capture-packed-sensor-raw.md +156 -0
  648. package/docs/api/capture-photographic-export.md +69 -31
  649. package/docs/api/capture-raw-frame-reconstruction.md +8 -8
  650. package/docs/api/capture-raw-white-level.md +37 -0
  651. package/docs/api/capture-release-sequence.md +6 -7
  652. package/docs/api/capture-sensor-raw-frame.md +6 -6
  653. package/docs/api/capture-sensor-raw-producer.md +17 -11
  654. package/docs/api/capture-simulated-capture.md +15 -15
  655. package/docs/api/color-camera-color-matrix.md +103 -0
  656. package/docs/api/color-capture-color.md +22 -11
  657. package/docs/api/color-chromatic-adaptation.md +82 -0
  658. package/docs/api/color-color-difference.md +134 -0
  659. package/docs/api/color-color-matching-functions.md +259 -0
  660. package/docs/api/color-colorimetry-math.md +54 -0
  661. package/docs/api/color-gamut-mapping.md +72 -0
  662. package/docs/api/color-illuminants.md +280 -0
  663. package/docs/api/color-rgb-color-spaces.md +151 -0
  664. package/docs/api/color-sensor-color-development.md +27 -0
  665. package/docs/api/color-srgb-icc.md +2 -4
  666. package/docs/api/color-white-balance.md +95 -19
  667. package/docs/api/composition-image-formation-plan.md +124 -95
  668. package/docs/api/composition-plan-consumer.md +7 -7
  669. package/docs/api/core-calculation-result.md +18 -14
  670. package/docs/api/core-configuration-error.md +1 -1
  671. package/docs/api/core-image-formation.md +7 -7
  672. package/docs/api/core-scientific-assurance.md +12 -10
  673. package/docs/api/core-spectral-composition.md +14 -14
  674. package/docs/api/core-spectral.md +6 -6
  675. package/docs/api/core-validation.md +3 -3
  676. package/docs/api/core-version.md +7 -6
  677. package/docs/api/equipment-exposure-capabilities.md +11 -10
  678. package/docs/api/equipment-generic-tier-assets.md +7 -2
  679. package/docs/api/equipment-generic-tier-presets.md +6 -6
  680. package/docs/api/equipment-iso-capabilities.md +18 -18
  681. package/docs/api/equipment-metering-capabilities.md +6 -6
  682. package/docs/api/equipment-release-capabilities.md +4 -4
  683. package/docs/api/exports.json +2253 -3
  684. package/docs/api/exposure-exposure-duration-control.md +9 -9
  685. package/docs/api/exposure-exposure-mode-resolver.md +35 -31
  686. package/docs/api/exposure-exposure.md +10 -10
  687. package/docs/api/exposure-flash-ttl.md +182 -0
  688. package/docs/api/exposure-flash.md +183 -28
  689. package/docs/api/exposure-metering-scene-radiance.md +11 -10
  690. package/docs/api/exposure-metering-target.md +9 -8
  691. package/docs/api/exposure-metering-temporal.md +8 -8
  692. package/docs/api/exposure-metering.md +69 -9
  693. package/docs/api/exposure-program-line.md +6 -5
  694. package/docs/api/facade-chart-radiance-batch.md +96 -0
  695. package/docs/api/facade-chart-scenes.md +240 -0
  696. package/docs/api/facade-scene-radiance.md +122 -0
  697. package/docs/api/facade-simulate-capture.md +397 -0
  698. package/docs/api/gpu-image-kernel-accelerator.md +157 -0
  699. package/docs/api/gpu-image-kernel-execution.md +152 -0
  700. package/docs/api/motion-camera-rotation.md +43 -26
  701. package/docs/api/motion-capture-rotation-inverse-mapping.md +24 -23
  702. package/docs/api/motion-capture-rotation-temporal-quadrature.md +22 -22
  703. package/docs/api/motion-capture-rotation-trajectory.md +15 -15
  704. package/docs/api/motion-capture-translation-parallax-temporal-quadrature.md +15 -14
  705. package/docs/api/motion-extended-object-projection.md +10 -8
  706. package/docs/api/motion-projected-motion.md +8 -8
  707. package/docs/api/motion-temporal-exposure-sum.md +98 -0
  708. package/docs/api/motion-video-sequence.md +159 -0
  709. package/docs/api/optics-aperture.md +8 -8
  710. package/docs/api/optics-atmospheric-haze.md +104 -0
  711. package/docs/api/optics-brown-conrady-distortion.md +123 -0
  712. package/docs/api/optics-circle-of-confusion.md +5 -4
  713. package/docs/api/optics-complex-pupil-psf.md +57 -16
  714. package/docs/api/optics-depth-of-field.md +12 -6
  715. package/docs/api/optics-diffraction-psf-profile.md +96 -0
  716. package/docs/api/optics-diffraction.md +8 -7
  717. package/docs/api/optics-focus-breathing.md +104 -16
  718. package/docs/api/optics-focus-state.md +9 -10
  719. package/docs/api/optics-front-of-lens-filter.md +72 -14
  720. package/docs/api/optics-illumination-vignetting.md +10 -10
  721. package/docs/api/optics-irradiance-convolution.md +95 -0
  722. package/docs/api/optics-lateral-chromatic-aberration.md +22 -21
  723. package/docs/api/optics-lens-psf-kernels.md +72 -0
  724. package/docs/api/optics-lens-psf-profile.md +48 -26
  725. package/docs/api/optics-longitudinal-chromatic-aberration.md +128 -0
  726. package/docs/api/optics-polygon-diffraction.md +78 -13
  727. package/docs/api/optics-profile-contract.md +4 -4
  728. package/docs/api/optics-psf-foundation.md +12 -12
  729. package/docs/api/optics-pupil-vignetting.md +132 -0
  730. package/docs/api/optics-radial-distortion.md +12 -12
  731. package/docs/api/optics-scene-to-sensor-irradiance.md +25 -14
  732. package/docs/api/optics-scene-to-sensor-quadrature.md +15 -12
  733. package/docs/api/optics-sensor-aperture-rays.md +3 -2
  734. package/docs/api/optics-sensor-environment-query.md +52 -9
  735. package/docs/api/optics-sensor-psf-quadrature.md +13 -10
  736. package/docs/api/optics-stray-light.md +12 -11
  737. package/docs/api/optics-thin-lens.md +4 -3
  738. package/docs/api/optics-zernike-wavefront.md +229 -0
  739. package/docs/api/output-capture-corrected-sdr.md +10 -7
  740. package/docs/api/output-capture-geometry.md +35 -36
  741. package/docs/api/output-capture-sdr.md +4 -4
  742. package/docs/api/output-crop.md +7 -4
  743. package/docs/api/output-geometric-transforms.md +65 -19
  744. package/docs/api/output-lens-corrections.md +17 -15
  745. package/docs/api/output-native-capture-sdr.md +26 -13
  746. package/docs/api/output-png-encoder.md +105 -0
  747. package/docs/api/output-print-contrast-reference.md +8 -8
  748. package/docs/api/output-print-detail.md +14 -14
  749. package/docs/api/output-print-jpeg.md +22 -5
  750. package/docs/api/output-print-plan.md +18 -18
  751. package/docs/api/output-print-region-statistics.md +14 -14
  752. package/docs/api/output-sdr-rendering.md +52 -10
  753. package/docs/api/output-subject-framing-crop.md +5 -6
  754. package/docs/api/processing-demosaic.md +120 -0
  755. package/docs/api/processing-denoise.md +148 -0
  756. package/docs/api/processing-focus-stacking.md +41 -0
  757. package/docs/api/processing-hdr.md +113 -0
  758. package/docs/api/processing-panorama.md +82 -0
  759. package/docs/api/processing-processing-task.md +107 -0
  760. package/docs/api/processing-tone-mapping.md +142 -0
  761. package/docs/api/schema-camera.md +6 -4
  762. package/docs/api/schema-illumination-spectral.md +10 -11
  763. package/docs/api/schema-illumination-temporal.md +13 -15
  764. package/docs/api/schema-illumination.md +4 -4
  765. package/docs/api/schema-scene-radiance-temporal.md +10 -11
  766. package/docs/api/schema-scene-radiance.md +18 -17
  767. package/docs/api/schema-scene.md +9 -9
  768. package/docs/api/schema-validation.md +1 -1
  769. package/docs/api/sensor-accumulated-charge.md +12 -20
  770. package/docs/api/sensor-architecture.md +15 -16
  771. package/docs/api/sensor-camera-saturation-capacity.md +9 -11
  772. package/docs/api/sensor-capture-color-sampling-binding.md +47 -51
  773. package/docs/api/sensor-capture-mode-timing.md +9 -9
  774. package/docs/api/sensor-capture-mode.md +29 -30
  775. package/docs/api/sensor-color-sampling.md +31 -33
  776. package/docs/api/sensor-constant-rate-temporal-integration.md +10 -11
  777. package/docs/api/sensor-dark-current.md +30 -14
  778. package/docs/api/sensor-environment-photo-signal.md +13 -6
  779. package/docs/api/sensor-eqe-electron-rate.md +9 -8
  780. package/docs/api/sensor-eqe-local-exposure.md +18 -17
  781. package/docs/api/sensor-eqe-temporal-exposure.md +12 -11
  782. package/docs/api/sensor-exposure-window.md +24 -24
  783. package/docs/api/sensor-fixed-pattern-noise.md +104 -0
  784. package/docs/api/sensor-iso-gain.md +63 -0
  785. package/docs/api/sensor-iso-signal-chain.md +13 -22
  786. package/docs/api/sensor-local-exposure-binding.md +12 -13
  787. package/docs/api/sensor-optical-stack.md +37 -40
  788. package/docs/api/sensor-photon-energy.md +10 -11
  789. package/docs/api/sensor-physical-charge-capacity.md +8 -13
  790. package/docs/api/sensor-pixel-pitch.md +1 -1
  791. package/docs/api/sensor-radiometry-readiness.md +9 -9
  792. package/docs/api/sensor-raw-readout.md +118 -52
  793. package/docs/api/sensor-raw-reconstruction.md +97 -20
  794. package/docs/api/sensor-readout-exposure-linkage.md +120 -24
  795. package/docs/api/sensor-readout-timing.md +33 -35
  796. package/docs/api/sensor-response-application-compatibility.md +9 -11
  797. package/docs/api/sensor-response-operating-range.md +14 -18
  798. package/docs/api/sensor-responsivity-photocurrent.md +9 -12
  799. package/docs/api/sensor-sampling-aperture.md +22 -25
  800. package/docs/api/sensor-scene-eqe-temporal-exposure.md +9 -8
  801. package/docs/api/sensor-sensor-geometry.md +23 -24
  802. package/docs/api/sensor-signal-noise.md +10 -10
  803. package/docs/api/sensor-spatial-sample-reduction.md +27 -30
  804. package/docs/api/sensor-spatial-sampling-quadrature.md +37 -39
  805. package/docs/api/sensor-spatio-spectral-reduction.md +27 -29
  806. package/docs/api/sensor-spectral-coverage.md +5 -5
  807. package/docs/api/sensor-spectral-quadrature.md +33 -35
  808. package/docs/api/sensor-spectral-response.md +28 -16
  809. package/docs/api/sensor-temporal-photo-signal.md +6 -6
  810. package/docs/api/simulation-poc-simulation.md +17 -16
  811. package/docs/api/stabilization-camera-shake.md +29 -10
  812. package/docs/api/stabilization-system.md +25 -21
  813. package/docs/examples/production-request.json +3821 -2157
  814. package/docs/examples/simulate-capture.mjs +14 -0
  815. package/llms.txt +35 -0
  816. package/package.json +32 -11
  817. package/AGENTS.md +0 -674
  818. package/CONTRIBUTING.md +0 -76
  819. package/DCO +0 -33
  820. package/dist/camera/equivalent-focal-length.d.ts.map +0 -1
  821. package/dist/camera/field-of-view.d.ts.map +0 -1
  822. package/dist/camera/projected-object-size.d.ts.map +0 -1
  823. package/dist/capture/capture-export-metadata.d.ts.map +0 -1
  824. package/dist/capture/environment-raw-producer.d.ts.map +0 -1
  825. package/dist/capture/export-jpeg.d.ts.map +0 -1
  826. package/dist/capture/export-tiff.d.ts.map +0 -1
  827. package/dist/capture/focus-control.d.ts.map +0 -1
  828. package/dist/capture/linear-encoding.d.ts.map +0 -1
  829. package/dist/capture/native-environment-raw.d.ts.map +0 -1
  830. package/dist/capture/native-raw-development.d.ts.map +0 -1
  831. package/dist/capture/native-raw.d.ts.map +0 -1
  832. package/dist/capture/photographic-export.d.ts.map +0 -1
  833. package/dist/capture/raw-frame-limits.d.ts.map +0 -1
  834. package/dist/capture/raw-frame-reconstruction.d.ts.map +0 -1
  835. package/dist/capture/release-sequence.d.ts.map +0 -1
  836. package/dist/capture/sensor-raw-frame.d.ts.map +0 -1
  837. package/dist/capture/sensor-raw-producer.d.ts.map +0 -1
  838. package/dist/capture/simulated-capture.d.ts.map +0 -1
  839. package/dist/color/capture-color.d.ts.map +0 -1
  840. package/dist/color/sensor-color-development.d.ts.map +0 -1
  841. package/dist/color/srgb-icc.d.ts.map +0 -1
  842. package/dist/color/srgb-transfer.d.ts.map +0 -1
  843. package/dist/color/white-balance.d.ts.map +0 -1
  844. package/dist/composition/image-formation-plan.d.ts.map +0 -1
  845. package/dist/composition/plan-consumer.d.ts.map +0 -1
  846. package/dist/core/calculation-result.d.ts.map +0 -1
  847. package/dist/core/canonical-json.d.ts.map +0 -1
  848. package/dist/core/configuration-error.d.ts.map +0 -1
  849. package/dist/core/evidence-provenance.d.ts.map +0 -1
  850. package/dist/core/image-formation.d.ts.map +0 -1
  851. package/dist/core/owned-data.d.ts.map +0 -1
  852. package/dist/core/record-validation.d.ts.map +0 -1
  853. package/dist/core/scientific-assurance.d.ts.map +0 -1
  854. package/dist/core/spectral-composition.d.ts.map +0 -1
  855. package/dist/core/spectral.d.ts.map +0 -1
  856. package/dist/core/validation.d.ts.map +0 -1
  857. package/dist/core/version.d.ts.map +0 -1
  858. package/dist/equipment/exposure-capabilities.d.ts.map +0 -1
  859. package/dist/equipment/generic-tier-assets.d.ts.map +0 -1
  860. package/dist/equipment/generic-tier-presets.d.ts.map +0 -1
  861. package/dist/equipment/iso-capabilities.d.ts.map +0 -1
  862. package/dist/equipment/metering-capabilities.d.ts.map +0 -1
  863. package/dist/equipment/release-capabilities.d.ts.map +0 -1
  864. package/dist/exposure/exposure-duration-control.d.ts.map +0 -1
  865. package/dist/exposure/exposure-mode-resolver.d.ts.map +0 -1
  866. package/dist/exposure/exposure.d.ts.map +0 -1
  867. package/dist/exposure/flash.d.ts.map +0 -1
  868. package/dist/exposure/metering-scene-radiance.d.ts.map +0 -1
  869. package/dist/exposure/metering-target.d.ts.map +0 -1
  870. package/dist/exposure/metering-temporal.d.ts.map +0 -1
  871. package/dist/exposure/metering.d.ts.map +0 -1
  872. package/dist/exposure/program-line.d.ts.map +0 -1
  873. package/dist/index.d.ts.map +0 -1
  874. package/dist/motion/camera-rotation.d.ts.map +0 -1
  875. package/dist/motion/capture-rotation-inverse-mapping.d.ts.map +0 -1
  876. package/dist/motion/capture-rotation-temporal-quadrature.d.ts.map +0 -1
  877. package/dist/motion/capture-rotation-trajectory.d.ts.map +0 -1
  878. package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts.map +0 -1
  879. package/dist/motion/extended-object-projection.d.ts.map +0 -1
  880. package/dist/motion/projected-motion.d.ts.map +0 -1
  881. package/dist/optics/aperture.d.ts.map +0 -1
  882. package/dist/optics/circle-of-confusion.d.ts.map +0 -1
  883. package/dist/optics/complex-pupil-psf.d.ts.map +0 -1
  884. package/dist/optics/depth-of-field.d.ts.map +0 -1
  885. package/dist/optics/diffraction.d.ts.map +0 -1
  886. package/dist/optics/focus-breathing.d.ts.map +0 -1
  887. package/dist/optics/focus-state.d.ts.map +0 -1
  888. package/dist/optics/front-of-lens-filter.d.ts.map +0 -1
  889. package/dist/optics/illumination-vignetting.d.ts.map +0 -1
  890. package/dist/optics/lateral-chromatic-aberration.d.ts.map +0 -1
  891. package/dist/optics/lens-psf-profile.d.ts.map +0 -1
  892. package/dist/optics/polygon-diffraction.d.ts.map +0 -1
  893. package/dist/optics/profile-contract.d.ts.map +0 -1
  894. package/dist/optics/psf-foundation.d.ts.map +0 -1
  895. package/dist/optics/radial-distortion.d.ts.map +0 -1
  896. package/dist/optics/scene-to-sensor-irradiance.d.ts.map +0 -1
  897. package/dist/optics/scene-to-sensor-quadrature.d.ts.map +0 -1
  898. package/dist/optics/sensor-aperture-rays.d.ts.map +0 -1
  899. package/dist/optics/sensor-environment-query.d.ts.map +0 -1
  900. package/dist/optics/sensor-psf-quadrature.d.ts.map +0 -1
  901. package/dist/optics/sensor-psf-support.d.ts.map +0 -1
  902. package/dist/optics/stray-light.d.ts.map +0 -1
  903. package/dist/optics/thin-lens.d.ts.map +0 -1
  904. package/dist/output/capture-corrected-sdr.d.ts.map +0 -1
  905. package/dist/output/capture-geometry.d.ts.map +0 -1
  906. package/dist/output/capture-sdr.d.ts.map +0 -1
  907. package/dist/output/crop.d.ts.map +0 -1
  908. package/dist/output/geometric-transforms.d.ts.map +0 -1
  909. package/dist/output/lens-corrections.d.ts.map +0 -1
  910. package/dist/output/native-capture-sdr.d.ts.map +0 -1
  911. package/dist/output/print-contrast-reference.d.ts.map +0 -1
  912. package/dist/output/print-detail.d.ts.map +0 -1
  913. package/dist/output/print-jpeg.d.ts.map +0 -1
  914. package/dist/output/print-plan.d.ts.map +0 -1
  915. package/dist/output/print-region-statistics.d.ts.map +0 -1
  916. package/dist/output/sdr-rendering.d.ts.map +0 -1
  917. package/dist/output/subject-framing-crop.d.ts.map +0 -1
  918. package/dist/schema/camera.d.ts.map +0 -1
  919. package/dist/schema/camera.js +0 -3
  920. package/dist/schema/camera.js.map +0 -1
  921. package/dist/schema/illumination-spectral.d.ts.map +0 -1
  922. package/dist/schema/illumination-temporal.d.ts.map +0 -1
  923. package/dist/schema/illumination.d.ts.map +0 -1
  924. package/dist/schema/scene-radiance-temporal.d.ts.map +0 -1
  925. package/dist/schema/scene-radiance.d.ts.map +0 -1
  926. package/dist/schema/scene.d.ts.map +0 -1
  927. package/dist/schema/scene.js +0 -3
  928. package/dist/schema/scene.js.map +0 -1
  929. package/dist/schema/validation.d.ts.map +0 -1
  930. package/dist/sensor/accumulated-charge.d.ts.map +0 -1
  931. package/dist/sensor/architecture.d.ts.map +0 -1
  932. package/dist/sensor/camera-saturation-capacity.d.ts.map +0 -1
  933. package/dist/sensor/capture-color-sampling-binding.d.ts.map +0 -1
  934. package/dist/sensor/capture-mode-timing.d.ts.map +0 -1
  935. package/dist/sensor/capture-mode.d.ts.map +0 -1
  936. package/dist/sensor/color-sampling.d.ts.map +0 -1
  937. package/dist/sensor/constant-rate-temporal-integration.d.ts.map +0 -1
  938. package/dist/sensor/dark-current.d.ts.map +0 -1
  939. package/dist/sensor/environment-photo-signal.d.ts.map +0 -1
  940. package/dist/sensor/eqe-electron-rate.d.ts.map +0 -1
  941. package/dist/sensor/eqe-local-exposure.d.ts.map +0 -1
  942. package/dist/sensor/eqe-temporal-exposure.d.ts.map +0 -1
  943. package/dist/sensor/exposure-window.d.ts.map +0 -1
  944. package/dist/sensor/iso-signal-chain.d.ts.map +0 -1
  945. package/dist/sensor/local-exposure-binding.d.ts.map +0 -1
  946. package/dist/sensor/optical-stack.d.ts.map +0 -1
  947. package/dist/sensor/photon-energy.d.ts.map +0 -1
  948. package/dist/sensor/physical-charge-capacity.d.ts.map +0 -1
  949. package/dist/sensor/pixel-pitch.d.ts.map +0 -1
  950. package/dist/sensor/radiometry-readiness.d.ts.map +0 -1
  951. package/dist/sensor/raw-readout.d.ts.map +0 -1
  952. package/dist/sensor/raw-reconstruction.d.ts.map +0 -1
  953. package/dist/sensor/readout-exposure-linkage.d.ts.map +0 -1
  954. package/dist/sensor/readout-timing.d.ts.map +0 -1
  955. package/dist/sensor/response-application-compatibility.d.ts.map +0 -1
  956. package/dist/sensor/response-operating-range.d.ts.map +0 -1
  957. package/dist/sensor/responsivity-photocurrent.d.ts.map +0 -1
  958. package/dist/sensor/sampling-aperture.d.ts.map +0 -1
  959. package/dist/sensor/scene-eqe-temporal-exposure.d.ts.map +0 -1
  960. package/dist/sensor/sensor-geometry.d.ts.map +0 -1
  961. package/dist/sensor/signal-noise.d.ts.map +0 -1
  962. package/dist/sensor/spatial-sample-reduction.d.ts.map +0 -1
  963. package/dist/sensor/spatial-sampling-quadrature.d.ts.map +0 -1
  964. package/dist/sensor/spatio-spectral-reduction.d.ts.map +0 -1
  965. package/dist/sensor/spectral-coverage.d.ts.map +0 -1
  966. package/dist/sensor/spectral-quadrature.d.ts.map +0 -1
  967. package/dist/sensor/spectral-response.d.ts.map +0 -1
  968. package/dist/sensor/temporal-eqe-sum.d.ts.map +0 -1
  969. package/dist/sensor/temporal-photo-signal.d.ts.map +0 -1
  970. package/dist/sensor/temporal-sample-binding.d.ts.map +0 -1
  971. package/dist/simulation/poc-simulation.d.ts.map +0 -1
  972. package/dist/stabilization/camera-shake.d.ts.map +0 -1
  973. package/dist/stabilization/system.d.ts.map +0 -1
  974. package/docs/API_STYLE.md +0 -235
  975. package/docs/ARCHITECTURE.md +0 -356
  976. package/docs/AUTOMATION_COORDINATION.md +0 -190
  977. package/docs/CAPTURE_COLOR.md +0 -25
  978. package/docs/CAPTURE_CORRECTED_SDR.md +0 -25
  979. package/docs/CAPTURE_EXPORT_METADATA.md +0 -27
  980. package/docs/CAPTURE_SDR.md +0 -22
  981. package/docs/DENSE_PUPIL_QUALIFICATION.md +0 -121
  982. package/docs/DEVELOPERS.md +0 -68
  983. package/docs/DIGITAL_OPTICS_FOUNDATION.md +0 -69
  984. package/docs/ENVIRONMENT_RAW_CAPTURE.md +0 -208
  985. package/docs/EXPORT_ACCEPTANCE.md +0 -133
  986. package/docs/GENERIC_TIER_PRESETS.md +0 -269
  987. package/docs/GEOMETRIC_PREPARATION_REUSE.md +0 -141
  988. package/docs/IMAGE_FORMATION.md +0 -247
  989. package/docs/LINEAR_CAPTURE_ENCODING.md +0 -25
  990. package/docs/MOTION_AND_SIGNAL.md +0 -250
  991. package/docs/NATIVE_CAPTURE_SDR.md +0 -70
  992. package/docs/NATIVE_CAPTURE_SDR_REVIEW.md +0 -37
  993. package/docs/NATIVE_CAPTURE_SDR_VALIDATION.md +0 -34
  994. package/docs/NATIVE_RAW_AND_PRINT.md +0 -54
  995. package/docs/NUMERICAL_CORRECTNESS.md +0 -191
  996. package/docs/PERFORMANCE_BASELINE.md +0 -56
  997. package/docs/PHOTOGRAPHIC_EXPORT.md +0 -206
  998. package/docs/PHYSICS_FOUNDATION.md +0 -426
  999. package/docs/POC_API.md +0 -278
  1000. package/docs/POC_PROJECTION_PLATFORM_REFERENCE.md +0 -12
  1001. package/docs/POC_PROJECTION_REUSE.md +0 -124
  1002. package/docs/PRINT_195_196_REVIEW.md +0 -93
  1003. package/docs/PRINT_196_ENGINE_ACCEPTANCE.md +0 -45
  1004. package/docs/PRINT_CONTRAST_REFERENCE.md +0 -43
  1005. package/docs/PRINT_DETAIL_ASSESSMENT.md +0 -81
  1006. package/docs/PRINT_DETAIL_JPEG_EVIDENCE.md +0 -36
  1007. package/docs/PRINT_DETAIL_SDR_EVIDENCE.md +0 -29
  1008. package/docs/PRINT_DETAIL_VALIDATION.md +0 -36
  1009. package/docs/PRINT_PLANNING.md +0 -75
  1010. package/docs/PRINT_REGION_STATISTICS.md +0 -38
  1011. package/docs/PROCESSED_OUTPUT.md +0 -157
  1012. package/docs/PRODUCTION_COMPOSITION.md +0 -373
  1013. package/docs/PRODUCTION_ENVIRONMENT_CAPTURE.md +0 -131
  1014. package/docs/PROVENANCE.md +0 -115
  1015. package/docs/PSF_FOUNDATION.md +0 -165
  1016. package/docs/RAW_FRAME_ENVELOPE.md +0 -56
  1017. package/docs/RAW_FRAME_RECONSTRUCTION.md +0 -30
  1018. package/docs/RELEASE_1_0.md +0 -66
  1019. package/docs/RELEASE_1_0_1.md +0 -61
  1020. package/docs/RELEASE_1_1_0.md +0 -25
  1021. package/docs/RELEASE_1_2_0.md +0 -51
  1022. package/docs/RELEASE_1_3_0.md +0 -15
  1023. package/docs/RELEASE_1_4_0.md +0 -23
  1024. package/docs/RELEASE_1_5_0.md +0 -105
  1025. package/docs/RELEASE_AUDIT.md +0 -39
  1026. package/docs/SCENE_RADIANCE_AND_ILLUMINATION.md +0 -298
  1027. package/docs/SCENE_SENSOR_QUADRATURE.md +0 -98
  1028. package/docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md +0 -86
  1029. package/docs/SCIENTIFIC_ASSURANCE.md +0 -280
  1030. package/docs/SCIENTIFIC_CONFORMANCE.md +0 -83
  1031. package/docs/SDR_RENDERING.md +0 -33
  1032. package/docs/SENSOR_APERTURE_RAYS.md +0 -23
  1033. package/docs/SENSOR_ENVIRONMENT_QUERY.md +0 -86
  1034. package/docs/SENSOR_EQE_LOCAL_EXPOSURE.md +0 -104
  1035. package/docs/SENSOR_EQE_TEMPORAL_EXPOSURE.md +0 -74
  1036. package/docs/SENSOR_PSF_QUADRATURE.md +0 -90
  1037. package/docs/SENSOR_RAW_FRAME.md +0 -20
  1038. package/docs/SENSOR_RAW_PRODUCER.md +0 -77
  1039. package/docs/SEPARABLE_EMISSION_DRAFT.md +0 -103
  1040. package/docs/SIGNAL_CONFORMANCE.md +0 -23
  1041. package/docs/SIMULATED_CAPTURE.md +0 -65
  1042. package/docs/STABILIZATION.md +0 -234
  1043. package/docs/TEMPORAL_PHOTO_RAW.md +0 -83
  1044. package/docs/TIER_ACCEPTANCE.md +0 -129
  1045. package/docs/TIER_PRESET_ACCEPTANCE.md +0 -59
  1046. package/docs/V1_COMPOSITION_MAP.md +0 -123
  1047. package/docs/V1_HELPER_REUSE_REVIEW.md +0 -60
  1048. package/docs/V1_PERFORMANCE_DISPOSITION.md +0 -88
  1049. package/docs/benchmarks/2026-10-01-main-baseline.json +0 -694
  1050. package/docs/benchmarks/2026-10-02-geometric-preparation-reuse.json +0 -2190
  1051. package/docs/benchmarks/2026-10-02-poc-projection-reuse.json +0 -2423
  1052. package/docs/benchmarks/2026-10-02-v1-environment-gc-profile.json +0 -210
  1053. package/docs/benchmarks/2026-10-02-v1-environment-ordinary.json +0 -187
  1054. package/docs/benchmarks/2026-10-02-v1-geometry-gc-profile.json +0 -756
  1055. package/docs/benchmarks/2026-10-02-v1-geometry-ordinary-1.json +0 -711
  1056. package/docs/benchmarks/2026-10-02-v1-geometry-ordinary-2.json +0 -711
  1057. package/docs/benchmarks/2026-10-02-v1-poc-gc-profile.json +0 -885
  1058. package/docs/benchmarks/2026-10-02-v1-poc-ordinary-1.json +0 -868
  1059. package/docs/benchmarks/2026-10-02-v1-poc-ordinary-2.json +0 -868
  1060. package/docs/licenses/castleCSF-MIT.txt +0 -21
  1061. package/docs/validation/dense-pupil-2026-10-06/pilot.jsonl +0 -6
  1062. package/docs/validation/documentation-fragments.json +0 -212
  1063. package/docs/validation/native-capture-sdr-darwin-arm64-node26-review.jsonl +0 -4
  1064. package/docs/validation/native-capture-sdr-darwin-arm64.jsonl +0 -3
  1065. package/docs/validation/native-raw-print-2026-10-04/fractional-asymmetric-crop.jpg +0 -0
  1066. package/docs/validation/native-raw-print-2026-10-04/gray-ramp.jpg +0 -0
  1067. package/docs/validation/native-raw-print-2026-10-04/linear-area-checker.jpg +0 -0
  1068. package/docs/validation/native-raw-print-2026-10-04/manifest.json +0 -218
  1069. package/docs/validation/native-raw-print-2026-10-04/megapixel-native.jpg +0 -0
  1070. package/docs/validation/native-raw-print-2026-10-04/native-color.jpg +0 -0
  1071. package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel-validation.json +0 -9
  1072. package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json +0 -29
  1073. package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json.codes.u16le.gz +0 -0
  1074. package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json.jpg +0 -0
  1075. package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json.rgb.gz +0 -0
  1076. package/docs/validation/native-raw-print-2026-10-04/srgb.icc +0 -0
  1077. package/docs/validation/native-raw-print-2026-10-04/validation.json +0 -41
  1078. package/docs/validation/print-196-candidate-capabilities.json +0 -28
  1079. package/docs/validation/print-196-candidate-evidence.json +0 -356
  1080. package/docs/validation/print-196-engine-acceptance.json +0 -81
  1081. package/docs/validation/print-detail-capabilities.json +0 -103
  1082. package/docs/validation/print-detail-jpeg-evidence.json +0 -116
  1083. package/docs/validation/print-detail-sdr-evidence.json +0 -81
  1084. package/docs/validation/release-audit-inventory.json +0 -1306
  1085. package/docs/validation/tier-acceptance-report-v1.json +0 -2538
@@ -1,14 +1,17 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  /**
3
- * Module boundary and integration notes.
4
- * Calculates EV100 from aperture and shutter duration.
5
- * Compares image-plane optical exposure using the proportional relation shutterSeconds / aperture^2.
6
- * This does not include scene light, lens transmission, vignetting, or sensor response and therefore
7
- * must not be interpreted as a photon-count result.
8
- * @see docs/USAGE.md for equations, coordinate/unit conventions, blockers and support limits.
3
+ * Basic exposure relations.
4
+ * - EV100: exposure value from aperture and shutter duration.
5
+ * - Relative optical exposure at the image plane, from shutterSeconds / aperture^2.
6
+ * - Relative rendering exposure, which also includes nominal ISO gain.
7
+ * These do not include scene light, lens transmission, vignetting or sensor response. Do not read
8
+ * them as photon counts.
9
+ * @see docs/USAGE.md for the equations, units, coordinate conventions, known blockers and support
10
+ * limits.
9
11
  */
10
12
  import { calculatedResult } from "../core/calculation-result.js";
11
13
  import { requirePositiveFinite } from "../core/validation.js";
14
+ import { requireInputKeys } from "../core/record-validation.js";
12
15
  /**
13
16
  * Calculates EV100 from aperture and shutter duration.
14
17
  *
@@ -16,6 +19,7 @@ import { requirePositiveFinite } from "../core/validation.js";
16
19
  * @returns EV100 value.
17
20
  */
18
21
  export function calculateExposureValue100(input) {
22
+ requireInputKeys(input, "calculateExposureValue100", ["aperture", "shutterSeconds"]);
19
23
  requirePositiveFinite("aperture", input.aperture);
20
24
  requirePositiveFinite("shutterSeconds", input.shutterSeconds);
21
25
  return calculatedResult(Math.log2((input.aperture * input.aperture) / input.shutterSeconds), "exposure-value-100", "1.0.0", ["Lens transmission (T-stop) is not modeled"]);
@@ -24,10 +28,11 @@ export function calculateExposureValue100(input) {
24
28
  * Compares image-plane optical exposure using the proportional relation
25
29
  * shutterSeconds / aperture^2.
26
30
  *
27
- * This does not include scene light, lens transmission, vignetting, or sensor
28
- * response and therefore must not be interpreted as a photon-count result.
31
+ * This does not include scene light, lens transmission, vignetting or sensor
32
+ * response. Do not read it as a photon count.
29
33
  */
30
34
  export function calculateRelativeOpticalExposure(input) {
35
+ requireInputKeys(input, "calculateRelativeOpticalExposure", ["aperture", "shutterSeconds", "referenceAperture", "referenceShutterSeconds"]);
31
36
  requirePositiveFinite("aperture", input.aperture);
32
37
  requirePositiveFinite("shutterSeconds", input.shutterSeconds);
33
38
  requirePositiveFinite("referenceAperture", input.referenceAperture);
@@ -49,15 +54,16 @@ export function calculateRelativeOpticalExposure(input) {
49
54
  * Calculates a relative linear rendering exposure from aperture, shutter, and
50
55
  * nominal ISO gain.
51
56
  *
52
- * This relation is intended for deterministic educational rendering relative to
53
- * a declared reference exposure. ISO is treated as a brightness/gain control;
54
- * it does not create photons and this function does not model sensor noise,
55
- * clipping, tone mapping, lens transmission, or absolute scene luminance.
57
+ * This relation is for deterministic educational rendering, relative to a
58
+ * declared reference exposure. ISO is treated as a brightness (gain) control;
59
+ * it does not create photons. This function does not model sensor noise,
60
+ * clipping, tone mapping, lens transmission or absolute scene luminance.
56
61
  *
57
62
  * @param input Current and reference aperture/shutter/ISO settings.
58
63
  * @returns Relative rendering factor and stop difference.
59
64
  */
60
65
  export function calculateRelativeRenderedExposure(input) {
66
+ requireInputKeys(input, "calculateRelativeRenderedExposure", ["aperture", "shutterSeconds", "iso", "referenceAperture", "referenceShutterSeconds", "referenceIso"]);
61
67
  requirePositiveFinite("iso", input.iso);
62
68
  requirePositiveFinite("referenceIso", input.referenceIso);
63
69
  const optical = calculateRelativeOpticalExposure({
@@ -81,13 +87,14 @@ export function calculateRelativeRenderedExposure(input) {
81
87
  ]);
82
88
  }
83
89
  /**
84
- * Calculates the ISO/gain setting that preserves nominal rendered exposure
85
- * after changing aperture and/or shutter, assuming all other factors remain
86
- * constant.
90
+ * Calculates the ISO (gain) setting that keeps the nominal rendered exposure
91
+ * the same after aperture, shutter or both change. Assumes nothing else
92
+ * changes.
87
93
  *
88
94
  * This is an exposure-compensation relation, not a sensor-noise model.
89
95
  */
90
96
  export function calculateEquivalentIso(input) {
97
+ requireInputKeys(input, "calculateEquivalentIso", ["baseIso", "baseAperture", "baseShutterSeconds", "aperture", "shutterSeconds"]);
91
98
  requirePositiveFinite("baseIso", input.baseIso);
92
99
  requirePositiveFinite("baseAperture", input.baseAperture);
93
100
  requirePositiveFinite("baseShutterSeconds", input.baseShutterSeconds);
@@ -1 +1 @@
1
- {"version":3,"file":"exposure.js","sourceRoot":"","sources":["../../src/exposure/exposure.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"exposure.js","sourceRoot":"","sources":["../../src/exposure/exposure.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Basic exposure relations.\n * - EV100: exposure value from aperture and shutter duration.\n * - Relative optical exposure at the image plane, from shutterSeconds / aperture^2.\n * - Relative rendering exposure, which also includes nominal ISO gain.\n * These do not include scene light, lens transmission, vignetting or sensor response. Do not read\n * them as photon counts.\n * @see docs/USAGE.md for the equations, units, coordinate conventions, known blockers and support\n * limits.\n */\n\nimport {\n calculatedResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport { requirePositiveFinite } from \"../core/validation.js\";\nimport { requireInputKeys } from \"../core/record-validation.js\";\n\nexport interface CalculateExposureValue100Input {\n /** F-number. */\n aperture: number;\n /** Shutter duration in seconds. */\n shutterSeconds: number;\n}\n\n/**\n * Calculates EV100 from aperture and shutter duration.\n *\n * @param input Aperture and shutter duration.\n * @returns EV100 value.\n */\nexport function calculateExposureValue100(\n input: CalculateExposureValue100Input\n): CalculationResult<number> {\n requireInputKeys(input, \"calculateExposureValue100\", [\"aperture\", \"shutterSeconds\"]);\n requirePositiveFinite(\"aperture\", input.aperture);\n requirePositiveFinite(\"shutterSeconds\", input.shutterSeconds);\n\n return calculatedResult(\n Math.log2((input.aperture * input.aperture) / input.shutterSeconds),\n \"exposure-value-100\",\n \"1.0.0\",\n [\"Lens transmission (T-stop) is not modeled\"]\n );\n}\n\nexport interface CalculateRelativeOpticalExposureInput {\n aperture: number;\n shutterSeconds: number;\n referenceAperture: number;\n referenceShutterSeconds: number;\n}\n\nexport interface RelativeOpticalExposure {\n /** Relative light exposure at the image plane; 1 equals the reference. */\n factor: number;\n /** Difference from the reference in stops. Positive means more light exposure. */\n stops: number;\n}\n\n/**\n * Compares image-plane optical exposure using the proportional relation\n * shutterSeconds / aperture^2.\n *\n * This does not include scene light, lens transmission, vignetting or sensor\n * response. Do not read it as a photon count.\n */\nexport function calculateRelativeOpticalExposure(\n input: CalculateRelativeOpticalExposureInput\n): CalculationResult<RelativeOpticalExposure> {\n requireInputKeys(input, \"calculateRelativeOpticalExposure\", [\"aperture\", \"shutterSeconds\", \"referenceAperture\", \"referenceShutterSeconds\"]);\n requirePositiveFinite(\"aperture\", input.aperture);\n requirePositiveFinite(\"shutterSeconds\", input.shutterSeconds);\n requirePositiveFinite(\"referenceAperture\", input.referenceAperture);\n requirePositiveFinite(\n \"referenceShutterSeconds\",\n input.referenceShutterSeconds\n );\n\n const current =\n input.shutterSeconds / (input.aperture * input.aperture);\n const reference =\n input.referenceShutterSeconds /\n (input.referenceAperture * input.referenceAperture);\n const factor = current / reference;\n\n return calculatedResult(\n {\n factor,\n stops: Math.log2(factor)\n },\n \"relative-optical-exposure\",\n \"1.0.0\",\n [\n \"Constant scene illumination\",\n \"Lens transmission is not modeled\",\n \"Sensor response is not modeled\"\n ]\n );\n}\n\nexport interface CalculateRelativeRenderedExposureInput {\n aperture: number;\n shutterSeconds: number;\n iso: number;\n referenceAperture: number;\n referenceShutterSeconds: number;\n referenceIso: number;\n}\n\nexport interface RelativeRenderedExposure {\n /** Nominal linear rendering multiplier; 1 equals the reference settings. */\n factor: number;\n /** Difference from the reference in stops. Positive means a brighter rendering. */\n stops: number;\n /** Image-plane optical exposure ratio before nominal ISO gain. */\n opticalFactor: number;\n /** Nominal ISO gain ratio relative to the reference ISO. */\n isoGainFactor: number;\n}\n\n/**\n * Calculates a relative linear rendering exposure from aperture, shutter, and\n * nominal ISO gain.\n *\n * This relation is for deterministic educational rendering, relative to a\n * declared reference exposure. ISO is treated as a brightness (gain) control;\n * it does not create photons. This function does not model sensor noise,\n * clipping, tone mapping, lens transmission or absolute scene luminance.\n *\n * @param input Current and reference aperture/shutter/ISO settings.\n * @returns Relative rendering factor and stop difference.\n */\nexport function calculateRelativeRenderedExposure(\n input: CalculateRelativeRenderedExposureInput\n): CalculationResult<RelativeRenderedExposure> {\n requireInputKeys(input, \"calculateRelativeRenderedExposure\", [\"aperture\", \"shutterSeconds\", \"iso\", \"referenceAperture\", \"referenceShutterSeconds\", \"referenceIso\"]);\n requirePositiveFinite(\"iso\", input.iso);\n requirePositiveFinite(\"referenceIso\", input.referenceIso);\n\n const optical = calculateRelativeOpticalExposure({\n aperture: input.aperture,\n shutterSeconds: input.shutterSeconds,\n referenceAperture: input.referenceAperture,\n referenceShutterSeconds: input.referenceShutterSeconds\n });\n const isoGainFactor = input.iso / input.referenceIso;\n const factor = optical.value.factor * isoGainFactor;\n\n return calculatedResult(\n {\n factor,\n stops: Math.log2(factor),\n opticalFactor: optical.value.factor,\n isoGainFactor\n },\n \"relative-rendered-exposure\",\n \"1.0.0\",\n [\n \"Constant scene illumination\",\n \"ISO is treated as nominal rendering gain, not photon creation\",\n \"Lens transmission and sensor-specific gain behavior are not modeled\",\n \"Clipping and display tone mapping are not modeled\"\n ]\n );\n}\n\nexport interface CalculateEquivalentIsoInput {\n baseIso: number;\n baseAperture: number;\n baseShutterSeconds: number;\n aperture: number;\n shutterSeconds: number;\n}\n\n/**\n * Calculates the ISO (gain) setting that keeps the nominal rendered exposure\n * the same after aperture, shutter or both change. Assumes nothing else\n * changes.\n *\n * This is an exposure-compensation relation, not a sensor-noise model.\n */\nexport function calculateEquivalentIso(\n input: CalculateEquivalentIsoInput\n): CalculationResult<number> {\n requireInputKeys(input, \"calculateEquivalentIso\", [\"baseIso\", \"baseAperture\", \"baseShutterSeconds\", \"aperture\", \"shutterSeconds\"]);\n requirePositiveFinite(\"baseIso\", input.baseIso);\n requirePositiveFinite(\"baseAperture\", input.baseAperture);\n requirePositiveFinite(\"baseShutterSeconds\", input.baseShutterSeconds);\n requirePositiveFinite(\"aperture\", input.aperture);\n requirePositiveFinite(\"shutterSeconds\", input.shutterSeconds);\n\n const baseLight =\n input.baseShutterSeconds /\n (input.baseAperture * input.baseAperture);\n const newLight =\n input.shutterSeconds / (input.aperture * input.aperture);\n\n return calculatedResult(\n input.baseIso * (baseLight / newLight),\n \"equivalent-iso-compensation\",\n \"1.0.0\",\n [\n \"Constant scene illumination\",\n \"ISO is treated as gain/brightness compensation, not photon creation\",\n \"Lens transmission and sensor-specific gain behavior are not modeled\"\n ]\n );\n}\n"]}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Flash guide numbers, and through-the-lens (TTL) flash exposure with a pre-flash that does not
3
+ * depend on any manufacturer.
4
+ *
5
+ * How TTL works here:
6
+ * 1. The pre-flash is measured with the existing relative exposure meter.
7
+ * 2. The solved power fraction is applied to a ManualFlashProfile.
8
+ * 3. That pulse is placed by the existing front/rear-curtain sync (resolveManualFlashSync) or by
9
+ * high-speed sync (resolveHighSpeedFlashSync).
10
+ * Flash metering stays separate from ambient metering. The ambient meter result is an input and is
11
+ * not changed. No vendor's TTL algorithm, zone weighting table or flash protocol is copied.
12
+ * @see docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md#flash-guide-number-ttl-and-high-speed-sync
13
+ */
14
+ import { type CalculationResult } from "../core/calculation-result.js";
15
+ import { type ManualFlashProfile } from "./flash.js";
16
+ import { type ExposureMeteringProfile, type ExposureMeteringSampleSet } from "./metering.js";
17
+ export declare const TTL_FLASH_MODEL: Readonly<{
18
+ readonly id: "preflash-linear-ttl";
19
+ readonly version: "1.0.0";
20
+ }>;
21
+ export interface FlashGuideNumberInput {
22
+ /** Guide number at full power for ISO 100, in metres (GN = distance · f-number). */
23
+ fullPowerGuideNumberMetersIso100: number;
24
+ /** Output as a fraction of full power, (0, 1]. */
25
+ powerFraction: number;
26
+ iso: number;
27
+ }
28
+ /**
29
+ * Effective guide number GN = GN_full · √p · √(ISO/100).
30
+ *
31
+ * The guide number relation GN = d·N follows from the inverse-square law. Light on the subject from a
32
+ * point-like flash falls as 1/d², and sensor exposure falls as 1/N². So exposure stays correct while
33
+ * d·N is constant (camera equation H = 0.65·L·t/N² and reference exposure H = 10/S, CIPA DC-004-2020,
34
+ * free). Exposure grows linearly with emitted energy (power fraction p), and the exposure needed falls
35
+ * inversely with ISO speed. So GN ∝ √p·√ISO. The engine does not model how a guide number is measured;
36
+ * the caller supplies it.
37
+ * @see docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md for the full derivation.
38
+ */
39
+ export declare function calculateFlashGuideNumber(input: FlashGuideNumberInput): number;
40
+ export interface FlashPowerForDistanceInput {
41
+ fullPowerGuideNumberMetersIso100: number;
42
+ subjectDistanceM: number;
43
+ apertureFNumber: number;
44
+ iso: number;
45
+ /** Lowest available power fraction, (0, 1]. */
46
+ minimumPowerFraction: number;
47
+ }
48
+ export interface FlashPowerForDistance {
49
+ /** p = (d·N / (GN_full·√(ISO/100)))², before clamping. */
50
+ requiredPowerFraction: number;
51
+ powerFraction: number;
52
+ status: "within-range" | "clamped-at-minimum-power" | "clamped-at-full-power";
53
+ /** log2(delivered / required) flash exposure; positive is overexposure. */
54
+ flashExposureErrorStops: number;
55
+ /** GN_full·√(ISO/100)/N: the farthest correctly exposed distance at full power. */
56
+ maximumDistanceM: number;
57
+ }
58
+ /** Manual guide-number exposure: the power fraction that exposes a subject at distance d correctly. */
59
+ export declare function calculateFlashPowerForDistance(input: FlashPowerForDistanceInput): FlashPowerForDistance;
60
+ export interface ResolveTtlFlashExposureInput {
61
+ /** Spatially linear metering profile (multi-zone-uniform, center-weighted-radial or spot). */
62
+ meteringProfile: ExposureMeteringProfile;
63
+ /** Measurement-window samples with the flash off. */
64
+ ambientSampleSet: ExposureMeteringSampleSet;
65
+ /** The same zones and settings with the pre-flash fired. */
66
+ preFlashSampleSet: ExposureMeteringSampleSet;
67
+ /** Pre-flash output as a fraction of full power, (0, 1]. */
68
+ preFlashPowerFraction: number;
69
+ /**
70
+ * Ratio of ambient light collected in the main exposure to that in the measurement window, at the
71
+ * same aperture and ISO (for example t_main/t_measure). Must be ≥ 0. The flash pulse falls inside
72
+ * both windows, so it is not scaled.
73
+ */
74
+ ambientScaleToMainExposure: number;
75
+ /** Flash exposure compensation applied to the TTL target, in stops. */
76
+ flashExposureCompensationStops: number;
77
+ /** Lowest available main-flash power fraction, (0, 1]. */
78
+ minimumPowerFraction: number;
79
+ /**
80
+ * Flash energy each line receives, relative to an ordinary pulse at the same power fraction. 1 for
81
+ * front/rear-curtain sync; η·t_e/D for high-speed sync (see resolveHighSpeedFlashSync). Defaults to 1.
82
+ */
83
+ syncEnergyFactor?: number;
84
+ /** Optional guide-number reporting. */
85
+ guideNumber?: {
86
+ fullPowerGuideNumberMetersIso100: number;
87
+ iso: number;
88
+ apertureFNumber: number;
89
+ };
90
+ }
91
+ export interface TtlFlashExposure {
92
+ modelId: typeof TTL_FLASH_MODEL.id;
93
+ modelVersion: typeof TTL_FLASH_MODEL.version;
94
+ status: "resolved" | "clamped-at-minimum-power" | "clamped-at-full-power" | "no-flash-return";
95
+ /** Metered ambient signal in the main exposure: k·M(ambient). */
96
+ ambientMainExposureMeteredSignal: number;
97
+ /** Metered flash-only signal per unit full power: M(preflash − ambient)/p_pre. */
98
+ flashMeteredSignalPerFullPower: number;
99
+ /** T·2^FEC. */
100
+ targetRelativeSignal: number;
101
+ /** Unclamped solution (T' − k·A)/(F·syncEnergyFactor); null with no flash return. */
102
+ requiredPowerFraction: number | null;
103
+ /** Commanded main-flash power fraction (clamped); null with no flash return. */
104
+ powerFraction: number | null;
105
+ ambientAloneReachesTarget: boolean;
106
+ predictedMeteredSignal: number;
107
+ /** log2(predicted / target); 0 when the solution is within range; null when nothing is predicted. */
108
+ predictedExposureErrorStops: number | null;
109
+ effectiveGuideNumberMetersAtIso: number | null;
110
+ flashRangeAtApertureM: number | null;
111
+ preFlashInsideMainExposure: false;
112
+ ambientMeteringModified: false;
113
+ }
114
+ /**
115
+ * Solves the main-flash power from a pre-flash measurement (manufacturer-independent TTL).
116
+ *
117
+ * The meter is linear for the policies allowed here: M(a + b) = M(a) + M(b).
118
+ * - The pre-flash at power p_pre adds a flash-only signal f_i = pre_i − ambient_i in each zone.
119
+ * - Flash signal is proportional to emitted energy, so at main power p it adds (p/p_pre)·M(f).
120
+ * - With ambient scaled to the main exposure by k, the metered total is k·A + p·F, where
121
+ * F = M(f)/p_pre.
122
+ * - Setting this equal to the target T' = T·2^FEC gives p = (T' − k·A)/(F·s). Here s is the sync
123
+ * energy factor (1 for ordinary sync, η·t_e/D for high-speed sync).
124
+ * - p is clamped to [p_min, 1], the guide-number range.
125
+ * Highlight policies are rejected: their weights depend on the signal, so the total is no longer
126
+ * linear in p.
127
+ */
128
+ export declare function resolveTtlFlashExposure(input: ResolveTtlFlashExposureInput): CalculationResult<TtlFlashExposure>;
129
+ /**
130
+ * Returns a copy of a manual flash profile with its relative output scaled by a resolved TTL power
131
+ * fraction, ready for resolveManualFlashSync (front/rear curtain). For high-speed sync, instead pass
132
+ * the unscaled profile, and pass `ttl.powerFraction` as resolveHighSpeedFlashSync's powerFraction.
133
+ * That way power is applied only once.
134
+ */
135
+ export declare function createTtlScaledFlashProfile(flashProfile: ManualFlashProfile, ttl: TtlFlashExposure): ManualFlashProfile;
@@ -0,0 +1,193 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * Flash guide numbers, and through-the-lens (TTL) flash exposure with a pre-flash that does not
4
+ * depend on any manufacturer.
5
+ *
6
+ * How TTL works here:
7
+ * 1. The pre-flash is measured with the existing relative exposure meter.
8
+ * 2. The solved power fraction is applied to a ManualFlashProfile.
9
+ * 3. That pulse is placed by the existing front/rear-curtain sync (resolveManualFlashSync) or by
10
+ * high-speed sync (resolveHighSpeedFlashSync).
11
+ * Flash metering stays separate from ambient metering. The ambient meter result is an input and is
12
+ * not changed. No vendor's TTL algorithm, zone weighting table or flash protocol is copied.
13
+ * @see docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md#flash-guide-number-ttl-and-high-speed-sync
14
+ */
15
+ import { approximationResult } from "../core/calculation-result.js";
16
+ import { InvalidConfigurationError } from "../core/configuration-error.js";
17
+ import { InvalidScientificInputError } from "../core/validation.js";
18
+ import { rejectUnknownFields, requireInputKeys, requireInputObject } from "../core/record-validation.js";
19
+ import { parseManualFlashProfile } from "./flash.js";
20
+ import { meterRelativeExposure, parseExposureMeteringProfile } from "./metering.js";
21
+ export const TTL_FLASH_MODEL = Object.freeze({ id: "preflash-linear-ttl", version: "1.0.0" });
22
+ function requirePositive(value, name) {
23
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
24
+ throw new InvalidScientificInputError(name + " must be a finite number greater than zero.");
25
+ }
26
+ return value;
27
+ }
28
+ function requireFraction(value, name) {
29
+ const parsed = requirePositive(value, name);
30
+ if (parsed > 1)
31
+ throw new InvalidScientificInputError(name + " must lie in (0, 1].");
32
+ return parsed;
33
+ }
34
+ /**
35
+ * Effective guide number GN = GN_full · √p · √(ISO/100).
36
+ *
37
+ * The guide number relation GN = d·N follows from the inverse-square law. Light on the subject from a
38
+ * point-like flash falls as 1/d², and sensor exposure falls as 1/N². So exposure stays correct while
39
+ * d·N is constant (camera equation H = 0.65·L·t/N² and reference exposure H = 10/S, CIPA DC-004-2020,
40
+ * free). Exposure grows linearly with emitted energy (power fraction p), and the exposure needed falls
41
+ * inversely with ISO speed. So GN ∝ √p·√ISO. The engine does not model how a guide number is measured;
42
+ * the caller supplies it.
43
+ * @see docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md for the full derivation.
44
+ */
45
+ export function calculateFlashGuideNumber(input) {
46
+ requireInputKeys(input, "calculateFlashGuideNumber", ["fullPowerGuideNumberMetersIso100", "powerFraction", "iso"]);
47
+ return requirePositive(input.fullPowerGuideNumberMetersIso100, "fullPowerGuideNumberMetersIso100") *
48
+ Math.sqrt(requireFraction(input.powerFraction, "powerFraction")) *
49
+ Math.sqrt(requirePositive(input.iso, "iso") / 100);
50
+ }
51
+ /** Manual guide-number exposure: the power fraction that exposes a subject at distance d correctly. */
52
+ export function calculateFlashPowerForDistance(input) {
53
+ requireInputKeys(input, "calculateFlashPowerForDistance", ["fullPowerGuideNumberMetersIso100", "subjectDistanceM",
54
+ "apertureFNumber", "iso", "minimumPowerFraction"]);
55
+ const gnIso = calculateFlashGuideNumber({ fullPowerGuideNumberMetersIso100: input.fullPowerGuideNumberMetersIso100,
56
+ powerFraction: 1, iso: input.iso });
57
+ const distance = requirePositive(input.subjectDistanceM, "subjectDistanceM");
58
+ const aperture = requirePositive(input.apertureFNumber, "apertureFNumber");
59
+ const minimum = requireFraction(input.minimumPowerFraction, "minimumPowerFraction");
60
+ const required = (distance * aperture / gnIso) ** 2;
61
+ const power = Math.min(1, Math.max(minimum, required));
62
+ return { requiredPowerFraction: required, powerFraction: power,
63
+ status: required < minimum ? "clamped-at-minimum-power" : required > 1 ? "clamped-at-full-power" : "within-range",
64
+ flashExposureErrorStops: Math.log2(power / required), maximumDistanceM: gnIso / aperture };
65
+ }
66
+ const LINEAR_POLICIES = new Set(["multi-zone-uniform", "center-weighted-radial", "spot"]);
67
+ function sameZones(a, b) {
68
+ if (a.sceneStateId !== b.sceneStateId || a.samples.length !== b.samples.length ||
69
+ JSON.stringify(a.captureGeometry) !== JSON.stringify(b.captureGeometry)) {
70
+ throw new InvalidScientificInputError("Ambient and pre-flash measurements must share scene state, geometry and zones.");
71
+ }
72
+ a.samples.forEach((sample, index) => {
73
+ const other = b.samples[index];
74
+ requireInputObject(sample, "ambientSampleSet.samples[" + index + "]");
75
+ requireInputObject(other, "preFlashSampleSet.samples[" + index + "]");
76
+ requireInputObject(sample.positionOrientedCaptureUv, "ambientSampleSet.samples[" + index + "].positionOrientedCaptureUv");
77
+ requireInputObject(other.positionOrientedCaptureUv, "preFlashSampleSet.samples[" + index + "].positionOrientedCaptureUv");
78
+ if (sample.sampleId !== other.sampleId || sample.areaWeight !== other.areaWeight ||
79
+ sample.positionOrientedCaptureUv.u !== other.positionOrientedCaptureUv.u ||
80
+ sample.positionOrientedCaptureUv.v !== other.positionOrientedCaptureUv.v) {
81
+ throw new InvalidScientificInputError("Ambient and pre-flash zones must match exactly and in order.");
82
+ }
83
+ });
84
+ }
85
+ /**
86
+ * Solves the main-flash power from a pre-flash measurement (manufacturer-independent TTL).
87
+ *
88
+ * The meter is linear for the policies allowed here: M(a + b) = M(a) + M(b).
89
+ * - The pre-flash at power p_pre adds a flash-only signal f_i = pre_i − ambient_i in each zone.
90
+ * - Flash signal is proportional to emitted energy, so at main power p it adds (p/p_pre)·M(f).
91
+ * - With ambient scaled to the main exposure by k, the metered total is k·A + p·F, where
92
+ * F = M(f)/p_pre.
93
+ * - Setting this equal to the target T' = T·2^FEC gives p = (T' − k·A)/(F·s). Here s is the sync
94
+ * energy factor (1 for ordinary sync, η·t_e/D for high-speed sync).
95
+ * - p is clamped to [p_min, 1], the guide-number range.
96
+ * Highlight policies are rejected: their weights depend on the signal, so the total is no longer
97
+ * linear in p.
98
+ */
99
+ export function resolveTtlFlashExposure(input) {
100
+ requireInputKeys(input, "resolveTtlFlashExposure", ["meteringProfile", "ambientSampleSet", "preFlashSampleSet", "preFlashPowerFraction", "ambientScaleToMainExposure", "flashExposureCompensationStops", "minimumPowerFraction", "syncEnergyFactor", "guideNumber"]);
101
+ requireInputObject(input.ambientSampleSet, "resolveTtlFlashExposure ambientSampleSet");
102
+ requireInputObject(input.preFlashSampleSet, "resolveTtlFlashExposure preFlashSampleSet");
103
+ if (input.guideNumber !== undefined) {
104
+ requireInputObject(input.guideNumber, "resolveTtlFlashExposure guideNumber");
105
+ rejectUnknownFields(input.guideNumber, ["fullPowerGuideNumberMetersIso100", "iso", "apertureFNumber"], "resolveTtlFlashExposure guideNumber");
106
+ }
107
+ if (!Array.isArray(input.ambientSampleSet.samples) || !Array.isArray(input.preFlashSampleSet.samples)) {
108
+ throw new InvalidConfigurationError("TTL sample sets must contain sample arrays.");
109
+ }
110
+ const profile = parseExposureMeteringProfile(input.meteringProfile);
111
+ if (!LINEAR_POLICIES.has(profile.policy.kind)) {
112
+ throw new InvalidScientificInputError("TTL flash requires a spatially linear metering policy (multi-zone-uniform, center-weighted-radial or spot).");
113
+ }
114
+ sameZones(input.ambientSampleSet, input.preFlashSampleSet);
115
+ const preFlash = requireFraction(input.preFlashPowerFraction, "preFlashPowerFraction");
116
+ const minimum = requireFraction(input.minimumPowerFraction, "minimumPowerFraction");
117
+ const k = input.ambientScaleToMainExposure;
118
+ if (typeof k !== "number" || !Number.isFinite(k) || k < 0) {
119
+ throw new InvalidScientificInputError("ambientScaleToMainExposure must be a finite number greater than or equal to zero.");
120
+ }
121
+ const fec = input.flashExposureCompensationStops;
122
+ if (typeof fec !== "number" || !Number.isFinite(fec)) {
123
+ throw new InvalidScientificInputError("flashExposureCompensationStops must be finite.");
124
+ }
125
+ const syncFactor = input.syncEnergyFactor === undefined ? 1 : requireFraction(input.syncEnergyFactor, "syncEnergyFactor");
126
+ const flashOnly = { ...input.preFlashSampleSet,
127
+ measurementId: input.preFlashSampleSet.measurementId + ":flash-only",
128
+ samples: input.preFlashSampleSet.samples.map((sample, index) => {
129
+ const difference = sample.relativeLinearSignal - input.ambientSampleSet.samples[index].relativeLinearSignal;
130
+ if (!(difference >= 0)) {
131
+ throw new InvalidScientificInputError("Pre-flash signal must not be below the ambient signal in any zone.");
132
+ }
133
+ return { ...sample, relativeLinearSignal: difference };
134
+ }) };
135
+ const ambient = meterRelativeExposure({ profile, sampleSet: input.ambientSampleSet }).value.meteredRelativeSignal;
136
+ const flashPerFull = meterRelativeExposure({ profile, sampleSet: flashOnly }).value.meteredRelativeSignal / preFlash;
137
+ const ambientMain = k * ambient;
138
+ const target = profile.target.targetRelativeSignal * Math.pow(2, fec);
139
+ const deliveredPerFull = flashPerFull * syncFactor;
140
+ let status, required, power;
141
+ if (deliveredPerFull === 0) {
142
+ status = "no-flash-return";
143
+ required = null;
144
+ power = null;
145
+ }
146
+ else {
147
+ required = (target - ambientMain) / deliveredPerFull;
148
+ power = Math.min(1, Math.max(minimum, required));
149
+ status = required < minimum ? "clamped-at-minimum-power" : required > 1 ? "clamped-at-full-power" : "resolved";
150
+ }
151
+ const predicted = ambientMain + (power ?? 0) * deliveredPerFull;
152
+ const gn = input.guideNumber;
153
+ const effectiveGn = gn === undefined || power === null ? null : calculateFlashGuideNumber({
154
+ fullPowerGuideNumberMetersIso100: gn.fullPowerGuideNumberMetersIso100, powerFraction: power, iso: gn.iso
155
+ }) * Math.sqrt(syncFactor);
156
+ return approximationResult({
157
+ modelId: TTL_FLASH_MODEL.id,
158
+ modelVersion: TTL_FLASH_MODEL.version,
159
+ status,
160
+ ambientMainExposureMeteredSignal: ambientMain,
161
+ flashMeteredSignalPerFullPower: flashPerFull,
162
+ targetRelativeSignal: target,
163
+ requiredPowerFraction: required,
164
+ powerFraction: power,
165
+ ambientAloneReachesTarget: ambientMain >= target,
166
+ predictedMeteredSignal: predicted,
167
+ predictedExposureErrorStops: predicted > 0 ? Math.log2(predicted / target) : null,
168
+ effectiveGuideNumberMetersAtIso: effectiveGn,
169
+ flashRangeAtApertureM: effectiveGn === null || gn === undefined ? null : effectiveGn / requirePositive(gn.apertureFNumber, "apertureFNumber"),
170
+ preFlashInsideMainExposure: false,
171
+ ambientMeteringModified: false
172
+ }, TTL_FLASH_MODEL.id, TTL_FLASH_MODEL.version, [
173
+ "Relative pre-exposure meter signals only; no calibrated flash energy, subject reflectance or distance is inferred.",
174
+ "Flash signal is assumed proportional to emitted energy and fully inside the main exposure (pulse) or each line's slit (HSS factor).",
175
+ "The pre-flash precedes the main exposure; subject motion and ambient change between pre-flash and exposure are not modeled.",
176
+ "This is a generic linear pre-flash solution, not any manufacturer's TTL algorithm, zone weighting or flash protocol."
177
+ ]);
178
+ }
179
+ /**
180
+ * Returns a copy of a manual flash profile with its relative output scaled by a resolved TTL power
181
+ * fraction, ready for resolveManualFlashSync (front/rear curtain). For high-speed sync, instead pass
182
+ * the unscaled profile, and pass `ttl.powerFraction` as resolveHighSpeedFlashSync's powerFraction.
183
+ * That way power is applied only once.
184
+ */
185
+ export function createTtlScaledFlashProfile(flashProfile, ttl) {
186
+ const flash = parseManualFlashProfile(flashProfile);
187
+ requireInputObject(ttl, "createTtlScaledFlashProfile ttl");
188
+ if (ttl.powerFraction === null || typeof ttl.powerFraction !== "number") {
189
+ throw new InvalidScientificInputError("TTL found no flash return; there is no power fraction to apply.");
190
+ }
191
+ return { ...flash, outputControl: { ...flash.outputControl, scale: flash.outputControl.scale * ttl.powerFraction } };
192
+ }
193
+ //# sourceMappingURL=flash-ttl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flash-ttl.js","sourceRoot":"","sources":["../../src/exposure/flash-ttl.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Flash guide numbers, and through-the-lens (TTL) flash exposure with a pre-flash that does not\n * depend on any manufacturer.\n *\n * How TTL works here:\n * 1. The pre-flash is measured with the existing relative exposure meter.\n * 2. The solved power fraction is applied to a ManualFlashProfile.\n * 3. That pulse is placed by the existing front/rear-curtain sync (resolveManualFlashSync) or by\n * high-speed sync (resolveHighSpeedFlashSync).\n * Flash metering stays separate from ambient metering. The ambient meter result is an input and is\n * not changed. No vendor's TTL algorithm, zone weighting table or flash protocol is copied.\n * @see docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md#flash-guide-number-ttl-and-high-speed-sync\n */\n\nimport { approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport { rejectUnknownFields, requireInputKeys, requireInputObject } from \"../core/record-validation.js\";\nimport { parseManualFlashProfile, type ManualFlashProfile } from \"./flash.js\";\nimport {\n meterRelativeExposure,\n parseExposureMeteringProfile,\n type ExposureMeteringProfile,\n type ExposureMeteringSampleSet\n} from \"./metering.js\";\n\nexport const TTL_FLASH_MODEL = Object.freeze({ id: \"preflash-linear-ttl\", version: \"1.0.0\" } as const);\n\nfunction requirePositive(value: unknown, name: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n throw new InvalidScientificInputError(name + \" must be a finite number greater than zero.\");\n }\n return value;\n}\n\nfunction requireFraction(value: unknown, name: string): number {\n const parsed = requirePositive(value, name);\n if (parsed > 1) throw new InvalidScientificInputError(name + \" must lie in (0, 1].\");\n return parsed;\n}\n\nexport interface FlashGuideNumberInput {\n /** Guide number at full power for ISO 100, in metres (GN = distance · f-number). */\n fullPowerGuideNumberMetersIso100: number;\n /** Output as a fraction of full power, (0, 1]. */\n powerFraction: number;\n iso: number;\n}\n\n/**\n * Effective guide number GN = GN_full · √p · √(ISO/100).\n *\n * The guide number relation GN = d·N follows from the inverse-square law. Light on the subject from a\n * point-like flash falls as 1/d², and sensor exposure falls as 1/N². So exposure stays correct while\n * d·N is constant (camera equation H = 0.65·L·t/N² and reference exposure H = 10/S, CIPA DC-004-2020,\n * free). Exposure grows linearly with emitted energy (power fraction p), and the exposure needed falls\n * inversely with ISO speed. So GN ∝ √p·√ISO. The engine does not model how a guide number is measured;\n * the caller supplies it.\n * @see docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md for the full derivation.\n */\nexport function calculateFlashGuideNumber(input: FlashGuideNumberInput): number {\n requireInputKeys(input, \"calculateFlashGuideNumber\", [\"fullPowerGuideNumberMetersIso100\", \"powerFraction\", \"iso\"]);\n return requirePositive(input.fullPowerGuideNumberMetersIso100, \"fullPowerGuideNumberMetersIso100\") *\n Math.sqrt(requireFraction(input.powerFraction, \"powerFraction\")) *\n Math.sqrt(requirePositive(input.iso, \"iso\") / 100);\n}\n\nexport interface FlashPowerForDistanceInput {\n fullPowerGuideNumberMetersIso100: number;\n subjectDistanceM: number;\n apertureFNumber: number;\n iso: number;\n /** Lowest available power fraction, (0, 1]. */\n minimumPowerFraction: number;\n}\n\nexport interface FlashPowerForDistance {\n /** p = (d·N / (GN_full·√(ISO/100)))², before clamping. */\n requiredPowerFraction: number;\n powerFraction: number;\n status: \"within-range\" | \"clamped-at-minimum-power\" | \"clamped-at-full-power\";\n /** log2(delivered / required) flash exposure; positive is overexposure. */\n flashExposureErrorStops: number;\n /** GN_full·√(ISO/100)/N: the farthest correctly exposed distance at full power. */\n maximumDistanceM: number;\n}\n\n/** Manual guide-number exposure: the power fraction that exposes a subject at distance d correctly. */\nexport function calculateFlashPowerForDistance(input: FlashPowerForDistanceInput): FlashPowerForDistance {\n requireInputKeys(input, \"calculateFlashPowerForDistance\", [\"fullPowerGuideNumberMetersIso100\", \"subjectDistanceM\",\n \"apertureFNumber\", \"iso\", \"minimumPowerFraction\"]);\n const gnIso = calculateFlashGuideNumber({ fullPowerGuideNumberMetersIso100: input.fullPowerGuideNumberMetersIso100,\n powerFraction: 1, iso: input.iso });\n const distance = requirePositive(input.subjectDistanceM, \"subjectDistanceM\");\n const aperture = requirePositive(input.apertureFNumber, \"apertureFNumber\");\n const minimum = requireFraction(input.minimumPowerFraction, \"minimumPowerFraction\");\n const required = (distance * aperture / gnIso) ** 2;\n const power = Math.min(1, Math.max(minimum, required));\n return { requiredPowerFraction: required, powerFraction: power,\n status: required < minimum ? \"clamped-at-minimum-power\" : required > 1 ? \"clamped-at-full-power\" : \"within-range\",\n flashExposureErrorStops: Math.log2(power / required), maximumDistanceM: gnIso / aperture };\n}\n\nexport interface ResolveTtlFlashExposureInput {\n /** Spatially linear metering profile (multi-zone-uniform, center-weighted-radial or spot). */\n meteringProfile: ExposureMeteringProfile;\n /** Measurement-window samples with the flash off. */\n ambientSampleSet: ExposureMeteringSampleSet;\n /** The same zones and settings with the pre-flash fired. */\n preFlashSampleSet: ExposureMeteringSampleSet;\n /** Pre-flash output as a fraction of full power, (0, 1]. */\n preFlashPowerFraction: number;\n /**\n * Ratio of ambient light collected in the main exposure to that in the measurement window, at the\n * same aperture and ISO (for example t_main/t_measure). Must be ≥ 0. The flash pulse falls inside\n * both windows, so it is not scaled.\n */\n ambientScaleToMainExposure: number;\n /** Flash exposure compensation applied to the TTL target, in stops. */\n flashExposureCompensationStops: number;\n /** Lowest available main-flash power fraction, (0, 1]. */\n minimumPowerFraction: number;\n /**\n * Flash energy each line receives, relative to an ordinary pulse at the same power fraction. 1 for\n * front/rear-curtain sync; η·t_e/D for high-speed sync (see resolveHighSpeedFlashSync). Defaults to 1.\n */\n syncEnergyFactor?: number;\n /** Optional guide-number reporting. */\n guideNumber?: { fullPowerGuideNumberMetersIso100: number; iso: number; apertureFNumber: number };\n}\n\nexport interface TtlFlashExposure {\n modelId: typeof TTL_FLASH_MODEL.id;\n modelVersion: typeof TTL_FLASH_MODEL.version;\n status: \"resolved\" | \"clamped-at-minimum-power\" | \"clamped-at-full-power\" | \"no-flash-return\";\n /** Metered ambient signal in the main exposure: k·M(ambient). */\n ambientMainExposureMeteredSignal: number;\n /** Metered flash-only signal per unit full power: M(preflash − ambient)/p_pre. */\n flashMeteredSignalPerFullPower: number;\n /** T·2^FEC. */\n targetRelativeSignal: number;\n /** Unclamped solution (T' − k·A)/(F·syncEnergyFactor); null with no flash return. */\n requiredPowerFraction: number | null;\n /** Commanded main-flash power fraction (clamped); null with no flash return. */\n powerFraction: number | null;\n ambientAloneReachesTarget: boolean;\n predictedMeteredSignal: number;\n /** log2(predicted / target); 0 when the solution is within range; null when nothing is predicted. */\n predictedExposureErrorStops: number | null;\n effectiveGuideNumberMetersAtIso: number | null;\n flashRangeAtApertureM: number | null;\n preFlashInsideMainExposure: false;\n ambientMeteringModified: false;\n}\n\nconst LINEAR_POLICIES = new Set([\"multi-zone-uniform\", \"center-weighted-radial\", \"spot\"]);\n\nfunction sameZones(a: ExposureMeteringSampleSet, b: ExposureMeteringSampleSet): void {\n if (a.sceneStateId !== b.sceneStateId || a.samples.length !== b.samples.length ||\n JSON.stringify(a.captureGeometry) !== JSON.stringify(b.captureGeometry)) {\n throw new InvalidScientificInputError(\"Ambient and pre-flash measurements must share scene state, geometry and zones.\");\n }\n a.samples.forEach((sample, index) => {\n const other = b.samples[index]!;\n requireInputObject(sample, \"ambientSampleSet.samples[\" + index + \"]\");\n requireInputObject(other, \"preFlashSampleSet.samples[\" + index + \"]\");\n requireInputObject(sample.positionOrientedCaptureUv, \"ambientSampleSet.samples[\" + index + \"].positionOrientedCaptureUv\");\n requireInputObject(other.positionOrientedCaptureUv, \"preFlashSampleSet.samples[\" + index + \"].positionOrientedCaptureUv\");\n if (sample.sampleId !== other.sampleId || sample.areaWeight !== other.areaWeight ||\n sample.positionOrientedCaptureUv.u !== other.positionOrientedCaptureUv.u ||\n sample.positionOrientedCaptureUv.v !== other.positionOrientedCaptureUv.v) {\n throw new InvalidScientificInputError(\"Ambient and pre-flash zones must match exactly and in order.\");\n }\n });\n}\n\n/**\n * Solves the main-flash power from a pre-flash measurement (manufacturer-independent TTL).\n *\n * The meter is linear for the policies allowed here: M(a + b) = M(a) + M(b).\n * - The pre-flash at power p_pre adds a flash-only signal f_i = pre_i − ambient_i in each zone.\n * - Flash signal is proportional to emitted energy, so at main power p it adds (p/p_pre)·M(f).\n * - With ambient scaled to the main exposure by k, the metered total is k·A + p·F, where\n * F = M(f)/p_pre.\n * - Setting this equal to the target T' = T·2^FEC gives p = (T' − k·A)/(F·s). Here s is the sync\n * energy factor (1 for ordinary sync, η·t_e/D for high-speed sync).\n * - p is clamped to [p_min, 1], the guide-number range.\n * Highlight policies are rejected: their weights depend on the signal, so the total is no longer\n * linear in p.\n */\nexport function resolveTtlFlashExposure(input: ResolveTtlFlashExposureInput): CalculationResult<TtlFlashExposure> {\n requireInputKeys(input, \"resolveTtlFlashExposure\", [\"meteringProfile\", \"ambientSampleSet\", \"preFlashSampleSet\", \"preFlashPowerFraction\", \"ambientScaleToMainExposure\", \"flashExposureCompensationStops\", \"minimumPowerFraction\", \"syncEnergyFactor\", \"guideNumber\"]);\n requireInputObject(input.ambientSampleSet, \"resolveTtlFlashExposure ambientSampleSet\");\n requireInputObject(input.preFlashSampleSet, \"resolveTtlFlashExposure preFlashSampleSet\");\n if (input.guideNumber !== undefined) {\n requireInputObject(input.guideNumber, \"resolveTtlFlashExposure guideNumber\");\n rejectUnknownFields(input.guideNumber, [\"fullPowerGuideNumberMetersIso100\", \"iso\", \"apertureFNumber\"], \"resolveTtlFlashExposure guideNumber\");\n }\n if (!Array.isArray(input.ambientSampleSet.samples) || !Array.isArray(input.preFlashSampleSet.samples)) {\n throw new InvalidConfigurationError(\"TTL sample sets must contain sample arrays.\");\n }\n const profile = parseExposureMeteringProfile(input.meteringProfile);\n if (!LINEAR_POLICIES.has(profile.policy.kind)) {\n throw new InvalidScientificInputError(\n \"TTL flash requires a spatially linear metering policy (multi-zone-uniform, center-weighted-radial or spot).\"\n );\n }\n sameZones(input.ambientSampleSet, input.preFlashSampleSet);\n const preFlash = requireFraction(input.preFlashPowerFraction, \"preFlashPowerFraction\");\n const minimum = requireFraction(input.minimumPowerFraction, \"minimumPowerFraction\");\n const k = input.ambientScaleToMainExposure;\n if (typeof k !== \"number\" || !Number.isFinite(k) || k < 0) {\n throw new InvalidScientificInputError(\"ambientScaleToMainExposure must be a finite number greater than or equal to zero.\");\n }\n const fec = input.flashExposureCompensationStops;\n if (typeof fec !== \"number\" || !Number.isFinite(fec)) {\n throw new InvalidScientificInputError(\"flashExposureCompensationStops must be finite.\");\n }\n const syncFactor = input.syncEnergyFactor === undefined ? 1 : requireFraction(input.syncEnergyFactor, \"syncEnergyFactor\");\n const flashOnly: ExposureMeteringSampleSet = { ...input.preFlashSampleSet,\n measurementId: input.preFlashSampleSet.measurementId + \":flash-only\",\n samples: input.preFlashSampleSet.samples.map((sample, index) => {\n const difference = sample.relativeLinearSignal - input.ambientSampleSet.samples[index]!.relativeLinearSignal;\n if (!(difference >= 0)) {\n throw new InvalidScientificInputError(\"Pre-flash signal must not be below the ambient signal in any zone.\");\n }\n return { ...sample, relativeLinearSignal: difference };\n }) };\n const ambient = meterRelativeExposure({ profile, sampleSet: input.ambientSampleSet }).value.meteredRelativeSignal;\n const flashPerFull = meterRelativeExposure({ profile, sampleSet: flashOnly }).value.meteredRelativeSignal / preFlash;\n const ambientMain = k * ambient;\n const target = profile.target.targetRelativeSignal * Math.pow(2, fec);\n const deliveredPerFull = flashPerFull * syncFactor;\n let status: TtlFlashExposure[\"status\"], required: number | null, power: number | null;\n if (deliveredPerFull === 0) {\n status = \"no-flash-return\"; required = null; power = null;\n } else {\n required = (target - ambientMain) / deliveredPerFull;\n power = Math.min(1, Math.max(minimum, required));\n status = required < minimum ? \"clamped-at-minimum-power\" : required > 1 ? \"clamped-at-full-power\" : \"resolved\";\n }\n const predicted = ambientMain + (power ?? 0) * deliveredPerFull;\n const gn = input.guideNumber;\n const effectiveGn = gn === undefined || power === null ? null : calculateFlashGuideNumber({\n fullPowerGuideNumberMetersIso100: gn.fullPowerGuideNumberMetersIso100, powerFraction: power, iso: gn.iso }) * Math.sqrt(syncFactor);\n return approximationResult({\n modelId: TTL_FLASH_MODEL.id,\n modelVersion: TTL_FLASH_MODEL.version,\n status,\n ambientMainExposureMeteredSignal: ambientMain,\n flashMeteredSignalPerFullPower: flashPerFull,\n targetRelativeSignal: target,\n requiredPowerFraction: required,\n powerFraction: power,\n ambientAloneReachesTarget: ambientMain >= target,\n predictedMeteredSignal: predicted,\n predictedExposureErrorStops: predicted > 0 ? Math.log2(predicted / target) : null,\n effectiveGuideNumberMetersAtIso: effectiveGn,\n flashRangeAtApertureM: effectiveGn === null || gn === undefined ? null : effectiveGn / requirePositive(gn.apertureFNumber, \"apertureFNumber\"),\n preFlashInsideMainExposure: false,\n ambientMeteringModified: false\n }, TTL_FLASH_MODEL.id, TTL_FLASH_MODEL.version, [\n \"Relative pre-exposure meter signals only; no calibrated flash energy, subject reflectance or distance is inferred.\",\n \"Flash signal is assumed proportional to emitted energy and fully inside the main exposure (pulse) or each line's slit (HSS factor).\",\n \"The pre-flash precedes the main exposure; subject motion and ambient change between pre-flash and exposure are not modeled.\",\n \"This is a generic linear pre-flash solution, not any manufacturer's TTL algorithm, zone weighting or flash protocol.\"\n ]);\n}\n\n/**\n * Returns a copy of a manual flash profile with its relative output scaled by a resolved TTL power\n * fraction, ready for resolveManualFlashSync (front/rear curtain). For high-speed sync, instead pass\n * the unscaled profile, and pass `ttl.powerFraction` as resolveHighSpeedFlashSync's powerFraction.\n * That way power is applied only once.\n */\nexport function createTtlScaledFlashProfile(flashProfile: ManualFlashProfile, ttl: TtlFlashExposure): ManualFlashProfile {\n const flash = parseManualFlashProfile(flashProfile);\n requireInputObject(ttl, \"createTtlScaledFlashProfile ttl\");\n if (ttl.powerFraction === null || typeof ttl.powerFraction !== \"number\") {\n throw new InvalidScientificInputError(\"TTL found no flash return; there is no power fraction to apply.\");\n }\n return { ...flash, outputControl: { ...flash.outputControl, scale: flash.outputControl.scale * ttl.powerFraction } };\n}\n"]}