@photivra/engine 1.4.0 → 2.0.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 +401 -6
- package/CITATION.cff +1 -1
- package/NODE_SUPPORT.md +64 -12
- package/README.md +301 -182
- package/SECURITY.md +37 -28
- package/THIRD_PARTY.md +148 -4
- package/dist/camera/equivalent-focal-length.d.ts +13 -14
- package/dist/camera/equivalent-focal-length.js +15 -13
- package/dist/camera/equivalent-focal-length.js.map +1 -1
- package/dist/camera/field-of-view.d.ts +30 -19
- package/dist/camera/field-of-view.js +67 -18
- package/dist/camera/field-of-view.js.map +1 -1
- package/dist/camera/lens-projection.d.ts +170 -0
- package/dist/camera/lens-projection.js +444 -0
- package/dist/camera/lens-projection.js.map +1 -0
- package/dist/camera/projected-object-size.d.ts +10 -11
- package/dist/camera/projected-object-size.js +12 -10
- package/dist/camera/projected-object-size.js.map +1 -1
- package/dist/capture/capture-export-metadata.d.ts +9 -10
- package/dist/capture/capture-export-metadata.js +8 -5
- package/dist/capture/capture-export-metadata.js.map +1 -1
- package/dist/capture/dng-import.d.ts +91 -0
- package/dist/capture/dng-import.js +343 -0
- package/dist/capture/dng-import.js.map +1 -0
- package/dist/capture/environment-raw-producer.d.ts +37 -17
- package/dist/capture/environment-raw-producer.js +43 -19
- package/dist/capture/environment-raw-producer.js.map +1 -1
- package/dist/capture/export-jpeg.d.ts +35 -4
- package/dist/capture/export-jpeg.js +133 -47
- package/dist/capture/export-jpeg.js.map +1 -1
- package/dist/capture/export-tiff.d.ts +48 -24
- package/dist/capture/export-tiff.js +91 -31
- package/dist/capture/export-tiff.js.map +1 -1
- package/dist/capture/focus-control.d.ts +42 -65
- package/dist/capture/focus-control.js +56 -75
- package/dist/capture/focus-control.js.map +1 -1
- package/dist/capture/host-yield-cadence.d.ts +25 -0
- package/dist/capture/host-yield-cadence.js +25 -0
- package/dist/capture/host-yield-cadence.js.map +1 -0
- package/dist/capture/linear-encoding.d.ts +14 -12
- package/dist/capture/linear-encoding.js +14 -13
- package/dist/capture/linear-encoding.js.map +1 -1
- package/dist/capture/lossless-jpeg.d.ts +27 -0
- package/dist/capture/lossless-jpeg.js +237 -0
- package/dist/capture/lossless-jpeg.js.map +1 -0
- package/dist/capture/native-environment-lean.d.ts +227 -0
- package/dist/capture/native-environment-lean.js +974 -0
- package/dist/capture/native-environment-lean.js.map +1 -0
- package/dist/capture/native-environment-optical-stage.d.ts +97 -0
- package/dist/capture/native-environment-optical-stage.js +340 -0
- package/dist/capture/native-environment-optical-stage.js.map +1 -0
- package/dist/capture/native-environment-raw.d.ts +140 -6
- package/dist/capture/native-environment-raw.js +435 -34
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/native-raw-development.d.ts +118 -5
- package/dist/capture/native-raw-development.js +224 -59
- package/dist/capture/native-raw-development.js.map +1 -1
- package/dist/capture/native-raw-dng.d.ts +60 -0
- package/dist/capture/native-raw-dng.js +167 -0
- package/dist/capture/native-raw-dng.js.map +1 -0
- package/dist/capture/native-raw.d.ts +67 -10
- package/dist/capture/native-raw.js +90 -24
- package/dist/capture/native-raw.js.map +1 -1
- package/dist/capture/packed-sensor-raw.d.ts +160 -0
- package/dist/capture/packed-sensor-raw.js +221 -0
- package/dist/capture/packed-sensor-raw.js.map +1 -0
- package/dist/capture/photographic-export.d.ts +58 -35
- package/dist/capture/photographic-export.js +177 -70
- package/dist/capture/photographic-export.js.map +1 -1
- package/dist/capture/raw-development-kernel.d.ts +52 -0
- package/dist/capture/raw-development-kernel.js +88 -0
- package/dist/capture/raw-development-kernel.js.map +1 -0
- package/dist/capture/raw-frame-limits.d.ts +7 -7
- package/dist/capture/raw-frame-limits.js +7 -6
- package/dist/capture/raw-frame-limits.js.map +1 -1
- package/dist/capture/raw-frame-reconstruction.d.ts +8 -9
- package/dist/capture/raw-frame-reconstruction.js +9 -8
- package/dist/capture/raw-frame-reconstruction.js.map +1 -1
- package/dist/capture/raw-white-level.d.ts +55 -0
- package/dist/capture/raw-white-level.js +165 -0
- package/dist/capture/raw-white-level.js.map +1 -0
- package/dist/capture/release-sequence.d.ts +5 -7
- package/dist/capture/release-sequence.js +15 -13
- package/dist/capture/release-sequence.js.map +1 -1
- package/dist/capture/sensor-raw-frame.d.ts +5 -6
- package/dist/capture/sensor-raw-frame.js +26 -9
- package/dist/capture/sensor-raw-frame.js.map +1 -1
- package/dist/capture/sensor-raw-producer.d.ts +21 -13
- package/dist/capture/sensor-raw-producer.js +86 -25
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/capture/simulated-capture.d.ts +15 -16
- package/dist/capture/simulated-capture.js +22 -12
- package/dist/capture/simulated-capture.js.map +1 -1
- package/dist/color/camera-color-matrix.d.ts +69 -0
- package/dist/color/camera-color-matrix.js +132 -0
- package/dist/color/camera-color-matrix.js.map +1 -0
- package/dist/color/capture-color.d.ts +17 -10
- package/dist/color/capture-color.js +50 -17
- package/dist/color/capture-color.js.map +1 -1
- package/dist/color/chromatic-adaptation.d.ts +63 -0
- package/dist/color/chromatic-adaptation.js +91 -0
- package/dist/color/chromatic-adaptation.js.map +1 -0
- package/dist/color/color-difference.d.ts +104 -0
- package/dist/color/color-difference.js +205 -0
- package/dist/color/color-difference.js.map +1 -0
- package/dist/color/color-matching-functions.d.ts +168 -0
- package/dist/color/color-matching-functions.js +309 -0
- package/dist/color/color-matching-functions.js.map +1 -0
- package/dist/color/colorimetry-math.d.ts +52 -0
- package/dist/color/colorimetry-math.js +144 -0
- package/dist/color/colorimetry-math.js.map +1 -0
- package/dist/color/gamut-mapping.d.ts +54 -0
- package/dist/color/gamut-mapping.js +107 -0
- package/dist/color/gamut-mapping.js.map +1 -0
- package/dist/color/illuminants.d.ts +182 -0
- package/dist/color/illuminants.js +434 -0
- package/dist/color/illuminants.js.map +1 -0
- package/dist/color/rgb-color-spaces.d.ts +79 -0
- package/dist/color/rgb-color-spaces.js +115 -0
- package/dist/color/rgb-color-spaces.js.map +1 -0
- package/dist/color/sensor-color-development.d.ts +33 -11
- package/dist/color/sensor-color-development.js +104 -30
- package/dist/color/sensor-color-development.js.map +1 -1
- package/dist/color/srgb-icc.d.ts +9 -2
- package/dist/color/srgb-icc.js +16 -5
- package/dist/color/srgb-icc.js.map +1 -1
- package/dist/color/srgb-transfer.d.ts +1 -2
- package/dist/color/srgb-transfer.js +1 -1
- package/dist/color/srgb-transfer.js.map +1 -1
- package/dist/color/white-balance.d.ts +68 -19
- package/dist/color/white-balance.js +168 -35
- package/dist/color/white-balance.js.map +1 -1
- package/dist/composition/image-formation-plan.d.ts +152 -128
- package/dist/composition/image-formation-plan.js +292 -138
- package/dist/composition/image-formation-plan.js.map +1 -1
- package/dist/composition/plan-consumer.d.ts +6 -7
- package/dist/composition/plan-consumer.js +14 -11
- package/dist/composition/plan-consumer.js.map +1 -1
- package/dist/core/calculation-result.d.ts +21 -14
- package/dist/core/calculation-result.js +209 -11
- package/dist/core/calculation-result.js.map +1 -1
- package/dist/core/canonical-json.d.ts +13 -8
- package/dist/core/canonical-json.js +34 -15
- package/dist/core/canonical-json.js.map +1 -1
- package/dist/core/configuration-error.d.ts +5 -4
- package/dist/core/configuration-error.js +5 -3
- package/dist/core/configuration-error.js.map +1 -1
- package/dist/core/evidence-provenance.d.ts +12 -12
- package/dist/core/evidence-provenance.js +10 -9
- package/dist/core/evidence-provenance.js.map +1 -1
- package/dist/core/image-formation.d.ts +11 -10
- package/dist/core/image-formation.js +11 -9
- package/dist/core/image-formation.js.map +1 -1
- package/dist/core/owned-data.d.ts +9 -17
- package/dist/core/owned-data.js +9 -16
- package/dist/core/owned-data.js.map +1 -1
- package/dist/core/portable-math.d.ts +15 -0
- package/dist/core/portable-math.js +56 -0
- package/dist/core/portable-math.js.map +1 -0
- package/dist/core/record-validation.d.ts +48 -9
- package/dist/core/record-validation.js +93 -19
- package/dist/core/record-validation.js.map +1 -1
- package/dist/core/scientific-assurance.d.ts +16 -14
- package/dist/core/scientific-assurance.js +22 -18
- package/dist/core/scientific-assurance.js.map +1 -1
- package/dist/core/spectral-composition.d.ts +13 -14
- package/dist/core/spectral-composition.js +30 -27
- package/dist/core/spectral-composition.js.map +1 -1
- package/dist/core/spectral.d.ts +5 -6
- package/dist/core/spectral.js +9 -7
- package/dist/core/spectral.js.map +1 -1
- package/dist/core/validation.d.ts +3 -6
- package/dist/core/validation.js +3 -5
- package/dist/core/validation.js.map +1 -1
- package/dist/core/version.d.ts +6 -6
- package/dist/core/version.js +6 -5
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/exposure-capabilities.d.ts +10 -10
- package/dist/equipment/exposure-capabilities.js +40 -30
- package/dist/equipment/exposure-capabilities.js.map +1 -1
- package/dist/equipment/generic-tier-assets.d.ts +13 -6
- package/dist/equipment/generic-tier-assets.js +34 -15
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/generic-tier-presets.d.ts +5 -6
- package/dist/equipment/generic-tier-presets.js +15 -13
- package/dist/equipment/generic-tier-presets.js.map +1 -1
- package/dist/equipment/iso-capabilities.d.ts +21 -22
- package/dist/equipment/iso-capabilities.js +49 -44
- package/dist/equipment/iso-capabilities.js.map +1 -1
- package/dist/equipment/metering-capabilities.d.ts +5 -6
- package/dist/equipment/metering-capabilities.js +22 -19
- package/dist/equipment/metering-capabilities.js.map +1 -1
- package/dist/equipment/release-capabilities.d.ts +3 -4
- package/dist/equipment/release-capabilities.js +18 -14
- package/dist/equipment/release-capabilities.js.map +1 -1
- package/dist/exposure/exposure-duration-control.d.ts +19 -17
- package/dist/exposure/exposure-duration-control.js +27 -23
- package/dist/exposure/exposure-duration-control.js.map +1 -1
- package/dist/exposure/exposure-mode-resolver.d.ts +42 -39
- package/dist/exposure/exposure-mode-resolver.js +127 -82
- package/dist/exposure/exposure-mode-resolver.js.map +1 -1
- package/dist/exposure/exposure.d.ts +17 -16
- package/dist/exposure/exposure.js +22 -15
- package/dist/exposure/exposure.js.map +1 -1
- package/dist/exposure/flash-ttl.d.ts +135 -0
- package/dist/exposure/flash-ttl.js +193 -0
- package/dist/exposure/flash-ttl.js.map +1 -0
- package/dist/exposure/flash.d.ts +144 -36
- package/dist/exposure/flash.js +259 -59
- package/dist/exposure/flash.js.map +1 -1
- package/dist/exposure/metering-scene-radiance.d.ts +10 -10
- package/dist/exposure/metering-scene-radiance.js +42 -23
- package/dist/exposure/metering-scene-radiance.js.map +1 -1
- package/dist/exposure/metering-target.d.ts +8 -8
- package/dist/exposure/metering-target.js +30 -20
- package/dist/exposure/metering-target.js.map +1 -1
- package/dist/exposure/metering-temporal.d.ts +16 -15
- package/dist/exposure/metering-temporal.js +41 -19
- package/dist/exposure/metering-temporal.js.map +1 -1
- package/dist/exposure/metering.d.ts +64 -17
- package/dist/exposure/metering.js +159 -30
- package/dist/exposure/metering.js.map +1 -1
- package/dist/exposure/program-line.d.ts +5 -5
- package/dist/exposure/program-line.js +20 -13
- package/dist/exposure/program-line.js.map +1 -1
- package/dist/facade/camera-preset.d.ts +8 -0
- package/dist/facade/camera-preset.js +102 -0
- package/dist/facade/camera-preset.js.map +1 -0
- package/dist/facade/chart-radiance-batch.d.ts +57 -0
- package/dist/facade/chart-radiance-batch.js +121 -0
- package/dist/facade/chart-radiance-batch.js.map +1 -0
- package/dist/facade/chart-scenes.d.ts +177 -0
- package/dist/facade/chart-scenes.js +232 -0
- package/dist/facade/chart-scenes.js.map +1 -0
- package/dist/facade/host-yield.d.ts +7 -0
- package/dist/facade/host-yield.js +23 -0
- package/dist/facade/host-yield.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +117 -0
- package/dist/facade/scene-radiance.js +205 -0
- package/dist/facade/scene-radiance.js.map +1 -0
- package/dist/facade/simulate-capture.d.ts +284 -0
- package/dist/facade/simulate-capture.js +1026 -0
- package/dist/facade/simulate-capture.js.map +1 -0
- package/dist/gpu/chart-radiance-gpu.d.ts +17 -0
- package/dist/gpu/chart-radiance-gpu.js +176 -0
- package/dist/gpu/chart-radiance-gpu.js.map +1 -0
- package/dist/gpu/image-kernel-accelerator.d.ts +132 -0
- package/dist/gpu/image-kernel-accelerator.js +720 -0
- package/dist/gpu/image-kernel-accelerator.js.map +1 -0
- package/dist/gpu/image-kernel-execution.d.ts +92 -0
- package/dist/gpu/image-kernel-execution.js +84 -0
- package/dist/gpu/image-kernel-execution.js.map +1 -0
- package/dist/gpu/sensor-stage-gpu.d.ts +44 -0
- package/dist/gpu/sensor-stage-gpu.js +317 -0
- package/dist/gpu/sensor-stage-gpu.js.map +1 -0
- package/dist/gpu/temporal-sum-gpu.d.ts +23 -0
- package/dist/gpu/temporal-sum-gpu.js +150 -0
- package/dist/gpu/temporal-sum-gpu.js.map +1 -0
- package/dist/gpu/webgpu-runtime.d.ts +63 -0
- package/dist/gpu/webgpu-runtime.js +215 -0
- package/dist/gpu/webgpu-runtime.js.map +1 -0
- package/dist/gpu/wgsl-chart-kernel.d.ts +30 -0
- package/dist/gpu/wgsl-chart-kernel.js +165 -0
- package/dist/gpu/wgsl-chart-kernel.js.map +1 -0
- package/dist/gpu/wgsl-kernels.d.ts +53 -0
- package/dist/gpu/wgsl-kernels.js +365 -0
- package/dist/gpu/wgsl-kernels.js.map +1 -0
- package/dist/gpu/wgsl-sensor-kernel.d.ts +64 -0
- package/dist/gpu/wgsl-sensor-kernel.js +409 -0
- package/dist/gpu/wgsl-sensor-kernel.js.map +1 -0
- package/dist/index.d.ts +89 -25
- package/dist/index.js +59 -15
- package/dist/index.js.map +1 -1
- package/dist/motion/camera-rotation.d.ts +92 -40
- package/dist/motion/camera-rotation.js +84 -47
- package/dist/motion/camera-rotation.js.map +1 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts +37 -34
- package/dist/motion/capture-rotation-inverse-mapping.js +32 -24
- package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts +39 -35
- package/dist/motion/capture-rotation-temporal-quadrature.js +37 -28
- package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -1
- package/dist/motion/capture-rotation-trajectory.d.ts +32 -28
- package/dist/motion/capture-rotation-trajectory.js +36 -26
- package/dist/motion/capture-rotation-trajectory.js.map +1 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts +23 -21
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js +33 -14
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js.map +1 -1
- package/dist/motion/extended-object-projection.d.ts +19 -16
- package/dist/motion/extended-object-projection.js +38 -18
- package/dist/motion/extended-object-projection.js.map +1 -1
- package/dist/motion/projected-motion.d.ts +18 -17
- package/dist/motion/projected-motion.js +25 -17
- package/dist/motion/projected-motion.js.map +1 -1
- package/dist/motion/temporal-exposure-sum.d.ts +55 -0
- package/dist/motion/temporal-exposure-sum.js +141 -0
- package/dist/motion/temporal-exposure-sum.js.map +1 -0
- package/dist/motion/video-sequence.d.ts +111 -0
- package/dist/motion/video-sequence.js +179 -0
- package/dist/motion/video-sequence.js.map +1 -0
- package/dist/optics/aperture.d.ts +14 -15
- package/dist/optics/aperture.js +13 -11
- package/dist/optics/aperture.js.map +1 -1
- package/dist/optics/atmospheric-haze.d.ts +83 -0
- package/dist/optics/atmospheric-haze.js +113 -0
- package/dist/optics/atmospheric-haze.js.map +1 -0
- package/dist/optics/brown-conrady-distortion.d.ts +116 -0
- package/dist/optics/brown-conrady-distortion.js +291 -0
- package/dist/optics/brown-conrady-distortion.js.map +1 -0
- package/dist/optics/circle-of-confusion.d.ts +10 -10
- package/dist/optics/circle-of-confusion.js +15 -11
- package/dist/optics/circle-of-confusion.js.map +1 -1
- package/dist/optics/complex-pupil-psf.d.ts +64 -33
- package/dist/optics/complex-pupil-psf.js +190 -98
- package/dist/optics/complex-pupil-psf.js.map +1 -1
- package/dist/optics/depth-of-field.d.ts +25 -15
- package/dist/optics/depth-of-field.js +67 -27
- package/dist/optics/depth-of-field.js.map +1 -1
- package/dist/optics/diffraction.d.ts +14 -13
- package/dist/optics/diffraction.js +14 -10
- package/dist/optics/diffraction.js.map +1 -1
- package/dist/optics/focus-breathing.d.ts +88 -27
- package/dist/optics/focus-breathing.js +114 -23
- package/dist/optics/focus-breathing.js.map +1 -1
- package/dist/optics/focus-state.d.ts +18 -18
- package/dist/optics/focus-state.js +21 -15
- package/dist/optics/focus-state.js.map +1 -1
- package/dist/optics/front-of-lens-filter.d.ts +45 -14
- package/dist/optics/front-of-lens-filter.js +259 -88
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/illumination-vignetting.d.ts +16 -17
- package/dist/optics/illumination-vignetting.js +40 -17
- package/dist/optics/illumination-vignetting.js.map +1 -1
- package/dist/optics/irradiance-convolution.d.ts +59 -0
- package/dist/optics/irradiance-convolution.js +138 -0
- package/dist/optics/irradiance-convolution.js.map +1 -0
- package/dist/optics/lateral-chromatic-aberration.d.ts +33 -30
- package/dist/optics/lateral-chromatic-aberration.js +33 -23
- package/dist/optics/lateral-chromatic-aberration.js.map +1 -1
- package/dist/optics/lens-psf-kernels.d.ts +89 -0
- package/dist/optics/lens-psf-kernels.js +175 -0
- package/dist/optics/lens-psf-kernels.js.map +1 -0
- package/dist/optics/lens-psf-profile.d.ts +78 -46
- package/dist/optics/lens-psf-profile.js +335 -124
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/longitudinal-chromatic-aberration.d.ts +102 -0
- package/dist/optics/longitudinal-chromatic-aberration.js +210 -0
- package/dist/optics/longitudinal-chromatic-aberration.js.map +1 -0
- package/dist/optics/polygon-diffraction.d.ts +80 -23
- package/dist/optics/polygon-diffraction.js +130 -25
- package/dist/optics/polygon-diffraction.js.map +1 -1
- package/dist/optics/profile-contract.d.ts +5 -6
- package/dist/optics/profile-contract.js +14 -11
- package/dist/optics/profile-contract.js.map +1 -1
- package/dist/optics/psf-foundation.d.ts +23 -23
- package/dist/optics/psf-foundation.js +24 -21
- package/dist/optics/psf-foundation.js.map +1 -1
- package/dist/optics/pupil-vignetting.d.ts +118 -0
- package/dist/optics/pupil-vignetting.js +264 -0
- package/dist/optics/pupil-vignetting.js.map +1 -0
- package/dist/optics/radial-distortion.d.ts +34 -33
- package/dist/optics/radial-distortion.js +37 -30
- package/dist/optics/radial-distortion.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.d.ts +47 -33
- package/dist/optics/scene-to-sensor-irradiance.js +73 -45
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/optics/scene-to-sensor-quadrature.d.ts +23 -18
- package/dist/optics/scene-to-sensor-quadrature.js +16 -11
- package/dist/optics/scene-to-sensor-quadrature.js.map +1 -1
- package/dist/optics/sensor-aperture-rays.d.ts +20 -4
- package/dist/optics/sensor-aperture-rays.js +32 -14
- package/dist/optics/sensor-aperture-rays.js.map +1 -1
- package/dist/optics/sensor-environment-query.d.ts +81 -16
- package/dist/optics/sensor-environment-query.js +145 -12
- package/dist/optics/sensor-environment-query.js.map +1 -1
- package/dist/optics/sensor-psf-quadrature.d.ts +12 -10
- package/dist/optics/sensor-psf-quadrature.js +18 -11
- package/dist/optics/sensor-psf-quadrature.js.map +1 -1
- package/dist/optics/sensor-psf-support.d.ts +8 -6
- package/dist/optics/sensor-psf-support.js +8 -5
- package/dist/optics/sensor-psf-support.js.map +1 -1
- package/dist/optics/stray-light.d.ts +22 -19
- package/dist/optics/stray-light.js +18 -12
- package/dist/optics/stray-light.js.map +1 -1
- package/dist/optics/thin-lens.d.ts +10 -9
- package/dist/optics/thin-lens.js +12 -8
- package/dist/optics/thin-lens.js.map +1 -1
- package/dist/optics/zernike-wavefront.d.ts +154 -0
- package/dist/optics/zernike-wavefront.js +352 -0
- package/dist/optics/zernike-wavefront.js.map +1 -0
- package/dist/output/capture-corrected-sdr.d.ts +16 -8
- package/dist/output/capture-corrected-sdr.js +16 -8
- package/dist/output/capture-corrected-sdr.js.map +1 -1
- package/dist/output/capture-geometry.d.ts +34 -36
- package/dist/output/capture-geometry.js +52 -32
- package/dist/output/capture-geometry.js.map +1 -1
- package/dist/output/capture-sdr.d.ts +7 -6
- package/dist/output/capture-sdr.js +11 -8
- package/dist/output/capture-sdr.js.map +1 -1
- package/dist/output/crop.d.ts +22 -6
- package/dist/output/crop.js +40 -6
- package/dist/output/crop.js.map +1 -1
- package/dist/output/geometric-transforms.d.ts +60 -23
- package/dist/output/geometric-transforms.js +111 -24
- package/dist/output/geometric-transforms.js.map +1 -1
- package/dist/output/lens-corrections.d.ts +27 -19
- package/dist/output/lens-corrections.js +29 -13
- package/dist/output/lens-corrections.js.map +1 -1
- package/dist/output/native-capture-sdr.d.ts +71 -16
- package/dist/output/native-capture-sdr.js +190 -33
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/output/png-encoder.d.ts +65 -0
- package/dist/output/png-encoder.js +461 -0
- package/dist/output/png-encoder.js.map +1 -0
- package/dist/output/print-contrast-reference.d.ts +10 -9
- package/dist/output/print-contrast-reference.js +10 -8
- package/dist/output/print-contrast-reference.js.map +1 -1
- package/dist/output/print-detail.d.ts +18 -17
- package/dist/output/print-detail.js +12 -10
- package/dist/output/print-detail.js.map +1 -1
- package/dist/output/print-jpeg.d.ts +26 -5
- package/dist/output/print-jpeg.js +117 -50
- package/dist/output/print-jpeg.js.map +1 -1
- package/dist/output/print-plan.d.ts +19 -19
- package/dist/output/print-plan.js +11 -10
- package/dist/output/print-plan.js.map +1 -1
- package/dist/output/print-region-statistics.d.ts +14 -15
- package/dist/output/print-region-statistics.js +11 -11
- package/dist/output/print-region-statistics.js.map +1 -1
- package/dist/output/sdr-rendering.d.ts +48 -10
- package/dist/output/sdr-rendering.js +114 -25
- package/dist/output/sdr-rendering.js.map +1 -1
- package/dist/output/subject-framing-crop.d.ts +6 -10
- package/dist/output/subject-framing-crop.js +23 -13
- package/dist/output/subject-framing-crop.js.map +1 -1
- package/dist/processing/demosaic.d.ts +90 -0
- package/dist/processing/demosaic.js +275 -0
- package/dist/processing/demosaic.js.map +1 -0
- package/dist/processing/denoise.d.ts +68 -0
- package/dist/processing/denoise.js +214 -0
- package/dist/processing/denoise.js.map +1 -0
- package/dist/processing/focus-stacking.d.ts +17 -0
- package/dist/processing/focus-stacking.js +80 -0
- package/dist/processing/focus-stacking.js.map +1 -0
- package/dist/processing/hdr.d.ts +54 -0
- package/dist/processing/hdr.js +172 -0
- package/dist/processing/hdr.js.map +1 -0
- package/dist/processing/image-ops.d.ts +66 -0
- package/dist/processing/image-ops.js +192 -0
- package/dist/processing/image-ops.js.map +1 -0
- package/dist/processing/panorama.d.ts +51 -0
- package/dist/processing/panorama.js +305 -0
- package/dist/processing/panorama.js.map +1 -0
- package/dist/processing/processing-task.d.ts +85 -0
- package/dist/processing/processing-task.js +164 -0
- package/dist/processing/processing-task.js.map +1 -0
- package/dist/processing/tone-mapping.d.ts +69 -0
- package/dist/processing/tone-mapping.js +310 -0
- package/dist/processing/tone-mapping.js.map +1 -0
- package/dist/schema/camera.d.ts +5 -4
- package/dist/schema/illumination-spectral.d.ts +13 -19
- package/dist/schema/illumination-spectral.js +23 -19
- package/dist/schema/illumination-spectral.js.map +1 -1
- package/dist/schema/illumination-temporal.d.ts +12 -15
- package/dist/schema/illumination-temporal.js +43 -28
- package/dist/schema/illumination-temporal.js.map +1 -1
- package/dist/schema/illumination.d.ts +5 -4
- package/dist/schema/illumination.js +55 -20
- package/dist/schema/illumination.js.map +1 -1
- package/dist/schema/scene-radiance-temporal.d.ts +9 -11
- package/dist/schema/scene-radiance-temporal.js +26 -23
- package/dist/schema/scene-radiance-temporal.js.map +1 -1
- package/dist/schema/scene-radiance.d.ts +17 -17
- package/dist/schema/scene-radiance.js +56 -34
- package/dist/schema/scene-radiance.js.map +1 -1
- package/dist/schema/scene.d.ts +14 -13
- package/dist/schema/validation.d.ts +0 -1
- package/dist/schema/validation.js +17 -15
- package/dist/schema/validation.js.map +1 -1
- package/dist/sensor/accumulated-charge.d.ts +45 -64
- package/dist/sensor/accumulated-charge.js +41 -47
- package/dist/sensor/accumulated-charge.js.map +1 -1
- package/dist/sensor/architecture.d.ts +22 -25
- package/dist/sensor/architecture.js +17 -16
- package/dist/sensor/architecture.js.map +1 -1
- package/dist/sensor/camera-saturation-capacity.d.ts +21 -28
- package/dist/sensor/camera-saturation-capacity.js +36 -34
- package/dist/sensor/camera-saturation-capacity.js.map +1 -1
- package/dist/sensor/capture-color-sampling-binding.d.ts +46 -51
- package/dist/sensor/capture-color-sampling-binding.js +39 -41
- package/dist/sensor/capture-color-sampling-binding.js.map +1 -1
- package/dist/sensor/capture-mode-timing.d.ts +8 -9
- package/dist/sensor/capture-mode-timing.js +24 -21
- package/dist/sensor/capture-mode-timing.js.map +1 -1
- package/dist/sensor/capture-mode.d.ts +28 -30
- package/dist/sensor/capture-mode.js +33 -31
- package/dist/sensor/capture-mode.js.map +1 -1
- package/dist/sensor/color-sampling.d.ts +30 -33
- package/dist/sensor/color-sampling.js +32 -37
- package/dist/sensor/color-sampling.js.map +1 -1
- package/dist/sensor/constant-rate-temporal-integration.d.ts +19 -23
- package/dist/sensor/constant-rate-temporal-integration.js +28 -26
- package/dist/sensor/constant-rate-temporal-integration.js.map +1 -1
- package/dist/sensor/dark-current.d.ts +53 -49
- package/dist/sensor/dark-current.js +87 -46
- package/dist/sensor/dark-current.js.map +1 -1
- package/dist/sensor/environment-photo-signal.d.ts +71 -30
- package/dist/sensor/environment-photo-signal.js +127 -46
- package/dist/sensor/environment-photo-signal.js.map +1 -1
- package/dist/sensor/eqe-electron-rate.d.ts +14 -13
- package/dist/sensor/eqe-electron-rate.js +34 -14
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/eqe-local-exposure.d.ts +24 -24
- package/dist/sensor/eqe-local-exposure.js +15 -11
- package/dist/sensor/eqe-local-exposure.js.map +1 -1
- package/dist/sensor/eqe-temporal-exposure.d.ts +11 -11
- package/dist/sensor/eqe-temporal-exposure.js +15 -10
- package/dist/sensor/eqe-temporal-exposure.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +48 -34
- package/dist/sensor/exposure-window.js +77 -36
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/fixed-pattern-noise.d.ts +108 -0
- package/dist/sensor/fixed-pattern-noise.js +166 -0
- package/dist/sensor/fixed-pattern-noise.js.map +1 -0
- package/dist/sensor/iso-gain.d.ts +44 -0
- package/dist/sensor/iso-gain.js +119 -0
- package/dist/sensor/iso-gain.js.map +1 -0
- package/dist/sensor/iso-signal-chain.d.ts +25 -48
- package/dist/sensor/iso-signal-chain.js +52 -66
- package/dist/sensor/iso-signal-chain.js.map +1 -1
- package/dist/sensor/local-exposure-binding.d.ts +21 -21
- package/dist/sensor/local-exposure-binding.js +22 -18
- package/dist/sensor/local-exposure-binding.js.map +1 -1
- package/dist/sensor/optical-stack.d.ts +36 -40
- package/dist/sensor/optical-stack.js +34 -37
- package/dist/sensor/optical-stack.js.map +1 -1
- package/dist/sensor/photon-energy.d.ts +22 -28
- package/dist/sensor/photon-energy.js +42 -34
- package/dist/sensor/photon-energy.js.map +1 -1
- package/dist/sensor/physical-charge-capacity.d.ts +20 -30
- package/dist/sensor/physical-charge-capacity.js +35 -36
- package/dist/sensor/physical-charge-capacity.js.map +1 -1
- package/dist/sensor/pixel-pitch.d.ts +2 -3
- package/dist/sensor/pixel-pitch.js +4 -2
- package/dist/sensor/pixel-pitch.js.map +1 -1
- package/dist/sensor/radiometry-readiness.d.ts +13 -15
- package/dist/sensor/radiometry-readiness.js +20 -17
- package/dist/sensor/radiometry-readiness.js.map +1 -1
- package/dist/sensor/raw-readout.d.ts +173 -83
- package/dist/sensor/raw-readout.js +425 -160
- package/dist/sensor/raw-readout.js.map +1 -1
- package/dist/sensor/raw-reconstruction.d.ts +112 -44
- package/dist/sensor/raw-reconstruction.js +200 -47
- package/dist/sensor/raw-reconstruction.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.d.ts +103 -34
- package/dist/sensor/readout-exposure-linkage.js +125 -27
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/dist/sensor/readout-timing.d.ts +43 -44
- package/dist/sensor/readout-timing.js +38 -30
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.d.ts +21 -28
- package/dist/sensor/response-application-compatibility.js +35 -34
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/response-operating-range.d.ts +26 -35
- package/dist/sensor/response-operating-range.js +40 -39
- package/dist/sensor/response-operating-range.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.d.ts +21 -29
- package/dist/sensor/responsivity-photocurrent.js +57 -40
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sampling-aperture.d.ts +21 -25
- package/dist/sensor/sampling-aperture.js +29 -28
- package/dist/sensor/sampling-aperture.js.map +1 -1
- package/dist/sensor/scene-eqe-temporal-exposure.d.ts +14 -12
- package/dist/sensor/scene-eqe-temporal-exposure.js +13 -8
- package/dist/sensor/scene-eqe-temporal-exposure.js.map +1 -1
- package/dist/sensor/sensor-geometry.d.ts +28 -32
- package/dist/sensor/sensor-geometry.js +35 -20
- package/dist/sensor/sensor-geometry.js.map +1 -1
- package/dist/sensor/signal-noise.d.ts +14 -16
- package/dist/sensor/signal-noise.js +15 -13
- package/dist/sensor/signal-noise.js.map +1 -1
- package/dist/sensor/spatial-sample-reduction.d.ts +45 -60
- package/dist/sensor/spatial-sample-reduction.js +39 -48
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spatial-sampling-quadrature.d.ts +46 -54
- package/dist/sensor/spatial-sampling-quadrature.js +31 -36
- package/dist/sensor/spatial-sampling-quadrature.js.map +1 -1
- package/dist/sensor/spatio-spectral-reduction.d.ts +32 -42
- package/dist/sensor/spatio-spectral-reduction.js +24 -29
- package/dist/sensor/spatio-spectral-reduction.js.map +1 -1
- package/dist/sensor/spectral-coverage.d.ts +6 -9
- package/dist/sensor/spectral-coverage.js +9 -6
- package/dist/sensor/spectral-coverage.js.map +1 -1
- package/dist/sensor/spectral-quadrature.d.ts +46 -60
- package/dist/sensor/spectral-quadrature.js +38 -48
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/spectral-response.d.ts +53 -41
- package/dist/sensor/spectral-response.js +80 -47
- package/dist/sensor/spectral-response.js.map +1 -1
- package/dist/sensor/stochastic-seed.d.ts +50 -0
- package/dist/sensor/stochastic-seed.js +123 -0
- package/dist/sensor/stochastic-seed.js.map +1 -0
- package/dist/sensor/temporal-eqe-sum.d.ts +2 -4
- package/dist/sensor/temporal-eqe-sum.js +5 -6
- package/dist/sensor/temporal-eqe-sum.js.map +1 -1
- package/dist/sensor/temporal-photo-signal.d.ts +5 -6
- package/dist/sensor/temporal-photo-signal.js +11 -10
- package/dist/sensor/temporal-photo-signal.js.map +1 -1
- package/dist/sensor/temporal-sample-binding.d.ts +1 -2
- package/dist/sensor/temporal-sample-binding.js +3 -3
- package/dist/sensor/temporal-sample-binding.js.map +1 -1
- package/dist/simulation/poc-simulation.d.ts +16 -16
- package/dist/simulation/poc-simulation.js +20 -15
- package/dist/simulation/poc-simulation.js.map +1 -1
- package/dist/stabilization/camera-shake.d.ts +42 -18
- package/dist/stabilization/camera-shake.js +43 -20
- package/dist/stabilization/camera-shake.js.map +1 -1
- package/dist/stabilization/system.d.ts +44 -41
- package/dist/stabilization/system.js +196 -108
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +183 -0
- package/docs/API_REFERENCE.md +761 -2
- package/docs/QUICK_START.md +495 -0
- package/docs/USAGE.md +1719 -714
- package/docs/api/camera-equivalent-focal-length.md +6 -7
- package/docs/api/camera-field-of-view.md +16 -8
- package/docs/api/camera-lens-projection.md +246 -0
- package/docs/api/camera-projected-object-size.md +6 -5
- package/docs/api/capture-capture-export-metadata.md +10 -10
- package/docs/api/capture-dng-import.md +134 -0
- package/docs/api/capture-environment-raw-producer.md +17 -11
- package/docs/api/capture-export-jpeg.md +16 -0
- package/docs/api/capture-focus-control.md +25 -47
- package/docs/api/capture-linear-encoding.md +21 -12
- package/docs/api/capture-lossless-jpeg.md +49 -0
- package/docs/api/capture-native-environment-optical-stage.md +75 -0
- package/docs/api/capture-native-environment-raw.md +161 -4
- package/docs/api/capture-native-raw-development.md +69 -4
- package/docs/api/capture-native-raw-dng.md +84 -0
- package/docs/api/capture-native-raw.md +23 -8
- package/docs/api/capture-packed-sensor-raw.md +156 -0
- package/docs/api/capture-photographic-export.md +69 -31
- package/docs/api/capture-raw-frame-reconstruction.md +8 -8
- package/docs/api/capture-raw-white-level.md +37 -0
- package/docs/api/capture-release-sequence.md +6 -7
- package/docs/api/capture-sensor-raw-frame.md +6 -6
- package/docs/api/capture-sensor-raw-producer.md +17 -11
- package/docs/api/capture-simulated-capture.md +15 -15
- package/docs/api/color-camera-color-matrix.md +103 -0
- package/docs/api/color-capture-color.md +22 -11
- package/docs/api/color-chromatic-adaptation.md +82 -0
- package/docs/api/color-color-difference.md +134 -0
- package/docs/api/color-color-matching-functions.md +259 -0
- package/docs/api/color-colorimetry-math.md +54 -0
- package/docs/api/color-gamut-mapping.md +72 -0
- package/docs/api/color-illuminants.md +280 -0
- package/docs/api/color-rgb-color-spaces.md +151 -0
- package/docs/api/color-sensor-color-development.md +27 -0
- package/docs/api/color-srgb-icc.md +2 -4
- package/docs/api/color-white-balance.md +95 -19
- package/docs/api/composition-image-formation-plan.md +124 -95
- package/docs/api/composition-plan-consumer.md +7 -7
- package/docs/api/core-calculation-result.md +18 -14
- package/docs/api/core-configuration-error.md +1 -1
- package/docs/api/core-image-formation.md +7 -7
- package/docs/api/core-scientific-assurance.md +12 -10
- package/docs/api/core-spectral-composition.md +14 -14
- package/docs/api/core-spectral.md +6 -6
- package/docs/api/core-validation.md +3 -3
- package/docs/api/core-version.md +7 -6
- package/docs/api/equipment-exposure-capabilities.md +11 -10
- package/docs/api/equipment-generic-tier-assets.md +7 -2
- package/docs/api/equipment-generic-tier-presets.md +6 -6
- package/docs/api/equipment-iso-capabilities.md +18 -18
- package/docs/api/equipment-metering-capabilities.md +6 -6
- package/docs/api/equipment-release-capabilities.md +4 -4
- package/docs/api/exports.json +2213 -8
- package/docs/api/exposure-exposure-duration-control.md +9 -9
- package/docs/api/exposure-exposure-mode-resolver.md +35 -31
- package/docs/api/exposure-exposure.md +10 -10
- package/docs/api/exposure-flash-ttl.md +182 -0
- package/docs/api/exposure-flash.md +183 -28
- package/docs/api/exposure-metering-scene-radiance.md +11 -10
- package/docs/api/exposure-metering-target.md +9 -8
- package/docs/api/exposure-metering-temporal.md +8 -8
- package/docs/api/exposure-metering.md +69 -9
- package/docs/api/exposure-program-line.md +6 -5
- package/docs/api/facade-chart-radiance-batch.md +96 -0
- package/docs/api/facade-chart-scenes.md +240 -0
- package/docs/api/facade-scene-radiance.md +122 -0
- package/docs/api/facade-simulate-capture.md +324 -0
- package/docs/api/gpu-image-kernel-accelerator.md +157 -0
- package/docs/api/gpu-image-kernel-execution.md +152 -0
- package/docs/api/motion-camera-rotation.md +43 -26
- package/docs/api/motion-capture-rotation-inverse-mapping.md +24 -23
- package/docs/api/motion-capture-rotation-temporal-quadrature.md +22 -22
- package/docs/api/motion-capture-rotation-trajectory.md +15 -15
- package/docs/api/motion-capture-translation-parallax-temporal-quadrature.md +15 -14
- package/docs/api/motion-extended-object-projection.md +10 -8
- package/docs/api/motion-projected-motion.md +8 -8
- package/docs/api/motion-temporal-exposure-sum.md +98 -0
- package/docs/api/motion-video-sequence.md +159 -0
- package/docs/api/optics-aperture.md +8 -8
- package/docs/api/optics-atmospheric-haze.md +104 -0
- package/docs/api/optics-brown-conrady-distortion.md +123 -0
- package/docs/api/optics-circle-of-confusion.md +5 -4
- package/docs/api/optics-complex-pupil-psf.md +57 -16
- package/docs/api/optics-depth-of-field.md +12 -6
- package/docs/api/optics-diffraction.md +8 -7
- package/docs/api/optics-focus-breathing.md +104 -16
- package/docs/api/optics-focus-state.md +9 -10
- package/docs/api/optics-front-of-lens-filter.md +72 -14
- package/docs/api/optics-illumination-vignetting.md +10 -10
- package/docs/api/optics-irradiance-convolution.md +95 -0
- package/docs/api/optics-lateral-chromatic-aberration.md +22 -21
- package/docs/api/optics-lens-psf-kernels.md +72 -0
- package/docs/api/optics-lens-psf-profile.md +48 -26
- package/docs/api/optics-longitudinal-chromatic-aberration.md +128 -0
- package/docs/api/optics-polygon-diffraction.md +78 -13
- package/docs/api/optics-profile-contract.md +4 -4
- package/docs/api/optics-psf-foundation.md +12 -12
- package/docs/api/optics-pupil-vignetting.md +132 -0
- package/docs/api/optics-radial-distortion.md +12 -12
- package/docs/api/optics-scene-to-sensor-irradiance.md +25 -14
- package/docs/api/optics-scene-to-sensor-quadrature.md +15 -12
- package/docs/api/optics-sensor-aperture-rays.md +3 -2
- package/docs/api/optics-sensor-environment-query.md +52 -9
- package/docs/api/optics-sensor-psf-quadrature.md +13 -10
- package/docs/api/optics-stray-light.md +12 -11
- package/docs/api/optics-thin-lens.md +4 -3
- package/docs/api/optics-zernike-wavefront.md +229 -0
- package/docs/api/output-capture-corrected-sdr.md +10 -7
- package/docs/api/output-capture-geometry.md +35 -36
- package/docs/api/output-capture-sdr.md +4 -4
- package/docs/api/output-crop.md +7 -4
- package/docs/api/output-geometric-transforms.md +65 -19
- package/docs/api/output-lens-corrections.md +17 -15
- package/docs/api/output-native-capture-sdr.md +26 -13
- package/docs/api/output-png-encoder.md +105 -0
- package/docs/api/output-print-contrast-reference.md +8 -8
- package/docs/api/output-print-detail.md +14 -14
- package/docs/api/output-print-jpeg.md +22 -5
- package/docs/api/output-print-plan.md +18 -18
- package/docs/api/output-print-region-statistics.md +14 -14
- package/docs/api/output-sdr-rendering.md +52 -10
- package/docs/api/output-subject-framing-crop.md +5 -6
- package/docs/api/processing-demosaic.md +120 -0
- package/docs/api/processing-denoise.md +148 -0
- package/docs/api/processing-focus-stacking.md +41 -0
- package/docs/api/processing-hdr.md +113 -0
- package/docs/api/processing-panorama.md +82 -0
- package/docs/api/processing-processing-task.md +107 -0
- package/docs/api/processing-tone-mapping.md +142 -0
- package/docs/api/schema-camera.md +6 -4
- package/docs/api/schema-illumination-spectral.md +10 -11
- package/docs/api/schema-illumination-temporal.md +13 -15
- package/docs/api/schema-illumination.md +4 -4
- package/docs/api/schema-scene-radiance-temporal.md +10 -11
- package/docs/api/schema-scene-radiance.md +18 -17
- package/docs/api/schema-scene.md +9 -9
- package/docs/api/schema-validation.md +1 -1
- package/docs/api/sensor-accumulated-charge.md +12 -20
- package/docs/api/sensor-architecture.md +15 -16
- package/docs/api/sensor-camera-saturation-capacity.md +9 -11
- package/docs/api/sensor-capture-color-sampling-binding.md +47 -51
- package/docs/api/sensor-capture-mode-timing.md +9 -9
- package/docs/api/sensor-capture-mode.md +29 -30
- package/docs/api/sensor-color-sampling.md +31 -33
- package/docs/api/sensor-constant-rate-temporal-integration.md +10 -11
- package/docs/api/sensor-dark-current.md +30 -14
- package/docs/api/sensor-environment-photo-signal.md +13 -6
- package/docs/api/sensor-eqe-electron-rate.md +9 -8
- package/docs/api/sensor-eqe-local-exposure.md +18 -17
- package/docs/api/sensor-eqe-temporal-exposure.md +12 -11
- package/docs/api/sensor-exposure-window.md +24 -24
- package/docs/api/sensor-fixed-pattern-noise.md +104 -0
- package/docs/api/sensor-iso-gain.md +63 -0
- package/docs/api/sensor-iso-signal-chain.md +13 -22
- package/docs/api/sensor-local-exposure-binding.md +12 -13
- package/docs/api/sensor-optical-stack.md +37 -40
- package/docs/api/sensor-photon-energy.md +10 -11
- package/docs/api/sensor-physical-charge-capacity.md +8 -13
- package/docs/api/sensor-pixel-pitch.md +1 -1
- package/docs/api/sensor-radiometry-readiness.md +9 -9
- package/docs/api/sensor-raw-readout.md +118 -52
- package/docs/api/sensor-raw-reconstruction.md +97 -20
- package/docs/api/sensor-readout-exposure-linkage.md +120 -24
- package/docs/api/sensor-readout-timing.md +33 -35
- package/docs/api/sensor-response-application-compatibility.md +9 -11
- package/docs/api/sensor-response-operating-range.md +14 -18
- package/docs/api/sensor-responsivity-photocurrent.md +9 -12
- package/docs/api/sensor-sampling-aperture.md +22 -25
- package/docs/api/sensor-scene-eqe-temporal-exposure.md +9 -8
- package/docs/api/sensor-sensor-geometry.md +23 -24
- package/docs/api/sensor-signal-noise.md +10 -10
- package/docs/api/sensor-spatial-sample-reduction.md +27 -30
- package/docs/api/sensor-spatial-sampling-quadrature.md +37 -39
- package/docs/api/sensor-spatio-spectral-reduction.md +27 -29
- package/docs/api/sensor-spectral-coverage.md +5 -5
- package/docs/api/sensor-spectral-quadrature.md +33 -35
- package/docs/api/sensor-spectral-response.md +28 -16
- package/docs/api/sensor-temporal-photo-signal.md +6 -6
- package/docs/api/simulation-poc-simulation.md +17 -16
- package/docs/api/stabilization-camera-shake.md +29 -10
- package/docs/api/stabilization-system.md +25 -21
- package/docs/examples/production-request.json +3821 -2157
- package/docs/examples/simulate-capture.mjs +14 -0
- package/llms.txt +35 -0
- package/package.json +32 -12
- package/AGENTS.md +0 -674
- package/CONTRIBUTING.md +0 -76
- package/DCO +0 -33
- package/dist/camera/equivalent-focal-length.d.ts.map +0 -1
- package/dist/camera/field-of-view.d.ts.map +0 -1
- package/dist/camera/projected-object-size.d.ts.map +0 -1
- package/dist/capture/capture-export-metadata.d.ts.map +0 -1
- package/dist/capture/environment-raw-producer.d.ts.map +0 -1
- package/dist/capture/export-jpeg.d.ts.map +0 -1
- package/dist/capture/export-tiff.d.ts.map +0 -1
- package/dist/capture/focus-control.d.ts.map +0 -1
- package/dist/capture/linear-encoding.d.ts.map +0 -1
- package/dist/capture/native-environment-raw.d.ts.map +0 -1
- package/dist/capture/native-raw-development.d.ts.map +0 -1
- package/dist/capture/native-raw.d.ts.map +0 -1
- package/dist/capture/photographic-export.d.ts.map +0 -1
- package/dist/capture/raw-frame-limits.d.ts.map +0 -1
- package/dist/capture/raw-frame-reconstruction.d.ts.map +0 -1
- package/dist/capture/release-sequence.d.ts.map +0 -1
- package/dist/capture/sensor-raw-frame.d.ts.map +0 -1
- package/dist/capture/sensor-raw-producer.d.ts.map +0 -1
- package/dist/capture/simulated-capture.d.ts.map +0 -1
- package/dist/color/capture-color.d.ts.map +0 -1
- package/dist/color/sensor-color-development.d.ts.map +0 -1
- package/dist/color/srgb-icc.d.ts.map +0 -1
- package/dist/color/srgb-transfer.d.ts.map +0 -1
- package/dist/color/white-balance.d.ts.map +0 -1
- package/dist/composition/image-formation-plan.d.ts.map +0 -1
- package/dist/composition/plan-consumer.d.ts.map +0 -1
- package/dist/core/calculation-result.d.ts.map +0 -1
- package/dist/core/canonical-json.d.ts.map +0 -1
- package/dist/core/configuration-error.d.ts.map +0 -1
- package/dist/core/evidence-provenance.d.ts.map +0 -1
- package/dist/core/image-formation.d.ts.map +0 -1
- package/dist/core/owned-data.d.ts.map +0 -1
- package/dist/core/record-validation.d.ts.map +0 -1
- package/dist/core/scientific-assurance.d.ts.map +0 -1
- package/dist/core/spectral-composition.d.ts.map +0 -1
- package/dist/core/spectral.d.ts.map +0 -1
- package/dist/core/validation.d.ts.map +0 -1
- package/dist/core/version.d.ts.map +0 -1
- package/dist/equipment/exposure-capabilities.d.ts.map +0 -1
- package/dist/equipment/generic-tier-assets.d.ts.map +0 -1
- package/dist/equipment/generic-tier-presets.d.ts.map +0 -1
- package/dist/equipment/iso-capabilities.d.ts.map +0 -1
- package/dist/equipment/metering-capabilities.d.ts.map +0 -1
- package/dist/equipment/release-capabilities.d.ts.map +0 -1
- package/dist/exposure/exposure-duration-control.d.ts.map +0 -1
- package/dist/exposure/exposure-mode-resolver.d.ts.map +0 -1
- package/dist/exposure/exposure.d.ts.map +0 -1
- package/dist/exposure/flash.d.ts.map +0 -1
- package/dist/exposure/metering-scene-radiance.d.ts.map +0 -1
- package/dist/exposure/metering-target.d.ts.map +0 -1
- package/dist/exposure/metering-temporal.d.ts.map +0 -1
- package/dist/exposure/metering.d.ts.map +0 -1
- package/dist/exposure/program-line.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/motion/camera-rotation.d.ts.map +0 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts.map +0 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts.map +0 -1
- package/dist/motion/capture-rotation-trajectory.d.ts.map +0 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts.map +0 -1
- package/dist/motion/extended-object-projection.d.ts.map +0 -1
- package/dist/motion/projected-motion.d.ts.map +0 -1
- package/dist/optics/aperture.d.ts.map +0 -1
- package/dist/optics/circle-of-confusion.d.ts.map +0 -1
- package/dist/optics/complex-pupil-psf.d.ts.map +0 -1
- package/dist/optics/depth-of-field.d.ts.map +0 -1
- package/dist/optics/diffraction.d.ts.map +0 -1
- package/dist/optics/focus-breathing.d.ts.map +0 -1
- package/dist/optics/focus-state.d.ts.map +0 -1
- package/dist/optics/front-of-lens-filter.d.ts.map +0 -1
- package/dist/optics/illumination-vignetting.d.ts.map +0 -1
- package/dist/optics/lateral-chromatic-aberration.d.ts.map +0 -1
- package/dist/optics/lens-psf-profile.d.ts.map +0 -1
- package/dist/optics/polygon-diffraction.d.ts.map +0 -1
- package/dist/optics/profile-contract.d.ts.map +0 -1
- package/dist/optics/psf-foundation.d.ts.map +0 -1
- package/dist/optics/radial-distortion.d.ts.map +0 -1
- package/dist/optics/scene-to-sensor-irradiance.d.ts.map +0 -1
- package/dist/optics/scene-to-sensor-quadrature.d.ts.map +0 -1
- package/dist/optics/sensor-aperture-rays.d.ts.map +0 -1
- package/dist/optics/sensor-environment-query.d.ts.map +0 -1
- package/dist/optics/sensor-psf-quadrature.d.ts.map +0 -1
- package/dist/optics/sensor-psf-support.d.ts.map +0 -1
- package/dist/optics/stray-light.d.ts.map +0 -1
- package/dist/optics/thin-lens.d.ts.map +0 -1
- package/dist/output/capture-corrected-sdr.d.ts.map +0 -1
- package/dist/output/capture-geometry.d.ts.map +0 -1
- package/dist/output/capture-sdr.d.ts.map +0 -1
- package/dist/output/crop.d.ts.map +0 -1
- package/dist/output/geometric-transforms.d.ts.map +0 -1
- package/dist/output/lens-corrections.d.ts.map +0 -1
- package/dist/output/native-capture-sdr.d.ts.map +0 -1
- package/dist/output/print-contrast-reference.d.ts.map +0 -1
- package/dist/output/print-detail.d.ts.map +0 -1
- package/dist/output/print-jpeg.d.ts.map +0 -1
- package/dist/output/print-plan.d.ts.map +0 -1
- package/dist/output/print-region-statistics.d.ts.map +0 -1
- package/dist/output/sdr-rendering.d.ts.map +0 -1
- package/dist/output/subject-framing-crop.d.ts.map +0 -1
- package/dist/schema/camera.d.ts.map +0 -1
- package/dist/schema/camera.js +0 -3
- package/dist/schema/camera.js.map +0 -1
- package/dist/schema/illumination-spectral.d.ts.map +0 -1
- package/dist/schema/illumination-temporal.d.ts.map +0 -1
- package/dist/schema/illumination.d.ts.map +0 -1
- package/dist/schema/scene-radiance-temporal.d.ts.map +0 -1
- package/dist/schema/scene-radiance.d.ts.map +0 -1
- package/dist/schema/scene.d.ts.map +0 -1
- package/dist/schema/scene.js +0 -3
- package/dist/schema/scene.js.map +0 -1
- package/dist/schema/validation.d.ts.map +0 -1
- package/dist/sensor/accumulated-charge.d.ts.map +0 -1
- package/dist/sensor/architecture.d.ts.map +0 -1
- package/dist/sensor/camera-saturation-capacity.d.ts.map +0 -1
- package/dist/sensor/capture-color-sampling-binding.d.ts.map +0 -1
- package/dist/sensor/capture-mode-timing.d.ts.map +0 -1
- package/dist/sensor/capture-mode.d.ts.map +0 -1
- package/dist/sensor/color-sampling.d.ts.map +0 -1
- package/dist/sensor/constant-rate-temporal-integration.d.ts.map +0 -1
- package/dist/sensor/dark-current.d.ts.map +0 -1
- package/dist/sensor/environment-photo-signal.d.ts.map +0 -1
- package/dist/sensor/eqe-electron-rate.d.ts.map +0 -1
- package/dist/sensor/eqe-local-exposure.d.ts.map +0 -1
- package/dist/sensor/eqe-temporal-exposure.d.ts.map +0 -1
- package/dist/sensor/exposure-window.d.ts.map +0 -1
- package/dist/sensor/iso-signal-chain.d.ts.map +0 -1
- package/dist/sensor/local-exposure-binding.d.ts.map +0 -1
- package/dist/sensor/optical-stack.d.ts.map +0 -1
- package/dist/sensor/photon-energy.d.ts.map +0 -1
- package/dist/sensor/physical-charge-capacity.d.ts.map +0 -1
- package/dist/sensor/pixel-pitch.d.ts.map +0 -1
- package/dist/sensor/radiometry-readiness.d.ts.map +0 -1
- package/dist/sensor/raw-readout.d.ts.map +0 -1
- package/dist/sensor/raw-reconstruction.d.ts.map +0 -1
- package/dist/sensor/readout-exposure-linkage.d.ts.map +0 -1
- package/dist/sensor/readout-timing.d.ts.map +0 -1
- package/dist/sensor/response-application-compatibility.d.ts.map +0 -1
- package/dist/sensor/response-operating-range.d.ts.map +0 -1
- package/dist/sensor/responsivity-photocurrent.d.ts.map +0 -1
- package/dist/sensor/sampling-aperture.d.ts.map +0 -1
- package/dist/sensor/scene-eqe-temporal-exposure.d.ts.map +0 -1
- package/dist/sensor/sensor-geometry.d.ts.map +0 -1
- package/dist/sensor/signal-noise.d.ts.map +0 -1
- package/dist/sensor/spatial-sample-reduction.d.ts.map +0 -1
- package/dist/sensor/spatial-sampling-quadrature.d.ts.map +0 -1
- package/dist/sensor/spatio-spectral-reduction.d.ts.map +0 -1
- package/dist/sensor/spectral-coverage.d.ts.map +0 -1
- package/dist/sensor/spectral-quadrature.d.ts.map +0 -1
- package/dist/sensor/spectral-response.d.ts.map +0 -1
- package/dist/sensor/temporal-eqe-sum.d.ts.map +0 -1
- package/dist/sensor/temporal-photo-signal.d.ts.map +0 -1
- package/dist/sensor/temporal-sample-binding.d.ts.map +0 -1
- package/dist/simulation/poc-simulation.d.ts.map +0 -1
- package/dist/stabilization/camera-shake.d.ts.map +0 -1
- package/dist/stabilization/system.d.ts.map +0 -1
- package/docs/API_STYLE.md +0 -235
- package/docs/ARCHITECTURE.md +0 -356
- package/docs/AUTOMATION_COORDINATION.md +0 -190
- package/docs/CAPTURE_COLOR.md +0 -25
- package/docs/CAPTURE_CORRECTED_SDR.md +0 -25
- package/docs/CAPTURE_EXPORT_METADATA.md +0 -27
- package/docs/CAPTURE_SDR.md +0 -22
- package/docs/DEVELOPERS.md +0 -68
- package/docs/DIGITAL_OPTICS_FOUNDATION.md +0 -69
- package/docs/ENVIRONMENT_RAW_CAPTURE.md +0 -208
- package/docs/EXPORT_ACCEPTANCE.md +0 -133
- package/docs/GENERIC_TIER_PRESETS.md +0 -269
- package/docs/GEOMETRIC_PREPARATION_REUSE.md +0 -141
- package/docs/IMAGE_FORMATION.md +0 -247
- package/docs/LINEAR_CAPTURE_ENCODING.md +0 -25
- package/docs/MOTION_AND_SIGNAL.md +0 -250
- package/docs/NATIVE_CAPTURE_SDR.md +0 -70
- package/docs/NATIVE_CAPTURE_SDR_REVIEW.md +0 -37
- package/docs/NATIVE_CAPTURE_SDR_VALIDATION.md +0 -34
- package/docs/NATIVE_RAW_AND_PRINT.md +0 -47
- package/docs/NUMERICAL_CORRECTNESS.md +0 -191
- package/docs/PERFORMANCE_BASELINE.md +0 -56
- package/docs/PHOTOGRAPHIC_EXPORT.md +0 -206
- package/docs/PHYSICS_FOUNDATION.md +0 -426
- package/docs/POC_API.md +0 -278
- package/docs/POC_PROJECTION_PLATFORM_REFERENCE.md +0 -12
- package/docs/POC_PROJECTION_REUSE.md +0 -124
- package/docs/PRINT_195_196_REVIEW.md +0 -93
- package/docs/PRINT_196_ENGINE_ACCEPTANCE.md +0 -45
- package/docs/PRINT_CONTRAST_REFERENCE.md +0 -43
- package/docs/PRINT_DETAIL_ASSESSMENT.md +0 -81
- package/docs/PRINT_DETAIL_JPEG_EVIDENCE.md +0 -36
- package/docs/PRINT_DETAIL_SDR_EVIDENCE.md +0 -29
- package/docs/PRINT_DETAIL_VALIDATION.md +0 -36
- package/docs/PRINT_PLANNING.md +0 -75
- package/docs/PRINT_REGION_STATISTICS.md +0 -38
- package/docs/PROCESSED_OUTPUT.md +0 -157
- package/docs/PRODUCTION_COMPOSITION.md +0 -373
- package/docs/PRODUCTION_ENVIRONMENT_CAPTURE.md +0 -131
- package/docs/PROVENANCE.md +0 -115
- package/docs/PSF_FOUNDATION.md +0 -165
- package/docs/RAW_FRAME_ENVELOPE.md +0 -56
- package/docs/RAW_FRAME_RECONSTRUCTION.md +0 -30
- package/docs/RELEASE_1_0.md +0 -66
- package/docs/RELEASE_1_0_1.md +0 -61
- package/docs/RELEASE_1_1_0.md +0 -25
- package/docs/RELEASE_1_2_0.md +0 -51
- package/docs/RELEASE_1_3_0.md +0 -15
- package/docs/RELEASE_1_4_0.md +0 -23
- package/docs/RELEASE_AUDIT.md +0 -39
- package/docs/SCENE_RADIANCE_AND_ILLUMINATION.md +0 -298
- package/docs/SCENE_SENSOR_QUADRATURE.md +0 -98
- package/docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md +0 -86
- package/docs/SCIENTIFIC_ASSURANCE.md +0 -280
- package/docs/SCIENTIFIC_CONFORMANCE.md +0 -83
- package/docs/SDR_RENDERING.md +0 -33
- package/docs/SENSOR_APERTURE_RAYS.md +0 -23
- package/docs/SENSOR_ENVIRONMENT_QUERY.md +0 -86
- package/docs/SENSOR_EQE_LOCAL_EXPOSURE.md +0 -104
- package/docs/SENSOR_EQE_TEMPORAL_EXPOSURE.md +0 -74
- package/docs/SENSOR_PSF_QUADRATURE.md +0 -90
- package/docs/SENSOR_RAW_FRAME.md +0 -20
- package/docs/SENSOR_RAW_PRODUCER.md +0 -77
- package/docs/SIGNAL_CONFORMANCE.md +0 -23
- package/docs/SIMULATED_CAPTURE.md +0 -65
- package/docs/STABILIZATION.md +0 -234
- package/docs/TEMPORAL_PHOTO_RAW.md +0 -83
- package/docs/TIER_ACCEPTANCE.md +0 -129
- package/docs/TIER_PRESET_ACCEPTANCE.md +0 -59
- package/docs/V1_COMPOSITION_MAP.md +0 -123
- package/docs/V1_HELPER_REUSE_REVIEW.md +0 -60
- package/docs/V1_PERFORMANCE_DISPOSITION.md +0 -88
- package/docs/benchmarks/2026-10-01-main-baseline.json +0 -694
- package/docs/benchmarks/2026-10-02-geometric-preparation-reuse.json +0 -2190
- package/docs/benchmarks/2026-10-02-poc-projection-reuse.json +0 -2423
- package/docs/benchmarks/2026-10-02-v1-environment-gc-profile.json +0 -210
- package/docs/benchmarks/2026-10-02-v1-environment-ordinary.json +0 -187
- package/docs/benchmarks/2026-10-02-v1-geometry-gc-profile.json +0 -756
- package/docs/benchmarks/2026-10-02-v1-geometry-ordinary-1.json +0 -711
- package/docs/benchmarks/2026-10-02-v1-geometry-ordinary-2.json +0 -711
- package/docs/benchmarks/2026-10-02-v1-poc-gc-profile.json +0 -885
- package/docs/benchmarks/2026-10-02-v1-poc-ordinary-1.json +0 -868
- package/docs/benchmarks/2026-10-02-v1-poc-ordinary-2.json +0 -868
- package/docs/licenses/castleCSF-MIT.txt +0 -21
- package/docs/validation/documentation-fragments.json +0 -212
- package/docs/validation/native-capture-sdr-darwin-arm64-node26-review.jsonl +0 -4
- package/docs/validation/native-capture-sdr-darwin-arm64.jsonl +0 -3
- package/docs/validation/native-raw-print-2026-10-04/fractional-asymmetric-crop.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/gray-ramp.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/linear-area-checker.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/manifest.json +0 -218
- package/docs/validation/native-raw-print-2026-10-04/megapixel-native.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/native-color.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel-validation.json +0 -9
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json +0 -29
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json.codes.u16le.gz +0 -0
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json.rgb.gz +0 -0
- package/docs/validation/native-raw-print-2026-10-04/srgb.icc +0 -0
- package/docs/validation/native-raw-print-2026-10-04/validation.json +0 -41
- package/docs/validation/print-196-candidate-capabilities.json +0 -28
- package/docs/validation/print-196-candidate-evidence.json +0 -356
- package/docs/validation/print-196-engine-acceptance.json +0 -81
- package/docs/validation/print-detail-capabilities.json +0 -103
- package/docs/validation/print-detail-jpeg-evidence.json +0 -116
- package/docs/validation/print-detail-sdr-evidence.json +0 -81
- package/docs/validation/release-audit-inventory.json +0 -1306
- package/docs/validation/tier-acceptance-report-v1.json +0 -2538
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
3
|
+
* How far a moving object travels across the sensor during an exposure. Uses ideal rectilinear
|
|
4
|
+
* projection and a constant straight-line object velocity.
|
|
5
|
+
* - Without focusDistanceM, the projection distance is the nominal focal length (the older pinhole
|
|
6
|
+
* behaviour).
|
|
7
|
+
* - With focusDistanceM, it is the thin-lens image distance for that focus.
|
|
8
|
+
*
|
|
9
|
+
* The object's positions when the shutter opens and closes are both projected onto the image plane,
|
|
10
|
+
* and the distance between them is measured. So sideways motion and motion toward or away from the
|
|
11
|
+
* camera are both handled, without a generic "subject speed" category.
|
|
12
|
+
* @see docs/MOTION_AND_SIGNAL.md for the equations, units, coordinate conventions, known blockers
|
|
13
|
+
* and support limits.
|
|
12
14
|
*/
|
|
13
15
|
import { calculatedResult } from "../core/calculation-result.js";
|
|
14
16
|
import { InvalidScientificInputError, requirePositiveFinite } from "../core/validation.js";
|
|
17
|
+
import { portableHypot } from "../core/portable-math.js";
|
|
15
18
|
import { calculateThinLensImageDistance } from "../optics/thin-lens.js";
|
|
19
|
+
import { rejectUnknownFields, requireInputKeys, requireInputObject } from "../core/record-validation.js";
|
|
20
|
+
const VECTOR3_FIELDS = ["x", "y", "z"];
|
|
16
21
|
function requireFiniteVector3(name, value) {
|
|
22
|
+
requireInputObject(value, name);
|
|
23
|
+
rejectUnknownFields(value, VECTOR3_FIELDS, name);
|
|
17
24
|
for (const component of ["x", "y", "z"]) {
|
|
18
25
|
if (!Number.isFinite(value[component])) {
|
|
19
26
|
throw new InvalidScientificInputError(`${name}.${component} must be finite.`);
|
|
@@ -24,19 +31,20 @@ function requireFiniteVector3(name, value) {
|
|
|
24
31
|
* Calculates sensor-plane motion during an exposure using ideal rectilinear
|
|
25
32
|
* projection and constant linear object velocity.
|
|
26
33
|
*
|
|
27
|
-
* Without focusDistanceM,
|
|
28
|
-
* pinhole
|
|
29
|
-
*
|
|
34
|
+
* Without focusDistanceM, the projection distance is the nominal focal length
|
|
35
|
+
* (the older pinhole behaviour). With focusDistanceM, it is the thin-lens
|
|
36
|
+
* image distance for that focus.
|
|
30
37
|
*
|
|
31
|
-
* The
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* generic "subject speed" category.
|
|
38
|
+
* The object's positions when the shutter opens and closes are both projected
|
|
39
|
+
* onto the image plane, and the distance between them is measured. So
|
|
40
|
+
* sideways motion and motion toward or away from the camera are both handled,
|
|
41
|
+
* without a generic "subject speed" category.
|
|
35
42
|
*
|
|
36
43
|
* @param input Camera, exposure, object-position, and velocity inputs.
|
|
37
44
|
* @returns Projected sensor-plane displacement.
|
|
38
45
|
*/
|
|
39
46
|
export function calculateProjectedMotionBlur(input) {
|
|
47
|
+
requireInputKeys(input, "calculateProjectedMotionBlur", ["focalLengthMm", "shutterSeconds", "positionM", "velocityMps", "focusDistanceM", "pixelPitchMicrometers"]);
|
|
40
48
|
requirePositiveFinite("focalLengthMm", input.focalLengthMm);
|
|
41
49
|
requirePositiveFinite("shutterSeconds", input.shutterSeconds);
|
|
42
50
|
requireFiniteVector3("positionM", input.positionM);
|
|
@@ -65,7 +73,7 @@ export function calculateProjectedMotionBlur(input) {
|
|
|
65
73
|
const endYmm = projectionDistanceMm * (endPositionM.y / endPositionM.z);
|
|
66
74
|
const deltaXMm = endXmm - startXmm;
|
|
67
75
|
const deltaYMm = endYmm - startYmm;
|
|
68
|
-
const distanceMm =
|
|
76
|
+
const distanceMm = portableHypot(deltaXMm, deltaYMm);
|
|
69
77
|
let distancePixels;
|
|
70
78
|
if (input.pixelPitchMicrometers !== undefined) {
|
|
71
79
|
requirePositiveFinite("pixelPitchMicrometers", input.pixelPitchMicrometers);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projected-motion.js","sourceRoot":"","sources":["../../src/motion/projected-motion.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC
|
|
1
|
+
{"version":3,"file":"projected-motion.js","sourceRoot":"","sources":["../../src/motion/projected-motion.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * How far a moving object travels across the sensor during an exposure. Uses ideal rectilinear\n * projection and a constant straight-line object velocity.\n * - Without focusDistanceM, the projection distance is the nominal focal length (the older pinhole\n * behaviour).\n * - With focusDistanceM, it is the thin-lens image distance for that focus.\n *\n * The object's positions when the shutter opens and closes are both projected onto the image plane,\n * and the distance between them is measured. So sideways motion and motion toward or away from the\n * camera are both handled, without a generic \"subject speed\" category.\n * @see docs/MOTION_AND_SIGNAL.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport {\n calculatedResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport {\n InvalidScientificInputError,\n requirePositiveFinite\n} from \"../core/validation.js\";\nimport { portableHypot } from \"../core/portable-math.js\";\nimport { calculateThinLensImageDistance } from \"../optics/thin-lens.js\";\nimport type { Vector3 } from \"../schema/scene.js\";\nimport { rejectUnknownFields, requireInputKeys, requireInputObject } from \"../core/record-validation.js\";\n\nconst VECTOR3_FIELDS = [\"x\", \"y\", \"z\"] as const;\n\nexport interface CalculateProjectedMotionBlurInput {\n /** Lens focal length in millimetres. */\n focalLengthMm: number;\n /** Shutter-open duration in seconds. */\n shutterSeconds: number;\n /** Object position at shutter open, in camera-relative metres. +z is away from the camera. */\n positionM: Vector3;\n /** Constant world-space velocity during the exposure, in metres per second. */\n velocityMps: Vector3;\n /** Optional focus distance in metres for focus-aware sensor-plane projection. */\n focusDistanceM?: number;\n /** Optional sensor pixel pitch in micrometres for pixel-domain blur reporting. */\n pixelPitchMicrometers?: number;\n}\n\nexport interface ProjectedMotionBlur {\n deltaXMm: number;\n deltaYMm: number;\n distanceMm: number;\n projectionDistanceMm: number;\n distancePixels?: number;\n}\n\nfunction requireFiniteVector3(name: string, value: Vector3): void {\n requireInputObject(value, name);\n rejectUnknownFields(value, VECTOR3_FIELDS, name);\n for (const component of [\"x\", \"y\", \"z\"] as const) {\n if (!Number.isFinite(value[component])) {\n throw new InvalidScientificInputError(\n `${name}.${component} must be finite.`\n );\n }\n }\n}\n\n/**\n * Calculates sensor-plane motion during an exposure using ideal rectilinear\n * projection and constant linear object velocity.\n *\n * Without focusDistanceM, the projection distance is the nominal focal length\n * (the older pinhole behaviour). With focusDistanceM, it is the thin-lens\n * image distance for that focus.\n *\n * The object's positions when the shutter opens and closes are both projected\n * onto the image plane, and the distance between them is measured. So\n * sideways motion and motion toward or away from the camera are both handled,\n * without a generic \"subject speed\" category.\n *\n * @param input Camera, exposure, object-position, and velocity inputs.\n * @returns Projected sensor-plane displacement.\n */\nexport function calculateProjectedMotionBlur(\n input: CalculateProjectedMotionBlurInput\n): CalculationResult<ProjectedMotionBlur> {\n requireInputKeys(input, \"calculateProjectedMotionBlur\", [\"focalLengthMm\", \"shutterSeconds\", \"positionM\", \"velocityMps\", \"focusDistanceM\", \"pixelPitchMicrometers\"]);\n requirePositiveFinite(\"focalLengthMm\", input.focalLengthMm);\n requirePositiveFinite(\"shutterSeconds\", input.shutterSeconds);\n\n requireFiniteVector3(\"positionM\", input.positionM);\n requireFiniteVector3(\"velocityMps\", input.velocityMps);\n\n if (input.positionM.z <= 0) {\n throw new InvalidScientificInputError(\n \"positionM.z must place the object in front of the camera.\"\n );\n }\n\n const endPositionM = {\n x: input.positionM.x + input.velocityMps.x * input.shutterSeconds,\n y: input.positionM.y + input.velocityMps.y * input.shutterSeconds,\n z: input.positionM.z + input.velocityMps.z * input.shutterSeconds\n };\n\n if (endPositionM.z <= 0) {\n throw new InvalidScientificInputError(\n \"Object motion crosses or reaches the camera plane during the exposure.\"\n );\n }\n\n const focusProjection =\n input.focusDistanceM === undefined\n ? undefined\n : calculateThinLensImageDistance({\n focalLengthMm: input.focalLengthMm,\n objectDistanceM: input.focusDistanceM\n });\n const projectionDistanceMm =\n focusProjection?.value.imageDistanceMm ?? input.focalLengthMm;\n\n const startXmm =\n projectionDistanceMm * (input.positionM.x / input.positionM.z);\n const startYmm =\n projectionDistanceMm * (input.positionM.y / input.positionM.z);\n const endXmm =\n projectionDistanceMm * (endPositionM.x / endPositionM.z);\n const endYmm =\n projectionDistanceMm * (endPositionM.y / endPositionM.z);\n\n const deltaXMm = endXmm - startXmm;\n const deltaYMm = endYmm - startYmm;\n const distanceMm = portableHypot(deltaXMm, deltaYMm);\n\n let distancePixels: number | undefined;\n if (input.pixelPitchMicrometers !== undefined) {\n requirePositiveFinite(\n \"pixelPitchMicrometers\",\n input.pixelPitchMicrometers\n );\n distancePixels = distanceMm / (input.pixelPitchMicrometers / 1000);\n }\n\n return calculatedResult(\n {\n deltaXMm,\n deltaYMm,\n distanceMm,\n projectionDistanceMm,\n ...(distancePixels === undefined ? {} : { distancePixels })\n },\n focusProjection === undefined\n ? \"constant-velocity-pinhole-motion\"\n : \"focus-aware-constant-velocity-thin-lens-motion\",\n \"1.0.0\",\n focusProjection === undefined\n ? [\n \"Ideal rectilinear/pinhole projection\",\n \"Constant object velocity during the exposure\",\n \"Camera motion is not included in this calculation\"\n ]\n : [\n \"Ideal rectilinear paraxial thin-lens projection to the selected sensor plane\",\n \"Constant object velocity during the exposure\",\n \"Camera motion is not included in this calculation\",\n \"Real-lens focus breathing is not modeled\"\n ]\n );\n}\n"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export declare const TEMPORAL_EXPOSURE_SUM_SCHEMA_VERSION: "0.1.0";
|
|
2
|
+
export declare const TEMPORAL_EXPOSURE_SUM_LIMITS: Readonly<{
|
|
3
|
+
maximumPixels: 24000000;
|
|
4
|
+
maximumDimension: 16384;
|
|
5
|
+
maximumTemporalSamples: 256;
|
|
6
|
+
maximumDisplacementSites: 4096;
|
|
7
|
+
maximumRowWeights: 4194304;
|
|
8
|
+
/** Keeps every float32 partial sum finite: 256 · 2^16 · 2^100 < 2^128. */
|
|
9
|
+
maximumSampleMagnitude: number;
|
|
10
|
+
maximumWeight: number;
|
|
11
|
+
}>;
|
|
12
|
+
export interface TemporalExposureSumInput {
|
|
13
|
+
schemaVersion: typeof TEMPORAL_EXPOSURE_SUM_SCHEMA_VERSION;
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
/** Row-major rate samples E₀ at site centres. Finite, non-negative, linear and additive (irradiance, photon or electron rate). */
|
|
17
|
+
samples: Float32Array | Float64Array;
|
|
18
|
+
/** Image displacement at each temporal node in grid sites, interleaved (dx₀, dy₀, dx₁, dy₁, …); +x right, +y down. */
|
|
19
|
+
displacements: Float64Array;
|
|
20
|
+
/** Quadrature weights `[k][row]` (nodes × height), finite and non-negative, for example seconds of each row's window near t_k. */
|
|
21
|
+
rowWeights: Float32Array | Float64Array;
|
|
22
|
+
boundary: "zero-outside-grid";
|
|
23
|
+
}
|
|
24
|
+
/** One temporal node: integer source offset of the top-left tap and the four bilinear weights (float64). */
|
|
25
|
+
export interface TemporalExposureSumNode {
|
|
26
|
+
offsetX: number;
|
|
27
|
+
offsetY: number;
|
|
28
|
+
weights: readonly [number, number, number, number];
|
|
29
|
+
}
|
|
30
|
+
export interface TemporalExposureSumPlan {
|
|
31
|
+
width: number;
|
|
32
|
+
height: number;
|
|
33
|
+
nodeCount: number;
|
|
34
|
+
nodes: readonly TemporalExposureSumNode[];
|
|
35
|
+
maximumSampleMagnitude: number;
|
|
36
|
+
/** Largest Σ_k w_k(y) over rows; the operator's weight sum for error composition. */
|
|
37
|
+
maximumRowWeightSum: number;
|
|
38
|
+
maximumWeight: number;
|
|
39
|
+
/** True when every displacement is a whole number of sites (no interpolation). */
|
|
40
|
+
integerDisplacements: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** Validates the request (every value once) and returns its plan. */
|
|
43
|
+
export declare function calculateTemporalExposureSumPlan(input: TemporalExposureSumInput): TemporalExposureSumPlan;
|
|
44
|
+
/**
|
|
45
|
+
* Reference rows `[y0, y1)` into `output` at `(y − y0)·width + x`. The order (node ascending; taps 00,
|
|
46
|
+
* 10, 01, 11 summed left to right; then times the row weight) is part of the contract shared with the
|
|
47
|
+
* WGSL kernel.
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
export declare function sumTemporalExposureRows(plan: TemporalExposureSumPlan, samples: Float32Array | Float64Array, rowWeights: Float32Array | Float64Array, y0: number, y1: number, output: Float64Array): void;
|
|
51
|
+
/** Synchronous float64 reference for bounded grids. Use the image-kernel accelerator for large grids. */
|
|
52
|
+
export declare function calculateTemporalExposureSum(input: TemporalExposureSumInput): {
|
|
53
|
+
plan: TemporalExposureSumPlan;
|
|
54
|
+
values: Float64Array;
|
|
55
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Exposure and motion as a weighted sum of shifted frames (#277, image-formation step 3). The CPU
|
|
4
|
+
* float64 reference for the `webgpu-f32` temporal stage; see docs/WEBGPU.md.
|
|
5
|
+
*
|
|
6
|
+
* A site's exposure is the time integral of its image-plane rate quantity over its own exposure window,
|
|
7
|
+
* H = ∫ E(x, t) dt (EMVA Standard 1288 Release 4.0 Linear, §2, free; CIPA DC-004-2020 §5.5, free). For an
|
|
8
|
+
* image that translates rigidly by d(t) on the sensor, E(x, t) = E₀(x − d(t)), so a temporal quadrature
|
|
9
|
+
* with nodes t_k and weights w_k gives
|
|
10
|
+
*
|
|
11
|
+
* out(x, y) = Σ_k w_k(y) · E₀(x − dx_k, y − dy_k).
|
|
12
|
+
*
|
|
13
|
+
* Motion blur is this superposition of displaced images (Szeliski, *Computer Vision: Algorithms and
|
|
14
|
+
* Applications*, 2nd ed., 2022, free at https://szeliski.org/Book/). The weights depend on the row so a
|
|
15
|
+
* rolling shutter, whose rows start and end their exposure at different times, is the same sum with
|
|
16
|
+
* row-dependent windows (Meingast, Geyer & Sastry, "Geometric Models of Rolling-Shutter Cameras",
|
|
17
|
+
* arXiv:cs/0503076, free); a global shutter uses the same weights on every row.
|
|
18
|
+
*
|
|
19
|
+
* Declared approximations, owned by the caller: the quadrature nodes and weights, and rigid translation
|
|
20
|
+
* (no rotation, warp or occlusion). Sub-site displacements use bilinear interpolation between the four
|
|
21
|
+
* nearest site centres, which is linear interpolation and slightly low-pass; it is labelled as an
|
|
22
|
+
* approximation, not exact resampling. Sources outside the grid are zero; no padding or renormalization.
|
|
23
|
+
*/
|
|
24
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
25
|
+
import { requireAllowlistedRecord } from "../core/record-validation.js";
|
|
26
|
+
export const TEMPORAL_EXPOSURE_SUM_SCHEMA_VERSION = "0.1.0";
|
|
27
|
+
export const TEMPORAL_EXPOSURE_SUM_LIMITS = Object.freeze({
|
|
28
|
+
maximumPixels: 24_000_000,
|
|
29
|
+
maximumDimension: 16_384,
|
|
30
|
+
maximumTemporalSamples: 256,
|
|
31
|
+
maximumDisplacementSites: 4_096,
|
|
32
|
+
maximumRowWeights: 4_194_304,
|
|
33
|
+
/** Keeps every float32 partial sum finite: 256 · 2^16 · 2^100 < 2^128. */
|
|
34
|
+
maximumSampleMagnitude: 2 ** 100,
|
|
35
|
+
maximumWeight: 2 ** 16
|
|
36
|
+
});
|
|
37
|
+
function positiveInteger(value, maximum) {
|
|
38
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0 || value > maximum) {
|
|
39
|
+
throw new InvalidConfigurationError("Invalid temporal exposure sum geometry.");
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
/** Validates the request (every value once) and returns its plan. */
|
|
44
|
+
export function calculateTemporalExposureSumPlan(input) {
|
|
45
|
+
const r = requireAllowlistedRecord(input, ["schemaVersion", "width", "height", "samples", "displacements", "rowWeights", "boundary"], "Invalid temporal exposure sum input.");
|
|
46
|
+
const L = TEMPORAL_EXPOSURE_SUM_LIMITS;
|
|
47
|
+
if (r.schemaVersion !== TEMPORAL_EXPOSURE_SUM_SCHEMA_VERSION || r.boundary !== "zero-outside-grid") {
|
|
48
|
+
throw new InvalidConfigurationError("Unsupported temporal exposure sum schema or boundary.");
|
|
49
|
+
}
|
|
50
|
+
const width = positiveInteger(r.width, L.maximumDimension), height = positiveInteger(r.height, L.maximumDimension);
|
|
51
|
+
if (width * height > L.maximumPixels)
|
|
52
|
+
throw new InvalidConfigurationError("Temporal exposure sum grid exceeds the pixel limit.");
|
|
53
|
+
const samples = r.samples, displacements = r.displacements, weights = r.rowWeights;
|
|
54
|
+
if (!(displacements instanceof Float64Array) || displacements.length < 2 || displacements.length % 2 !== 0 ||
|
|
55
|
+
displacements.length / 2 > L.maximumTemporalSamples) {
|
|
56
|
+
throw new InvalidConfigurationError("Temporal exposure sum needs 1 to 256 displacement pairs.");
|
|
57
|
+
}
|
|
58
|
+
const nodeCount = displacements.length / 2;
|
|
59
|
+
if (!(samples instanceof Float32Array || samples instanceof Float64Array) || samples.length !== width * height ||
|
|
60
|
+
!(weights instanceof Float32Array || weights instanceof Float64Array) || weights.length !== nodeCount * height ||
|
|
61
|
+
weights.length > L.maximumRowWeights) {
|
|
62
|
+
throw new InvalidConfigurationError("Temporal exposure sum arrays do not match the declared geometry.");
|
|
63
|
+
}
|
|
64
|
+
let maximumSampleMagnitude = 0;
|
|
65
|
+
for (let i = 0; i < samples.length; i++) {
|
|
66
|
+
const v = samples[i];
|
|
67
|
+
if (!(v >= 0 && v <= L.maximumSampleMagnitude))
|
|
68
|
+
throw new InvalidConfigurationError("Temporal samples must be finite, non-negative and bounded.");
|
|
69
|
+
if (v > maximumSampleMagnitude)
|
|
70
|
+
maximumSampleMagnitude = v;
|
|
71
|
+
}
|
|
72
|
+
let maximumWeight = 0, maximumRowWeightSum = 0;
|
|
73
|
+
const rowSums = new Float64Array(height);
|
|
74
|
+
for (let k = 0; k < nodeCount; k++) {
|
|
75
|
+
for (let y = 0; y < height; y++) {
|
|
76
|
+
const w = weights[k * height + y];
|
|
77
|
+
if (!(w >= 0 && w <= L.maximumWeight))
|
|
78
|
+
throw new InvalidConfigurationError("Temporal row weights must be finite, non-negative and bounded.");
|
|
79
|
+
if (w > maximumWeight)
|
|
80
|
+
maximumWeight = w;
|
|
81
|
+
rowSums[y] += w;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
for (const s of rowSums)
|
|
85
|
+
if (s > maximumRowWeightSum)
|
|
86
|
+
maximumRowWeightSum = s;
|
|
87
|
+
let integerDisplacements = true;
|
|
88
|
+
const nodes = [];
|
|
89
|
+
for (let k = 0; k < nodeCount; k++) {
|
|
90
|
+
const dx = displacements[2 * k], dy = displacements[2 * k + 1];
|
|
91
|
+
if (!(Math.abs(dx) <= L.maximumDisplacementSites && Math.abs(dy) <= L.maximumDisplacementSites)) {
|
|
92
|
+
throw new InvalidConfigurationError("Temporal displacements must be finite and within 4096 sites.");
|
|
93
|
+
}
|
|
94
|
+
// Source position x − dx = x + offsetX + ax with ax in [0, 1).
|
|
95
|
+
const offsetX = Math.floor(-dx), offsetY = Math.floor(-dy), ax = -dx - offsetX, ay = -dy - offsetY;
|
|
96
|
+
if (ax !== 0 || ay !== 0)
|
|
97
|
+
integerDisplacements = false;
|
|
98
|
+
nodes.push(Object.freeze({ offsetX, offsetY,
|
|
99
|
+
weights: Object.freeze([(1 - ax) * (1 - ay), ax * (1 - ay), (1 - ax) * ay, ax * ay]) }));
|
|
100
|
+
}
|
|
101
|
+
return Object.freeze({ width, height, nodeCount, nodes: Object.freeze(nodes), maximumSampleMagnitude, maximumRowWeightSum, maximumWeight,
|
|
102
|
+
integerDisplacements });
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Reference rows `[y0, y1)` into `output` at `(y − y0)·width + x`. The order (node ascending; taps 00,
|
|
106
|
+
* 10, 01, 11 summed left to right; then times the row weight) is part of the contract shared with the
|
|
107
|
+
* WGSL kernel.
|
|
108
|
+
* @internal
|
|
109
|
+
*/
|
|
110
|
+
export function sumTemporalExposureRows(plan, samples, rowWeights, y0, y1, output) {
|
|
111
|
+
const { width, height, nodes } = plan;
|
|
112
|
+
for (let y = y0; y < y1; y++) {
|
|
113
|
+
for (let x = 0; x < width; x++) {
|
|
114
|
+
let sum = 0;
|
|
115
|
+
for (let k = 0; k < nodes.length; k++) {
|
|
116
|
+
const node = nodes[k], sx = x + node.offsetX, sy = y + node.offsetY, b = node.weights;
|
|
117
|
+
const left = sx >= 0 && sx < width, right = sx + 1 >= 0 && sx + 1 < width;
|
|
118
|
+
const top = sy >= 0 && sy < height, bottom = sy + 1 >= 0 && sy + 1 < height;
|
|
119
|
+
let inner = 0;
|
|
120
|
+
if (top && left)
|
|
121
|
+
inner += b[0] * samples[sy * width + sx];
|
|
122
|
+
if (top && right)
|
|
123
|
+
inner += b[1] * samples[sy * width + sx + 1];
|
|
124
|
+
if (bottom && left)
|
|
125
|
+
inner += b[2] * samples[(sy + 1) * width + sx];
|
|
126
|
+
if (bottom && right)
|
|
127
|
+
inner += b[3] * samples[(sy + 1) * width + sx + 1];
|
|
128
|
+
sum += rowWeights[k * height + y] * inner;
|
|
129
|
+
}
|
|
130
|
+
output[(y - y0) * width + x] = sum;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/** Synchronous float64 reference for bounded grids. Use the image-kernel accelerator for large grids. */
|
|
135
|
+
export function calculateTemporalExposureSum(input) {
|
|
136
|
+
const plan = calculateTemporalExposureSumPlan(input);
|
|
137
|
+
const values = new Float64Array(plan.width * plan.height);
|
|
138
|
+
sumTemporalExposureRows(plan, input.samples, input.rowWeights, 0, plan.height, values);
|
|
139
|
+
return { plan, values };
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=temporal-exposure-sum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temporal-exposure-sum.js","sourceRoot":"","sources":["../../src/motion/temporal-exposure-sum.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Exposure and motion as a weighted sum of shifted frames (#277, image-formation step 3). The CPU\n * float64 reference for the `webgpu-f32` temporal stage; see docs/WEBGPU.md.\n *\n * A site's exposure is the time integral of its image-plane rate quantity over its own exposure window,\n * H = ∫ E(x, t) dt (EMVA Standard 1288 Release 4.0 Linear, §2, free; CIPA DC-004-2020 §5.5, free). For an\n * image that translates rigidly by d(t) on the sensor, E(x, t) = E₀(x − d(t)), so a temporal quadrature\n * with nodes t_k and weights w_k gives\n *\n * out(x, y) = Σ_k w_k(y) · E₀(x − dx_k, y − dy_k).\n *\n * Motion blur is this superposition of displaced images (Szeliski, *Computer Vision: Algorithms and\n * Applications*, 2nd ed., 2022, free at https://szeliski.org/Book/). The weights depend on the row so a\n * rolling shutter, whose rows start and end their exposure at different times, is the same sum with\n * row-dependent windows (Meingast, Geyer & Sastry, \"Geometric Models of Rolling-Shutter Cameras\",\n * arXiv:cs/0503076, free); a global shutter uses the same weights on every row.\n *\n * Declared approximations, owned by the caller: the quadrature nodes and weights, and rigid translation\n * (no rotation, warp or occlusion). Sub-site displacements use bilinear interpolation between the four\n * nearest site centres, which is linear interpolation and slightly low-pass; it is labelled as an\n * approximation, not exact resampling. Sources outside the grid are zero; no padding or renormalization.\n */\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireAllowlistedRecord } from \"../core/record-validation.js\";\n\nexport const TEMPORAL_EXPOSURE_SUM_SCHEMA_VERSION = \"0.1.0\" as const;\nexport const TEMPORAL_EXPOSURE_SUM_LIMITS = Object.freeze({\n maximumPixels: 24_000_000,\n maximumDimension: 16_384,\n maximumTemporalSamples: 256,\n maximumDisplacementSites: 4_096,\n maximumRowWeights: 4_194_304,\n /** Keeps every float32 partial sum finite: 256 · 2^16 · 2^100 < 2^128. */\n maximumSampleMagnitude: 2 ** 100,\n maximumWeight: 2 ** 16\n});\n\nexport interface TemporalExposureSumInput {\n schemaVersion: typeof TEMPORAL_EXPOSURE_SUM_SCHEMA_VERSION;\n width: number;\n height: number;\n /** Row-major rate samples E₀ at site centres. Finite, non-negative, linear and additive (irradiance, photon or electron rate). */\n samples: Float32Array | Float64Array;\n /** Image displacement at each temporal node in grid sites, interleaved (dx₀, dy₀, dx₁, dy₁, …); +x right, +y down. */\n displacements: Float64Array;\n /** Quadrature weights `[k][row]` (nodes × height), finite and non-negative, for example seconds of each row's window near t_k. */\n rowWeights: Float32Array | Float64Array;\n boundary: \"zero-outside-grid\";\n}\n\n/** One temporal node: integer source offset of the top-left tap and the four bilinear weights (float64). */\nexport interface TemporalExposureSumNode {\n offsetX: number;\n offsetY: number;\n weights: readonly [number, number, number, number];\n}\n\nexport interface TemporalExposureSumPlan {\n width: number;\n height: number;\n nodeCount: number;\n nodes: readonly TemporalExposureSumNode[];\n maximumSampleMagnitude: number;\n /** Largest Σ_k w_k(y) over rows; the operator's weight sum for error composition. */\n maximumRowWeightSum: number;\n maximumWeight: number;\n /** True when every displacement is a whole number of sites (no interpolation). */\n integerDisplacements: boolean;\n}\n\nfunction positiveInteger(value: unknown, maximum: number): number {\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value <= 0 || value > maximum) {\n throw new InvalidConfigurationError(\"Invalid temporal exposure sum geometry.\");\n }\n return value;\n}\n\n/** Validates the request (every value once) and returns its plan. */\nexport function calculateTemporalExposureSumPlan(input: TemporalExposureSumInput): TemporalExposureSumPlan {\n const r = requireAllowlistedRecord(input, [\"schemaVersion\", \"width\", \"height\", \"samples\", \"displacements\", \"rowWeights\", \"boundary\"],\n \"Invalid temporal exposure sum input.\");\n const L = TEMPORAL_EXPOSURE_SUM_LIMITS;\n if (r.schemaVersion !== TEMPORAL_EXPOSURE_SUM_SCHEMA_VERSION || r.boundary !== \"zero-outside-grid\") {\n throw new InvalidConfigurationError(\"Unsupported temporal exposure sum schema or boundary.\");\n }\n const width = positiveInteger(r.width, L.maximumDimension), height = positiveInteger(r.height, L.maximumDimension);\n if (width * height > L.maximumPixels) throw new InvalidConfigurationError(\"Temporal exposure sum grid exceeds the pixel limit.\");\n const samples = r.samples, displacements = r.displacements, weights = r.rowWeights;\n if (!(displacements instanceof Float64Array) || displacements.length < 2 || displacements.length % 2 !== 0 ||\n displacements.length / 2 > L.maximumTemporalSamples) {\n throw new InvalidConfigurationError(\"Temporal exposure sum needs 1 to 256 displacement pairs.\");\n }\n const nodeCount = displacements.length / 2;\n if (!(samples instanceof Float32Array || samples instanceof Float64Array) || samples.length !== width * height ||\n !(weights instanceof Float32Array || weights instanceof Float64Array) || weights.length !== nodeCount * height ||\n weights.length > L.maximumRowWeights) {\n throw new InvalidConfigurationError(\"Temporal exposure sum arrays do not match the declared geometry.\");\n }\n let maximumSampleMagnitude = 0;\n for (let i = 0; i < samples.length; i++) {\n const v = samples[i]!;\n if (!(v >= 0 && v <= L.maximumSampleMagnitude)) throw new InvalidConfigurationError(\"Temporal samples must be finite, non-negative and bounded.\");\n if (v > maximumSampleMagnitude) maximumSampleMagnitude = v;\n }\n let maximumWeight = 0, maximumRowWeightSum = 0;\n const rowSums = new Float64Array(height);\n for (let k = 0; k < nodeCount; k++) {\n for (let y = 0; y < height; y++) {\n const w = weights[k * height + y]!;\n if (!(w >= 0 && w <= L.maximumWeight)) throw new InvalidConfigurationError(\"Temporal row weights must be finite, non-negative and bounded.\");\n if (w > maximumWeight) maximumWeight = w;\n rowSums[y]! += w;\n }\n }\n for (const s of rowSums) if (s > maximumRowWeightSum) maximumRowWeightSum = s;\n let integerDisplacements = true;\n const nodes: TemporalExposureSumNode[] = [];\n for (let k = 0; k < nodeCount; k++) {\n const dx = displacements[2 * k]!, dy = displacements[2 * k + 1]!;\n if (!(Math.abs(dx) <= L.maximumDisplacementSites && Math.abs(dy) <= L.maximumDisplacementSites)) {\n throw new InvalidConfigurationError(\"Temporal displacements must be finite and within 4096 sites.\");\n }\n // Source position x − dx = x + offsetX + ax with ax in [0, 1).\n const offsetX = Math.floor(-dx), offsetY = Math.floor(-dy), ax = -dx - offsetX, ay = -dy - offsetY;\n if (ax !== 0 || ay !== 0) integerDisplacements = false;\n nodes.push(Object.freeze({ offsetX, offsetY,\n weights: Object.freeze([(1 - ax) * (1 - ay), ax * (1 - ay), (1 - ax) * ay, ax * ay] as const) }));\n }\n return Object.freeze({ width, height, nodeCount, nodes: Object.freeze(nodes), maximumSampleMagnitude, maximumRowWeightSum, maximumWeight,\n integerDisplacements });\n}\n\n/**\n * Reference rows `[y0, y1)` into `output` at `(y − y0)·width + x`. The order (node ascending; taps 00,\n * 10, 01, 11 summed left to right; then times the row weight) is part of the contract shared with the\n * WGSL kernel.\n * @internal\n */\nexport function sumTemporalExposureRows(plan: TemporalExposureSumPlan, samples: Float32Array | Float64Array, rowWeights: Float32Array | Float64Array,\n y0: number, y1: number, output: Float64Array): void {\n const { width, height, nodes } = plan;\n for (let y = y0; y < y1; y++) {\n for (let x = 0; x < width; x++) {\n let sum = 0;\n for (let k = 0; k < nodes.length; k++) {\n const node = nodes[k]!, sx = x + node.offsetX, sy = y + node.offsetY, b = node.weights;\n const left = sx >= 0 && sx < width, right = sx + 1 >= 0 && sx + 1 < width;\n const top = sy >= 0 && sy < height, bottom = sy + 1 >= 0 && sy + 1 < height;\n let inner = 0;\n if (top && left) inner += b[0] * samples[sy * width + sx]!;\n if (top && right) inner += b[1] * samples[sy * width + sx + 1]!;\n if (bottom && left) inner += b[2] * samples[(sy + 1) * width + sx]!;\n if (bottom && right) inner += b[3] * samples[(sy + 1) * width + sx + 1]!;\n sum += rowWeights[k * height + y]! * inner;\n }\n output[(y - y0) * width + x] = sum;\n }\n }\n}\n\n/** Synchronous float64 reference for bounded grids. Use the image-kernel accelerator for large grids. */\nexport function calculateTemporalExposureSum(input: TemporalExposureSumInput): { plan: TemporalExposureSumPlan; values: Float64Array } {\n const plan = calculateTemporalExposureSumPlan(input);\n const values = new Float64Array(plan.width * plan.height);\n sumTemporalExposureRows(plan, input.samples, input.rowWeights, 0, plan.height, values);\n return { plan, values };\n}\n"]}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video frame sequences. Builds a deterministic sequence of frames from the "video" optical capture
|
|
3
|
+
* state (frameRateHz) and a shutter angle.
|
|
4
|
+
*
|
|
5
|
+
* Each frame is an ordinary ResolvedReleaseFrame, so the production capture snapshot and
|
|
6
|
+
* image-formation plan use it unchanged. An optional electronic rolling shutter gives every frame the
|
|
7
|
+
* same line-by-line exposure offsets. Frame timing, seeds and schedules depend only on the inputs and
|
|
8
|
+
* the absolute frame index. They never depend on how the sequence is split into chunks, or on
|
|
9
|
+
* earlier frames.
|
|
10
|
+
* @see docs/MOTION_AND_SIGNAL.md#video-frame-sequences for equations, conventions and limits.
|
|
11
|
+
*/
|
|
12
|
+
import { type EvidenceProvenance } from "../core/evidence-provenance.js";
|
|
13
|
+
import type { ReleaseAutomationState, ResolvedReleaseFrame } from "../capture/release-sequence.js";
|
|
14
|
+
import { type FocusPlane } from "../optics/focus-state.js";
|
|
15
|
+
import { type OpticalProfileState } from "../optics/profile-contract.js";
|
|
16
|
+
import { createRollingShutterCaptureExposureSchedule, type ElectronicRollingShutterExposureSchedule } from "../sensor/readout-exposure-linkage.js";
|
|
17
|
+
import type { RollingSensorReadoutTimingDeclaration } from "../sensor/readout-timing.js";
|
|
18
|
+
export declare const VIDEO_FRAME_SEQUENCE_VERSION: "1.0.0";
|
|
19
|
+
/** Stream identifier ("VIDF"). Keeps per-frame video seeds separate from per-site noise streams. */
|
|
20
|
+
export declare const VIDEO_FRAME_SEED_STREAM_ID: 1447642182;
|
|
21
|
+
/** Maximum frames per call. Resolve longer clips in chunks using firstFrameIndex. */
|
|
22
|
+
export declare const VIDEO_FRAME_SEQUENCE_MAXIMUM_FRAMES: 100000;
|
|
23
|
+
/**
|
|
24
|
+
* Exposure time for a shutter angle (as on a rotary film-camera shutter): t = (angle / 360) / frameRateHz.
|
|
25
|
+
* A 180° angle exposes for half of each frame period.
|
|
26
|
+
*/
|
|
27
|
+
export declare function calculateShutterAngleExposureSeconds(frameRateHz: number, shutterAngleDegrees: number): number;
|
|
28
|
+
/** Inverse of {@link calculateShutterAngleExposureSeconds}: angle = 360 · frameRateHz · t. */
|
|
29
|
+
export declare function calculateShutterAngleFromExposureSeconds(frameRateHz: number, exposureSeconds: number): number;
|
|
30
|
+
export interface ShutterAngleRuleAssessment {
|
|
31
|
+
frameRateHz: number;
|
|
32
|
+
shutterAngleDegrees: number;
|
|
33
|
+
exposureSeconds: number;
|
|
34
|
+
/** 1 / (2 · frameRateHz): the 180° convention. */
|
|
35
|
+
conventionExposureSeconds: number;
|
|
36
|
+
/** log2(exposure / convention): negative is shorter (crisper, more staccato) motion. */
|
|
37
|
+
deviationStops: number;
|
|
38
|
+
classification: "matches-180-degree-convention" | "shorter-than-convention" | "longer-than-convention";
|
|
39
|
+
/** The 180° rule is a cinematographic convention for motion-blur appearance, not a physical law. */
|
|
40
|
+
conventionNotPhysics: true;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Compares a shutter angle with the 180° cinematographic convention (exposure = half the frame
|
|
44
|
+
* period). Within a relative 1e-9 the angle "matches". Otherwise the signed deviation is reported.
|
|
45
|
+
*/
|
|
46
|
+
export declare function assessShutterAngleRule(frameRateHz: number, shutterAngleDegrees: number): ShutterAngleRuleAssessment;
|
|
47
|
+
export interface ResolveVideoFrameSequenceInput {
|
|
48
|
+
sequenceId: string;
|
|
49
|
+
/** Exact optical capture state. captureMode must be "video", with a positive frameRateHz. */
|
|
50
|
+
opticalState: OpticalProfileState;
|
|
51
|
+
/** Shutter angle in (0, 360]; exposure = angle / 360 / frameRateHz. */
|
|
52
|
+
shutterAngleDegrees: number;
|
|
53
|
+
/** Absolute index of the first frame to resolve (default 0). */
|
|
54
|
+
firstFrameIndex?: number;
|
|
55
|
+
frameCount: number;
|
|
56
|
+
sequenceSeedUint32: number;
|
|
57
|
+
iso: number;
|
|
58
|
+
/** Defaults to the optical state's finite focus distance. */
|
|
59
|
+
focus?: FocusPlane;
|
|
60
|
+
automation: {
|
|
61
|
+
ae: ReleaseAutomationState;
|
|
62
|
+
af: ReleaseAutomationState;
|
|
63
|
+
awb: ReleaseAutomationState;
|
|
64
|
+
};
|
|
65
|
+
whiteBalanceStateId?: string;
|
|
66
|
+
/** Evidence for the commanded frame rate and shutter-angle timing. Used for the exposure fact. */
|
|
67
|
+
timingEvidence: readonly EvidenceProvenance[];
|
|
68
|
+
/** Optional electronic rolling shutter applied identically to every frame. */
|
|
69
|
+
rollingShutter?: {
|
|
70
|
+
readout: RollingSensorReadoutTimingDeclaration;
|
|
71
|
+
linkageEvidence: readonly EvidenceProvenance[];
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export interface VideoFrameSequence {
|
|
75
|
+
version: typeof VIDEO_FRAME_SEQUENCE_VERSION;
|
|
76
|
+
sequenceId: string;
|
|
77
|
+
frameRateHz: number;
|
|
78
|
+
framePeriodSeconds: number;
|
|
79
|
+
shutterAngleDegrees: number;
|
|
80
|
+
exposureSeconds: number;
|
|
81
|
+
shutterAngleRule: ShutterAngleRuleAssessment;
|
|
82
|
+
firstFrameIndex: number;
|
|
83
|
+
frameCount: number;
|
|
84
|
+
sequenceSeedUint32: number;
|
|
85
|
+
seedDerivation: "murmur3-x86-32(sequenceSeed, absoluteFrameIndex, VIDEO_FRAME_SEED_STREAM_ID)";
|
|
86
|
+
frameTimeDerivation: "absoluteFrameIndex / frameRateHz";
|
|
87
|
+
/**
|
|
88
|
+
* Exposure schedule for each frame. It is the same for every frame; times are relative to each
|
|
89
|
+
* frame's own first-opening phase. Null when no rolling shutter is declared; the caller then
|
|
90
|
+
* supplies the global schedule of its capture mode.
|
|
91
|
+
*/
|
|
92
|
+
exposureSchedule: ReturnType<typeof createRollingShutterCaptureExposureSchedule> | null;
|
|
93
|
+
rollingShutter: Pick<ElectronicRollingShutterExposureSchedule, "modelId" | "modelVersion" | "lineScanSkewSeconds" | "linkage"> | null;
|
|
94
|
+
/** Ordinary release frames: pass each to createProductionCaptureSnapshotFromReleaseFrame. */
|
|
95
|
+
frames: readonly ResolvedReleaseFrame[];
|
|
96
|
+
limitations: readonly string[];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Resolves `frameCount` consecutive video frames starting at `firstFrameIndex`.
|
|
100
|
+
*
|
|
101
|
+
* Frame k (absolute index) opens k / frameRateHz seconds after the sequence starts, and exposes for
|
|
102
|
+
* (angle / 360) / frameRateHz. Its random seed is a MurmurHash3 of (sequence seed, k, stream id).
|
|
103
|
+
*
|
|
104
|
+
* Every value depends only on the inputs and k. So resolving frames 0–99 at once, or as 0–49 then
|
|
105
|
+
* 50–99, gives identical frames.
|
|
106
|
+
*
|
|
107
|
+
* With a rolling shutter, the line at normalized scan position s in frame k integrates over
|
|
108
|
+
* [k/f + s·τ, k/f + s·τ + T]. τ must not exceed the frame period, so each line is read once per
|
|
109
|
+
* frame.
|
|
110
|
+
*/
|
|
111
|
+
export declare function resolveVideoFrameSequence(input: ResolveVideoFrameSequenceInput): VideoFrameSequence;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Video frame sequences. Builds a deterministic sequence of frames from the "video" optical capture
|
|
4
|
+
* state (frameRateHz) and a shutter angle.
|
|
5
|
+
*
|
|
6
|
+
* Each frame is an ordinary ResolvedReleaseFrame, so the production capture snapshot and
|
|
7
|
+
* image-formation plan use it unchanged. An optional electronic rolling shutter gives every frame the
|
|
8
|
+
* same line-by-line exposure offsets. Frame timing, seeds and schedules depend only on the inputs and
|
|
9
|
+
* the absolute frame index. They never depend on how the sequence is split into chunks, or on
|
|
10
|
+
* earlier frames.
|
|
11
|
+
* @see docs/MOTION_AND_SIGNAL.md#video-frame-sequences for equations, conventions and limits.
|
|
12
|
+
*/
|
|
13
|
+
import { parseEvidenceList } from "../core/evidence-provenance.js";
|
|
14
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
15
|
+
import { rejectUnknownFields, requireInputObject, requirePublicOpaqueId, requireInputKeys } from "../core/record-validation.js";
|
|
16
|
+
import { InvalidScientificInputError } from "../core/validation.js";
|
|
17
|
+
import { parseFocusPlane } from "../optics/focus-state.js";
|
|
18
|
+
import { parseOpticalProfileState } from "../optics/profile-contract.js";
|
|
19
|
+
import { resolveElectronicRollingShutterExposureSchedule, ELECTRONIC_ROLLING_SHUTTER_MODEL, createRollingShutterCaptureExposureSchedule } from "../sensor/readout-exposure-linkage.js";
|
|
20
|
+
import { deriveNativeSiteStreamSeedUint32 } from "../sensor/stochastic-seed.js";
|
|
21
|
+
export const VIDEO_FRAME_SEQUENCE_VERSION = "1.0.0";
|
|
22
|
+
/** Stream identifier ("VIDF"). Keeps per-frame video seeds separate from per-site noise streams. */
|
|
23
|
+
export const VIDEO_FRAME_SEED_STREAM_ID = 0x56494446;
|
|
24
|
+
/** Maximum frames per call. Resolve longer clips in chunks using firstFrameIndex. */
|
|
25
|
+
export const VIDEO_FRAME_SEQUENCE_MAXIMUM_FRAMES = 100_000;
|
|
26
|
+
function requireFrameRate(frameRateHz) {
|
|
27
|
+
if (typeof frameRateHz !== "number" || !Number.isFinite(frameRateHz) || frameRateHz <= 0) {
|
|
28
|
+
throw new InvalidScientificInputError("frameRateHz must be a finite number greater than zero.");
|
|
29
|
+
}
|
|
30
|
+
return frameRateHz;
|
|
31
|
+
}
|
|
32
|
+
function requireShutterAngle(shutterAngleDegrees) {
|
|
33
|
+
if (typeof shutterAngleDegrees !== "number" || !Number.isFinite(shutterAngleDegrees) ||
|
|
34
|
+
shutterAngleDegrees <= 0 || shutterAngleDegrees > 360) {
|
|
35
|
+
throw new InvalidScientificInputError("shutterAngleDegrees must lie in (0, 360].");
|
|
36
|
+
}
|
|
37
|
+
return shutterAngleDegrees;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Exposure time for a shutter angle (as on a rotary film-camera shutter): t = (angle / 360) / frameRateHz.
|
|
41
|
+
* A 180° angle exposes for half of each frame period.
|
|
42
|
+
*/
|
|
43
|
+
export function calculateShutterAngleExposureSeconds(frameRateHz, shutterAngleDegrees) {
|
|
44
|
+
return requireShutterAngle(shutterAngleDegrees) / 360 / requireFrameRate(frameRateHz);
|
|
45
|
+
}
|
|
46
|
+
/** Inverse of {@link calculateShutterAngleExposureSeconds}: angle = 360 · frameRateHz · t. */
|
|
47
|
+
export function calculateShutterAngleFromExposureSeconds(frameRateHz, exposureSeconds) {
|
|
48
|
+
if (typeof exposureSeconds !== "number" || !Number.isFinite(exposureSeconds) || exposureSeconds <= 0) {
|
|
49
|
+
throw new InvalidScientificInputError("exposureSeconds must be a finite number greater than zero.");
|
|
50
|
+
}
|
|
51
|
+
const angle = 360 * requireFrameRate(frameRateHz) * exposureSeconds;
|
|
52
|
+
if (angle > 360 * (1 + 1e-12)) {
|
|
53
|
+
throw new InvalidScientificInputError("Exposure longer than one frame period has no shutter angle.");
|
|
54
|
+
}
|
|
55
|
+
return Math.min(360, angle);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Compares a shutter angle with the 180° cinematographic convention (exposure = half the frame
|
|
59
|
+
* period). Within a relative 1e-9 the angle "matches". Otherwise the signed deviation is reported.
|
|
60
|
+
*/
|
|
61
|
+
export function assessShutterAngleRule(frameRateHz, shutterAngleDegrees) {
|
|
62
|
+
const exposureSeconds = calculateShutterAngleExposureSeconds(frameRateHz, shutterAngleDegrees);
|
|
63
|
+
const conventionExposureSeconds = 1 / (2 * frameRateHz);
|
|
64
|
+
const ratio = exposureSeconds / conventionExposureSeconds;
|
|
65
|
+
return {
|
|
66
|
+
frameRateHz, shutterAngleDegrees, exposureSeconds, conventionExposureSeconds,
|
|
67
|
+
deviationStops: Math.log2(ratio),
|
|
68
|
+
classification: Math.abs(ratio - 1) <= 1e-9 ? "matches-180-degree-convention"
|
|
69
|
+
: ratio < 1 ? "shorter-than-convention" : "longer-than-convention",
|
|
70
|
+
conventionNotPhysics: true
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Resolves `frameCount` consecutive video frames starting at `firstFrameIndex`.
|
|
75
|
+
*
|
|
76
|
+
* Frame k (absolute index) opens k / frameRateHz seconds after the sequence starts, and exposes for
|
|
77
|
+
* (angle / 360) / frameRateHz. Its random seed is a MurmurHash3 of (sequence seed, k, stream id).
|
|
78
|
+
*
|
|
79
|
+
* Every value depends only on the inputs and k. So resolving frames 0–99 at once, or as 0–49 then
|
|
80
|
+
* 50–99, gives identical frames.
|
|
81
|
+
*
|
|
82
|
+
* With a rolling shutter, the line at normalized scan position s in frame k integrates over
|
|
83
|
+
* [k/f + s·τ, k/f + s·τ + T]. τ must not exceed the frame period, so each line is read once per
|
|
84
|
+
* frame.
|
|
85
|
+
*/
|
|
86
|
+
export function resolveVideoFrameSequence(input) {
|
|
87
|
+
requireInputKeys(input, "resolveVideoFrameSequence", ["sequenceId", "opticalState", "shutterAngleDegrees", "firstFrameIndex", "frameCount", "sequenceSeedUint32", "iso", "focus", "automation", "whiteBalanceStateId", "timingEvidence", "rollingShutter"]);
|
|
88
|
+
requireInputObject(input.automation, "resolveVideoFrameSequence automation");
|
|
89
|
+
rejectUnknownFields(input.automation, ["ae", "af", "awb"], "resolveVideoFrameSequence automation");
|
|
90
|
+
if (input.rollingShutter !== undefined) {
|
|
91
|
+
requireInputObject(input.rollingShutter, "resolveVideoFrameSequence rollingShutter");
|
|
92
|
+
rejectUnknownFields(input.rollingShutter, ["readout", "linkageEvidence"], "resolveVideoFrameSequence rollingShutter");
|
|
93
|
+
}
|
|
94
|
+
const sequenceId = requirePublicOpaqueId(input.sequenceId, "Invalid video sequence ID.");
|
|
95
|
+
const optical = parseOpticalProfileState(input.opticalState);
|
|
96
|
+
if (optical.captureMode !== "video") {
|
|
97
|
+
throw new InvalidConfigurationError("Video frame sequences require an optical state with captureMode \"video\".");
|
|
98
|
+
}
|
|
99
|
+
const frameRateHz = optical.frameRateHz;
|
|
100
|
+
const shutterAngleDegrees = requireShutterAngle(input.shutterAngleDegrees);
|
|
101
|
+
const exposureSeconds = calculateShutterAngleExposureSeconds(frameRateHz, shutterAngleDegrees);
|
|
102
|
+
const first = input.firstFrameIndex ?? 0;
|
|
103
|
+
if (!Number.isSafeInteger(first) || first < 0 || !Number.isSafeInteger(input.frameCount) || input.frameCount < 1 ||
|
|
104
|
+
input.frameCount > VIDEO_FRAME_SEQUENCE_MAXIMUM_FRAMES || first + input.frameCount - 1 > 0xffffffff) {
|
|
105
|
+
throw new InvalidScientificInputError("Video frames need a non-negative first index, 1–100000 frames and uint32 frame indices.");
|
|
106
|
+
}
|
|
107
|
+
const seed = input.sequenceSeedUint32;
|
|
108
|
+
if (!Number.isInteger(seed) || seed < 0 || seed > 0xffffffff) {
|
|
109
|
+
throw new InvalidScientificInputError("sequenceSeedUint32 must be a uint32 integer.");
|
|
110
|
+
}
|
|
111
|
+
if (typeof input.iso !== "number" || !Number.isFinite(input.iso) || input.iso <= 0) {
|
|
112
|
+
throw new InvalidScientificInputError("iso must be a finite number greater than zero.");
|
|
113
|
+
}
|
|
114
|
+
const timingEvidence = parseEvidenceList(input.timingEvidence, "video.timingEvidence");
|
|
115
|
+
const focus = parseFocusPlane(input.focus ?? { kind: "finite", distanceM: optical.focusDistanceM });
|
|
116
|
+
const automation = { ae: input.automation.ae, af: input.automation.af, awb: input.automation.awb };
|
|
117
|
+
for (const state of Object.values(automation)) {
|
|
118
|
+
if (state !== "manual" && state !== "locked" && state !== "continuous") {
|
|
119
|
+
throw new InvalidConfigurationError("Video automation states must be manual, locked or continuous.");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const whiteBalanceStateId = input.whiteBalanceStateId === undefined ? undefined
|
|
123
|
+
: requirePublicOpaqueId(input.whiteBalanceStateId, "Invalid white-balance state ID.");
|
|
124
|
+
const framePeriodSeconds = 1 / frameRateHz;
|
|
125
|
+
let rolling = null;
|
|
126
|
+
if (input.rollingShutter !== undefined) {
|
|
127
|
+
rolling = resolveElectronicRollingShutterExposureSchedule({ readout: input.rollingShutter.readout,
|
|
128
|
+
nominalExposureDurationSeconds: { value: exposureSeconds, unit: "s", evidence: timingEvidence },
|
|
129
|
+
linkageEvidence: input.rollingShutter.linkageEvidence });
|
|
130
|
+
if (rolling.lineScanSkewSeconds > framePeriodSeconds) {
|
|
131
|
+
throw new InvalidScientificInputError("Rolling-shutter line skew exceeds the video frame period; lines cannot be read once per frame.");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const start = (index) => index / frameRateHz;
|
|
135
|
+
const frames = Array.from({ length: input.frameCount }, (_, offset) => {
|
|
136
|
+
const frameIndex = first + offset, exposureStartTimeSeconds = start(frameIndex);
|
|
137
|
+
return {
|
|
138
|
+
sequenceId,
|
|
139
|
+
frameIndex,
|
|
140
|
+
releaseFrameId: sequenceId + ":video:" + frameIndex,
|
|
141
|
+
exposureStartTimeSeconds,
|
|
142
|
+
exposureEndTimeSeconds: exposureStartTimeSeconds + exposureSeconds,
|
|
143
|
+
sceneTimeSecondsFromSequenceStart: exposureStartTimeSeconds,
|
|
144
|
+
startIntervalFromPreviousSeconds: frameIndex === 0 ? null : exposureStartTimeSeconds - start(frameIndex - 1),
|
|
145
|
+
timingConstraints: ["requested-cadence"],
|
|
146
|
+
stochasticSeedUint32: deriveNativeSiteStreamSeedUint32(seed, frameIndex, VIDEO_FRAME_SEED_STREAM_ID),
|
|
147
|
+
exposure: { aperture: optical.aperture, shutterSeconds: exposureSeconds, iso: input.iso },
|
|
148
|
+
focus: { ...focus },
|
|
149
|
+
automation: { ...automation },
|
|
150
|
+
...(whiteBalanceStateId === undefined ? {} : { whiteBalanceStateId })
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
return {
|
|
154
|
+
version: VIDEO_FRAME_SEQUENCE_VERSION,
|
|
155
|
+
sequenceId,
|
|
156
|
+
frameRateHz,
|
|
157
|
+
framePeriodSeconds,
|
|
158
|
+
shutterAngleDegrees,
|
|
159
|
+
exposureSeconds,
|
|
160
|
+
shutterAngleRule: assessShutterAngleRule(frameRateHz, shutterAngleDegrees),
|
|
161
|
+
firstFrameIndex: first,
|
|
162
|
+
frameCount: input.frameCount,
|
|
163
|
+
sequenceSeedUint32: seed,
|
|
164
|
+
seedDerivation: "murmur3-x86-32(sequenceSeed, absoluteFrameIndex, VIDEO_FRAME_SEED_STREAM_ID)",
|
|
165
|
+
frameTimeDerivation: "absoluteFrameIndex / frameRateHz",
|
|
166
|
+
exposureSchedule: rolling === null ? null : createRollingShutterCaptureExposureSchedule(rolling),
|
|
167
|
+
rollingShutter: rolling === null ? null : { modelId: ELECTRONIC_ROLLING_SHUTTER_MODEL.id,
|
|
168
|
+
modelVersion: ELECTRONIC_ROLLING_SHUTTER_MODEL.version, lineScanSkewSeconds: rolling.lineScanSkewSeconds,
|
|
169
|
+
linkage: rolling.linkage },
|
|
170
|
+
frames,
|
|
171
|
+
limitations: [
|
|
172
|
+
"Frame timing is ideal: no frame-rate drift, dropped frames, variable frame rate or sensor-mode switching.",
|
|
173
|
+
"Exposure follows the shutter-angle relation t = angle/360/f; automatic exposure between frames is not modeled.",
|
|
174
|
+
"The 180-degree rule is reported as a cinematographic convention, not a physical requirement.",
|
|
175
|
+
"Video encoding, compression, temporal noise reduction and frame interpolation are not modeled."
|
|
176
|
+
]
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=video-sequence.js.map
|