@photivra/engine 2.20.0 → 2.21.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 (174) hide show
  1. package/CHANGELOG.md +178 -1
  2. package/CITATION.cff +1 -1
  3. package/README.md +7 -6
  4. package/SECURITY.md +1 -1
  5. package/THIRD_PARTY.md +7 -0
  6. package/dist/capture/dng-lens-correction-opcodes.d.ts +2 -2
  7. package/dist/capture/dng-lens-correction-opcodes.js +2 -2
  8. package/dist/capture/dng-lens-correction-opcodes.js.map +1 -1
  9. package/dist/capture/exposure-build-up-stage.d.ts +16 -0
  10. package/dist/capture/exposure-build-up-stage.js +4 -0
  11. package/dist/capture/exposure-build-up-stage.js.map +1 -0
  12. package/dist/capture/native-environment-lean.d.ts +2 -1
  13. package/dist/capture/native-environment-lean.js +41 -73
  14. package/dist/capture/native-environment-lean.js.map +1 -1
  15. package/dist/capture/native-environment-tabulated.js +4 -3
  16. package/dist/capture/native-environment-tabulated.js.map +1 -1
  17. package/dist/capture/native-raw.d.ts +3 -2
  18. package/dist/capture/native-raw.js +5 -4
  19. package/dist/capture/native-raw.js.map +1 -1
  20. package/dist/capture/sensor-raw-producer.d.ts +4 -1
  21. package/dist/capture/sensor-raw-producer.js +12 -3
  22. package/dist/capture/sensor-raw-producer.js.map +1 -1
  23. package/dist/core/version.d.ts +1 -1
  24. package/dist/core/version.js +1 -1
  25. package/dist/core/version.js.map +1 -1
  26. package/dist/equipment/generic-lens-catalogue.d.ts +3 -2
  27. package/dist/equipment/generic-lens-catalogue.js +18 -5
  28. package/dist/equipment/generic-lens-catalogue.js.map +1 -1
  29. package/dist/equipment/generic-tier-assets.d.ts +32 -0
  30. package/dist/equipment/generic-tier-assets.js +16 -11
  31. package/dist/equipment/generic-tier-assets.js.map +1 -1
  32. package/dist/equipment/sensor-profile-body.d.ts +78 -0
  33. package/dist/equipment/sensor-profile-body.js +77 -0
  34. package/dist/equipment/sensor-profile-body.js.map +1 -0
  35. package/dist/equipment/sensor-profiles.d.ts +8 -0
  36. package/dist/equipment/sensor-profiles.js +82 -0
  37. package/dist/equipment/sensor-profiles.js.map +1 -0
  38. package/dist/facade/catalogue-lens-signal.d.ts +2 -2
  39. package/dist/facade/catalogue-lens-signal.js +58 -71
  40. package/dist/facade/catalogue-lens-signal.js.map +1 -1
  41. package/dist/facade/chart-radiance-batch.js +2 -1
  42. package/dist/facade/chart-radiance-batch.js.map +1 -1
  43. package/dist/facade/defocus-image-space-provider.d.ts +7 -0
  44. package/dist/facade/defocus-image-space-provider.js +64 -76
  45. package/dist/facade/defocus-image-space-provider.js.map +1 -1
  46. package/dist/facade/display-view-gpu-session.js +2 -0
  47. package/dist/facade/display-view-gpu-session.js.map +1 -1
  48. package/dist/facade/display-view-gpu.d.ts +6 -1
  49. package/dist/facade/display-view-gpu.js.map +1 -1
  50. package/dist/facade/display-view-lens-signal.js +25 -23
  51. package/dist/facade/display-view-lens-signal.js.map +1 -1
  52. package/dist/facade/display-view.js +5 -23
  53. package/dist/facade/display-view.js.map +1 -1
  54. package/dist/facade/expected-signal-setup.d.ts +3 -1
  55. package/dist/facade/expected-signal-setup.js +1 -1
  56. package/dist/facade/expected-signal-setup.js.map +1 -1
  57. package/dist/facade/expected-signal.d.ts +47 -14
  58. package/dist/facade/expected-signal.js +117 -112
  59. package/dist/facade/expected-signal.js.map +1 -1
  60. package/dist/facade/exposure-build-up.d.ts +70 -0
  61. package/dist/facade/exposure-build-up.js +164 -0
  62. package/dist/facade/exposure-build-up.js.map +1 -0
  63. package/dist/facade/fast-methods.js +9 -1
  64. package/dist/facade/fast-methods.js.map +1 -1
  65. package/dist/facade/generic-lens-capture.d.ts +2 -2
  66. package/dist/facade/generic-lens-capture.js +2 -2
  67. package/dist/facade/generic-lens-capture.js.map +1 -1
  68. package/dist/facade/image-plane-enable.d.ts +7 -0
  69. package/dist/facade/image-plane-enable.js +17 -0
  70. package/dist/facade/image-plane-enable.js.map +1 -0
  71. package/dist/facade/image-plane-lattice-data.d.ts +6 -0
  72. package/dist/facade/image-plane-lattice-data.js +10 -0
  73. package/dist/facade/image-plane-lattice-data.js.map +1 -0
  74. package/dist/facade/image-plane-support.d.ts +33 -0
  75. package/dist/facade/image-plane-support.js +11 -0
  76. package/dist/facade/image-plane-support.js.map +1 -0
  77. package/dist/facade/image-plane.d.ts +36 -0
  78. package/dist/facade/image-plane.js +353 -0
  79. package/dist/facade/image-plane.js.map +1 -0
  80. package/dist/facade/mixed-illumination.d.ts +108 -0
  81. package/dist/facade/mixed-illumination.js +174 -0
  82. package/dist/facade/mixed-illumination.js.map +1 -0
  83. package/dist/facade/representative-light-sources.d.ts +72 -0
  84. package/dist/facade/representative-light-sources.js +124 -0
  85. package/dist/facade/representative-light-sources.js.map +1 -0
  86. package/dist/facade/scene-radiance.d.ts +129 -4
  87. package/dist/facade/scene-radiance.js +48 -13
  88. package/dist/facade/scene-radiance.js.map +1 -1
  89. package/dist/facade/simulate-capture.d.ts +39 -10
  90. package/dist/facade/simulate-capture.js +252 -92
  91. package/dist/facade/simulate-capture.js.map +1 -1
  92. package/dist/facade/simulate-display-view.js +14 -6
  93. package/dist/facade/simulate-display-view.js.map +1 -1
  94. package/dist/gpu/chart-composite-gpu.d.ts +13 -1
  95. package/dist/gpu/chart-composite-gpu.js +48 -9
  96. package/dist/gpu/chart-composite-gpu.js.map +1 -1
  97. package/dist/gpu/chart-radiance-gpu.js +4 -30
  98. package/dist/gpu/chart-radiance-gpu.js.map +1 -1
  99. package/dist/gpu/display-view-composite-material-module.d.ts +10 -4
  100. package/dist/gpu/display-view-composite-material-module.js +39 -13
  101. package/dist/gpu/display-view-composite-material-module.js.map +1 -1
  102. package/dist/gpu/display-view-image-material-module.d.ts +86 -0
  103. package/dist/gpu/display-view-image-material-module.js +339 -0
  104. package/dist/gpu/display-view-image-material-module.js.map +1 -0
  105. package/dist/gpu/display-view-image-quality.d.ts +45 -0
  106. package/dist/gpu/display-view-image-quality.js +380 -0
  107. package/dist/gpu/display-view-image-quality.js.map +1 -0
  108. package/dist/gpu/display-view-quality-gpu.d.ts +67 -1
  109. package/dist/gpu/display-view-quality-gpu.js +136 -205
  110. package/dist/gpu/display-view-quality-gpu.js.map +1 -1
  111. package/dist/gpu/display-view-speed-gpu.d.ts +51 -3
  112. package/dist/gpu/display-view-speed-gpu.js +131 -93
  113. package/dist/gpu/display-view-speed-gpu.js.map +1 -1
  114. package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +29 -15
  115. package/dist/gpu/wgsl-display-view-quality-kernel.js +58 -36
  116. package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
  117. package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +21 -6
  118. package/dist/gpu/wgsl-display-view-speed-kernel.js +46 -11
  119. package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
  120. package/dist/gpu/wgsl-exact-sum.d.ts +20 -0
  121. package/dist/gpu/wgsl-exact-sum.js +42 -0
  122. package/dist/gpu/wgsl-exact-sum.js.map +1 -0
  123. package/dist/index.d.ts +11 -3
  124. package/dist/index.js +7 -1
  125. package/dist/index.js.map +1 -1
  126. package/dist/motion/subject-motion.d.ts +66 -0
  127. package/dist/motion/subject-motion.js +52 -0
  128. package/dist/motion/subject-motion.js.map +1 -0
  129. package/dist/optics/generic-lens-lateral-color.d.ts +83 -0
  130. package/dist/optics/generic-lens-lateral-color.js +77 -0
  131. package/dist/optics/generic-lens-lateral-color.js.map +1 -0
  132. package/dist/optics/generic-lens-psf.js +54 -46
  133. package/dist/optics/generic-lens-psf.js.map +1 -1
  134. package/dist/optics/lens-psf-profile.d.ts +7 -0
  135. package/dist/optics/lens-psf-profile.js +2 -1
  136. package/dist/optics/lens-psf-profile.js.map +1 -1
  137. package/dist/output/developed-lens-corrections.d.ts +19 -5
  138. package/dist/output/developed-lens-corrections.js +28 -9
  139. package/dist/output/developed-lens-corrections.js.map +1 -1
  140. package/dist/output/generic-lens-corrections.d.ts +41 -5
  141. package/dist/output/generic-lens-corrections.js +52 -8
  142. package/dist/output/generic-lens-corrections.js.map +1 -1
  143. package/dist/output/print-plan.d.ts +41 -5
  144. package/dist/output/print-plan.js +59 -14
  145. package/dist/output/print-plan.js.map +1 -1
  146. package/dist/sensor/binomial-sample.d.ts +3 -0
  147. package/dist/sensor/binomial-sample.js +86 -0
  148. package/dist/sensor/binomial-sample.js.map +1 -0
  149. package/dist/sensor/sensor-characteristics.d.ts +10 -0
  150. package/dist/sensor/sensor-characteristics.js +20 -9
  151. package/dist/sensor/sensor-characteristics.js.map +1 -1
  152. package/docs/AGENT_GUIDE.md +1 -0
  153. package/docs/API_REFERENCE.md +98 -1
  154. package/docs/QUICK_START.md +125 -0
  155. package/docs/USAGE.md +92 -1
  156. package/docs/api/core-version.md +1 -1
  157. package/docs/api/equipment-generic-lens-catalogue.md +10 -5
  158. package/docs/api/equipment-sensor-profile-body.md +64 -0
  159. package/docs/api/equipment-sensor-profiles.md +86 -0
  160. package/docs/api/exports.json +207 -2
  161. package/docs/api/facade-exposure-build-up.md +105 -0
  162. package/docs/api/facade-fast-methods.md +9 -1
  163. package/docs/api/facade-image-plane-enable.md +16 -0
  164. package/docs/api/facade-mixed-illumination.md +67 -0
  165. package/docs/api/facade-representative-light-sources.md +131 -0
  166. package/docs/api/facade-scene-radiance.md +54 -3
  167. package/docs/api/facade-simulate-capture.md +26 -6
  168. package/docs/api/motion-subject-motion.md +23 -0
  169. package/docs/api/optics-generic-lens-lateral-color.md +79 -0
  170. package/docs/api/output-developed-lens-corrections.md +10 -1
  171. package/docs/api/output-generic-lens-corrections.md +40 -4
  172. package/docs/api/output-print-plan.md +35 -1
  173. package/llms.txt +2 -0
  174. package/package.json +1 -1
