@photivra/engine 2.12.0 → 2.14.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 +144 -1
- package/CITATION.cff +1 -1
- package/README.md +7 -7
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +3 -0
- package/dist/camera/lens-projection.js +2 -1
- package/dist/camera/lens-projection.js.map +1 -1
- package/dist/capture/dng-import.js +1 -1
- package/dist/capture/dng-import.js.map +1 -1
- package/dist/capture/export-jpeg.d.ts +1 -1
- package/dist/capture/export-jpeg.js +6 -4
- package/dist/capture/export-jpeg.js.map +1 -1
- package/dist/capture/host-yield-cadence.js +1 -1
- package/dist/capture/host-yield-cadence.js.map +1 -1
- package/dist/capture/native-environment-optical-stage.js +1 -1
- package/dist/capture/native-environment-optical-stage.js.map +1 -1
- package/dist/capture/native-raw.js +1 -1
- package/dist/capture/native-raw.js.map +1 -1
- package/dist/capture/packed-sensor-raw.js +3 -3
- package/dist/capture/packed-sensor-raw.js.map +1 -1
- package/dist/capture/sensor-raw-producer.js +1 -1
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/color/capture-color.js +3 -3
- package/dist/color/capture-color.js.map +1 -1
- package/dist/color/chromatic-adaptation.js +2 -2
- package/dist/color/chromatic-adaptation.js.map +1 -1
- package/dist/color/color-matching-functions.js +1 -1
- package/dist/color/color-matching-functions.js.map +1 -1
- package/dist/color/colorimetry-math.js +2 -2
- package/dist/color/colorimetry-math.js.map +1 -1
- package/dist/color/illuminants.js +3 -3
- package/dist/color/illuminants.js.map +1 -1
- package/dist/color/rgb-color-spaces.js +1 -1
- package/dist/color/rgb-color-spaces.js.map +1 -1
- package/dist/color/sensor-color-development.js +1 -1
- package/dist/color/sensor-color-development.js.map +1 -1
- package/dist/core/record-validation.js +3 -3
- package/dist/core/record-validation.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-prime-lenses.js +3 -3
- package/dist/equipment/generic-prime-lenses.js.map +1 -1
- package/dist/equipment/generic-tier-assets.d.ts +23 -1
- package/dist/equipment/generic-tier-assets.js +58 -30
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/generic-tier-presets.d.ts +6 -3
- package/dist/equipment/generic-tier-presets.js +26 -13
- package/dist/equipment/generic-tier-presets.js.map +1 -1
- package/dist/exposure/auto-iso-slowest-shutter.d.ts +120 -0
- package/dist/exposure/auto-iso-slowest-shutter.js +217 -0
- package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -0
- package/dist/exposure/exposure-mode-resolver.d.ts +57 -1
- package/dist/exposure/exposure-mode-resolver.js +238 -33
- package/dist/exposure/exposure-mode-resolver.js.map +1 -1
- package/dist/exposure/flash-ttl.js +1 -1
- package/dist/exposure/flash-ttl.js.map +1 -1
- package/dist/exposure/flash.js +1 -1
- package/dist/exposure/flash.js.map +1 -1
- package/dist/facade/chart-material-layers.js +2 -2
- package/dist/facade/chart-material-layers.js.map +1 -1
- package/dist/facade/chart-radiance-batch.js +1 -1
- package/dist/facade/chart-radiance-batch.js.map +1 -1
- package/dist/facade/chart-scenes.d.ts +45 -8
- package/dist/facade/chart-scenes.js +101 -44
- package/dist/facade/chart-scenes.js.map +1 -1
- package/dist/facade/color-patches.d.ts +129 -0
- package/dist/facade/color-patches.js +209 -0
- package/dist/facade/color-patches.js.map +1 -0
- package/dist/facade/diffraction-provider.js +12 -13
- package/dist/facade/diffraction-provider.js.map +1 -1
- package/dist/facade/display-view-gpu.js +1 -1
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view.d.ts +27 -0
- package/dist/facade/display-view.js +234 -65
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/scene-radiance.js +2 -2
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +139 -12
- package/dist/facade/simulate-capture.js +209 -36
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.js +2 -2
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.js +2 -2
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/display-view-composite-material-module.js +1 -1
- package/dist/gpu/display-view-composite-material-module.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +2 -1
- package/dist/gpu/display-view-quality-gpu.js +24 -14
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/image-kernel-execution.js +2 -2
- package/dist/gpu/image-kernel-execution.js.map +1 -1
- package/dist/gpu/temporal-sum-gpu.js +23 -23
- package/dist/gpu/webgpu-runtime.js +1 -1
- package/dist/gpu/webgpu-runtime.js.map +1 -1
- package/dist/gpu/wgsl-chart-composite-kernel.js +318 -318
- package/dist/gpu/wgsl-chart-composite-kernel.js.map +1 -1
- package/dist/gpu/wgsl-chart-kernel.js +117 -117
- package/dist/gpu/wgsl-chart-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +13 -1
- package/dist/gpu/wgsl-display-view-quality-kernel.js +522 -488
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.js +248 -248
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
- package/dist/gpu/wgsl-kernels.js +203 -203
- package/dist/gpu/wgsl-kernels.js.map +1 -1
- package/dist/gpu/wgsl-sensor-kernel.js +302 -302
- package/dist/gpu/wgsl-sensor-kernel.js.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/motion/temporal-exposure-sum.js +1 -1
- package/dist/motion/temporal-exposure-sum.js.map +1 -1
- package/dist/optics/diffraction-psf-profile.js +4 -4
- package/dist/optics/diffraction-psf-profile.js.map +1 -1
- package/dist/optics/front-of-lens-filter.js +1 -1
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/irradiance-convolution.d.ts +10 -0
- package/dist/optics/irradiance-convolution.js +49 -14
- package/dist/optics/irradiance-convolution.js.map +1 -1
- package/dist/output/native-capture-sdr.js +1 -1
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/output/png-encoder.js +2 -2
- package/dist/output/png-encoder.js.map +1 -1
- package/dist/output/print-jpeg.js +13 -10
- package/dist/output/print-jpeg.js.map +1 -1
- package/dist/output/text-metadata.d.ts +22 -2
- package/dist/output/text-metadata.js +58 -9
- package/dist/output/text-metadata.js.map +1 -1
- package/dist/sensor/fixed-pattern-noise.js +1 -1
- package/dist/sensor/fixed-pattern-noise.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.js +1 -1
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/docs/API_REFERENCE.md +49 -1
- package/docs/QUICK_START.md +104 -9
- package/docs/USAGE.md +241 -2
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-tier-assets.md +41 -1
- package/docs/api/equipment-generic-tier-presets.md +11 -3
- package/docs/api/exports.json +172 -2
- package/docs/api/exposure-auto-iso-slowest-shutter.md +139 -0
- package/docs/api/exposure-exposure-mode-resolver.md +68 -0
- package/docs/api/facade-chart-scenes.md +36 -5
- package/docs/api/facade-color-patches.md +150 -0
- package/docs/api/facade-simulate-capture.md +140 -9
- package/docs/api/output-text-metadata.md +34 -0
- package/llms.txt +1 -0
- package/package.json +2 -2
|
@@ -18,7 +18,7 @@ import { InvalidScientificInputError } from "../core/validation.js";
|
|
|
18
18
|
import { rejectUnknownFields, requireInputKeys, requireInputObject } from "../core/record-validation.js";
|
|
19
19
|
import { parseManualFlashProfile } from "./flash.js";
|
|
20
20
|
import { meterRelativeExposure, parseExposureMeteringProfile } from "./metering.js";
|
|
21
|
-
export const TTL_FLASH_MODEL = Object.freeze({ id: "preflash-linear-ttl", version: "1.0.0" });
|
|
21
|
+
export const TTL_FLASH_MODEL = /* @__PURE__ */ Object.freeze({ id: "preflash-linear-ttl", version: "1.0.0" });
|
|
22
22
|
function requirePositive(value, name) {
|
|
23
23
|
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
24
24
|
throw new InvalidScientificInputError(name + " must be a finite number greater than zero.");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flash-ttl.js","sourceRoot":"","sources":["../../src/exposure/flash-ttl.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Flash guide numbers, and through-the-lens (TTL) flash exposure with a pre-flash that does not\n * depend on any manufacturer.\n *\n * How TTL works here:\n * 1. The pre-flash is measured with the existing relative exposure meter.\n * 2. The solved power fraction is applied to a ManualFlashProfile.\n * 3. That pulse is placed by the existing front/rear-curtain sync (resolveManualFlashSync) or by\n * high-speed sync (resolveHighSpeedFlashSync).\n * Flash metering stays separate from ambient metering. The ambient meter result is an input and is\n * not changed. No vendor's TTL algorithm, zone weighting table or flash protocol is copied.\n * @see docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md#flash-guide-number-ttl-and-high-speed-sync\n */\n\nimport { approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport { rejectUnknownFields, requireInputKeys, requireInputObject } from \"../core/record-validation.js\";\nimport { parseManualFlashProfile, type ManualFlashProfile } from \"./flash.js\";\nimport {\n meterRelativeExposure,\n parseExposureMeteringProfile,\n type ExposureMeteringProfile,\n type ExposureMeteringSampleSet\n} from \"./metering.js\";\n\nexport const TTL_FLASH_MODEL = Object.freeze({ id: \"preflash-linear-ttl\", version: \"1.0.0\" } as const);\n\nfunction requirePositive(value: unknown, name: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n throw new InvalidScientificInputError(name + \" must be a finite number greater than zero.\");\n }\n return value;\n}\n\nfunction requireFraction(value: unknown, name: string): number {\n const parsed = requirePositive(value, name);\n if (parsed > 1) throw new InvalidScientificInputError(name + \" must lie in (0, 1].\");\n return parsed;\n}\n\nexport interface FlashGuideNumberInput {\n /** Guide number at full power for ISO 100, in metres (GN = distance · f-number). */\n fullPowerGuideNumberMetersIso100: number;\n /** Output as a fraction of full power, (0, 1]. */\n powerFraction: number;\n iso: number;\n}\n\n/**\n * Effective guide number GN = GN_full · √p · √(ISO/100).\n *\n * The guide number relation GN = d·N follows from the inverse-square law. Light on the subject from a\n * point-like flash falls as 1/d², and sensor exposure falls as 1/N². So exposure stays correct while\n * d·N is constant (camera equation H = 0.65·L·t/N² and reference exposure H = 10/S, CIPA DC-004-2020,\n * free). Exposure grows linearly with emitted energy (power fraction p), and the exposure needed falls\n * inversely with ISO speed. So GN ∝ √p·√ISO. The engine does not model how a guide number is measured;\n * the caller supplies it.\n * @see docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md for the full derivation.\n */\nexport function calculateFlashGuideNumber(input: FlashGuideNumberInput): number {\n requireInputKeys(input, \"calculateFlashGuideNumber\", [\"fullPowerGuideNumberMetersIso100\", \"powerFraction\", \"iso\"]);\n return requirePositive(input.fullPowerGuideNumberMetersIso100, \"fullPowerGuideNumberMetersIso100\") *\n Math.sqrt(requireFraction(input.powerFraction, \"powerFraction\")) *\n Math.sqrt(requirePositive(input.iso, \"iso\") / 100);\n}\n\nexport interface FlashPowerForDistanceInput {\n fullPowerGuideNumberMetersIso100: number;\n subjectDistanceM: number;\n apertureFNumber: number;\n iso: number;\n /** Lowest available power fraction, (0, 1]. */\n minimumPowerFraction: number;\n}\n\nexport interface FlashPowerForDistance {\n /** p = (d·N / (GN_full·√(ISO/100)))², before clamping. */\n requiredPowerFraction: number;\n powerFraction: number;\n status: \"within-range\" | \"clamped-at-minimum-power\" | \"clamped-at-full-power\";\n /** log2(delivered / required) flash exposure; positive is overexposure. */\n flashExposureErrorStops: number;\n /** GN_full·√(ISO/100)/N: the farthest correctly exposed distance at full power. */\n maximumDistanceM: number;\n}\n\n/** Manual guide-number exposure: the power fraction that exposes a subject at distance d correctly. */\nexport function calculateFlashPowerForDistance(input: FlashPowerForDistanceInput): FlashPowerForDistance {\n requireInputKeys(input, \"calculateFlashPowerForDistance\", [\"fullPowerGuideNumberMetersIso100\", \"subjectDistanceM\",\n \"apertureFNumber\", \"iso\", \"minimumPowerFraction\"]);\n const gnIso = calculateFlashGuideNumber({ fullPowerGuideNumberMetersIso100: input.fullPowerGuideNumberMetersIso100,\n powerFraction: 1, iso: input.iso });\n const distance = requirePositive(input.subjectDistanceM, \"subjectDistanceM\");\n const aperture = requirePositive(input.apertureFNumber, \"apertureFNumber\");\n const minimum = requireFraction(input.minimumPowerFraction, \"minimumPowerFraction\");\n const required = (distance * aperture / gnIso) ** 2;\n const power = Math.min(1, Math.max(minimum, required));\n return { requiredPowerFraction: required, powerFraction: power,\n status: required < minimum ? \"clamped-at-minimum-power\" : required > 1 ? \"clamped-at-full-power\" : \"within-range\",\n flashExposureErrorStops: Math.log2(power / required), maximumDistanceM: gnIso / aperture };\n}\n\nexport interface ResolveTtlFlashExposureInput {\n /** Spatially linear metering profile (multi-zone-uniform, center-weighted-radial or spot). */\n meteringProfile: ExposureMeteringProfile;\n /** Measurement-window samples with the flash off. */\n ambientSampleSet: ExposureMeteringSampleSet;\n /** The same zones and settings with the pre-flash fired. */\n preFlashSampleSet: ExposureMeteringSampleSet;\n /** Pre-flash output as a fraction of full power, (0, 1]. */\n preFlashPowerFraction: number;\n /**\n * Ratio of ambient light collected in the main exposure to that in the measurement window, at the\n * same aperture and ISO (for example t_main/t_measure). Must be ≥ 0. The flash pulse falls inside\n * both windows, so it is not scaled.\n */\n ambientScaleToMainExposure: number;\n /** Flash exposure compensation applied to the TTL target, in stops. */\n flashExposureCompensationStops: number;\n /** Lowest available main-flash power fraction, (0, 1]. */\n minimumPowerFraction: number;\n /**\n * Flash energy each line receives, relative to an ordinary pulse at the same power fraction. 1 for\n * front/rear-curtain sync; η·t_e/D for high-speed sync (see resolveHighSpeedFlashSync). Defaults to 1.\n */\n syncEnergyFactor?: number;\n /** Optional guide-number reporting. */\n guideNumber?: { fullPowerGuideNumberMetersIso100: number; iso: number; apertureFNumber: number };\n}\n\nexport interface TtlFlashExposure {\n modelId: typeof TTL_FLASH_MODEL.id;\n modelVersion: typeof TTL_FLASH_MODEL.version;\n status: \"resolved\" | \"clamped-at-minimum-power\" | \"clamped-at-full-power\" | \"no-flash-return\";\n /** Metered ambient signal in the main exposure: k·M(ambient). */\n ambientMainExposureMeteredSignal: number;\n /** Metered flash-only signal per unit full power: M(preflash − ambient)/p_pre. */\n flashMeteredSignalPerFullPower: number;\n /** T·2^FEC. */\n targetRelativeSignal: number;\n /** Unclamped solution (T' − k·A)/(F·syncEnergyFactor); null with no flash return. */\n requiredPowerFraction: number | null;\n /** Commanded main-flash power fraction (clamped); null with no flash return. */\n powerFraction: number | null;\n ambientAloneReachesTarget: boolean;\n predictedMeteredSignal: number;\n /** log2(predicted / target); 0 when the solution is within range; null when nothing is predicted. */\n predictedExposureErrorStops: number | null;\n effectiveGuideNumberMetersAtIso: number | null;\n flashRangeAtApertureM: number | null;\n preFlashInsideMainExposure: false;\n ambientMeteringModified: false;\n}\n\nconst LINEAR_POLICIES = new Set([\"multi-zone-uniform\", \"center-weighted-radial\", \"spot\"]);\n\nfunction sameZones(a: ExposureMeteringSampleSet, b: ExposureMeteringSampleSet): void {\n if (a.sceneStateId !== b.sceneStateId || a.samples.length !== b.samples.length ||\n JSON.stringify(a.captureGeometry) !== JSON.stringify(b.captureGeometry)) {\n throw new InvalidScientificInputError(\"Ambient and pre-flash measurements must share scene state, geometry and zones.\");\n }\n a.samples.forEach((sample, index) => {\n const other = b.samples[index]!;\n requireInputObject(sample, \"ambientSampleSet.samples[\" + index + \"]\");\n requireInputObject(other, \"preFlashSampleSet.samples[\" + index + \"]\");\n requireInputObject(sample.positionOrientedCaptureUv, \"ambientSampleSet.samples[\" + index + \"].positionOrientedCaptureUv\");\n requireInputObject(other.positionOrientedCaptureUv, \"preFlashSampleSet.samples[\" + index + \"].positionOrientedCaptureUv\");\n if (sample.sampleId !== other.sampleId || sample.areaWeight !== other.areaWeight ||\n sample.positionOrientedCaptureUv.u !== other.positionOrientedCaptureUv.u ||\n sample.positionOrientedCaptureUv.v !== other.positionOrientedCaptureUv.v) {\n throw new InvalidScientificInputError(\"Ambient and pre-flash zones must match exactly and in order.\");\n }\n });\n}\n\n/**\n * Solves the main-flash power from a pre-flash measurement (manufacturer-independent TTL).\n *\n * The meter is linear for the policies allowed here: M(a + b) = M(a) + M(b).\n * - The pre-flash at power p_pre adds a flash-only signal f_i = pre_i − ambient_i in each zone.\n * - Flash signal is proportional to emitted energy, so at main power p it adds (p/p_pre)·M(f).\n * - With ambient scaled to the main exposure by k, the metered total is k·A + p·F, where\n * F = M(f)/p_pre.\n * - Setting this equal to the target T' = T·2^FEC gives p = (T' − k·A)/(F·s). Here s is the sync\n * energy factor (1 for ordinary sync, η·t_e/D for high-speed sync).\n * - p is clamped to [p_min, 1], the guide-number range.\n * Highlight policies are rejected: their weights depend on the signal, so the total is no longer\n * linear in p.\n */\nexport function resolveTtlFlashExposure(input: ResolveTtlFlashExposureInput): CalculationResult<TtlFlashExposure> {\n requireInputKeys(input, \"resolveTtlFlashExposure\", [\"meteringProfile\", \"ambientSampleSet\", \"preFlashSampleSet\", \"preFlashPowerFraction\", \"ambientScaleToMainExposure\", \"flashExposureCompensationStops\", \"minimumPowerFraction\", \"syncEnergyFactor\", \"guideNumber\"]);\n requireInputObject(input.ambientSampleSet, \"resolveTtlFlashExposure ambientSampleSet\");\n requireInputObject(input.preFlashSampleSet, \"resolveTtlFlashExposure preFlashSampleSet\");\n if (input.guideNumber !== undefined) {\n requireInputObject(input.guideNumber, \"resolveTtlFlashExposure guideNumber\");\n rejectUnknownFields(input.guideNumber, [\"fullPowerGuideNumberMetersIso100\", \"iso\", \"apertureFNumber\"], \"resolveTtlFlashExposure guideNumber\");\n }\n if (!Array.isArray(input.ambientSampleSet.samples) || !Array.isArray(input.preFlashSampleSet.samples)) {\n throw new InvalidConfigurationError(\"TTL sample sets must contain sample arrays.\");\n }\n const profile = parseExposureMeteringProfile(input.meteringProfile);\n if (!LINEAR_POLICIES.has(profile.policy.kind)) {\n throw new InvalidScientificInputError(\n \"TTL flash requires a spatially linear metering policy (multi-zone-uniform, center-weighted-radial or spot).\"\n );\n }\n sameZones(input.ambientSampleSet, input.preFlashSampleSet);\n const preFlash = requireFraction(input.preFlashPowerFraction, \"preFlashPowerFraction\");\n const minimum = requireFraction(input.minimumPowerFraction, \"minimumPowerFraction\");\n const k = input.ambientScaleToMainExposure;\n if (typeof k !== \"number\" || !Number.isFinite(k) || k < 0) {\n throw new InvalidScientificInputError(\"ambientScaleToMainExposure must be a finite number greater than or equal to zero.\");\n }\n const fec = input.flashExposureCompensationStops;\n if (typeof fec !== \"number\" || !Number.isFinite(fec)) {\n throw new InvalidScientificInputError(\"flashExposureCompensationStops must be finite.\");\n }\n const syncFactor = input.syncEnergyFactor === undefined ? 1 : requireFraction(input.syncEnergyFactor, \"syncEnergyFactor\");\n const flashOnly: ExposureMeteringSampleSet = { ...input.preFlashSampleSet,\n measurementId: input.preFlashSampleSet.measurementId + \":flash-only\",\n samples: input.preFlashSampleSet.samples.map((sample, index) => {\n const difference = sample.relativeLinearSignal - input.ambientSampleSet.samples[index]!.relativeLinearSignal;\n if (!(difference >= 0)) {\n throw new InvalidScientificInputError(\"Pre-flash signal must not be below the ambient signal in any zone.\");\n }\n return { ...sample, relativeLinearSignal: difference };\n }) };\n const ambient = meterRelativeExposure({ profile, sampleSet: input.ambientSampleSet }).value.meteredRelativeSignal;\n const flashPerFull = meterRelativeExposure({ profile, sampleSet: flashOnly }).value.meteredRelativeSignal / preFlash;\n const ambientMain = k * ambient;\n const target = profile.target.targetRelativeSignal * Math.pow(2, fec);\n const deliveredPerFull = flashPerFull * syncFactor;\n let status: TtlFlashExposure[\"status\"], required: number | null, power: number | null;\n if (deliveredPerFull === 0) {\n status = \"no-flash-return\"; required = null; power = null;\n } else {\n required = (target - ambientMain) / deliveredPerFull;\n power = Math.min(1, Math.max(minimum, required));\n status = required < minimum ? \"clamped-at-minimum-power\" : required > 1 ? \"clamped-at-full-power\" : \"resolved\";\n }\n const predicted = ambientMain + (power ?? 0) * deliveredPerFull;\n const gn = input.guideNumber;\n const effectiveGn = gn === undefined || power === null ? null : calculateFlashGuideNumber({\n fullPowerGuideNumberMetersIso100: gn.fullPowerGuideNumberMetersIso100, powerFraction: power, iso: gn.iso }) * Math.sqrt(syncFactor);\n return approximationResult({\n modelId: TTL_FLASH_MODEL.id,\n modelVersion: TTL_FLASH_MODEL.version,\n status,\n ambientMainExposureMeteredSignal: ambientMain,\n flashMeteredSignalPerFullPower: flashPerFull,\n targetRelativeSignal: target,\n requiredPowerFraction: required,\n powerFraction: power,\n ambientAloneReachesTarget: ambientMain >= target,\n predictedMeteredSignal: predicted,\n predictedExposureErrorStops: predicted > 0 ? Math.log2(predicted / target) : null,\n effectiveGuideNumberMetersAtIso: effectiveGn,\n flashRangeAtApertureM: effectiveGn === null || gn === undefined ? null : effectiveGn / requirePositive(gn.apertureFNumber, \"apertureFNumber\"),\n preFlashInsideMainExposure: false,\n ambientMeteringModified: false\n }, TTL_FLASH_MODEL.id, TTL_FLASH_MODEL.version, [\n \"Relative pre-exposure meter signals only; no calibrated flash energy, subject reflectance or distance is inferred.\",\n \"Flash signal is assumed proportional to emitted energy and fully inside the main exposure (pulse) or each line's slit (HSS factor).\",\n \"The pre-flash precedes the main exposure; subject motion and ambient change between pre-flash and exposure are not modeled.\",\n \"This is a generic linear pre-flash solution, not any manufacturer's TTL algorithm, zone weighting or flash protocol.\"\n ]);\n}\n\n/**\n * Returns a copy of a manual flash profile with its relative output scaled by a resolved TTL power\n * fraction, ready for resolveManualFlashSync (front/rear curtain). For high-speed sync, instead pass\n * the unscaled profile, and pass `ttl.powerFraction` as resolveHighSpeedFlashSync's powerFraction.\n * That way power is applied only once.\n */\nexport function createTtlScaledFlashProfile(flashProfile: ManualFlashProfile, ttl: TtlFlashExposure): ManualFlashProfile {\n const flash = parseManualFlashProfile(flashProfile);\n requireInputObject(ttl, \"createTtlScaledFlashProfile ttl\");\n if (ttl.powerFraction === null || typeof ttl.powerFraction !== \"number\") {\n throw new InvalidScientificInputError(\"TTL found no flash return; there is no power fraction to apply.\");\n }\n return { ...flash, outputControl: { ...flash.outputControl, scale: flash.outputControl.scale * ttl.powerFraction } };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"flash-ttl.js","sourceRoot":"","sources":["../../src/exposure/flash-ttl.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Flash guide numbers, and through-the-lens (TTL) flash exposure with a pre-flash that does not\n * depend on any manufacturer.\n *\n * How TTL works here:\n * 1. The pre-flash is measured with the existing relative exposure meter.\n * 2. The solved power fraction is applied to a ManualFlashProfile.\n * 3. That pulse is placed by the existing front/rear-curtain sync (resolveManualFlashSync) or by\n * high-speed sync (resolveHighSpeedFlashSync).\n * Flash metering stays separate from ambient metering. The ambient meter result is an input and is\n * not changed. No vendor's TTL algorithm, zone weighting table or flash protocol is copied.\n * @see docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md#flash-guide-number-ttl-and-high-speed-sync\n */\n\nimport { approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport { rejectUnknownFields, requireInputKeys, requireInputObject } from \"../core/record-validation.js\";\nimport { parseManualFlashProfile, type ManualFlashProfile } from \"./flash.js\";\nimport {\n meterRelativeExposure,\n parseExposureMeteringProfile,\n type ExposureMeteringProfile,\n type ExposureMeteringSampleSet\n} from \"./metering.js\";\n\nexport const TTL_FLASH_MODEL = /* @__PURE__ */ Object.freeze({ id: \"preflash-linear-ttl\", version: \"1.0.0\" } as const);\n\nfunction requirePositive(value: unknown, name: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n throw new InvalidScientificInputError(name + \" must be a finite number greater than zero.\");\n }\n return value;\n}\n\nfunction requireFraction(value: unknown, name: string): number {\n const parsed = requirePositive(value, name);\n if (parsed > 1) throw new InvalidScientificInputError(name + \" must lie in (0, 1].\");\n return parsed;\n}\n\nexport interface FlashGuideNumberInput {\n /** Guide number at full power for ISO 100, in metres (GN = distance · f-number). */\n fullPowerGuideNumberMetersIso100: number;\n /** Output as a fraction of full power, (0, 1]. */\n powerFraction: number;\n iso: number;\n}\n\n/**\n * Effective guide number GN = GN_full · √p · √(ISO/100).\n *\n * The guide number relation GN = d·N follows from the inverse-square law. Light on the subject from a\n * point-like flash falls as 1/d², and sensor exposure falls as 1/N². So exposure stays correct while\n * d·N is constant (camera equation H = 0.65·L·t/N² and reference exposure H = 10/S, CIPA DC-004-2020,\n * free). Exposure grows linearly with emitted energy (power fraction p), and the exposure needed falls\n * inversely with ISO speed. So GN ∝ √p·√ISO. The engine does not model how a guide number is measured;\n * the caller supplies it.\n * @see docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md for the full derivation.\n */\nexport function calculateFlashGuideNumber(input: FlashGuideNumberInput): number {\n requireInputKeys(input, \"calculateFlashGuideNumber\", [\"fullPowerGuideNumberMetersIso100\", \"powerFraction\", \"iso\"]);\n return requirePositive(input.fullPowerGuideNumberMetersIso100, \"fullPowerGuideNumberMetersIso100\") *\n Math.sqrt(requireFraction(input.powerFraction, \"powerFraction\")) *\n Math.sqrt(requirePositive(input.iso, \"iso\") / 100);\n}\n\nexport interface FlashPowerForDistanceInput {\n fullPowerGuideNumberMetersIso100: number;\n subjectDistanceM: number;\n apertureFNumber: number;\n iso: number;\n /** Lowest available power fraction, (0, 1]. */\n minimumPowerFraction: number;\n}\n\nexport interface FlashPowerForDistance {\n /** p = (d·N / (GN_full·√(ISO/100)))², before clamping. */\n requiredPowerFraction: number;\n powerFraction: number;\n status: \"within-range\" | \"clamped-at-minimum-power\" | \"clamped-at-full-power\";\n /** log2(delivered / required) flash exposure; positive is overexposure. */\n flashExposureErrorStops: number;\n /** GN_full·√(ISO/100)/N: the farthest correctly exposed distance at full power. */\n maximumDistanceM: number;\n}\n\n/** Manual guide-number exposure: the power fraction that exposes a subject at distance d correctly. */\nexport function calculateFlashPowerForDistance(input: FlashPowerForDistanceInput): FlashPowerForDistance {\n requireInputKeys(input, \"calculateFlashPowerForDistance\", [\"fullPowerGuideNumberMetersIso100\", \"subjectDistanceM\",\n \"apertureFNumber\", \"iso\", \"minimumPowerFraction\"]);\n const gnIso = calculateFlashGuideNumber({ fullPowerGuideNumberMetersIso100: input.fullPowerGuideNumberMetersIso100,\n powerFraction: 1, iso: input.iso });\n const distance = requirePositive(input.subjectDistanceM, \"subjectDistanceM\");\n const aperture = requirePositive(input.apertureFNumber, \"apertureFNumber\");\n const minimum = requireFraction(input.minimumPowerFraction, \"minimumPowerFraction\");\n const required = (distance * aperture / gnIso) ** 2;\n const power = Math.min(1, Math.max(minimum, required));\n return { requiredPowerFraction: required, powerFraction: power,\n status: required < minimum ? \"clamped-at-minimum-power\" : required > 1 ? \"clamped-at-full-power\" : \"within-range\",\n flashExposureErrorStops: Math.log2(power / required), maximumDistanceM: gnIso / aperture };\n}\n\nexport interface ResolveTtlFlashExposureInput {\n /** Spatially linear metering profile (multi-zone-uniform, center-weighted-radial or spot). */\n meteringProfile: ExposureMeteringProfile;\n /** Measurement-window samples with the flash off. */\n ambientSampleSet: ExposureMeteringSampleSet;\n /** The same zones and settings with the pre-flash fired. */\n preFlashSampleSet: ExposureMeteringSampleSet;\n /** Pre-flash output as a fraction of full power, (0, 1]. */\n preFlashPowerFraction: number;\n /**\n * Ratio of ambient light collected in the main exposure to that in the measurement window, at the\n * same aperture and ISO (for example t_main/t_measure). Must be ≥ 0. The flash pulse falls inside\n * both windows, so it is not scaled.\n */\n ambientScaleToMainExposure: number;\n /** Flash exposure compensation applied to the TTL target, in stops. */\n flashExposureCompensationStops: number;\n /** Lowest available main-flash power fraction, (0, 1]. */\n minimumPowerFraction: number;\n /**\n * Flash energy each line receives, relative to an ordinary pulse at the same power fraction. 1 for\n * front/rear-curtain sync; η·t_e/D for high-speed sync (see resolveHighSpeedFlashSync). Defaults to 1.\n */\n syncEnergyFactor?: number;\n /** Optional guide-number reporting. */\n guideNumber?: { fullPowerGuideNumberMetersIso100: number; iso: number; apertureFNumber: number };\n}\n\nexport interface TtlFlashExposure {\n modelId: typeof TTL_FLASH_MODEL.id;\n modelVersion: typeof TTL_FLASH_MODEL.version;\n status: \"resolved\" | \"clamped-at-minimum-power\" | \"clamped-at-full-power\" | \"no-flash-return\";\n /** Metered ambient signal in the main exposure: k·M(ambient). */\n ambientMainExposureMeteredSignal: number;\n /** Metered flash-only signal per unit full power: M(preflash − ambient)/p_pre. */\n flashMeteredSignalPerFullPower: number;\n /** T·2^FEC. */\n targetRelativeSignal: number;\n /** Unclamped solution (T' − k·A)/(F·syncEnergyFactor); null with no flash return. */\n requiredPowerFraction: number | null;\n /** Commanded main-flash power fraction (clamped); null with no flash return. */\n powerFraction: number | null;\n ambientAloneReachesTarget: boolean;\n predictedMeteredSignal: number;\n /** log2(predicted / target); 0 when the solution is within range; null when nothing is predicted. */\n predictedExposureErrorStops: number | null;\n effectiveGuideNumberMetersAtIso: number | null;\n flashRangeAtApertureM: number | null;\n preFlashInsideMainExposure: false;\n ambientMeteringModified: false;\n}\n\nconst LINEAR_POLICIES = new Set([\"multi-zone-uniform\", \"center-weighted-radial\", \"spot\"]);\n\nfunction sameZones(a: ExposureMeteringSampleSet, b: ExposureMeteringSampleSet): void {\n if (a.sceneStateId !== b.sceneStateId || a.samples.length !== b.samples.length ||\n JSON.stringify(a.captureGeometry) !== JSON.stringify(b.captureGeometry)) {\n throw new InvalidScientificInputError(\"Ambient and pre-flash measurements must share scene state, geometry and zones.\");\n }\n a.samples.forEach((sample, index) => {\n const other = b.samples[index]!;\n requireInputObject(sample, \"ambientSampleSet.samples[\" + index + \"]\");\n requireInputObject(other, \"preFlashSampleSet.samples[\" + index + \"]\");\n requireInputObject(sample.positionOrientedCaptureUv, \"ambientSampleSet.samples[\" + index + \"].positionOrientedCaptureUv\");\n requireInputObject(other.positionOrientedCaptureUv, \"preFlashSampleSet.samples[\" + index + \"].positionOrientedCaptureUv\");\n if (sample.sampleId !== other.sampleId || sample.areaWeight !== other.areaWeight ||\n sample.positionOrientedCaptureUv.u !== other.positionOrientedCaptureUv.u ||\n sample.positionOrientedCaptureUv.v !== other.positionOrientedCaptureUv.v) {\n throw new InvalidScientificInputError(\"Ambient and pre-flash zones must match exactly and in order.\");\n }\n });\n}\n\n/**\n * Solves the main-flash power from a pre-flash measurement (manufacturer-independent TTL).\n *\n * The meter is linear for the policies allowed here: M(a + b) = M(a) + M(b).\n * - The pre-flash at power p_pre adds a flash-only signal f_i = pre_i − ambient_i in each zone.\n * - Flash signal is proportional to emitted energy, so at main power p it adds (p/p_pre)·M(f).\n * - With ambient scaled to the main exposure by k, the metered total is k·A + p·F, where\n * F = M(f)/p_pre.\n * - Setting this equal to the target T' = T·2^FEC gives p = (T' − k·A)/(F·s). Here s is the sync\n * energy factor (1 for ordinary sync, η·t_e/D for high-speed sync).\n * - p is clamped to [p_min, 1], the guide-number range.\n * Highlight policies are rejected: their weights depend on the signal, so the total is no longer\n * linear in p.\n */\nexport function resolveTtlFlashExposure(input: ResolveTtlFlashExposureInput): CalculationResult<TtlFlashExposure> {\n requireInputKeys(input, \"resolveTtlFlashExposure\", [\"meteringProfile\", \"ambientSampleSet\", \"preFlashSampleSet\", \"preFlashPowerFraction\", \"ambientScaleToMainExposure\", \"flashExposureCompensationStops\", \"minimumPowerFraction\", \"syncEnergyFactor\", \"guideNumber\"]);\n requireInputObject(input.ambientSampleSet, \"resolveTtlFlashExposure ambientSampleSet\");\n requireInputObject(input.preFlashSampleSet, \"resolveTtlFlashExposure preFlashSampleSet\");\n if (input.guideNumber !== undefined) {\n requireInputObject(input.guideNumber, \"resolveTtlFlashExposure guideNumber\");\n rejectUnknownFields(input.guideNumber, [\"fullPowerGuideNumberMetersIso100\", \"iso\", \"apertureFNumber\"], \"resolveTtlFlashExposure guideNumber\");\n }\n if (!Array.isArray(input.ambientSampleSet.samples) || !Array.isArray(input.preFlashSampleSet.samples)) {\n throw new InvalidConfigurationError(\"TTL sample sets must contain sample arrays.\");\n }\n const profile = parseExposureMeteringProfile(input.meteringProfile);\n if (!LINEAR_POLICIES.has(profile.policy.kind)) {\n throw new InvalidScientificInputError(\n \"TTL flash requires a spatially linear metering policy (multi-zone-uniform, center-weighted-radial or spot).\"\n );\n }\n sameZones(input.ambientSampleSet, input.preFlashSampleSet);\n const preFlash = requireFraction(input.preFlashPowerFraction, \"preFlashPowerFraction\");\n const minimum = requireFraction(input.minimumPowerFraction, \"minimumPowerFraction\");\n const k = input.ambientScaleToMainExposure;\n if (typeof k !== \"number\" || !Number.isFinite(k) || k < 0) {\n throw new InvalidScientificInputError(\"ambientScaleToMainExposure must be a finite number greater than or equal to zero.\");\n }\n const fec = input.flashExposureCompensationStops;\n if (typeof fec !== \"number\" || !Number.isFinite(fec)) {\n throw new InvalidScientificInputError(\"flashExposureCompensationStops must be finite.\");\n }\n const syncFactor = input.syncEnergyFactor === undefined ? 1 : requireFraction(input.syncEnergyFactor, \"syncEnergyFactor\");\n const flashOnly: ExposureMeteringSampleSet = { ...input.preFlashSampleSet,\n measurementId: input.preFlashSampleSet.measurementId + \":flash-only\",\n samples: input.preFlashSampleSet.samples.map((sample, index) => {\n const difference = sample.relativeLinearSignal - input.ambientSampleSet.samples[index]!.relativeLinearSignal;\n if (!(difference >= 0)) {\n throw new InvalidScientificInputError(\"Pre-flash signal must not be below the ambient signal in any zone.\");\n }\n return { ...sample, relativeLinearSignal: difference };\n }) };\n const ambient = meterRelativeExposure({ profile, sampleSet: input.ambientSampleSet }).value.meteredRelativeSignal;\n const flashPerFull = meterRelativeExposure({ profile, sampleSet: flashOnly }).value.meteredRelativeSignal / preFlash;\n const ambientMain = k * ambient;\n const target = profile.target.targetRelativeSignal * Math.pow(2, fec);\n const deliveredPerFull = flashPerFull * syncFactor;\n let status: TtlFlashExposure[\"status\"], required: number | null, power: number | null;\n if (deliveredPerFull === 0) {\n status = \"no-flash-return\"; required = null; power = null;\n } else {\n required = (target - ambientMain) / deliveredPerFull;\n power = Math.min(1, Math.max(minimum, required));\n status = required < minimum ? \"clamped-at-minimum-power\" : required > 1 ? \"clamped-at-full-power\" : \"resolved\";\n }\n const predicted = ambientMain + (power ?? 0) * deliveredPerFull;\n const gn = input.guideNumber;\n const effectiveGn = gn === undefined || power === null ? null : calculateFlashGuideNumber({\n fullPowerGuideNumberMetersIso100: gn.fullPowerGuideNumberMetersIso100, powerFraction: power, iso: gn.iso }) * Math.sqrt(syncFactor);\n return approximationResult({\n modelId: TTL_FLASH_MODEL.id,\n modelVersion: TTL_FLASH_MODEL.version,\n status,\n ambientMainExposureMeteredSignal: ambientMain,\n flashMeteredSignalPerFullPower: flashPerFull,\n targetRelativeSignal: target,\n requiredPowerFraction: required,\n powerFraction: power,\n ambientAloneReachesTarget: ambientMain >= target,\n predictedMeteredSignal: predicted,\n predictedExposureErrorStops: predicted > 0 ? Math.log2(predicted / target) : null,\n effectiveGuideNumberMetersAtIso: effectiveGn,\n flashRangeAtApertureM: effectiveGn === null || gn === undefined ? null : effectiveGn / requirePositive(gn.apertureFNumber, \"apertureFNumber\"),\n preFlashInsideMainExposure: false,\n ambientMeteringModified: false\n }, TTL_FLASH_MODEL.id, TTL_FLASH_MODEL.version, [\n \"Relative pre-exposure meter signals only; no calibrated flash energy, subject reflectance or distance is inferred.\",\n \"Flash signal is assumed proportional to emitted energy and fully inside the main exposure (pulse) or each line's slit (HSS factor).\",\n \"The pre-flash precedes the main exposure; subject motion and ambient change between pre-flash and exposure are not modeled.\",\n \"This is a generic linear pre-flash solution, not any manufacturer's TTL algorithm, zone weighting or flash protocol.\"\n ]);\n}\n\n/**\n * Returns a copy of a manual flash profile with its relative output scaled by a resolved TTL power\n * fraction, ready for resolveManualFlashSync (front/rear curtain). For high-speed sync, instead pass\n * the unscaled profile, and pass `ttl.powerFraction` as resolveHighSpeedFlashSync's powerFraction.\n * That way power is applied only once.\n */\nexport function createTtlScaledFlashProfile(flashProfile: ManualFlashProfile, ttl: TtlFlashExposure): ManualFlashProfile {\n const flash = parseManualFlashProfile(flashProfile);\n requireInputObject(ttl, \"createTtlScaledFlashProfile ttl\");\n if (ttl.powerFraction === null || typeof ttl.powerFraction !== \"number\") {\n throw new InvalidScientificInputError(\"TTL found no flash return; there is no power fraction to apply.\");\n }\n return { ...flash, outputControl: { ...flash.outputControl, scale: flash.outputControl.scale * ttl.powerFraction } };\n}\n"]}
|
package/dist/exposure/flash.js
CHANGED
|
@@ -26,7 +26,7 @@ export const FLASH_SYNC_CAPABILITY_SCHEMA_VERSION = "0.1.0";
|
|
|
26
26
|
/** Sync-capability schema that may declare high-speed sync (a fast pulse train that acts as continuous light). */
|
|
27
27
|
export const FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION = "0.2.0";
|
|
28
28
|
/** Model identity of the pulsed quasi-continuous high-speed-sync burst. */
|
|
29
|
-
export const HIGH_SPEED_SYNC_MODEL = Object.freeze({
|
|
29
|
+
export const HIGH_SPEED_SYNC_MODEL = /* @__PURE__ */ Object.freeze({
|
|
30
30
|
id: "flash-hss-quasi-continuous-burst",
|
|
31
31
|
version: "1.0.0"
|
|
32
32
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flash.js","sourceRoot":"","sources":["../../src/exposure/flash.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Manual flash and flash sync.\n *\n * The parsers validate untrusted input and return the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected.\n *\n * Manual flash is a relative light pulse added on top of the scene light, timed on the capture's\n * opening-reference clock.\n * - Ordinary front- or rear-curtain sync needs a real interval when the whole frame is open at once.\n * - High-speed sync (HSS; schema 0.2.0 sync profiles) is separate: a near-continuous burst that\n * covers the travelling shutter slit (resolveHighSpeedFlashSync).\n * - TTL pre-flash power and guide-number relations are in flash-ttl.ts.\n * Source brightness, optical transport and sensor integration have their own contracts.\n * @see docs/USAGE.md for the equations, units, coordinate conventions, known blockers and support\n * limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport type {\n ResolvedReleaseFrame\n} from \"../capture/release-sequence.js\";\nimport {\n parseSceneIlluminationProfile,\n type SceneIlluminationProfile,\n type SceneIlluminationSource\n} from \"../schema/illumination.js\";\nimport {\n parseSceneIlluminationTemporalProfile,\n type SceneIlluminationTemporalProfile,\n type SceneIlluminationTemporalWaveformSample\n} from \"../schema/illumination-temporal.js\";\nimport type {\n ResolvedCaptureModeTiming\n} from \"../sensor/capture-mode-timing.js\";\nimport { requireInputObject, requireInputKeys, rejectUnknownFields } from \"../core/record-validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const MANUAL_FLASH_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\nexport const FLASH_SYNC_CAPABILITY_SCHEMA_VERSION =\n \"0.1.0\" as const;\n/** Sync-capability schema that may declare high-speed sync (a fast pulse train that acts as continuous light). */\nexport const FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION =\n \"0.2.0\" as const;\n/** Model identity of the pulsed quasi-continuous high-speed-sync burst. */\nexport const HIGH_SPEED_SYNC_MODEL = Object.freeze({\n id: \"flash-hss-quasi-continuous-burst\",\n version: \"1.0.0\"\n} as const);\n\nexport type ManualFlashSyncMode =\n | \"front-curtain\"\n | \"rear-curtain\";\n\nexport type RequestedFlashSyncMode =\n | ManualFlashSyncMode\n | \"high-speed-sync\";\n\nexport interface ManualFlashPulseProfile {\n waveformId: string;\n scientificStatus: \"approximation\";\n supportDurationSeconds: number;\n interpolation: \"piecewise-linear\";\n samples:\n readonly SceneIlluminationTemporalWaveformSample[];\n normalization:\n \"relative-peak-one\";\n evidence:\n readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface ManualFlashProfile {\n schemaVersion:\n typeof MANUAL_FLASH_PROFILE_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n sourceTemplate:\n Omit<\n SceneIlluminationSource,\n \"enabled\" |\n \"temporalBehavior\"\n >;\n pulse:\n ManualFlashPulseProfile;\n outputControl: {\n kind:\n \"relative-linear-source-scale\";\n scale: number;\n flashExposureCompensationStops:\n 0;\n };\n ttlModeled: false;\n highSpeedSyncModeled: false;\n recycleBehaviorModeled: false;\n redEyePreflashModeled: false;\n modelingLightModeled: false;\n afAssistModeled: false;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface FlashSyncCapabilityProfile {\n schemaVersion:\n | typeof FLASH_SYNC_CAPABILITY_SCHEMA_VERSION\n | typeof FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n captureModeId: string;\n timingProfileId: string;\n supportedOrdinarySyncModes:\n readonly ManualFlashSyncMode[];\n /** Schema 0.1.0 is always false; schema 0.2.0 may declare HSS with {@link highSpeedSync}. */\n highSpeedSyncSupported: boolean;\n /** Present exactly when highSpeedSyncSupported is true (schema 0.2.0). */\n highSpeedSync?: {\n /**\n * η: energy of one full-power high-speed-sync burst, as a fraction of one full-power ordinary\n * pulse, in (0, 1]. The caller declares it from evidence (capacitor and thermal limits). It is\n * never inferred.\n */\n burstEnergyFractionOfFullPulse: number;\n evidence: readonly EvidenceProvenance[];\n };\n ordinarySyncRequiresWholeActiveFrameSimultaneouslyExposed:\n true;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface ResolveManualFlashSyncInput {\n flashEnabled: boolean;\n flashProfile:\n ManualFlashProfile;\n syncCapabilities:\n FlashSyncCapabilityProfile;\n timing:\n ResolvedCaptureModeTiming;\n syncMode:\n RequestedFlashSyncMode;\n releaseFrame?:\n ResolvedReleaseFrame;\n}\n\nexport interface ResolvedManualFlashSync {\n flashEnabled: boolean;\n flashProfileId: string;\n flashProfileVersion: string;\n sourceId: string;\n captureModeId: string;\n timingProfileId: string;\n syncCapabilityProfileId:\n string;\n syncMode:\n RequestedFlashSyncMode;\n syncStatus:\n | \"disabled\"\n | \"ordinary-sync-resolved\";\n timeReference:\n \"first-opening-boundary-phase\";\n wholeActiveFrameOpenInterval:\n {\n startSecondsFromCaptureReference:\n number;\n endSecondsFromCaptureReference:\n number;\n durationSeconds: number;\n };\n pulseSupportDurationSeconds:\n number;\n pulseStartSecondsFromCaptureReference:\n number | null;\n pulseEndSecondsFromCaptureReference:\n number | null;\n waveformTimeZeroSecondsFromCaptureReference:\n number | null;\n releaseFrameBinding:\n | {\n sequenceId: string;\n releaseFrameId: string;\n frameIndex: number;\n sceneTimeSecondsFromSequenceStartAtPulseStart:\n number;\n sceneTimeSecondsFromSequenceStartAtPulseEnd:\n number;\n }\n | null;\n hssModeled: false;\n ttlModeled: false;\n sensorReadoutTimingUsedAsExposureTiming:\n false;\n whiteBalanceModified: false;\n focusModified: false;\n exposureSettingsModified: false;\n driveModeModified: false;\n supportStateModified: false;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\n/** Fields of a resolved sync (ordinary or HSS) needed to register a flash overlay. */\nexport type FlashOverlaySyncRegistration = Pick<\n ResolvedManualFlashSync,\n | \"flashEnabled\"\n | \"flashProfileId\"\n | \"flashProfileVersion\"\n | \"sourceId\"\n | \"waveformTimeZeroSecondsFromCaptureReference\"\n | \"evidence\"\n>;\n\nexport interface CreateManualFlashIlluminationOverlayInput {\n baseIlluminationProfile:\n SceneIlluminationProfile;\n baseTemporalProfile?:\n SceneIlluminationTemporalProfile;\n flashProfile:\n ManualFlashProfile;\n resolvedSync:\n FlashOverlaySyncRegistration;\n illuminationProfileId: string;\n temporalProfileId: string;\n}\n\nexport interface ManualFlashIlluminationOverlay {\n flashApplied: boolean;\n illuminationProfile:\n SceneIlluminationProfile;\n temporalProfile:\n SceneIlluminationTemporalProfile | null;\n sourceId: string;\n waveformId: string;\n timeReference:\n \"first-opening-boundary-phase\";\n sourceMagnitudeAppliedBySceneTransport:\n true;\n materialTransportOwnedBySceneRadiance:\n true;\n visibilityOwnedBySceneRadiance:\n true;\n indirectTransportOwnedBySceneRadiance:\n true;\n postRenderBrightnessMultiplierUsed:\n false;\n whiteBalanceModified: false;\n ambientMeteringModified: false;\n ttlMeteringIncluded: false;\n ambientTemporalBehaviorPreserved:\n true;\n}\n\nconst ORDINARY_SYNC_MODES =\n new Set<ManualFlashSyncMode>([\n \"front-curtain\",\n \"rear-curtain\"\n ]);\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be a non-empty string.\"\n );\n }\n return value.trim();\n}\n\nfunction requireFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be finite.\"\n );\n }\n return value;\n}\n\nfunction requirePositiveFinite(\n value: unknown,\n path: string\n): number {\n const parsed =\n requireFinite(value, path);\n if (parsed <= 0) {\n throw new InvalidConfigurationError(\n path +\n \" must be greater than zero.\"\n );\n }\n return parsed;\n}\n\nfunction parseLimitations(\n value: unknown,\n path: string\n): readonly string[] {\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(\n path + \" must be an array.\"\n );\n }\n const parsed =\n value.map((entry, index) =>\n requireNonEmptyString(\n entry,\n path +\n \"[\" +\n index +\n \"]\"\n )\n );\n if (\n new Set(parsed).size !==\n parsed.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must not contain duplicates.\"\n );\n }\n return parsed;\n}\n\nfunction parsePulseSamples(\n value: unknown,\n supportDurationSeconds:\n number,\n path: string\n): readonly SceneIlluminationTemporalWaveformSample[] {\n if (\n !Array.isArray(value) ||\n value.length < 2\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must contain at least two waveform samples.\"\n );\n }\n const samples =\n value.map((entry, index) => {\n const samplePath =\n path +\n \"[\" +\n index +\n \"]\";\n const record =\n requireRecord(\n entry,\n samplePath, [\"timeSecondsFromWaveformReference\", \"relativeMagnitudeMultiplier\"]\n );\n const time =\n requireFinite(\n record\n .timeSecondsFromWaveformReference,\n samplePath +\n \".timeSecondsFromWaveformReference\"\n );\n const magnitude =\n requireFinite(\n record\n .relativeMagnitudeMultiplier,\n samplePath +\n \".relativeMagnitudeMultiplier\"\n );\n if (\n time < 0 ||\n time >\n supportDurationSeconds\n ) {\n throw new InvalidConfigurationError(\n samplePath +\n \".timeSecondsFromWaveformReference must lie within the declared pulse support.\"\n );\n }\n if (magnitude < 0) {\n throw new InvalidConfigurationError(\n samplePath +\n \".relativeMagnitudeMultiplier must be nonnegative.\"\n );\n }\n return {\n timeSecondsFromWaveformReference:\n time,\n relativeMagnitudeMultiplier:\n magnitude\n };\n });\n\n for (\n let index = 1;\n index < samples.length;\n index += 1\n ) {\n if (\n !(\n samples[index]!\n .timeSecondsFromWaveformReference >\n samples[index - 1]!\n .timeSecondsFromWaveformReference\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \" times must be strictly increasing.\"\n );\n }\n }\n if (\n samples[0]!\n .timeSecondsFromWaveformReference !==\n 0 ||\n samples[\n samples.length - 1\n ]!\n .timeSecondsFromWaveformReference !==\n supportDurationSeconds\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must start at waveform time 0 and end exactly at supportDurationSeconds.\"\n );\n }\n const peak =\n Math.max(\n ...samples.map(\n (sample) =>\n sample\n .relativeMagnitudeMultiplier\n )\n );\n if (\n Math.abs(peak - 1) >\n 1e-12\n ) {\n throw new InvalidConfigurationError(\n path +\n \" peak relative magnitude must equal one for relative-peak-one normalization.\"\n );\n }\n\n return samples;\n}\n\nfunction validateSourceTemplate(\n sourceTemplate:\n ManualFlashProfile[\"sourceTemplate\"]\n): ManualFlashProfile[\"sourceTemplate\"] {\n requireInputObject(sourceTemplate, \"manualFlashProfile.sourceTemplate\");\n const probe =\n parseSceneIlluminationProfile({\n schemaVersion: \"0.1.0\",\n profileId:\n \"manual-flash-source-validation\",\n sceneId:\n \"manual-flash-source-validation\",\n evidence:\n sourceTemplate.evidence,\n sources: [{\n ...sourceTemplate,\n enabled: true,\n temporalBehavior: {\n kind:\n \"time-invariant\"\n }\n }],\n sceneRadianceCalculated:\n false,\n materialResponseApplied:\n false,\n visibilityEvaluated:\n false,\n indirectTransportEvaluated:\n false,\n fluorescenceModeled:\n false,\n volumetricTransportModeled:\n false,\n polarizationModeled:\n false\n });\n const source =\n probe.sources[0];\n if (source === undefined) {\n throw new InvalidConfigurationError(\n \"manualFlashProfile.sourceTemplate must produce one valid illumination source.\"\n );\n }\n return {\n sourceId:\n source.sourceId,\n family:\n source.family,\n geometry:\n source.geometry,\n magnitude:\n source.magnitude,\n spectrum:\n source.spectrum,\n evidence:\n source.evidence,\n ...(source.limitations ===\n undefined\n ? {}\n : {\n limitations:\n source.limitations\n })\n };\n}\n\n/**\n * Validates an untrusted declaration and returns the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected here.\n *\n * Manual flash is a relative light pulse added on top of the scene light, timed on the capture's\n * opening-reference clock. Ordinary front- or rear-curtain sync needs a real interval when the whole\n * frame is open at once. High-speed sync (HSS), TTL and flash metering are not handled here. Source\n * brightness, optical transport and sensor integration have their own contracts.\n * @param value - unknown. Untrusted input; TypeScript types alone are not validation.\n * @returns ManualFlashProfile. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function parseManualFlashProfile(\n value: unknown\n): ManualFlashProfile {\n const record =\n requireRecord(\n value,\n \"manualFlashProfile\", [\"schemaVersion\", \"pulse\", \"outputControl\", \"profileId\", \"profileVersion\", \"sourceTemplate\", \"evidence\", \"limitations\", \"ttlModeled\", \"highSpeedSyncModeled\", \"recycleBehaviorModeled\", \"redEyePreflashModeled\", \"modelingLightModeled\", \"afAssistModeled\"]\n );\n if (\n record.schemaVersion !==\n MANUAL_FLASH_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'manualFlashProfile.schemaVersion must be \"' +\n MANUAL_FLASH_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n for (\n const [key, expected] of [\n [\"ttlModeled\", false],\n [\"highSpeedSyncModeled\", false],\n [\"recycleBehaviorModeled\", false],\n [\"redEyePreflashModeled\", false],\n [\"modelingLightModeled\", false],\n [\"afAssistModeled\", false]\n ] as const\n ) {\n if (record[key] !== expected) {\n throw new InvalidConfigurationError(\n \"manualFlashProfile.\" +\n key +\n \" must be false in schema 0.1.0.\"\n );\n }\n }\n\n const pulse =\n requireRecord(\n record.pulse,\n \"manualFlashProfile.pulse\", [\"supportDurationSeconds\", \"scientificStatus\", \"interpolation\", \"normalization\", \"waveformId\", \"samples\", \"evidence\", \"limitations\"]\n );\n const supportDurationSeconds =\n requirePositiveFinite(\n pulse.supportDurationSeconds,\n \"manualFlashProfile.pulse.supportDurationSeconds\"\n );\n if (\n pulse.scientificStatus !==\n \"approximation\" ||\n pulse.interpolation !==\n \"piecewise-linear\" ||\n pulse.normalization !==\n \"relative-peak-one\"\n ) {\n throw new InvalidConfigurationError(\n \"manualFlashProfile.pulse scientificStatus/interpolation/normalization is invalid.\"\n );\n }\n\n const output =\n requireRecord(\n record.outputControl,\n \"manualFlashProfile.outputControl\", [\"kind\", \"flashExposureCompensationStops\", \"scale\"]\n );\n if (\n output.kind !==\n \"relative-linear-source-scale\" ||\n output\n .flashExposureCompensationStops !==\n 0\n ) {\n throw new InvalidConfigurationError(\n \"manualFlashProfile.outputControl must use relative-linear-source-scale with zero flash exposure compensation in the manual-only schema.\"\n );\n }\n\n return {\n schemaVersion:\n MANUAL_FLASH_PROFILE_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"manualFlashProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"manualFlashProfile.profileVersion\"\n ),\n sourceTemplate:\n validateSourceTemplate(\n record.sourceTemplate as\n ManualFlashProfile[\"sourceTemplate\"]\n ),\n pulse: {\n waveformId:\n requireNonEmptyString(\n pulse.waveformId,\n \"manualFlashProfile.pulse.waveformId\"\n ),\n scientificStatus:\n \"approximation\",\n supportDurationSeconds,\n interpolation:\n \"piecewise-linear\",\n samples:\n parsePulseSamples(\n pulse.samples,\n supportDurationSeconds,\n \"manualFlashProfile.pulse.samples\"\n ),\n normalization:\n \"relative-peak-one\",\n evidence:\n parseEvidenceList(\n pulse.evidence,\n \"manualFlashProfile.pulse.evidence\"\n ),\n limitations:\n parseLimitations(\n pulse.limitations,\n \"manualFlashProfile.pulse.limitations\"\n )\n },\n outputControl: {\n kind:\n \"relative-linear-source-scale\",\n scale:\n requirePositiveFinite(\n output.scale,\n \"manualFlashProfile.outputControl.scale\"\n ),\n flashExposureCompensationStops:\n 0\n },\n ttlModeled: false,\n highSpeedSyncModeled: false,\n recycleBehaviorModeled:\n false,\n redEyePreflashModeled:\n false,\n modelingLightModeled:\n false,\n afAssistModeled: false,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"manualFlashProfile.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"manualFlashProfile.limitations\"\n )\n };\n}\n\n/**\n * Validates an untrusted declaration and returns the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected here.\n *\n * Manual flash is a relative light pulse added on top of the scene light, timed on the capture's\n * opening-reference clock. Ordinary front- or rear-curtain sync needs a real interval when the whole\n * frame is open at once. High-speed sync (HSS), TTL and flash metering are not handled here. Source\n * brightness, optical transport and sensor integration have their own contracts.\n * @param value - unknown. Untrusted input; TypeScript types alone are not validation.\n * @returns FlashSyncCapabilityProfile. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function parseFlashSyncCapabilityProfile(\n value: unknown\n): FlashSyncCapabilityProfile {\n const record =\n requireRecord(\n value,\n \"flashSyncCapabilityProfile\", [\"schemaVersion\", \"highSpeedSyncSupported\", \"ordinarySyncRequiresWholeActiveFrameSimultaneouslyExposed\", \"highSpeedSync\", \"supportedOrdinarySyncModes\", \"profileId\", \"profileVersion\", \"captureModeId\", \"timingProfileId\", \"evidence\", \"limitations\"]\n );\n if (\n record.schemaVersion !==\n FLASH_SYNC_CAPABILITY_SCHEMA_VERSION &&\n record.schemaVersion !==\n FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'flashSyncCapabilityProfile.schemaVersion must be \"' +\n FLASH_SYNC_CAPABILITY_SCHEMA_VERSION +\n '\" or \"' +\n FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION +\n '\".'\n );\n }\n const hssSchema =\n record.schemaVersion ===\n FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION;\n if (\n (hssSchema\n ? typeof record.highSpeedSyncSupported !==\n \"boolean\"\n : record.highSpeedSyncSupported !==\n false) ||\n record\n .ordinarySyncRequiresWholeActiveFrameSimultaneouslyExposed !==\n true\n ) {\n throw new InvalidConfigurationError(\n \"flashSyncCapabilityProfile schema 0.1.0 supports ordinary whole-frame sync only and must not claim HSS.\"\n );\n }\n let highSpeedSync:\n FlashSyncCapabilityProfile[\"highSpeedSync\"];\n if (record.highSpeedSyncSupported === true) {\n const hss = requireRecord(\n record.highSpeedSync,\n \"flashSyncCapabilityProfile.highSpeedSync\", [\"burstEnergyFractionOfFullPulse\", \"evidence\"]\n );\n const fraction = requirePositiveFinite(\n hss.burstEnergyFractionOfFullPulse,\n \"flashSyncCapabilityProfile.highSpeedSync.burstEnergyFractionOfFullPulse\"\n );\n if (fraction > 1) {\n throw new InvalidConfigurationError(\n \"flashSyncCapabilityProfile.highSpeedSync.burstEnergyFractionOfFullPulse must be at most 1.\"\n );\n }\n highSpeedSync = {\n burstEnergyFractionOfFullPulse:\n fraction,\n evidence: parseEvidenceList(\n hss.evidence,\n \"flashSyncCapabilityProfile.highSpeedSync.evidence\"\n )\n };\n } else if (\n record.highSpeedSync !==\n undefined\n ) {\n throw new InvalidConfigurationError(\n \"flashSyncCapabilityProfile.highSpeedSync must be omitted when HSS is unsupported.\"\n );\n }\n if (\n !Array.isArray(\n record.supportedOrdinarySyncModes\n ) ||\n record\n .supportedOrdinarySyncModes\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"flashSyncCapabilityProfile.supportedOrdinarySyncModes must be a non-empty array.\"\n );\n }\n const modes =\n record\n .supportedOrdinarySyncModes\n .map((entry, index) => {\n if (\n typeof entry !==\n \"string\" ||\n !ORDINARY_SYNC_MODES.has(\n entry as ManualFlashSyncMode\n )\n ) {\n throw new InvalidConfigurationError(\n \"flashSyncCapabilityProfile.supportedOrdinarySyncModes[\" +\n index +\n \"] is invalid.\"\n );\n }\n return entry as\n ManualFlashSyncMode;\n });\n if (\n new Set(modes).size !==\n modes.length\n ) {\n throw new InvalidConfigurationError(\n \"flashSyncCapabilityProfile.supportedOrdinarySyncModes must not contain duplicates.\"\n );\n }\n\n return {\n schemaVersion: hssSchema\n ? FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION\n : FLASH_SYNC_CAPABILITY_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"flashSyncCapabilityProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"flashSyncCapabilityProfile.profileVersion\"\n ),\n captureModeId:\n requireNonEmptyString(\n record.captureModeId,\n \"flashSyncCapabilityProfile.captureModeId\"\n ),\n timingProfileId:\n requireNonEmptyString(\n record.timingProfileId,\n \"flashSyncCapabilityProfile.timingProfileId\"\n ),\n supportedOrdinarySyncModes:\n modes,\n highSpeedSyncSupported:\n highSpeedSync !== undefined,\n ...(highSpeedSync === undefined\n ? {}\n : { highSpeedSync }),\n ordinarySyncRequiresWholeActiveFrameSimultaneouslyExposed:\n true,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"flashSyncCapabilityProfile.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"flashSyncCapabilityProfile.limitations\"\n )\n };\n}\n\n/**\n * Shape guard for the resolved capture-mode timing record read by the flash sync functions: every\n * nested object read below must be an object, so a malformed record fails with\n * InvalidConfigurationError instead of a raw TypeError. Values are checked where they are used.\n */\nfunction requireTimingRecordShape(timing: unknown, path: string): void {\n requireInputObject(timing, path);\n const record = timing as Record<string, unknown>;\n if (!Array.isArray(record.evidence)) throw new InvalidConfigurationError(path + \".evidence must be an array.\");\n requireInputObject(record.exposureWindows, path + \".exposureWindows\");\n const windows = record.exposureWindows as Record<string, unknown>;\n requireInputObject(windows.nominalExposureDurationSeconds, path + \".exposureWindows.nominalExposureDurationSeconds\");\n requireInputObject(windows.localExposureDurationRangeSeconds, path + \".exposureWindows.localExposureDurationRangeSeconds\");\n for (const boundary of [\"opening\", \"closing\"] as const) {\n requireInputObject(windows[boundary], path + \".exposureWindows.\" + boundary);\n const schedule = (windows[boundary] as Record<string, unknown>).schedule;\n requireInputObject(schedule, path + \".exposureWindows.\" + boundary + \".schedule\");\n if ((schedule as Record<string, unknown>).kind !== \"simultaneous\") {\n requireInputObject((schedule as Record<string, unknown>).traversalDurationSeconds, path + \".exposureWindows.\" + boundary + \".schedule.traversalDurationSeconds\");\n }\n }\n}\n\nfunction wholeFrameOpenInterval(\n timing:\n ResolvedCaptureModeTiming\n): {\n startSecondsFromCaptureReference:\n number;\n endSecondsFromCaptureReference:\n number;\n durationSeconds: number;\n} {\n const opening =\n timing.exposureWindows.opening\n .schedule;\n const latestOpening =\n opening.kind ===\n \"simultaneous\"\n ? 0\n : opening\n .traversalDurationSeconds\n .value;\n const earliestClosing =\n timing.exposureWindows\n .nominalExposureDurationSeconds\n .value;\n const duration =\n earliestClosing -\n latestOpening;\n return {\n startSecondsFromCaptureReference:\n latestOpening,\n endSecondsFromCaptureReference:\n earliestClosing,\n durationSeconds:\n Math.max(0, duration)\n };\n}\n\nfunction validateReleaseBinding(\n release:\n ResolvedReleaseFrame,\n timing:\n ResolvedCaptureModeTiming\n): void {\n requireInputObject(release, \"releaseFrame\");\n requireInputObject(release.exposure, \"releaseFrame.exposure\");\n const nominal =\n timing.exposureWindows\n .nominalExposureDurationSeconds\n .value;\n const scale =\n Math.max(\n 1,\n Math.abs(nominal),\n Math.abs(\n release.exposure\n .shutterSeconds\n )\n );\n if (\n Math.abs(\n release.exposure\n .shutterSeconds -\n nominal\n ) >\n Number.EPSILON *\n 16 *\n scale\n ) {\n throw new InvalidScientificInputError(\n \"releaseFrame shutter duration must match the exposure duration of the capture-mode exposure-window timing.\"\n );\n }\n}\n\n/**\n * Places a declared ordinary flash pulse inside the actual interval when the whole frame is open, for\n * front- or rear-curtain sync. Otherwise returns a structured incompatibility.\n *\n * Manual flash is a relative light pulse added on top of the scene light, timed on the capture's\n * opening-reference clock. Ordinary front- or rear-curtain sync needs a real interval when the whole\n * frame is open at once. High-speed sync (HSS), TTL and flash metering are not handled here. Source\n * brightness, optical transport and sensor integration have their own contracts.\n * @param input - ResolveManualFlashSyncInput. See that type for coordinates, units and profile binding.\n * @returns ResolvedManualFlashSync. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function resolveManualFlashSync(\n input:\n ResolveManualFlashSyncInput\n): ResolvedManualFlashSync {\n requireInputKeys(input, \"resolveManualFlashSync\", [\"flashEnabled\", \"flashProfile\", \"syncCapabilities\", \"timing\", \"syncMode\", \"releaseFrame\"]);\n requireTimingRecordShape(input.timing, \"resolveManualFlashSync timing\");\n const flash =\n parseManualFlashProfile(\n input.flashProfile\n );\n const capabilities =\n parseFlashSyncCapabilityProfile(\n input.syncCapabilities\n );\n\n if (\n capabilities.captureModeId !==\n input.timing.captureModeId ||\n capabilities.timingProfileId !==\n input.timing.timingProfileId\n ) {\n throw new InvalidScientificInputError(\n \"Flash sync capability profile must exactly match the resolved capture-mode and timing-profile identities.\"\n );\n }\n if (\n input.releaseFrame !==\n undefined\n ) {\n validateReleaseBinding(\n input.releaseFrame,\n input.timing\n );\n }\n\n const openInterval =\n wholeFrameOpenInterval(\n input.timing\n );\n const base = {\n flashProfileId:\n flash.profileId,\n flashProfileVersion:\n flash.profileVersion,\n sourceId:\n flash.sourceTemplate.sourceId,\n captureModeId:\n input.timing.captureModeId,\n timingProfileId:\n input.timing.timingProfileId,\n syncCapabilityProfileId:\n capabilities.profileId,\n syncMode:\n input.syncMode,\n timeReference:\n \"first-opening-boundary-phase\" as const,\n wholeActiveFrameOpenInterval:\n openInterval,\n pulseSupportDurationSeconds:\n flash.pulse\n .supportDurationSeconds,\n hssModeled: false as const,\n ttlModeled: false as const,\n sensorReadoutTimingUsedAsExposureTiming:\n false as const,\n whiteBalanceModified:\n false as const,\n focusModified: false as const,\n exposureSettingsModified:\n false as const,\n driveModeModified:\n false as const,\n supportStateModified:\n false as const,\n evidence: [\n ...flash.evidence,\n ...capabilities.evidence,\n ...input.timing.evidence\n ],\n limitations: [\n ...flash.limitations,\n ...capabilities.limitations,\n \"Ordinary flash synchronization is registered to exposure-boundary timing, never sensor data-readout timing.\",\n \"Schema 0.1.0 does not model HSS, TTL/preflash metering, recycle/thermal limits, red-eye preflash, modeling lights, AF-assist or branded flash protocols.\"\n ]\n };\n\n if (!input.flashEnabled) {\n return {\n flashEnabled: false,\n ...base,\n syncStatus:\n \"disabled\",\n pulseStartSecondsFromCaptureReference:\n null,\n pulseEndSecondsFromCaptureReference:\n null,\n waveformTimeZeroSecondsFromCaptureReference:\n null,\n releaseFrameBinding:\n null\n };\n }\n\n if (\n input.syncMode ===\n \"high-speed-sync\"\n ) {\n throw new InvalidScientificInputError(\n \"High-speed sync is not an ordinary sync mode; ordinary single-pulse flash cannot be used as an HSS substitute. Use resolveHighSpeedFlashSync with an HSS-capable sync profile.\"\n );\n }\n if (\n !capabilities\n .supportedOrdinarySyncModes\n .includes(\n input.syncMode\n )\n ) {\n throw new InvalidScientificInputError(\n \"Requested ordinary flash sync mode is not supported by the capability profile.\"\n );\n }\n if (\n openInterval.durationSeconds <=\n 0\n ) {\n throw new InvalidScientificInputError(\n \"Ordinary one-pulse flash cannot uniformly expose the active frame because the exposure-window timing has no whole-frame-open interval.\"\n );\n }\n if (\n flash.pulse\n .supportDurationSeconds >\n openInterval.durationSeconds\n ) {\n throw new InvalidScientificInputError(\n \"Ordinary flash pulse support does not fit inside the whole-active-frame-open interval.\"\n );\n }\n\n const pulseStart =\n input.syncMode ===\n \"front-curtain\"\n ? openInterval\n .startSecondsFromCaptureReference\n : openInterval\n .endSecondsFromCaptureReference -\n flash.pulse\n .supportDurationSeconds;\n const pulseEnd =\n pulseStart +\n flash.pulse\n .supportDurationSeconds;\n\n const releaseBinding =\n input.releaseFrame ===\n undefined\n ? null\n : {\n sequenceId:\n input.releaseFrame\n .sequenceId,\n releaseFrameId:\n input.releaseFrame\n .releaseFrameId,\n frameIndex:\n input.releaseFrame\n .frameIndex,\n sceneTimeSecondsFromSequenceStartAtPulseStart:\n input.releaseFrame\n .sceneTimeSecondsFromSequenceStart +\n pulseStart,\n sceneTimeSecondsFromSequenceStartAtPulseEnd:\n input.releaseFrame\n .sceneTimeSecondsFromSequenceStart +\n pulseEnd\n };\n\n return {\n flashEnabled: true,\n ...base,\n syncStatus:\n \"ordinary-sync-resolved\",\n pulseStartSecondsFromCaptureReference:\n pulseStart,\n pulseEndSecondsFromCaptureReference:\n pulseEnd,\n waveformTimeZeroSecondsFromCaptureReference:\n pulseStart,\n releaseFrameBinding:\n releaseBinding\n };\n}\n\nfunction scaledFlashSource(\n flash:\n ManualFlashProfile\n): SceneIlluminationSource {\n const template =\n flash.sourceTemplate;\n const magnitude =\n template.magnitude;\n if (\n magnitude.kind !==\n \"relative-linear-scale\"\n ) {\n throw new InvalidScientificInputError(\n \"Manual flash schema 0.1.0 relative output control requires a relative-linear-scale illumination source magnitude; calibrated physical flash energy belongs to a later profile.\"\n );\n }\n\n return {\n ...template,\n magnitude: {\n ...magnitude,\n scale:\n magnitude.scale *\n flash.outputControl.scale\n },\n enabled: true,\n temporalBehavior: {\n kind:\n \"time-invariant\"\n }\n };\n}\n\n/**\n * Builds a temporal illumination overlay from the resolved manual pulse. The identity of the base\n * ambient light source is kept.\n *\n * Manual flash is a relative light pulse added on top of the scene light, timed on the capture's\n * opening-reference clock. Ordinary front- or rear-curtain sync needs a real interval when the whole\n * frame is open at once. High-speed sync (HSS), TTL and flash metering are not handled here. Source\n * brightness, optical transport and sensor integration have their own contracts.\n * @param input - CreateManualFlashIlluminationOverlayInput. See that type for coordinates, units and profile binding.\n * @returns ManualFlashIlluminationOverlay. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function createManualFlashIlluminationOverlay(\n input:\n CreateManualFlashIlluminationOverlayInput\n): ManualFlashIlluminationOverlay {\n requireInputKeys(input, \"createManualFlashIlluminationOverlay\", [\"baseIlluminationProfile\", \"baseTemporalProfile\", \"flashProfile\", \"resolvedSync\", \"illuminationProfileId\", \"temporalProfileId\"]);\n const base =\n parseSceneIlluminationProfile(\n input\n .baseIlluminationProfile\n );\n const baseTemporal =\n input.baseTemporalProfile ===\n undefined\n ? null\n : parseSceneIlluminationTemporalProfile(\n input.baseTemporalProfile\n );\n if (\n baseTemporal !== null &&\n (\n baseTemporal.sceneId !==\n base.sceneId ||\n baseTemporal\n .illuminationProfileId !==\n base.profileId\n )\n ) {\n throw new InvalidScientificInputError(\n \"baseTemporalProfile must exactly match the base illumination profile scene/profile identities.\"\n );\n }\n\n const flash =\n parseManualFlashProfile(\n input.flashProfile\n );\n const sync =\n input.resolvedSync;\n requireInputObject(sync, \"createManualFlashIlluminationOverlay resolvedSync\");\n if (!Array.isArray(sync.evidence)) throw new InvalidConfigurationError(\"createManualFlashIlluminationOverlay resolvedSync.evidence must be an array.\");\n\n if (\n sync.flashProfileId !==\n flash.profileId ||\n sync.flashProfileVersion !==\n flash.profileVersion ||\n sync.sourceId !==\n flash.sourceTemplate.sourceId\n ) {\n throw new InvalidScientificInputError(\n \"Resolved flash sync identity must match the manual flash profile.\"\n );\n }\n if (\n base.sources.some(\n (source) =>\n source.sourceId ===\n flash.sourceTemplate\n .sourceId\n )\n ) {\n throw new InvalidScientificInputError(\n \"Flash sourceId must be unique within the base illumination profile.\"\n );\n }\n\n if (!sync.flashEnabled) {\n return {\n flashApplied: false,\n illuminationProfile:\n base,\n temporalProfile:\n baseTemporal,\n sourceId:\n flash.sourceTemplate\n .sourceId,\n waveformId:\n flash.pulse.waveformId,\n timeReference:\n \"first-opening-boundary-phase\",\n sourceMagnitudeAppliedBySceneTransport:\n true,\n materialTransportOwnedBySceneRadiance:\n true,\n visibilityOwnedBySceneRadiance:\n true,\n indirectTransportOwnedBySceneRadiance:\n true,\n postRenderBrightnessMultiplierUsed:\n false,\n whiteBalanceModified:\n false,\n ambientMeteringModified:\n false,\n ambientTemporalBehaviorPreserved:\n true,\n ttlMeteringIncluded:\n false\n };\n }\n if (\n sync\n .waveformTimeZeroSecondsFromCaptureReference ===\n null\n ) {\n throw new InvalidScientificInputError(\n \"Enabled flash sync must provide an authoritative waveform time-zero registration.\"\n );\n }\n\n const flashSource =\n scaledFlashSource(\n flash\n );\n const illumination =\n parseSceneIlluminationProfile({\n ...base,\n profileId:\n requireNonEmptyString(\n input.illuminationProfileId,\n \"illuminationProfileId\"\n ),\n sources: [\n ...base.sources,\n flashSource\n ]\n });\n\n const temporal =\n parseSceneIlluminationTemporalProfile({\n schemaVersion: \"0.1.0\",\n profileId:\n requireNonEmptyString(\n input.temporalProfileId,\n \"temporalProfileId\"\n ),\n sceneId:\n illumination.sceneId,\n illuminationProfileId:\n illumination.profileId,\n evidence: [\n ...(baseTemporal?.evidence ?? []),\n ...flash.evidence,\n ...sync.evidence\n ],\n waveforms: [\n ...(baseTemporal?.waveforms ?? []),\n {\n waveformId:\n flash.pulse.waveformId,\n kind:\n \"aperiodic-relative-multiplier\",\n timeUnit: \"s\",\n scientificStatus:\n \"approximation\",\n uncertainty: {\n kind:\n \"not-quantified\",\n limitation:\n \"Manual flash pulse timing/shape is an explicit approximation.\"\n },\n evidence:\n flash.pulse.evidence,\n interpolation:\n \"piecewise-linear\",\n samples:\n flash.pulse.samples,\n outsideSupportBehavior:\n \"zero\"\n }\n ],\n sourceBindings: [\n ...(baseTemporal?.sourceBindings ?? []),\n {\n bindingId:\n flash.profileId +\n \":sync\",\n sourceId:\n flashSource.sourceId,\n waveformId:\n flash.pulse.waveformId,\n captureTimeReference:\n \"first-opening-boundary-phase\",\n waveformTimeZeroSecondsFromCaptureReference:\n sync\n .waveformTimeZeroSecondsFromCaptureReference,\n scientificStatus:\n \"approximation\",\n timingUncertainty: {\n kind:\n \"not-quantified\",\n limitation:\n \"Schema 0.1.0 uses ideal deterministic flash trigger registration within the declared exposure-window schedule.\"\n },\n evidence:\n sync.evidence\n }\n ],\n baseIlluminationProfileRemainsAuthoritative:\n true,\n sensorReadoutTimingUsedAsExposureTiming:\n false,\n automaticExposurePolicyIncluded:\n false\n });\n\n return {\n flashApplied: true,\n illuminationProfile:\n illumination,\n temporalProfile:\n temporal,\n sourceId:\n flashSource.sourceId,\n waveformId:\n flash.pulse.waveformId,\n timeReference:\n \"first-opening-boundary-phase\",\n sourceMagnitudeAppliedBySceneTransport:\n true,\n materialTransportOwnedBySceneRadiance:\n true,\n visibilityOwnedBySceneRadiance:\n true,\n indirectTransportOwnedBySceneRadiance:\n true,\n postRenderBrightnessMultiplierUsed:\n false,\n whiteBalanceModified:\n false,\n ambientMeteringModified:\n false,\n ambientTemporalBehaviorPreserved:\n true,\n ttlMeteringIncluded:\n false\n };\n}\n\nexport interface ResolveHighSpeedFlashSyncInput {\n flashEnabled: boolean;\n /** Ordinary full-power pulse definition; its integral defines the full-power pulse energy. */\n flashProfile: ManualFlashProfile;\n /** Schema 0.2.0 profile with highSpeedSyncSupported true. */\n syncCapabilities: FlashSyncCapabilityProfile;\n timing: ResolvedCaptureModeTiming;\n /** Commanded output as a fraction of full power, (0, 1]. */\n powerFraction: number;\n releaseFrame?: ResolvedReleaseFrame;\n}\n\nexport interface ResolvedHighSpeedFlashSync extends FlashOverlaySyncRegistration {\n modelId: typeof HIGH_SPEED_SYNC_MODEL.id;\n modelVersion: typeof HIGH_SPEED_SYNC_MODEL.version;\n syncMode: \"high-speed-sync\";\n syncStatus: \"disabled\" | \"high-speed-sync-resolved\";\n captureModeId: string;\n timingProfileId: string;\n syncCapabilityProfileId: string;\n timeReference: \"first-opening-boundary-phase\";\n powerFraction: number;\n /** η from the sync capability profile. */\n burstEnergyFractionOfFullPulse: number;\n /** ∫ pulse(t) dt of the declared ordinary pulse, whose relative peak is 1 (relative multiplier · s). */\n singlePulseIntegratedRelativeSeconds: number;\n /** D: burst support covering the first line opening to the last line closing. */\n burstStartSecondsFromCaptureReference: number;\n burstEndSecondsFromCaptureReference: number;\n burstDurationSeconds: number;\n /** Local (slit) exposure durations t_e over the active frame. */\n localExposureDurationRangeSeconds: { minimum: number; maximum: number };\n /** Flash energy each line receives relative to one ordinary pulse at the same power: η·t_e/D. */\n energyFractionOfSinglePulseRange: { minimum: number; maximum: number };\n /** Effective guide-number factor relative to the same-power ordinary pulse: √(η·t_e/D). */\n guideNumberFactorRange: { minimum: number; maximum: number };\n uniformAcrossActiveFrame: boolean;\n /** The rectangular high-speed-sync burst, written as a manual pulse profile for the illumination overlay. */\n burstFlashProfile: ManualFlashProfile | null;\n releaseFrameBinding:\n | {\n sequenceId: string;\n releaseFrameId: string;\n frameIndex: number;\n sceneTimeSecondsFromSequenceStartAtBurstStart: number;\n sceneTimeSecondsFromSequenceStartAtBurstEnd: number;\n }\n | null;\n hssModeled: true;\n ttlModeled: false;\n sensorReadoutTimingUsedAsExposureTiming: false;\n limitations: readonly string[];\n}\n\nfunction integratePulse(samples: readonly SceneIlluminationTemporalWaveformSample[]): number {\n let area = 0;\n for (let index = 1; index < samples.length; index += 1) {\n const a = samples[index - 1]!, b = samples[index]!;\n area += (b.timeSecondsFromWaveformReference - a.timeSecondsFromWaveformReference) *\n (a.relativeMagnitudeMultiplier + b.relativeMagnitudeMultiplier) / 2;\n }\n return area;\n}\n\n/**\n * Resolves high-speed (focal-plane) sync (HSS): a fast pulse train that acts as continuous light and\n * covers the whole travelling-slit exposure.\n *\n * At shutter speeds faster than the ordinary sync limit, the shutter's opening and closing edges\n * cross the frame as a slit, and the whole frame is never open at once. A single short pulse would\n * light only a band.\n *\n * HSS instead fires a rapid pulse train. It behaves like constant output P over the burst D, from\n * the first line opening to the last line closing. Each line collects P·t_e over its slit time t_e.\n * - The burst energy is E_burst = η·p·E_pulse. η comes from the sync profile, p is the power\n * fraction and E_pulse is the energy of an ordinary full-power pulse.\n * - So P = E_burst/D, and each line receives η·p·E_pulse·t_e/D.\n * - Exposure ∝ GN² (inverse-square law, GN = d·N). So, relative to an ordinary pulse at the same\n * power, the effective guide number is GN_HSS/GN = √(η·t_e/D).\n * Shortening t_e by one stop therefore costs half a stop of guide number.\n *\n * Approximations: the pulse train is treated as continuous (pulse period ≪ t_e). Recycle and thermal\n * limits are folded into η. Front/rear-curtain placement does not apply, because the burst covers\n * the whole exposure.\n * @see docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md#high-speed-sync\n */\nexport function resolveHighSpeedFlashSync(input: ResolveHighSpeedFlashSyncInput): ResolvedHighSpeedFlashSync {\n requireInputKeys(input, \"resolveHighSpeedFlashSync\", [\"flashEnabled\", \"flashProfile\", \"syncCapabilities\", \"timing\", \"powerFraction\", \"releaseFrame\"]);\n requireTimingRecordShape(input.timing, \"resolveHighSpeedFlashSync timing\");\n const flash = parseManualFlashProfile(input.flashProfile);\n const capabilities = parseFlashSyncCapabilityProfile(input.syncCapabilities);\n if (capabilities.captureModeId !== input.timing.captureModeId || capabilities.timingProfileId !== input.timing.timingProfileId) {\n throw new InvalidScientificInputError(\n \"Flash sync capability profile must exactly match the resolved capture-mode and timing-profile identities.\"\n );\n }\n if (!capabilities.highSpeedSyncSupported || capabilities.highSpeedSync === undefined) {\n throw new InvalidScientificInputError(\"The flash sync capability profile does not declare high-speed sync.\");\n }\n const power = input.powerFraction;\n if (typeof power !== \"number\" || !Number.isFinite(power) || power <= 0 || power > 1) {\n throw new InvalidScientificInputError(\"HSS powerFraction must lie in (0, 1].\");\n }\n if (input.releaseFrame !== undefined) validateReleaseBinding(input.releaseFrame, input.timing);\n\n const windows = input.timing.exposureWindows;\n const closing = windows.closing.schedule;\n const burstEnd = windows.nominalExposureDurationSeconds.value +\n (closing.kind === \"simultaneous\" ? 0 : closing.traversalDurationSeconds.value);\n const eta = capabilities.highSpeedSync.burstEnergyFractionOfFullPulse;\n const local = windows.localExposureDurationRangeSeconds;\n const fraction = { minimum: eta * local.minimum / burstEnd, maximum: eta * local.maximum / burstEnd };\n const pulseEnergy = integratePulse(flash.pulse.samples);\n const burstFlashProfile: ManualFlashProfile = {\n ...flash,\n pulse: {\n ...flash.pulse,\n waveformId: flash.pulse.waveformId + \"-hss-burst\",\n supportDurationSeconds: burstEnd,\n samples: [\n { timeSecondsFromWaveformReference: 0, relativeMagnitudeMultiplier: 1 },\n { timeSecondsFromWaveformReference: burstEnd, relativeMagnitudeMultiplier: 1 }\n ],\n limitations: [...flash.pulse.limitations,\n \"Quasi-continuous HSS burst: the pulse train is approximated by constant output over the burst support.\"]\n },\n outputControl: { ...flash.outputControl, scale: flash.outputControl.scale * power * eta * pulseEnergy / burstEnd }\n };\n const enabled = input.flashEnabled;\n return {\n modelId: HIGH_SPEED_SYNC_MODEL.id,\n modelVersion: HIGH_SPEED_SYNC_MODEL.version,\n flashEnabled: enabled,\n flashProfileId: flash.profileId,\n flashProfileVersion: flash.profileVersion,\n sourceId: flash.sourceTemplate.sourceId,\n syncMode: \"high-speed-sync\",\n syncStatus: enabled ? \"high-speed-sync-resolved\" : \"disabled\",\n captureModeId: input.timing.captureModeId,\n timingProfileId: input.timing.timingProfileId,\n syncCapabilityProfileId: capabilities.profileId,\n timeReference: \"first-opening-boundary-phase\",\n powerFraction: power,\n burstEnergyFractionOfFullPulse: eta,\n singlePulseIntegratedRelativeSeconds: pulseEnergy,\n burstStartSecondsFromCaptureReference: 0,\n burstEndSecondsFromCaptureReference: burstEnd,\n burstDurationSeconds: burstEnd,\n localExposureDurationRangeSeconds: { minimum: local.minimum, maximum: local.maximum },\n energyFractionOfSinglePulseRange: fraction,\n guideNumberFactorRange: { minimum: Math.sqrt(fraction.minimum), maximum: Math.sqrt(fraction.maximum) },\n uniformAcrossActiveFrame: local.minimum === local.maximum,\n burstFlashProfile: enabled ? burstFlashProfile : null,\n waveformTimeZeroSecondsFromCaptureReference: enabled ? 0 : null,\n releaseFrameBinding: !enabled || input.releaseFrame === undefined ? null : {\n sequenceId: input.releaseFrame.sequenceId,\n releaseFrameId: input.releaseFrame.releaseFrameId,\n frameIndex: input.releaseFrame.frameIndex,\n sceneTimeSecondsFromSequenceStartAtBurstStart: input.releaseFrame.sceneTimeSecondsFromSequenceStart,\n sceneTimeSecondsFromSequenceStartAtBurstEnd: input.releaseFrame.sceneTimeSecondsFromSequenceStart + burstEnd\n },\n hssModeled: true,\n ttlModeled: false,\n sensorReadoutTimingUsedAsExposureTiming: false,\n evidence: [...flash.evidence, ...capabilities.evidence, ...capabilities.highSpeedSync.evidence, ...input.timing.evidence],\n limitations: [\n ...flash.limitations,\n ...capabilities.limitations,\n \"HSS burst is registered to exposure-boundary timing (first line opening to last line closing), never sensor data-readout timing.\",\n \"Pulse-train ripple, recycle/thermal limits beyond the declared burst energy fraction and branded flash protocols are not modeled.\"\n ]\n };\n}\n\n/**\n * Registers a resolved high-speed-sync burst as a temporal illumination overlay: a rectangular\n * waveform over [0, D]. Each line then collects the burst over its own local exposure window.\n */\nexport function createHighSpeedSyncIlluminationOverlay(\n input: Omit<CreateManualFlashIlluminationOverlayInput, \"resolvedSync\"> & { resolvedSync: ResolvedHighSpeedFlashSync }\n): ManualFlashIlluminationOverlay {\n requireInputKeys(input, \"createHighSpeedSyncIlluminationOverlay\", [\"baseIlluminationProfile\", \"baseTemporalProfile\", \"flashProfile\", \"illuminationProfileId\", \"temporalProfileId\", \"resolvedSync\"]);\n requireInputObject(input.resolvedSync, \"createHighSpeedSyncIlluminationOverlay resolvedSync\");\n return createManualFlashIlluminationOverlay({ ...input,\n flashProfile: input.resolvedSync.burstFlashProfile ?? input.flashProfile });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"flash.js","sourceRoot":"","sources":["../../src/exposure/flash.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Manual flash and flash sync.\n *\n * The parsers validate untrusted input and return the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected.\n *\n * Manual flash is a relative light pulse added on top of the scene light, timed on the capture's\n * opening-reference clock.\n * - Ordinary front- or rear-curtain sync needs a real interval when the whole frame is open at once.\n * - High-speed sync (HSS; schema 0.2.0 sync profiles) is separate: a near-continuous burst that\n * covers the travelling shutter slit (resolveHighSpeedFlashSync).\n * - TTL pre-flash power and guide-number relations are in flash-ttl.ts.\n * Source brightness, optical transport and sensor integration have their own contracts.\n * @see docs/USAGE.md for the equations, units, coordinate conventions, known blockers and support\n * limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport type {\n ResolvedReleaseFrame\n} from \"../capture/release-sequence.js\";\nimport {\n parseSceneIlluminationProfile,\n type SceneIlluminationProfile,\n type SceneIlluminationSource\n} from \"../schema/illumination.js\";\nimport {\n parseSceneIlluminationTemporalProfile,\n type SceneIlluminationTemporalProfile,\n type SceneIlluminationTemporalWaveformSample\n} from \"../schema/illumination-temporal.js\";\nimport type {\n ResolvedCaptureModeTiming\n} from \"../sensor/capture-mode-timing.js\";\nimport { requireInputObject, requireInputKeys, rejectUnknownFields } from \"../core/record-validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const MANUAL_FLASH_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\nexport const FLASH_SYNC_CAPABILITY_SCHEMA_VERSION =\n \"0.1.0\" as const;\n/** Sync-capability schema that may declare high-speed sync (a fast pulse train that acts as continuous light). */\nexport const FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION =\n \"0.2.0\" as const;\n/** Model identity of the pulsed quasi-continuous high-speed-sync burst. */\nexport const HIGH_SPEED_SYNC_MODEL = /* @__PURE__ */ Object.freeze({\n id: \"flash-hss-quasi-continuous-burst\",\n version: \"1.0.0\"\n} as const);\n\nexport type ManualFlashSyncMode =\n | \"front-curtain\"\n | \"rear-curtain\";\n\nexport type RequestedFlashSyncMode =\n | ManualFlashSyncMode\n | \"high-speed-sync\";\n\nexport interface ManualFlashPulseProfile {\n waveformId: string;\n scientificStatus: \"approximation\";\n supportDurationSeconds: number;\n interpolation: \"piecewise-linear\";\n samples:\n readonly SceneIlluminationTemporalWaveformSample[];\n normalization:\n \"relative-peak-one\";\n evidence:\n readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface ManualFlashProfile {\n schemaVersion:\n typeof MANUAL_FLASH_PROFILE_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n sourceTemplate:\n Omit<\n SceneIlluminationSource,\n \"enabled\" |\n \"temporalBehavior\"\n >;\n pulse:\n ManualFlashPulseProfile;\n outputControl: {\n kind:\n \"relative-linear-source-scale\";\n scale: number;\n flashExposureCompensationStops:\n 0;\n };\n ttlModeled: false;\n highSpeedSyncModeled: false;\n recycleBehaviorModeled: false;\n redEyePreflashModeled: false;\n modelingLightModeled: false;\n afAssistModeled: false;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface FlashSyncCapabilityProfile {\n schemaVersion:\n | typeof FLASH_SYNC_CAPABILITY_SCHEMA_VERSION\n | typeof FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n captureModeId: string;\n timingProfileId: string;\n supportedOrdinarySyncModes:\n readonly ManualFlashSyncMode[];\n /** Schema 0.1.0 is always false; schema 0.2.0 may declare HSS with {@link highSpeedSync}. */\n highSpeedSyncSupported: boolean;\n /** Present exactly when highSpeedSyncSupported is true (schema 0.2.0). */\n highSpeedSync?: {\n /**\n * η: energy of one full-power high-speed-sync burst, as a fraction of one full-power ordinary\n * pulse, in (0, 1]. The caller declares it from evidence (capacitor and thermal limits). It is\n * never inferred.\n */\n burstEnergyFractionOfFullPulse: number;\n evidence: readonly EvidenceProvenance[];\n };\n ordinarySyncRequiresWholeActiveFrameSimultaneouslyExposed:\n true;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface ResolveManualFlashSyncInput {\n flashEnabled: boolean;\n flashProfile:\n ManualFlashProfile;\n syncCapabilities:\n FlashSyncCapabilityProfile;\n timing:\n ResolvedCaptureModeTiming;\n syncMode:\n RequestedFlashSyncMode;\n releaseFrame?:\n ResolvedReleaseFrame;\n}\n\nexport interface ResolvedManualFlashSync {\n flashEnabled: boolean;\n flashProfileId: string;\n flashProfileVersion: string;\n sourceId: string;\n captureModeId: string;\n timingProfileId: string;\n syncCapabilityProfileId:\n string;\n syncMode:\n RequestedFlashSyncMode;\n syncStatus:\n | \"disabled\"\n | \"ordinary-sync-resolved\";\n timeReference:\n \"first-opening-boundary-phase\";\n wholeActiveFrameOpenInterval:\n {\n startSecondsFromCaptureReference:\n number;\n endSecondsFromCaptureReference:\n number;\n durationSeconds: number;\n };\n pulseSupportDurationSeconds:\n number;\n pulseStartSecondsFromCaptureReference:\n number | null;\n pulseEndSecondsFromCaptureReference:\n number | null;\n waveformTimeZeroSecondsFromCaptureReference:\n number | null;\n releaseFrameBinding:\n | {\n sequenceId: string;\n releaseFrameId: string;\n frameIndex: number;\n sceneTimeSecondsFromSequenceStartAtPulseStart:\n number;\n sceneTimeSecondsFromSequenceStartAtPulseEnd:\n number;\n }\n | null;\n hssModeled: false;\n ttlModeled: false;\n sensorReadoutTimingUsedAsExposureTiming:\n false;\n whiteBalanceModified: false;\n focusModified: false;\n exposureSettingsModified: false;\n driveModeModified: false;\n supportStateModified: false;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\n/** Fields of a resolved sync (ordinary or HSS) needed to register a flash overlay. */\nexport type FlashOverlaySyncRegistration = Pick<\n ResolvedManualFlashSync,\n | \"flashEnabled\"\n | \"flashProfileId\"\n | \"flashProfileVersion\"\n | \"sourceId\"\n | \"waveformTimeZeroSecondsFromCaptureReference\"\n | \"evidence\"\n>;\n\nexport interface CreateManualFlashIlluminationOverlayInput {\n baseIlluminationProfile:\n SceneIlluminationProfile;\n baseTemporalProfile?:\n SceneIlluminationTemporalProfile;\n flashProfile:\n ManualFlashProfile;\n resolvedSync:\n FlashOverlaySyncRegistration;\n illuminationProfileId: string;\n temporalProfileId: string;\n}\n\nexport interface ManualFlashIlluminationOverlay {\n flashApplied: boolean;\n illuminationProfile:\n SceneIlluminationProfile;\n temporalProfile:\n SceneIlluminationTemporalProfile | null;\n sourceId: string;\n waveformId: string;\n timeReference:\n \"first-opening-boundary-phase\";\n sourceMagnitudeAppliedBySceneTransport:\n true;\n materialTransportOwnedBySceneRadiance:\n true;\n visibilityOwnedBySceneRadiance:\n true;\n indirectTransportOwnedBySceneRadiance:\n true;\n postRenderBrightnessMultiplierUsed:\n false;\n whiteBalanceModified: false;\n ambientMeteringModified: false;\n ttlMeteringIncluded: false;\n ambientTemporalBehaviorPreserved:\n true;\n}\n\nconst ORDINARY_SYNC_MODES =\n new Set<ManualFlashSyncMode>([\n \"front-curtain\",\n \"rear-curtain\"\n ]);\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be a non-empty string.\"\n );\n }\n return value.trim();\n}\n\nfunction requireFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be finite.\"\n );\n }\n return value;\n}\n\nfunction requirePositiveFinite(\n value: unknown,\n path: string\n): number {\n const parsed =\n requireFinite(value, path);\n if (parsed <= 0) {\n throw new InvalidConfigurationError(\n path +\n \" must be greater than zero.\"\n );\n }\n return parsed;\n}\n\nfunction parseLimitations(\n value: unknown,\n path: string\n): readonly string[] {\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(\n path + \" must be an array.\"\n );\n }\n const parsed =\n value.map((entry, index) =>\n requireNonEmptyString(\n entry,\n path +\n \"[\" +\n index +\n \"]\"\n )\n );\n if (\n new Set(parsed).size !==\n parsed.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must not contain duplicates.\"\n );\n }\n return parsed;\n}\n\nfunction parsePulseSamples(\n value: unknown,\n supportDurationSeconds:\n number,\n path: string\n): readonly SceneIlluminationTemporalWaveformSample[] {\n if (\n !Array.isArray(value) ||\n value.length < 2\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must contain at least two waveform samples.\"\n );\n }\n const samples =\n value.map((entry, index) => {\n const samplePath =\n path +\n \"[\" +\n index +\n \"]\";\n const record =\n requireRecord(\n entry,\n samplePath, [\"timeSecondsFromWaveformReference\", \"relativeMagnitudeMultiplier\"]\n );\n const time =\n requireFinite(\n record\n .timeSecondsFromWaveformReference,\n samplePath +\n \".timeSecondsFromWaveformReference\"\n );\n const magnitude =\n requireFinite(\n record\n .relativeMagnitudeMultiplier,\n samplePath +\n \".relativeMagnitudeMultiplier\"\n );\n if (\n time < 0 ||\n time >\n supportDurationSeconds\n ) {\n throw new InvalidConfigurationError(\n samplePath +\n \".timeSecondsFromWaveformReference must lie within the declared pulse support.\"\n );\n }\n if (magnitude < 0) {\n throw new InvalidConfigurationError(\n samplePath +\n \".relativeMagnitudeMultiplier must be nonnegative.\"\n );\n }\n return {\n timeSecondsFromWaveformReference:\n time,\n relativeMagnitudeMultiplier:\n magnitude\n };\n });\n\n for (\n let index = 1;\n index < samples.length;\n index += 1\n ) {\n if (\n !(\n samples[index]!\n .timeSecondsFromWaveformReference >\n samples[index - 1]!\n .timeSecondsFromWaveformReference\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \" times must be strictly increasing.\"\n );\n }\n }\n if (\n samples[0]!\n .timeSecondsFromWaveformReference !==\n 0 ||\n samples[\n samples.length - 1\n ]!\n .timeSecondsFromWaveformReference !==\n supportDurationSeconds\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must start at waveform time 0 and end exactly at supportDurationSeconds.\"\n );\n }\n const peak =\n Math.max(\n ...samples.map(\n (sample) =>\n sample\n .relativeMagnitudeMultiplier\n )\n );\n if (\n Math.abs(peak - 1) >\n 1e-12\n ) {\n throw new InvalidConfigurationError(\n path +\n \" peak relative magnitude must equal one for relative-peak-one normalization.\"\n );\n }\n\n return samples;\n}\n\nfunction validateSourceTemplate(\n sourceTemplate:\n ManualFlashProfile[\"sourceTemplate\"]\n): ManualFlashProfile[\"sourceTemplate\"] {\n requireInputObject(sourceTemplate, \"manualFlashProfile.sourceTemplate\");\n const probe =\n parseSceneIlluminationProfile({\n schemaVersion: \"0.1.0\",\n profileId:\n \"manual-flash-source-validation\",\n sceneId:\n \"manual-flash-source-validation\",\n evidence:\n sourceTemplate.evidence,\n sources: [{\n ...sourceTemplate,\n enabled: true,\n temporalBehavior: {\n kind:\n \"time-invariant\"\n }\n }],\n sceneRadianceCalculated:\n false,\n materialResponseApplied:\n false,\n visibilityEvaluated:\n false,\n indirectTransportEvaluated:\n false,\n fluorescenceModeled:\n false,\n volumetricTransportModeled:\n false,\n polarizationModeled:\n false\n });\n const source =\n probe.sources[0];\n if (source === undefined) {\n throw new InvalidConfigurationError(\n \"manualFlashProfile.sourceTemplate must produce one valid illumination source.\"\n );\n }\n return {\n sourceId:\n source.sourceId,\n family:\n source.family,\n geometry:\n source.geometry,\n magnitude:\n source.magnitude,\n spectrum:\n source.spectrum,\n evidence:\n source.evidence,\n ...(source.limitations ===\n undefined\n ? {}\n : {\n limitations:\n source.limitations\n })\n };\n}\n\n/**\n * Validates an untrusted declaration and returns the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected here.\n *\n * Manual flash is a relative light pulse added on top of the scene light, timed on the capture's\n * opening-reference clock. Ordinary front- or rear-curtain sync needs a real interval when the whole\n * frame is open at once. High-speed sync (HSS), TTL and flash metering are not handled here. Source\n * brightness, optical transport and sensor integration have their own contracts.\n * @param value - unknown. Untrusted input; TypeScript types alone are not validation.\n * @returns ManualFlashProfile. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function parseManualFlashProfile(\n value: unknown\n): ManualFlashProfile {\n const record =\n requireRecord(\n value,\n \"manualFlashProfile\", [\"schemaVersion\", \"pulse\", \"outputControl\", \"profileId\", \"profileVersion\", \"sourceTemplate\", \"evidence\", \"limitations\", \"ttlModeled\", \"highSpeedSyncModeled\", \"recycleBehaviorModeled\", \"redEyePreflashModeled\", \"modelingLightModeled\", \"afAssistModeled\"]\n );\n if (\n record.schemaVersion !==\n MANUAL_FLASH_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'manualFlashProfile.schemaVersion must be \"' +\n MANUAL_FLASH_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n for (\n const [key, expected] of [\n [\"ttlModeled\", false],\n [\"highSpeedSyncModeled\", false],\n [\"recycleBehaviorModeled\", false],\n [\"redEyePreflashModeled\", false],\n [\"modelingLightModeled\", false],\n [\"afAssistModeled\", false]\n ] as const\n ) {\n if (record[key] !== expected) {\n throw new InvalidConfigurationError(\n \"manualFlashProfile.\" +\n key +\n \" must be false in schema 0.1.0.\"\n );\n }\n }\n\n const pulse =\n requireRecord(\n record.pulse,\n \"manualFlashProfile.pulse\", [\"supportDurationSeconds\", \"scientificStatus\", \"interpolation\", \"normalization\", \"waveformId\", \"samples\", \"evidence\", \"limitations\"]\n );\n const supportDurationSeconds =\n requirePositiveFinite(\n pulse.supportDurationSeconds,\n \"manualFlashProfile.pulse.supportDurationSeconds\"\n );\n if (\n pulse.scientificStatus !==\n \"approximation\" ||\n pulse.interpolation !==\n \"piecewise-linear\" ||\n pulse.normalization !==\n \"relative-peak-one\"\n ) {\n throw new InvalidConfigurationError(\n \"manualFlashProfile.pulse scientificStatus/interpolation/normalization is invalid.\"\n );\n }\n\n const output =\n requireRecord(\n record.outputControl,\n \"manualFlashProfile.outputControl\", [\"kind\", \"flashExposureCompensationStops\", \"scale\"]\n );\n if (\n output.kind !==\n \"relative-linear-source-scale\" ||\n output\n .flashExposureCompensationStops !==\n 0\n ) {\n throw new InvalidConfigurationError(\n \"manualFlashProfile.outputControl must use relative-linear-source-scale with zero flash exposure compensation in the manual-only schema.\"\n );\n }\n\n return {\n schemaVersion:\n MANUAL_FLASH_PROFILE_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"manualFlashProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"manualFlashProfile.profileVersion\"\n ),\n sourceTemplate:\n validateSourceTemplate(\n record.sourceTemplate as\n ManualFlashProfile[\"sourceTemplate\"]\n ),\n pulse: {\n waveformId:\n requireNonEmptyString(\n pulse.waveformId,\n \"manualFlashProfile.pulse.waveformId\"\n ),\n scientificStatus:\n \"approximation\",\n supportDurationSeconds,\n interpolation:\n \"piecewise-linear\",\n samples:\n parsePulseSamples(\n pulse.samples,\n supportDurationSeconds,\n \"manualFlashProfile.pulse.samples\"\n ),\n normalization:\n \"relative-peak-one\",\n evidence:\n parseEvidenceList(\n pulse.evidence,\n \"manualFlashProfile.pulse.evidence\"\n ),\n limitations:\n parseLimitations(\n pulse.limitations,\n \"manualFlashProfile.pulse.limitations\"\n )\n },\n outputControl: {\n kind:\n \"relative-linear-source-scale\",\n scale:\n requirePositiveFinite(\n output.scale,\n \"manualFlashProfile.outputControl.scale\"\n ),\n flashExposureCompensationStops:\n 0\n },\n ttlModeled: false,\n highSpeedSyncModeled: false,\n recycleBehaviorModeled:\n false,\n redEyePreflashModeled:\n false,\n modelingLightModeled:\n false,\n afAssistModeled: false,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"manualFlashProfile.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"manualFlashProfile.limitations\"\n )\n };\n}\n\n/**\n * Validates an untrusted declaration and returns the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected here.\n *\n * Manual flash is a relative light pulse added on top of the scene light, timed on the capture's\n * opening-reference clock. Ordinary front- or rear-curtain sync needs a real interval when the whole\n * frame is open at once. High-speed sync (HSS), TTL and flash metering are not handled here. Source\n * brightness, optical transport and sensor integration have their own contracts.\n * @param value - unknown. Untrusted input; TypeScript types alone are not validation.\n * @returns FlashSyncCapabilityProfile. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function parseFlashSyncCapabilityProfile(\n value: unknown\n): FlashSyncCapabilityProfile {\n const record =\n requireRecord(\n value,\n \"flashSyncCapabilityProfile\", [\"schemaVersion\", \"highSpeedSyncSupported\", \"ordinarySyncRequiresWholeActiveFrameSimultaneouslyExposed\", \"highSpeedSync\", \"supportedOrdinarySyncModes\", \"profileId\", \"profileVersion\", \"captureModeId\", \"timingProfileId\", \"evidence\", \"limitations\"]\n );\n if (\n record.schemaVersion !==\n FLASH_SYNC_CAPABILITY_SCHEMA_VERSION &&\n record.schemaVersion !==\n FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'flashSyncCapabilityProfile.schemaVersion must be \"' +\n FLASH_SYNC_CAPABILITY_SCHEMA_VERSION +\n '\" or \"' +\n FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION +\n '\".'\n );\n }\n const hssSchema =\n record.schemaVersion ===\n FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION;\n if (\n (hssSchema\n ? typeof record.highSpeedSyncSupported !==\n \"boolean\"\n : record.highSpeedSyncSupported !==\n false) ||\n record\n .ordinarySyncRequiresWholeActiveFrameSimultaneouslyExposed !==\n true\n ) {\n throw new InvalidConfigurationError(\n \"flashSyncCapabilityProfile schema 0.1.0 supports ordinary whole-frame sync only and must not claim HSS.\"\n );\n }\n let highSpeedSync:\n FlashSyncCapabilityProfile[\"highSpeedSync\"];\n if (record.highSpeedSyncSupported === true) {\n const hss = requireRecord(\n record.highSpeedSync,\n \"flashSyncCapabilityProfile.highSpeedSync\", [\"burstEnergyFractionOfFullPulse\", \"evidence\"]\n );\n const fraction = requirePositiveFinite(\n hss.burstEnergyFractionOfFullPulse,\n \"flashSyncCapabilityProfile.highSpeedSync.burstEnergyFractionOfFullPulse\"\n );\n if (fraction > 1) {\n throw new InvalidConfigurationError(\n \"flashSyncCapabilityProfile.highSpeedSync.burstEnergyFractionOfFullPulse must be at most 1.\"\n );\n }\n highSpeedSync = {\n burstEnergyFractionOfFullPulse:\n fraction,\n evidence: parseEvidenceList(\n hss.evidence,\n \"flashSyncCapabilityProfile.highSpeedSync.evidence\"\n )\n };\n } else if (\n record.highSpeedSync !==\n undefined\n ) {\n throw new InvalidConfigurationError(\n \"flashSyncCapabilityProfile.highSpeedSync must be omitted when HSS is unsupported.\"\n );\n }\n if (\n !Array.isArray(\n record.supportedOrdinarySyncModes\n ) ||\n record\n .supportedOrdinarySyncModes\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"flashSyncCapabilityProfile.supportedOrdinarySyncModes must be a non-empty array.\"\n );\n }\n const modes =\n record\n .supportedOrdinarySyncModes\n .map((entry, index) => {\n if (\n typeof entry !==\n \"string\" ||\n !ORDINARY_SYNC_MODES.has(\n entry as ManualFlashSyncMode\n )\n ) {\n throw new InvalidConfigurationError(\n \"flashSyncCapabilityProfile.supportedOrdinarySyncModes[\" +\n index +\n \"] is invalid.\"\n );\n }\n return entry as\n ManualFlashSyncMode;\n });\n if (\n new Set(modes).size !==\n modes.length\n ) {\n throw new InvalidConfigurationError(\n \"flashSyncCapabilityProfile.supportedOrdinarySyncModes must not contain duplicates.\"\n );\n }\n\n return {\n schemaVersion: hssSchema\n ? FLASH_SYNC_CAPABILITY_HSS_SCHEMA_VERSION\n : FLASH_SYNC_CAPABILITY_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"flashSyncCapabilityProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"flashSyncCapabilityProfile.profileVersion\"\n ),\n captureModeId:\n requireNonEmptyString(\n record.captureModeId,\n \"flashSyncCapabilityProfile.captureModeId\"\n ),\n timingProfileId:\n requireNonEmptyString(\n record.timingProfileId,\n \"flashSyncCapabilityProfile.timingProfileId\"\n ),\n supportedOrdinarySyncModes:\n modes,\n highSpeedSyncSupported:\n highSpeedSync !== undefined,\n ...(highSpeedSync === undefined\n ? {}\n : { highSpeedSync }),\n ordinarySyncRequiresWholeActiveFrameSimultaneouslyExposed:\n true,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"flashSyncCapabilityProfile.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"flashSyncCapabilityProfile.limitations\"\n )\n };\n}\n\n/**\n * Shape guard for the resolved capture-mode timing record read by the flash sync functions: every\n * nested object read below must be an object, so a malformed record fails with\n * InvalidConfigurationError instead of a raw TypeError. Values are checked where they are used.\n */\nfunction requireTimingRecordShape(timing: unknown, path: string): void {\n requireInputObject(timing, path);\n const record = timing as Record<string, unknown>;\n if (!Array.isArray(record.evidence)) throw new InvalidConfigurationError(path + \".evidence must be an array.\");\n requireInputObject(record.exposureWindows, path + \".exposureWindows\");\n const windows = record.exposureWindows as Record<string, unknown>;\n requireInputObject(windows.nominalExposureDurationSeconds, path + \".exposureWindows.nominalExposureDurationSeconds\");\n requireInputObject(windows.localExposureDurationRangeSeconds, path + \".exposureWindows.localExposureDurationRangeSeconds\");\n for (const boundary of [\"opening\", \"closing\"] as const) {\n requireInputObject(windows[boundary], path + \".exposureWindows.\" + boundary);\n const schedule = (windows[boundary] as Record<string, unknown>).schedule;\n requireInputObject(schedule, path + \".exposureWindows.\" + boundary + \".schedule\");\n if ((schedule as Record<string, unknown>).kind !== \"simultaneous\") {\n requireInputObject((schedule as Record<string, unknown>).traversalDurationSeconds, path + \".exposureWindows.\" + boundary + \".schedule.traversalDurationSeconds\");\n }\n }\n}\n\nfunction wholeFrameOpenInterval(\n timing:\n ResolvedCaptureModeTiming\n): {\n startSecondsFromCaptureReference:\n number;\n endSecondsFromCaptureReference:\n number;\n durationSeconds: number;\n} {\n const opening =\n timing.exposureWindows.opening\n .schedule;\n const latestOpening =\n opening.kind ===\n \"simultaneous\"\n ? 0\n : opening\n .traversalDurationSeconds\n .value;\n const earliestClosing =\n timing.exposureWindows\n .nominalExposureDurationSeconds\n .value;\n const duration =\n earliestClosing -\n latestOpening;\n return {\n startSecondsFromCaptureReference:\n latestOpening,\n endSecondsFromCaptureReference:\n earliestClosing,\n durationSeconds:\n Math.max(0, duration)\n };\n}\n\nfunction validateReleaseBinding(\n release:\n ResolvedReleaseFrame,\n timing:\n ResolvedCaptureModeTiming\n): void {\n requireInputObject(release, \"releaseFrame\");\n requireInputObject(release.exposure, \"releaseFrame.exposure\");\n const nominal =\n timing.exposureWindows\n .nominalExposureDurationSeconds\n .value;\n const scale =\n Math.max(\n 1,\n Math.abs(nominal),\n Math.abs(\n release.exposure\n .shutterSeconds\n )\n );\n if (\n Math.abs(\n release.exposure\n .shutterSeconds -\n nominal\n ) >\n Number.EPSILON *\n 16 *\n scale\n ) {\n throw new InvalidScientificInputError(\n \"releaseFrame shutter duration must match the exposure duration of the capture-mode exposure-window timing.\"\n );\n }\n}\n\n/**\n * Places a declared ordinary flash pulse inside the actual interval when the whole frame is open, for\n * front- or rear-curtain sync. Otherwise returns a structured incompatibility.\n *\n * Manual flash is a relative light pulse added on top of the scene light, timed on the capture's\n * opening-reference clock. Ordinary front- or rear-curtain sync needs a real interval when the whole\n * frame is open at once. High-speed sync (HSS), TTL and flash metering are not handled here. Source\n * brightness, optical transport and sensor integration have their own contracts.\n * @param input - ResolveManualFlashSyncInput. See that type for coordinates, units and profile binding.\n * @returns ResolvedManualFlashSync. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function resolveManualFlashSync(\n input:\n ResolveManualFlashSyncInput\n): ResolvedManualFlashSync {\n requireInputKeys(input, \"resolveManualFlashSync\", [\"flashEnabled\", \"flashProfile\", \"syncCapabilities\", \"timing\", \"syncMode\", \"releaseFrame\"]);\n requireTimingRecordShape(input.timing, \"resolveManualFlashSync timing\");\n const flash =\n parseManualFlashProfile(\n input.flashProfile\n );\n const capabilities =\n parseFlashSyncCapabilityProfile(\n input.syncCapabilities\n );\n\n if (\n capabilities.captureModeId !==\n input.timing.captureModeId ||\n capabilities.timingProfileId !==\n input.timing.timingProfileId\n ) {\n throw new InvalidScientificInputError(\n \"Flash sync capability profile must exactly match the resolved capture-mode and timing-profile identities.\"\n );\n }\n if (\n input.releaseFrame !==\n undefined\n ) {\n validateReleaseBinding(\n input.releaseFrame,\n input.timing\n );\n }\n\n const openInterval =\n wholeFrameOpenInterval(\n input.timing\n );\n const base = {\n flashProfileId:\n flash.profileId,\n flashProfileVersion:\n flash.profileVersion,\n sourceId:\n flash.sourceTemplate.sourceId,\n captureModeId:\n input.timing.captureModeId,\n timingProfileId:\n input.timing.timingProfileId,\n syncCapabilityProfileId:\n capabilities.profileId,\n syncMode:\n input.syncMode,\n timeReference:\n \"first-opening-boundary-phase\" as const,\n wholeActiveFrameOpenInterval:\n openInterval,\n pulseSupportDurationSeconds:\n flash.pulse\n .supportDurationSeconds,\n hssModeled: false as const,\n ttlModeled: false as const,\n sensorReadoutTimingUsedAsExposureTiming:\n false as const,\n whiteBalanceModified:\n false as const,\n focusModified: false as const,\n exposureSettingsModified:\n false as const,\n driveModeModified:\n false as const,\n supportStateModified:\n false as const,\n evidence: [\n ...flash.evidence,\n ...capabilities.evidence,\n ...input.timing.evidence\n ],\n limitations: [\n ...flash.limitations,\n ...capabilities.limitations,\n \"Ordinary flash synchronization is registered to exposure-boundary timing, never sensor data-readout timing.\",\n \"Schema 0.1.0 does not model HSS, TTL/preflash metering, recycle/thermal limits, red-eye preflash, modeling lights, AF-assist or branded flash protocols.\"\n ]\n };\n\n if (!input.flashEnabled) {\n return {\n flashEnabled: false,\n ...base,\n syncStatus:\n \"disabled\",\n pulseStartSecondsFromCaptureReference:\n null,\n pulseEndSecondsFromCaptureReference:\n null,\n waveformTimeZeroSecondsFromCaptureReference:\n null,\n releaseFrameBinding:\n null\n };\n }\n\n if (\n input.syncMode ===\n \"high-speed-sync\"\n ) {\n throw new InvalidScientificInputError(\n \"High-speed sync is not an ordinary sync mode; ordinary single-pulse flash cannot be used as an HSS substitute. Use resolveHighSpeedFlashSync with an HSS-capable sync profile.\"\n );\n }\n if (\n !capabilities\n .supportedOrdinarySyncModes\n .includes(\n input.syncMode\n )\n ) {\n throw new InvalidScientificInputError(\n \"Requested ordinary flash sync mode is not supported by the capability profile.\"\n );\n }\n if (\n openInterval.durationSeconds <=\n 0\n ) {\n throw new InvalidScientificInputError(\n \"Ordinary one-pulse flash cannot uniformly expose the active frame because the exposure-window timing has no whole-frame-open interval.\"\n );\n }\n if (\n flash.pulse\n .supportDurationSeconds >\n openInterval.durationSeconds\n ) {\n throw new InvalidScientificInputError(\n \"Ordinary flash pulse support does not fit inside the whole-active-frame-open interval.\"\n );\n }\n\n const pulseStart =\n input.syncMode ===\n \"front-curtain\"\n ? openInterval\n .startSecondsFromCaptureReference\n : openInterval\n .endSecondsFromCaptureReference -\n flash.pulse\n .supportDurationSeconds;\n const pulseEnd =\n pulseStart +\n flash.pulse\n .supportDurationSeconds;\n\n const releaseBinding =\n input.releaseFrame ===\n undefined\n ? null\n : {\n sequenceId:\n input.releaseFrame\n .sequenceId,\n releaseFrameId:\n input.releaseFrame\n .releaseFrameId,\n frameIndex:\n input.releaseFrame\n .frameIndex,\n sceneTimeSecondsFromSequenceStartAtPulseStart:\n input.releaseFrame\n .sceneTimeSecondsFromSequenceStart +\n pulseStart,\n sceneTimeSecondsFromSequenceStartAtPulseEnd:\n input.releaseFrame\n .sceneTimeSecondsFromSequenceStart +\n pulseEnd\n };\n\n return {\n flashEnabled: true,\n ...base,\n syncStatus:\n \"ordinary-sync-resolved\",\n pulseStartSecondsFromCaptureReference:\n pulseStart,\n pulseEndSecondsFromCaptureReference:\n pulseEnd,\n waveformTimeZeroSecondsFromCaptureReference:\n pulseStart,\n releaseFrameBinding:\n releaseBinding\n };\n}\n\nfunction scaledFlashSource(\n flash:\n ManualFlashProfile\n): SceneIlluminationSource {\n const template =\n flash.sourceTemplate;\n const magnitude =\n template.magnitude;\n if (\n magnitude.kind !==\n \"relative-linear-scale\"\n ) {\n throw new InvalidScientificInputError(\n \"Manual flash schema 0.1.0 relative output control requires a relative-linear-scale illumination source magnitude; calibrated physical flash energy belongs to a later profile.\"\n );\n }\n\n return {\n ...template,\n magnitude: {\n ...magnitude,\n scale:\n magnitude.scale *\n flash.outputControl.scale\n },\n enabled: true,\n temporalBehavior: {\n kind:\n \"time-invariant\"\n }\n };\n}\n\n/**\n * Builds a temporal illumination overlay from the resolved manual pulse. The identity of the base\n * ambient light source is kept.\n *\n * Manual flash is a relative light pulse added on top of the scene light, timed on the capture's\n * opening-reference clock. Ordinary front- or rear-curtain sync needs a real interval when the whole\n * frame is open at once. High-speed sync (HSS), TTL and flash metering are not handled here. Source\n * brightness, optical transport and sensor integration have their own contracts.\n * @param input - CreateManualFlashIlluminationOverlayInput. See that type for coordinates, units and profile binding.\n * @returns ManualFlashIlluminationOverlay. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function createManualFlashIlluminationOverlay(\n input:\n CreateManualFlashIlluminationOverlayInput\n): ManualFlashIlluminationOverlay {\n requireInputKeys(input, \"createManualFlashIlluminationOverlay\", [\"baseIlluminationProfile\", \"baseTemporalProfile\", \"flashProfile\", \"resolvedSync\", \"illuminationProfileId\", \"temporalProfileId\"]);\n const base =\n parseSceneIlluminationProfile(\n input\n .baseIlluminationProfile\n );\n const baseTemporal =\n input.baseTemporalProfile ===\n undefined\n ? null\n : parseSceneIlluminationTemporalProfile(\n input.baseTemporalProfile\n );\n if (\n baseTemporal !== null &&\n (\n baseTemporal.sceneId !==\n base.sceneId ||\n baseTemporal\n .illuminationProfileId !==\n base.profileId\n )\n ) {\n throw new InvalidScientificInputError(\n \"baseTemporalProfile must exactly match the base illumination profile scene/profile identities.\"\n );\n }\n\n const flash =\n parseManualFlashProfile(\n input.flashProfile\n );\n const sync =\n input.resolvedSync;\n requireInputObject(sync, \"createManualFlashIlluminationOverlay resolvedSync\");\n if (!Array.isArray(sync.evidence)) throw new InvalidConfigurationError(\"createManualFlashIlluminationOverlay resolvedSync.evidence must be an array.\");\n\n if (\n sync.flashProfileId !==\n flash.profileId ||\n sync.flashProfileVersion !==\n flash.profileVersion ||\n sync.sourceId !==\n flash.sourceTemplate.sourceId\n ) {\n throw new InvalidScientificInputError(\n \"Resolved flash sync identity must match the manual flash profile.\"\n );\n }\n if (\n base.sources.some(\n (source) =>\n source.sourceId ===\n flash.sourceTemplate\n .sourceId\n )\n ) {\n throw new InvalidScientificInputError(\n \"Flash sourceId must be unique within the base illumination profile.\"\n );\n }\n\n if (!sync.flashEnabled) {\n return {\n flashApplied: false,\n illuminationProfile:\n base,\n temporalProfile:\n baseTemporal,\n sourceId:\n flash.sourceTemplate\n .sourceId,\n waveformId:\n flash.pulse.waveformId,\n timeReference:\n \"first-opening-boundary-phase\",\n sourceMagnitudeAppliedBySceneTransport:\n true,\n materialTransportOwnedBySceneRadiance:\n true,\n visibilityOwnedBySceneRadiance:\n true,\n indirectTransportOwnedBySceneRadiance:\n true,\n postRenderBrightnessMultiplierUsed:\n false,\n whiteBalanceModified:\n false,\n ambientMeteringModified:\n false,\n ambientTemporalBehaviorPreserved:\n true,\n ttlMeteringIncluded:\n false\n };\n }\n if (\n sync\n .waveformTimeZeroSecondsFromCaptureReference ===\n null\n ) {\n throw new InvalidScientificInputError(\n \"Enabled flash sync must provide an authoritative waveform time-zero registration.\"\n );\n }\n\n const flashSource =\n scaledFlashSource(\n flash\n );\n const illumination =\n parseSceneIlluminationProfile({\n ...base,\n profileId:\n requireNonEmptyString(\n input.illuminationProfileId,\n \"illuminationProfileId\"\n ),\n sources: [\n ...base.sources,\n flashSource\n ]\n });\n\n const temporal =\n parseSceneIlluminationTemporalProfile({\n schemaVersion: \"0.1.0\",\n profileId:\n requireNonEmptyString(\n input.temporalProfileId,\n \"temporalProfileId\"\n ),\n sceneId:\n illumination.sceneId,\n illuminationProfileId:\n illumination.profileId,\n evidence: [\n ...(baseTemporal?.evidence ?? []),\n ...flash.evidence,\n ...sync.evidence\n ],\n waveforms: [\n ...(baseTemporal?.waveforms ?? []),\n {\n waveformId:\n flash.pulse.waveformId,\n kind:\n \"aperiodic-relative-multiplier\",\n timeUnit: \"s\",\n scientificStatus:\n \"approximation\",\n uncertainty: {\n kind:\n \"not-quantified\",\n limitation:\n \"Manual flash pulse timing/shape is an explicit approximation.\"\n },\n evidence:\n flash.pulse.evidence,\n interpolation:\n \"piecewise-linear\",\n samples:\n flash.pulse.samples,\n outsideSupportBehavior:\n \"zero\"\n }\n ],\n sourceBindings: [\n ...(baseTemporal?.sourceBindings ?? []),\n {\n bindingId:\n flash.profileId +\n \":sync\",\n sourceId:\n flashSource.sourceId,\n waveformId:\n flash.pulse.waveformId,\n captureTimeReference:\n \"first-opening-boundary-phase\",\n waveformTimeZeroSecondsFromCaptureReference:\n sync\n .waveformTimeZeroSecondsFromCaptureReference,\n scientificStatus:\n \"approximation\",\n timingUncertainty: {\n kind:\n \"not-quantified\",\n limitation:\n \"Schema 0.1.0 uses ideal deterministic flash trigger registration within the declared exposure-window schedule.\"\n },\n evidence:\n sync.evidence\n }\n ],\n baseIlluminationProfileRemainsAuthoritative:\n true,\n sensorReadoutTimingUsedAsExposureTiming:\n false,\n automaticExposurePolicyIncluded:\n false\n });\n\n return {\n flashApplied: true,\n illuminationProfile:\n illumination,\n temporalProfile:\n temporal,\n sourceId:\n flashSource.sourceId,\n waveformId:\n flash.pulse.waveformId,\n timeReference:\n \"first-opening-boundary-phase\",\n sourceMagnitudeAppliedBySceneTransport:\n true,\n materialTransportOwnedBySceneRadiance:\n true,\n visibilityOwnedBySceneRadiance:\n true,\n indirectTransportOwnedBySceneRadiance:\n true,\n postRenderBrightnessMultiplierUsed:\n false,\n whiteBalanceModified:\n false,\n ambientMeteringModified:\n false,\n ambientTemporalBehaviorPreserved:\n true,\n ttlMeteringIncluded:\n false\n };\n}\n\nexport interface ResolveHighSpeedFlashSyncInput {\n flashEnabled: boolean;\n /** Ordinary full-power pulse definition; its integral defines the full-power pulse energy. */\n flashProfile: ManualFlashProfile;\n /** Schema 0.2.0 profile with highSpeedSyncSupported true. */\n syncCapabilities: FlashSyncCapabilityProfile;\n timing: ResolvedCaptureModeTiming;\n /** Commanded output as a fraction of full power, (0, 1]. */\n powerFraction: number;\n releaseFrame?: ResolvedReleaseFrame;\n}\n\nexport interface ResolvedHighSpeedFlashSync extends FlashOverlaySyncRegistration {\n modelId: typeof HIGH_SPEED_SYNC_MODEL.id;\n modelVersion: typeof HIGH_SPEED_SYNC_MODEL.version;\n syncMode: \"high-speed-sync\";\n syncStatus: \"disabled\" | \"high-speed-sync-resolved\";\n captureModeId: string;\n timingProfileId: string;\n syncCapabilityProfileId: string;\n timeReference: \"first-opening-boundary-phase\";\n powerFraction: number;\n /** η from the sync capability profile. */\n burstEnergyFractionOfFullPulse: number;\n /** ∫ pulse(t) dt of the declared ordinary pulse, whose relative peak is 1 (relative multiplier · s). */\n singlePulseIntegratedRelativeSeconds: number;\n /** D: burst support covering the first line opening to the last line closing. */\n burstStartSecondsFromCaptureReference: number;\n burstEndSecondsFromCaptureReference: number;\n burstDurationSeconds: number;\n /** Local (slit) exposure durations t_e over the active frame. */\n localExposureDurationRangeSeconds: { minimum: number; maximum: number };\n /** Flash energy each line receives relative to one ordinary pulse at the same power: η·t_e/D. */\n energyFractionOfSinglePulseRange: { minimum: number; maximum: number };\n /** Effective guide-number factor relative to the same-power ordinary pulse: √(η·t_e/D). */\n guideNumberFactorRange: { minimum: number; maximum: number };\n uniformAcrossActiveFrame: boolean;\n /** The rectangular high-speed-sync burst, written as a manual pulse profile for the illumination overlay. */\n burstFlashProfile: ManualFlashProfile | null;\n releaseFrameBinding:\n | {\n sequenceId: string;\n releaseFrameId: string;\n frameIndex: number;\n sceneTimeSecondsFromSequenceStartAtBurstStart: number;\n sceneTimeSecondsFromSequenceStartAtBurstEnd: number;\n }\n | null;\n hssModeled: true;\n ttlModeled: false;\n sensorReadoutTimingUsedAsExposureTiming: false;\n limitations: readonly string[];\n}\n\nfunction integratePulse(samples: readonly SceneIlluminationTemporalWaveformSample[]): number {\n let area = 0;\n for (let index = 1; index < samples.length; index += 1) {\n const a = samples[index - 1]!, b = samples[index]!;\n area += (b.timeSecondsFromWaveformReference - a.timeSecondsFromWaveformReference) *\n (a.relativeMagnitudeMultiplier + b.relativeMagnitudeMultiplier) / 2;\n }\n return area;\n}\n\n/**\n * Resolves high-speed (focal-plane) sync (HSS): a fast pulse train that acts as continuous light and\n * covers the whole travelling-slit exposure.\n *\n * At shutter speeds faster than the ordinary sync limit, the shutter's opening and closing edges\n * cross the frame as a slit, and the whole frame is never open at once. A single short pulse would\n * light only a band.\n *\n * HSS instead fires a rapid pulse train. It behaves like constant output P over the burst D, from\n * the first line opening to the last line closing. Each line collects P·t_e over its slit time t_e.\n * - The burst energy is E_burst = η·p·E_pulse. η comes from the sync profile, p is the power\n * fraction and E_pulse is the energy of an ordinary full-power pulse.\n * - So P = E_burst/D, and each line receives η·p·E_pulse·t_e/D.\n * - Exposure ∝ GN² (inverse-square law, GN = d·N). So, relative to an ordinary pulse at the same\n * power, the effective guide number is GN_HSS/GN = √(η·t_e/D).\n * Shortening t_e by one stop therefore costs half a stop of guide number.\n *\n * Approximations: the pulse train is treated as continuous (pulse period ≪ t_e). Recycle and thermal\n * limits are folded into η. Front/rear-curtain placement does not apply, because the burst covers\n * the whole exposure.\n * @see docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md#high-speed-sync\n */\nexport function resolveHighSpeedFlashSync(input: ResolveHighSpeedFlashSyncInput): ResolvedHighSpeedFlashSync {\n requireInputKeys(input, \"resolveHighSpeedFlashSync\", [\"flashEnabled\", \"flashProfile\", \"syncCapabilities\", \"timing\", \"powerFraction\", \"releaseFrame\"]);\n requireTimingRecordShape(input.timing, \"resolveHighSpeedFlashSync timing\");\n const flash = parseManualFlashProfile(input.flashProfile);\n const capabilities = parseFlashSyncCapabilityProfile(input.syncCapabilities);\n if (capabilities.captureModeId !== input.timing.captureModeId || capabilities.timingProfileId !== input.timing.timingProfileId) {\n throw new InvalidScientificInputError(\n \"Flash sync capability profile must exactly match the resolved capture-mode and timing-profile identities.\"\n );\n }\n if (!capabilities.highSpeedSyncSupported || capabilities.highSpeedSync === undefined) {\n throw new InvalidScientificInputError(\"The flash sync capability profile does not declare high-speed sync.\");\n }\n const power = input.powerFraction;\n if (typeof power !== \"number\" || !Number.isFinite(power) || power <= 0 || power > 1) {\n throw new InvalidScientificInputError(\"HSS powerFraction must lie in (0, 1].\");\n }\n if (input.releaseFrame !== undefined) validateReleaseBinding(input.releaseFrame, input.timing);\n\n const windows = input.timing.exposureWindows;\n const closing = windows.closing.schedule;\n const burstEnd = windows.nominalExposureDurationSeconds.value +\n (closing.kind === \"simultaneous\" ? 0 : closing.traversalDurationSeconds.value);\n const eta = capabilities.highSpeedSync.burstEnergyFractionOfFullPulse;\n const local = windows.localExposureDurationRangeSeconds;\n const fraction = { minimum: eta * local.minimum / burstEnd, maximum: eta * local.maximum / burstEnd };\n const pulseEnergy = integratePulse(flash.pulse.samples);\n const burstFlashProfile: ManualFlashProfile = {\n ...flash,\n pulse: {\n ...flash.pulse,\n waveformId: flash.pulse.waveformId + \"-hss-burst\",\n supportDurationSeconds: burstEnd,\n samples: [\n { timeSecondsFromWaveformReference: 0, relativeMagnitudeMultiplier: 1 },\n { timeSecondsFromWaveformReference: burstEnd, relativeMagnitudeMultiplier: 1 }\n ],\n limitations: [...flash.pulse.limitations,\n \"Quasi-continuous HSS burst: the pulse train is approximated by constant output over the burst support.\"]\n },\n outputControl: { ...flash.outputControl, scale: flash.outputControl.scale * power * eta * pulseEnergy / burstEnd }\n };\n const enabled = input.flashEnabled;\n return {\n modelId: HIGH_SPEED_SYNC_MODEL.id,\n modelVersion: HIGH_SPEED_SYNC_MODEL.version,\n flashEnabled: enabled,\n flashProfileId: flash.profileId,\n flashProfileVersion: flash.profileVersion,\n sourceId: flash.sourceTemplate.sourceId,\n syncMode: \"high-speed-sync\",\n syncStatus: enabled ? \"high-speed-sync-resolved\" : \"disabled\",\n captureModeId: input.timing.captureModeId,\n timingProfileId: input.timing.timingProfileId,\n syncCapabilityProfileId: capabilities.profileId,\n timeReference: \"first-opening-boundary-phase\",\n powerFraction: power,\n burstEnergyFractionOfFullPulse: eta,\n singlePulseIntegratedRelativeSeconds: pulseEnergy,\n burstStartSecondsFromCaptureReference: 0,\n burstEndSecondsFromCaptureReference: burstEnd,\n burstDurationSeconds: burstEnd,\n localExposureDurationRangeSeconds: { minimum: local.minimum, maximum: local.maximum },\n energyFractionOfSinglePulseRange: fraction,\n guideNumberFactorRange: { minimum: Math.sqrt(fraction.minimum), maximum: Math.sqrt(fraction.maximum) },\n uniformAcrossActiveFrame: local.minimum === local.maximum,\n burstFlashProfile: enabled ? burstFlashProfile : null,\n waveformTimeZeroSecondsFromCaptureReference: enabled ? 0 : null,\n releaseFrameBinding: !enabled || input.releaseFrame === undefined ? null : {\n sequenceId: input.releaseFrame.sequenceId,\n releaseFrameId: input.releaseFrame.releaseFrameId,\n frameIndex: input.releaseFrame.frameIndex,\n sceneTimeSecondsFromSequenceStartAtBurstStart: input.releaseFrame.sceneTimeSecondsFromSequenceStart,\n sceneTimeSecondsFromSequenceStartAtBurstEnd: input.releaseFrame.sceneTimeSecondsFromSequenceStart + burstEnd\n },\n hssModeled: true,\n ttlModeled: false,\n sensorReadoutTimingUsedAsExposureTiming: false,\n evidence: [...flash.evidence, ...capabilities.evidence, ...capabilities.highSpeedSync.evidence, ...input.timing.evidence],\n limitations: [\n ...flash.limitations,\n ...capabilities.limitations,\n \"HSS burst is registered to exposure-boundary timing (first line opening to last line closing), never sensor data-readout timing.\",\n \"Pulse-train ripple, recycle/thermal limits beyond the declared burst energy fraction and branded flash protocols are not modeled.\"\n ]\n };\n}\n\n/**\n * Registers a resolved high-speed-sync burst as a temporal illumination overlay: a rectangular\n * waveform over [0, D]. Each line then collects the burst over its own local exposure window.\n */\nexport function createHighSpeedSyncIlluminationOverlay(\n input: Omit<CreateManualFlashIlluminationOverlayInput, \"resolvedSync\"> & { resolvedSync: ResolvedHighSpeedFlashSync }\n): ManualFlashIlluminationOverlay {\n requireInputKeys(input, \"createHighSpeedSyncIlluminationOverlay\", [\"baseIlluminationProfile\", \"baseTemporalProfile\", \"flashProfile\", \"illuminationProfileId\", \"temporalProfileId\", \"resolvedSync\"]);\n requireInputObject(input.resolvedSync, \"createHighSpeedSyncIlluminationOverlay resolvedSync\");\n return createManualFlashIlluminationOverlay({ ...input,\n flashProfile: input.resolvedSync.burstFlashProfile ?? input.flashProfile });\n}\n"]}
|
|
@@ -23,9 +23,9 @@ import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
|
23
23
|
import { requireInputKeys, requireInputObject } from "../core/record-validation.js";
|
|
24
24
|
import { resolveChartScene, resolveChartMaterial, chartMaterialInputs } from "./chart-scenes.js";
|
|
25
25
|
/** The cell index grain of every layer: cells across and down the mask box. */
|
|
26
|
-
export const CHART_MASK_INDEX_GRAIN = Object.freeze({ cellsX: 64, cellsY: 16 });
|
|
26
|
+
export const CHART_MASK_INDEX_GRAIN = /* @__PURE__ */ Object.freeze({ cellsX: 64, cellsY: 16 });
|
|
27
27
|
/** Limits of a declared scene. */
|
|
28
|
-
export const CHART_MATERIAL_LAYER_LIMITS = Object.freeze({ maximumLayers: 16, maximumShapes: 4096, maximumRings: 256, maximumEdges: 65_536 });
|
|
28
|
+
export const CHART_MATERIAL_LAYER_LIMITS = /* @__PURE__ */ Object.freeze({ maximumLayers: 16, maximumShapes: 4096, maximumRings: 256, maximumEdges: 65_536 });
|
|
29
29
|
const SCENE_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/u;
|
|
30
30
|
const finite = (value, name) => {
|
|
31
31
|
if (typeof value !== "number" || !Number.isFinite(value))
|