@photivra/engine 2.19.0 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +289 -1
- package/CITATION.cff +1 -1
- package/NODE_SUPPORT.md +7 -5
- package/README.md +7 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +21 -10
- package/dist/capture/dng-lens-correction-opcodes.d.ts +32 -0
- package/dist/capture/dng-lens-correction-opcodes.js +119 -0
- package/dist/capture/dng-lens-correction-opcodes.js.map +1 -0
- package/dist/capture/exposure-build-up-stage.d.ts +16 -0
- package/dist/capture/exposure-build-up-stage.js +4 -0
- package/dist/capture/exposure-build-up-stage.js.map +1 -0
- package/dist/capture/native-environment-lean.d.ts +2 -1
- package/dist/capture/native-environment-lean.js +42 -78
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-tabulated.js +4 -3
- package/dist/capture/native-environment-tabulated.js.map +1 -1
- package/dist/capture/native-raw-dng.d.ts +6 -0
- package/dist/capture/native-raw-dng.js +16 -2
- package/dist/capture/native-raw-dng.js.map +1 -1
- package/dist/capture/native-raw.d.ts +3 -2
- package/dist/capture/native-raw.js +5 -4
- package/dist/capture/native-raw.js.map +1 -1
- package/dist/capture/sensor-raw-producer.d.ts +4 -1
- package/dist/capture/sensor-raw-producer.js +15 -8
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/core/shared-helpers.d.ts +2 -0
- package/dist/core/shared-helpers.js +4 -0
- package/dist/core/shared-helpers.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/generic-lens-catalogue.d.ts +11 -4
- package/dist/equipment/generic-lens-catalogue.js +49 -7
- package/dist/equipment/generic-lens-catalogue.js.map +1 -1
- package/dist/equipment/generic-tier-assets.d.ts +32 -0
- package/dist/equipment/generic-tier-assets.js +18 -14
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/generic-tier-presets.js +2 -3
- package/dist/equipment/generic-tier-presets.js.map +1 -1
- package/dist/equipment/sensor-profile-body.d.ts +78 -0
- package/dist/equipment/sensor-profile-body.js +77 -0
- package/dist/equipment/sensor-profile-body.js.map +1 -0
- package/dist/equipment/sensor-profiles.d.ts +8 -0
- package/dist/equipment/sensor-profiles.js +82 -0
- package/dist/equipment/sensor-profiles.js.map +1 -0
- package/dist/facade/catalogue-lens-signal.d.ts +2 -2
- package/dist/facade/catalogue-lens-signal.js +58 -71
- package/dist/facade/catalogue-lens-signal.js.map +1 -1
- package/dist/facade/chart-radiance-batch.js +2 -1
- package/dist/facade/chart-radiance-batch.js.map +1 -1
- package/dist/facade/defocus-image-space-provider.d.ts +7 -0
- package/dist/facade/defocus-image-space-provider.js +64 -76
- package/dist/facade/defocus-image-space-provider.js.map +1 -1
- package/dist/facade/display-view-gpu-session.js +2 -0
- package/dist/facade/display-view-gpu-session.js.map +1 -1
- package/dist/facade/display-view-gpu.d.ts +13 -5
- package/dist/facade/display-view-gpu.js +4 -4
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view-lens-signal.d.ts +1 -1
- package/dist/facade/display-view-lens-signal.js +30 -26
- package/dist/facade/display-view-lens-signal.js.map +1 -1
- package/dist/facade/display-view.d.ts +3 -1
- package/dist/facade/display-view.js +6 -24
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/expected-signal-setup.d.ts +3 -1
- package/dist/facade/expected-signal-setup.js +1 -1
- package/dist/facade/expected-signal-setup.js.map +1 -1
- package/dist/facade/expected-signal.d.ts +47 -14
- package/dist/facade/expected-signal.js +117 -112
- package/dist/facade/expected-signal.js.map +1 -1
- package/dist/facade/exposure-build-up.d.ts +70 -0
- package/dist/facade/exposure-build-up.js +164 -0
- package/dist/facade/exposure-build-up.js.map +1 -0
- package/dist/facade/fast-methods.d.ts +50 -0
- package/dist/facade/fast-methods.js +58 -0
- package/dist/facade/fast-methods.js.map +1 -0
- package/dist/facade/fast-resolution.d.ts +12 -0
- package/dist/facade/fast-resolution.js +18 -0
- package/dist/facade/fast-resolution.js.map +1 -0
- package/dist/facade/generic-lens-capture.d.ts +5 -4
- package/dist/facade/generic-lens-capture.js +5 -4
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/image-plane-enable.d.ts +7 -0
- package/dist/facade/image-plane-enable.js +17 -0
- package/dist/facade/image-plane-enable.js.map +1 -0
- package/dist/facade/image-plane-lattice-data.d.ts +6 -0
- package/dist/facade/image-plane-lattice-data.js +10 -0
- package/dist/facade/image-plane-lattice-data.js.map +1 -0
- package/dist/facade/image-plane-support.d.ts +33 -0
- package/dist/facade/image-plane-support.js +11 -0
- package/dist/facade/image-plane-support.js.map +1 -0
- package/dist/facade/image-plane.d.ts +36 -0
- package/dist/facade/image-plane.js +353 -0
- package/dist/facade/image-plane.js.map +1 -0
- package/dist/facade/mixed-illumination.d.ts +108 -0
- package/dist/facade/mixed-illumination.js +174 -0
- package/dist/facade/mixed-illumination.js.map +1 -0
- package/dist/facade/representative-light-sources.d.ts +72 -0
- package/dist/facade/representative-light-sources.js +124 -0
- package/dist/facade/representative-light-sources.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +129 -4
- package/dist/facade/scene-radiance.js +48 -13
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +88 -19
- package/dist/facade/simulate-capture.js +374 -145
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.d.ts +3 -2
- package/dist/facade/simulate-display-view.js +36 -18
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.d.ts +13 -1
- package/dist/gpu/chart-composite-gpu.js +48 -9
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/chart-radiance-gpu.js +4 -30
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-composite-material-module.d.ts +10 -4
- package/dist/gpu/display-view-composite-material-module.js +39 -13
- package/dist/gpu/display-view-composite-material-module.js.map +1 -1
- package/dist/gpu/display-view-image-material-module.d.ts +86 -0
- package/dist/gpu/display-view-image-material-module.js +339 -0
- package/dist/gpu/display-view-image-material-module.js.map +1 -0
- package/dist/gpu/display-view-image-quality.d.ts +45 -0
- package/dist/gpu/display-view-image-quality.js +380 -0
- package/dist/gpu/display-view-image-quality.js.map +1 -0
- package/dist/gpu/display-view-quality-gpu.d.ts +67 -1
- package/dist/gpu/display-view-quality-gpu.js +136 -205
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.d.ts +51 -3
- package/dist/gpu/display-view-speed-gpu.js +131 -93
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +29 -15
- package/dist/gpu/wgsl-display-view-quality-kernel.js +58 -36
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +21 -6
- package/dist/gpu/wgsl-display-view-speed-kernel.js +46 -11
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
- package/dist/gpu/wgsl-exact-sum.d.ts +20 -0
- package/dist/gpu/wgsl-exact-sum.js +42 -0
- package/dist/gpu/wgsl-exact-sum.js.map +1 -0
- package/dist/index.d.ts +18 -3
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/motion/subject-motion.d.ts +66 -0
- package/dist/motion/subject-motion.js +52 -0
- package/dist/motion/subject-motion.js.map +1 -0
- package/dist/optics/aperture-diameter.d.ts +47 -0
- package/dist/optics/aperture-diameter.js +50 -0
- package/dist/optics/aperture-diameter.js.map +1 -0
- package/dist/optics/detail-limit.d.ts +182 -0
- package/dist/optics/detail-limit.js +336 -0
- package/dist/optics/detail-limit.js.map +1 -0
- package/dist/optics/generic-lens-lateral-color.d.ts +83 -0
- package/dist/optics/generic-lens-lateral-color.js +77 -0
- package/dist/optics/generic-lens-lateral-color.js.map +1 -0
- package/dist/optics/generic-lens-psf.d.ts +18 -2
- package/dist/optics/generic-lens-psf.js +79 -48
- package/dist/optics/generic-lens-psf.js.map +1 -1
- package/dist/optics/lens-psf-profile.d.ts +7 -0
- package/dist/optics/lens-psf-profile.js +2 -1
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.d.ts +13 -0
- package/dist/optics/scene-to-sensor-irradiance.js +7 -0
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/output/crop-to-match-focal-length.d.ts +62 -0
- package/dist/output/crop-to-match-focal-length.js +63 -0
- package/dist/output/crop-to-match-focal-length.js.map +1 -0
- package/dist/output/developed-lens-corrections.d.ts +19 -5
- package/dist/output/developed-lens-corrections.js +30 -11
- package/dist/output/developed-lens-corrections.js.map +1 -1
- package/dist/output/generic-lens-corrections.d.ts +41 -3
- package/dist/output/generic-lens-corrections.js +57 -9
- package/dist/output/generic-lens-corrections.js.map +1 -1
- package/dist/output/lens-corrections.d.ts +12 -2
- package/dist/output/lens-corrections.js +22 -7
- package/dist/output/lens-corrections.js.map +1 -1
- package/dist/output/print-contrast-reference.js +1 -1
- package/dist/output/print-contrast-reference.js.map +1 -1
- package/dist/output/print-plan.d.ts +41 -5
- package/dist/output/print-plan.js +59 -14
- package/dist/output/print-plan.js.map +1 -1
- package/dist/output/print-size-blur-noise.d.ts +110 -0
- package/dist/output/print-size-blur-noise.js +138 -0
- package/dist/output/print-size-blur-noise.js.map +1 -0
- package/dist/sensor/binomial-sample.d.ts +3 -0
- package/dist/sensor/binomial-sample.js +86 -0
- package/dist/sensor/binomial-sample.js.map +1 -0
- package/dist/sensor/eqe-electron-rate.js +1 -7
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +2 -0
- package/dist/sensor/exposure-window.js +2 -2
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/readout-timing.js +2 -23
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.js +1 -6
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.js +1 -7
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sensor-characteristics.d.ts +147 -0
- package/dist/sensor/sensor-characteristics.js +126 -0
- package/dist/sensor/sensor-characteristics.js.map +1 -0
- package/dist/sensor/spatial-sample-reduction.js +1 -5
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spectral-quadrature.js +1 -6
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/temporal-photo-signal.d.ts +3 -0
- package/dist/sensor/temporal-photo-signal.js +5 -2
- package/dist/sensor/temporal-photo-signal.js.map +1 -1
- package/dist/stabilization/system.d.ts +9 -0
- package/dist/stabilization/system.js +5 -6
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +5 -0
- package/docs/API_REFERENCE.md +173 -2
- package/docs/QUICK_START.md +213 -6
- package/docs/USAGE.md +157 -3
- package/docs/api/capture-native-raw-dng.md +6 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-lens-catalogue.md +17 -7
- package/docs/api/equipment-sensor-profile-body.md +64 -0
- package/docs/api/equipment-sensor-profiles.md +86 -0
- package/docs/api/exports.json +357 -2
- package/docs/api/facade-display-view-gpu.md +5 -2
- package/docs/api/facade-exposure-build-up.md +105 -0
- package/docs/api/facade-fast-methods.md +99 -0
- package/docs/api/facade-image-plane-enable.md +16 -0
- package/docs/api/facade-mixed-illumination.md +67 -0
- package/docs/api/facade-representative-light-sources.md +131 -0
- package/docs/api/facade-scene-radiance.md +54 -3
- package/docs/api/facade-simulate-capture.md +60 -15
- package/docs/api/facade-simulate-display-view.md +3 -2
- package/docs/api/motion-subject-motion.md +23 -0
- package/docs/api/optics-aperture-diameter.md +51 -0
- package/docs/api/optics-detail-limit.md +203 -0
- package/docs/api/optics-generic-lens-lateral-color.md +79 -0
- package/docs/api/output-crop-to-match-focal-length.md +67 -0
- package/docs/api/output-developed-lens-corrections.md +10 -1
- package/docs/api/output-generic-lens-corrections.md +40 -2
- package/docs/api/output-lens-corrections.md +11 -1
- package/docs/api/output-print-plan.md +35 -1
- package/docs/api/output-print-size-blur-noise.md +115 -0
- package/docs/api/sensor-sensor-characteristics.md +105 -0
- package/llms.txt +6 -0
- package/package.json +1 -1
|
@@ -66,6 +66,8 @@ export interface DisplayViewResult {
|
|
|
66
66
|
/** #516: as in the capture result. */
|
|
67
67
|
isoControl: "manual" | "automatic"; autoIso?: SimulateCaptureAutoIsoReport };
|
|
68
68
|
scene: SimulateCaptureResult["scene"];
|
|
69
|
+
/** #555, #535: as in the capture result. */
|
|
70
|
+
sensor: SimulateCaptureSensorReport;
|
|
69
71
|
/**
|
|
70
72
|
* Work done: real pixels sampled, real-site expectations evaluated, scene queries, display pixels sampled in full (detail) or with
|
|
71
73
|
* a quarter of the samples per axis (uniform), display pixels whose value includes the AHD low-signal correction, and wall-clock
|
|
@@ -142,7 +144,7 @@ a capture does. `motion.rotation` is a non-zero angular velocity; `sensor.tempor
|
|
|
142
144
|
|
|
143
145
|
```ts
|
|
144
146
|
SIMULATE_CAPTURE_COST_OPTIONS = Object.freeze(["lens.pupilSampling", "lens.projection", "lens.distortion", "lens.vignetting", "lens.psf",
|
|
145
|
-
"lens.diffraction", "lens.defocus", "lens.catalogue", "sensor.antiAliasing", "sensor.pixelAperture.box", "sensor.temporalSampleCount", "motion.rotation", "motion.shutter.rolling", "output.borderHandling.mirror", "output.region",
|
|
147
|
+
"lens.diffraction", "lens.defocus", "lens.catalogue", "sensor.antiAliasing", "sensor.pixelAperture.box", "sensor.temporalSampleCount", "motion.rotation", "motion.subject", "motion.shutter.rolling", "output.borderHandling.mirror", "output.region",
|
|
146
148
|
"output.whiteBalance.auto", "output.demosaic.ahd", "output.highlightMode.reconstruct", "output.colorEncoding.wide-gamut", "output.gamutMapping.perceptual",
|
|
147
149
|
"output.diffractionCorrection", "output.sharpening", "output.lensCorrections", "output.format.jpeg", "output.format.png", "output.format.dng"] as const)
|
|
148
150
|
```
|
|
@@ -173,7 +175,7 @@ the record form with `fast` and is reported in `diagnostics.fast.applied` when i
|
|
|
173
175
|
whether or not it has a fast method yet; one without runs exact and reports `false`.
|
|
174
176
|
|
|
175
177
|
```ts
|
|
176
|
-
SIMULATE_CAPTURE_FAST_OPTIONS = Object.freeze(["lens.diffraction", "lens.catalogue", "sensor.antiAliasing", "sensor.pixelAperture.box", "output.demosaic.ahd"] as const)
|
|
178
|
+
SIMULATE_CAPTURE_FAST_OPTIONS = Object.freeze(["lens.diffraction", "lens.catalogue", "sensor.antiAliasing", "sensor.pixelAperture.box", "output.demosaic.ahd", "motion.subject"] as const)
|
|
177
179
|
```
|
|
178
180
|
|
|
179
181
|
## SIMULATE_CAPTURE_METERING_MODES
|
|
@@ -425,6 +427,12 @@ One part of a whole-frame DNG (#391): a region render's packed RAW and where its
|
|
|
425
427
|
export interface SimulateCaptureDngPart {
|
|
426
428
|
raw: Pick<NativeRawOutput, "codes" | "blackLevels" | "digitalSaturationCodes" | "saturationFlags" | "effectiveSaturationCodes">;
|
|
427
429
|
region: { nativeRect: { x: number; y: number; width: number; height: number } };
|
|
430
|
+
/**
|
|
431
|
+
* 2.20.0: true when a fast method ran for this part (`Object.values(result.diagnostics.fast.applied).includes(true)`). The join
|
|
432
|
+
* refuses such a part unless its own request resolves to fast too (a DNG, JPEG or PNG is exact by default): render the parts with
|
|
433
|
+
* the same `fast` as the join, or with `fast: false`.
|
|
434
|
+
*/
|
|
435
|
+
fast?: boolean;
|
|
428
436
|
}
|
|
429
437
|
```
|
|
430
438
|
|
|
@@ -450,8 +458,10 @@ export type SimulateCaptureFastOption = typeof SIMULATE_CAPTURE_FAST_OPTIONS[num
|
|
|
450
458
|
|
|
451
459
|
```ts
|
|
452
460
|
export interface SimulateCaptureFastReport {
|
|
453
|
-
/**
|
|
461
|
+
/** 2.20.0: the resolved top-level value (`fast`, else the format default), or true when any option's record sets `fast: true`. */
|
|
454
462
|
requested: boolean;
|
|
463
|
+
/** 2.20.0: where the top-level value came from: the request's `fast`, or the format default (see {@link SimulateCaptureOptions.fast}). */
|
|
464
|
+
defaultedFrom: "request" | "format";
|
|
455
465
|
/** Each fast-capable option that ran, in {@link SIMULATE_CAPTURE_FAST_OPTIONS} order: true where its fast method ran. */
|
|
456
466
|
applied: Readonly<Partial<Record<SimulateCaptureFastOption, boolean>>>;
|
|
457
467
|
/** `engine-reference` when every option ran exact; `approximation-with-a-priori-bound` when any fast method ran (the WebGPU execution record's values). */
|
|
@@ -462,6 +472,10 @@ export interface SimulateCaptureFastReport {
|
|
|
462
472
|
## SimulateCaptureLensCatalogueRecord
|
|
463
473
|
|
|
464
474
|
`lens.catalogue` as a record (#568): the lens id as `kind` and the `fast` override (see {@link SimulateCaptureOptions.fast}).
|
|
475
|
+
Fast: the tabulated fast method (#568), and with `lens.defocus` the lens's bokeh without its cat's eye (#567; fast wides and
|
|
476
|
+
normals only), whose field-varying PSF needs a finer fast grid (measured 2.2–3.4× slower); with camera rotation under
|
|
477
|
+
`motion.shutter: "rolling"`, the per-tap PSF points instead of the lattice reading (#588). Exact: the per-site PSF with the
|
|
478
|
+
cat's eye, read on the lattice. Blades and spherical aberration always apply (they cost nothing).
|
|
465
479
|
|
|
466
480
|
```ts
|
|
467
481
|
export interface SimulateCaptureLensCatalogueRecord { kind: string; fast?: boolean }
|
|
@@ -516,6 +530,11 @@ export interface SimulateCaptureMotion {
|
|
|
516
530
|
shutter?: "global" | "rolling";
|
|
517
531
|
/** Rolling shutter only: time from the first to the last line over the simulated frame, in s. Default: the body's declared readout skew. */
|
|
518
532
|
rollingShutterSkewSeconds?: number;
|
|
533
|
+
/**
|
|
534
|
+
* #551: a moving subject: the whole scene, or one rectangle of it over a still background, translating on the scene plane
|
|
535
|
+
* (and optionally rotating about the optical axis) during the exposure. Off by default (a still scene).
|
|
536
|
+
*/
|
|
537
|
+
subject?: SimulateCaptureSubjectMotion;
|
|
519
538
|
}
|
|
520
539
|
```
|
|
521
540
|
|
|
@@ -557,9 +576,9 @@ export interface SimulateCaptureOptions {
|
|
|
557
576
|
* factor and it replaces the tier lens's focal length and f-number range (the transmission is kept). The capture renders the
|
|
558
577
|
* lens's character, all labelled approximations: its PSF (diffraction with the lens's Seidel aberrations, axial and lateral
|
|
559
578
|
* colour, at the resolved f-number and focus) through the environment PSF quadrature, its radial distortion, its vignetting
|
|
560
|
-
* and, for the fisheyes, the equisolid projection. Flare
|
|
579
|
+
* and, for the fisheyes, the equisolid projection. Flare and focus breathing are not rendered. Not combinable
|
|
561
580
|
* with `prime`, `focalLengthMm`, `projection`, `distortion`, `vignetting`, `psf`, `diffraction` or `pupilSampling` (the
|
|
562
|
-
* lens sets them); `defocus` convolves the
|
|
581
|
+
* lens sets them); `defocus` convolves the lens's bokeh kernel (#567) into its PSF. The display view renders it with the PSF taken per field zone (#569; docs/DISPLAY_VIEW.md). Default off.
|
|
563
582
|
* #568: the record form `{ kind: <lens id>, fast }` overrides the top-level `fast` flag for this option; the fast method
|
|
564
583
|
* blends the PSF between exactly resolved kernels on a field grid and tabulates each site's expected signal
|
|
565
584
|
* (docs/LENS_CATALOGUE.md, "Fast method").
|
|
@@ -659,9 +678,10 @@ export interface SimulateCaptureOptions {
|
|
|
659
678
|
/**
|
|
660
679
|
* Required: an engine chart (for example `{ preset: "uniform" }`, an 18 % grey card), a declared `material-layers` scene (#491:
|
|
661
680
|
* a chart under shape-mask layers, as `resolveChartMaterialLayers` takes it; the capture is that of its `callerScene`, byte for
|
|
662
|
-
* byte, and the display view can render it on the GPU),
|
|
681
|
+
* byte, and the display view can render it on the GPU), a caller reflectance, radiance or material function, or (2.21, #581) an
|
|
682
|
+
* `image-plane` scene: a photo as a flat print (docs/IMAGE_PLANE.md).
|
|
663
683
|
*/
|
|
664
|
-
scene: ChartScene | ChartMaterialLayerScene | CallerReflectanceScene | CallerRadianceScene | CallerMaterialScene;
|
|
684
|
+
scene: ChartScene | ChartMaterialLayerScene | CallerReflectanceScene | CallerRadianceScene | CallerMaterialScene | ImagePlaneScene;
|
|
665
685
|
/** Distance from the camera to the scene plane in metres. Default 5. */
|
|
666
686
|
subjectDistanceM?: number;
|
|
667
687
|
/**
|
|
@@ -676,6 +696,12 @@ export interface SimulateCaptureOptions {
|
|
|
676
696
|
illuminant?: CaptureIlluminant;
|
|
677
697
|
/** Illuminance on the scene plane, lux. Default about 21 481 lux (see `SIMULATE_CAPTURE_DEFAULT_ILLUMINANCE_LUX` and the assumptions). */
|
|
678
698
|
illuminanceLux?: number;
|
|
699
|
+
/**
|
|
700
|
+
* 2.22 (#550), opt-in mixed lighting: two or more sources blended across the chart (docs/MIXED_ILLUMINATION.md), instead of
|
|
701
|
+
* `illuminant` and `illuminanceLux`. The frame center's light sets the grey-card meter and the standard-exposure figures, and
|
|
702
|
+
* its strongest source the "scene-illuminant" white balance; both are reported in `assumptions`.
|
|
703
|
+
*/
|
|
704
|
+
illumination?: MixedIllumination;
|
|
679
705
|
output?: {
|
|
680
706
|
/** Output pixels; the native sensor raster adds a one-site demosaic border on each side. Defaults 64 × 64. */
|
|
681
707
|
width?: number;
|
|
@@ -700,7 +726,7 @@ export interface SimulateCaptureOptions {
|
|
|
700
726
|
exposureCompensationStops?: number;
|
|
701
727
|
/** Default "scene-illuminant". */
|
|
702
728
|
whiteBalance?: SimulateCaptureWhiteBalance;
|
|
703
|
-
/** JPEG constant quantization step 1-255 (not a manufacturer 'quality'). Default 2. */
|
|
729
|
+
/** JPEG constant quantization step 1-255 (not a manufacturer 'quality'). Default 1 (2.20.0; 2 before), the full-quality export. */
|
|
704
730
|
jpegQuantizationStep?: number;
|
|
705
731
|
/** PNG only. Default "srgb". */
|
|
706
732
|
colorEncoding?: SimulateCaptureColorEncoding;
|
|
@@ -715,8 +741,13 @@ export interface SimulateCaptureOptions {
|
|
|
715
741
|
demosaic?: SimulateCaptureDemosaic | SimulateCaptureDemosaicRecord;
|
|
716
742
|
/** Default "margin". */
|
|
717
743
|
borderHandling?: SimulateCaptureBorderHandling;
|
|
718
|
-
/**
|
|
719
|
-
|
|
744
|
+
/**
|
|
745
|
+
* DNG only: optional capture-event time (YYYY-MM-DDTHH:mm:ss.sssZ); without it no date tags are written. Opt-in (#587), with
|
|
746
|
+
* `lens.catalogue`: `lensCorrectionOpcodes` writes the selected corrections of {@link SimulateCaptureLensCorrections} into the DNG as
|
|
747
|
+
* optional DNG opcodes in OpcodeList3 (FixVignetteRadial, WarpRectilinear with the zoom-to-fill; docs/NATIVE_RAW_AND_PRINT.md), for RAW editors
|
|
748
|
+
* that apply them; the RAW codes are unchanged. Whole frame only (no `region`). All off (or omitted): the same DNG bytes as without it.
|
|
749
|
+
*/
|
|
750
|
+
dng?: { capturedAtUtc?: string; lensCorrectionOpcodes?: SimulateCaptureLensCorrections };
|
|
720
751
|
/**
|
|
721
752
|
* Opt-in (2.4) text written into the file for formats "jpeg", "png" and "dng": the caller's description,
|
|
722
753
|
* software, copyright and comment, unchanged (JPEG XMP + COM, PNG tEXt/iTXt, DNG TIFF tags + XMP; see the
|
|
@@ -768,7 +799,15 @@ export interface SimulateCaptureOptions {
|
|
|
768
799
|
};
|
|
769
800
|
/** Camera motion and shutter type. Default: still camera, global electronic shutter. */
|
|
770
801
|
motion?: SimulateCaptureMotion;
|
|
771
|
-
sensor
|
|
802
|
+
/** #555: plus the sensor characteristics ({@link SimulateCaptureSensorCharacteristics}), each off by default. */
|
|
803
|
+
sensor?: SimulateCaptureSensorCharacteristics & {
|
|
804
|
+
/**
|
|
805
|
+
* #554: a sensor profile record (`SENSOR_PROFILES`, or `resolveSensorProfile(id)`), checked strictly. It replaces the body's ISO range, readout regimes
|
|
806
|
+
* (full well, read noise of each conversion gain, the dual-gain switch, high-gain storage, ADC bit depth), readout time and
|
|
807
|
+
* fixed-pattern noise, and sets the default pixel pitch and peak QE; explicit fields here still override it one at a time.
|
|
808
|
+
* Default: none (the body's own sensor). See docs/SENSOR_PROFILES.md.
|
|
809
|
+
*/
|
|
810
|
+
profile?: SensorProfile;
|
|
772
811
|
/**
|
|
773
812
|
* Pixel pitch in micrometres, 0.5–1000. Default 6. The simulated sensor is output width × pitch wide. 2.5: above 100 µm the
|
|
774
813
|
* capture is a downsized view of a whole frame (for example 36 mm / 48 pixels = 750 µm), recorded in the assumption
|
|
@@ -795,10 +834,14 @@ export interface SimulateCaptureOptions {
|
|
|
795
834
|
pixelAperture?: SimulateCapturePixelAperture;
|
|
796
835
|
};
|
|
797
836
|
/**
|
|
798
|
-
* Exact or fast (#395). `false
|
|
799
|
-
*
|
|
800
|
-
*
|
|
801
|
-
*
|
|
837
|
+
* Exact or fast (#395). `false`: every option runs its exact method, the engine reference. `true`: each option listed in
|
|
838
|
+
* {@link SIMULATE_CAPTURE_FAST_OPTIONS} runs its fast method where it has one, a measured, bounded approximation of the exact
|
|
839
|
+
* one; an option without a fast method runs exact. An option's own record `fast` overrides this for that option only.
|
|
840
|
+
* Omitted (2.20.0), the format decides: fast for `output.format` "srgb-8" and "srgb-16" and for the display view, exact for
|
|
841
|
+
* "dng", "jpeg" and "png" (exports) and for `simulateIdealReference`. `diagnostics.fast` reports the resolved value, where it
|
|
842
|
+
* came from and what ran. Fast methods: `lens.catalogue` (#568, #567) and `lens.diffraction` under rolling-shutter rotation
|
|
843
|
+
* (#565); in the display view also its catalogue PSF zones, its sampling of uniform pixels and its AHD low-signal correction
|
|
844
|
+
* (docs/DISPLAY_VIEW.md). The exact result also carries `result.sensor.midGrey` (#535). Calculators should pass `fast: false`.
|
|
802
845
|
*/
|
|
803
846
|
fast?: boolean;
|
|
804
847
|
/** Aborting cancels the running task; the promise rejects with a domain error and returns no partial image. */
|
|
@@ -994,6 +1037,8 @@ export interface SimulateCaptureResult {
|
|
|
994
1037
|
limitations: readonly string[];
|
|
995
1038
|
};
|
|
996
1039
|
assumptions: readonly SimulateCaptureAssumption[];
|
|
1040
|
+
/** #555, #535: the sensor characteristics used, the calculated dynamic range and (when the request resolves to exact) the mid-grey noise figure. */
|
|
1041
|
+
sensor: SimulateCaptureSensorReport;
|
|
997
1042
|
}
|
|
998
1043
|
```
|
|
999
1044
|
|
|
@@ -65,9 +65,10 @@ responses through the environment chain, the diffraction kernels, readout moment
|
|
|
65
65
|
about 0.3–1.3 s per call on a 24 MP request; a region costs only its own pixels. Errors in the request are raised here;
|
|
66
66
|
errors in the view by `render`.
|
|
67
67
|
|
|
68
|
-
2.11 (#481): `prepareOptions.gpu` chooses the renderer: `"off"`
|
|
68
|
+
2.11 (#481): `prepareOptions.gpu` chooses the renderer: `"off"` is the CPU reference, today's bytes; `"auto"` renders
|
|
69
69
|
on WebGPU when a conforming device is available and the request is supported, else on the CPU, labelled; `"require"` fails
|
|
70
|
-
instead of falling back (`ImageKernelExecutionError`, acquisition failures here, later ones from `render`).
|
|
70
|
+
instead of falling back (`ImageKernelExecutionError`, acquisition failures here, later ones from `render`). 2.20.0: the default is
|
|
71
|
+
`"auto"` when the request resolves to fast (the view's default) and `"off"` with `fast: false`. `gpuDevice` is a
|
|
71
72
|
WebGPU entry point or an `ImageKernelAccelerator` whose device the view shares; without it the engine acquires one device
|
|
72
73
|
for the prepared view (the request's `signal` aborts the acquisition) and `dispose()` releases it. The realm's
|
|
73
74
|
`setWebGpuEnabled(false)` vetoes both GPU modes (`webgpu-disabled`). See docs/DISPLAY_VIEW.md, "Rendering on the GPU".
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# motion/subject-motion.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
|
+
## SimulateCaptureSubjectMotion
|
|
6
|
+
|
|
7
|
+
`motion.subject` of `simulateCapture`: a moving subject on the scene plane (#551).
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
export interface SimulateCaptureSubjectMotion {
|
|
11
|
+
/** Velocity on the scene plane, m/s: +x right, +y up as seen from the camera. Missing components are 0. */
|
|
12
|
+
velocityMPerSec?: { x?: number; y?: number };
|
|
13
|
+
/** Rotation about the optical axis direction, rad/s, counter-clockwise as seen from the camera (+x toward +y). Default 0. */
|
|
14
|
+
angularVelocityRadPerSec?: number;
|
|
15
|
+
/**
|
|
16
|
+
* The moving part: a rectangle on the scene plane at rest (at the first opening reference), its centre and size in metres
|
|
17
|
+
* (+x right, +y up from the optical axis). Omitted: the whole scene moves.
|
|
18
|
+
*/
|
|
19
|
+
region?: { centerXM: number; centerYM: number; widthM: number; heightM: number };
|
|
20
|
+
/** Exact or fast (2.20.0 convention): fast takes fewer temporal midpoints when the subject's streak is short (see the docs). */
|
|
21
|
+
fast?: boolean;
|
|
22
|
+
}
|
|
23
|
+
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# optics/aperture-diameter.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
|
+
## ApertureDiameter
|
|
6
|
+
|
|
7
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
export interface ApertureDiameter {
|
|
11
|
+
/** Focal length supplied by the caller, in millimetres. */
|
|
12
|
+
focalLengthMm: number;
|
|
13
|
+
/** f-number supplied by the caller. */
|
|
14
|
+
fNumber: number;
|
|
15
|
+
/** Entrance-pupil diameter D = focalLengthMm / fNumber, in millimetres. */
|
|
16
|
+
entrancePupilDiameterMm: number;
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## calculateApertureDiameter
|
|
21
|
+
|
|
22
|
+
Entrance-pupil (aperture) diameter in millimetres: focal length ÷ f-number.
|
|
23
|
+
|
|
24
|
+
Exact by the definition of the f-number for an ideal lens focused at infinity. It is the
|
|
25
|
+
entrance pupil (the aperture stop as seen from the front), not the diaphragm's physical
|
|
26
|
+
opening. Close focus (working f-number N·(1 + m/P) with pupil magnification P) and focal-length
|
|
27
|
+
changes while focusing are not modelled.
|
|
28
|
+
|
|
29
|
+
Example: 50 mm at f/2 gives 25 mm; at f/4, 12.5 mm (half the diameter, a quarter of the area:
|
|
30
|
+
two stops).
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
export function calculateApertureDiameter(
|
|
34
|
+
input: CalculateApertureDiameterInput
|
|
35
|
+
): CalculationResult<ApertureDiameter>;
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
39
|
+
|
|
40
|
+
## CalculateApertureDiameterInput
|
|
41
|
+
|
|
42
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
export interface CalculateApertureDiameterInput {
|
|
46
|
+
/** Focal length of the lens in millimetres (the physical focal length, not a 35 mm equivalent). */
|
|
47
|
+
focalLengthMm: number;
|
|
48
|
+
/** f-number set on the lens (N = focal length / entrance-pupil diameter). */
|
|
49
|
+
fNumber: number;
|
|
50
|
+
}
|
|
51
|
+
```
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# optics/detail-limit.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
|
+
## calculateDetailLimit
|
|
6
|
+
|
|
7
|
+
Which limits detail for given settings: the lens (diffraction at this f-number, aberrations, defocus) or the sensor's pixel
|
|
8
|
+
pitch. Returns the optics' resolution (MTF50 and the diffraction cut-off, cycles/mm), the sampling's (Nyquist frequency
|
|
9
|
+
and, with a Bayer filter, the red and blue sites'), the system MTF50 (optics × pixel aperture), the f-number from which
|
|
10
|
+
diffraction limits on this sensor, and which one limits.
|
|
11
|
+
|
|
12
|
+
The sensor limits when the optics still pass 50 % contrast at the Nyquist frequency 1/(2p); otherwise the lens does,
|
|
13
|
+
through diffraction when its wavefront error is within the Maréchal criterion (RMS ≤ λ/14), else through aberrations or
|
|
14
|
+
defocus. The optics MTF is the exact scalar OTF of the stated wavefront at one wavelength; the decision rule and the
|
|
15
|
+
catalogue lenses' wavefronts are approximations.
|
|
16
|
+
|
|
17
|
+
Example: an ideal 50 mm lens at f/22 on a 36 × 24 mm, 6000-pixel-wide sensor (6 µm) is limited by diffraction (optics
|
|
18
|
+
MTF50 ≈ 33 cycles/mm against a Nyquist frequency of ≈ 83); at f/4 the pixel pitch limits.
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
export function calculateDetailLimit(input: CalculateDetailLimitInput): CalculationResult<DetailLimit>;
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
25
|
+
|
|
26
|
+
## CalculateDetailLimitInput
|
|
27
|
+
|
|
28
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
export interface CalculateDetailLimitInput {
|
|
32
|
+
/** Active imaging area and horizontal pixel count; pitch = widthMm / pixelWidth. */
|
|
33
|
+
sensor: {
|
|
34
|
+
widthMm: number;
|
|
35
|
+
heightMm: number;
|
|
36
|
+
pixelWidth: number;
|
|
37
|
+
/** Default `"bayer"`. `"none"`: every site records full detail (a monochrome sensor). */
|
|
38
|
+
colorFilterArray?: "bayer" | "none";
|
|
39
|
+
};
|
|
40
|
+
lens: DetailLimitIdealLens | DetailLimitCatalogueLens;
|
|
41
|
+
/** f-number set on the lens. */
|
|
42
|
+
fNumber: number;
|
|
43
|
+
/**
|
|
44
|
+
* Focus and subject distances from the lens in meters. Omitted: focused at infinity, subject in focus. `subjectDistanceM`
|
|
45
|
+
* omitted: the subject is at the focus distance.
|
|
46
|
+
*/
|
|
47
|
+
focus?: { focusDistanceM: number; subjectDistanceM?: number };
|
|
48
|
+
/** Field height as a fraction of the half-diagonal, 0 (center, default) to 1 (corner). Only aberrations depend on it. */
|
|
49
|
+
fieldPosition?: number;
|
|
50
|
+
/** Wavelength in nanometres, 380–780. Default 550. */
|
|
51
|
+
wavelengthNm?: number;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## DETAIL_LIMIT_LIMITS
|
|
56
|
+
|
|
57
|
+
Limits of `calculateDetailLimit`: the wavelength range and the largest wavefront (sum of the magnitudes of its terms, in
|
|
58
|
+
waves) whose transfer function is integrated. Beyond it the blur is geometric and the quadrature would grow without
|
|
59
|
+
bound; use `calculateDefocusCircle` for such a blur.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
DETAIL_LIMIT_LIMITS = Object.freeze({ minimumWavelengthNm: 380, maximumWavelengthNm: 780, maximumWavefrontWaves: 64 })
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## DetailLimit
|
|
66
|
+
|
|
67
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
export interface DetailLimit {
|
|
71
|
+
/** The lens or the sensor. */
|
|
72
|
+
limitedBy: DetailLimitedBy;
|
|
73
|
+
/** Diffraction, aberrations or defocus (the lens), or the pixel pitch (the sensor). */
|
|
74
|
+
limitingFactor: DetailLimitingFactor;
|
|
75
|
+
/** Optics MTF50 / Nyquist frequency: at least 1 when the sensor limits. */
|
|
76
|
+
opticsToNyquistRatio: number;
|
|
77
|
+
fNumber: number;
|
|
78
|
+
wavelengthNm: number;
|
|
79
|
+
/** Physical focal length used (the catalogue lens's on this sensor), mm. */
|
|
80
|
+
focalLengthMm: number;
|
|
81
|
+
fieldPosition: number;
|
|
82
|
+
optics: DetailLimitOptics;
|
|
83
|
+
sampling: DetailLimitSampling;
|
|
84
|
+
system: DetailLimitSystem;
|
|
85
|
+
/**
|
|
86
|
+
* The f-number at which an aberration-free lens in focus has its MTF50 at the Nyquist frequency (2·p·0.40397/λ at
|
|
87
|
+
* infinity focus): from it on, diffraction limits detail on this sensor whatever the lens.
|
|
88
|
+
*/
|
|
89
|
+
diffractionLimitedFNumber: number;
|
|
90
|
+
basis: Readonly<Record<"optics" | "sampling" | "system" | "limitedBy", DetailLimitBasis>>;
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## DetailLimitBasis
|
|
95
|
+
|
|
96
|
+
Whether a quantity is exact under its stated conditions or an approximation.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
export interface DetailLimitBasis { kind: "exact" | "approximation"; statement: string }
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## DetailLimitCatalogueLens
|
|
103
|
+
|
|
104
|
+
A generic catalogue lens (`GENERIC_LENS_IDS`), resolved for the sensor as `resolveGenericLens` does.
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
export interface DetailLimitCatalogueLens {
|
|
108
|
+
kind: "catalogue";
|
|
109
|
+
lensId: string;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## DetailLimitedBy
|
|
114
|
+
|
|
115
|
+
Which component limits detail.
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
export type DetailLimitedBy = "lens" | "sensor";
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## DetailLimitIdealLens
|
|
122
|
+
|
|
123
|
+
A lens with no aberrations (diffraction only).
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
export interface DetailLimitIdealLens {
|
|
127
|
+
kind: "ideal";
|
|
128
|
+
/** Physical focal length in millimeters (for the working f-number and the defocus of a subject off the focus distance). */
|
|
129
|
+
focalLengthMm: number;
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## DetailLimitingFactor
|
|
134
|
+
|
|
135
|
+
What limits it: the lens's diffraction, aberrations or defocus, or the sensor's pixel pitch.
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
export type DetailLimitingFactor = "diffraction" | "aberrations" | "defocus" | "pixel-pitch";
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## DetailLimitOptics
|
|
142
|
+
|
|
143
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
export interface DetailLimitOptics {
|
|
147
|
+
/** Working f-number N_w = N·v/f (thin-lens image distance v; N at infinity focus). */
|
|
148
|
+
workingFNumber: number;
|
|
149
|
+
/** Diffraction cut-off 1/(λ·N_w) in cycles/mm: no optics passes detail beyond it. */
|
|
150
|
+
cutoffCyclesPerMm: number;
|
|
151
|
+
/** Frequency where the optics' MTF falls to 0.5, the lower of the two directions, cycles/mm. */
|
|
152
|
+
mtf50CyclesPerMm: number;
|
|
153
|
+
/** MTF50 for detail along the radius from the image center (tangential), cycles/mm. */
|
|
154
|
+
tangentialMtf50CyclesPerMm: number;
|
|
155
|
+
/** MTF50 for detail across the radius (sagittal), cycles/mm. Equal to the tangential value at the center. */
|
|
156
|
+
sagittalMtf50CyclesPerMm: number;
|
|
157
|
+
/** MTF50 of an aberration-free lens in focus at the same working f-number (0.40397·cut-off), cycles/mm. */
|
|
158
|
+
diffractionMtf50CyclesPerMm: number;
|
|
159
|
+
/** Optics MTF at the sensor's Nyquist frequency (lower direction). */
|
|
160
|
+
mtfAtNyquist: number;
|
|
161
|
+
/** RMS wavefront error in waves at the wavelength: of the aberrations, of the defocus, and of both together. */
|
|
162
|
+
rmsWavefrontErrorWaves: { aberrations: number; defocus: number; total: number };
|
|
163
|
+
/** Whether the total RMS wavefront error is within the Maréchal criterion λ/14. */
|
|
164
|
+
withinMarechalCriterion: boolean;
|
|
165
|
+
/** Geometric blur-circle diameter of the defocus on the sensor, mm (0 in focus). */
|
|
166
|
+
defocusBlurDiameterMm: number;
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## DetailLimitSampling
|
|
171
|
+
|
|
172
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
export interface DetailLimitSampling {
|
|
176
|
+
colorFilterArray: "bayer" | "none";
|
|
177
|
+
/** Pixel pitch in micrometres: widthMm / pixelWidth. */
|
|
178
|
+
pixelPitchMicrometers: number;
|
|
179
|
+
/** 1/(2p), cycles/mm: the finest detail the pixel grid records without aliasing (Bayer green sites too, along rows and columns). */
|
|
180
|
+
nyquistCyclesPerMm: number;
|
|
181
|
+
/** Bayer only: 1/(4p), the Nyquist frequency of the red and blue sites. Null without a color filter array. */
|
|
182
|
+
redBlueNyquistCyclesPerMm: number | null;
|
|
183
|
+
/** Pixel aperture MTF at the Nyquist frequency: sinc(1/2) = 2/π. */
|
|
184
|
+
pixelApertureMtfAtNyquist: number;
|
|
185
|
+
/** Frequency where the pixel aperture MTF falls to 0.5 (0.60335/p), cycles/mm: beyond the Nyquist frequency. */
|
|
186
|
+
pixelApertureMtf50CyclesPerMm: number;
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## DetailLimitSystem
|
|
191
|
+
|
|
192
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
export interface DetailLimitSystem {
|
|
196
|
+
/** MTF50 of optics × pixel aperture (lower direction), cycles/mm. Detail above the Nyquist frequency aliases. */
|
|
197
|
+
mtf50CyclesPerMm: number;
|
|
198
|
+
/** The same in line pairs per picture height (cycles/mm × heightMm). */
|
|
199
|
+
mtf50LinePairsPerPictureHeight: number;
|
|
200
|
+
/** System MTF at the Nyquist frequency (lower direction). */
|
|
201
|
+
mtfAtNyquist: number;
|
|
202
|
+
}
|
|
203
|
+
```
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# optics/generic-lens-lateral-color.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
|
+
## calculateLateralColorFringe
|
|
6
|
+
|
|
7
|
+
The red–blue image displacement of a catalogue lens at a field position on a sensor, in micrometres and pixels, from the
|
|
8
|
+
lens's own lateral-colour model Δr(λ) = L·R·H·D(λ) at the lens corrections' channel wavelengths (610 and 465 nm), or at the
|
|
9
|
+
given `channelDispersion`. Exact for the model (no fast mode); an approximation of a generic lens, not a measured product.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
export function calculateLateralColorFringe(input: CalculateLateralColorFringeInput): CalculationResult<LateralColorFringe>;
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
16
|
+
|
|
17
|
+
## CalculateLateralColorFringeInput
|
|
18
|
+
|
|
19
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
export interface CalculateLateralColorFringeInput {
|
|
23
|
+
/** A catalogue id (`GENERIC_LENS_IDS`). */
|
|
24
|
+
lensId: string;
|
|
25
|
+
/** The sensor's active capture area, mm (the lens is scaled to it as in `resolveGenericLens`). */
|
|
26
|
+
activeImagingArea: { widthMm: number; heightMm: number };
|
|
27
|
+
/** The sensor's pixel pitch, µm. */
|
|
28
|
+
pixelPitchMicrometers: number;
|
|
29
|
+
/**
|
|
30
|
+
* The field position as fractions of the frame's half-width (x, +right) and half-height (y, +up) from the optical axis, each
|
|
31
|
+
* in [−1, 1]. Default `{ x: 1, y: 1 }`: the top-right corner.
|
|
32
|
+
*/
|
|
33
|
+
fieldPosition?: { x: number; y: number };
|
|
34
|
+
/**
|
|
35
|
+
* 2.21.0: each channel's effective dispersion (`calculateChannelEffectiveDispersion` for the camera's channels and the light;
|
|
36
|
+
* only `red` and `blue` are read). Default: D at the single wavelengths 610 and 465 nm.
|
|
37
|
+
*/
|
|
38
|
+
channelDispersion?: ChannelDispersion;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## LateralColorDisplacement
|
|
43
|
+
|
|
44
|
+
A signed displacement of the blue image from the red one: radial (positive: blue farther from the axis) and its x and y parts.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
export interface LateralColorDisplacement {
|
|
48
|
+
radial: number;
|
|
49
|
+
x: number;
|
|
50
|
+
y: number;
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## LateralColorFringe
|
|
55
|
+
|
|
56
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
export interface LateralColorFringe {
|
|
60
|
+
lensId: string;
|
|
61
|
+
/** The image-plane point, mm from the optical axis (+x right, +y up). */
|
|
62
|
+
imagePointMm: { x: number; y: number };
|
|
63
|
+
/** Field height H: the point's distance from the axis as a fraction of the half-diagonal (1 at the corner). */
|
|
64
|
+
fieldHeight: number;
|
|
65
|
+
/** The channel wavelengths the displacement is taken at, nm; null with a given `channelDispersion`. */
|
|
66
|
+
channelWavelengthsNm: { red: number; blue: number } | null;
|
|
67
|
+
/** The red and blue dispersions D used (normalized: 0 at the d line, F minus C = 1). */
|
|
68
|
+
channelDispersion: { red: number; blue: number };
|
|
69
|
+
/** Blue-minus-red image displacement, µm. */
|
|
70
|
+
blueMinusRedMicrometers: LateralColorDisplacement;
|
|
71
|
+
/** The same in pixels of the given pitch. */
|
|
72
|
+
blueMinusRedPixels: LateralColorDisplacement;
|
|
73
|
+
/** The fringe width: |radial| displacement, µm and pixels. */
|
|
74
|
+
fringeWidthMicrometers: number;
|
|
75
|
+
fringeWidthPixels: number;
|
|
76
|
+
/** The lens's own F-to-C (486 to 656 nm) displacement at this point, L·R·H, µm. */
|
|
77
|
+
fToCMicrometers: number;
|
|
78
|
+
}
|
|
79
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# output/crop-to-match-focal-length.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
|
+
## calculateCropToMatchFocalLength
|
|
6
|
+
|
|
7
|
+
The centred crop that makes an image from a shorter lens match a longer lens's framing from the
|
|
8
|
+
same position: crop factor target ÷ focal length, and the pixels and megapixels left.
|
|
9
|
+
|
|
10
|
+
Exact for ideal rectilinear lenses focused at infinity, to whole pixels (the crop is
|
|
11
|
+
`calculateCenteredCrop`'s, which keeps the aspect ratio). At close focus the matching factor is
|
|
12
|
+
larger, F·(d − f)/(f·(d − F)) at object distance d (thin lens); that, distortion and focus
|
|
13
|
+
breathing are not modelled. The crop has the longer lens's framing and perspective but fewer
|
|
14
|
+
pixels: it records no more detail than the cropped part of the shorter lens's image.
|
|
15
|
+
|
|
16
|
+
Example: a 24 MP (6000 × 4000) image at 50 mm cropped to match 100 mm: factor 2, 3000 × 2000,
|
|
17
|
+
6 MP.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
export function calculateCropToMatchFocalLength(
|
|
21
|
+
input: CalculateCropToMatchFocalLengthInput
|
|
22
|
+
): CalculationResult<CropToMatchFocalLength>;
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
26
|
+
|
|
27
|
+
## CalculateCropToMatchFocalLengthInput
|
|
28
|
+
|
|
29
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
export interface CalculateCropToMatchFocalLengthInput {
|
|
33
|
+
/** Focal length the image was taken with, in millimetres. */
|
|
34
|
+
focalLengthMm: number;
|
|
35
|
+
/** Longer focal length whose framing the crop should match, in millimetres. At least `focalLengthMm`. */
|
|
36
|
+
targetFocalLengthMm: number;
|
|
37
|
+
/** Image width in pixels (for example the sensor's output width). */
|
|
38
|
+
pixelWidth: number;
|
|
39
|
+
/** Image height in pixels. */
|
|
40
|
+
pixelHeight: number;
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## CropToMatchFocalLength
|
|
45
|
+
|
|
46
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
export interface CropToMatchFocalLength {
|
|
50
|
+
/** Focal length supplied by the caller, in millimetres. */
|
|
51
|
+
focalLengthMm: number;
|
|
52
|
+
/** Target focal length supplied by the caller, in millimetres. */
|
|
53
|
+
targetFocalLengthMm: number;
|
|
54
|
+
/** Linear crop factor targetFocalLengthMm / focalLengthMm (1 means no crop). */
|
|
55
|
+
cropFactor: number;
|
|
56
|
+
/** Width left after the centred crop, in pixels (as `calculateCenteredCrop`). */
|
|
57
|
+
pixelWidth: number;
|
|
58
|
+
/** Height left after the centred crop, in pixels. */
|
|
59
|
+
pixelHeight: number;
|
|
60
|
+
/** Pixels left, in millions. */
|
|
61
|
+
megapixels: number;
|
|
62
|
+
/** Megapixels of the uncropped image. */
|
|
63
|
+
sourceMegapixels: number;
|
|
64
|
+
/** Fraction of the original pixel area retained, about 1 / cropFactor². */
|
|
65
|
+
retainedAreaFraction: number;
|
|
66
|
+
}
|
|
67
|
+
```
|
|
@@ -2,10 +2,19 @@
|
|
|
2
2
|
|
|
3
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
4
|
|
|
5
|
+
## ChannelDispersion
|
|
6
|
+
|
|
7
|
+
A normalized dispersion per channel (`genericLensDispersion` units: 0 at the d line, F minus C = 1).
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
export type ChannelDispersion = Readonly<Record<LensCorrectionChannel, number>>;
|
|
11
|
+
```
|
|
12
|
+
|
|
5
13
|
## GENERIC_LENS_CORRECTION_CHANNEL_WAVELENGTHS_NM
|
|
6
14
|
|
|
7
15
|
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.
|
|
16
|
+
a camera's channel responses peak, not a measured camera. The default of `createGenericLensCorrectionProfile` without a
|
|
17
|
+
`channelDispersion`; `simulateCapture`'s `output.lensCorrections` uses the capture's own channels instead (#589).
|
|
9
18
|
|
|
10
19
|
```ts
|
|
11
20
|
GENERIC_LENS_CORRECTION_CHANNEL_WAVELENGTHS_NM: Readonly<Record<LensCorrectionChannel, number>> = Object.freeze({ red: 610, green: 540, blue: 465 })
|