@photivra/engine 2.18.0 → 2.20.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 +179 -1
- package/CITATION.cff +1 -1
- package/NODE_SUPPORT.md +7 -5
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +14 -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/focus-control.js +2 -75
- package/dist/capture/focus-control.js.map +1 -1
- package/dist/capture/native-environment-lean.d.ts +1 -0
- package/dist/capture/native-environment-lean.js +2 -6
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-optical-stage.d.ts +1 -0
- package/dist/capture/native-environment-optical-stage.js +2 -5
- package/dist/capture/native-environment-optical-stage.js.map +1 -1
- package/dist/capture/native-environment-raw.js +1 -5
- package/dist/capture/native-environment-raw.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/release-sequence.js +2 -47
- package/dist/capture/release-sequence.js.map +1 -1
- package/dist/capture/sensor-raw-producer.js +3 -5
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/color/white-balance.d.ts +2 -0
- package/dist/color/white-balance.js +3 -56
- package/dist/color/white-balance.js.map +1 -1
- package/dist/composition/image-formation-plan.d.ts +1 -0
- package/dist/composition/image-formation-plan.js +3 -49
- package/dist/composition/image-formation-plan.js.map +1 -1
- package/dist/core/evidence-provenance.js +1 -16
- package/dist/core/evidence-provenance.js.map +1 -1
- package/dist/core/record-validation.d.ts +54 -0
- package/dist/core/record-validation.js +176 -0
- package/dist/core/record-validation.js.map +1 -1
- package/dist/core/scientific-assurance.js +1 -18
- package/dist/core/scientific-assurance.js.map +1 -1
- package/dist/core/shared-helpers.d.ts +35 -0
- package/dist/core/shared-helpers.js +38 -0
- package/dist/core/shared-helpers.js.map +1 -0
- package/dist/core/spectral-composition.js +1 -36
- package/dist/core/spectral-composition.js.map +1 -1
- package/dist/core/spectral.js +1 -19
- package/dist/core/spectral.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/exposure-capabilities.d.ts +1 -0
- package/dist/equipment/exposure-capabilities.js +2 -36
- package/dist/equipment/exposure-capabilities.js.map +1 -1
- package/dist/equipment/generic-lens-catalogue.d.ts +8 -2
- package/dist/equipment/generic-lens-catalogue.js +31 -2
- package/dist/equipment/generic-lens-catalogue.js.map +1 -1
- package/dist/equipment/generic-tier-assets.js +2 -3
- 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/iso-capabilities.js +2 -49
- package/dist/equipment/iso-capabilities.js.map +1 -1
- package/dist/equipment/metering-capabilities.js +1 -26
- package/dist/equipment/metering-capabilities.js.map +1 -1
- package/dist/equipment/release-capabilities.js +1 -53
- package/dist/equipment/release-capabilities.js.map +1 -1
- package/dist/exposure/auto-iso-slowest-shutter.js +1 -7
- package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -1
- package/dist/exposure/exposure-duration-control.js +1 -16
- package/dist/exposure/exposure-duration-control.js.map +1 -1
- package/dist/exposure/exposure-mode-resolver.js +1 -17
- package/dist/exposure/exposure-mode-resolver.js.map +1 -1
- package/dist/exposure/filtered-exposure-time.d.ts +93 -0
- package/dist/exposure/filtered-exposure-time.js +129 -0
- package/dist/exposure/filtered-exposure-time.js.map +1 -0
- package/dist/exposure/flash-ttl.d.ts +1 -0
- package/dist/exposure/flash-ttl.js +1 -1
- package/dist/exposure/flash-ttl.js.map +1 -1
- package/dist/exposure/flash.js +1 -49
- package/dist/exposure/flash.js.map +1 -1
- package/dist/exposure/metering-scene-radiance.js +1 -25
- package/dist/exposure/metering-scene-radiance.js.map +1 -1
- package/dist/exposure/metering-target.js +1 -30
- package/dist/exposure/metering-target.js.map +1 -1
- package/dist/exposure/metering-temporal.js +1 -8
- package/dist/exposure/metering-temporal.js.map +1 -1
- package/dist/exposure/metering.js +1 -72
- package/dist/exposure/metering.js.map +1 -1
- package/dist/exposure/program-line.js +1 -45
- package/dist/exposure/program-line.js.map +1 -1
- package/dist/facade/develop-joined-parts.d.ts +29 -0
- package/dist/facade/develop-joined-parts.js +33 -0
- package/dist/facade/develop-joined-parts.js.map +1 -0
- package/dist/facade/display-view-gpu.d.ts +7 -4
- 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 +5 -3
- 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 +1 -1
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/fast-methods.d.ts +50 -0
- package/dist/facade/fast-methods.js +50 -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 +6 -3
- package/dist/facade/generic-lens-capture.js +6 -3
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +88 -16
- package/dist/facade/simulate-capture.js +279 -153
- 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 +22 -12
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.js +1 -3
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/chart-radiance-gpu.js +1 -5
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +13 -1
- package/dist/gpu/display-view-quality-gpu.js +4 -8
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.js +3 -25
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/sensor-stage-gpu.js +1 -5
- package/dist/gpu/sensor-stage-gpu.js.map +1 -1
- package/dist/gpu/webgpu-runtime.d.ts +2 -0
- package/dist/gpu/webgpu-runtime.js +3 -0
- package/dist/gpu/webgpu-runtime.js.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/motion/camera-rotation.js +1 -6
- package/dist/motion/camera-rotation.js.map +1 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts +12 -0
- package/dist/motion/capture-rotation-inverse-mapping.js +2 -2
- package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-rotation-temporal-quadrature.js +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -1
- package/dist/motion/capture-rotation-trajectory.js +2 -17
- package/dist/motion/capture-rotation-trajectory.js.map +1 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js +3 -14
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js.map +1 -1
- package/dist/motion/extended-object-projection.js +5 -40
- package/dist/motion/extended-object-projection.js.map +1 -1
- 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/atmospheric-haze.js +1 -7
- package/dist/optics/atmospheric-haze.js.map +1 -1
- package/dist/optics/brown-conrady-distortion.js +1 -7
- package/dist/optics/brown-conrady-distortion.js.map +1 -1
- package/dist/optics/complex-pupil-psf.d.ts +1 -0
- package/dist/optics/complex-pupil-psf.js +2 -84
- package/dist/optics/complex-pupil-psf.js.map +1 -1
- 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/focus-state.js +1 -11
- package/dist/optics/focus-state.js.map +1 -1
- package/dist/optics/front-of-lens-filter.d.ts +5 -0
- package/dist/optics/front-of-lens-filter.js +3 -65
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/generic-lens-psf.d.ts +18 -2
- package/dist/optics/generic-lens-psf.js +25 -2
- package/dist/optics/generic-lens-psf.js.map +1 -1
- package/dist/optics/generic-nd-filter-presets.d.ts +12 -0
- package/dist/optics/generic-nd-filter-presets.js +48 -0
- package/dist/optics/generic-nd-filter-presets.js.map +1 -0
- package/dist/optics/illumination-vignetting.js +1 -6
- package/dist/optics/illumination-vignetting.js.map +1 -1
- package/dist/optics/lens-psf-profile.d.ts +4 -1
- package/dist/optics/lens-psf-profile.js +12 -111
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/longitudinal-chromatic-aberration.js +1 -7
- package/dist/optics/longitudinal-chromatic-aberration.js.map +1 -1
- package/dist/optics/pupil-vignetting.js +1 -7
- package/dist/optics/pupil-vignetting.js.map +1 -1
- package/dist/optics/radial-distortion.js +1 -6
- package/dist/optics/radial-distortion.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.d.ts +13 -0
- package/dist/optics/scene-to-sensor-irradiance.js +11 -96
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/optics/stray-light.d.ts +1 -0
- package/dist/optics/stray-light.js +1 -1
- package/dist/optics/stray-light.js.map +1 -1
- package/dist/optics/zernike-wavefront.js +1 -7
- package/dist/optics/zernike-wavefront.js.map +1 -1
- package/dist/output/capture-geometry.js +1 -8
- package/dist/output/capture-geometry.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 +62 -0
- package/dist/output/developed-lens-corrections.js +135 -0
- package/dist/output/developed-lens-corrections.js.map +1 -0
- package/dist/output/generic-lens-corrections.d.ts +5 -7
- package/dist/output/generic-lens-corrections.js +11 -10
- package/dist/output/generic-lens-corrections.js.map +1 -1
- package/dist/output/geometric-transforms.js +1 -4
- package/dist/output/geometric-transforms.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/native-capture-sdr.d.ts +2 -2
- package/dist/output/native-capture-sdr.js +3 -2
- package/dist/output/native-capture-sdr.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-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/processing/development-detail.d.ts +29 -0
- package/dist/processing/development-detail.js +128 -107
- package/dist/processing/development-detail.js.map +1 -1
- package/dist/schema/illumination-temporal.js +3 -72
- package/dist/schema/illumination-temporal.js.map +1 -1
- package/dist/schema/illumination.d.ts +1 -0
- package/dist/schema/illumination.js +2 -65
- package/dist/schema/illumination.js.map +1 -1
- package/dist/schema/scene-radiance-temporal.js +2 -14
- package/dist/schema/scene-radiance-temporal.js.map +1 -1
- package/dist/schema/scene-radiance.js +2 -60
- package/dist/schema/scene-radiance.js.map +1 -1
- package/dist/schema/validation.d.ts +2 -0
- package/dist/schema/validation.js +2 -17
- package/dist/schema/validation.js.map +1 -1
- package/dist/sensor/accumulated-charge.js +2 -59
- package/dist/sensor/accumulated-charge.js.map +1 -1
- package/dist/sensor/architecture.js +1 -16
- package/dist/sensor/architecture.js.map +1 -1
- package/dist/sensor/camera-saturation-capacity.d.ts +1 -0
- package/dist/sensor/camera-saturation-capacity.js +3 -55
- package/dist/sensor/camera-saturation-capacity.js.map +1 -1
- package/dist/sensor/capture-color-sampling-binding.js +1 -26
- package/dist/sensor/capture-color-sampling-binding.js.map +1 -1
- package/dist/sensor/capture-mode-timing.js +1 -39
- package/dist/sensor/capture-mode-timing.js.map +1 -1
- package/dist/sensor/capture-mode.js +1 -23
- package/dist/sensor/capture-mode.js.map +1 -1
- package/dist/sensor/color-sampling.js +1 -26
- package/dist/sensor/color-sampling.js.map +1 -1
- package/dist/sensor/constant-rate-temporal-integration.js +2 -46
- package/dist/sensor/constant-rate-temporal-integration.js.map +1 -1
- package/dist/sensor/dark-current.js +2 -45
- package/dist/sensor/dark-current.js.map +1 -1
- package/dist/sensor/eqe-electron-rate.js +2 -41
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +7 -0
- package/dist/sensor/exposure-window.js +9 -24
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/iso-gain.js +1 -7
- package/dist/sensor/iso-gain.js.map +1 -1
- package/dist/sensor/iso-signal-chain.js +1 -43
- package/dist/sensor/iso-signal-chain.js.map +1 -1
- package/dist/sensor/optical-stack.js +1 -25
- package/dist/sensor/optical-stack.js.map +1 -1
- package/dist/sensor/photon-energy.js +1 -26
- package/dist/sensor/photon-energy.js.map +1 -1
- package/dist/sensor/physical-charge-capacity.js +3 -77
- package/dist/sensor/physical-charge-capacity.js.map +1 -1
- package/dist/sensor/radiometry-readiness.js +2 -23
- package/dist/sensor/radiometry-readiness.js.map +1 -1
- package/dist/sensor/raw-readout.d.ts +3 -0
- package/dist/sensor/raw-readout.js +4 -66
- package/dist/sensor/raw-readout.js.map +1 -1
- package/dist/sensor/raw-reconstruction.js +2 -64
- package/dist/sensor/raw-reconstruction.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.js +1 -9
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/dist/sensor/readout-timing.js +4 -79
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.d.ts +2 -0
- package/dist/sensor/response-application-compatibility.js +4 -35
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/response-operating-range.d.ts +1 -0
- package/dist/sensor/response-operating-range.js +3 -79
- package/dist/sensor/response-operating-range.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.js +4 -114
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sampling-aperture.js +1 -25
- package/dist/sensor/sampling-aperture.js.map +1 -1
- package/dist/sensor/sensor-characteristics.d.ts +137 -0
- package/dist/sensor/sensor-characteristics.js +115 -0
- package/dist/sensor/sensor-characteristics.js.map +1 -0
- package/dist/sensor/spatial-sample-reduction.js +3 -24
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spatial-sampling-quadrature.js +1 -3
- package/dist/sensor/spatial-sampling-quadrature.js.map +1 -1
- package/dist/sensor/spatio-spectral-reduction.js +1 -18
- package/dist/sensor/spatio-spectral-reduction.js.map +1 -1
- package/dist/sensor/spectral-coverage.d.ts +10 -1
- package/dist/sensor/spectral-coverage.js +1 -1
- package/dist/sensor/spectral-coverage.js.map +1 -1
- package/dist/sensor/spectral-quadrature.js +3 -41
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/spectral-response.js +1 -47
- package/dist/sensor/spectral-response.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/camera-shake.js +1 -6
- package/dist/stabilization/camera-shake.js.map +1 -1
- package/dist/stabilization/system.d.ts +9 -0
- package/dist/stabilization/system.js +7 -86
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +5 -0
- package/docs/API_REFERENCE.md +116 -3
- package/docs/QUICK_START.md +178 -14
- package/docs/USAGE.md +111 -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 +7 -2
- package/docs/api/exports.json +203 -3
- package/docs/api/exposure-filtered-exposure-time.md +105 -0
- package/docs/api/facade-develop-joined-parts.md +32 -0
- package/docs/api/facade-display-view-gpu.md +5 -2
- package/docs/api/facade-fast-methods.md +91 -0
- package/docs/api/facade-simulate-capture.md +72 -16
- package/docs/api/facade-simulate-display-view.md +3 -2
- package/docs/api/optics-aperture-diameter.md +51 -0
- package/docs/api/optics-detail-limit.md +203 -0
- package/docs/api/optics-generic-nd-filter-presets.md +34 -0
- package/docs/api/optics-lens-psf-profile.md +3 -1
- package/docs/api/output-crop-to-match-focal-length.md +67 -0
- package/docs/api/output-developed-lens-corrections.md +12 -0
- package/docs/api/output-generic-lens-corrections.md +3 -10
- package/docs/api/output-lens-corrections.md +11 -1
- package/docs/api/output-print-size-blur-noise.md +115 -0
- package/docs/api/sensor-sensor-characteristics.md +105 -0
- package/llms.txt +5 -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.20.0 / root contract 2.20.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,10 +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) |
|
|
22
|
+
| Shutter time with an ND filter | [`calculateFilteredExposureTime`](api/exposure-filtered-exposure-time.md#calculatefilteredexposuretime) |
|
|
21
23
|
| Diffraction | [`calculateAiryDisk`](api/optics-diffraction.md#calculateairydisk) |
|
|
24
|
+
| Which limits detail: the lens or the sensor | [`calculateDetailLimit`](api/optics-detail-limit.md#calculatedetaillimit) |
|
|
22
25
|
| Sensor signal, noise and SNR | [`calculatePhotoelectrons`](api/sensor-signal-noise.md#calculatephotoelectrons), [`calculateSignalToNoise`](api/sensor-signal-noise.md#calculatesignaltonoise) |
|
|
23
26
|
| Colour temperature | [`calculateChromaticityFromCorrelatedColorTemperature`](api/color-illuminants.md#calculatechromaticityfromcorrelatedcolortemperature), [`calculateCorrelatedColorTemperature`](api/color-illuminants.md#calculatecorrelatedcolortemperature) |
|
|
24
27
|
| White balance from Kelvin and tint | [`createColorTemperatureWhiteBalanceIntent`](api/color-white-balance.md#createcolortemperaturewhitebalanceintent), [`resolveColorTemperatureWhiteBalance`](api/color-white-balance.md#resolvecolortemperaturewhitebalance) |
|
|
@@ -1056,6 +1059,18 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1056
1059
|
| [`RelativeOpticalExposure`](api/exposure-exposure.md#relativeopticalexposure) | Type |
|
|
1057
1060
|
| [`RelativeRenderedExposure`](api/exposure-exposure.md#relativerenderedexposure) | Type |
|
|
1058
1061
|
|
|
1062
|
+
## exposure/filtered-exposure-time.ts
|
|
1063
|
+
|
|
1064
|
+
[Detailed contracts](api/exposure-filtered-exposure-time.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/exposure/filtered-exposure-time.ts)
|
|
1065
|
+
|
|
1066
|
+
| Export | Kind |
|
|
1067
|
+
| --- | --- |
|
|
1068
|
+
| [`calculateFilteredExposureTime`](api/exposure-filtered-exposure-time.md#calculatefilteredexposuretime) | Runtime |
|
|
1069
|
+
| [`CalculateFilteredExposureTimeInput`](api/exposure-filtered-exposure-time.md#calculatefilteredexposuretimeinput) | Type |
|
|
1070
|
+
| [`FILTERED_EXPOSURE_DEFAULT_WAVELENGTH_NANOMETERS`](api/exposure-filtered-exposure-time.md#filtered_exposure_default_wavelength_nanometers) | Runtime |
|
|
1071
|
+
| [`FilteredExposureDialSetting`](api/exposure-filtered-exposure-time.md#filteredexposuredialsetting) | Type |
|
|
1072
|
+
| [`FilteredExposureTime`](api/exposure-filtered-exposure-time.md#filteredexposuretime) | Type |
|
|
1073
|
+
|
|
1059
1074
|
## exposure/flash-ttl.ts
|
|
1060
1075
|
|
|
1061
1076
|
[Detailed contracts](api/exposure-flash-ttl.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/exposure/flash-ttl.ts)
|
|
@@ -1267,6 +1282,14 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1267
1282
|
| [`EvaluateColorPatchReflectanceInput`](api/facade-color-patches.md#evaluatecolorpatchreflectanceinput) | Type |
|
|
1268
1283
|
| [`getColorPatchSet`](api/facade-color-patches.md#getcolorpatchset) | Runtime |
|
|
1269
1284
|
|
|
1285
|
+
## facade/develop-joined-parts.ts
|
|
1286
|
+
|
|
1287
|
+
[Detailed contracts](api/facade-develop-joined-parts.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/facade/develop-joined-parts.ts)
|
|
1288
|
+
|
|
1289
|
+
| Export | Kind |
|
|
1290
|
+
| --- | --- |
|
|
1291
|
+
| [`simulateCaptureFromParts`](api/facade-develop-joined-parts.md#simulatecapturefromparts) | Runtime |
|
|
1292
|
+
|
|
1270
1293
|
## facade/display-view-gpu.ts
|
|
1271
1294
|
|
|
1272
1295
|
[Detailed contracts](api/facade-display-view-gpu.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/facade/display-view-gpu.ts)
|
|
@@ -1291,6 +1314,15 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1291
1314
|
| [`DisplayViewCorrectionStateSet`](api/facade-display-view.md#displayviewcorrectionstateset) | Type |
|
|
1292
1315
|
| [`serializeDisplayViewCorrectionStates`](api/facade-display-view.md#serializedisplayviewcorrectionstates) | Runtime |
|
|
1293
1316
|
|
|
1317
|
+
## facade/fast-methods.ts
|
|
1318
|
+
|
|
1319
|
+
[Detailed contracts](api/facade-fast-methods.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/facade/fast-methods.ts)
|
|
1320
|
+
|
|
1321
|
+
| Export | Kind |
|
|
1322
|
+
| --- | --- |
|
|
1323
|
+
| [`SIMULATE_CAPTURE_FAST_METHODS`](api/facade-fast-methods.md#simulate_capture_fast_methods) | Runtime |
|
|
1324
|
+
| [`SimulateCaptureFastMethod`](api/facade-fast-methods.md#simulatecapturefastmethod) | Type |
|
|
1325
|
+
|
|
1294
1326
|
## facade/scene-radiance.ts
|
|
1295
1327
|
|
|
1296
1328
|
[Detailed contracts](api/facade-scene-radiance.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/facade/scene-radiance.ts)
|
|
@@ -1347,6 +1379,7 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1347
1379
|
| [`SimulateCaptureFastOption`](api/facade-simulate-capture.md#simulatecapturefastoption) | Type |
|
|
1348
1380
|
| [`SimulateCaptureFastReport`](api/facade-simulate-capture.md#simulatecapturefastreport) | Type |
|
|
1349
1381
|
| [`SimulateCaptureLensCatalogueRecord`](api/facade-simulate-capture.md#simulatecapturelenscataloguerecord) | Type |
|
|
1382
|
+
| [`SimulateCaptureLensCorrections`](api/facade-simulate-capture.md#simulatecapturelenscorrections) | Type |
|
|
1350
1383
|
| [`SimulateCaptureLensDistortion`](api/facade-simulate-capture.md#simulatecapturelensdistortion) | Type |
|
|
1351
1384
|
| [`SimulateCaptureMetering`](api/facade-simulate-capture.md#simulatecapturemetering) | Type |
|
|
1352
1385
|
| [`SimulateCaptureMotion`](api/facade-simulate-capture.md#simulatecapturemotion) | Type |
|
|
@@ -1561,6 +1594,16 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1561
1594
|
| [`VIDEO_FRAME_SEQUENCE_VERSION`](api/motion-video-sequence.md#video_frame_sequence_version) | Runtime |
|
|
1562
1595
|
| [`VideoFrameSequence`](api/motion-video-sequence.md#videoframesequence) | Type |
|
|
1563
1596
|
|
|
1597
|
+
## optics/aperture-diameter.ts
|
|
1598
|
+
|
|
1599
|
+
[Detailed contracts](api/optics-aperture-diameter.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/aperture-diameter.ts)
|
|
1600
|
+
|
|
1601
|
+
| Export | Kind |
|
|
1602
|
+
| --- | --- |
|
|
1603
|
+
| [`ApertureDiameter`](api/optics-aperture-diameter.md#aperturediameter) | Type |
|
|
1604
|
+
| [`calculateApertureDiameter`](api/optics-aperture-diameter.md#calculateaperturediameter) | Runtime |
|
|
1605
|
+
| [`CalculateApertureDiameterInput`](api/optics-aperture-diameter.md#calculateaperturediameterinput) | Type |
|
|
1606
|
+
|
|
1564
1607
|
## optics/aperture.ts
|
|
1565
1608
|
|
|
1566
1609
|
[Detailed contracts](api/optics-aperture.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/aperture.ts)
|
|
@@ -1665,6 +1708,25 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1665
1708
|
| [`DefocusCircle`](api/optics-depth-of-field.md#defocuscircle) | Type |
|
|
1666
1709
|
| [`DepthOfField`](api/optics-depth-of-field.md#depthoffield) | Type |
|
|
1667
1710
|
|
|
1711
|
+
## optics/detail-limit.ts
|
|
1712
|
+
|
|
1713
|
+
[Detailed contracts](api/optics-detail-limit.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/detail-limit.ts)
|
|
1714
|
+
|
|
1715
|
+
| Export | Kind |
|
|
1716
|
+
| --- | --- |
|
|
1717
|
+
| [`calculateDetailLimit`](api/optics-detail-limit.md#calculatedetaillimit) | Runtime |
|
|
1718
|
+
| [`CalculateDetailLimitInput`](api/optics-detail-limit.md#calculatedetaillimitinput) | Type |
|
|
1719
|
+
| [`DETAIL_LIMIT_LIMITS`](api/optics-detail-limit.md#detail_limit_limits) | Runtime |
|
|
1720
|
+
| [`DetailLimit`](api/optics-detail-limit.md#detaillimit) | Type |
|
|
1721
|
+
| [`DetailLimitBasis`](api/optics-detail-limit.md#detaillimitbasis) | Type |
|
|
1722
|
+
| [`DetailLimitCatalogueLens`](api/optics-detail-limit.md#detaillimitcataloguelens) | Type |
|
|
1723
|
+
| [`DetailLimitedBy`](api/optics-detail-limit.md#detaillimitedby) | Type |
|
|
1724
|
+
| [`DetailLimitIdealLens`](api/optics-detail-limit.md#detaillimitideallens) | Type |
|
|
1725
|
+
| [`DetailLimitingFactor`](api/optics-detail-limit.md#detaillimitingfactor) | Type |
|
|
1726
|
+
| [`DetailLimitOptics`](api/optics-detail-limit.md#detaillimitoptics) | Type |
|
|
1727
|
+
| [`DetailLimitSampling`](api/optics-detail-limit.md#detaillimitsampling) | Type |
|
|
1728
|
+
| [`DetailLimitSystem`](api/optics-detail-limit.md#detaillimitsystem) | Type |
|
|
1729
|
+
|
|
1668
1730
|
## optics/diffraction-psf-profile.ts
|
|
1669
1731
|
|
|
1670
1732
|
[Detailed contracts](api/optics-diffraction-psf-profile.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/diffraction-psf-profile.ts)
|
|
@@ -1739,6 +1801,16 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
1739
1801
|
| [`resolveFrontOfLensFilterTransmission`](api/optics-front-of-lens-filter.md#resolvefrontoflensfiltertransmission) | Runtime |
|
|
1740
1802
|
| [`ResolveFrontOfLensFilterTransmissionInput`](api/optics-front-of-lens-filter.md#resolvefrontoflensfiltertransmissioninput) | Type |
|
|
1741
1803
|
|
|
1804
|
+
## optics/generic-nd-filter-presets.ts
|
|
1805
|
+
|
|
1806
|
+
[Detailed contracts](api/optics-generic-nd-filter-presets.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/generic-nd-filter-presets.ts)
|
|
1807
|
+
|
|
1808
|
+
| Export | Kind |
|
|
1809
|
+
| --- | --- |
|
|
1810
|
+
| [`GENERIC_ND_FILTER_PROFILES`](api/optics-generic-nd-filter-presets.md#generic_nd_filter_profiles) | Runtime |
|
|
1811
|
+
| [`GENERIC_ND_FILTER_STOPS`](api/optics-generic-nd-filter-presets.md#generic_nd_filter_stops) | Runtime |
|
|
1812
|
+
| [`GenericNdFilterStops`](api/optics-generic-nd-filter-presets.md#genericndfilterstops) | Type |
|
|
1813
|
+
|
|
1742
1814
|
## optics/illumination-vignetting.ts
|
|
1743
1815
|
|
|
1744
1816
|
[Detailed contracts](api/optics-illumination-vignetting.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/illumination-vignetting.ts)
|
|
@@ -2085,6 +2157,16 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
2085
2157
|
| [`CaptureSdrResult`](api/output-capture-sdr.md#capturesdrresult) | Type |
|
|
2086
2158
|
| [`parseCaptureSdrInput`](api/output-capture-sdr.md#parsecapturesdrinput) | Runtime |
|
|
2087
2159
|
|
|
2160
|
+
## output/crop-to-match-focal-length.ts
|
|
2161
|
+
|
|
2162
|
+
[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)
|
|
2163
|
+
|
|
2164
|
+
| Export | Kind |
|
|
2165
|
+
| --- | --- |
|
|
2166
|
+
| [`calculateCropToMatchFocalLength`](api/output-crop-to-match-focal-length.md#calculatecroptomatchfocallength) | Runtime |
|
|
2167
|
+
| [`CalculateCropToMatchFocalLengthInput`](api/output-crop-to-match-focal-length.md#calculatecroptomatchfocallengthinput) | Type |
|
|
2168
|
+
| [`CropToMatchFocalLength`](api/output-crop-to-match-focal-length.md#croptomatchfocallength) | Type |
|
|
2169
|
+
|
|
2088
2170
|
## output/crop.ts
|
|
2089
2171
|
|
|
2090
2172
|
[Detailed contracts](api/output-crop.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/output/crop.ts)
|
|
@@ -2095,6 +2177,14 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
2095
2177
|
| [`CalculateCenteredCropInput`](api/output-crop.md#calculatecenteredcropinput) | Type |
|
|
2096
2178
|
| [`CenteredCrop`](api/output-crop.md#centeredcrop) | Type |
|
|
2097
2179
|
|
|
2180
|
+
## output/developed-lens-corrections.ts
|
|
2181
|
+
|
|
2182
|
+
[Detailed contracts](api/output-developed-lens-corrections.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/output/developed-lens-corrections.ts)
|
|
2183
|
+
|
|
2184
|
+
| Export | Kind |
|
|
2185
|
+
| --- | --- |
|
|
2186
|
+
| [`GENERIC_LENS_CORRECTION_CHANNEL_WAVELENGTHS_NM`](api/output-developed-lens-corrections.md#generic_lens_correction_channel_wavelengths_nm) | Runtime |
|
|
2187
|
+
|
|
2098
2188
|
## output/generic-lens-corrections.ts
|
|
2099
2189
|
|
|
2100
2190
|
[Detailed contracts](api/output-generic-lens-corrections.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/output/generic-lens-corrections.ts)
|
|
@@ -2103,7 +2193,6 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
2103
2193
|
| --- | --- |
|
|
2104
2194
|
| [`createGenericLensCorrectionProfile`](api/output-generic-lens-corrections.md#creategenericlenscorrectionprofile) | Runtime |
|
|
2105
2195
|
| [`CreateGenericLensCorrectionProfileInput`](api/output-generic-lens-corrections.md#creategenericlenscorrectionprofileinput) | Type |
|
|
2106
|
-
| [`GENERIC_LENS_CORRECTION_CHANNEL_WAVELENGTHS_NM`](api/output-generic-lens-corrections.md#generic_lens_correction_channel_wavelengths_nm) | Runtime |
|
|
2107
2196
|
|
|
2108
2197
|
## output/geometric-transforms.ts
|
|
2109
2198
|
|
|
@@ -2277,6 +2366,20 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
2277
2366
|
| [`PrintRegionRaster`](api/output-print-region-statistics.md#printregionraster) | Type |
|
|
2278
2367
|
| [`PrintRegionStatisticsAssessment`](api/output-print-region-statistics.md#printregionstatisticsassessment) | Type |
|
|
2279
2368
|
|
|
2369
|
+
## output/print-size-blur-noise.ts
|
|
2370
|
+
|
|
2371
|
+
[Detailed contracts](api/output-print-size-blur-noise.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/output/print-size-blur-noise.ts)
|
|
2372
|
+
|
|
2373
|
+
| Export | Kind |
|
|
2374
|
+
| --- | --- |
|
|
2375
|
+
| [`calculatePrintSizeLimitWithBlurAndNoise`](api/output-print-size-blur-noise.md#calculateprintsizelimitwithblurandnoise) | Runtime |
|
|
2376
|
+
| [`PrintBlurInput`](api/output-print-size-blur-noise.md#printblurinput) | Type |
|
|
2377
|
+
| [`PrintImageMm`](api/output-print-size-blur-noise.md#printimagemm) | Type |
|
|
2378
|
+
| [`PrintNoiseInput`](api/output-print-size-blur-noise.md#printnoiseinput) | Type |
|
|
2379
|
+
| [`PrintSharpCleanCriterion`](api/output-print-size-blur-noise.md#printsharpcleancriterion) | Type |
|
|
2380
|
+
| [`PrintSizeLimitWithBlurAndNoise`](api/output-print-size-blur-noise.md#printsizelimitwithblurandnoise) | Type |
|
|
2381
|
+
| [`PrintSizeLimitWithBlurAndNoiseInput`](api/output-print-size-blur-noise.md#printsizelimitwithblurandnoiseinput) | Type |
|
|
2382
|
+
|
|
2280
2383
|
## output/sdr-rendering.ts
|
|
2281
2384
|
|
|
2282
2385
|
[Detailed contracts](api/output-sdr-rendering.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/output/sdr-rendering.ts)
|
|
@@ -3085,6 +3188,16 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
|
|
|
3085
3188
|
| [`CalculateSceneSensorEqeTemporalExposureInput`](api/sensor-scene-eqe-temporal-exposure.md#calculatescenesensoreqetemporalexposureinput) | Type |
|
|
3086
3189
|
| [`SceneSensorEqeTemporalExposure`](api/sensor-scene-eqe-temporal-exposure.md#scenesensoreqetemporalexposure) | Type |
|
|
3087
3190
|
|
|
3191
|
+
## sensor/sensor-characteristics.ts
|
|
3192
|
+
|
|
3193
|
+
[Detailed contracts](api/sensor-sensor-characteristics.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/sensor/sensor-characteristics.ts)
|
|
3194
|
+
|
|
3195
|
+
| Export | Kind |
|
|
3196
|
+
| --- | --- |
|
|
3197
|
+
| [`SimulateCaptureNoiseComponents`](api/sensor-sensor-characteristics.md#simulatecapturenoisecomponents) | Type |
|
|
3198
|
+
| [`SimulateCaptureSensorCharacteristics`](api/sensor-sensor-characteristics.md#simulatecapturesensorcharacteristics) | Type |
|
|
3199
|
+
| [`SimulateCaptureSensorReport`](api/sensor-sensor-characteristics.md#simulatecapturesensorreport) | Type |
|
|
3200
|
+
|
|
3088
3201
|
## sensor/sensor-geometry.ts
|
|
3089
3202
|
|
|
3090
3203
|
[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) |
|
|
@@ -104,6 +105,7 @@ modelling choices (such as "no lens PSF") as `kind: "model"`.
|
|
|
104
105
|
| `output.exposureCompensationStops` | 0 | #556: a development exposure push, −2 to +5 stops, on the RAW before white balance (see [Development exposure push](#development-exposure-push-556)). |
|
|
105
106
|
| `output.diffractionCorrection` | off | #552: `{ wavelengthNm?, regularization?, maximumGain?, kernelRadiusPixels? }`, a bounded deconvolution of the diffraction blur; needs `lens.diffraction`. It never restores detail beyond the diffraction cut-off (see [Sharpening and diffraction correction](#sharpening-and-diffraction-correction-552)). |
|
|
106
107
|
| `output.sharpening` | off | #552: `{ radiusPixels?, amount?, threshold? }`, an unsharp mask after the tone curve; sRGB output only (see [Sharpening and diffraction correction](#sharpening-and-diffraction-correction-552)). |
|
|
108
|
+
| `output.lensCorrections` | off | #570, with `lens.catalogue`: `{ distortion?, lateralColor?, vignetting? }`, the lens's own corrections on the developed JPEG, PNG and samples; the DNG is never corrected. Works with `output.region` (see [Generic lens catalogue](#generic-lens-catalogue-549)). |
|
|
107
109
|
| `output.whiteBalance` | `"scene-illuminant"` | Also `"auto"`, `"none"`, `{ kelvin, tint? }` and `{ channelGains }`. |
|
|
108
110
|
| `output.jpegQuantizationStep` | 2 | JPEG only: constant step 1–255, not a manufacturer quality scale. |
|
|
109
111
|
| `sensor.pixelPitchMicrometers` | 6 | 0.5–1000 (2.5; 0.5–100 before). The sensor is `width × pitch` wide (see [Geometry](#geometry)); the ISO readout scales with the pixel area (see [ISO and pixel size](#iso-and-pixel-size)). Above 100 µm the capture is a downsized view of a whole frame (see [Whole-frame views](#whole-frame-views-25)). |
|
|
@@ -116,7 +118,7 @@ modelling choices (such as "no lens PSF") as `kind: "model"`.
|
|
|
116
118
|
| `motion.angularVelocityRadPerSec` | still | `{ pitch?, yaw?, roll? }` in rad/s (see [Motion](#motion)). |
|
|
117
119
|
| `motion.shutter` | `"global"` | Or `"rolling"`. |
|
|
118
120
|
| `motion.rollingShutterSkewSeconds` | the body's readout skew | Rolling only. |
|
|
119
|
-
| `signal`, `onProgress` | none | An `AbortSignal` cancels the running task; `onProgress` reports `raw`, `white-balance`, `development` 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
|
+
| `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. |
|
|
120
122
|
|
|
121
123
|
Unknown fields are rejected, so a typo never silently falls back to a default.
|
|
122
124
|
|
|
@@ -205,11 +207,13 @@ and every number is a labelled approximation.
|
|
|
205
207
|
for the macro); an f-number or distance outside the lens's range is refused.
|
|
206
208
|
- **Its character is rendered:** a field- and wavelength-dependent PSF (diffraction with the lens's Seidel aberrations, axial and
|
|
207
209
|
lateral colour) through the environment PSF quadrature, its radial distortion, its vignetting and, for the fisheyes, the
|
|
208
|
-
equisolid projection (beyond 90° there is no scene, so the 8 mm's circle is black outside). Flare
|
|
209
|
-
|
|
210
|
+
equisolid projection (beyond 90° there is no scene, so the 8 mm's circle is black outside). Flare and focus breathing are
|
|
211
|
+
reported in the assumption `lens.catalogue.character`, not rendered.
|
|
210
212
|
- **Professional lenses are better** where the owner's table says so: sharper centres and corners, less coma, lateral colour,
|
|
211
213
|
distortion and vignetting, better close focus and focus consistency. The measurements are in the catalogue page.
|
|
212
|
-
- **Combinations:** `lens.defocus` convolves the
|
|
214
|
+
- **Combinations:** `lens.defocus` convolves the lens's own bokeh kernel (#567: its blades, its W040 and, on the fast wides
|
|
215
|
+
and normals, a cat's eye, which is lens.catalogue's exact method: on when the request resolves to exact (`fast: false`, the
|
|
216
|
+
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);
|
|
213
217
|
`lens.focusScatter: { seed, shotIndex? }` moves the focus by a seeded autofocus error (`simulateGenericLensFocusError`), off
|
|
214
218
|
by default. `prime`, `focalLengthMm`, `projection`, `distortion`, `vignetting`, `psf`, `diffraction` and `pupilSampling` are
|
|
215
219
|
set by the lens and refused with it. The display view renders `lens.catalogue` since #569, with the PSF taken per field zone
|
|
@@ -217,6 +221,13 @@ and every number is a labelled approximation.
|
|
|
217
221
|
- **Cost:** one scene query per kernel tap through the lens field mapping, like `lens.distortion`: a 48 × 48 region of a full frame
|
|
218
222
|
at 6 µm takes about 1 s with *PV 50 1.2 Pro* and 6 s with *PV 50 1.8* (Apple M5 Pro), against 0.01 s with `lens.prime`. Render
|
|
219
223
|
regions, or use a coarser `sensor.spectralStepNanometers`.
|
|
224
|
+
- **Lens corrections (#570):** `output: { lensCorrections: { distortion: true, lateralColor: true, vignetting: true } }` applies the
|
|
225
|
+
lens's generic correction profile (`createGenericLensCorrectionProfile`) to the developed linear colour, each correction
|
|
226
|
+
switched on separately, as cameras do for their JPEGs. The RAW and the DNG are never corrected. The image keeps its size and is
|
|
227
|
+
magnified just enough to have no missing pixels (`magnification` in the `output.lensCorrections` assumption, 1 for the barrel
|
|
228
|
+
wide angles); vignetting is corrected to a flat field. Regions and parts are byte-identical to the whole frame. The costs are
|
|
229
|
+
real: stretched corners lose resolution and brightened corners are noisier
|
|
230
|
+
([DIGITAL_OPTICS_FOUNDATION.md](https://github.com/Photivra/photivra/blob/main/docs/DIGITAL_OPTICS_FOUNDATION.md#lens-corrections-in-the-development-570)).
|
|
220
231
|
- **Fast method (#568):** `fast: true` (or `lens: { catalogue: { kind: "pv-50-1.8", fast: true } }`) blends the PSF over a field
|
|
221
232
|
grid and tabulates each site's signal, a labeled approximation within 2.3e-4 of the frame's peak signal of the exact method
|
|
222
233
|
(measured): a 768 × 512 whole full frame renders within 2× of the same `lens.prime` capture. It needs a still camera, site-center
|
|
@@ -252,9 +263,20 @@ the crop factor, so a 50 mm lens is 50 mm on full frame and on APS-C, as when a
|
|
|
252
263
|
- **An optional f-number range:** `lens.ideal: { focalLengthMm, widestFNumber, narrowestFNumber }` (either or both, within
|
|
253
264
|
`IDEAL_LENS_LIMITS`, the widest no larger than the narrowest; each defaults to its bound) narrows that range like a real
|
|
254
265
|
lens's: `lens.fNumber` must lie in it, and shutter priority and program choose apertures only in it. The assumption then
|
|
255
|
-
records the range (`{ lensId, focalLengthMm, widestFNumber, narrowestFNumber }`); without it nothing changes.
|
|
256
|
-
the
|
|
257
|
-
range
|
|
266
|
+
records the range (`{ lensId, focalLengthMm, widestFNumber, narrowestFNumber }`); without it nothing changes. A range without
|
|
267
|
+
f/8 takes the reference exposure at its aperture nearest f/8 (the same N²/t). Where that shutter would be shorter than the
|
|
268
|
+
body's shortest (a range narrower than about f/1, such as f/0.5–f/0.9), the anchor takes the shortest shutter instead, a lower
|
|
269
|
+
N²/t that the meter and the exposure modes measure from, so the exposure is the same (#585; refused in every mode before 2.19.0).
|
|
270
|
+
- **Program with a range (#583):** program follows the engine's program line (f/16 1/2000 s … f/8 1/125 s … f/4 1.024 s). A
|
|
271
|
+
range that holds f/4–f/16 keeps it unchanged. Otherwise the line's f/4 and f/16 move to the range (each clamped to it): the
|
|
272
|
+
same shape, with the aperture held at the range's end and the shutter taking up the stops (the same N²/t, so the same
|
|
273
|
+
exposure), still from 1/2000 s to 1.024 s. Beyond the line's ends the resolver holds them, as before (with `iso: "auto"` the
|
|
274
|
+
ISO rises in dim light; with a fixed ISO the capture is under- or overexposed and `exposure.standardExposureDeviationStops`
|
|
275
|
+
says by how much). For example f/8–f/32 gives f/16 1/2000 s … f/16 1/125 s … f/8 1/125 s … f/8 1.024 s. The
|
|
276
|
+
`exposure.programLine` assumption then records the limited line (profile id `"facade-generic-program-line-lens-range"`, with its `nodes`). The same
|
|
277
|
+
applies to the `lens.prime` and `lens.catalogue` ranges that do not hold f/4–f/16 (the 800 mm and 1200 mm-equivalent primes;
|
|
278
|
+
*PV 800 5.6 Pro*, *PV 1200 8 Pro*, *PV 200 5.6*, *PV 300 5.6*, *PV 400 5.6*, *PV 500 5.6*, *PV 600 6.3* and *PV 800 9*),
|
|
279
|
+
which program refused before 2.19.0. An approximation: a generic line, not a manufacturer's program.
|
|
258
280
|
- **The same blur models as `lens.prime`:** `lens.defocus` (the thin-lens blur circle of `calculateDefocusCircle`), `lens.diffraction`
|
|
259
281
|
(the Airy pattern) and `lens.vignetting` (a caller profile). Without them the ideal lens renders sharp and evenly lit. It focuses
|
|
260
282
|
at any distance beyond the focal length (no minimum focus distance; the subject must be at least twice the focal length away, as
|
|
@@ -441,6 +463,73 @@ large-pixel sensor may therefore saturate earlier, and a real small-pixel sensor
|
|
|
441
463
|
given a higher base ISO. When the pitch is not 6 µm, the assumption `sensor.isoAreaNormalization`
|
|
442
464
|
records the area ratio and this approximation.
|
|
443
465
|
|
|
466
|
+
### Sensor characteristics (#555)
|
|
467
|
+
|
|
468
|
+
Each characteristic of the body's sensor can be set on its own under `sensor`. All are off by
|
|
469
|
+
default: a request that sets none is byte-identical to 2.19.0, and every value set is listed in the
|
|
470
|
+
assumption `sensor.characteristics`. The figures under the result's `sensor` are calculated from
|
|
471
|
+
them; they are results, not settings.
|
|
472
|
+
|
|
473
|
+
```ts
|
|
474
|
+
const r = await simulateCapture({ scene: { preset: "uniform" }, sensor: {
|
|
475
|
+
pixelPitchMicrometers: 4,
|
|
476
|
+
peakQuantumEfficiency: 0.8, // green EQE at 555 nm, 0.05–0.9 (default 0.5)
|
|
477
|
+
fullWell: { electrons: 50_000, link: "none" }, // or linked to pixel area (the default)
|
|
478
|
+
readNoise: { lowGainElectrons: 3, highGainElectrons: 1.2, highGainFromIso: 640 },
|
|
479
|
+
readoutSeconds: 0.012, // rolling-shutter skew
|
|
480
|
+
adcBitDepth: 16, // 12, 14 or 16
|
|
481
|
+
fixedPatternNoise: true // the body's synthetic pattern (advanced)
|
|
482
|
+
}, fast: false }); // fast: false computes the mid-gray noise figure
|
|
483
|
+
r.sensor.dynamicRangeStops; r.sensor.midGrey?.snrDecibels;
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
| Option | Range | Default | Effect |
|
|
487
|
+
| --- | --- | --- | --- |
|
|
488
|
+
| `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. |
|
|
489
|
+
| `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. |
|
|
490
|
+
| `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. |
|
|
491
|
+
| `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). |
|
|
492
|
+
| `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. |
|
|
493
|
+
| `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. |
|
|
494
|
+
|
|
495
|
+
How the full well and the ISO rating interact (an approximation, recorded in the assumption): the
|
|
496
|
+
facade keeps each ISO setting's readout regime, so the full well is reached at the white level of
|
|
497
|
+
base ISO and every regime's conversion gain and pre-ADC saturation scale with it (`chargeScale`).
|
|
498
|
+
The output per unit focal-plane exposure H then changes by 2^`sensitivityOffsetStops` =
|
|
499
|
+
QE scale × (pixel area / 36 µm²) × (body full well / full well): the body's rating S = 10/H (CIPA
|
|
500
|
+
DC-004-2020 §3.2) still holds only when that is 1, as it is for a linked full well and the default
|
|
501
|
+
QE. A higher QE makes the same exposure brighter; a larger unlinked full well makes it darker and
|
|
502
|
+
gives more highlight headroom. The high conversion gain's smaller charge storage is not modelled
|
|
503
|
+
when the switch ISO is lowered. The assumption notes a full well outside 200–10 000 e⁻ per µm² of
|
|
504
|
+
pixel area as unusual for the pitch; that is a design range around the tiers' 556–1 667 e⁻/µm² and
|
|
505
|
+
published values such as about 4 000 e⁻/µm² at 2 µm and 1 400 e⁻/µm² at 5.2 µm (Farrell, Xiao &
|
|
506
|
+
Kavusi, *Proc. SPIE* 6069, 2006, Table 1), not a published bound.
|
|
507
|
+
|
|
508
|
+
**Dynamic range** (`sensor.dynamicRangeStops` at the capture's ISO, `sensor.dynamicRangeByIso` for
|
|
509
|
+
every ISO setting of the body): engineering dynamic range log₂(S_sat / σ_floor). S_sat is the charge
|
|
510
|
+
at the RAW white level (the full well over the analog gain, limited by the charge capacity and the
|
|
511
|
+
ADC range) and σ_floor = √(σ_read² + σ_q²), the temporal dark noise of EMVA 1288 Release 4.0 without
|
|
512
|
+
dark current, with σ_q the ADC quantization (1/12 code², plus 1/12 code² of rounding after a digital
|
|
513
|
+
gain) in electrons. With no read noise the range is limited by the ADC alone: log₂((white − black)·√12).
|
|
514
|
+
The Professional tier gives 14.7 stops at ISO 100, 12.7 at ISO 800 (high gain) and 9.7 at ISO 6400;
|
|
515
|
+
the Consumer tier 11.7, 10.0 and 7.0.
|
|
516
|
+
|
|
517
|
+
**Noise figure** (#535, `sensor.midGrey`): computed only when the request resolves to exact (`fast:
|
|
518
|
+
false`, the default for DNG, JPEG and PNG exports; about 0.3 ms); a fast request (the sRGB default)
|
|
519
|
+
omits it. The expected signal-to-noise ratio of an 18 % Lambertian
|
|
520
|
+
gray patch under the request's illuminant and illuminance, at the capture's exposure, ISO and
|
|
521
|
+
sensor, from the engine's own noise model (a model figure, not a measurement). It is the green
|
|
522
|
+
channel next to the optical axis (no vignetting, PSF or motion). `signalElectrons` S is the patch's
|
|
523
|
+
expected charge; `noiseElectrons` splits the noise into photon shot √S, read, dark-current shot
|
|
524
|
+
√(D·t) with D = 1 e⁻/s, ADC quantization and, with `fixedPatternNoise`, the fixed pattern
|
|
525
|
+
√((PRNU·S)² + (DSNU·D·t)² + row² + column²) (hot pixels excluded; a spatial noise, the same in every
|
|
526
|
+
capture), added in quadrature as `total`. `snr` = S / total and `snrDecibels` = 20·log₁₀(snr).
|
|
527
|
+
`clipped` is true when the patch reaches the white level, where the figure no longer describes
|
|
528
|
+
the image. With the defaults (Professional, f/8, 1/125 s, ISO 100, 21 481 lux) S ≈ 7 842 e⁻ and the
|
|
529
|
+
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):
|
|
530
|
+
the photon shot noise grows as √S, so less light means more noise whatever the ISO. The display view
|
|
531
|
+
reports the same `sensor` record as its capture.
|
|
532
|
+
|
|
444
533
|
## Exposure
|
|
445
534
|
|
|
446
535
|
The facade meters the scene like a reflected-light meter:
|
|
@@ -533,7 +622,7 @@ Exposure compensation applies to the meter target first, as with a numeric ISO.
|
|
|
533
622
|
| `manual` | Your aperture and shutter; the ISO makes up the exposure (`resolveManualExposureMode`, automatic ISO). |
|
|
534
623
|
| `aperture-priority` | Your aperture. The shutter follows the meter at the lowest ISO, but no slower than `exposure.autoIso.slowestPreferredShutterSeconds` (required; seconds within the body's shutter range, or `"auto"`, see below); the ISO makes up the rest. At the Auto ISO maximum, `afterMaximumIso` decides: `"allow-slower-shutter"` (the default) lengthens the shutter to reach the target, `"hold-preferred-shutter"` keeps it and leaves the exposure under target (`resolveAperturePriorityAutoIsoExposureMode`). |
|
|
535
624
|
| `shutter-priority` | Your shutter. The aperture is chosen at the lowest ISO, no wider than the target needs, so it stops at the widest aperture; the ISO makes up the rest (`resolveShutterPriorityExposureMode`, policy `minimum-iso-aperture-first`). |
|
|
536
|
-
| `program` | The generic program line at the lowest ISO; beyond the line's end (f/4, 1.024 s) the ISO rises (`resolveProgramAutoExposureMode`, automatic ISO). With `exposure.autoIso.slowestPreferredShutterSeconds` (optional, a number or `"auto"`, #504) the line's shutter is held at it before the ISO rises, and `afterMaximumIso` applies as in aperture priority, never past the line's own shutter. |
|
|
625
|
+
| `program` | The generic program line (limited to the lens's f-number range, #583) at the lowest ISO; beyond the line's end (f/4, 1.024 s) the ISO rises (`resolveProgramAutoExposureMode`, automatic ISO). With `exposure.autoIso.slowestPreferredShutterSeconds` (optional, a number or `"auto"`, #504) the line's shutter is held at it before the ISO rises, and `afterMaximumIso` applies as in aperture priority, never past the line's own shutter. |
|
|
537
626
|
|
|
538
627
|
The result says what happened. `exposure.settings.iso` is the ISO used and `exposure.isoControl` is `"automatic"`.
|
|
539
628
|
`exposure.autoIso` reports `idealIsoBeforeConstraints`, the Auto ISO range (`autoIsoMinimum`, `autoIsoMaximum`),
|
|
@@ -971,10 +1060,14 @@ console.log(result.diagnostics.detail); // { diffractionCorrection: {...}, sharp
|
|
|
971
1060
|
noise; it adds no detail. Not with a wide-gamut `output.colorEncoding` or `output.gamutMapping: "perceptual"`.
|
|
972
1061
|
- **Reported:** the `output.diffractionCorrection` and `output.sharpening` assumptions (settings, cut-off, measured filter
|
|
973
1062
|
response, defaults used), `diagnostics.detail` (ringing, clipping and halo counts) and `diagnostics.options`.
|
|
974
|
-
- **Not combinable** with `output.region`; not offered by `simulateDisplayView` or `simulateIdealReference`.
|
|
975
|
-
|
|
976
|
-
|
|
1063
|
+
- **Not combinable** with `output.region`; not offered by `simulateDisplayView` or `simulateIdealReference`. A capture rendered
|
|
1064
|
+
in region parts takes them through `simulateCaptureFromParts` (#571, [Developing a capture rendered in parts](#developing-a-capture-rendered-in-parts-571)).
|
|
1065
|
+
The DNG holds the RAW codes and is unchanged; only `image.samples` (and the JPEG or PNG made from them) change.
|
|
1066
|
+
- **Cost:** both stages need the whole developed image, as AHD does. At 256 × 256 on an Apple M5 Pro (Node.js 24.19.0) the
|
|
977
1067
|
development took 8 ms by default, 15 ms with sharpening and 18–20 ms with diffraction correction (R = 3–5), one run each.
|
|
1068
|
+
Since #571 they run row by row in place, with the same sums in the same order (the same bytes as 2.18.0): one developed
|
|
1069
|
+
image in memory instead of up to six, and `onProgress` reports each output row as the `diffraction-correction` and
|
|
1070
|
+
`sharpening` stages. At 24 MP see [Developing a capture rendered in parts](#developing-a-capture-rendered-in-parts-571).
|
|
978
1071
|
|
|
979
1072
|
The trade-offs of these and the lens corrections (corner resolution after distortion correction, corner noise after
|
|
980
1073
|
vignetting correction, residual longitudinal CA, halo overshoot, nothing beyond the cut-off) are measured in
|
|
@@ -1070,6 +1163,18 @@ The optics options feed only what the environment site contract accepts:
|
|
|
1070
1163
|
scene; a test checks it to 1e-12 per site. With camera rotation, a projection or distortion, or
|
|
1071
1164
|
vignetting, the per-tap quadrature runs instead (much slower). `request.diffraction` holds the profile,
|
|
1072
1165
|
the equivalent `sampled-local` PSF and which execution ran.
|
|
1166
|
+
- Ties on chart boundaries (2.20.0, #565): the per-tap quadrature reads each tap's scene point at its site-lattice point, as
|
|
1167
|
+
the object-space convolution, the out-of-focus capture and the display view do, so a tap exactly on a chart boundary (a
|
|
1168
|
+
Siemens star's spokes through lattice points) resolves to the same material on every path. With camera rotation under
|
|
1169
|
+
`motion.shutter: "rolling"` every row has its own instants, so the lattice is read once per instant; there reading the
|
|
1170
|
+
lattice is `lens.diffraction`'s exact method and keeping each tap's own point its fast method; the lattice costs about
|
|
1171
|
+
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
|
|
1172
|
+
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
|
|
1173
|
+
DNG, JPEG and PNG; `lens.diffraction: { kind, fast }` or the top-level `fast` wins, and the fast method reports
|
|
1174
|
+
`diagnostics.fast.applied["lens.diffraction"]: true` and the assumption `fast.lens.diffraction`. The two readings differ
|
|
1175
|
+
only at such ties. Region renders joined into one frame (`serializeSimulatedCaptureDngFromParts`,
|
|
1176
|
+
`simulateCaptureFromParts`) match the whole-frame render only if every part resolves `fast` the same way: give the parts
|
|
1177
|
+
and the whole request the same `fast` (a part rendered fast is refused by an exact join).
|
|
1073
1178
|
- The convolution runs in 32-row bands and computes only each band's own values, not the 2R rows and
|
|
1074
1179
|
columns of padding around it (#419; the values are bit-identical to the full-grid convolution's). On a
|
|
1075
1180
|
function scene with the Quality options at 1 µm and f/16 (R 32), 96 × 72, `diagnostics.timingsMs.diffraction`
|
|
@@ -1400,9 +1505,9 @@ lens: { focalLengthMm: 50, fNumber: 4, focusDistanceM: 1.4, defocus: { model: "g
|
|
|
1400
1505
|
combined with `lens.diffraction` (every zone would need its own combined kernel per node). Above a kernel radius of 64
|
|
1401
1506
|
sites it is refused: #564's run convolution takes one kernel per request, and extending it to one kernel per zone is left
|
|
1402
1507
|
for later. `simulateDisplayView` and `prepareDisplayView` refuse it; they render `blades` and `sphericalAberration`.
|
|
1403
|
-
- **With `lens.catalogue` (#549)** the three options are refused by name.
|
|
1404
|
-
own
|
|
1405
|
-
|
|
1508
|
+
- **With `lens.catalogue` (#549)** the three options are refused by name: since 2.20.0 (#567) the catalogue lens sets
|
|
1509
|
+
all three itself (its blades, its own W040 and, on the fast wides and normals, a cat's eye) and folds that kernel into
|
|
1510
|
+
its PSF ([Lens catalogue, Bokeh](https://github.com/Photivra/photivra/blob/main/docs/LENS_CATALOGUE.md#bokeh-567)).
|
|
1406
1511
|
- **Sampling.** Without spherical aberration each site's weight is the exact area of the projected open pupil (a convex
|
|
1407
1512
|
polygon; circles and blade arcs are 1024-gons scaled to their true area, within 5e-6 of the radius of the true curve)
|
|
1408
1513
|
inside the site's cell, divided by its area (`"exact-polygon-cell-area"`). With it the pupil is sampled on a square grid
|
|
@@ -1865,6 +1970,65 @@ const dng = await serializeSimulatedCaptureDngFromParts(dngFrame, parts);
|
|
|
1865
1970
|
console.log(dng.bytes.length);
|
|
1866
1971
|
```
|
|
1867
1972
|
|
|
1973
|
+
### Developing a capture rendered in parts (#571)
|
|
1974
|
+
|
|
1975
|
+
`simulateCaptureFromParts(options, parts)` develops the whole frame of `options` from region renders of the same
|
|
1976
|
+
request. It joins the parts' RAW exactly as `serializeSimulatedCaptureDngFromParts` does (the same parts, the same checks),
|
|
1977
|
+
then develops the joined RAW as `simulateCapture(options)` would, including the steps that filter across the whole image and
|
|
1978
|
+
that a region refuses: `output.diffractionCorrection` and `output.sharpening`. The joined RAW is the whole render's RAW, so the
|
|
1979
|
+
result's `image.samples`, JPEG or PNG bytes, `raw` and `plan` are those of the whole-frame capture, bit for bit. Pass the
|
|
1980
|
+
whole request (no `output.region`); render the parts with the same request plus `output.region`, without the detail stages,
|
|
1981
|
+
`output.dng` and auto white balance (none changes the RAW codes; auto white balance is measured here over the joined frame).
|
|
1982
|
+
`output.lensCorrections` (#570) is honored as in the whole-frame capture, bit for bit; a part may keep or drop it (a corrected
|
|
1983
|
+
region only widens its `region.nativeRect`). The corrections run on the whole developed frame and hold a second developed
|
|
1984
|
+
image while they resample it.
|
|
1985
|
+
|
|
1986
|
+
`onProgress` reports `development`, then `diffraction-correction` and `sharpening` once per output row of the whole image
|
|
1987
|
+
(each stage ends with `completedTileCount === totalTileCount`), then `jpeg`; no `raw` stage, since no RAW is rendered. A host
|
|
1988
|
+
can show these as "Applying diffraction correction to the whole image" and "Applying sharpening to the whole image". The
|
|
1989
|
+
lens corrections run between the two and report no stage of their own.
|
|
1990
|
+
`signal` cancels the step. In the result, `diagnostics.providerEvaluationCount` is 0, `diagnostics.timingsMs` are this call's
|
|
1991
|
+
(`raw` is the join), `diagnostics.fast` and the `raw.*` assumptions of how the RAW was rendered are in the parts' results
|
|
1992
|
+
instead, and a `parts` assumption records the join.
|
|
1993
|
+
|
|
1994
|
+
```ts
|
|
1995
|
+
import { simulateCaptureFromParts, simulateCapture, type SimulateCaptureDngPart, type SimulateCaptureOptions } from "@photivra/engine";
|
|
1996
|
+
|
|
1997
|
+
const whole: SimulateCaptureOptions = { scene: { preset: "slanted-edge" }, lens: { fNumber: 16, diffraction: "circular-aperture" },
|
|
1998
|
+
output: { width: 96, height: 64, format: "jpeg", diffractionCorrection: {}, sharpening: {} } };
|
|
1999
|
+
// Two strips rendered without the whole-image stages (in an application, in separate Web Workers).
|
|
2000
|
+
const parts: SimulateCaptureDngPart[] = await Promise.all([0, 32].map(async (y) => {
|
|
2001
|
+
const part = await simulateCapture({ ...whole, output: { width: 96, height: 64, region: { x: 0, y, width: 96, height: 32 } } });
|
|
2002
|
+
return { raw: part.raw, region: part.region! };
|
|
2003
|
+
}));
|
|
2004
|
+
const developed = await simulateCaptureFromParts({ ...whole, onProgress: ({ stage, completedTileCount, totalTileCount }) => {
|
|
2005
|
+
if (stage === "sharpening") console.log("Applying sharpening to the whole image", completedTileCount / totalTileCount);
|
|
2006
|
+
} }, parts);
|
|
2007
|
+
console.log(developed.image.jpeg!.length); // the bytes of simulateCapture(whole).image.jpeg
|
|
2008
|
+
```
|
|
2009
|
+
|
|
2010
|
+
Tests compare the result with the whole-frame capture byte for byte: JPEG with both stages, 16-bit sRGB with a thresholded
|
|
2011
|
+
mask, AHD with auto white balance, a development push and the four-spot filter, Display P3 PNG with diffraction correction,
|
|
2012
|
+
DNG with both stages, no stage at all, and a catalogue lens with all three lens corrections and sharpening (parts rendered
|
|
2013
|
+
with and without the corrections); and the row-by-row stages against whole-image passes on odd sizes.
|
|
2014
|
+
|
|
2015
|
+
**Measured at 24 MP** (6000 × 4000 at 6 µm, slanted edge at f/8 with `lens.diffraction`, 8 parts; Apple M5 Pro, Node.js 24.19.0,
|
|
2016
|
+
one thread, a shared machine, two runs; `node scripts/benchmark-joined-development.mjs`):
|
|
2017
|
+
|
|
2018
|
+
| Step | Time | Peak memory (process) |
|
|
2019
|
+
| --- | --- | --- |
|
|
2020
|
+
| Join and develop, no detail stage | 1.9–2.2 s (join 0.13–0.15 s) | 532–551 MiB |
|
|
2021
|
+
| … with sharpening (σ = 1) | 3.3–3.7 s (sharpening 1.9–2.1 s) | 1,080 MiB |
|
|
2022
|
+
| … with diffraction correction (R = 3, the default) | 3.7–3.9 s (correction 2.0 s) | 1,079–1,080 MiB |
|
|
2023
|
+
| … with both | 5.1–5.4 s (development 1.2 s, correction 2.0–2.1 s, sharpening 1.7–1.8 s) | 1,079 MiB |
|
|
2024
|
+
| Whole `simulateCapture` with both, for comparison | 10.0–10.4 s (RAW 4.8–4.9 s) | 924 MiB |
|
|
2025
|
+
|
|
2026
|
+
The peak includes the parts' RAW read back (7 bytes per native site) and the joined RAW. The detail stages' share is the one
|
|
2027
|
+
developed image in 64-bit floats (24 bytes per pixel, 549 MiB at 24 MP), held as before by AHD and the wide-gamut paths. In
|
|
2028
|
+
2.18.0 the stages held up to six such images: the same whole capture with both stages peaked at 3,670 MB (resident set
|
|
2029
|
+
sampled every 50 ms). The extra pass therefore costs about 5 s on one worker after the parts, against about 10 s to render
|
|
2030
|
+
the whole frame again on one worker.
|
|
2031
|
+
|
|
1868
2032
|
### A Print JPEG written in strips
|
|
1869
2033
|
|
|
1870
2034
|
At 1:1 (output size equal to the crop), a Print JPEG's rows can be coded on separate workers.
|