@photivra/engine 2.19.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.
- package/CHANGELOG.md +289 -1
- package/CITATION.cff +1 -1
- package/NODE_SUPPORT.md +7 -5
- package/README.md +7 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +21 -10
- package/dist/capture/dng-lens-correction-opcodes.d.ts +32 -0
- package/dist/capture/dng-lens-correction-opcodes.js +119 -0
- package/dist/capture/dng-lens-correction-opcodes.js.map +1 -0
- package/dist/capture/exposure-build-up-stage.d.ts +16 -0
- package/dist/capture/exposure-build-up-stage.js +4 -0
- package/dist/capture/exposure-build-up-stage.js.map +1 -0
- package/dist/capture/native-environment-lean.d.ts +2 -1
- package/dist/capture/native-environment-lean.js +42 -78
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-tabulated.js +4 -3
- package/dist/capture/native-environment-tabulated.js.map +1 -1
- package/dist/capture/native-raw-dng.d.ts +6 -0
- package/dist/capture/native-raw-dng.js +16 -2
- package/dist/capture/native-raw-dng.js.map +1 -1
- package/dist/capture/native-raw.d.ts +3 -2
- package/dist/capture/native-raw.js +5 -4
- package/dist/capture/native-raw.js.map +1 -1
- package/dist/capture/sensor-raw-producer.d.ts +4 -1
- package/dist/capture/sensor-raw-producer.js +15 -8
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/core/shared-helpers.d.ts +2 -0
- package/dist/core/shared-helpers.js +4 -0
- package/dist/core/shared-helpers.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/generic-lens-catalogue.d.ts +11 -4
- package/dist/equipment/generic-lens-catalogue.js +49 -7
- package/dist/equipment/generic-lens-catalogue.js.map +1 -1
- package/dist/equipment/generic-tier-assets.d.ts +32 -0
- package/dist/equipment/generic-tier-assets.js +18 -14
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/generic-tier-presets.js +2 -3
- package/dist/equipment/generic-tier-presets.js.map +1 -1
- package/dist/equipment/sensor-profile-body.d.ts +78 -0
- package/dist/equipment/sensor-profile-body.js +77 -0
- package/dist/equipment/sensor-profile-body.js.map +1 -0
- package/dist/equipment/sensor-profiles.d.ts +8 -0
- package/dist/equipment/sensor-profiles.js +82 -0
- package/dist/equipment/sensor-profiles.js.map +1 -0
- package/dist/facade/catalogue-lens-signal.d.ts +2 -2
- package/dist/facade/catalogue-lens-signal.js +58 -71
- package/dist/facade/catalogue-lens-signal.js.map +1 -1
- package/dist/facade/chart-radiance-batch.js +2 -1
- package/dist/facade/chart-radiance-batch.js.map +1 -1
- package/dist/facade/defocus-image-space-provider.d.ts +7 -0
- package/dist/facade/defocus-image-space-provider.js +64 -76
- package/dist/facade/defocus-image-space-provider.js.map +1 -1
- package/dist/facade/display-view-gpu-session.js +2 -0
- package/dist/facade/display-view-gpu-session.js.map +1 -1
- package/dist/facade/display-view-gpu.d.ts +13 -5
- package/dist/facade/display-view-gpu.js +4 -4
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view-lens-signal.d.ts +1 -1
- package/dist/facade/display-view-lens-signal.js +30 -26
- package/dist/facade/display-view-lens-signal.js.map +1 -1
- package/dist/facade/display-view.d.ts +3 -1
- package/dist/facade/display-view.js +6 -24
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/expected-signal-setup.d.ts +3 -1
- package/dist/facade/expected-signal-setup.js +1 -1
- package/dist/facade/expected-signal-setup.js.map +1 -1
- package/dist/facade/expected-signal.d.ts +47 -14
- package/dist/facade/expected-signal.js +117 -112
- package/dist/facade/expected-signal.js.map +1 -1
- package/dist/facade/exposure-build-up.d.ts +70 -0
- package/dist/facade/exposure-build-up.js +164 -0
- package/dist/facade/exposure-build-up.js.map +1 -0
- package/dist/facade/fast-methods.d.ts +50 -0
- package/dist/facade/fast-methods.js +58 -0
- package/dist/facade/fast-methods.js.map +1 -0
- package/dist/facade/fast-resolution.d.ts +12 -0
- package/dist/facade/fast-resolution.js +18 -0
- package/dist/facade/fast-resolution.js.map +1 -0
- package/dist/facade/generic-lens-capture.d.ts +5 -4
- package/dist/facade/generic-lens-capture.js +5 -4
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/image-plane-enable.d.ts +7 -0
- package/dist/facade/image-plane-enable.js +17 -0
- package/dist/facade/image-plane-enable.js.map +1 -0
- package/dist/facade/image-plane-lattice-data.d.ts +6 -0
- package/dist/facade/image-plane-lattice-data.js +10 -0
- package/dist/facade/image-plane-lattice-data.js.map +1 -0
- package/dist/facade/image-plane-support.d.ts +33 -0
- package/dist/facade/image-plane-support.js +11 -0
- package/dist/facade/image-plane-support.js.map +1 -0
- package/dist/facade/image-plane.d.ts +36 -0
- package/dist/facade/image-plane.js +353 -0
- package/dist/facade/image-plane.js.map +1 -0
- package/dist/facade/mixed-illumination.d.ts +108 -0
- package/dist/facade/mixed-illumination.js +174 -0
- package/dist/facade/mixed-illumination.js.map +1 -0
- package/dist/facade/representative-light-sources.d.ts +72 -0
- package/dist/facade/representative-light-sources.js +124 -0
- package/dist/facade/representative-light-sources.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +129 -4
- package/dist/facade/scene-radiance.js +48 -13
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +88 -19
- package/dist/facade/simulate-capture.js +374 -145
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.d.ts +3 -2
- package/dist/facade/simulate-display-view.js +36 -18
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.d.ts +13 -1
- package/dist/gpu/chart-composite-gpu.js +48 -9
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/chart-radiance-gpu.js +4 -30
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-composite-material-module.d.ts +10 -4
- package/dist/gpu/display-view-composite-material-module.js +39 -13
- package/dist/gpu/display-view-composite-material-module.js.map +1 -1
- package/dist/gpu/display-view-image-material-module.d.ts +86 -0
- package/dist/gpu/display-view-image-material-module.js +339 -0
- package/dist/gpu/display-view-image-material-module.js.map +1 -0
- package/dist/gpu/display-view-image-quality.d.ts +45 -0
- package/dist/gpu/display-view-image-quality.js +380 -0
- package/dist/gpu/display-view-image-quality.js.map +1 -0
- package/dist/gpu/display-view-quality-gpu.d.ts +67 -1
- package/dist/gpu/display-view-quality-gpu.js +136 -205
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.d.ts +51 -3
- package/dist/gpu/display-view-speed-gpu.js +131 -93
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +29 -15
- package/dist/gpu/wgsl-display-view-quality-kernel.js +58 -36
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +21 -6
- package/dist/gpu/wgsl-display-view-speed-kernel.js +46 -11
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
- package/dist/gpu/wgsl-exact-sum.d.ts +20 -0
- package/dist/gpu/wgsl-exact-sum.js +42 -0
- package/dist/gpu/wgsl-exact-sum.js.map +1 -0
- package/dist/index.d.ts +18 -3
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/motion/subject-motion.d.ts +66 -0
- package/dist/motion/subject-motion.js +52 -0
- package/dist/motion/subject-motion.js.map +1 -0
- package/dist/optics/aperture-diameter.d.ts +47 -0
- package/dist/optics/aperture-diameter.js +50 -0
- package/dist/optics/aperture-diameter.js.map +1 -0
- package/dist/optics/detail-limit.d.ts +182 -0
- package/dist/optics/detail-limit.js +336 -0
- package/dist/optics/detail-limit.js.map +1 -0
- package/dist/optics/generic-lens-lateral-color.d.ts +83 -0
- package/dist/optics/generic-lens-lateral-color.js +77 -0
- package/dist/optics/generic-lens-lateral-color.js.map +1 -0
- package/dist/optics/generic-lens-psf.d.ts +18 -2
- package/dist/optics/generic-lens-psf.js +79 -48
- package/dist/optics/generic-lens-psf.js.map +1 -1
- package/dist/optics/lens-psf-profile.d.ts +7 -0
- package/dist/optics/lens-psf-profile.js +2 -1
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.d.ts +13 -0
- package/dist/optics/scene-to-sensor-irradiance.js +7 -0
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/output/crop-to-match-focal-length.d.ts +62 -0
- package/dist/output/crop-to-match-focal-length.js +63 -0
- package/dist/output/crop-to-match-focal-length.js.map +1 -0
- package/dist/output/developed-lens-corrections.d.ts +19 -5
- package/dist/output/developed-lens-corrections.js +30 -11
- package/dist/output/developed-lens-corrections.js.map +1 -1
- package/dist/output/generic-lens-corrections.d.ts +41 -3
- package/dist/output/generic-lens-corrections.js +57 -9
- package/dist/output/generic-lens-corrections.js.map +1 -1
- package/dist/output/lens-corrections.d.ts +12 -2
- package/dist/output/lens-corrections.js +22 -7
- package/dist/output/lens-corrections.js.map +1 -1
- package/dist/output/print-contrast-reference.js +1 -1
- package/dist/output/print-contrast-reference.js.map +1 -1
- package/dist/output/print-plan.d.ts +41 -5
- package/dist/output/print-plan.js +59 -14
- package/dist/output/print-plan.js.map +1 -1
- package/dist/output/print-size-blur-noise.d.ts +110 -0
- package/dist/output/print-size-blur-noise.js +138 -0
- package/dist/output/print-size-blur-noise.js.map +1 -0
- package/dist/sensor/binomial-sample.d.ts +3 -0
- package/dist/sensor/binomial-sample.js +86 -0
- package/dist/sensor/binomial-sample.js.map +1 -0
- package/dist/sensor/eqe-electron-rate.js +1 -7
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +2 -0
- package/dist/sensor/exposure-window.js +2 -2
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/readout-timing.js +2 -23
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.js +1 -6
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.js +1 -7
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sensor-characteristics.d.ts +147 -0
- package/dist/sensor/sensor-characteristics.js +126 -0
- package/dist/sensor/sensor-characteristics.js.map +1 -0
- package/dist/sensor/spatial-sample-reduction.js +1 -5
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spectral-quadrature.js +1 -6
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/temporal-photo-signal.d.ts +3 -0
- package/dist/sensor/temporal-photo-signal.js +5 -2
- package/dist/sensor/temporal-photo-signal.js.map +1 -1
- package/dist/stabilization/system.d.ts +9 -0
- package/dist/stabilization/system.js +5 -6
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +5 -0
- package/docs/API_REFERENCE.md +173 -2
- package/docs/QUICK_START.md +213 -6
- package/docs/USAGE.md +157 -3
- package/docs/api/capture-native-raw-dng.md +6 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-lens-catalogue.md +17 -7
- package/docs/api/equipment-sensor-profile-body.md +64 -0
- package/docs/api/equipment-sensor-profiles.md +86 -0
- package/docs/api/exports.json +357 -2
- package/docs/api/facade-display-view-gpu.md +5 -2
- package/docs/api/facade-exposure-build-up.md +105 -0
- package/docs/api/facade-fast-methods.md +99 -0
- package/docs/api/facade-image-plane-enable.md +16 -0
- package/docs/api/facade-mixed-illumination.md +67 -0
- package/docs/api/facade-representative-light-sources.md +131 -0
- package/docs/api/facade-scene-radiance.md +54 -3
- package/docs/api/facade-simulate-capture.md +60 -15
- package/docs/api/facade-simulate-display-view.md +3 -2
- package/docs/api/motion-subject-motion.md +23 -0
- package/docs/api/optics-aperture-diameter.md +51 -0
- package/docs/api/optics-detail-limit.md +203 -0
- package/docs/api/optics-generic-lens-lateral-color.md +79 -0
- package/docs/api/output-crop-to-match-focal-length.md +67 -0
- package/docs/api/output-developed-lens-corrections.md +10 -1
- package/docs/api/output-generic-lens-corrections.md +40 -2
- package/docs/api/output-lens-corrections.md +11 -1
- package/docs/api/output-print-plan.md +35 -1
- package/docs/api/output-print-size-blur-noise.md +115 -0
- package/docs/api/sensor-sensor-characteristics.md +105 -0
- package/llms.txt +6 -0
- package/package.json +1 -1
package/docs/API_REFERENCE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Public API reference
|
|
2
2
|
|
|
3
|
-
Generated from the exact root exports for **@photivra/engine 2.
|
|
3
|
+
Generated from the exact root exports for **@photivra/engine 2.21.0 / root contract 2.21.0** by `node scripts/generate-api-reference.mjs`. No module deep import is supported.
|
|
4
4
|
|
|
5
5
|
Use [the developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md) for executable paths and scientific boundaries. Types are contracts, not runtime validation: parse untrusted data, preserve units/reference frames, read assessment blockers, and retain evidence/limitations. Optional properties do not imply a universal default. Model/schema IDs remain independent of the distribution.
|
|
6
6
|
|
|
@@ -15,11 +15,13 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
15
15
|
| Exposure value and equivalent settings | [`calculateExposureValue100`](api/exposure-exposure.md#calculateexposurevalue100), [`calculateEquivalentIso`](api/exposure-exposure.md#calculateequivalentiso), [`calculateRelativeRenderedExposure`](api/exposure-exposure.md#calculaterelativerenderedexposure) |
|
|
16
16
|
| Depth of field, hyperfocal distance and defocus blur | [`calculateDepthOfField`](api/optics-depth-of-field.md#calculatedepthoffield), [`calculateDefocusCircle`](api/optics-depth-of-field.md#calculatedefocuscircle) |
|
|
17
17
|
| Field of view | [`calculateFieldOfView`](api/camera-field-of-view.md#calculatefieldofview) |
|
|
18
|
-
| Crop factor, 35 mm-equivalent focal length and crops | [`calculateEquivalentFocalLength35Mm`](api/camera-equivalent-focal-length.md#calculateequivalentfocallength35mm), [`calculateCenteredCrop`](api/output-crop.md#calculatecenteredcrop) |
|
|
18
|
+
| Crop factor, 35 mm-equivalent focal length and crops | [`calculateEquivalentFocalLength35Mm`](api/camera-equivalent-focal-length.md#calculateequivalentfocallength35mm), [`calculateCenteredCrop`](api/output-crop.md#calculatecenteredcrop), [`calculateCropToMatchFocalLength`](api/output-crop-to-match-focal-length.md#calculatecroptomatchfocallength) |
|
|
19
|
+
| Aperture (entrance-pupil) diameter | [`calculateApertureDiameter`](api/optics-aperture-diameter.md#calculateaperturediameter) |
|
|
19
20
|
| Equivalent f-number, sensor area and blur as a share of the frame | [`calculateSensorEquivalence`](api/camera-sensor-equivalence.md#calculatesensorequivalence), [`calculateBlurShareOfFrame`](api/camera-sensor-equivalence.md#calculateblurshareofframe) |
|
|
20
21
|
| Motion blur and shutter speed | [`calculateProjectedMotionBlur`](api/motion-projected-motion.md#calculateprojectedmotionblur), [`calculateShutterAngleExposureSeconds`](api/motion-video-sequence.md#calculateshutterangleexposureseconds) |
|
|
21
22
|
| Shutter time with an ND filter | [`calculateFilteredExposureTime`](api/exposure-filtered-exposure-time.md#calculatefilteredexposuretime) |
|
|
22
23
|
| Diffraction | [`calculateAiryDisk`](api/optics-diffraction.md#calculateairydisk) |
|
|
24
|
+
| Which limits detail: the lens or the sensor | [`calculateDetailLimit`](api/optics-detail-limit.md#calculatedetaillimit) |
|
|
23
25
|
| Sensor signal, noise and SNR | [`calculatePhotoelectrons`](api/sensor-signal-noise.md#calculatephotoelectrons), [`calculateSignalToNoise`](api/sensor-signal-noise.md#calculatesignaltonoise) |
|
|
24
26
|
| Colour temperature | [`calculateChromaticityFromCorrelatedColorTemperature`](api/color-illuminants.md#calculatechromaticityfromcorrelatedcolortemperature), [`calculateCorrelatedColorTemperature`](api/color-illuminants.md#calculatecorrelatedcolortemperature) |
|
|
25
27
|
| White balance from Kelvin and tint | [`createColorTemperatureWhiteBalanceIntent`](api/color-white-balance.md#createcolortemperaturewhitebalanceintent), [`resolveColorTemperatureWhiteBalance`](api/color-white-balance.md#resolvecolortemperaturewhitebalance) |
|
|
@@ -974,6 +976,26 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
974
976
|
| [`GenericReleaseDriveMode`](api/equipment-release-capabilities.md#genericreleasedrivemode) | Type |
|
|
975
977
|
| [`parseGenericReleaseCapabilityProfile`](api/equipment-release-capabilities.md#parsegenericreleasecapabilityprofile) | Runtime |
|
|
976
978
|
|
|
979
|
+
## equipment/sensor-profile-body.ts
|
|
980
|
+
|
|
981
|
+
[Detailed contracts](api/equipment-sensor-profile-body.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/equipment/sensor-profile-body.ts)
|
|
982
|
+
|
|
983
|
+
| Export | Kind |
|
|
984
|
+
| --- | --- |
|
|
985
|
+
| [`SENSOR_PROFILE_ISO_ANCHOR`](api/equipment-sensor-profile-body.md#sensor_profile_iso_anchor) | Runtime |
|
|
986
|
+
| [`SensorProfile`](api/equipment-sensor-profile-body.md#sensorprofile) | Type |
|
|
987
|
+
| [`SensorProfileValueKind`](api/equipment-sensor-profile-body.md#sensorprofilevaluekind) | Type |
|
|
988
|
+
|
|
989
|
+
## equipment/sensor-profiles.ts
|
|
990
|
+
|
|
991
|
+
[Detailed contracts](api/equipment-sensor-profiles.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/equipment/sensor-profiles.ts)
|
|
992
|
+
|
|
993
|
+
| Export | Kind |
|
|
994
|
+
| --- | --- |
|
|
995
|
+
| [`resolveSensorProfile`](api/equipment-sensor-profiles.md#resolvesensorprofile) | Runtime |
|
|
996
|
+
| [`SENSOR_PROFILE_IDS`](api/equipment-sensor-profiles.md#sensor_profile_ids) | Runtime |
|
|
997
|
+
| [`SENSOR_PROFILES`](api/equipment-sensor-profiles.md#sensor_profiles) | Runtime |
|
|
998
|
+
|
|
977
999
|
## exposure/auto-iso-slowest-shutter.ts
|
|
978
1000
|
|
|
979
1001
|
[Detailed contracts](api/exposure-auto-iso-slowest-shutter.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/exposure/auto-iso-slowest-shutter.ts)
|
|
@@ -1312,6 +1334,66 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1312
1334
|
| [`DisplayViewCorrectionStateSet`](api/facade-display-view.md#displayviewcorrectionstateset) | Type |
|
|
1313
1335
|
| [`serializeDisplayViewCorrectionStates`](api/facade-display-view.md#serializedisplayviewcorrectionstates) | Runtime |
|
|
1314
1336
|
|
|
1337
|
+
## facade/exposure-build-up.ts
|
|
1338
|
+
|
|
1339
|
+
[Detailed contracts](api/facade-exposure-build-up.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/facade/exposure-build-up.ts)
|
|
1340
|
+
|
|
1341
|
+
| Export | Kind |
|
|
1342
|
+
| --- | --- |
|
|
1343
|
+
| [`EXPOSURE_BUILD_UP_MAXIMUM_FRACTIONS`](api/facade-exposure-build-up.md#exposure_build_up_maximum_fractions) | Runtime |
|
|
1344
|
+
| [`EXPOSURE_BUILD_UP_STREAM_BASE`](api/facade-exposure-build-up.md#exposure_build_up_stream_base) | Runtime |
|
|
1345
|
+
| [`simulateExposureBuildUp`](api/facade-exposure-build-up.md#simulateexposurebuildup) | Runtime |
|
|
1346
|
+
| [`SimulateExposureBuildUpFrame`](api/facade-exposure-build-up.md#simulateexposurebuildupframe) | Type |
|
|
1347
|
+
| [`SimulateExposureBuildUpOptions`](api/facade-exposure-build-up.md#simulateexposurebuildupoptions) | Type |
|
|
1348
|
+
| [`SimulateExposureBuildUpResult`](api/facade-exposure-build-up.md#simulateexposurebuildupresult) | Type |
|
|
1349
|
+
|
|
1350
|
+
## facade/fast-methods.ts
|
|
1351
|
+
|
|
1352
|
+
[Detailed contracts](api/facade-fast-methods.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/facade/fast-methods.ts)
|
|
1353
|
+
|
|
1354
|
+
| Export | Kind |
|
|
1355
|
+
| --- | --- |
|
|
1356
|
+
| [`SIMULATE_CAPTURE_FAST_METHODS`](api/facade-fast-methods.md#simulate_capture_fast_methods) | Runtime |
|
|
1357
|
+
| [`SimulateCaptureFastMethod`](api/facade-fast-methods.md#simulatecapturefastmethod) | Type |
|
|
1358
|
+
|
|
1359
|
+
## facade/image-plane-enable.ts
|
|
1360
|
+
|
|
1361
|
+
[Detailed contracts](api/facade-image-plane-enable.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/facade/image-plane-enable.ts)
|
|
1362
|
+
|
|
1363
|
+
| Export | Kind |
|
|
1364
|
+
| --- | --- |
|
|
1365
|
+
| [`prepareImagePlaneScenes`](api/facade-image-plane-enable.md#prepareimageplanescenes) | Runtime |
|
|
1366
|
+
|
|
1367
|
+
## facade/mixed-illumination.ts
|
|
1368
|
+
|
|
1369
|
+
[Detailed contracts](api/facade-mixed-illumination.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/facade/mixed-illumination.ts)
|
|
1370
|
+
|
|
1371
|
+
| Export | Kind |
|
|
1372
|
+
| --- | --- |
|
|
1373
|
+
| [`MixedIllumination`](api/facade-mixed-illumination.md#mixedillumination) | Type |
|
|
1374
|
+
| [`MixedIlluminationBlend`](api/facade-mixed-illumination.md#mixedilluminationblend) | Type |
|
|
1375
|
+
| [`MixedIlluminationPoint`](api/facade-mixed-illumination.md#mixedilluminationpoint) | Type |
|
|
1376
|
+
| [`MixedIlluminationPointSource`](api/facade-mixed-illumination.md#mixedilluminationpointsource) | Type |
|
|
1377
|
+
| [`MixedIlluminationSource`](api/facade-mixed-illumination.md#mixedilluminationsource) | Type |
|
|
1378
|
+
|
|
1379
|
+
## facade/representative-light-sources.ts
|
|
1380
|
+
|
|
1381
|
+
[Detailed contracts](api/facade-representative-light-sources.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/facade/representative-light-sources.ts)
|
|
1382
|
+
|
|
1383
|
+
| Export | Kind |
|
|
1384
|
+
| --- | --- |
|
|
1385
|
+
| [`createRepresentativeLightSourceIlluminant`](api/facade-representative-light-sources.md#createrepresentativelightsourceilluminant) | Runtime |
|
|
1386
|
+
| [`createRepresentativeLightSourceSpectrum`](api/facade-representative-light-sources.md#createrepresentativelightsourcespectrum) | Runtime |
|
|
1387
|
+
| [`getRepresentativeLightSourceSet`](api/facade-representative-light-sources.md#getrepresentativelightsourceset) | Runtime |
|
|
1388
|
+
| [`REPRESENTATIVE_LIGHT_SOURCE_IDS`](api/facade-representative-light-sources.md#representative_light_source_ids) | Runtime |
|
|
1389
|
+
| [`REPRESENTATIVE_LIGHT_SOURCE_SET_ID`](api/facade-representative-light-sources.md#representative_light_source_set_id) | Runtime |
|
|
1390
|
+
| [`REPRESENTATIVE_LIGHT_SOURCE_SET_VERSION`](api/facade-representative-light-sources.md#representative_light_source_set_version) | Runtime |
|
|
1391
|
+
| [`REPRESENTATIVE_LIGHT_SOURCE_WAVELENGTH_RANGE_NANOMETERS`](api/facade-representative-light-sources.md#representative_light_source_wavelength_range_nanometers) | Runtime |
|
|
1392
|
+
| [`RepresentativeLightSource`](api/facade-representative-light-sources.md#representativelightsource) | Type |
|
|
1393
|
+
| [`RepresentativeLightSourceBand`](api/facade-representative-light-sources.md#representativelightsourceband) | Type |
|
|
1394
|
+
| [`RepresentativeLightSourceId`](api/facade-representative-light-sources.md#representativelightsourceid) | Type |
|
|
1395
|
+
| [`RepresentativeLightSourceSet`](api/facade-representative-light-sources.md#representativelightsourceset) | Type |
|
|
1396
|
+
|
|
1315
1397
|
## facade/scene-radiance.ts
|
|
1316
1398
|
|
|
1317
1399
|
[Detailed contracts](api/facade-scene-radiance.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/facade/scene-radiance.ts)
|
|
@@ -1326,6 +1408,8 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1326
1408
|
| [`CHART_SIZE_DEFAULT_SURROUND_REFLECTANCE`](api/facade-scene-radiance.md#chart_size_default_surround_reflectance) | Runtime |
|
|
1327
1409
|
| [`ChartSizeOption`](api/facade-scene-radiance.md#chartsizeoption) | Type |
|
|
1328
1410
|
| [`createPlanarSceneRadianceProvider`](api/facade-scene-radiance.md#createplanarsceneradianceprovider) | Runtime |
|
|
1411
|
+
| [`ImagePlaneImage`](api/facade-scene-radiance.md#imageplaneimage) | Type |
|
|
1412
|
+
| [`ImagePlaneScene`](api/facade-scene-radiance.md#imageplanescene) | Type |
|
|
1329
1413
|
| [`PHOTOPIC_MAXIMUM_LUMINOUS_EFFICACY_LM_PER_W`](api/facade-scene-radiance.md#photopic_maximum_luminous_efficacy_lm_per_w) | Runtime |
|
|
1330
1414
|
| [`PlanarSceneRadianceProvider`](api/facade-scene-radiance.md#planarsceneradianceprovider) | Type |
|
|
1331
1415
|
| [`resolveCaptureIlluminant`](api/facade-scene-radiance.md#resolvecaptureilluminant) | Runtime |
|
|
@@ -1552,6 +1636,14 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1552
1636
|
| [`CalculateProjectedMotionBlurInput`](api/motion-projected-motion.md#calculateprojectedmotionblurinput) | Type |
|
|
1553
1637
|
| [`ProjectedMotionBlur`](api/motion-projected-motion.md#projectedmotionblur) | Type |
|
|
1554
1638
|
|
|
1639
|
+
## motion/subject-motion.ts
|
|
1640
|
+
|
|
1641
|
+
[Detailed contracts](api/motion-subject-motion.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/motion/subject-motion.ts)
|
|
1642
|
+
|
|
1643
|
+
| Export | Kind |
|
|
1644
|
+
| --- | --- |
|
|
1645
|
+
| [`SimulateCaptureSubjectMotion`](api/motion-subject-motion.md#simulatecapturesubjectmotion) | Type |
|
|
1646
|
+
|
|
1555
1647
|
## motion/temporal-exposure-sum.ts
|
|
1556
1648
|
|
|
1557
1649
|
[Detailed contracts](api/motion-temporal-exposure-sum.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/motion/temporal-exposure-sum.ts)
|
|
@@ -1583,6 +1675,16 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1583
1675
|
| [`VIDEO_FRAME_SEQUENCE_VERSION`](api/motion-video-sequence.md#video_frame_sequence_version) | Runtime |
|
|
1584
1676
|
| [`VideoFrameSequence`](api/motion-video-sequence.md#videoframesequence) | Type |
|
|
1585
1677
|
|
|
1678
|
+
## optics/aperture-diameter.ts
|
|
1679
|
+
|
|
1680
|
+
[Detailed contracts](api/optics-aperture-diameter.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/aperture-diameter.ts)
|
|
1681
|
+
|
|
1682
|
+
| Export | Kind |
|
|
1683
|
+
| --- | --- |
|
|
1684
|
+
| [`ApertureDiameter`](api/optics-aperture-diameter.md#aperturediameter) | Type |
|
|
1685
|
+
| [`calculateApertureDiameter`](api/optics-aperture-diameter.md#calculateaperturediameter) | Runtime |
|
|
1686
|
+
| [`CalculateApertureDiameterInput`](api/optics-aperture-diameter.md#calculateaperturediameterinput) | Type |
|
|
1687
|
+
|
|
1586
1688
|
## optics/aperture.ts
|
|
1587
1689
|
|
|
1588
1690
|
[Detailed contracts](api/optics-aperture.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/aperture.ts)
|
|
@@ -1687,6 +1789,25 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1687
1789
|
| [`DefocusCircle`](api/optics-depth-of-field.md#defocuscircle) | Type |
|
|
1688
1790
|
| [`DepthOfField`](api/optics-depth-of-field.md#depthoffield) | Type |
|
|
1689
1791
|
|
|
1792
|
+
## optics/detail-limit.ts
|
|
1793
|
+
|
|
1794
|
+
[Detailed contracts](api/optics-detail-limit.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/detail-limit.ts)
|
|
1795
|
+
|
|
1796
|
+
| Export | Kind |
|
|
1797
|
+
| --- | --- |
|
|
1798
|
+
| [`calculateDetailLimit`](api/optics-detail-limit.md#calculatedetaillimit) | Runtime |
|
|
1799
|
+
| [`CalculateDetailLimitInput`](api/optics-detail-limit.md#calculatedetaillimitinput) | Type |
|
|
1800
|
+
| [`DETAIL_LIMIT_LIMITS`](api/optics-detail-limit.md#detail_limit_limits) | Runtime |
|
|
1801
|
+
| [`DetailLimit`](api/optics-detail-limit.md#detaillimit) | Type |
|
|
1802
|
+
| [`DetailLimitBasis`](api/optics-detail-limit.md#detaillimitbasis) | Type |
|
|
1803
|
+
| [`DetailLimitCatalogueLens`](api/optics-detail-limit.md#detaillimitcataloguelens) | Type |
|
|
1804
|
+
| [`DetailLimitedBy`](api/optics-detail-limit.md#detaillimitedby) | Type |
|
|
1805
|
+
| [`DetailLimitIdealLens`](api/optics-detail-limit.md#detaillimitideallens) | Type |
|
|
1806
|
+
| [`DetailLimitingFactor`](api/optics-detail-limit.md#detaillimitingfactor) | Type |
|
|
1807
|
+
| [`DetailLimitOptics`](api/optics-detail-limit.md#detaillimitoptics) | Type |
|
|
1808
|
+
| [`DetailLimitSampling`](api/optics-detail-limit.md#detaillimitsampling) | Type |
|
|
1809
|
+
| [`DetailLimitSystem`](api/optics-detail-limit.md#detaillimitsystem) | Type |
|
|
1810
|
+
|
|
1690
1811
|
## optics/diffraction-psf-profile.ts
|
|
1691
1812
|
|
|
1692
1813
|
[Detailed contracts](api/optics-diffraction-psf-profile.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/diffraction-psf-profile.ts)
|
|
@@ -1761,6 +1882,17 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1761
1882
|
| [`resolveFrontOfLensFilterTransmission`](api/optics-front-of-lens-filter.md#resolvefrontoflensfiltertransmission) | Runtime |
|
|
1762
1883
|
| [`ResolveFrontOfLensFilterTransmissionInput`](api/optics-front-of-lens-filter.md#resolvefrontoflensfiltertransmissioninput) | Type |
|
|
1763
1884
|
|
|
1885
|
+
## optics/generic-lens-lateral-color.ts
|
|
1886
|
+
|
|
1887
|
+
[Detailed contracts](api/optics-generic-lens-lateral-color.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/generic-lens-lateral-color.ts)
|
|
1888
|
+
|
|
1889
|
+
| Export | Kind |
|
|
1890
|
+
| --- | --- |
|
|
1891
|
+
| [`calculateLateralColorFringe`](api/optics-generic-lens-lateral-color.md#calculatelateralcolorfringe) | Runtime |
|
|
1892
|
+
| [`CalculateLateralColorFringeInput`](api/optics-generic-lens-lateral-color.md#calculatelateralcolorfringeinput) | Type |
|
|
1893
|
+
| [`LateralColorDisplacement`](api/optics-generic-lens-lateral-color.md#lateralcolordisplacement) | Type |
|
|
1894
|
+
| [`LateralColorFringe`](api/optics-generic-lens-lateral-color.md#lateralcolorfringe) | Type |
|
|
1895
|
+
|
|
1764
1896
|
## optics/generic-nd-filter-presets.ts
|
|
1765
1897
|
|
|
1766
1898
|
[Detailed contracts](api/optics-generic-nd-filter-presets.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/generic-nd-filter-presets.ts)
|
|
@@ -2117,6 +2249,16 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
2117
2249
|
| [`CaptureSdrResult`](api/output-capture-sdr.md#capturesdrresult) | Type |
|
|
2118
2250
|
| [`parseCaptureSdrInput`](api/output-capture-sdr.md#parsecapturesdrinput) | Runtime |
|
|
2119
2251
|
|
|
2252
|
+
## output/crop-to-match-focal-length.ts
|
|
2253
|
+
|
|
2254
|
+
[Detailed contracts](api/output-crop-to-match-focal-length.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/output/crop-to-match-focal-length.ts)
|
|
2255
|
+
|
|
2256
|
+
| Export | Kind |
|
|
2257
|
+
| --- | --- |
|
|
2258
|
+
| [`calculateCropToMatchFocalLength`](api/output-crop-to-match-focal-length.md#calculatecroptomatchfocallength) | Runtime |
|
|
2259
|
+
| [`CalculateCropToMatchFocalLengthInput`](api/output-crop-to-match-focal-length.md#calculatecroptomatchfocallengthinput) | Type |
|
|
2260
|
+
| [`CropToMatchFocalLength`](api/output-crop-to-match-focal-length.md#croptomatchfocallength) | Type |
|
|
2261
|
+
|
|
2120
2262
|
## output/crop.ts
|
|
2121
2263
|
|
|
2122
2264
|
[Detailed contracts](api/output-crop.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/output/crop.ts)
|
|
@@ -2133,6 +2275,7 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
2133
2275
|
|
|
2134
2276
|
| Export | Kind |
|
|
2135
2277
|
| --- | --- |
|
|
2278
|
+
| [`ChannelDispersion`](api/output-developed-lens-corrections.md#channeldispersion) | Type |
|
|
2136
2279
|
| [`GENERIC_LENS_CORRECTION_CHANNEL_WAVELENGTHS_NM`](api/output-developed-lens-corrections.md#generic_lens_correction_channel_wavelengths_nm) | Runtime |
|
|
2137
2280
|
|
|
2138
2281
|
## output/generic-lens-corrections.ts
|
|
@@ -2141,6 +2284,8 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
2141
2284
|
|
|
2142
2285
|
| Export | Kind |
|
|
2143
2286
|
| --- | --- |
|
|
2287
|
+
| [`calculateChannelEffectiveDispersion`](api/output-generic-lens-corrections.md#calculatechanneleffectivedispersion) | Runtime |
|
|
2288
|
+
| [`CalculateChannelEffectiveDispersionInput`](api/output-generic-lens-corrections.md#calculatechanneleffectivedispersioninput) | Type |
|
|
2144
2289
|
| [`createGenericLensCorrectionProfile`](api/output-generic-lens-corrections.md#creategenericlenscorrectionprofile) | Runtime |
|
|
2145
2290
|
| [`CreateGenericLensCorrectionProfileInput`](api/output-generic-lens-corrections.md#creategenericlenscorrectionprofileinput) | Type |
|
|
2146
2291
|
|
|
@@ -2286,7 +2431,9 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
2286
2431
|
| [`calculatePrintPlan`](api/output-print-plan.md#calculateprintplan) | Runtime |
|
|
2287
2432
|
| [`calculatePrintSizeLimit`](api/output-print-plan.md#calculateprintsizelimit) | Runtime |
|
|
2288
2433
|
| [`parsePrintPlanInput`](api/output-print-plan.md#parseprintplaninput) | Runtime |
|
|
2434
|
+
| [`PrintContainLayout`](api/output-print-plan.md#printcontainlayout) | Type |
|
|
2289
2435
|
| [`PrintedImageSize`](api/output-print-plan.md#printedimagesize) | Type |
|
|
2436
|
+
| [`PrintFit`](api/output-print-plan.md#printfit) | Type |
|
|
2290
2437
|
| [`PrintLength`](api/output-print-plan.md#printlength) | Type |
|
|
2291
2438
|
| [`PrintNativeSource`](api/output-print-plan.md#printnativesource) | Type |
|
|
2292
2439
|
| [`PrintPlan`](api/output-print-plan.md#printplan) | Type |
|
|
@@ -2316,6 +2463,20 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
2316
2463
|
| [`PrintRegionRaster`](api/output-print-region-statistics.md#printregionraster) | Type |
|
|
2317
2464
|
| [`PrintRegionStatisticsAssessment`](api/output-print-region-statistics.md#printregionstatisticsassessment) | Type |
|
|
2318
2465
|
|
|
2466
|
+
## output/print-size-blur-noise.ts
|
|
2467
|
+
|
|
2468
|
+
[Detailed contracts](api/output-print-size-blur-noise.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/output/print-size-blur-noise.ts)
|
|
2469
|
+
|
|
2470
|
+
| Export | Kind |
|
|
2471
|
+
| --- | --- |
|
|
2472
|
+
| [`calculatePrintSizeLimitWithBlurAndNoise`](api/output-print-size-blur-noise.md#calculateprintsizelimitwithblurandnoise) | Runtime |
|
|
2473
|
+
| [`PrintBlurInput`](api/output-print-size-blur-noise.md#printblurinput) | Type |
|
|
2474
|
+
| [`PrintImageMm`](api/output-print-size-blur-noise.md#printimagemm) | Type |
|
|
2475
|
+
| [`PrintNoiseInput`](api/output-print-size-blur-noise.md#printnoiseinput) | Type |
|
|
2476
|
+
| [`PrintSharpCleanCriterion`](api/output-print-size-blur-noise.md#printsharpcleancriterion) | Type |
|
|
2477
|
+
| [`PrintSizeLimitWithBlurAndNoise`](api/output-print-size-blur-noise.md#printsizelimitwithblurandnoise) | Type |
|
|
2478
|
+
| [`PrintSizeLimitWithBlurAndNoiseInput`](api/output-print-size-blur-noise.md#printsizelimitwithblurandnoiseinput) | Type |
|
|
2479
|
+
|
|
2319
2480
|
## output/sdr-rendering.ts
|
|
2320
2481
|
|
|
2321
2482
|
[Detailed contracts](api/output-sdr-rendering.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/output/sdr-rendering.ts)
|
|
@@ -3124,6 +3285,16 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
3124
3285
|
| [`CalculateSceneSensorEqeTemporalExposureInput`](api/sensor-scene-eqe-temporal-exposure.md#calculatescenesensoreqetemporalexposureinput) | Type |
|
|
3125
3286
|
| [`SceneSensorEqeTemporalExposure`](api/sensor-scene-eqe-temporal-exposure.md#scenesensoreqetemporalexposure) | Type |
|
|
3126
3287
|
|
|
3288
|
+
## sensor/sensor-characteristics.ts
|
|
3289
|
+
|
|
3290
|
+
[Detailed contracts](api/sensor-sensor-characteristics.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/sensor/sensor-characteristics.ts)
|
|
3291
|
+
|
|
3292
|
+
| Export | Kind |
|
|
3293
|
+
| --- | --- |
|
|
3294
|
+
| [`SimulateCaptureNoiseComponents`](api/sensor-sensor-characteristics.md#simulatecapturenoisecomponents) | Type |
|
|
3295
|
+
| [`SimulateCaptureSensorCharacteristics`](api/sensor-sensor-characteristics.md#simulatecapturesensorcharacteristics) | Type |
|
|
3296
|
+
| [`SimulateCaptureSensorReport`](api/sensor-sensor-characteristics.md#simulatecapturesensorreport) | Type |
|
|
3297
|
+
|
|
3127
3298
|
## sensor/sensor-geometry.ts
|
|
3128
3299
|
|
|
3129
3300
|
[Detailed contracts](api/sensor-sensor-geometry.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/sensor/sensor-geometry.ts)
|
package/docs/QUICK_START.md
CHANGED
|
@@ -48,6 +48,7 @@ the example above is [simulate-capture.mjs](examples/simulate-capture.mjs).
|
|
|
48
48
|
| `raw` | The packed native RAW: codes, black levels, saturation flags and per-phase white levels |
|
|
49
49
|
| `plan` | The native RAW plan the engine executed |
|
|
50
50
|
| `request` | The complete underlying request: `environmentRaw` (the native environment RAW input), `siteInput(index)` (rebuilds the physical input of any sensor site), `development` (the RAW development input) and `whiteBalanceState` |
|
|
51
|
+
| `sensor` | 2.20 (#555, #535): the sensor characteristics used (pitch, peak QE, full well, read noise of each conversion gain and the dual-gain switch ISO, readout time, ADC bit depth, fixed-pattern noise), the calculated dynamic range (`dynamicRangeStops`, and per ISO setting) and, on exact requests, the mid-gray noise figure (`midGrey`); see [Sensor characteristics](#sensor-characteristics-555) |
|
|
51
52
|
| `exposure` | Mode, resolved settings, EV100, `isoControl` (`"manual"` or `"automatic"`) and, with `iso: "auto"`, `autoIso` (how the ISO was chosen and what limited it), metered scene luminance, the deviation from the standard exposure in stops (`standardExposureDeviationStops`), the illuminance at which the settings give the standard exposure (`standardExposureIlluminanceLux`), from 2.14 the deviation from the standard exposure of an 18 % grey card under the scene's illuminance (`greyCardDeviationStops`, incident metering) and the exposure-mode resolver's full output |
|
|
52
53
|
| `scene` | Chart parameters, illuminant, distance, framed size and the scene's SHA-256 digest (it covers caller illuminant and reflectance spectra; see `sourceSha256`) |
|
|
53
54
|
| `diagnostics` | Radiance query count, highlight and rendering counters, per-stage timings (`timingsMs`) and, from 2.1, the opt-ins that ran (`options`); see [Cost of each option](#cost-of-each-option) |
|
|
@@ -87,6 +88,7 @@ modelling choices (such as "no lens PSF") as `kind: "model"`.
|
|
|
87
88
|
| `chartSize` | fill the frame | 2.3: `{ widthM, heightM?, surroundReflectance? }` places the chart at its physical size (see [Fixed-size chart](#fixed-size-chart-23)). |
|
|
88
89
|
| `illuminant` | Planckian 6500 K | Also `"cie-a"`, `{ kind: "planckian", temperatureKelvin }`, `{ kind: "daylight", correlatedColorTemperatureKelvin, basis }` or `{ kind: "spectrum", spectrum }`. |
|
|
89
90
|
| `illuminanceLux` | 21 481 (π·80 000/11.7) | See [Exposure](#exposure). |
|
|
91
|
+
| `illumination` | off | 2.22 (#550): mixed lighting, two to eight sources (`{ illuminant, illuminanceLux }`) blended across the chart by a linear gradient, a radial falloff or regions, and point sources (`points`) with inverse-square falloff, instead of `illuminant` and `illuminanceLux`. The frame center's light sets the grey card and its strongest source the `"scene-illuminant"` white balance (see [Mixed lighting](https://github.com/Photivra/photivra/blob/main/docs/MIXED_ILLUMINATION.md)). |
|
|
90
92
|
| `output.width`, `output.height` | 64 × 64 | Output pixels, 1–4094 each. The sensor has one extra site on each side for demosaicing (see `output.borderHandling`). |
|
|
91
93
|
| `output.maximumPixels` | off | Opt-in large images (2.2): the most native sensor sites the capture may allocate, up to `NATIVE_RAW_LIMITS.ceilingPixels` (2^27). Sides may then reach 16 384 sites including the margin (see [Large images](#large-images)). |
|
|
92
94
|
| `output.region` | whole frame | 2.3: `{ x, y, width, height }` renders that rectangle of the frame, byte-identical to the whole render (see [Region rendering](#region-rendering-23)). |
|
|
@@ -117,6 +119,7 @@ modelling choices (such as "no lens PSF") as `kind: "model"`.
|
|
|
117
119
|
| `motion.angularVelocityRadPerSec` | still | `{ pitch?, yaw?, roll? }` in rad/s (see [Motion](#motion)). |
|
|
118
120
|
| `motion.shutter` | `"global"` | Or `"rolling"`. |
|
|
119
121
|
| `motion.rollingShutterSkewSeconds` | the body's readout skew | Rolling only. |
|
|
122
|
+
| `motion.subject` | still subject | 2.22.0: `{ velocityMPerSec?: { x?, y? }, angularVelocityRadPerSec?, region?, fast? }`, a moving subject (see [Subject motion](#subject-motion)). |
|
|
120
123
|
| `signal`, `onProgress` | none | An `AbortSignal` cancels the running task; `onProgress` reports `raw`, `white-balance`, `development`, `diffraction-correction` and `sharpening` (#571: output rows, with those options) and `jpeg` tiles. The last event of each stage has `completedTileCount === totalTileCount`. The capture yields to the host about every 8 ms with a `MessageChannel` message (else `setImmediate`, else `setTimeout`), so other queued tasks run in between: an abort sent from another task, such as a Web Worker `message` event, takes effect at the next yield. |
|
|
121
124
|
|
|
122
125
|
Unknown fields are rejected, so a typo never silently falls back to a default.
|
|
@@ -206,11 +209,13 @@ and every number is a labelled approximation.
|
|
|
206
209
|
for the macro); an f-number or distance outside the lens's range is refused.
|
|
207
210
|
- **Its character is rendered:** a field- and wavelength-dependent PSF (diffraction with the lens's Seidel aberrations, axial and
|
|
208
211
|
lateral colour) through the environment PSF quadrature, its radial distortion, its vignetting and, for the fisheyes, the
|
|
209
|
-
equisolid projection (beyond 90° there is no scene, so the 8 mm's circle is black outside). Flare
|
|
210
|
-
|
|
212
|
+
equisolid projection (beyond 90° there is no scene, so the 8 mm's circle is black outside). Flare and focus breathing are
|
|
213
|
+
reported in the assumption `lens.catalogue.character`, not rendered.
|
|
211
214
|
- **Professional lenses are better** where the owner's table says so: sharper centres and corners, less coma, lateral colour,
|
|
212
215
|
distortion and vignetting, better close focus and focus consistency. The measurements are in the catalogue page.
|
|
213
|
-
- **Combinations:** `lens.defocus` convolves the
|
|
216
|
+
- **Combinations:** `lens.defocus` convolves the lens's own bokeh kernel (#567: its blades, its W040 and, on the fast wides
|
|
217
|
+
and normals, a cat's eye, which is lens.catalogue's exact method: on when the request resolves to exact (`fast: false`, the
|
|
218
|
+
default for DNG, JPEG and PNG), off on fast requests, since it would slow the fast method 2–3.5×; [Bokeh](https://github.com/Photivra/photivra/blob/main/docs/LENS_CATALOGUE.md#bokeh-567)) into the lens's PSF (a combined kernel up to 16 sites in radius);
|
|
214
219
|
`lens.focusScatter: { seed, shotIndex? }` moves the focus by a seeded autofocus error (`simulateGenericLensFocusError`), off
|
|
215
220
|
by default. `prime`, `focalLengthMm`, `projection`, `distortion`, `vignetting`, `psf`, `diffraction` and `pupilSampling` are
|
|
216
221
|
set by the lens and refused with it. The display view renders `lens.catalogue` since #569, with the PSF taken per field zone
|
|
@@ -460,6 +465,96 @@ large-pixel sensor may therefore saturate earlier, and a real small-pixel sensor
|
|
|
460
465
|
given a higher base ISO. When the pitch is not 6 µm, the assumption `sensor.isoAreaNormalization`
|
|
461
466
|
records the area ratio and this approximation.
|
|
462
467
|
|
|
468
|
+
### Sensor characteristics (#555)
|
|
469
|
+
|
|
470
|
+
Each characteristic of the body's sensor can be set on its own under `sensor`. All are off by
|
|
471
|
+
default: a request that sets none is byte-identical to 2.19.0, and every value set is listed in the
|
|
472
|
+
assumption `sensor.characteristics`. The figures under the result's `sensor` are calculated from
|
|
473
|
+
them; they are results, not settings.
|
|
474
|
+
|
|
475
|
+
```ts
|
|
476
|
+
const r = await simulateCapture({ scene: { preset: "uniform" }, sensor: {
|
|
477
|
+
pixelPitchMicrometers: 4,
|
|
478
|
+
peakQuantumEfficiency: 0.8, // green EQE at 555 nm, 0.05–0.9 (default 0.5)
|
|
479
|
+
fullWell: { electrons: 50_000, link: "none" }, // or linked to pixel area (the default)
|
|
480
|
+
readNoise: { lowGainElectrons: 3, highGainElectrons: 1.2, highGainFromIso: 640 },
|
|
481
|
+
readoutSeconds: 0.012, // rolling-shutter skew
|
|
482
|
+
adcBitDepth: 16, // 12, 14 or 16
|
|
483
|
+
fixedPatternNoise: true // the body's synthetic pattern (advanced)
|
|
484
|
+
}, fast: false }); // fast: false computes the mid-gray noise figure
|
|
485
|
+
r.sensor.dynamicRangeStops; r.sensor.midGrey?.snrDecibels;
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
| Option | Range | Default | Effect |
|
|
489
|
+
| --- | --- | --- | --- |
|
|
490
|
+
| `peakQuantumEfficiency` | 0.05–0.9 | 0.5 | Multiplies every channel's EQE curve by value / 0.5: the curves keep their shape and the colour matrix, and the collected charge scales in proportion. 0.9 keeps the blue channel's peak below 1. |
|
|
491
|
+
| `fullWell` | 100–1e10 e⁻ at the pitch | the body's base-ISO saturation at 6 µm, × pitch²/36 µm² | The charge at the RAW white level at base ISO (the saturation capacity of EMVA 1288 Release 4.0). `link: "pixel-area"` (default) scales `electrons`, the full well at `referencePixelPitchMicrometers` (default 6), by (pitch / reference)²; `link: "none"` uses it at any pitch. |
|
|
492
|
+
| `readNoise` | 0–100 e⁻; switch ISO 100–1e7 | the body's (tiers: 2/1.1, 3/1.4 and 6/2.5 e⁻, switch at ISO 800) | Read noise of the low and the high conversion gain, and `highGainFromIso`, the ISO from which the high gain is used. A switch above the body's top ISO keeps the low gain throughout. |
|
|
493
|
+
| `readoutSeconds` | 1e-6–1 s | the body's (8, 15, 30 ms) | The rolling shutter's top-to-bottom skew (`motion.shutter: "rolling"`; `motion.rollingShutterSkewSeconds` still overrides it). |
|
|
494
|
+
| `adcBitDepth` | 12, 14, 16 | the body's (consumer 12, others 14) | The black level scales by 2^Δbits (1 024 at 14 bits → 4 096 at 16), the saturation code is 2^bits − 1 and the conversion gain follows, so the same charge reaches the same fraction of the code range. A 16-bit RAW writes a 16-bit DNG with white level 65 535. |
|
|
495
|
+
| `fixedPatternNoise` | `true`/`false` | `false` | The body's synthetic fixed-pattern profile (PRNU, DSNU, hot pixels, row and column offsets), the same pattern in every capture. Not available in `simulateDisplayView`, which refuses it. |
|
|
496
|
+
|
|
497
|
+
How the full well and the ISO rating interact (an approximation, recorded in the assumption): the
|
|
498
|
+
facade keeps each ISO setting's readout regime, so the full well is reached at the white level of
|
|
499
|
+
base ISO and every regime's conversion gain and pre-ADC saturation scale with it (`chargeScale`).
|
|
500
|
+
The output per unit focal-plane exposure H then changes by 2^`sensitivityOffsetStops` =
|
|
501
|
+
QE scale × (pixel area / 36 µm²) × (body full well / full well): the body's rating S = 10/H (CIPA
|
|
502
|
+
DC-004-2020 §3.2) still holds only when that is 1, as it is for a linked full well and the default
|
|
503
|
+
QE. A higher QE makes the same exposure brighter; a larger unlinked full well makes it darker and
|
|
504
|
+
gives more highlight headroom. The high conversion gain's smaller charge storage is not modelled
|
|
505
|
+
when the switch ISO is lowered. The assumption notes a full well outside 200–10 000 e⁻ per µm² of
|
|
506
|
+
pixel area as unusual for the pitch; that is a design range around the tiers' 556–1 667 e⁻/µm² and
|
|
507
|
+
published values such as about 4 000 e⁻/µm² at 2 µm and 1 400 e⁻/µm² at 5.2 µm (Farrell, Xiao &
|
|
508
|
+
Kavusi, *Proc. SPIE* 6069, 2006, Table 1), not a published bound.
|
|
509
|
+
|
|
510
|
+
**Dynamic range** (`sensor.dynamicRangeStops` at the capture's ISO, `sensor.dynamicRangeByIso` for
|
|
511
|
+
every ISO setting of the body): engineering dynamic range log₂(S_sat / σ_floor). S_sat is the charge
|
|
512
|
+
at the RAW white level (the full well over the analog gain, limited by the charge capacity and the
|
|
513
|
+
ADC range) and σ_floor = √(σ_read² + σ_q²), the temporal dark noise of EMVA 1288 Release 4.0 without
|
|
514
|
+
dark current, with σ_q the ADC quantization (1/12 code², plus 1/12 code² of rounding after a digital
|
|
515
|
+
gain) in electrons. With no read noise the range is limited by the ADC alone: log₂((white − black)·√12).
|
|
516
|
+
The Professional tier gives 14.7 stops at ISO 100, 12.7 at ISO 800 (high gain) and 9.7 at ISO 6400;
|
|
517
|
+
the Consumer tier 11.7, 10.0 and 7.0.
|
|
518
|
+
|
|
519
|
+
**Noise figure** (#535, `sensor.midGrey`): computed only when the request resolves to exact (`fast:
|
|
520
|
+
false`, the default for DNG, JPEG and PNG exports; about 0.3 ms); a fast request (the sRGB default)
|
|
521
|
+
omits it. The expected signal-to-noise ratio of an 18 % Lambertian
|
|
522
|
+
gray patch under the request's illuminant and illuminance, at the capture's exposure, ISO and
|
|
523
|
+
sensor, from the engine's own noise model (a model figure, not a measurement). It is the green
|
|
524
|
+
channel next to the optical axis (no vignetting, PSF or motion). `signalElectrons` S is the patch's
|
|
525
|
+
expected charge; `noiseElectrons` splits the noise into photon shot √S, read, dark-current shot
|
|
526
|
+
√(D·t) with D = 1 e⁻/s, ADC quantization and, with `fixedPatternNoise`, the fixed pattern
|
|
527
|
+
√((PRNU·S)² + (DSNU·D·t)² + row² + column²) (hot pixels excluded; a spatial noise, the same in every
|
|
528
|
+
capture), added in quadrature as `total`. `snr` = S / total and `snrDecibels` = 20·log₁₀(snr).
|
|
529
|
+
`clipped` is true when the patch reaches the white level, where the figure no longer describes
|
|
530
|
+
the image. With the defaults (Professional, f/8, 1/125 s, ISO 100, 21 481 lux) S ≈ 7 842 e⁻ and the
|
|
531
|
+
SNR is 88.5 (38.9 dB); at ISO 6400 with 1/64 of the light, S ≈ 123 e⁻ and the SNR is 11.0 (20.8 dB):
|
|
532
|
+
the photon shot noise grows as √S, so less light means more noise whatever the ISO. The display view
|
|
533
|
+
reports the same `sensor` record as its capture.
|
|
534
|
+
|
|
535
|
+
### Sensor profiles (#554)
|
|
536
|
+
|
|
537
|
+
`sensor.profile` takes one of eight representative sensor profile records whose values come from
|
|
538
|
+
published specifications (`SENSOR_PROFILES`, or `resolveSensorProfile(id)`; unnamed, by format,
|
|
539
|
+
resolution, architecture and era), checked strictly, so a modified copy also works. It
|
|
540
|
+
replaces the body's ISO range, readout regimes (full well, read noise of each conversion gain, the
|
|
541
|
+
dual-gain switch and the high gain's storage, ADC bit depth), readout time and fixed-pattern noise,
|
|
542
|
+
and sets the default pitch and peak QE; the characteristics above still override it one at a time.
|
|
543
|
+
|
|
544
|
+
```ts
|
|
545
|
+
import { resolveSensorProfile, simulateCapture } from "@photivra/engine";
|
|
546
|
+
const phone = await simulateCapture({ scene: { preset: "uniform" }, sensor: { profile: resolveSensorProfile("phone-50mp-stacked") } });
|
|
547
|
+
phone.sensor.fullWellElectrons; // 8 600 e⁻ at 1.197 µm
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
Each profile's base ISO is re-rated from its full well, QE and pixel area, so the same ISO reaches
|
|
551
|
+
the RAW white at the same exposure on every profile (the assumption `sensor.profile` records the
|
|
552
|
+
values and the rounding). The phone profile takes the catalogue's three phone lenses
|
|
553
|
+
(`lens: { catalogue: "pv-24-1.8-phone" }`), and they need it. With a profile, a catalogue lens is framed on
|
|
554
|
+
the profile's real sensor (the largest centred region of the output's aspect; assumption `sensor.profileView`), so it
|
|
555
|
+
shows its real field of view. Values, sources, the framing and the ISO rating:
|
|
556
|
+
[SENSOR_PROFILES.md](https://github.com/Photivra/photivra/blob/main/docs/SENSOR_PROFILES.md).
|
|
557
|
+
|
|
463
558
|
## Exposure
|
|
464
559
|
|
|
465
560
|
The facade meters the scene like a reflected-light meter:
|
|
@@ -1093,6 +1188,18 @@ The optics options feed only what the environment site contract accepts:
|
|
|
1093
1188
|
scene; a test checks it to 1e-12 per site. With camera rotation, a projection or distortion, or
|
|
1094
1189
|
vignetting, the per-tap quadrature runs instead (much slower). `request.diffraction` holds the profile,
|
|
1095
1190
|
the equivalent `sampled-local` PSF and which execution ran.
|
|
1191
|
+
- Ties on chart boundaries (2.20.0, #565): the per-tap quadrature reads each tap's scene point at its site-lattice point, as
|
|
1192
|
+
the object-space convolution, the out-of-focus capture and the display view do, so a tap exactly on a chart boundary (a
|
|
1193
|
+
Siemens star's spokes through lattice points) resolves to the same material on every path. With camera rotation under
|
|
1194
|
+
`motion.shutter: "rolling"` every row has its own instants, so the lattice is read once per instant; there reading the
|
|
1195
|
+
lattice is `lens.diffraction`'s exact method and keeping each tap's own point its fast method; the lattice costs about
|
|
1196
|
+
1.2× the time (dead leaves 48 × 32 at f/8: 4.0–4.1 s against 4.8–5.0 s; a Siemens star 32 × 24 at f/16: 6.8 s against
|
|
1197
|
+
8.1–8.2 s; November 9, 2026, Apple M5 Pro, Node 24.19.0). The format default decides (2.20.0): fast for sRGB samples, exact for
|
|
1198
|
+
DNG, JPEG and PNG; `lens.diffraction: { kind, fast }` or the top-level `fast` wins, and the fast method reports
|
|
1199
|
+
`diagnostics.fast.applied["lens.diffraction"]: true` and the assumption `fast.lens.diffraction`. The two readings differ
|
|
1200
|
+
only at such ties. Region renders joined into one frame (`serializeSimulatedCaptureDngFromParts`,
|
|
1201
|
+
`simulateCaptureFromParts`) match the whole-frame render only if every part resolves `fast` the same way: give the parts
|
|
1202
|
+
and the whole request the same `fast` (a part rendered fast is refused by an exact join).
|
|
1096
1203
|
- The convolution runs in 32-row bands and computes only each band's own values, not the 2R rows and
|
|
1097
1204
|
columns of padding around it (#419; the values are bit-identical to the full-grid convolution's). On a
|
|
1098
1205
|
function scene with the Quality options at 1 µm and f/16 (R 32), 96 × 72, `diagnostics.timingsMs.diffraction`
|
|
@@ -1423,9 +1530,9 @@ lens: { focalLengthMm: 50, fNumber: 4, focusDistanceM: 1.4, defocus: { model: "g
|
|
|
1423
1530
|
combined with `lens.diffraction` (every zone would need its own combined kernel per node). Above a kernel radius of 64
|
|
1424
1531
|
sites it is refused: #564's run convolution takes one kernel per request, and extending it to one kernel per zone is left
|
|
1425
1532
|
for later. `simulateDisplayView` and `prepareDisplayView` refuse it; they render `blades` and `sphericalAberration`.
|
|
1426
|
-
- **With `lens.catalogue` (#549)** the three options are refused by name.
|
|
1427
|
-
own
|
|
1428
|
-
|
|
1533
|
+
- **With `lens.catalogue` (#549)** the three options are refused by name: since 2.20.0 (#567) the catalogue lens sets
|
|
1534
|
+
all three itself (its blades, its own W040 and, on the fast wides and normals, a cat's eye) and folds that kernel into
|
|
1535
|
+
its PSF ([Lens catalogue, Bokeh](https://github.com/Photivra/photivra/blob/main/docs/LENS_CATALOGUE.md#bokeh-567)).
|
|
1429
1536
|
- **Sampling.** Without spherical aberration each site's weight is the exact area of the projected open pupil (a convex
|
|
1430
1537
|
polygon; circles and blade arcs are 1024-gons scaled to their true area, within 5e-6 of the radius of the true curve)
|
|
1431
1538
|
inside the site's cell, divided by its area (`"exact-polygon-cell-area"`). With it the pupil is sampled on a square grid
|
|
@@ -1607,6 +1714,48 @@ const pan = await simulateCapture({
|
|
|
1607
1714
|
console.log(pan.assumptions.find((a) => a.id === "sensor.shutter")?.value, pan.exposure.settings.shutterSeconds);
|
|
1608
1715
|
```
|
|
1609
1716
|
|
|
1717
|
+
## Subject motion
|
|
1718
|
+
|
|
1719
|
+
`motion.subject` (2.22.0, #551) moves the subject on the scene plane during the exposure: the whole scene, or one
|
|
1720
|
+
rectangle of it (`region: { centerXM, centerYM, widthM, heightM }` in metres at rest) over a still background.
|
|
1721
|
+
|
|
1722
|
+
- `velocityMPerSec: { x, y }` is a translation in m/s on the plane (+x right, +y up as seen from the camera).
|
|
1723
|
+
`angularVelocityRadPerSec` adds a rotation about an axis parallel to the optical axis, counter-clockwise as seen from
|
|
1724
|
+
the camera: the optical axis for the whole scene, the region's center for a region.
|
|
1725
|
+
- The model is rigid motion of a planar layer. At time t from the first opening (camera rotation's time reference), a
|
|
1726
|
+
subject point at rest q is at R(ωt)(q − c) + c + v·t. A plane point shows the subject where one is there, else the
|
|
1727
|
+
region's rest rectangle shows a neutral 18 % background (what the subject revealed), else the still scene. The background
|
|
1728
|
+
is lit by the plane's irradiance at that point: the illuminant, or with `illumination` (#550) the blend and point sources there.
|
|
1729
|
+
- Every scene query reads the subject at its own time. The blur is therefore the same temporal midpoint quadrature as
|
|
1730
|
+
camera rotation (`sensor.temporalSampleCount`, default 8 with a moving subject), and an edge streaks over
|
|
1731
|
+
v·T·m on the sensor (m = v′/D, the thin-lens image distance over the subject distance). With few samples a long streak
|
|
1732
|
+
shows separate copies; raise the count. A test checks the length within sampling error.
|
|
1733
|
+
- A rolling shutter skews a moving subject: each row's exposure window opens later, so it sees the subject later. A test
|
|
1734
|
+
checks the skew against the site windows' start offsets.
|
|
1735
|
+
- Panning: a camera yaw of −v/D rad/s (the engine's rotation convention) follows a subject moving at v m/s in +x. The
|
|
1736
|
+
subject stays sharp and the background streaks.
|
|
1737
|
+
- It combines with `lens.diffraction`, `lens.defocus` (global shutter; their site lattices are formed at each midpoint), the
|
|
1738
|
+
lens projection, distortion and vignetting, and camera rotation. `lens.pupilSampling` is refused.
|
|
1739
|
+
- Display view: sideways motion under a global shutter only. It refuses a rotating subject and a rolling shutter with a
|
|
1740
|
+
reason; `simulateCapture` renders both.
|
|
1741
|
+
- Fast method (2.20.0 convention): with the default count and a still camera, `fast` takes one midpoint per site of the
|
|
1742
|
+
streak plus one when that is fewer than 8 (taps less than one site apart). Exact keeps 8, and an explicit
|
|
1743
|
+
`sensor.temporalSampleCount` always wins. Fast is the default for sRGB samples and the display view, exact for DNG,
|
|
1744
|
+
JPEG and PNG.
|
|
1745
|
+
- Off by default: a request without `motion.subject` is byte-identical to 2.20.0.
|
|
1746
|
+
|
|
1747
|
+
```ts
|
|
1748
|
+
import { simulateCapture } from "@photivra/engine";
|
|
1749
|
+
|
|
1750
|
+
// A subject 4 mm wide moving right at 0.2 m/s, with the camera panning to follow it.
|
|
1751
|
+
const pan = await simulateCapture({
|
|
1752
|
+
scene: { preset: "bar-groups" }, subjectDistanceM: 2, lens: { focalLengthMm: 50 },
|
|
1753
|
+
motion: { angularVelocityRadPerSec: { yaw: -0.1 }, subject: { velocityMPerSec: { x: 0.2 }, region: { centerXM: 0.002, centerYM: 0, widthM: 0.004, heightM: 0.004 } } },
|
|
1754
|
+
output: { width: 32, height: 16 }
|
|
1755
|
+
});
|
|
1756
|
+
console.log(pan.assumptions.find((a) => a.id === "motion.subject")?.value);
|
|
1757
|
+
```
|
|
1758
|
+
|
|
1610
1759
|
## Performance
|
|
1611
1760
|
|
|
1612
1761
|
Almost all of the cost is engine time per sensor site; the facade itself adds little. Since 2.0, the
|
|
@@ -1947,6 +2096,64 @@ developed image in 64-bit floats (24 bytes per pixel, 549 MiB at 24 MP), held as
|
|
|
1947
2096
|
sampled every 50 ms). The extra pass therefore costs about 5 s on one worker after the parts, against about 10 s to render
|
|
1948
2097
|
the whole frame again on one worker.
|
|
1949
2098
|
|
|
2099
|
+
### Exposure build-up (#534)
|
|
2100
|
+
|
|
2101
|
+
`simulateExposureBuildUp(options, { fractions })` renders fractions of one exposure as one accumulating process, the way a
|
|
2102
|
+
camera's live readout of a long exposure shows the light building up. Each fraction is read out and developed as its own
|
|
2103
|
+
photo, and the fraction at 1 is `simulateCapture(options)`, byte for byte (owner decision, 2026-11-06).
|
|
2104
|
+
|
|
2105
|
+
- **Signal.** Each fraction fⱼ below 1 is a capture of the same request in manual mode at the whole exposure's resolved
|
|
2106
|
+
f-number and ISO and the shutter fⱼ·t. So its expected signal at every site is integrated from the spectrum over the window
|
|
2107
|
+
[0, fⱼ·t] by the capture itself. That includes camera rotation, `motion.subject` (#551), mixed lighting (#550, which does not
|
|
2108
|
+
change over time) and, with a rolling shutter, each row's own window. No per-channel signal is precomputed (owner rule).
|
|
2109
|
+
- **Charge.** Photon and dark-charge arrivals are Poisson processes with any rate over time. Given a count n over [0, t], the
|
|
2110
|
+
count over [0, s] is Binomial(n, Λ(s)/Λ(t)), with Λ the expected count (R. G. Gallager, *Discrete Stochastic Processes*,
|
|
2111
|
+
chapter 2, sections 2.4 and 2.5, MIT OpenCourseWare 6.262, free). The whole exposure keeps its ordinary draws. Going down
|
|
2112
|
+
the fractions, each site's photo and dark counts are split: N(fⱼ) ~ Binomial(N(fⱼ₊₁), λ(fⱼ)/λ(fⱼ₊₁)), with λ the site's
|
|
2113
|
+
expected mean in each render (after PRNU and DSNU). As a result:
|
|
2114
|
+
- each fraction's counts are Poisson with that fraction's own mean, which is the mean and variance of a capture at fⱼ·t;
|
|
2115
|
+
- the counts never decrease from one fraction to the next;
|
|
2116
|
+
- two fractions' counts covary by the earlier one's mean.
|
|
2117
|
+
|
|
2118
|
+
The binomial draws are exact: inversion, and Hörmann's BTRS rejection (`src/sensor/binomial-sample.ts`).
|
|
2119
|
+
- **Quadrature.** The windows are nested, so the true means never decrease. The temporal midpoint quadrature can still give an
|
|
2120
|
+
earlier fraction a larger estimate than a later one at a site under motion. There the count is kept (probability 1), and the
|
|
2121
|
+
`exposure.buildUp` assumption counts those sites (`nonMonotoneSites`). Raise `sensor.temporalSampleCount` to remove them.
|
|
2122
|
+
- **Sensor.** Fixed-pattern noise (PRNU, DSNU, hot pixels, offsets) belongs to the sensor and is the same in every fraction.
|
|
2123
|
+
Each fraction's charge is clipped at the full well (`sensor.fullWell`), then read out once: its own read noise (the regime's
|
|
2124
|
+
components; dual gain as the ISO selects), pre-ADC and ADC saturation, and quantization at the ADC bit depth (#555; a #554
|
|
2125
|
+
sensor profile's readout feeds the same stage).
|
|
2126
|
+
- **Cost and settings.** One capture per fraction, plus about 64 bytes per native site for the chain. The request's `fast`
|
|
2127
|
+
and the format default apply to every fraction, and the build-up adds no fast method: with `fast: false` (the calculator's
|
|
2128
|
+
setting) every fraction is an exact capture. `"auto"` white balance is measured on each fraction, as its own photo.
|
|
2129
|
+
- **Limits.** On screen only: formats `"srgb-8"` and `"srgb-16"` (a fraction's JPEG, PNG or DNG is refused). 1 to 64
|
|
2130
|
+
fractions, strictly increasing, above 0 and at most 1. Each fraction's shutter fⱼ·t must be one the body can set. A
|
|
2131
|
+
fraction's realization depends on the whole list, because each step of the chain has its own seeded streams
|
|
2132
|
+
(`EXPOSURE_BUILD_UP_STREAM_BASE`). The same request and list always give the same frames.
|
|
2133
|
+
- **Result.** One frame per fraction: `{ fraction, elapsedSeconds, result }`. Below 1, `result` is the fraction capture's
|
|
2134
|
+
result (`image`, `raw`, `plan` and `request` at fⱼ·t), with the build-up's counts and the assumption `exposure.buildUp`.
|
|
2135
|
+
Its `exposure` and `sensor` are the whole exposure's reports: the camera's settings and noise figure, not the elapsed part's.
|
|
2136
|
+
|
|
2137
|
+
```ts
|
|
2138
|
+
import { simulateExposureBuildUp } from "@photivra/engine";
|
|
2139
|
+
|
|
2140
|
+
const build = await simulateExposureBuildUp({ scene: { preset: "slanted-edge" }, exposure: { mode: "manual", shutterSeconds: 1 / 15, iso: 400 },
|
|
2141
|
+
motion: { angularVelocityRadPerSec: { yaw: 0.2 } }, output: { width: 64, height: 48 } }, { fractions: [0.2, 0.4, 0.6, 0.8, 1] });
|
|
2142
|
+
for (const frame of build.frames) console.log(frame.fraction, frame.elapsedSeconds, frame.result.image.samples.length);
|
|
2143
|
+
```
|
|
2144
|
+
|
|
2145
|
+
The tests are in `test/exposure-build-up.test.ts`:
|
|
2146
|
+
|
|
2147
|
+
- The last fraction equals `simulateCapture` byte for byte: tabulated and lean paths, fixed pattern, dual gain, auto white
|
|
2148
|
+
balance and Auto ISO, camera rotation, rolling shutter, a moving subject and mixed lighting.
|
|
2149
|
+
- Each fraction's mean and variance match a single capture at f·t. Under motion this is checked column by column, and the
|
|
2150
|
+
fraction is shown to differ from the whole exposure scaled by f.
|
|
2151
|
+
- Without read noise the codes never decrease, and Cov(c₁, c₂) = Var(c₁).
|
|
2152
|
+
- Dark frames' read noise is independent between readouts.
|
|
2153
|
+
- A fraction past the full well clips.
|
|
2154
|
+
|
|
2155
|
+
`test/binomial-sample.test.ts` checks the binomial draws with chi-square tests of the probability mass function.
|
|
2156
|
+
|
|
1950
2157
|
### A Print JPEG written in strips
|
|
1951
2158
|
|
|
1952
2159
|
At 1:1 (output size equal to the crop), a Print JPEG's rows can be coded on separate workers.
|