@@ -0,0 +1,86 @@
1
+ # equipment/sensor-profiles.ts public contracts
2
+
3
+ The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
4
+
5
+ ## resolveSensorProfile
6
+
7
+ The profile record with this id (for `sensor.profile`); a clear error listing the ids otherwise.
8
+
9
+ ```ts
10
+ export function resolveSensorProfile(id: unknown): SensorProfile;
11
+ ```
12
+
13
+ This call is synchronous; any supplied provider must follow its explicit synchronous contract.
14
+
15
+ ## SENSOR_PROFILE_IDS
16
+
17
+ The profile ids, in catalogue order.
18
+
19
+ ```ts
20
+ SENSOR_PROFILE_IDS: readonly string[] = Object.freeze(SENSOR_PROFILES.map((p) => p.id))
21
+ ```
22
+
23
+ ## SENSOR_PROFILES
24
+
25
+ The catalogue, in the issue's order. Frozen.
26
+
27
+ ```ts
28
+ SENSOR_PROFILES: readonly SensorProfile[] = Object.freeze(([
29
+ { id: "full-frame-24mp-bsi-2020s", name: "Full frame 24 MP BSI, 2020s", marketTag: "consumer", architecture: "back-illuminated",
30
+ sensorWidthMm: 36.07, sensorHeightMm: 24.01, pixelsWide: 6072, pixelsHigh: 4042, pixelPitchMicrometers: 5.94, peakQuantumEfficiency: .8,
31
+ fullWellElectrons: 100000, readNoise: { lowGainElectrons: 6.4, highGainElectrons: 1.1, highGainFromIso: 500 }, highGainFullWellElectrons: 20000,
32
+ adcBitDepth: 14, baseIso: 100, maximumIso: 51200, maximumAnalogGain: 64, readoutSeconds: .05, fixedPattern: BSI,
33
+ goodFor: ["landscape", "portrait", "travel"], description: "Large pixels and a deep full well for wide dynamic range at base ISO; a moderate readout shows some rolling-shutter skew.",
34
+ fixedLenses: null, provenance: { ...sourced("S1", "pixels", "pixelPitchMicrometers", "peakQuantumEfficiency", "fullWellElectrons", "readNoise", "adcBitDepth"),
35
+ sensorSize: "derived", architecture: "published S1", highGainFromIso: "derived S1", highGainFullWellElectrons: "derived", baseIso: "derived" } },
36
+ { id: "full-frame-45mp-stacked-2020s", name: "Full frame 45 MP stacked, 2020s", marketTag: "professional", architecture: "stacked",
37
+ sensorWidthMm: 36, sensorHeightMm: 24, pixelsWide: 8256, pixelsHigh: 5504, pixelPitchMicrometers: 4.36, peakQuantumEfficiency: .8,
38
+ fullWellElectrons: 69000, readNoise: { lowGainElectrons: 3.5, highGainElectrons: 1.5, highGainFromIso: 250 }, highGainFullWellElectrons: 22080,
39
+ adcBitDepth: 14, baseIso: 80, maximumIso: 25600, maximumAnalogGain: 64, readoutSeconds: .005, fixedPattern: BSI,
40
+ goodFor: ["landscape", "studio", "wildlife"], description: "High resolution with a fast stacked readout: fine detail for landscape and studio work, little rolling-shutter skew for action.",
41
+ fixedLenses: null, provenance: { pixelPitchMicrometers: "derived", fullWellElectrons: "design (S2 scaled by pixel area)", readNoise: "design (S2)", highGainFromIso: "design (S2)",
42
+ highGainFullWellElectrons: "derived", baseIso: "derived" } },
43
+ { id: "full-frame-24mp-stacked-sports-2020s", name: "Full frame 24 MP stacked (sports), 2020s", marketTag: "professional", architecture: "stacked",
44
+ sensorWidthMm: 36, sensorHeightMm: 24, pixelsWide: 6000, pixelsHigh: 4000, pixelPitchMicrometers: 6, peakQuantumEfficiency: .8,
45
+ fullWellElectrons: 80000, readNoise: { lowGainElectrons: 3, highGainElectrons: 1, highGainFromIso: 400 }, highGainFullWellElectrons: 25000,
46
+ adcBitDepth: 14, baseIso: 125, maximumIso: 102400, maximumAnalogGain: 64, readoutSeconds: .0025, fixedPattern: BSI,
47
+ goodFor: ["sports", "wildlife", "journalism"], description: "The fastest readout and low high-gain read noise: almost no rolling-shutter skew and clean high ISO, at a moderate resolution.",
48
+ fixedLenses: null, provenance: { pixelPitchMicrometers: "derived", highGainFullWellElectrons: "derived", baseIso: "derived" } },
49
+ { id: "full-frame-24mp-fsi-2010s", name: "Full frame 24 MP front-illuminated, 2010s", marketTag: "professional", architecture: "front-illuminated",
50
+ sensorWidthMm: 36.01, sensorHeightMm: 24.07, pixelsWide: 6032, pixelsHigh: 4032, pixelPitchMicrometers: 5.97, peakQuantumEfficiency: .53,
51
+ fullWellElectrons: 76000, readNoise: { lowGainElectrons: 4, highGainElectrons: 4, highGainFromIso: null }, highGainFullWellElectrons: null,
52
+ adcBitDepth: 14, baseIso: 80, maximumIso: 25600, maximumAnalogGain: 64, readoutSeconds: .08, fixedPattern: FSI,
53
+ goodFor: ["portrait", "landscape", "journalism"], description: "An older professional sensor: lower QE and one conversion gain, so a modern consumer BSI sensor beats it at high ISO; slow readout.",
54
+ fixedLenses: null, provenance: { ...sourced("S3", "pixels", "pixelPitchMicrometers", "peakQuantumEfficiency", "fullWellElectrons", "adcBitDepth"),
55
+ sensorSize: "derived", architecture: "derived S4", baseIso: "derived" } },
56
+ { id: "aps-c-24mp-fsi-2020s", name: "APS-C 24 MP front-illuminated, 2020s", marketTag: "consumer", architecture: "front-illuminated",
57
+ sensorWidthMm: 23.55, sensorHeightMm: 15.73, pixelsWide: 6024, pixelsHigh: 4024, pixelPitchMicrometers: 3.91, peakQuantumEfficiency: .55,
58
+ fullWellElectrons: 36000, readNoise: { lowGainElectrons: 2.7, highGainElectrons: 2.7, highGainFromIso: null }, highGainFullWellElectrons: null,
59
+ adcBitDepth: 14, baseIso: 80, maximumIso: 25600, maximumAnalogGain: 64, readoutSeconds: .06, fixedPattern: FSI,
60
+ goodFor: ["travel", "family", "learning"], description: "A smaller, front-illuminated sensor: less light per pixel, a slower readout and more rolling-shutter skew.",
61
+ fixedLenses: null, provenance: { ...sourced("S5", "pixels", "pixelPitchMicrometers", "architecture", "fullWellElectrons", "readNoise", "adcBitDepth"), sensorSize: "derived", baseIso: "derived" } },
62
+ { id: "aps-c-26mp-bsi-2020s", name: "APS-C 26 MP BSI, 2020s", marketTag: "professional", architecture: "back-illuminated",
63
+ sensorWidthMm: 23.49, sensorHeightMm: 15.7, pixelsWide: 6248, pixelsHigh: 4176, pixelPitchMicrometers: 3.76, peakQuantumEfficiency: .8,
64
+ fullWellElectrons: 50000, readNoise: { lowGainElectrons: 3.3, highGainElectrons: 1, highGainFromIso: 250 }, highGainFullWellElectrons: 16000,
65
+ adcBitDepth: 14, baseIso: 80, maximumIso: 25600, maximumAnalogGain: 64, readoutSeconds: .025, fixedPattern: BSI,
66
+ goodFor: ["wildlife", "sports", "travel"], description: "A BSI APS-C sensor with dual conversion gain whose readout beats the consumer full-frame profile's.",
67
+ fixedLenses: null, provenance: { ...sourced("S6", "pixels", "pixelPitchMicrometers", "peakQuantumEfficiency", "fullWellElectrons", "readNoise"), sensorSize: "derived",
68
+ architecture: "published S6", highGainFromIso: "design (S7)", highGainFullWellElectrons: "derived", baseIso: "derived" } },
69
+ { id: "medium-format-100mp-bsi-16bit", name: "Medium format 100 MP BSI, 16-bit", marketTag: "professional", architecture: "back-illuminated",
70
+ sensorWidthMm: 43.856, sensorHeightMm: 32.9, pixelsWide: 11656, pixelsHigh: 8750, pixelPitchMicrometers: 3.76, peakQuantumEfficiency: .8,
71
+ fullWellElectrons: 50300, readNoise: { lowGainElectrons: 3.3, highGainElectrons: 1, highGainFromIso: 250 }, highGainFullWellElectrons: 16096,
72
+ adcBitDepth: 16, baseIso: 80, maximumIso: 12800, maximumAnalogGain: 64, readoutSeconds: .25, fixedPattern: BSI,
73
+ goodFor: ["studio", "landscape", "portrait"], description: "A large sensor with 100 MP and a 16-bit RAW; a slow readout makes its electronic shutter unsuited to motion.",
74
+ fixedLenses: null, provenance: { ...sourced("S7", "pixels", "pixelPitchMicrometers", "sensorSize", "fullWellElectrons", "readNoise", "adcBitDepth"), architecture: "published S8",
75
+ highGainFromIso: "derived S7", highGainFullWellElectrons: "derived", baseIso: "derived" } },
76
+ { id: "phone-50mp-stacked", name: "Phone, large, 50 MP stacked", marketTag: "consumer", architecture: "stacked",
77
+ sensorWidthMm: 9.844, sensorHeightMm: 7.431, pixelsWide: 8192, pixelsHigh: 6144, pixelPitchMicrometers: 1.197, peakQuantumEfficiency: .75,
78
+ fullWellElectrons: 8600, readNoise: { lowGainElectrons: 3, highGainElectrons: 1.4, highGainFromIso: 160 }, highGainFullWellElectrons: 2150,
79
+ adcBitDepth: 12, baseIso: 40, maximumIso: 6400, maximumAnalogGain: 64, readoutSeconds: 1 / 30,
80
+ fixedPattern: { prnu: .008, dsnu: .3, hotPixelFraction: 2e-4, hotPixelMultiplier: 50, rowElectrons: .2, columnElectrons: .2 },
81
+ goodFor: ["everyday", "travel", "family"], description: "A large phone sensor: tiny pixels with a small full well, so less dynamic range and more noise per pixel; simulated as a single frame (no multi-frame stacking).",
82
+ fixedLenses: "phone", provenance: { ...sourced("S9", "pixels", "pixelPitchMicrometers", "sensorSize", "architecture", "adcBitDepth"), fullWellElectrons: "design (S10 scaled by pixel area)",
83
+ readNoise: "high gain published S10, low gain design", highGainFullWellElectrons: "derived", readoutSeconds: "derived S9 (1 / full-resolution frame rate)",
84
+ fixedPattern: "PRNU, row and column published S10; the rest design", baseIso: "derived" } }
85
+ ] satisfies SensorProfile[]).map((p) => Object.freeze(p)))
86
+ ```
@@ -1,6 +1,6 @@
1
1
  {
2
- "packageVersion": "2.20.0",
3
- "engineApiVersion": "2.20.0",
2
+ "packageVersion": "2.21.0",
3
+ "engineApiVersion": "2.21.0",
4
4
  "exports": [
5
5
  {
6
6
  "name": "AbsoluteUncertaintyEstimate",
@@ -512,6 +512,16 @@
512
512
  "source": "src/output/crop.ts",
513
513
  "kind": "type"
514
514
  },
515
+ {
516
+ "name": "calculateChannelEffectiveDispersion",
517
+ "source": "src/output/generic-lens-corrections.ts",
518
+ "kind": "runtime"
519
+ },
520
+ {
521
+ "name": "CalculateChannelEffectiveDispersionInput",
522
+ "source": "src/output/generic-lens-corrections.ts",
523
+ "kind": "type"
524
+ },
515
525
  {
516
526
  "name": "calculateChartFraming",
517
527
  "source": "src/facade/subject-framing.ts",
@@ -972,6 +982,16 @@
972
982
  "source": "src/optics/lateral-chromatic-aberration.ts",
973
983
  "kind": "type"
974
984
  },
985
+ {
986
+ "name": "calculateLateralColorFringe",
987
+ "source": "src/optics/generic-lens-lateral-color.ts",
988
+ "kind": "runtime"
989
+ },
990
+ {
991
+ "name": "CalculateLateralColorFringeInput",
992
+ "source": "src/optics/generic-lens-lateral-color.ts",
993
+ "kind": "type"
994
+ },
975
995
  {
976
996
  "name": "calculateLensComplexPupilPsf",
977
997
  "source": "src/optics/complex-pupil-psf.ts",
@@ -1952,6 +1972,11 @@
1952
1972
  "source": "src/processing/demosaic.ts",
1953
1973
  "kind": "type"
1954
1974
  },
1975
+ {
1976
+ "name": "ChannelDispersion",
1977
+ "source": "src/output/developed-lens-corrections.ts",
1978
+ "kind": "type"
1979
+ },
1955
1980
  {
1956
1981
  "name": "ChannelSeparationVectorMm",
1957
1982
  "source": "src/optics/lateral-chromatic-aberration.ts",
@@ -2692,6 +2717,16 @@
2692
2717
  "source": "src/processing/tone-mapping.ts",
2693
2718
  "kind": "runtime"
2694
2719
  },
2720
+ {
2721
+ "name": "createRepresentativeLightSourceIlluminant",
2722
+ "source": "src/facade/representative-light-sources.ts",
2723
+ "kind": "runtime"
2724
+ },
2725
+ {
2726
+ "name": "createRepresentativeLightSourceSpectrum",
2727
+ "source": "src/facade/representative-light-sources.ts",
2728
+ "kind": "runtime"
2729
+ },
2695
2730
  {
2696
2731
  "name": "createRollingShutterCaptureExposureSchedule",
2697
2732
  "source": "src/sensor/readout-exposure-linkage.ts",
@@ -3247,6 +3282,16 @@
3247
3282
  "source": "src/capture/photographic-export.ts",
3248
3283
  "kind": "type"
3249
3284
  },
3285
+ {
3286
+ "name": "EXPOSURE_BUILD_UP_MAXIMUM_FRACTIONS",
3287
+ "source": "src/facade/exposure-build-up.ts",
3288
+ "kind": "runtime"
3289
+ },
3290
+ {
3291
+ "name": "EXPOSURE_BUILD_UP_STREAM_BASE",
3292
+ "source": "src/facade/exposure-build-up.ts",
3293
+ "kind": "runtime"
3294
+ },
3250
3295
  {
3251
3296
  "name": "EXPOSURE_DURATION_CONTROL_VERSION",
3252
3297
  "source": "src/exposure/exposure-duration-control.ts",
@@ -3997,6 +4042,11 @@
3997
4042
  "source": "src/optics/psf-foundation.ts",
3998
4043
  "kind": "runtime"
3999
4044
  },
4045
+ {
4046
+ "name": "getRepresentativeLightSourceSet",
4047
+ "source": "src/facade/representative-light-sources.ts",
4048
+ "kind": "runtime"
4049
+ },
4000
4050
  {
4001
4051
  "name": "getWebGpuEnabled",
4002
4052
  "source": "src/gpu/webgpu-switch.ts",
@@ -4247,6 +4297,11 @@
4247
4297
  "source": "src/gpu/image-kernel-execution.ts",
4248
4298
  "kind": "type"
4249
4299
  },
4300
+ {
4301
+ "name": "ImagePlaneImage",
4302
+ "source": "src/facade/scene-radiance.ts",
4303
+ "kind": "type"
4304
+ },
4250
4305
  {
4251
4306
  "name": "ImagePlaneMetricPointMm",
4252
4307
  "source": "src/output/capture-geometry.ts",
@@ -4257,6 +4312,11 @@
4257
4312
  "source": "src/motion/camera-rotation.ts",
4258
4313
  "kind": "type"
4259
4314
  },
4315
+ {
4316
+ "name": "ImagePlaneScene",
4317
+ "source": "src/facade/scene-radiance.ts",
4318
+ "kind": "type"
4319
+ },
4260
4320
  {
4261
4321
  "name": "ImagingAreaMetrics",
4262
4322
  "source": "src/sensor/sensor-geometry.ts",
@@ -4487,6 +4547,16 @@
4487
4547
  "source": "src/optics/lateral-chromatic-aberration.ts",
4488
4548
  "kind": "type"
4489
4549
  },
4550
+ {
4551
+ "name": "LateralColorDisplacement",
4552
+ "source": "src/optics/generic-lens-lateral-color.ts",
4553
+ "kind": "type"
4554
+ },
4555
+ {
4556
+ "name": "LateralColorFringe",
4557
+ "source": "src/optics/generic-lens-lateral-color.ts",
4558
+ "kind": "type"
4559
+ },
4490
4560
  {
4491
4561
  "name": "LayeredColorSamplingLayout",
4492
4562
  "source": "src/sensor/color-sampling.ts",
@@ -4847,6 +4917,31 @@
4847
4917
  "source": "src/exposure/metering-temporal.ts",
4848
4918
  "kind": "type"
4849
4919
  },
4920
+ {
4921
+ "name": "MixedIllumination",
4922
+ "source": "src/facade/mixed-illumination.ts",
4923
+ "kind": "type"
4924
+ },
4925
+ {
4926
+ "name": "MixedIlluminationBlend",
4927
+ "source": "src/facade/mixed-illumination.ts",
4928
+ "kind": "type"
4929
+ },
4930
+ {
4931
+ "name": "MixedIlluminationPoint",
4932
+ "source": "src/facade/mixed-illumination.ts",
4933
+ "kind": "type"
4934
+ },
4935
+ {
4936
+ "name": "MixedIlluminationPointSource",
4937
+ "source": "src/facade/mixed-illumination.ts",
4938
+ "kind": "type"
4939
+ },
4940
+ {
4941
+ "name": "MixedIlluminationSource",
4942
+ "source": "src/facade/mixed-illumination.ts",
4943
+ "kind": "type"
4944
+ },
4850
4945
  {
4851
4946
  "name": "MonochromeColorSamplingLayout",
4852
4947
  "source": "src/sensor/color-sampling.ts",
@@ -6012,6 +6107,11 @@
6012
6107
  "source": "src/composition/image-formation-plan.ts",
6013
6108
  "kind": "type"
6014
6109
  },
6110
+ {
6111
+ "name": "prepareImagePlaneScenes",
6112
+ "source": "src/facade/image-plane-enable.ts",
6113
+ "kind": "runtime"
6114
+ },
6015
6115
  {
6016
6116
  "name": "prepareRgbGamutMapping",
6017
6117
  "source": "src/color/gamut-mapping.ts",
@@ -6067,6 +6167,11 @@
6067
6167
  "source": "src/output/print-size-blur-noise.ts",
6068
6168
  "kind": "type"
6069
6169
  },
6170
+ {
6171
+ "name": "PrintContainLayout",
6172
+ "source": "src/output/print-plan.ts",
6173
+ "kind": "type"
6174
+ },
6070
6175
  {
6071
6176
  "name": "PrintContrastReference",
6072
6177
  "source": "src/output/print-contrast-reference.ts",
@@ -6092,6 +6197,11 @@
6092
6197
  "source": "src/output/print-plan.ts",
6093
6198
  "kind": "type"
6094
6199
  },
6200
+ {
6201
+ "name": "PrintFit",
6202
+ "source": "src/output/print-plan.ts",
6203
+ "kind": "type"
6204
+ },
6095
6205
  {
6096
6206
  "name": "PrintImageMm",
6097
6207
  "source": "src/output/print-size-blur-noise.ts",
@@ -6727,6 +6837,46 @@
6727
6837
  "source": "src/composition/image-formation-plan.ts",
6728
6838
  "kind": "type"
6729
6839
  },
6840
+ {
6841
+ "name": "REPRESENTATIVE_LIGHT_SOURCE_IDS",
6842
+ "source": "src/facade/representative-light-sources.ts",
6843
+ "kind": "runtime"
6844
+ },
6845
+ {
6846
+ "name": "REPRESENTATIVE_LIGHT_SOURCE_SET_ID",
6847
+ "source": "src/facade/representative-light-sources.ts",
6848
+ "kind": "runtime"
6849
+ },
6850
+ {
6851
+ "name": "REPRESENTATIVE_LIGHT_SOURCE_SET_VERSION",
6852
+ "source": "src/facade/representative-light-sources.ts",
6853
+ "kind": "runtime"
6854
+ },
6855
+ {
6856
+ "name": "REPRESENTATIVE_LIGHT_SOURCE_WAVELENGTH_RANGE_NANOMETERS",
6857
+ "source": "src/facade/representative-light-sources.ts",
6858
+ "kind": "runtime"
6859
+ },
6860
+ {
6861
+ "name": "RepresentativeLightSource",
6862
+ "source": "src/facade/representative-light-sources.ts",
6863
+ "kind": "type"
6864
+ },
6865
+ {
6866
+ "name": "RepresentativeLightSourceBand",
6867
+ "source": "src/facade/representative-light-sources.ts",
6868
+ "kind": "type"
6869
+ },
6870
+ {
6871
+ "name": "RepresentativeLightSourceId",
6872
+ "source": "src/facade/representative-light-sources.ts",
6873
+ "kind": "type"
6874
+ },
6875
+ {
6876
+ "name": "RepresentativeLightSourceSet",
6877
+ "source": "src/facade/representative-light-sources.ts",
6878
+ "kind": "type"
6879
+ },
6730
6880
  {
6731
6881
  "name": "RequestedFlashSyncMode",
6732
6882
  "source": "src/exposure/flash.ts",
@@ -7242,6 +7392,11 @@
7242
7392
  "source": "src/schema/illumination-spectral.ts",
7243
7393
  "kind": "runtime"
7244
7394
  },
7395
+ {
7396
+ "name": "resolveSensorProfile",
7397
+ "source": "src/equipment/sensor-profiles.ts",
7398
+ "kind": "runtime"
7399
+ },
7245
7400
  {
7246
7401
  "name": "resolveSensorRawReconstruction",
7247
7402
  "source": "src/sensor/raw-reconstruction.ts",
@@ -7787,6 +7942,21 @@
7787
7942
  "source": "src/sensor/fixed-pattern-noise.ts",
7788
7943
  "kind": "runtime"
7789
7944
  },
7945
+ {
7946
+ "name": "SENSOR_PROFILE_IDS",
7947
+ "source": "src/equipment/sensor-profiles.ts",
7948
+ "kind": "runtime"
7949
+ },
7950
+ {
7951
+ "name": "SENSOR_PROFILE_ISO_ANCHOR",
7952
+ "source": "src/equipment/sensor-profile-body.ts",
7953
+ "kind": "runtime"
7954
+ },
7955
+ {
7956
+ "name": "SENSOR_PROFILES",
7957
+ "source": "src/equipment/sensor-profiles.ts",
7958
+ "kind": "runtime"
7959
+ },
7790
7960
  {
7791
7961
  "name": "SENSOR_RAW_CAPTURE_SAMPLE_VERSION",
7792
7962
  "source": "src/sensor/raw-reconstruction.ts",
@@ -8147,6 +8317,16 @@
8147
8317
  "source": "src/sensor/physical-charge-capacity.ts",
8148
8318
  "kind": "type"
8149
8319
  },
8320
+ {
8321
+ "name": "SensorProfile",
8322
+ "source": "src/equipment/sensor-profile-body.ts",
8323
+ "kind": "type"
8324
+ },
8325
+ {
8326
+ "name": "SensorProfileValueKind",
8327
+ "source": "src/equipment/sensor-profile-body.ts",
8328
+ "kind": "type"
8329
+ },
8150
8330
  {
8151
8331
  "name": "SensorPsfIrradianceQuadrature",
8152
8332
  "source": "src/optics/sensor-psf-quadrature.ts",
@@ -8827,6 +9007,11 @@
8827
9007
  "source": "src/facade/simulate-capture.ts",
8828
9008
  "kind": "type"
8829
9009
  },
9010
+ {
9011
+ "name": "SimulateCaptureSubjectMotion",
9012
+ "source": "src/motion/subject-motion.ts",
9013
+ "kind": "type"
9014
+ },
8830
9015
  {
8831
9016
  "name": "SimulateCaptureWhiteBalance",
8832
9017
  "source": "src/facade/simulate-capture.ts",
@@ -8867,6 +9052,26 @@
8867
9052
  "source": "src/capture/environment-raw-producer.ts",
8868
9053
  "kind": "type"
8869
9054
  },
9055
+ {
9056
+ "name": "simulateExposureBuildUp",
9057
+ "source": "src/facade/exposure-build-up.ts",
9058
+ "kind": "runtime"
9059
+ },
9060
+ {
9061
+ "name": "SimulateExposureBuildUpFrame",
9062
+ "source": "src/facade/exposure-build-up.ts",
9063
+ "kind": "type"
9064
+ },
9065
+ {
9066
+ "name": "SimulateExposureBuildUpOptions",
9067
+ "source": "src/facade/exposure-build-up.ts",
9068
+ "kind": "type"
9069
+ },
9070
+ {
9071
+ "name": "SimulateExposureBuildUpResult",
9072
+ "source": "src/facade/exposure-build-up.ts",
9073
+ "kind": "type"
9074
+ },
8870
9075
  {
8871
9076
  "name": "simulateGenericLensFocusError",
8872
9077
  "source": "src/equipment/generic-lens-catalogue.ts",
@@ -0,0 +1,105 @@
1
+ # facade/exposure-build-up.ts public contracts
2
+
3
+ The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
4
+
5
+ ## EXPOSURE_BUILD_UP_MAXIMUM_FRACTIONS
6
+
7
+ The most fractions one build-up takes.
8
+
9
+ ```ts
10
+ EXPOSURE_BUILD_UP_MAXIMUM_FRACTIONS = 64
11
+ ```
12
+
13
+ ## EXPOSURE_BUILD_UP_STREAM_BASE
14
+
15
+ The first stream ID of the build-up's per-site random streams (`deriveNativeSiteStreamSeedUint32`): fraction j's photo split,
16
+ dark split and readout use streams base + 3j, + 3j + 1 and + 3j + 2 (j = 0 … 63). The whole exposure keeps the ordinary
17
+ streams 0 (charge) and 1 (read noise).
18
+
19
+ ```ts
20
+ EXPOSURE_BUILD_UP_STREAM_BASE = 0x42550000
21
+ ```
22
+
23
+ ## simulateExposureBuildUp
24
+
25
+ Renders fractions of one exposure as one accumulating process (#534), the way a camera's live readout of a long exposure
26
+ would show the light building up. Each fraction is read out and developed as its own photo.
27
+
28
+ The model: photon and dark-charge arrivals at a site are Poisson processes (photon shot noise: EMVA 1288 Release 4.0,
29
+ section 2, free), with any rate over time. Given the count n over [0, t] of a Poisson process with mean Λ(t), its arrival
30
+ times are n independent times with distribution Λ(s)/Λ(t) on [0, t], so its count over [0, s] is Binomial(n, Λ(s)/Λ(t))
31
+ (R. G. Gallager, Discrete Stochastic Processes, chapter 2, sections 2.4 and 2.5, MIT OpenCourseWare 6.262, free).
32
+
33
+ The method: the whole exposure is `simulateCapture(options)` itself, with its ordinary draws and seeds. Each earlier fraction
34
+ fⱼ is a capture of the same request in manual mode at the whole exposure's resolved f-number and ISO and the shutter fⱼ·t,
35
+ so its expected signal at every site is integrated from the spectrum over the window [0, fⱼ·t] by the capture itself (the
36
+ camera rotation, `motion.subject` and mixed lighting included, and each row's own window with a rolling shutter). Its
37
+ counts are not drawn anew: going down the fractions, each site's photo and dark counts are N(fⱼ) ~ Binomial(N(fⱼ₊₁), λ(fⱼ) /
38
+ λ(fⱼ₊₁)), with λ the site's expected mean in each render (after PRNU and DSNU). So every fraction's counts are Poisson with
39
+ that fraction's own mean (the mean and variance of `simulateCapture` at fⱼ·t), they never decrease from one fraction to the
40
+ next, and two fractions' counts covary by the earlier one's mean. Fixed-pattern noise is the sensor's own and the same in
41
+ every fraction. Each fraction's charge is clipped at the full well, then read once: its own read noise (dual gain as the ISO
42
+ selects), pre-ADC and ADC saturation and quantization at the ADC bit depth.
43
+
44
+ The windows are nested, so the true means never decrease; the capture's temporal midpoint quadrature can still put an
45
+ earlier fraction's estimate above a later one's at a site (motion blur). There the split takes probability 1 (the count is
46
+ kept), and the `exposure.buildUp` assumption counts those sites (`nonMonotoneSites`): an approximation of the quadrature,
47
+ not of the binomial law. Raise `sensor.temporalSampleCount` to remove them.
48
+
49
+ Cost: one capture per fraction, plus about 64 bytes per native site for the chain. Exact or fast: the request's own `fast`
50
+ (and the format default) applies to every fraction; the build-up adds no fast method, so with `fast: false` (the calculator's
51
+ setting) every fraction is an exact capture. On screen only: formats "srgb-8" and "srgb-16" (a fraction's JPEG, PNG or DNG
52
+ is refused). A fraction's realization depends on the whole `fractions` list (each step of the chain has its own streams);
53
+ the same request and list always give the same frames.
54
+
55
+ ```ts
56
+ export async function simulateExposureBuildUp(options: SimulateCaptureOptions, buildUp: SimulateExposureBuildUpOptions): Promise<SimulateExposureBuildUpResult>;
57
+ ```
58
+
59
+ This call is asynchronous; byte hashing uses the caller runtime's Web Crypto.
60
+
61
+ ## SimulateExposureBuildUpFrame
62
+
63
+ One readout of a build-up.
64
+
65
+ ```ts
66
+ export interface SimulateExposureBuildUpFrame {
67
+ /** The fraction of the exposure collected. */
68
+ fraction: number;
69
+ /** fraction × the request's shutter time, in s. */
70
+ elapsedSeconds: number;
71
+ /**
72
+ * The fraction developed as its own photo. At fraction 1 it is `simulateCapture(options)` itself, byte for byte. Below 1 it is
73
+ * the result of the fraction's capture (manual, the whole exposure's f-number and ISO, shutter fraction·t: its `image`, `raw`,
74
+ * `plan` and `request`), with the build-up's counts, the `exposure.buildUp` assumption, and the whole exposure's `exposure` and
75
+ * `sensor` reports (the camera's settings and noise figure, not the elapsed part's).
76
+ */
77
+ result: SimulateCaptureResult;
78
+ }
79
+ ```
80
+
81
+ ## SimulateExposureBuildUpOptions
82
+
83
+ The build-up to render with {@link simulateExposureBuildUp}.
84
+
85
+ ```ts
86
+ export interface SimulateExposureBuildUpOptions {
87
+ /**
88
+ * Fractions of `exposure.shutterSeconds` to read out, strictly increasing, each above 0 and at most 1 (1 to 64 of them), for
89
+ * example `[0.2, 0.4, 0.6, 0.8, 1]`. A fraction of 1 is the whole exposure: `simulateCapture` of the request.
90
+ */
91
+ fractions: readonly number[];
92
+ }
93
+ ```
94
+
95
+ ## SimulateExposureBuildUpResult
96
+
97
+ The readouts of {@link simulateExposureBuildUp}, in the order of `fractions`.
98
+
99
+ ```ts
100
+ export interface SimulateExposureBuildUpResult {
101
+ /** The whole exposure's shutter time, in s. */
102
+ shutterSeconds: number;
103
+ frames: readonly SimulateExposureBuildUpFrame[];
104
+ }
105
+ ```
@@ -21,9 +21,13 @@ SIMULATE_CAPTURE_FAST_METHODS: readonly SimulateCaptureFastMethod[] = Object.fre
21
21
  exact: "one zone per site: the PSF at each site centre", followsFormatDefault: true,
22
22
  resolver: { file: CAPTURE, call: "resolveFast(catalogueFast, fastTop)" }, report: { applied: "lens.catalogue", assumption: "view.lensPsf" } },
23
23
  { id: "lens.diffraction/rolling-shutter-taps", override: "lens.diffraction", methods: "fast-and-exact", runs: ["simulateCapture"],
24
- fast: "#565: under rolling-shutter rotation, each PSF tap reads the scene at its own source point",
24
+ fast: "#565: under rolling-shutter rotation (#551: or subject motion), each PSF tap reads the scene at its own source point",
25
25
  exact: "each tap reads the scene at its site-lattice point (ties on chart boundaries resolve as on the lattice)", followsFormatDefault: true,
26
26
  resolver: { file: CAPTURE, call: "resolveFast(diffractionFast, fastTop)" }, report: { applied: "lens.diffraction", assumption: "fast.lens.diffraction" } },
27
+ { id: "lens.catalogue/rolling-shutter-taps", override: "lens.catalogue", methods: "fast-and-exact", runs: ["simulateCapture"],
28
+ fast: "#588: under rolling-shutter rotation, each catalogue PSF tap reads the scene at its own source point",
29
+ exact: "each tap reads the scene at its site-lattice point (ties on chart boundaries resolve as on the lattice)", followsFormatDefault: true,
30
+ resolver: { file: CAPTURE, call: "resolveFast(catalogueFast, fastTop)" }, report: { applied: "lens.catalogue", assumption: "fast.lens.catalogue" } },
27
31
  { id: "output.demosaic.ahd/view-low-signal-correction", override: "output.demosaic", methods: "fast-and-exact", runs: ["simulateDisplayView", "prepareDisplayView"],
28
32
  fast: "(H3) 2048 draws per correction state, applied where a pixel's linear noise exceeds 0.01",
29
33
  exact: "8192 draws per state, at the same 0.01 threshold", followsFormatDefault: true,
@@ -40,6 +44,10 @@ SIMULATE_CAPTURE_FAST_METHODS: readonly SimulateCaptureFastMethod[] = Object.fre
40
44
  { id: "sensor.midGrey", override: "fast", methods: "fast-and-exact", runs: ["simulateCapture", "simulateDisplayView", "prepareDisplayView"],
41
45
  fast: "#535: the mid-gray noise figure is not computed (about 0.3 ms)", exact: "result.sensor.midGrey is computed", followsFormatDefault: true,
42
46
  resolver: { file: CAPTURE, call: "fastTop ? undefined : 0" }, report: { field: "sensor.midGrey" } },
47
+ { id: "motion.subject/temporal-midpoints", override: "motion.subject", methods: "fast-and-exact", runs: ["simulateCapture", "simulateDisplayView", "prepareDisplayView"],
48
+ fast: "#551: with the default count and a still camera, one temporal midpoint per site of the subject's streak plus one, when that is fewer than 8",
49
+ exact: "the default 8 temporal midpoints (an explicit sensor.temporalSampleCount always wins)", followsFormatDefault: true,
50
+ resolver: { file: CAPTURE, call: "resolveFast(subjectFast, fastTop)" }, report: { applied: "motion.subject", assumption: "fast.motion.subject" } },
43
51
  { id: "lens.diffraction", override: "lens.diffraction", methods: "exact-only", runs: ["simulateCapture", "simulateDisplayView", "prepareDisplayView"],
44
52
  fast: "", exact: "the diffraction kernels (a fast method only under rolling-shutter rotation, above)", followsFormatDefault: true,
45
53
  resolver: { file: CAPTURE, call: "resolveFast(diffractionFast, fastTop)" }, report: { applied: "lens.diffraction" } },
@@ -0,0 +1,16 @@
1
+ # facade/image-plane-enable.ts public contracts
2
+
3
+ The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
4
+
5
+ ## prepareImagePlaneScenes
6
+
7
+ 2.21 (#581): enables `{ kind: "image-plane" }` scenes (a photo as a flat print, docs/IMAGE_PLANE.md) in this JavaScript realm by
8
+ loading their module (a lazy chunk of about 14 KB gzip with its lattice data). Call it once, in the worker that captures, before
9
+ the first request with such a scene; later calls resolve at once. A request with an image-plane scene before it fails with a
10
+ message saying so.
11
+
12
+ ```ts
13
+ export async function prepareImagePlaneScenes(): Promise<void>;
14
+ ```
15
+
16
+ This call is asynchronous; byte hashing uses the caller runtime's Web Crypto.
@@ -0,0 +1,67 @@
1
+ # facade/mixed-illumination.ts public contracts
2
+
3
+ The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
4
+
5
+ ## MixedIllumination
6
+
7
+ 2.22 (#550), `simulateCapture` `illumination`: sources blended across the chart and point sources with inverse-square falloff
8
+ (docs/MIXED_ILLUMINATION.md). It replaces `illuminant` and `illuminanceLux`. `sources` lists 1 to 8 sources (with two or more, a
9
+ `blend` is required; one lights the whole plane); `points` lists 1 to 8 point sources; a request needs two or more sources or at least one point. Blend
10
+ coordinates are chart-local with `chartSize` and frame units without it; (0, 0) is the frame center.
11
+
12
+ ```ts
13
+ export interface MixedIllumination {
14
+ sources?: readonly MixedIlluminationSource[];
15
+ blend?: MixedIlluminationBlend;
16
+ points?: readonly MixedIlluminationPointSource[];
17
+ }
18
+ ```
19
+
20
+ ## MixedIlluminationBlend
21
+
22
+ How the sources blend across the chart. `linear-gradient` and `radial` map a point to a position t in [0, 1] (its projection
23
+ onto `from` → `to`, clamped; or its distance from `center` over `radius`, clamped) and crossfade linearly between consecutive
24
+ sources at their `stops` (one per source, non-decreasing in [0, 1]; default evenly spaced from 0 to 1): source 0 alone up to
25
+ stops[0], the last source alone from its stop on, and two equal stops a hard edge (the later source from the stop on).
26
+ `regions` gives each point the source of the first rectangle that contains it (bounds inclusive) and `outsideSource` elsewhere.
27
+
28
+ ```ts
29
+ export type MixedIlluminationBlend =
30
+ | { kind: "linear-gradient"; from: MixedIlluminationPoint; to: MixedIlluminationPoint; stops?: readonly number[] }
31
+ | { kind: "radial"; center?: MixedIlluminationPoint; radius: number; stops?: readonly number[] }
32
+ | { kind: "regions"; regions: readonly { source: number; uMin: number; uMax: number; vMin: number; vMax: number }[]; outsideSource: number };
33
+ ```
34
+
35
+ ## MixedIlluminationPoint
36
+
37
+ A point in chart coordinates (see {@link MixedIllumination}).
38
+
39
+ ```ts
40
+ export interface MixedIlluminationPoint { u: number; v: number }
41
+ ```
42
+
43
+ ## MixedIlluminationPointSource
44
+
45
+ 2.22 (#550): a point light on the scene plane's front side: an illuminant spectrum, a position in metres (`xM`, `yM` on the plane
46
+ from the optical axis, +x right and +y up as seen from the camera; `heightM` > 0 in front of the plane, toward the camera) and an
47
+ intensity, either in candela or as the illuminance it gives at normal incidence at a reference distance (I = E·r²).
48
+
49
+ ```ts
50
+ export interface MixedIlluminationPointSource {
51
+ illuminant: CaptureIlluminant;
52
+ position: { xM: number; yM: number; heightM: number };
53
+ intensity: { candela: number } | { illuminanceLux: number; distanceM: number };
54
+ }
55
+ ```
56
+
57
+ ## MixedIlluminationSource
58
+
59
+ One light source of a mixed illumination: an illuminant (as `simulateCapture` `illuminant` takes it) at an illuminance.
60
+
61
+ ```ts
62
+ export interface MixedIlluminationSource {
63
+ illuminant: CaptureIlluminant;
64
+ /** Illuminance this source alone gives where its weight is 1, lux, (0, 1e7]. */
65
+ illuminanceLux: number;
66
+ }
67
+ ```