@photivra/engine 1.5.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +414 -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 +116 -9
- package/dist/capture/native-raw-development.js +221 -62
- 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 +65 -12
- package/dist/capture/native-raw.js +81 -19
- 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/diffraction-provider.d.ts +30 -0
- package/dist/facade/diffraction-provider.js +127 -0
- package/dist/facade/diffraction-provider.js.map +1 -0
- package/dist/facade/host-yield.d.ts +7 -0
- package/dist/facade/host-yield.js +19 -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 +363 -0
- package/dist/facade/simulate-capture.js +1281 -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 +91 -25
- package/dist/index.js +60 -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-psf-profile.d.ts +118 -0
- package/dist/optics/diffraction-psf-profile.js +252 -0
- package/dist/optics/diffraction-psf-profile.js.map +1 -0
- 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 +777 -2
- package/docs/QUICK_START.md +663 -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 -8
- package/docs/api/capture-native-raw-dng.md +84 -0
- package/docs/api/capture-native-raw.md +21 -10
- 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 +2253 -3
- 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 +397 -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-psf-profile.md +96 -0
- 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 -11
- 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/DENSE_PUPIL_QUALIFICATION.md +0 -121
- 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 -54
- 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_1_5_0.md +0 -105
- 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/SEPARABLE_EMISSION_DRAFT.md +0 -103
- 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/dense-pupil-2026-10-06/pilot.jsonl +0 -6
- 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
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Procedural test charts for the capture facade, written for this engine. Every chart is a flat,
|
|
4
|
+
* Lambertian (matte) reflectance pattern, defined by formulas in normalized frame coordinates. No
|
|
5
|
+
* third-party chart data (for example ColorChecker reflectances) is bundled. Coloured patches use
|
|
6
|
+
* spectra that the caller supplies.
|
|
7
|
+
*
|
|
8
|
+
* Frame coordinates: `u` runs from -1 (left edge of the framed chart) to +1 (right edge); `v` points up
|
|
9
|
+
* and has the same scale, so it runs from -aspect to +aspect where aspect = height/width of the frame.
|
|
10
|
+
* The facade places the chart perpendicular to the optical axis at the subject distance and sizes it so
|
|
11
|
+
* that this rectangle exactly fills the active capture (see `SimulateCaptureResult.assumptions`).
|
|
12
|
+
*
|
|
13
|
+
* The slanted edge follows the geometry described by P. D. Burns, "Slanted-Edge MTF for Digital Camera
|
|
14
|
+
* and Scanner Analysis", IS&T PICS 2000 (free from imaging.org; also ISO 12233). It is a near-vertical
|
|
15
|
+
* edge rotated by a few degrees (5 degrees by default), with a 4:1 light/dark reflectance ratio by
|
|
16
|
+
* default. This is only a geometric description. No measured chart or ISO test procedure is copied.
|
|
17
|
+
* @see docs/QUICK_START.md for the chart catalogue and their analytic definitions.
|
|
18
|
+
*/
|
|
19
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
20
|
+
import { prepareColorimetricSpectrum } from "../color/color-matching-functions.js";
|
|
21
|
+
import { requireInputObject, requireInputKeys } from "../core/record-validation.js";
|
|
22
|
+
export const CHART_SCENE_PRESETS = Object.freeze(["uniform", "slanted-edge", "siemens-star",
|
|
23
|
+
"step-wedge", "grey-ramp", "checkerboard", "point-grid", "patches"]);
|
|
24
|
+
/** Engine-chosen chart parameters, each reported when the caller omitted it. */
|
|
25
|
+
export const CHART_SCENE_DEFAULTS = Object.freeze({
|
|
26
|
+
uniform: Object.freeze({ reflectance: 0.18 }),
|
|
27
|
+
"slanted-edge": Object.freeze({ angleDegrees: 5, darkReflectance: 0.15, lightReflectance: 0.6 }),
|
|
28
|
+
"siemens-star": Object.freeze({ cycles: 36, radiusFraction: 0.9, darkReflectance: 0.05, lightReflectance: 0.8, backgroundReflectance: 0.18 }),
|
|
29
|
+
"step-wedge": Object.freeze({ steps: 11, minimumReflectance: 0.03, maximumReflectance: 0.9, spacing: "equal-density" }),
|
|
30
|
+
"grey-ramp": Object.freeze({ minimumReflectance: 0.03, maximumReflectance: 0.9 }),
|
|
31
|
+
checkerboard: Object.freeze({ squaresAcross: 8, darkReflectance: 0.05, lightReflectance: 0.8 }),
|
|
32
|
+
"point-grid": Object.freeze({ columns: 5, rows: 3, radius: 0.01, pointReflectance: 0.9, backgroundReflectance: 0.02 }),
|
|
33
|
+
patches: Object.freeze({ gapFraction: 0.1, backgroundReflectance: 0.18 })
|
|
34
|
+
});
|
|
35
|
+
function reflectance(value, name) {
|
|
36
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1)
|
|
37
|
+
throw new InvalidConfigurationError(name + " must be a reflectance in [0, 1].");
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
function integerIn(value, name, minimum, maximum) {
|
|
41
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum || value > maximum)
|
|
42
|
+
throw new InvalidConfigurationError(name + " must be an integer from " + minimum + " to " + maximum + ".");
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
function finiteIn(value, name, minimum, maximum, open = false) {
|
|
46
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < minimum || value > maximum || (open && (value === minimum || value === maximum)))
|
|
47
|
+
throw new InvalidConfigurationError(name + " is outside its supported range.");
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
/** Wavelength range every chart spectrum must cover (the facade's sensor quadrature range). */
|
|
51
|
+
export const CHART_SPECTRAL_RANGE_NANOMETERS = Object.freeze({ minimum: 380, maximum: 780 });
|
|
52
|
+
function material(value, name) {
|
|
53
|
+
if (typeof value === "number")
|
|
54
|
+
return { kind: "neutral", reflectance: reflectance(value, name) };
|
|
55
|
+
let spectrum;
|
|
56
|
+
try {
|
|
57
|
+
spectrum = prepareColorimetricSpectrum(value, name);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
throw new InvalidConfigurationError(name + " must be a neutral reflectance or a valid reflectance spectrum: " + (error instanceof Error ? error.message : "invalid"));
|
|
61
|
+
}
|
|
62
|
+
const range = spectrum.wavelengthRangeNanometers;
|
|
63
|
+
if (range.minimum > CHART_SPECTRAL_RANGE_NANOMETERS.minimum || range.maximum < CHART_SPECTRAL_RANGE_NANOMETERS.maximum)
|
|
64
|
+
throw new InvalidConfigurationError(name + " must cover 380-780 nm.");
|
|
65
|
+
for (let nm = CHART_SPECTRAL_RANGE_NANOMETERS.minimum; nm <= CHART_SPECTRAL_RANGE_NANOMETERS.maximum; nm += 5)
|
|
66
|
+
reflectance(spectrum.evaluate(nm), name + " values");
|
|
67
|
+
return { kind: "spectrum", spectrum };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Validates a chart description and resolves every default. `aspect` is the frame height/width. Unknown
|
|
71
|
+
* fields are rejected so that a mistyped parameter never silently falls back to a default.
|
|
72
|
+
*/
|
|
73
|
+
export function resolveChartScene(input) {
|
|
74
|
+
requireInputObject(input, "resolveChartScene input");
|
|
75
|
+
for (const key of Object.keys(input))
|
|
76
|
+
if (key !== "scene" && key !== "aspect")
|
|
77
|
+
throw new InvalidConfigurationError("resolveChartScene input has unknown field \"" + key + "\".");
|
|
78
|
+
const { scene, aspect } = input;
|
|
79
|
+
requireInputObject(scene, "chart scene");
|
|
80
|
+
if (typeof aspect !== "number" || !Number.isFinite(aspect) || aspect <= 0)
|
|
81
|
+
throw new InvalidConfigurationError("Chart aspect must be positive.");
|
|
82
|
+
const preset = scene.preset;
|
|
83
|
+
if (typeof preset !== "string" || !CHART_SCENE_PRESETS.includes(preset))
|
|
84
|
+
throw new InvalidConfigurationError("Unknown chart preset.");
|
|
85
|
+
const record = scene;
|
|
86
|
+
const defaults = CHART_SCENE_DEFAULTS[preset];
|
|
87
|
+
const allowed = ["preset", ...Object.keys(defaults), ...(preset === "patches" ? ["patches", "columns"] : [])];
|
|
88
|
+
for (const key of Object.keys(record))
|
|
89
|
+
if (!allowed.includes(key))
|
|
90
|
+
throw new InvalidConfigurationError("Unknown chart parameter: " + key + ".");
|
|
91
|
+
const defaulted = [];
|
|
92
|
+
const get = (key) => { if (record[key] === undefined) {
|
|
93
|
+
if (key in defaults)
|
|
94
|
+
defaulted.push(key);
|
|
95
|
+
return defaults[key];
|
|
96
|
+
} return record[key]; };
|
|
97
|
+
const neutral = (key) => reflectance(get(key), key);
|
|
98
|
+
const done = (parameters, materials, materialAt) => Object.freeze({ preset: preset, parameters: Object.freeze(parameters), defaultedParameters: Object.freeze(defaulted), aspect, materials: Object.freeze(materials), materialAt,
|
|
99
|
+
reflectanceAt(u, v, nm) {
|
|
100
|
+
const m = materials[materialAt(u, v)];
|
|
101
|
+
if (m.kind === "neutral")
|
|
102
|
+
return m.reflectance;
|
|
103
|
+
const value = m.spectrum.evaluate(nm);
|
|
104
|
+
if (!(value >= 0 && value <= 1))
|
|
105
|
+
throw new InvalidConfigurationError("Chart reflectance spectrum left [0, 1].");
|
|
106
|
+
return value;
|
|
107
|
+
} });
|
|
108
|
+
switch (preset) {
|
|
109
|
+
case "uniform": {
|
|
110
|
+
const raw = get("reflectance"), m = material(raw, "reflectance");
|
|
111
|
+
return done({ reflectance: typeof raw === "number" ? raw : "caller-spectrum" }, [m], () => 0);
|
|
112
|
+
}
|
|
113
|
+
case "slanted-edge": {
|
|
114
|
+
const angle = finiteIn(get("angleDegrees"), "angleDegrees", -45, 45, true), dark = neutral("darkReflectance"), light = neutral("lightReflectance");
|
|
115
|
+
const t = angle * Math.PI / 180, c = Math.cos(t), s = Math.sin(t);
|
|
116
|
+
// Edge through the frame centre along (sin t, cos t); the light side is to the right.
|
|
117
|
+
return done({ angleDegrees: angle, darkReflectance: dark, lightReflectance: light }, [{ kind: "neutral", reflectance: dark }, { kind: "neutral", reflectance: light }], (u, v) => (u * c - v * s >= 0 ? 1 : 0));
|
|
118
|
+
}
|
|
119
|
+
case "siemens-star": {
|
|
120
|
+
const cycles = integerIn(get("cycles"), "cycles", 2, 360), radius = finiteIn(get("radiusFraction"), "radiusFraction", 0, 1, false);
|
|
121
|
+
if (radius === 0)
|
|
122
|
+
throw new InvalidConfigurationError("radiusFraction must be positive.");
|
|
123
|
+
const dark = neutral("darkReflectance"), light = neutral("lightReflectance"), background = neutral("backgroundReflectance"), r = radius * aspect;
|
|
124
|
+
return done({ cycles, radiusFraction: radius, darkReflectance: dark, lightReflectance: light, backgroundReflectance: background }, [{ kind: "neutral", reflectance: dark }, { kind: "neutral", reflectance: light }, { kind: "neutral", reflectance: background }], (u, v) => {
|
|
125
|
+
if (u * u + v * v > r * r)
|
|
126
|
+
return 2;
|
|
127
|
+
const phase = Math.atan2(v, u) / (2 * Math.PI) + 0.5; // [0, 1]
|
|
128
|
+
return Math.floor(phase * 2 * cycles) % 2 === 0 ? 1 : 0;
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
case "step-wedge": {
|
|
132
|
+
const steps = integerIn(get("steps"), "steps", 2, 64), lo = neutral("minimumReflectance"), hi = neutral("maximumReflectance"), spacing = get("spacing");
|
|
133
|
+
if (spacing !== "equal-density" && spacing !== "linear")
|
|
134
|
+
throw new InvalidConfigurationError("spacing must be equal-density or linear.");
|
|
135
|
+
if (!(hi > lo) || (spacing === "equal-density" && lo <= 0))
|
|
136
|
+
throw new InvalidConfigurationError("Step wedge needs 0 < minimum < maximum reflectance.");
|
|
137
|
+
const values = calculateStepWedgeReflectances({ steps, minimumReflectance: lo, maximumReflectance: hi, spacing });
|
|
138
|
+
return done({ steps, minimumReflectance: lo, maximumReflectance: hi, spacing, stepReflectances: values }, values.map((reflectanceValue) => ({ kind: "neutral", reflectance: reflectanceValue })), (u) => Math.min(steps - 1, Math.max(0, Math.floor((u + 1) / 2 * steps))));
|
|
139
|
+
}
|
|
140
|
+
case "grey-ramp": {
|
|
141
|
+
const lo = neutral("minimumReflectance"), hi = neutral("maximumReflectance");
|
|
142
|
+
if (!(hi > lo))
|
|
143
|
+
throw new InvalidConfigurationError("Grey ramp needs minimum < maximum reflectance.");
|
|
144
|
+
// A continuous ramp is stored as 1024 neutral levels. The step size (< 0.1 % of the range) is far below sensor noise.
|
|
145
|
+
const levels = 1024, materials = Array.from({ length: levels }, (_, i) => ({ kind: "neutral", reflectance: lo + (hi - lo) * (i + 0.5) / levels }));
|
|
146
|
+
return done({ minimumReflectance: lo, maximumReflectance: hi, representation: "1024 equal neutral levels" }, materials, (u) => Math.min(levels - 1, Math.max(0, Math.floor((u + 1) / 2 * levels))));
|
|
147
|
+
}
|
|
148
|
+
case "checkerboard": {
|
|
149
|
+
const across = integerIn(get("squaresAcross"), "squaresAcross", 2, 256), dark = neutral("darkReflectance"), light = neutral("lightReflectance"), size = 2 / across;
|
|
150
|
+
return done({ squaresAcross: across, darkReflectance: dark, lightReflectance: light }, [{ kind: "neutral", reflectance: dark }, { kind: "neutral", reflectance: light }], (u, v) => ((Math.floor((u + 1) / size) + Math.floor((aspect - v) / size)) % 2 === 0 ? 1 : 0));
|
|
151
|
+
}
|
|
152
|
+
case "point-grid": {
|
|
153
|
+
const columns = integerIn(get("columns"), "columns", 1, 256), rows = integerIn(get("rows"), "rows", 1, 256);
|
|
154
|
+
const radius = finiteIn(get("radius"), "radius", 0, 1, true), point = neutral("pointReflectance"), background = neutral("backgroundReflectance");
|
|
155
|
+
const centers = calculatePointGridCenters({ columns, rows, aspect });
|
|
156
|
+
const cellW = 2 / columns, cellH = 2 * aspect / rows;
|
|
157
|
+
return done({ columns, rows, radius, pointReflectance: point, backgroundReflectance: background }, [{ kind: "neutral", reflectance: background }, { kind: "neutral", reflectance: point }], (u, v) => {
|
|
158
|
+
const i = Math.min(columns - 1, Math.max(0, Math.floor((u + 1) / cellW))), j = Math.min(rows - 1, Math.max(0, Math.floor((aspect - v) / cellH)));
|
|
159
|
+
const c = centers[j * columns + i];
|
|
160
|
+
return (u - c.u) ** 2 + (v - c.v) ** 2 <= radius * radius ? 1 : 0;
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
case "patches": {
|
|
164
|
+
const list = record.patches;
|
|
165
|
+
if (!Array.isArray(list) || list.length < 1 || list.length > 1024)
|
|
166
|
+
throw new InvalidConfigurationError("patches must list 1 to 1024 caller reflectances.");
|
|
167
|
+
const ids = new Set();
|
|
168
|
+
const materials = [];
|
|
169
|
+
for (const [index, patch] of list.entries()) {
|
|
170
|
+
requireInputObject(patch, "patches[" + index + "]");
|
|
171
|
+
const p = patch;
|
|
172
|
+
for (const key of Object.keys(p))
|
|
173
|
+
if (key !== "patchId" && key !== "reflectance")
|
|
174
|
+
throw new InvalidConfigurationError("Unknown patch field: " + key + ".");
|
|
175
|
+
if (typeof p.patchId !== "string" || p.patchId.trim() === "" || ids.has(p.patchId))
|
|
176
|
+
throw new InvalidConfigurationError("Each patch needs a unique non-empty patchId.");
|
|
177
|
+
ids.add(p.patchId);
|
|
178
|
+
materials.push(material(p.reflectance, "patches[" + index + "].reflectance"));
|
|
179
|
+
}
|
|
180
|
+
const columnsRaw = record.columns === undefined ? Math.ceil(Math.sqrt(list.length)) : record.columns;
|
|
181
|
+
if (record.columns === undefined)
|
|
182
|
+
defaulted.push("columns");
|
|
183
|
+
const columns = integerIn(columnsRaw, "columns", 1, list.length), rows = Math.ceil(list.length / columns);
|
|
184
|
+
const gap = finiteIn(get("gapFraction"), "gapFraction", 0, 0.5), background = neutral("backgroundReflectance");
|
|
185
|
+
if (gap >= 0.5)
|
|
186
|
+
throw new InvalidConfigurationError("gapFraction must be below 0.5.");
|
|
187
|
+
const backgroundIndex = materials.length;
|
|
188
|
+
materials.push({ kind: "neutral", reflectance: background });
|
|
189
|
+
const cellW = 2 / columns, cellH = 2 * aspect / rows;
|
|
190
|
+
return done({ patchIds: list.map((p) => p.patchId), columns, rows, gapFraction: gap, backgroundReflectance: background }, materials, (u, v) => {
|
|
191
|
+
const fx = (u + 1) / cellW, fy = (aspect - v) / cellH, i = Math.floor(fx), j = Math.floor(fy);
|
|
192
|
+
if (i < 0 || j < 0 || i >= columns || j >= rows)
|
|
193
|
+
return backgroundIndex;
|
|
194
|
+
const index = j * columns + i, x = fx - i, y = fy - j;
|
|
195
|
+
if (index >= list.length || x < gap / 2 || x > 1 - gap / 2 || y < gap / 2 || y > 1 - gap / 2)
|
|
196
|
+
return backgroundIndex;
|
|
197
|
+
return index;
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Step reflectances of a step wedge. `equal-density` spaces optical density D = -log10(R) evenly, which
|
|
204
|
+
* gives geometric reflectance steps, as on a photographic step tablet. `linear` spaces reflectance evenly.
|
|
205
|
+
*/
|
|
206
|
+
export function calculateStepWedgeReflectances(input) {
|
|
207
|
+
requireInputKeys(input, "calculateStepWedgeReflectances", ["steps", "minimumReflectance", "maximumReflectance", "spacing"]);
|
|
208
|
+
const steps = integerIn(input.steps, "steps", 2, 64), lo = reflectance(input.minimumReflectance, "minimumReflectance"), hi = reflectance(input.maximumReflectance, "maximumReflectance");
|
|
209
|
+
if (input.spacing !== "equal-density" && input.spacing !== "linear")
|
|
210
|
+
throw new InvalidConfigurationError("spacing must be equal-density or linear.");
|
|
211
|
+
if (!(hi > lo) || (input.spacing === "equal-density" && lo <= 0))
|
|
212
|
+
throw new InvalidConfigurationError("Step wedge needs 0 < minimum < maximum reflectance.");
|
|
213
|
+
return Array.from({ length: steps }, (_, k) => {
|
|
214
|
+
if (k === steps - 1)
|
|
215
|
+
return hi;
|
|
216
|
+
const t = k / (steps - 1);
|
|
217
|
+
return input.spacing === "linear" ? lo + (hi - lo) * t : lo * (hi / lo) ** t;
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
/** Centres (frame units) of a point grid: one disk centred in each of columns × rows equal cells, row-major from the top-left. */
|
|
221
|
+
export function calculatePointGridCenters(input) {
|
|
222
|
+
requireInputKeys(input, "calculatePointGridCenters", ["columns", "rows", "aspect"]);
|
|
223
|
+
const columns = integerIn(input.columns, "columns", 1, 256), rows = integerIn(input.rows, "rows", 1, 256);
|
|
224
|
+
if (typeof input.aspect !== "number" || !Number.isFinite(input.aspect) || input.aspect <= 0)
|
|
225
|
+
throw new InvalidConfigurationError("aspect must be positive.");
|
|
226
|
+
const out = [];
|
|
227
|
+
for (let j = 0; j < rows; j++)
|
|
228
|
+
for (let i = 0; i < columns; i++)
|
|
229
|
+
out.push({ u: -1 + (i + 0.5) * 2 / columns, v: input.aspect - (j + 0.5) * 2 * input.aspect / rows });
|
|
230
|
+
return out;
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=chart-scenes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart-scenes.js","sourceRoot":"","sources":["../../src/facade/chart-scenes.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Procedural test charts for the capture facade, written for this engine. Every chart is a flat,\n * Lambertian (matte) reflectance pattern, defined by formulas in normalized frame coordinates. No\n * third-party chart data (for example ColorChecker reflectances) is bundled. Coloured patches use\n * spectra that the caller supplies.\n *\n * Frame coordinates: `u` runs from -1 (left edge of the framed chart) to +1 (right edge); `v` points up\n * and has the same scale, so it runs from -aspect to +aspect where aspect = height/width of the frame.\n * The facade places the chart perpendicular to the optical axis at the subject distance and sizes it so\n * that this rectangle exactly fills the active capture (see `SimulateCaptureResult.assumptions`).\n *\n * The slanted edge follows the geometry described by P. D. Burns, \"Slanted-Edge MTF for Digital Camera\n * and Scanner Analysis\", IS&T PICS 2000 (free from imaging.org; also ISO 12233). It is a near-vertical\n * edge rotated by a few degrees (5 degrees by default), with a 4:1 light/dark reflectance ratio by\n * default. This is only a geometric description. No measured chart or ISO test procedure is copied.\n * @see docs/QUICK_START.md for the chart catalogue and their analytic definitions.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { prepareColorimetricSpectrum, type ColorimetricSpectrum, type PreparedColorimetricSpectrum } from \"../color/color-matching-functions.js\";\nimport { requireInputObject, requireInputKeys } from \"../core/record-validation.js\";\n\n/** A neutral (spectrally flat) reflectance in [0, 1], or a caller reflectance spectrum (values in [0, 1]). */\nexport type ChartReflectance = number | ColorimetricSpectrum;\n\nexport interface UniformChartScene { preset: \"uniform\"; reflectance?: ChartReflectance }\nexport interface SlantedEdgeChartScene {\n preset: \"slanted-edge\";\n /** Clockwise tilt of the edge from vertical, degrees, in (-45, 45). Default 5. */\n angleDegrees?: number;\n /** Left (dark) side reflectance. Default 0.15. */\n darkReflectance?: number;\n /** Right (light) side reflectance. Default 0.6 (4:1 with the default dark side). */\n lightReflectance?: number;\n}\nexport interface SiemensStarChartScene {\n preset: \"siemens-star\";\n /** Light/dark sector pairs around the star, 2..360. Default 36. */\n cycles?: number;\n /** Star radius as a fraction of the frame half-height, (0, 1]. Default 0.9. */\n radiusFraction?: number;\n darkReflectance?: number;\n lightReflectance?: number;\n /** Reflectance outside the star. Default 0.18. */\n backgroundReflectance?: number;\n}\nexport interface StepWedgeChartScene {\n preset: \"step-wedge\";\n /** Number of equal-width vertical steps from left (minimum) to right (maximum), 2..64. Default 11. */\n steps?: number;\n minimumReflectance?: number;\n maximumReflectance?: number;\n /** `equal-density` (geometric, default) or `linear` reflectance spacing. */\n spacing?: \"equal-density\" | \"linear\";\n}\nexport interface GreyRampChartScene {\n preset: \"grey-ramp\";\n /** Continuous ramp, linear in reflectance from left (minimum) to right (maximum). */\n minimumReflectance?: number;\n maximumReflectance?: number;\n}\nexport interface CheckerboardChartScene {\n preset: \"checkerboard\";\n /** Squares across the frame width, 2..256. Default 8. */\n squaresAcross?: number;\n darkReflectance?: number;\n lightReflectance?: number;\n}\nexport interface PointGridChartScene {\n preset: \"point-grid\";\n /** Grid columns and rows of small disks centred in equal cells. Defaults 5 × 3. */\n columns?: number;\n rows?: number;\n /** Disk radius in frame units (fraction of the frame half-width). Default 0.01. */\n radius?: number;\n pointReflectance?: number;\n backgroundReflectance?: number;\n}\nexport interface PatchChartScene {\n preset: \"patches\";\n /** Caller reflectance per patch, row-major; the facade bundles no colour-chart data. 1..1024 patches. */\n patches: readonly { patchId: string; reflectance: ChartReflectance }[];\n /** Patches per row. Default ceil(sqrt(patch count)). */\n columns?: number;\n /** Gap between patches as a fraction of the cell size, [0, 0.5). Default 0.1. */\n gapFraction?: number;\n backgroundReflectance?: number;\n}\nexport type ChartScene = UniformChartScene | SlantedEdgeChartScene | SiemensStarChartScene | StepWedgeChartScene |\n GreyRampChartScene | CheckerboardChartScene | PointGridChartScene | PatchChartScene;\nexport type ChartScenePresetId = ChartScene[\"preset\"];\nexport const CHART_SCENE_PRESETS: readonly ChartScenePresetId[] = Object.freeze([\"uniform\", \"slanted-edge\", \"siemens-star\",\n \"step-wedge\", \"grey-ramp\", \"checkerboard\", \"point-grid\", \"patches\"] as const);\n\n/** Engine-chosen chart parameters, each reported when the caller omitted it. */\nexport const CHART_SCENE_DEFAULTS = Object.freeze({\n uniform: Object.freeze({ reflectance: 0.18 }),\n \"slanted-edge\": Object.freeze({ angleDegrees: 5, darkReflectance: 0.15, lightReflectance: 0.6 }),\n \"siemens-star\": Object.freeze({ cycles: 36, radiusFraction: 0.9, darkReflectance: 0.05, lightReflectance: 0.8, backgroundReflectance: 0.18 }),\n \"step-wedge\": Object.freeze({ steps: 11, minimumReflectance: 0.03, maximumReflectance: 0.9, spacing: \"equal-density\" as const }),\n \"grey-ramp\": Object.freeze({ minimumReflectance: 0.03, maximumReflectance: 0.9 }),\n checkerboard: Object.freeze({ squaresAcross: 8, darkReflectance: 0.05, lightReflectance: 0.8 }),\n \"point-grid\": Object.freeze({ columns: 5, rows: 3, radius: 0.01, pointReflectance: 0.9, backgroundReflectance: 0.02 }),\n patches: Object.freeze({ gapFraction: 0.1, backgroundReflectance: 0.18 })\n});\n\n/** A validated chart: every parameter resolved, plus which ones came from {@link CHART_SCENE_DEFAULTS}. */\nexport interface ResolvedChartScene {\n preset: ChartScenePresetId;\n /** Fully resolved parameters (spectra are reported as `\"caller-spectrum\"`). */\n parameters: Readonly<Record<string, unknown>>;\n /** Names of parameters filled from defaults. */\n defaultedParameters: readonly string[];\n /** Frame aspect (height / width) the chart was resolved for. */\n aspect: number;\n /**\n * Material index at a frame point (u right, v up). The index points into `materials`, starting at 0.\n * Points outside the framed rectangle still evaluate (the pattern continues as defined), so blur and\n * small framing differences stay well defined.\n */\n materialAt(u: number, v: number): number;\n /** Reflectance materials: a neutral number or a prepared caller spectrum. */\n materials: readonly ({ kind: \"neutral\"; reflectance: number } | { kind: \"spectrum\"; spectrum: PreparedColorimetricSpectrum })[];\n /** Reflectance in [0, 1] at a frame point and wavelength (nm). */\n reflectanceAt(u: number, v: number, wavelengthNanometers: number): number;\n}\n\nfunction reflectance(value: unknown, name: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0 || value > 1) throw new InvalidConfigurationError(name + \" must be a reflectance in [0, 1].\");\n return value;\n}\nfunction integerIn(value: unknown, name: string, minimum: number, maximum: number): number {\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < minimum || value > maximum) throw new InvalidConfigurationError(name + \" must be an integer from \" + minimum + \" to \" + maximum + \".\");\n return value;\n}\nfunction finiteIn(value: unknown, name: string, minimum: number, maximum: number, open = false): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < minimum || value > maximum || (open && (value === minimum || value === maximum)))\n throw new InvalidConfigurationError(name + \" is outside its supported range.\");\n return value;\n}\n/** Wavelength range every chart spectrum must cover (the facade's sensor quadrature range). */\nexport const CHART_SPECTRAL_RANGE_NANOMETERS = Object.freeze({ minimum: 380, maximum: 780 });\nfunction material(value: unknown, name: string): ResolvedChartScene[\"materials\"][number] {\n if (typeof value === \"number\") return { kind: \"neutral\", reflectance: reflectance(value, name) };\n let spectrum: PreparedColorimetricSpectrum;\n try { spectrum = prepareColorimetricSpectrum(value as ColorimetricSpectrum, name); } catch (error) {\n throw new InvalidConfigurationError(name + \" must be a neutral reflectance or a valid reflectance spectrum: \" + (error instanceof Error ? error.message : \"invalid\"));\n }\n const range = spectrum.wavelengthRangeNanometers;\n if (range.minimum > CHART_SPECTRAL_RANGE_NANOMETERS.minimum || range.maximum < CHART_SPECTRAL_RANGE_NANOMETERS.maximum)\n throw new InvalidConfigurationError(name + \" must cover 380-780 nm.\");\n for (let nm = CHART_SPECTRAL_RANGE_NANOMETERS.minimum; nm <= CHART_SPECTRAL_RANGE_NANOMETERS.maximum; nm += 5) reflectance(spectrum.evaluate(nm), name + \" values\");\n return { kind: \"spectrum\", spectrum };\n}\n\n/**\n * Validates a chart description and resolves every default. `aspect` is the frame height/width. Unknown\n * fields are rejected so that a mistyped parameter never silently falls back to a default.\n */\nexport function resolveChartScene(input: { scene: ChartScene; aspect: number }): ResolvedChartScene {\n requireInputObject(input, \"resolveChartScene input\");\n for (const key of Object.keys(input)) if (key !== \"scene\" && key !== \"aspect\") throw new InvalidConfigurationError(\"resolveChartScene input has unknown field \\\"\" + key + \"\\\".\");\n const { scene, aspect } = input;\n requireInputObject(scene, \"chart scene\");\n if (typeof aspect !== \"number\" || !Number.isFinite(aspect) || aspect <= 0) throw new InvalidConfigurationError(\"Chart aspect must be positive.\");\n const preset = (scene as { preset?: unknown }).preset;\n if (typeof preset !== \"string\" || !(CHART_SCENE_PRESETS as readonly string[]).includes(preset)) throw new InvalidConfigurationError(\"Unknown chart preset.\");\n const record = scene as unknown as Record<string, unknown>;\n const defaults = CHART_SCENE_DEFAULTS[preset as ChartScenePresetId] as Record<string, unknown>;\n const allowed = [\"preset\", ...Object.keys(defaults), ...(preset === \"patches\" ? [\"patches\", \"columns\"] : [])];\n for (const key of Object.keys(record)) if (!allowed.includes(key)) throw new InvalidConfigurationError(\"Unknown chart parameter: \" + key + \".\");\n const defaulted: string[] = [];\n const get = (key: string): unknown => { if (record[key] === undefined) { if (key in defaults) defaulted.push(key); return defaults[key]; } return record[key]; };\n const neutral = (key: string): number => reflectance(get(key), key);\n const done = (parameters: Record<string, unknown>, materials: ResolvedChartScene[\"materials\"], materialAt: (u: number, v: number) => number): ResolvedChartScene =>\n Object.freeze({ preset: preset as ChartScenePresetId, parameters: Object.freeze(parameters), defaultedParameters: Object.freeze(defaulted), aspect, materials: Object.freeze(materials), materialAt,\n reflectanceAt(u: number, v: number, nm: number): number {\n const m = materials[materialAt(u, v)]!;\n if (m.kind === \"neutral\") return m.reflectance;\n const value = m.spectrum.evaluate(nm);\n if (!(value >= 0 && value <= 1)) throw new InvalidConfigurationError(\"Chart reflectance spectrum left [0, 1].\");\n return value;\n } });\n switch (preset as ChartScenePresetId) {\n case \"uniform\": {\n const raw = get(\"reflectance\"), m = material(raw, \"reflectance\");\n return done({ reflectance: typeof raw === \"number\" ? raw : \"caller-spectrum\" }, [m], () => 0);\n }\n case \"slanted-edge\": {\n const angle = finiteIn(get(\"angleDegrees\"), \"angleDegrees\", -45, 45, true), dark = neutral(\"darkReflectance\"), light = neutral(\"lightReflectance\");\n const t = angle * Math.PI / 180, c = Math.cos(t), s = Math.sin(t);\n // Edge through the frame centre along (sin t, cos t); the light side is to the right.\n return done({ angleDegrees: angle, darkReflectance: dark, lightReflectance: light },\n [{ kind: \"neutral\", reflectance: dark }, { kind: \"neutral\", reflectance: light }], (u, v) => (u * c - v * s >= 0 ? 1 : 0));\n }\n case \"siemens-star\": {\n const cycles = integerIn(get(\"cycles\"), \"cycles\", 2, 360), radius = finiteIn(get(\"radiusFraction\"), \"radiusFraction\", 0, 1, false);\n if (radius === 0) throw new InvalidConfigurationError(\"radiusFraction must be positive.\");\n const dark = neutral(\"darkReflectance\"), light = neutral(\"lightReflectance\"), background = neutral(\"backgroundReflectance\"), r = radius * aspect;\n return done({ cycles, radiusFraction: radius, darkReflectance: dark, lightReflectance: light, backgroundReflectance: background },\n [{ kind: \"neutral\", reflectance: dark }, { kind: \"neutral\", reflectance: light }, { kind: \"neutral\", reflectance: background }], (u, v) => {\n if (u * u + v * v > r * r) return 2;\n const phase = Math.atan2(v, u) / (2 * Math.PI) + 0.5; // [0, 1]\n return Math.floor(phase * 2 * cycles) % 2 === 0 ? 1 : 0;\n });\n }\n case \"step-wedge\": {\n const steps = integerIn(get(\"steps\"), \"steps\", 2, 64), lo = neutral(\"minimumReflectance\"), hi = neutral(\"maximumReflectance\"), spacing = get(\"spacing\");\n if (spacing !== \"equal-density\" && spacing !== \"linear\") throw new InvalidConfigurationError(\"spacing must be equal-density or linear.\");\n if (!(hi > lo) || (spacing === \"equal-density\" && lo <= 0)) throw new InvalidConfigurationError(\"Step wedge needs 0 < minimum < maximum reflectance.\");\n const values = calculateStepWedgeReflectances({ steps, minimumReflectance: lo, maximumReflectance: hi, spacing });\n return done({ steps, minimumReflectance: lo, maximumReflectance: hi, spacing, stepReflectances: values },\n values.map((reflectanceValue) => ({ kind: \"neutral\" as const, reflectance: reflectanceValue })),\n (u) => Math.min(steps - 1, Math.max(0, Math.floor((u + 1) / 2 * steps))));\n }\n case \"grey-ramp\": {\n const lo = neutral(\"minimumReflectance\"), hi = neutral(\"maximumReflectance\");\n if (!(hi > lo)) throw new InvalidConfigurationError(\"Grey ramp needs minimum < maximum reflectance.\");\n // A continuous ramp is stored as 1024 neutral levels. The step size (< 0.1 % of the range) is far below sensor noise.\n const levels = 1024, materials = Array.from({ length: levels }, (_, i) => ({ kind: \"neutral\" as const, reflectance: lo + (hi - lo) * (i + 0.5) / levels }));\n return done({ minimumReflectance: lo, maximumReflectance: hi, representation: \"1024 equal neutral levels\" }, materials,\n (u) => Math.min(levels - 1, Math.max(0, Math.floor((u + 1) / 2 * levels))));\n }\n case \"checkerboard\": {\n const across = integerIn(get(\"squaresAcross\"), \"squaresAcross\", 2, 256), dark = neutral(\"darkReflectance\"), light = neutral(\"lightReflectance\"), size = 2 / across;\n return done({ squaresAcross: across, darkReflectance: dark, lightReflectance: light },\n [{ kind: \"neutral\", reflectance: dark }, { kind: \"neutral\", reflectance: light }],\n (u, v) => ((Math.floor((u + 1) / size) + Math.floor((aspect - v) / size)) % 2 === 0 ? 1 : 0));\n }\n case \"point-grid\": {\n const columns = integerIn(get(\"columns\"), \"columns\", 1, 256), rows = integerIn(get(\"rows\"), \"rows\", 1, 256);\n const radius = finiteIn(get(\"radius\"), \"radius\", 0, 1, true), point = neutral(\"pointReflectance\"), background = neutral(\"backgroundReflectance\");\n const centers = calculatePointGridCenters({ columns, rows, aspect });\n const cellW = 2 / columns, cellH = 2 * aspect / rows;\n return done({ columns, rows, radius, pointReflectance: point, backgroundReflectance: background },\n [{ kind: \"neutral\", reflectance: background }, { kind: \"neutral\", reflectance: point }], (u, v) => {\n const i = Math.min(columns - 1, Math.max(0, Math.floor((u + 1) / cellW))), j = Math.min(rows - 1, Math.max(0, Math.floor((aspect - v) / cellH)));\n const c = centers[j * columns + i]!;\n return (u - c.u) ** 2 + (v - c.v) ** 2 <= radius * radius ? 1 : 0;\n });\n }\n case \"patches\": {\n const list = record.patches;\n if (!Array.isArray(list) || list.length < 1 || list.length > 1024) throw new InvalidConfigurationError(\"patches must list 1 to 1024 caller reflectances.\");\n const ids = new Set<string>();\n const materials: ResolvedChartScene[\"materials\"][number][] = [];\n for (const [index, patch] of list.entries()) {\n requireInputObject(patch, \"patches[\" + index + \"]\");\n const p = patch as Record<string, unknown>;\n for (const key of Object.keys(p)) if (key !== \"patchId\" && key !== \"reflectance\") throw new InvalidConfigurationError(\"Unknown patch field: \" + key + \".\");\n if (typeof p.patchId !== \"string\" || p.patchId.trim() === \"\" || ids.has(p.patchId)) throw new InvalidConfigurationError(\"Each patch needs a unique non-empty patchId.\");\n ids.add(p.patchId);\n materials.push(material(p.reflectance, \"patches[\" + index + \"].reflectance\"));\n }\n const columnsRaw = record.columns === undefined ? Math.ceil(Math.sqrt(list.length)) : record.columns;\n if (record.columns === undefined) defaulted.push(\"columns\");\n const columns = integerIn(columnsRaw, \"columns\", 1, list.length), rows = Math.ceil(list.length / columns);\n const gap = finiteIn(get(\"gapFraction\"), \"gapFraction\", 0, 0.5), background = neutral(\"backgroundReflectance\");\n if (gap >= 0.5) throw new InvalidConfigurationError(\"gapFraction must be below 0.5.\");\n const backgroundIndex = materials.length;\n materials.push({ kind: \"neutral\", reflectance: background });\n const cellW = 2 / columns, cellH = 2 * aspect / rows;\n return done({ patchIds: list.map((p: { patchId: string }) => p.patchId), columns, rows, gapFraction: gap, backgroundReflectance: background }, materials, (u, v) => {\n const fx = (u + 1) / cellW, fy = (aspect - v) / cellH, i = Math.floor(fx), j = Math.floor(fy);\n if (i < 0 || j < 0 || i >= columns || j >= rows) return backgroundIndex;\n const index = j * columns + i, x = fx - i, y = fy - j;\n if (index >= list.length || x < gap / 2 || x > 1 - gap / 2 || y < gap / 2 || y > 1 - gap / 2) return backgroundIndex;\n return index;\n });\n }\n }\n}\n\n/**\n * Step reflectances of a step wedge. `equal-density` spaces optical density D = -log10(R) evenly, which\n * gives geometric reflectance steps, as on a photographic step tablet. `linear` spaces reflectance evenly.\n */\nexport function calculateStepWedgeReflectances(input: { steps: number; minimumReflectance: number; maximumReflectance: number;\n spacing: \"equal-density\" | \"linear\" }): number[] {\n requireInputKeys(input, \"calculateStepWedgeReflectances\", [\"steps\", \"minimumReflectance\", \"maximumReflectance\", \"spacing\"]);\n const steps = integerIn(input.steps, \"steps\", 2, 64), lo = reflectance(input.minimumReflectance, \"minimumReflectance\"), hi = reflectance(input.maximumReflectance, \"maximumReflectance\");\n if (input.spacing !== \"equal-density\" && input.spacing !== \"linear\") throw new InvalidConfigurationError(\"spacing must be equal-density or linear.\");\n if (!(hi > lo) || (input.spacing === \"equal-density\" && lo <= 0)) throw new InvalidConfigurationError(\"Step wedge needs 0 < minimum < maximum reflectance.\");\n return Array.from({ length: steps }, (_, k) => {\n if (k === steps - 1) return hi;\n const t = k / (steps - 1);\n return input.spacing === \"linear\" ? lo + (hi - lo) * t : lo * (hi / lo) ** t;\n });\n}\n\n/** Centres (frame units) of a point grid: one disk centred in each of columns × rows equal cells, row-major from the top-left. */\nexport function calculatePointGridCenters(input: { columns: number; rows: number; aspect: number }): { u: number; v: number }[] {\n requireInputKeys(input, \"calculatePointGridCenters\", [\"columns\", \"rows\", \"aspect\"]);\n const columns = integerIn(input.columns, \"columns\", 1, 256), rows = integerIn(input.rows, \"rows\", 1, 256);\n if (typeof input.aspect !== \"number\" || !Number.isFinite(input.aspect) || input.aspect <= 0) throw new InvalidConfigurationError(\"aspect must be positive.\");\n const out: { u: number; v: number }[] = [];\n for (let j = 0; j < rows; j++) for (let i = 0; i < columns; i++) out.push({ u: -1 + (i + 0.5) * 2 / columns, v: input.aspect - (j + 0.5) * 2 * input.aspect / rows });\n return out;\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ResolveLensSampledPsfInput } from "../optics/lens-psf-profile.js";
|
|
2
|
+
import type { PlanarSceneRadianceProvider } from "./scene-radiance.js";
|
|
3
|
+
export interface DiffractedPlanarProviderInput {
|
|
4
|
+
base: PlanarSceneRadianceProvider;
|
|
5
|
+
/** The optical state of the sampled PSF, as for `resolveLensSampledPsf`, without field point and wavelength. */
|
|
6
|
+
psf: Omit<ResolveLensSampledPsfInput, "fieldPointMm" | "wavelengthNm">;
|
|
7
|
+
/** Spectral nodes the environment queries (the profile's wavelength nodes). */
|
|
8
|
+
wavelengthsNm: readonly number[];
|
|
9
|
+
kernelRadius: number;
|
|
10
|
+
nativeWidth: number;
|
|
11
|
+
nativeHeight: number;
|
|
12
|
+
/** Output (active) width in sites: frame units are 2/outputWidth per site. */
|
|
13
|
+
outputWidth: number;
|
|
14
|
+
sitePitchMicrometers: number;
|
|
15
|
+
/** Planar geometry of the base provider, to map query directions to plane points exactly as it does. */
|
|
16
|
+
distanceM: number;
|
|
17
|
+
metresPerFrameUnit: number;
|
|
18
|
+
/**
|
|
19
|
+
* Offsets of the query points from the site centres, in sites (+x right, +y down): the anti-aliasing split
|
|
20
|
+
* offsets with their sign reversed (the environment queries q − a). Default: one zero offset.
|
|
21
|
+
*/
|
|
22
|
+
queryOffsetsSites?: readonly {
|
|
23
|
+
x: number;
|
|
24
|
+
y: number;
|
|
25
|
+
}[];
|
|
26
|
+
/** Called with the duration in ms of each band convolution (diagnostics only; never changes values). */
|
|
27
|
+
onConvolution?: (milliseconds: number) => void;
|
|
28
|
+
}
|
|
29
|
+
/** Internal (not exported from the package): the base provider with diffraction applied as an object-space convolution. */
|
|
30
|
+
export declare function createDiffractedPlanarProvider(input: DiffractedPlanarProviderInput): PlanarSceneRadianceProvider;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Fast execution of `simulateCapture`'s `lens.diffraction` (2.1): an object-space convolution in the scene
|
|
4
|
+
* provider, instead of one scene query per PSF tap in the environment PSF quadrature.
|
|
5
|
+
*
|
|
6
|
+
* The environment quadrature computes, at each site centre q and spectral node λ,
|
|
7
|
+
* E(q, λ) = Σ_k K_λ(k)·T·L(s_k(q), λ),
|
|
8
|
+
* where s_k(q) is the tap's source point (`sensorPsfSourcePoint`), L the scene radiance at the plane point
|
|
9
|
+
* that source point sees, and T the radiance-to-irradiance factor. For the facade's planar scene seen
|
|
10
|
+
* through the ideal rectilinear projection with a still camera and no lens field mapping, field throughput or
|
|
11
|
+
* pupil rays:
|
|
12
|
+
* - T is the same at every sensor point (paraxial π/(4·N_w²), no cos⁴ term), and
|
|
13
|
+
* - with the kernel sampled on the site pitch, every source point is the centre of another site, so the plane
|
|
14
|
+
* points form one regular lattice: u = (i + ½ − W/2)·2/w, v = −(j + ½ − H/2)·2/w (frame units, native
|
|
15
|
+
* site (i, j), W×H native sites, w output width).
|
|
16
|
+
* So E(q, λ) = T·B(q, λ) with B = K_λ ⊛ L sampled on that lattice: the same sum, in a different floating-point
|
|
17
|
+
* order. B is computed once per spectral node with the engine's isoplanatic convolution
|
|
18
|
+
* (`calculateIrradianceConvolution`, kernels from `resolveLensPsfConvolutionKernels`, exact site sampling) over a
|
|
19
|
+
* grid that holds every source (the native raster plus the kernel radius on each side), in row bands. The
|
|
20
|
+
* provider then answers each site-centre query with B instead of L, and the environment request declares no
|
|
21
|
+
* PSF. Incoherent imaging is a linear superposition of intensity PSFs, so convolving radiance on the object
|
|
22
|
+
* plane and convolving irradiance on the image plane agree for a planar object and a space-invariant PSF
|
|
23
|
+
* (MIT OpenCourseWare 2.71, lecture 22, free; also see: Goodman, Introduction to Fourier Optics, 4th ed., §6.1).
|
|
24
|
+
*
|
|
25
|
+
* With an anti-aliasing point-splitting filter (2.1, `sensor.antiAliasing`) the environment queries the PSF taps
|
|
26
|
+
* around each pre-filter source point q − a (a = a split offset) instead of around q. Those taps lie on the site
|
|
27
|
+
* lattice shifted by a, so the same argument holds on each shifted lattice: B is computed once per distinct
|
|
28
|
+
* fractional shift (offsets that differ by whole sites share one lattice; the centred four-spot filter with a
|
|
29
|
+
* one-site separation needs a single half-site-shifted lattice) over the native raster widened by the largest
|
|
30
|
+
* offset, and the environment's spatial quadrature still forms the weighted split sum.
|
|
31
|
+
*
|
|
32
|
+
* A query that does not land on one of the lattices (within 1e-6 site) is refused rather than approximated: the
|
|
33
|
+
* facade uses this path only when the lattice argument above holds.
|
|
34
|
+
*/
|
|
35
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
36
|
+
import { calculateIrradianceConvolution } from "../optics/irradiance-convolution.js";
|
|
37
|
+
import { resolveLensPsfConvolutionKernels } from "../optics/lens-psf-kernels.js";
|
|
38
|
+
/** Rows of native sites per convolution band, and the bands kept. Banding changes memory only, never values. */
|
|
39
|
+
const BAND_ROWS = 32;
|
|
40
|
+
const CACHED_BANDS = 4;
|
|
41
|
+
const LATTICE_TOLERANCE_SITES = 1e-6;
|
|
42
|
+
/** Internal (not exported from the package): the base provider with diffraction applied as an object-space convolution. */
|
|
43
|
+
export function createDiffractedPlanarProvider(input) {
|
|
44
|
+
const { base, wavelengthsNm, nativeWidth: W, nativeHeight: H, kernelRadius: R } = input;
|
|
45
|
+
const g = 2 / input.outputWidth, pitch = input.sitePitchMicrometers;
|
|
46
|
+
const index = new Map(wavelengthsNm.map((nm, i) => [nm, i]));
|
|
47
|
+
// One lattice per distinct fractional query offset; M extra sites per side hold the offset queries.
|
|
48
|
+
const offsets = input.queryOffsetsSites ?? [{ x: 0, y: 0 }];
|
|
49
|
+
const fraction = (value) => { const f = value - Math.floor(value); return f > 1 - LATTICE_TOLERANCE_SITES ? 0 : f < LATTICE_TOLERANCE_SITES ? 0 : f; };
|
|
50
|
+
const shifts = [];
|
|
51
|
+
for (const o of offsets) {
|
|
52
|
+
const f = { x: fraction(o.x), y: fraction(o.y) };
|
|
53
|
+
if (!shifts.some((s) => Math.abs(s.x - f.x) <= LATTICE_TOLERANCE_SITES && Math.abs(s.y - f.y) <= LATTICE_TOLERANCE_SITES))
|
|
54
|
+
shifts.push(f);
|
|
55
|
+
}
|
|
56
|
+
const M = Math.max(0, ...offsets.map((o) => Math.ceil(Math.max(Math.abs(o.x), Math.abs(o.y)) - LATTICE_TOLERANCE_SITES)));
|
|
57
|
+
const LW = W + 2 * M, LH = H + 2 * M;
|
|
58
|
+
// One kernel per wavelength, on the site grid, from the engine's own tap-to-site mapping (field point 0, 0).
|
|
59
|
+
const kernels = wavelengthsNm.map((wavelengthNm) => {
|
|
60
|
+
const k = resolveLensPsfConvolutionKernels({ schemaVersion: "0.1.0", psf: input.psf, spectralWeights: [{ wavelengthNm, weight: 1 }],
|
|
61
|
+
grid: { width: 1, height: 1, sitePitchMicrometers: { x: pitch, y: pitch }, opticalAxisSite: { x: 0.5, y: 0.5 } }, patchWidth: 1, patchHeight: 1,
|
|
62
|
+
kernelRadius: R }).value;
|
|
63
|
+
if (!k.exactSiteSampling || k.kernelRadius !== R)
|
|
64
|
+
throw new InvalidConfigurationError("Diffraction kernels must sample the site pitch exactly.");
|
|
65
|
+
return k.kernels;
|
|
66
|
+
});
|
|
67
|
+
const gridWidth = LW + 2 * R;
|
|
68
|
+
const now = () => globalThis.performance?.now() ?? Date.now();
|
|
69
|
+
const bands = new Map();
|
|
70
|
+
function band(b) {
|
|
71
|
+
const cached = bands.get(b);
|
|
72
|
+
if (cached) {
|
|
73
|
+
bands.delete(b);
|
|
74
|
+
bands.set(b, cached);
|
|
75
|
+
return cached;
|
|
76
|
+
}
|
|
77
|
+
const started = input.onConvolution ? now() : 0;
|
|
78
|
+
const y0 = b * BAND_ROWS, rows = Math.min(BAND_ROWS, LH - y0), gridHeight = rows + 2 * R;
|
|
79
|
+
const values = shifts.map((shift) => wavelengthsNm.map((nm, w) => {
|
|
80
|
+
const samples = new Float64Array(gridWidth * gridHeight);
|
|
81
|
+
for (let gy = 0; gy < gridHeight; gy++) {
|
|
82
|
+
const v = shift.y === 0 ? -(y0 + gy - R - M + 0.5 - H / 2) * g : -(y0 + gy - R - M + 0.5 + shift.y - H / 2) * g;
|
|
83
|
+
for (let gx = 0; gx < gridWidth; gx++)
|
|
84
|
+
samples[gy * gridWidth + gx] = base.radianceAt(shift.x === 0 ? (gx - R - M + 0.5 - W / 2) * g : (gx - R - M + 0.5 + shift.x - W / 2) * g, v, nm);
|
|
85
|
+
}
|
|
86
|
+
const blurred = calculateIrradianceConvolution({ schemaVersion: "0.1.0", width: gridWidth, height: gridHeight, samples, kernelRadius: R,
|
|
87
|
+
patchWidth: gridWidth, patchHeight: gridHeight, kernels: kernels[w], boundary: "zero-outside-grid" }).values;
|
|
88
|
+
const out = new Float64Array(LW * rows);
|
|
89
|
+
for (let y = 0; y < rows; y++)
|
|
90
|
+
out.set(blurred.subarray((y + R) * gridWidth + R, (y + R) * gridWidth + R + LW), y * LW);
|
|
91
|
+
return out;
|
|
92
|
+
}));
|
|
93
|
+
bands.set(b, values);
|
|
94
|
+
if (bands.size > CACHED_BANDS)
|
|
95
|
+
bands.delete(bands.keys().next().value);
|
|
96
|
+
if (input.onConvolution)
|
|
97
|
+
input.onConvolution(now() - started);
|
|
98
|
+
return values;
|
|
99
|
+
}
|
|
100
|
+
function blurredAt(u, v, nm) {
|
|
101
|
+
const w = index.get(nm), fi = u / g - 0.5 + W / 2, fj = -v / g - 0.5 + H / 2;
|
|
102
|
+
if (w !== undefined)
|
|
103
|
+
for (let s = 0; s < shifts.length; s++) {
|
|
104
|
+
const shift = shifts[s], i = Math.round(fi - shift.x), j = Math.round(fj - shift.y);
|
|
105
|
+
if (Math.abs(fi - shift.x - i) > LATTICE_TOLERANCE_SITES || Math.abs(fj - shift.y - j) > LATTICE_TOLERANCE_SITES)
|
|
106
|
+
continue;
|
|
107
|
+
if (i < -M || j < -M || i >= W + M || j >= H + M)
|
|
108
|
+
break;
|
|
109
|
+
const lj = j + M;
|
|
110
|
+
return band(Math.floor(lj / BAND_ROWS))[s][w][(lj % BAND_ROWS) * LW + i + M];
|
|
111
|
+
}
|
|
112
|
+
throw new InvalidConfigurationError("Diffraction query is off the site lattice; the object-space convolution does not apply.");
|
|
113
|
+
}
|
|
114
|
+
const scale = input.metresPerFrameUnit, distance = input.distanceM;
|
|
115
|
+
return {
|
|
116
|
+
sceneId: base.sceneId, providerProfileId: base.providerProfileId, radianceAt: base.radianceAt,
|
|
117
|
+
evaluateRadiance(request) {
|
|
118
|
+
const result = base.evaluateRadiance(request), o = request.target.outgoingDirectionUnitVector;
|
|
119
|
+
const t = distance / -o.z;
|
|
120
|
+
return { ...result, spectralRadianceWattsPerSquareMeterSteradianNanometer: blurredAt(-o.x * t / scale, -o.y * t / scale, request.wavelengthNanometers) };
|
|
121
|
+
},
|
|
122
|
+
evaluateApertureRadiance() {
|
|
123
|
+
throw new InvalidConfigurationError("Diffraction by object-space convolution does not take pupil rays.");
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=diffraction-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diffraction-provider.js","sourceRoot":"","sources":["../../src/facade/diffraction-provider.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Fast execution of `simulateCapture`'s `lens.diffraction` (2.1): an object-space convolution in the scene\n * provider, instead of one scene query per PSF tap in the environment PSF quadrature.\n *\n * The environment quadrature computes, at each site centre q and spectral node λ,\n * E(q, λ) = Σ_k K_λ(k)·T·L(s_k(q), λ),\n * where s_k(q) is the tap's source point (`sensorPsfSourcePoint`), L the scene radiance at the plane point\n * that source point sees, and T the radiance-to-irradiance factor. For the facade's planar scene seen\n * through the ideal rectilinear projection with a still camera and no lens field mapping, field throughput or\n * pupil rays:\n * - T is the same at every sensor point (paraxial π/(4·N_w²), no cos⁴ term), and\n * - with the kernel sampled on the site pitch, every source point is the centre of another site, so the plane\n * points form one regular lattice: u = (i + ½ − W/2)·2/w, v = −(j + ½ − H/2)·2/w (frame units, native\n * site (i, j), W×H native sites, w output width).\n * So E(q, λ) = T·B(q, λ) with B = K_λ ⊛ L sampled on that lattice: the same sum, in a different floating-point\n * order. B is computed once per spectral node with the engine's isoplanatic convolution\n * (`calculateIrradianceConvolution`, kernels from `resolveLensPsfConvolutionKernels`, exact site sampling) over a\n * grid that holds every source (the native raster plus the kernel radius on each side), in row bands. The\n * provider then answers each site-centre query with B instead of L, and the environment request declares no\n * PSF. Incoherent imaging is a linear superposition of intensity PSFs, so convolving radiance on the object\n * plane and convolving irradiance on the image plane agree for a planar object and a space-invariant PSF\n * (MIT OpenCourseWare 2.71, lecture 22, free; also see: Goodman, Introduction to Fourier Optics, 4th ed., §6.1).\n *\n * With an anti-aliasing point-splitting filter (2.1, `sensor.antiAliasing`) the environment queries the PSF taps\n * around each pre-filter source point q − a (a = a split offset) instead of around q. Those taps lie on the site\n * lattice shifted by a, so the same argument holds on each shifted lattice: B is computed once per distinct\n * fractional shift (offsets that differ by whole sites share one lattice; the centred four-spot filter with a\n * one-site separation needs a single half-site-shifted lattice) over the native raster widened by the largest\n * offset, and the environment's spatial quadrature still forms the weighted split sum.\n *\n * A query that does not land on one of the lattices (within 1e-6 site) is refused rather than approximated: the\n * facade uses this path only when the lattice argument above holds.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport type { SceneRadianceEvaluationRequest, SceneRadianceEvaluationResult } from \"../schema/scene-radiance.js\";\nimport { calculateIrradianceConvolution } from \"../optics/irradiance-convolution.js\";\nimport { resolveLensPsfConvolutionKernels } from \"../optics/lens-psf-kernels.js\";\nimport type { ResolveLensSampledPsfInput } from \"../optics/lens-psf-profile.js\";\nimport type { PlanarSceneRadianceProvider } from \"./scene-radiance.js\";\n\n/** Rows of native sites per convolution band, and the bands kept. Banding changes memory only, never values. */\nconst BAND_ROWS = 32;\nconst CACHED_BANDS = 4;\nconst LATTICE_TOLERANCE_SITES = 1e-6;\n\nexport interface DiffractedPlanarProviderInput {\n base: PlanarSceneRadianceProvider;\n /** The optical state of the sampled PSF, as for `resolveLensSampledPsf`, without field point and wavelength. */\n psf: Omit<ResolveLensSampledPsfInput, \"fieldPointMm\" | \"wavelengthNm\">;\n /** Spectral nodes the environment queries (the profile's wavelength nodes). */\n wavelengthsNm: readonly number[];\n kernelRadius: number;\n nativeWidth: number;\n nativeHeight: number;\n /** Output (active) width in sites: frame units are 2/outputWidth per site. */\n outputWidth: number;\n sitePitchMicrometers: number;\n /** Planar geometry of the base provider, to map query directions to plane points exactly as it does. */\n distanceM: number;\n metresPerFrameUnit: number;\n /**\n * Offsets of the query points from the site centres, in sites (+x right, +y down): the anti-aliasing split\n * offsets with their sign reversed (the environment queries q − a). Default: one zero offset.\n */\n queryOffsetsSites?: readonly { x: number; y: number }[];\n /** Called with the duration in ms of each band convolution (diagnostics only; never changes values). */\n onConvolution?: (milliseconds: number) => void;\n}\n\n/** Internal (not exported from the package): the base provider with diffraction applied as an object-space convolution. */\nexport function createDiffractedPlanarProvider(input: DiffractedPlanarProviderInput): PlanarSceneRadianceProvider {\n const { base, wavelengthsNm, nativeWidth: W, nativeHeight: H, kernelRadius: R } = input;\n const g = 2 / input.outputWidth, pitch = input.sitePitchMicrometers;\n const index = new Map(wavelengthsNm.map((nm, i) => [nm, i]));\n // One lattice per distinct fractional query offset; M extra sites per side hold the offset queries.\n const offsets = input.queryOffsetsSites ?? [{ x: 0, y: 0 }];\n const fraction = (value: number): number => { const f = value - Math.floor(value); return f > 1 - LATTICE_TOLERANCE_SITES ? 0 : f < LATTICE_TOLERANCE_SITES ? 0 : f; };\n const shifts: { x: number; y: number }[] = [];\n for (const o of offsets) {\n const f = { x: fraction(o.x), y: fraction(o.y) };\n if (!shifts.some((s) => Math.abs(s.x - f.x) <= LATTICE_TOLERANCE_SITES && Math.abs(s.y - f.y) <= LATTICE_TOLERANCE_SITES)) shifts.push(f);\n }\n const M = Math.max(0, ...offsets.map((o) => Math.ceil(Math.max(Math.abs(o.x), Math.abs(o.y)) - LATTICE_TOLERANCE_SITES)));\n const LW = W + 2 * M, LH = H + 2 * M;\n // One kernel per wavelength, on the site grid, from the engine's own tap-to-site mapping (field point 0, 0).\n const kernels = wavelengthsNm.map((wavelengthNm) => {\n const k = resolveLensPsfConvolutionKernels({ schemaVersion: \"0.1.0\", psf: input.psf, spectralWeights: [{ wavelengthNm, weight: 1 }],\n grid: { width: 1, height: 1, sitePitchMicrometers: { x: pitch, y: pitch }, opticalAxisSite: { x: 0.5, y: 0.5 } }, patchWidth: 1, patchHeight: 1,\n kernelRadius: R }).value;\n if (!k.exactSiteSampling || k.kernelRadius !== R) throw new InvalidConfigurationError(\"Diffraction kernels must sample the site pitch exactly.\");\n return k.kernels;\n });\n const gridWidth = LW + 2 * R;\n const now = (): number => globalThis.performance?.now() ?? Date.now();\n const bands = new Map<number, Float64Array[][]>();\n function band(b: number): Float64Array[][] {\n const cached = bands.get(b);\n if (cached) { bands.delete(b); bands.set(b, cached); return cached; }\n const started = input.onConvolution ? now() : 0;\n const y0 = b * BAND_ROWS, rows = Math.min(BAND_ROWS, LH - y0), gridHeight = rows + 2 * R;\n const values = shifts.map((shift) => wavelengthsNm.map((nm, w) => {\n const samples = new Float64Array(gridWidth * gridHeight);\n for (let gy = 0; gy < gridHeight; gy++) {\n const v = shift.y === 0 ? -(y0 + gy - R - M + 0.5 - H / 2) * g : -(y0 + gy - R - M + 0.5 + shift.y - H / 2) * g;\n for (let gx = 0; gx < gridWidth; gx++) samples[gy * gridWidth + gx] = base.radianceAt(shift.x === 0 ? (gx - R - M + 0.5 - W / 2) * g : (gx - R - M + 0.5 + shift.x - W / 2) * g, v, nm);\n }\n const blurred = calculateIrradianceConvolution({ schemaVersion: \"0.1.0\", width: gridWidth, height: gridHeight, samples, kernelRadius: R,\n patchWidth: gridWidth, patchHeight: gridHeight, kernels: kernels[w]!, boundary: \"zero-outside-grid\" }).values;\n const out = new Float64Array(LW * rows);\n for (let y = 0; y < rows; y++) out.set(blurred.subarray((y + R) * gridWidth + R, (y + R) * gridWidth + R + LW), y * LW);\n return out;\n }));\n bands.set(b, values);\n if (bands.size > CACHED_BANDS) bands.delete(bands.keys().next().value!);\n if (input.onConvolution) input.onConvolution(now() - started);\n return values;\n }\n function blurredAt(u: number, v: number, nm: number): number {\n const w = index.get(nm), fi = u / g - 0.5 + W / 2, fj = -v / g - 0.5 + H / 2;\n if (w !== undefined) for (let s = 0; s < shifts.length; s++) {\n const shift = shifts[s]!, i = Math.round(fi - shift.x), j = Math.round(fj - shift.y);\n if (Math.abs(fi - shift.x - i) > LATTICE_TOLERANCE_SITES || Math.abs(fj - shift.y - j) > LATTICE_TOLERANCE_SITES) continue;\n if (i < -M || j < -M || i >= W + M || j >= H + M) break;\n const lj = j + M;\n return band(Math.floor(lj / BAND_ROWS))[s]![w]![(lj % BAND_ROWS) * LW + i + M]!;\n }\n throw new InvalidConfigurationError(\"Diffraction query is off the site lattice; the object-space convolution does not apply.\");\n }\n const scale = input.metresPerFrameUnit, distance = input.distanceM;\n return {\n sceneId: base.sceneId, providerProfileId: base.providerProfileId, radianceAt: base.radianceAt,\n evaluateRadiance(request: Readonly<SceneRadianceEvaluationRequest>): SceneRadianceEvaluationResult {\n const result = base.evaluateRadiance(request), o = (request.target as { outgoingDirectionUnitVector: { x: number; y: number; z: number } }).outgoingDirectionUnitVector;\n const t = distance / -o.z;\n return { ...result, spectralRadianceWattsPerSquareMeterSteradianNanometer: blurredAt(-o.x * t / scale, -o.y * t / scale, request.wavelengthNanometers) };\n },\n evaluateApertureRadiance(): SceneRadianceEvaluationResult {\n throw new InvalidConfigurationError(\"Diffraction by object-space convolution does not take pupil rays.\");\n }\n };\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Mechanism chosen by {@link createHostYield}, for diagnostics and tests. */
|
|
2
|
+
export type HostYieldMechanism = "message-channel" | "set-immediate" | "set-timeout";
|
|
3
|
+
/** Returns a function that yields to the host event loop once per call, and the mechanism it uses. */
|
|
4
|
+
export declare function createHostYield(host?: object): {
|
|
5
|
+
mechanism: HostYieldMechanism;
|
|
6
|
+
yieldControl: () => Promise<void>;
|
|
7
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/** Returns a function that yields to the host event loop once per call, and the mechanism it uses. */
|
|
3
|
+
export function createHostYield(host = globalThis) {
|
|
4
|
+
const g = host;
|
|
5
|
+
const Channel = g.MessageChannel;
|
|
6
|
+
if (typeof Channel === "function") {
|
|
7
|
+
return { mechanism: "message-channel", yieldControl: () => new Promise((resolve) => {
|
|
8
|
+
const channel = new Channel();
|
|
9
|
+
channel.port1.onmessage = () => { channel.port1.close(); resolve(); };
|
|
10
|
+
channel.port2.postMessage(undefined);
|
|
11
|
+
}) };
|
|
12
|
+
}
|
|
13
|
+
const immediate = g.setImmediate;
|
|
14
|
+
if (typeof immediate === "function") {
|
|
15
|
+
return { mechanism: "set-immediate", yieldControl: () => new Promise((resolve) => { immediate.call(host, resolve); }) };
|
|
16
|
+
}
|
|
17
|
+
return { mechanism: "set-timeout", yieldControl: () => new Promise((resolve) => { setTimeout(resolve, 0); }) };
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=host-yield.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-yield.js","sourceRoot":"","sources":["../../src/facade/host-yield.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAsCtC,sGAAsG;AACtG,MAAM,UAAU,eAAe,CAAC,OAAe,UAAU;IACvD,MAAM,CAAC,GAAG,IAAoB,CAAC;IAC/B,MAAM,OAAO,GAAG,CAAC,CAAC,cAAc,CAAC;IACjC,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QAClC,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBACvF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;gBAC9B,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,GAAS,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC5E,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YACvC,CAAC,CAAC,EAAE,CAAC;IACP,CAAC;IACD,MAAM,SAAS,GAAG,CAAC,CAAC,YAAY,CAAC;IACjC,IAAI,OAAO,SAAS,KAAK,UAAU,EAAE,CAAC;QACpC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChI,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACvH,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Host yield for the capture facade's cooperative tasks. Browsers clamp nested `setTimeout(…, 0)` to\n * at least 4 ms (WHATWG HTML timers, nesting level above 5), so a task that yields every few\n * milliseconds through timers can sit idle for a large share of its run time. The first available\n * mechanism is used:\n *\n * 1. a `MessageChannel` message, a new task without the timer clamp (one channel per yield, closed after\n * delivery, so no port keeps a Node process alive);\n * 2. `setImmediate` (Node and some other non-browser hosts);\n * 3. `setTimeout(…, 0)` as the last resort.\n *\n * Every yield must let tasks that are already queued run first, so that a caller's cancel message (for\n * example a Web Worker `message` event that aborts the capture's `AbortSignal`) is handled at the next\n * yield. A `MessageChannel` message is queued on the HTML posted message task source, the same source as\n * worker and port `message` events, and tasks from one source run in the order they were queued.\n *\n * `scheduler.yield()` is deliberately not used (engine 2.0.0 used it first). Its continuation inherits\n * the \"user-visible\" priority and gets a higher effective priority than ordinary tasks; the WICG\n * Prioritized Task Scheduling draft (§ \"Task and Continuation Priorities\", effective priority table;\n * § \"Event loop: processing model\" note) intends such continuations to run ahead of most other task\n * sources, and its explainer (\"Preventing Task Starvation by Continuations\") only bounds that by\n * duration. A capture that yields every 8 ms through `scheduler.yield()` therefore starved a worker's\n * cancel message until the capture finished (measured in Chromium).\n *\n * Only global feature detection is used; nothing is imported, so the browser package surface is unchanged.\n * The yield changes scheduling only, never results.\n */\n\ntype YieldGlobals = {\n MessageChannel?: new () => { port1: { onmessage: ((event: unknown) => void) | null; close(): void }; port2: { postMessage(message: unknown): void } };\n setImmediate?: (callback: () => void) => unknown;\n};\n\n/** Mechanism chosen by {@link createHostYield}, for diagnostics and tests. */\nexport type HostYieldMechanism = \"message-channel\" | \"set-immediate\" | \"set-timeout\";\n\n/** Returns a function that yields to the host event loop once per call, and the mechanism it uses. */\nexport function createHostYield(host: object = globalThis): { mechanism: HostYieldMechanism; yieldControl: () => Promise<void> } {\n const g = host as YieldGlobals;\n const Channel = g.MessageChannel;\n if (typeof Channel === \"function\") {\n return { mechanism: \"message-channel\", yieldControl: () => new Promise<void>((resolve) => {\n const channel = new Channel();\n channel.port1.onmessage = (): void => { channel.port1.close(); resolve(); };\n channel.port2.postMessage(undefined);\n }) };\n }\n const immediate = g.setImmediate;\n if (typeof immediate === \"function\") {\n return { mechanism: \"set-immediate\", yieldControl: () => new Promise<void>((resolve) => { immediate.call(host, resolve); }) };\n }\n return { mechanism: \"set-timeout\", yieldControl: () => new Promise<void>((resolve) => { setTimeout(resolve, 0); }) };\n}\n"]}
|