@photivra/engine 2.18.0 → 2.19.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 +68 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/dist/capture/focus-control.js +2 -75
- package/dist/capture/focus-control.js.map +1 -1
- package/dist/capture/native-environment-lean.d.ts +1 -0
- package/dist/capture/native-environment-lean.js +1 -1
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-optical-stage.d.ts +1 -0
- package/dist/capture/native-environment-optical-stage.js +2 -5
- package/dist/capture/native-environment-optical-stage.js.map +1 -1
- package/dist/capture/native-environment-raw.js +1 -5
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/release-sequence.js +2 -47
- package/dist/capture/release-sequence.js.map +1 -1
- package/dist/color/white-balance.d.ts +2 -0
- package/dist/color/white-balance.js +3 -56
- package/dist/color/white-balance.js.map +1 -1
- package/dist/composition/image-formation-plan.d.ts +1 -0
- package/dist/composition/image-formation-plan.js +3 -49
- package/dist/composition/image-formation-plan.js.map +1 -1
- package/dist/core/evidence-provenance.js +1 -16
- package/dist/core/evidence-provenance.js.map +1 -1
- package/dist/core/record-validation.d.ts +54 -0
- package/dist/core/record-validation.js +176 -0
- package/dist/core/record-validation.js.map +1 -1
- package/dist/core/scientific-assurance.js +1 -18
- package/dist/core/scientific-assurance.js.map +1 -1
- package/dist/core/shared-helpers.d.ts +33 -0
- package/dist/core/shared-helpers.js +34 -0
- package/dist/core/shared-helpers.js.map +1 -0
- package/dist/core/spectral-composition.js +1 -36
- package/dist/core/spectral-composition.js.map +1 -1
- package/dist/core/spectral.js +1 -19
- package/dist/core/spectral.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/exposure-capabilities.d.ts +1 -0
- package/dist/equipment/exposure-capabilities.js +2 -36
- package/dist/equipment/exposure-capabilities.js.map +1 -1
- package/dist/equipment/iso-capabilities.js +2 -49
- package/dist/equipment/iso-capabilities.js.map +1 -1
- package/dist/equipment/metering-capabilities.js +1 -26
- package/dist/equipment/metering-capabilities.js.map +1 -1
- package/dist/equipment/release-capabilities.js +1 -53
- package/dist/equipment/release-capabilities.js.map +1 -1
- package/dist/exposure/auto-iso-slowest-shutter.js +1 -7
- package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -1
- package/dist/exposure/exposure-duration-control.js +1 -16
- package/dist/exposure/exposure-duration-control.js.map +1 -1
- package/dist/exposure/exposure-mode-resolver.js +1 -17
- package/dist/exposure/exposure-mode-resolver.js.map +1 -1
- package/dist/exposure/filtered-exposure-time.d.ts +93 -0
- package/dist/exposure/filtered-exposure-time.js +129 -0
- package/dist/exposure/filtered-exposure-time.js.map +1 -0
- package/dist/exposure/flash-ttl.d.ts +1 -0
- package/dist/exposure/flash-ttl.js +1 -1
- package/dist/exposure/flash-ttl.js.map +1 -1
- package/dist/exposure/flash.js +1 -49
- package/dist/exposure/flash.js.map +1 -1
- package/dist/exposure/metering-scene-radiance.js +1 -25
- package/dist/exposure/metering-scene-radiance.js.map +1 -1
- package/dist/exposure/metering-target.js +1 -30
- package/dist/exposure/metering-target.js.map +1 -1
- package/dist/exposure/metering-temporal.js +1 -8
- package/dist/exposure/metering-temporal.js.map +1 -1
- package/dist/exposure/metering.js +1 -72
- package/dist/exposure/metering.js.map +1 -1
- package/dist/exposure/program-line.js +1 -45
- package/dist/exposure/program-line.js.map +1 -1
- package/dist/facade/develop-joined-parts.d.ts +29 -0
- package/dist/facade/develop-joined-parts.js +33 -0
- package/dist/facade/develop-joined-parts.js.map +1 -0
- package/dist/facade/generic-lens-capture.d.ts +4 -2
- package/dist/facade/generic-lens-capture.js +4 -2
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +37 -5
- package/dist/facade/simulate-capture.js +153 -96
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.js +1 -3
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/chart-radiance-gpu.js +1 -5
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +13 -1
- package/dist/gpu/display-view-quality-gpu.js +4 -8
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.js +3 -25
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/sensor-stage-gpu.js +1 -5
- package/dist/gpu/sensor-stage-gpu.js.map +1 -1
- package/dist/gpu/webgpu-runtime.d.ts +2 -0
- package/dist/gpu/webgpu-runtime.js +3 -0
- package/dist/gpu/webgpu-runtime.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/motion/camera-rotation.js +1 -6
- package/dist/motion/camera-rotation.js.map +1 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts +12 -0
- package/dist/motion/capture-rotation-inverse-mapping.js +2 -2
- package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-rotation-temporal-quadrature.js +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -1
- package/dist/motion/capture-rotation-trajectory.js +2 -17
- package/dist/motion/capture-rotation-trajectory.js.map +1 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js +3 -14
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js.map +1 -1
- package/dist/motion/extended-object-projection.js +5 -40
- package/dist/motion/extended-object-projection.js.map +1 -1
- package/dist/optics/atmospheric-haze.js +1 -7
- package/dist/optics/atmospheric-haze.js.map +1 -1
- package/dist/optics/brown-conrady-distortion.js +1 -7
- package/dist/optics/brown-conrady-distortion.js.map +1 -1
- package/dist/optics/complex-pupil-psf.d.ts +1 -0
- package/dist/optics/complex-pupil-psf.js +2 -84
- package/dist/optics/complex-pupil-psf.js.map +1 -1
- package/dist/optics/focus-state.js +1 -11
- package/dist/optics/focus-state.js.map +1 -1
- package/dist/optics/front-of-lens-filter.d.ts +5 -0
- package/dist/optics/front-of-lens-filter.js +3 -65
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/generic-nd-filter-presets.d.ts +12 -0
- package/dist/optics/generic-nd-filter-presets.js +48 -0
- package/dist/optics/generic-nd-filter-presets.js.map +1 -0
- package/dist/optics/illumination-vignetting.js +1 -6
- package/dist/optics/illumination-vignetting.js.map +1 -1
- package/dist/optics/lens-psf-profile.d.ts +4 -1
- package/dist/optics/lens-psf-profile.js +12 -111
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/longitudinal-chromatic-aberration.js +1 -7
- package/dist/optics/longitudinal-chromatic-aberration.js.map +1 -1
- package/dist/optics/pupil-vignetting.js +1 -7
- package/dist/optics/pupil-vignetting.js.map +1 -1
- package/dist/optics/radial-distortion.js +1 -6
- package/dist/optics/radial-distortion.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.js +4 -96
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/optics/stray-light.d.ts +1 -0
- package/dist/optics/stray-light.js +1 -1
- package/dist/optics/stray-light.js.map +1 -1
- package/dist/optics/zernike-wavefront.js +1 -7
- package/dist/optics/zernike-wavefront.js.map +1 -1
- package/dist/output/capture-geometry.js +1 -8
- package/dist/output/capture-geometry.js.map +1 -1
- package/dist/output/developed-lens-corrections.d.ts +62 -0
- package/dist/output/developed-lens-corrections.js +135 -0
- package/dist/output/developed-lens-corrections.js.map +1 -0
- package/dist/output/generic-lens-corrections.d.ts +2 -6
- package/dist/output/generic-lens-corrections.js +3 -6
- package/dist/output/generic-lens-corrections.js.map +1 -1
- package/dist/output/geometric-transforms.js +1 -4
- package/dist/output/geometric-transforms.js.map +1 -1
- package/dist/output/native-capture-sdr.d.ts +2 -2
- package/dist/output/native-capture-sdr.js +3 -2
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/processing/development-detail.d.ts +29 -0
- package/dist/processing/development-detail.js +128 -107
- package/dist/processing/development-detail.js.map +1 -1
- package/dist/schema/illumination-temporal.js +3 -72
- package/dist/schema/illumination-temporal.js.map +1 -1
- package/dist/schema/illumination.d.ts +1 -0
- package/dist/schema/illumination.js +2 -65
- package/dist/schema/illumination.js.map +1 -1
- package/dist/schema/scene-radiance-temporal.js +2 -14
- package/dist/schema/scene-radiance-temporal.js.map +1 -1
- package/dist/schema/scene-radiance.js +2 -60
- package/dist/schema/scene-radiance.js.map +1 -1
- package/dist/schema/validation.d.ts +2 -0
- package/dist/schema/validation.js +2 -17
- package/dist/schema/validation.js.map +1 -1
- package/dist/sensor/accumulated-charge.js +2 -59
- package/dist/sensor/accumulated-charge.js.map +1 -1
- package/dist/sensor/architecture.js +1 -16
- package/dist/sensor/architecture.js.map +1 -1
- package/dist/sensor/camera-saturation-capacity.d.ts +1 -0
- package/dist/sensor/camera-saturation-capacity.js +3 -55
- package/dist/sensor/camera-saturation-capacity.js.map +1 -1
- package/dist/sensor/capture-color-sampling-binding.js +1 -26
- package/dist/sensor/capture-color-sampling-binding.js.map +1 -1
- package/dist/sensor/capture-mode-timing.js +1 -39
- package/dist/sensor/capture-mode-timing.js.map +1 -1
- package/dist/sensor/capture-mode.js +1 -23
- package/dist/sensor/capture-mode.js.map +1 -1
- package/dist/sensor/color-sampling.js +1 -26
- package/dist/sensor/color-sampling.js.map +1 -1
- package/dist/sensor/constant-rate-temporal-integration.js +2 -46
- package/dist/sensor/constant-rate-temporal-integration.js.map +1 -1
- package/dist/sensor/dark-current.js +2 -45
- package/dist/sensor/dark-current.js.map +1 -1
- package/dist/sensor/eqe-electron-rate.js +2 -35
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +5 -0
- package/dist/sensor/exposure-window.js +7 -22
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/iso-gain.js +1 -7
- package/dist/sensor/iso-gain.js.map +1 -1
- package/dist/sensor/iso-signal-chain.js +1 -43
- package/dist/sensor/iso-signal-chain.js.map +1 -1
- package/dist/sensor/optical-stack.js +1 -25
- package/dist/sensor/optical-stack.js.map +1 -1
- package/dist/sensor/photon-energy.js +1 -26
- package/dist/sensor/photon-energy.js.map +1 -1
- package/dist/sensor/physical-charge-capacity.js +3 -77
- package/dist/sensor/physical-charge-capacity.js.map +1 -1
- package/dist/sensor/radiometry-readiness.js +2 -23
- package/dist/sensor/radiometry-readiness.js.map +1 -1
- package/dist/sensor/raw-readout.d.ts +3 -0
- package/dist/sensor/raw-readout.js +4 -66
- package/dist/sensor/raw-readout.js.map +1 -1
- package/dist/sensor/raw-reconstruction.js +2 -64
- package/dist/sensor/raw-reconstruction.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.js +1 -9
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/dist/sensor/readout-timing.js +3 -57
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.d.ts +2 -0
- package/dist/sensor/response-application-compatibility.js +3 -29
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/response-operating-range.d.ts +1 -0
- package/dist/sensor/response-operating-range.js +3 -79
- package/dist/sensor/response-operating-range.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.js +4 -108
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sampling-aperture.js +1 -25
- package/dist/sensor/sampling-aperture.js.map +1 -1
- package/dist/sensor/spatial-sample-reduction.js +2 -19
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spatial-sampling-quadrature.js +1 -3
- package/dist/sensor/spatial-sampling-quadrature.js.map +1 -1
- package/dist/sensor/spatio-spectral-reduction.js +1 -18
- package/dist/sensor/spatio-spectral-reduction.js.map +1 -1
- package/dist/sensor/spectral-coverage.d.ts +10 -1
- package/dist/sensor/spectral-coverage.js +1 -1
- package/dist/sensor/spectral-coverage.js.map +1 -1
- package/dist/sensor/spectral-quadrature.js +2 -35
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/spectral-response.js +1 -47
- package/dist/sensor/spectral-response.js.map +1 -1
- package/dist/stabilization/camera-shake.js +1 -6
- package/dist/stabilization/camera-shake.js.map +1 -1
- package/dist/stabilization/system.js +2 -80
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +1 -0
- package/docs/API_REFERENCE.md +41 -2
- package/docs/QUICK_START.md +90 -8
- package/docs/USAGE.md +47 -2
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +53 -3
- package/docs/api/exposure-filtered-exposure-time.md +105 -0
- package/docs/api/facade-develop-joined-parts.md +32 -0
- package/docs/api/facade-simulate-capture.md +36 -5
- package/docs/api/optics-generic-nd-filter-presets.md +34 -0
- package/docs/api/optics-lens-psf-profile.md +3 -1
- package/docs/api/output-developed-lens-corrections.md +12 -0
- package/docs/api/output-generic-lens-corrections.md +0 -9
- package/llms.txt +1 -0
- package/package.json +1 -1
package/docs/USAGE.md
CHANGED
|
@@ -374,7 +374,7 @@ The actual focal length stays the physical optical quantity used by projection a
|
|
|
374
374
|
- Focus distance is not part of conventional 35 mm-equivalent focal length. A later digital/output crop and the output resolution are also excluded.
|
|
375
375
|
- If a product wants to describe the final digital framing, it should label it as output framing. It should not silently replace the optical focal length or the capture-equivalent focal length.
|
|
376
376
|
|
|
377
|
-
To render a lens by its physical focal length on any sensor, give `simulateCapture()` or the display view `lens.ideal: { focalLengthMm }` with any `lens.fNumber` within `IDEAL_LENS_LIMITS` (f/0.5–f/128, 1–4000 mm; optional `widestFNumber` and `narrowestFNumber` narrow the f-number range for the automatic exposure modes): an aberration-free thin lens that is not scaled by the crop factor, unlike `lens.prime` (see docs/QUICK_START.md, "Ideal lens at any focal length and f-number").
|
|
377
|
+
To render a lens by its physical focal length on any sensor, give `simulateCapture()` or the display view `lens.ideal: { focalLengthMm }` with any `lens.fNumber` within `IDEAL_LENS_LIMITS` (f/0.5–f/128, 1–4000 mm; optional `widestFNumber` and `narrowestFNumber` narrow the f-number range for the automatic exposure modes; in program the engine's program line is limited to that range, #583): an aberration-free thin lens that is not scaled by the crop factor, unlike `lens.prime` (see docs/QUICK_START.md, "Ideal lens at any focal length and f-number").
|
|
378
378
|
|
|
379
379
|
`calculateImagingAreaMetrics()` provides the same canonical diagonal crop-factor calculation, independent of raster density, so other engine modules do not need to repeat that formula.
|
|
380
380
|
|
|
@@ -1058,6 +1058,30 @@ T_stack = T_1 * T_2 * ... * T_n
|
|
|
1058
1058
|
|
|
1059
1059
|
The stack keeps each filter's identity and evidence. The combined numeric uncertainty is deliberately reported as **not propagated**, unless it is established whether the filters' errors are correlated or independent. Each filter's own uncertainty stays attached to that filter.
|
|
1060
1060
|
|
|
1061
|
+
### Exposure time with an ND filter
|
|
1062
|
+
|
|
1063
|
+
`calculateFilteredExposureTime({ shutterSeconds, filter, shutterDialSeconds? })` (model `filtered-exposure-time` 1.0.0, #578) gives the shutter time that keeps the same exposure at the same f-number and ISO after adding one filter or a stack (`filter` takes one profile or an array in light-path order): `filteredShutterSeconds = shutterSeconds / T`, with `T` the stack's combined transmittance from `composeFrontOfLensFilterTransmission()`. It also returns `attenuationStops`, `exposureFactor` (`1/T`) and the full `filterTransmission`. With a `shutterDialSeconds` list (for example `GENERIC_THIRD_STOP_SHUTTER_SECONDS`) it adds `dial`: the nearest dial value in stops (the shorter on a tie), its exposure error in stops, and `clamped: "maximum"` when the exact time is longer than the longest dial value (use bulb).
|
|
1064
|
+
|
|
1065
|
+
- Exact under the linear sensor model (exposure `H = E·t`); film reciprocity failure is not modelled.
|
|
1066
|
+
- Nominal filters vary: a "10-stop" filter (`T = 2^-10`) gives 1/125 s → 8.19 s, an ND1000 (OD 3.0, 9.97 stops) gives exactly 8 s. The result is only as good as the profile, and is an approximation whenever a profile is.
|
|
1067
|
+
- Generic presets: `GENERIC_ND_FILTER_PROFILES[3]`, `[6]` and `[10]` (keys in `GENERIC_ND_FILTER_STOPS`) are frozen, unbranded, spectrally flat profiles over 380–780 nm with a transmittance of exactly 2^-N (1/8, 1/64, 1/1024). They are idealized (`scientificStatus: "approximation"`, uncertainty not quantified), and any function that takes a front-of-lens filter profile accepts them. For other filters, build a profile with `parseFrontOfLensFilterProfile()`.
|
|
1068
|
+
- Filters are resolved at 550 nm unless `wavelengthNanometers` is given; neutral filters do not depend on it. `incidentPolarization` matters only with a polarizer in the stack.
|
|
1069
|
+
|
|
1070
|
+
```ts
|
|
1071
|
+
import {
|
|
1072
|
+
GENERIC_ND_FILTER_PROFILES,
|
|
1073
|
+
GENERIC_THIRD_STOP_SHUTTER_SECONDS,
|
|
1074
|
+
calculateFilteredExposureTime
|
|
1075
|
+
} from "@photivra/engine";
|
|
1076
|
+
|
|
1077
|
+
const { value } = calculateFilteredExposureTime({
|
|
1078
|
+
shutterSeconds: 1 / 125,
|
|
1079
|
+
filter: GENERIC_ND_FILTER_PROFILES[10],
|
|
1080
|
+
shutterDialSeconds: GENERIC_THIRD_STOP_SHUTTER_SECONDS
|
|
1081
|
+
});
|
|
1082
|
+
console.log(value.filteredShutterSeconds.toFixed(2), value.dial?.shutterSeconds); // 8.19 8
|
|
1083
|
+
```
|
|
1084
|
+
|
|
1061
1085
|
### Spectral boundary
|
|
1062
1086
|
|
|
1063
1087
|
Spectral filter data stays wavelength-resolved all the way through the [scene-radiance-to-sensor bridge](#scene-radiance-to-sensor-irradiance). Photivra does not turn a spectral filter into an undocumented RGB tint.
|
|
@@ -5527,6 +5551,20 @@ All modes:
|
|
|
5527
5551
|
|
|
5528
5552
|
Flash-aware behaviour, safety shift and the program behaviour of named cameras are separate work.
|
|
5529
5553
|
|
|
5554
|
+
### The capture facade's program line and the lens's f-number range (#583)
|
|
5555
|
+
|
|
5556
|
+
`simulateCapture()` and the display view in `exposure.mode: "program"` use an engine-authored generic line (f/16 1/2000 s … f/8
|
|
5557
|
+
1/125 s … f/4 1.024 s, assumption `exposure.programLine`). `resolveProgramAutoExposureMode()` refuses a line whose apertures leave
|
|
5558
|
+
the capability range, so with a lens range that does not hold f/4–f/16 (`lens.ideal` `widestFNumber`/`narrowestFNumber`,
|
|
5559
|
+
`lens.prime`, `lens.catalogue`) the facade limits the line to the range first: the line's f/4 and f/16 are clamped to the range, giving the same shape with
|
|
5560
|
+
the aperture held at the range's end and the shutter keeping each point's exposure (t/N², camera equation H = 0.65·L·t/N²),
|
|
5561
|
+
still from 1/2000 s to 1.024 s. Where both lines run, the limited line's aperture is the old one clamped in log2 to the range.
|
|
5562
|
+
Beyond the line's ends the resolver holds them as before. A range that holds f/4–f/16, or no range, keeps the line and its
|
|
5563
|
+
bytes. The limited line is recorded as its profile (id `"facade-generic-program-line-lens-range"`), with node stops measured from the
|
|
5564
|
+
capture's exposure anchor (f/8, 1/125 s; the same N²/t at the range's aperture nearest f/8; or, #585, that aperture at the
|
|
5565
|
+
body's shortest shutter when the same N²/t would need a shorter one). An approximation of a generic
|
|
5566
|
+
program, not a manufacturer's.
|
|
5567
|
+
|
|
5530
5568
|
## Program Auto and Full Auto exposure
|
|
5531
5569
|
|
|
5532
5570
|
Program Auto and Full Auto exposure both need a declared, versioned **program line**: a curve that says which aperture and shutter to use at each brightness level. The engine does not invent one "correct" aperture/shutter pair.
|
|
@@ -7480,7 +7518,8 @@ own designs, not real products). `resolveGenericLens` resolves one for a sensor,
|
|
|
7480
7518
|
(scaled by the crop factor), aperture range, close focus, projection and its character, Seidel aberrations, axial and lateral
|
|
7481
7519
|
colour, distortion and vignetting profiles, flare, breathing and focus scatter, each a labelled approximation.
|
|
7482
7520
|
`simulateGenericLensFocusError` draws a seeded autofocus error; `createGenericLensCorrectionProfile` builds the lens's generic
|
|
7483
|
-
correction profile for `resolveLensCorrectionPlan
|
|
7521
|
+
correction profile for `resolveLensCorrectionPlan`, which `simulateCapture` applies to its developed image with
|
|
7522
|
+
`output.lensCorrections` (#570; never to the RAW or the DNG). `simulateCapture` renders a catalogue lens with `lens.catalogue`
|
|
7484
7523
|
([quick start](QUICK_START.md#generic-lens-catalogue-549)); `fast: true` (or `lens: { catalogue: { kind, fast: true } }`) takes its
|
|
7485
7524
|
fast method (#568), a labeled approximation that blends the PSF over a field grid, for interactive captures. Equations, tables and the
|
|
7486
7525
|
chart measurements: [LENS_CATALOGUE.md](https://github.com/Photivra/photivra/blob/main/docs/LENS_CATALOGUE.md).
|
|
@@ -7742,6 +7781,12 @@ console.log(star.assumptions.filter((a) => a.kind === "default").map((a) => a.id
|
|
|
7742
7781
|
console.log(star.request.siteInput(0).environment.optics.nominalFNumber);
|
|
7743
7782
|
```
|
|
7744
7783
|
|
|
7784
|
+
A capture can render its RAW in parallel parts (`output.region`, one call per part). `serializeSimulatedCaptureDngFromParts()`
|
|
7785
|
+
writes the whole frame's DNG from the parts, and `simulateCaptureFromParts()` (#571) develops the whole frame from them,
|
|
7786
|
+
including the whole-image stages `output.diffractionCorrection` and `output.sharpening` that a region refuses, with the same
|
|
7787
|
+
bytes as a whole-frame `simulateCapture()` and per-row progress (`diffraction-correction`, `sharpening`). See
|
|
7788
|
+
[Quick start, Developing a capture rendered in parts](QUICK_START.md#developing-a-capture-rendered-in-parts-571).
|
|
7789
|
+
|
|
7745
7790
|
### Color charts (2.14)
|
|
7746
7791
|
|
|
7747
7792
|
The engine's own [color patches](https://github.com/Photivra/photivra/blob/main/docs/COLOR_PATCHES.md) are reflectance spectra lit by the capture's illuminant. Draw the
|
package/docs/api/core-version.md
CHANGED
|
@@ -11,5 +11,5 @@ version they were made with. Proof-of-concept (POC), schema and model contracts
|
|
|
11
11
|
own versions. Release checks confirm it matches package.json and the packed package.
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
ENGINE_API_VERSION = "2.
|
|
14
|
+
ENGINE_API_VERSION = "2.19.0" as const
|
|
15
15
|
```
|
package/docs/api/exports.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"packageVersion": "2.
|
|
3
|
-
"engineApiVersion": "2.
|
|
2
|
+
"packageVersion": "2.19.0",
|
|
3
|
+
"engineApiVersion": "2.19.0",
|
|
4
4
|
"exports": [
|
|
5
5
|
{
|
|
6
6
|
"name": "AbsoluteUncertaintyEstimate",
|
|
@@ -732,6 +732,16 @@
|
|
|
732
732
|
"source": "src/camera/field-of-view.ts",
|
|
733
733
|
"kind": "type"
|
|
734
734
|
},
|
|
735
|
+
{
|
|
736
|
+
"name": "calculateFilteredExposureTime",
|
|
737
|
+
"source": "src/exposure/filtered-exposure-time.ts",
|
|
738
|
+
"kind": "runtime"
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
"name": "CalculateFilteredExposureTimeInput",
|
|
742
|
+
"source": "src/exposure/filtered-exposure-time.ts",
|
|
743
|
+
"kind": "type"
|
|
744
|
+
},
|
|
735
745
|
{
|
|
736
746
|
"name": "calculateFlashGuideNumber",
|
|
737
747
|
"source": "src/exposure/flash-ttl.ts",
|
|
@@ -3317,6 +3327,21 @@
|
|
|
3317
3327
|
"source": "src/camera/field-of-view.ts",
|
|
3318
3328
|
"kind": "type"
|
|
3319
3329
|
},
|
|
3330
|
+
{
|
|
3331
|
+
"name": "FILTERED_EXPOSURE_DEFAULT_WAVELENGTH_NANOMETERS",
|
|
3332
|
+
"source": "src/exposure/filtered-exposure-time.ts",
|
|
3333
|
+
"kind": "runtime"
|
|
3334
|
+
},
|
|
3335
|
+
{
|
|
3336
|
+
"name": "FilteredExposureDialSetting",
|
|
3337
|
+
"source": "src/exposure/filtered-exposure-time.ts",
|
|
3338
|
+
"kind": "type"
|
|
3339
|
+
},
|
|
3340
|
+
{
|
|
3341
|
+
"name": "FilteredExposureTime",
|
|
3342
|
+
"source": "src/exposure/filtered-exposure-time.ts",
|
|
3343
|
+
"kind": "type"
|
|
3344
|
+
},
|
|
3320
3345
|
{
|
|
3321
3346
|
"name": "FixedMultiFrameCaptureAcquisition",
|
|
3322
3347
|
"source": "src/sensor/capture-mode.ts",
|
|
@@ -3584,7 +3609,7 @@
|
|
|
3584
3609
|
},
|
|
3585
3610
|
{
|
|
3586
3611
|
"name": "GENERIC_LENS_CORRECTION_CHANNEL_WAVELENGTHS_NM",
|
|
3587
|
-
"source": "src/output/
|
|
3612
|
+
"source": "src/output/developed-lens-corrections.ts",
|
|
3588
3613
|
"kind": "runtime"
|
|
3589
3614
|
},
|
|
3590
3615
|
{
|
|
@@ -3597,6 +3622,16 @@
|
|
|
3597
3622
|
"source": "src/equipment/generic-lens-catalogue.ts",
|
|
3598
3623
|
"kind": "runtime"
|
|
3599
3624
|
},
|
|
3625
|
+
{
|
|
3626
|
+
"name": "GENERIC_ND_FILTER_PROFILES",
|
|
3627
|
+
"source": "src/optics/generic-nd-filter-presets.ts",
|
|
3628
|
+
"kind": "runtime"
|
|
3629
|
+
},
|
|
3630
|
+
{
|
|
3631
|
+
"name": "GENERIC_ND_FILTER_STOPS",
|
|
3632
|
+
"source": "src/optics/generic-nd-filter-presets.ts",
|
|
3633
|
+
"kind": "runtime"
|
|
3634
|
+
},
|
|
3600
3635
|
{
|
|
3601
3636
|
"name": "GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM",
|
|
3602
3637
|
"source": "src/equipment/generic-prime-lenses.ts",
|
|
@@ -3747,6 +3782,11 @@
|
|
|
3747
3782
|
"source": "src/equipment/generic-lens-catalogue.ts",
|
|
3748
3783
|
"kind": "type"
|
|
3749
3784
|
},
|
|
3785
|
+
{
|
|
3786
|
+
"name": "GenericNdFilterStops",
|
|
3787
|
+
"source": "src/optics/generic-nd-filter-presets.ts",
|
|
3788
|
+
"kind": "type"
|
|
3789
|
+
},
|
|
3750
3790
|
{
|
|
3751
3791
|
"name": "GenericOpticalEvidence",
|
|
3752
3792
|
"source": "src/optics/profile-contract.ts",
|
|
@@ -8572,11 +8612,21 @@
|
|
|
8572
8612
|
"source": "src/facade/simulate-capture.ts",
|
|
8573
8613
|
"kind": "type"
|
|
8574
8614
|
},
|
|
8615
|
+
{
|
|
8616
|
+
"name": "simulateCaptureFromParts",
|
|
8617
|
+
"source": "src/facade/develop-joined-parts.ts",
|
|
8618
|
+
"kind": "runtime"
|
|
8619
|
+
},
|
|
8575
8620
|
{
|
|
8576
8621
|
"name": "SimulateCaptureLensCatalogueRecord",
|
|
8577
8622
|
"source": "src/facade/simulate-capture.ts",
|
|
8578
8623
|
"kind": "type"
|
|
8579
8624
|
},
|
|
8625
|
+
{
|
|
8626
|
+
"name": "SimulateCaptureLensCorrections",
|
|
8627
|
+
"source": "src/facade/simulate-capture.ts",
|
|
8628
|
+
"kind": "type"
|
|
8629
|
+
},
|
|
8580
8630
|
{
|
|
8581
8631
|
"name": "SimulateCaptureLensDistortion",
|
|
8582
8632
|
"source": "src/facade/simulate-capture.ts",
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# exposure/filtered-exposure-time.ts public contracts
|
|
2
|
+
|
|
3
|
+
The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
|
|
4
|
+
|
|
5
|
+
## calculateFilteredExposureTime
|
|
6
|
+
|
|
7
|
+
Shutter time that keeps the same exposure after adding front-of-lens filters, such as a
|
|
8
|
+
neutral-density (ND) filter: t / T, with T the combined transmittance of the filter profiles.
|
|
9
|
+
Aperture and ISO are unchanged.
|
|
10
|
+
|
|
11
|
+
Exact under the linear sensor model (exposure H = E·t); film reciprocity failure is not modelled.
|
|
12
|
+
Nominal filters vary: a "10-stop" or ND1000 (OD 3.0, 9.97 stops) filter transmits roughly, not
|
|
13
|
+
exactly, its rating, so the result is only as good as the profile. The envelope is an
|
|
14
|
+
approximation whenever any profile's `scientificStatus` is `"approximation"`.
|
|
15
|
+
|
|
16
|
+
Example: 1/125 s with `GENERIC_ND_FILTER_PROFILES[10]` (exactly 2^-10) gives 1024/125 = 8.192 s;
|
|
17
|
+
on a third-stop dial, 8 s.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
export function calculateFilteredExposureTime(
|
|
21
|
+
input: CalculateFilteredExposureTimeInput
|
|
22
|
+
): CalculationResult<FilteredExposureTime>;
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
26
|
+
|
|
27
|
+
## CalculateFilteredExposureTimeInput
|
|
28
|
+
|
|
29
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
export interface CalculateFilteredExposureTimeInput {
|
|
33
|
+
/** Shutter time without the filter, in seconds. */
|
|
34
|
+
shutterSeconds: number;
|
|
35
|
+
/**
|
|
36
|
+
* One front-of-lens filter profile, or several in light-path order (scene side first), as
|
|
37
|
+
* accepted by `composeFrontOfLensFilterTransmission`.
|
|
38
|
+
*/
|
|
39
|
+
filter: FrontOfLensFilterProfile | readonly FrontOfLensFilterProfile[];
|
|
40
|
+
/**
|
|
41
|
+
* Optional shutter dial, in seconds (for example `GENERIC_THIRD_STOP_SHUTTER_SECONDS`). When
|
|
42
|
+
* given, the result also reports the nearest dial value (nearest in stops, the shorter on a tie).
|
|
43
|
+
*/
|
|
44
|
+
shutterDialSeconds?: readonly number[];
|
|
45
|
+
/** Wavelength at which the filters are resolved. Defaults to 550 nm. Neutral filters do not depend on it. */
|
|
46
|
+
wavelengthNanometers?: number;
|
|
47
|
+
/** Wavelength basis; defaults to the first filter profile's basis and must match every profile. */
|
|
48
|
+
wavelengthBasis?: Exclude<SpectralWavelengthBasis, "unspecified">;
|
|
49
|
+
/** Incident polarization, which matters only when a polarizer is in the stack. Omitted means unpolarized. */
|
|
50
|
+
incidentPolarization?: LinearPolarizationState;
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## FILTERED_EXPOSURE_DEFAULT_WAVELENGTH_NANOMETERS
|
|
55
|
+
|
|
56
|
+
Wavelength used when the caller gives none: 550 nm, near the photopic peak. Neutral filters do not depend on it.
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
FILTERED_EXPOSURE_DEFAULT_WAVELENGTH_NANOMETERS = 550 as const
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## FilteredExposureDialSetting
|
|
63
|
+
|
|
64
|
+
The dial value nearest the exact filtered shutter time.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
export interface FilteredExposureDialSetting {
|
|
68
|
+
/** Nearest dial value in seconds. */
|
|
69
|
+
shutterSeconds: number;
|
|
70
|
+
/**
|
|
71
|
+
* log2(dial / exact filtered time): exposure of the dial setting relative to the unfiltered
|
|
72
|
+
* exposure, in stops. Positive is brighter (longer), negative darker.
|
|
73
|
+
*/
|
|
74
|
+
exposureErrorStops: number;
|
|
75
|
+
/** `"maximum"` when the exact time is longer than every dial value (use bulb for the exact time), `"minimum"` when shorter than every one. */
|
|
76
|
+
clamped: false | "minimum" | "maximum";
|
|
77
|
+
/** How the dial value was chosen. */
|
|
78
|
+
quantizationPolicy: "nearest-log2-shorter-on-tie";
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## FilteredExposureTime
|
|
83
|
+
|
|
84
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
export interface FilteredExposureTime {
|
|
88
|
+
/** Shutter time without the filter, in seconds. */
|
|
89
|
+
shutterSeconds: number;
|
|
90
|
+
/** Shutter time that gives the same exposure with the filter: shutterSeconds / linearTransmissionFactor. */
|
|
91
|
+
filteredShutterSeconds: number;
|
|
92
|
+
/** Combined intensity transmittance T of the filter stack, in (0, 1]. */
|
|
93
|
+
linearTransmissionFactor: number;
|
|
94
|
+
/** Combined attenuation −log2 T, in stops. */
|
|
95
|
+
attenuationStops: number;
|
|
96
|
+
/** Shutter multiplier 1/T = 2^attenuationStops. */
|
|
97
|
+
exposureFactor: number;
|
|
98
|
+
/** Wavelength at which the filters were resolved, in nanometres. */
|
|
99
|
+
wavelengthNanometers: number;
|
|
100
|
+
/** The filter-stack transmission this result is based on, with each filter's identity and evidence. */
|
|
101
|
+
filterTransmission: ComposedFrontOfLensFilterTransmission;
|
|
102
|
+
/** Nearest shutter-dial value; present only when `shutterDialSeconds` was given. */
|
|
103
|
+
dial?: FilteredExposureDialSetting;
|
|
104
|
+
}
|
|
105
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# facade/develop-joined-parts.ts public contracts
|
|
2
|
+
|
|
3
|
+
The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
|
|
4
|
+
|
|
5
|
+
## simulateCaptureFromParts
|
|
6
|
+
|
|
7
|
+
Develops the whole frame of `options` from the packed RAW of region renders of the same request (#571), so a capture can
|
|
8
|
+
render its RAW in parallel parts and still take the development steps that filter across the whole image:
|
|
9
|
+
`output.diffractionCorrection` and `output.sharpening`, which a region render refuses, and `output.lensCorrections` (#570), which
|
|
10
|
+
runs on the whole developed frame here exactly as in `simulateCapture(options)`. The parts are joined exactly as
|
|
11
|
+
{@link serializeSimulatedCaptureDngFromParts } joins them (they must cover every native site and agree where they overlap),
|
|
12
|
+
and the joined RAW is the whole render's RAW, so the result's `image` (samples and JPEG or PNG bytes), `raw` codes and
|
|
13
|
+
`plan` are those of `simulateCapture(options)`, bit for bit.
|
|
14
|
+
|
|
15
|
+
`options` is the whole request (no `output.region`), with the development options it should have; render the parts with
|
|
16
|
+
the same request plus `output.region`, without `output.diffractionCorrection`, `output.sharpening` and `output.dng`, and with a
|
|
17
|
+
fixed white balance in place of `"auto"` (none of these change the RAW codes; auto white balance is measured here over the
|
|
18
|
+
joined frame). A part may keep or drop `output.lensCorrections` (a corrected region only widens its `region.nativeRect`).
|
|
19
|
+
Any `output.format` serves for a part.
|
|
20
|
+
|
|
21
|
+
`onProgress` reports the `white-balance` (with auto white balance), `development`, `diffraction-correction`, `sharpening` and
|
|
22
|
+
`jpeg` stages, the detail stages once per output row, so a host can show "Applying sharpening to the whole image". The lens
|
|
23
|
+
corrections report no stage of their own: they run between `diffraction-correction` and `sharpening`.
|
|
24
|
+
No `raw` stage is reported: no RAW is rendered. What differs from the whole render's result: `diagnostics.providerEvaluationCount`
|
|
25
|
+
is 0, `diagnostics.timingsMs` are this call's, `diagnostics.fast` and the `raw.*` assumptions of how the RAW was rendered are
|
|
26
|
+
not repeated (they are in the parts' results), and a `parts` assumption records the join.
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
export async function simulateCaptureFromParts(options: SimulateCaptureOptions, parts: readonly SimulateCaptureDngPart[]): Promise<SimulateCaptureResult>;
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
This call is asynchronous; byte hashing uses the caller runtime's Web Crypto.
|
|
@@ -144,7 +144,7 @@ a capture does. `motion.rotation` is a non-zero angular velocity; `sensor.tempor
|
|
|
144
144
|
SIMULATE_CAPTURE_COST_OPTIONS = Object.freeze(["lens.pupilSampling", "lens.projection", "lens.distortion", "lens.vignetting", "lens.psf",
|
|
145
145
|
"lens.diffraction", "lens.defocus", "lens.catalogue", "sensor.antiAliasing", "sensor.pixelAperture.box", "sensor.temporalSampleCount", "motion.rotation", "motion.shutter.rolling", "output.borderHandling.mirror", "output.region",
|
|
146
146
|
"output.whiteBalance.auto", "output.demosaic.ahd", "output.highlightMode.reconstruct", "output.colorEncoding.wide-gamut", "output.gamutMapping.perceptual",
|
|
147
|
-
"output.diffractionCorrection", "output.sharpening", "output.format.jpeg", "output.format.png", "output.format.dng"] as const)
|
|
147
|
+
"output.diffractionCorrection", "output.sharpening", "output.lensCorrections", "output.format.jpeg", "output.format.png", "output.format.dng"] as const)
|
|
148
148
|
```
|
|
149
149
|
|
|
150
150
|
## SIMULATE_CAPTURE_DEFAULT_ILLUMINANCE_LUX
|
|
@@ -467,6 +467,22 @@ export interface SimulateCaptureFastReport {
|
|
|
467
467
|
export interface SimulateCaptureLensCatalogueRecord { kind: string; fast?: boolean }
|
|
468
468
|
```
|
|
469
469
|
|
|
470
|
+
## SimulateCaptureLensCorrections
|
|
471
|
+
|
|
472
|
+
`output.lensCorrections` (#570): which of the catalogue lens's generic corrections (`createGenericLensCorrectionProfile`) the
|
|
473
|
+
development applies. Each is off unless set to true.
|
|
474
|
+
|
|
475
|
+
```ts
|
|
476
|
+
export interface SimulateCaptureLensCorrections {
|
|
477
|
+
/** Radial distortion r_d = r(1 + k1ρ²), inverted by resampling: it stretches the corners and lowers their resolution. */
|
|
478
|
+
distortion?: boolean;
|
|
479
|
+
/** Lateral colour: each channel rescaled by 1/(1 + L·D(λ_c)) into register; axial (longitudinal) colour stays. */
|
|
480
|
+
lateralColor?: boolean;
|
|
481
|
+
/** Vignetting: a gain 1/E(ρ) at each pixel's source point; corner noise rises with the signal, the SNR does not. */
|
|
482
|
+
vignetting?: boolean;
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
|
|
470
486
|
## SimulateCaptureLensDistortion
|
|
471
487
|
|
|
472
488
|
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
@@ -531,7 +547,8 @@ export interface SimulateCaptureOptions {
|
|
|
531
547
|
* distance beyond the focal length (no minimum focus distance; `subjectDistanceM` must be at least twice the focal length, as for
|
|
532
548
|
* every lens). Works in `simulateCapture` and the display view. Not combinable with `prime`, `catalogue` or `focalLengthMm`.
|
|
533
549
|
* Optional `widestFNumber` and `narrowestFNumber` (within `IDEAL_LENS_LIMITS`, widest ≤ narrowest; each defaults to its bound)
|
|
534
|
-
* narrow the range: `fNumber` must lie in it, and shutter priority and program choose apertures only in it
|
|
550
|
+
* narrow the range: `fNumber` must lie in it, and shutter priority and program choose apertures only in it (program limits its
|
|
551
|
+
* line to a range that does not hold f/4–f/16, #583). Default off.
|
|
535
552
|
*/
|
|
536
553
|
ideal?: { focalLengthMm: number; widestFNumber?: number; narrowestFNumber?: number };
|
|
537
554
|
/**
|
|
@@ -738,6 +755,16 @@ export interface SimulateCaptureOptions {
|
|
|
738
755
|
* (not the wide-gamut or perceptual PNG paths); not combinable with `region`. The DNG's RAW codes are not changed. Default off.
|
|
739
756
|
*/
|
|
740
757
|
sharpening?: SimulateCaptureSharpening;
|
|
758
|
+
/**
|
|
759
|
+
* Opt-in (#570), with `lens.catalogue`: the lens's generic corrections (see {@link SimulateCaptureLensCorrections}) on the
|
|
760
|
+
* developed linear colour, after demosaic, colour, white balance and `diffractionCorrection`, before the tone curve; for the JPEG,
|
|
761
|
+
* PNG and samples. The RAW and the DNG are never corrected. To keep the output size with no missing pixels, the corrected image is
|
|
762
|
+
* magnified by the smallest factor 1/m ≥ 1 that keeps every pixel's source inside the frame (recorded in the
|
|
763
|
+
* `output.lensCorrections` assumption). Works with `region`: a region develops the frame pixels its corrected pixels read
|
|
764
|
+
* (`region.nativeRect`, `raw` and `plan` describe that rectangle) and its pixels are the whole render's. All off (or omitted):
|
|
765
|
+
* the development is unchanged.
|
|
766
|
+
*/
|
|
767
|
+
lensCorrections?: SimulateCaptureLensCorrections;
|
|
741
768
|
};
|
|
742
769
|
/** Camera motion and shutter type. Default: still camera, global electronic shutter. */
|
|
743
770
|
motion?: SimulateCaptureMotion;
|
|
@@ -776,7 +803,7 @@ export interface SimulateCaptureOptions {
|
|
|
776
803
|
fast?: boolean;
|
|
777
804
|
/** Aborting cancels the running task; the promise rejects with a domain error and returns no partial image. */
|
|
778
805
|
signal?: AbortSignal;
|
|
779
|
-
/** Called after each committed RAW, development or JPEG tile. Cannot change output. */
|
|
806
|
+
/** Called after each committed RAW, development, detail or JPEG tile (see {@link SimulateCaptureProgress}). Cannot change output. */
|
|
780
807
|
onProgress?: (progress: SimulateCaptureProgress) => void;
|
|
781
808
|
}
|
|
782
809
|
```
|
|
@@ -799,11 +826,15 @@ export type SimulateCapturePixelAperture = "point" | "box" | { kind: "box"; samp
|
|
|
799
826
|
|
|
800
827
|
## SimulateCaptureProgress
|
|
801
828
|
|
|
802
|
-
|
|
829
|
+
One progress event of `onProgress`. Stages run in this order: `raw`, `white-balance` (with auto white balance), `development`
|
|
830
|
+
(rows), then, when requested, `diffraction-correction` and `sharpening` (#571: one event per output row of the whole image;
|
|
831
|
+
each stage's last event has `completedTileCount === totalTileCount`), then `jpeg`. `output.lensCorrections` (#570) runs between
|
|
832
|
+
`diffraction-correction` and `sharpening` and reports no stage of its own. {@link simulateCaptureFromParts }
|
|
833
|
+
reports no `raw` stage: its RAW comes from the parts.
|
|
803
834
|
|
|
804
835
|
```ts
|
|
805
836
|
export interface SimulateCaptureProgress {
|
|
806
|
-
stage: "raw" | "white-balance" | "development" | "jpeg";
|
|
837
|
+
stage: "raw" | "white-balance" | "development" | "diffraction-correction" | "sharpening" | "jpeg";
|
|
807
838
|
completedTileCount: number;
|
|
808
839
|
totalTileCount: number;
|
|
809
840
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# optics/generic-nd-filter-presets.ts public contracts
|
|
2
|
+
|
|
3
|
+
The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
|
|
4
|
+
|
|
5
|
+
## GENERIC_ND_FILTER_PROFILES
|
|
6
|
+
|
|
7
|
+
Frozen generic ND filter profiles keyed by stops: `GENERIC_ND_FILTER_PROFILES[10]` transmits
|
|
8
|
+
exactly 1/1024. Spectrally flat over 380–780 nm (air), idealized (`scientificStatus:
|
|
9
|
+
"approximation"`), unbranded. 1/125 s with the 10-stop preset gives 1024/125 ≈ 8.19 s in
|
|
10
|
+
`calculateFilteredExposureTime`.
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
GENERIC_ND_FILTER_PROFILES: Readonly<Record<GenericNdFilterStops, FrontOfLensFilterProfile>> = freezeOwnedData({
|
|
14
|
+
3: idealNdProfile(3),
|
|
15
|
+
6: idealNdProfile(6),
|
|
16
|
+
10: idealNdProfile(10)
|
|
17
|
+
})
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## GENERIC_ND_FILTER_STOPS
|
|
21
|
+
|
|
22
|
+
Attenuations, in stops, of the generic ND presets.
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
GENERIC_ND_FILTER_STOPS = Object.freeze([3, 6, 10] as const)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## GenericNdFilterStops
|
|
29
|
+
|
|
30
|
+
One of the generic ND preset attenuations: 3, 6 or 10 stops.
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
export type GenericNdFilterStops = (typeof GENERIC_ND_FILTER_STOPS)[number];
|
|
34
|
+
```
|
|
@@ -200,7 +200,9 @@ Kernel interpolation between regular-grid nodes.
|
|
|
200
200
|
- `rotationally-symmetric-radial-field-centroid-aligned`: for a rotationally symmetric lens. Nodes
|
|
201
201
|
are declared only along the +X field axis (fieldYmm = [0], fieldXmm >= 0). A query at field
|
|
202
202
|
(x, y) is interpolated, with centroid alignment, at radius hypot(x, y). The kernel is then
|
|
203
|
-
rotated by atan2(y, x) about its centre
|
|
203
|
+
rotated by atan2(y, x) about its centre, with the kernel row index increasing with image +Y (the
|
|
204
|
+
convention the environment PSF quadrature applies), so an asymmetric kernel points the same way
|
|
205
|
+
as in the 2-D grid modes. The sample pitch must be square.
|
|
204
206
|
Shifts and rotations use bilinear resampling. This smooths the kernel slightly (by at most about
|
|
205
207
|
one sample). Samples outside the kernel are zero, and the result is renormalised to unit energy.
|
|
206
208
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# output/developed-lens-corrections.ts public contracts
|
|
2
|
+
|
|
3
|
+
The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
|
|
4
|
+
|
|
5
|
+
## GENERIC_LENS_CORRECTION_CHANNEL_WAVELENGTHS_NM
|
|
6
|
+
|
|
7
|
+
Effective wavelengths of the red, green and blue channels for the lateral-colour map, nm: a generic approximation of where
|
|
8
|
+
a camera's channel responses peak, not a measured camera.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
GENERIC_LENS_CORRECTION_CHANNEL_WAVELENGTHS_NM: Readonly<Record<LensCorrectionChannel, number>> = Object.freeze({ red: 610, green: 540, blue: 465 })
|
|
12
|
+
```
|
|
@@ -28,12 +28,3 @@ export interface CreateGenericLensCorrectionProfileInput {
|
|
|
28
28
|
state: OpticalProfileState;
|
|
29
29
|
}
|
|
30
30
|
```
|
|
31
|
-
|
|
32
|
-
## GENERIC_LENS_CORRECTION_CHANNEL_WAVELENGTHS_NM
|
|
33
|
-
|
|
34
|
-
Effective wavelengths of the red, green and blue channels for the lateral-colour map, nm: a generic approximation of where
|
|
35
|
-
a camera's channel responses peak, not a measured camera.
|
|
36
|
-
|
|
37
|
-
```ts
|
|
38
|
-
GENERIC_LENS_CORRECTION_CHANNEL_WAVELENGTHS_NM: Readonly<Record<LensCorrectionChannel, number>> = Object.freeze({ red: 610, green: 540, blue: 465 })
|
|
39
|
-
```
|
package/llms.txt
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
- [calculateBlurShareOfFrame()](https://github.com/Photivra/photivra/blob/main/docs/api/camera-sensor-equivalence.md#calculateblurshareofframe): a blur circle as a share of the frame diagonal, or its size on a print
|
|
29
29
|
- [calculateCenteredCrop()](https://github.com/Photivra/photivra/blob/main/docs/api/output-crop.md#calculatecenteredcrop): pixels left after a centred crop
|
|
30
30
|
- [calculateProjectedMotionBlur()](https://github.com/Photivra/photivra/blob/main/docs/api/motion-projected-motion.md#calculateprojectedmotionblur): how far a moving subject smears on the sensor during the shutter time
|
|
31
|
+
- [calculateFilteredExposureTime()](https://github.com/Photivra/photivra/blob/main/docs/api/exposure-filtered-exposure-time.md#calculatefilteredexposuretime): shutter time that keeps the same exposure with an ND (or any front-of-lens) filter, and the nearest shutter-dial value; `GENERIC_ND_FILTER_PROFILES` gives idealized 3-, 6- and 10-stop filters (exactly 2^-N)
|
|
31
32
|
- [calculateAiryDisk()](https://github.com/Photivra/photivra/blob/main/docs/api/optics-diffraction.md#calculateairydisk): diffraction spot size from f-number and wavelength
|
|
32
33
|
- [calculateSignalToNoise()](https://github.com/Photivra/photivra/blob/main/docs/api/sensor-signal-noise.md#calculatesignaltonoise): expected SNR from signal and read noise in electrons
|
|
33
34
|
- [calculateChromaticityFromCorrelatedColorTemperature()](https://github.com/Photivra/photivra/blob/main/docs/api/color-illuminants.md#calculatechromaticityfromcorrelatedcolortemperature): white point for a colour temperature in kelvin
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@photivra/engine",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.19.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Scientific TypeScript engine for camera optics, exposure, focus, motion, sensor sampling, diffraction, and digital imaging calculations.",
|
|
6
6
|
"type": "module",
|