@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sensor-raw-producer.js","sourceRoot":"","sources":["../../src/capture/sensor-raw-producer.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Produces a sensor RAW frame from per-site exposure inputs, using the existing sensor steps:\n * accumulated charge → capacity → Poisson (shot) noise → read noise and ADC → native sample →\n * immutable frame.\n *\n * Inputs must be complete. Charge, noise or RAW codes cannot be passed in as a shortcut.\n * @see docs/SIMULATED_CAPTURE.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport { requireAllowlistedRecord, requirePublicOpaqueId } from \"../core/record-validation.js\";\n\nimport { parseSensorEqeTemporalPhotoSignal } from \"../sensor/temporal-photo-signal.js\";\nimport { RAW_REFERENCE_MAX_NATIVE_SITES } from \"./raw-frame-limits.js\";\n\nimport { approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { parseEvidenceList } from \"../core/evidence-provenance.js\";\nimport { parseSimulatedCapture } from \"./simulated-capture.js\";\nimport { createSensorRawFrame, type SensorRawFrameInput, type SensorRawFrame } from \"./sensor-raw-frame.js\";\nimport { composeSensorAccumulatedCharge, parseSensorAccumulatedChargeCompletenessProfile, parseSensorAdditionalStoredChargeComponent,\n type ComposeSensorPhotoAccumulatedChargeInput as ComposeSensorAccumulatedChargeInput } from \"../sensor/accumulated-charge.js\";\nimport { assessSensorPhysicalChargeCapacity, parseSensorPhysicalChargeCapacityProfile,\n type SensorPhysicalChargeCapacityProfile } from \"../sensor/physical-charge-capacity.js\";\nimport { simulateSensorChargeRealization, simulateSensorRawCode, parseSensorChargeSamplingProfile,\n parseSensorReadoutConversionProfile, resolveSensorReadoutRegime, type SensorChargeSamplingProfile, type SensorReadoutConversionProfile } from \"../sensor/raw-readout.js\";\nimport { createSensorRawCaptureSample } from \"../sensor/raw-reconstruction.js\";\nimport { parseSensorFixedPatternNoiseProfile, type SensorFixedPatternNoiseProfile } from \"../sensor/fixed-pattern-noise.js\";\nimport { deriveNativeSiteStreamSeedUint32, NATIVE_SITE_CHARGE_STREAM_ID, NATIVE_SITE_READ_NOISE_STREAM_ID } from \"../sensor/stochastic-seed.js\";\nimport { parseSensorColorSamplingProfile } from \"../sensor/color-sampling.js\";\nimport { parseCaptureModeProfile } from \"../sensor/capture-mode.js\";\nimport { parseNativeEffectiveRasterColorSamplingBindingProfile, resolveCaptureModeColorSamplingContributors } from \"../sensor/capture-color-sampling-binding.js\";\nimport { calculateCaptureExposureWindows, type CalculateCaptureExposureWindowsInput, type CaptureExposureWindows } from \"../sensor/exposure-window.js\";\n\nexport const SENSOR_RAW_PRODUCER_SCHEMA_VERSION = \"0.3.0\" as const;\n/**\n * Version of the capture noise model. It fixes the hashed per-site seed schedule and the signed electronic\n * readout behaviour.\n *\n * 0.4.0: exact ADC rounding with ties up, normal-approximation Poisson draws for means of 1e9 and above,\n * optional post-ADC digital gain and INL (integral non-linearity), and optional per-sensor fixed-pattern noise.\n */\nexport const SENSOR_RAW_PRODUCER_NOISE_MODEL = Object.freeze({ id: \"photivra-native-raw-noise\", version: \"0.4.0\" } as const);\n/** For each native site: one declared exposure event (EQE photo signal, dark signal, charge completeness) and its readout state. */\nexport interface SensorRawProducerSiteInput {\n charge: ComposeSensorAccumulatedChargeInput;\n samplingProfile: SensorChargeSamplingProfile;\n capacityProfile: SensorPhysicalChargeCapacityProfile;\n operatingStateId: string;\n readoutProfile: SensorReadoutConversionProfile;\n regimeId: string;\n /** Optional fixed-pattern noise (FPN) for this sensor; one profile for the whole frame. Omit it to disable FPN. */\n fixedPatternNoise?: SensorFixedPatternNoiseProfile;\n}\n/** Exposure schedule for the full sensor. The producer owns the sampling coordinates. */\nexport type SensorRawProducerExposureWindowInput = Omit<CalculateCaptureExposureWindowsInput,\n \"nativeRaster\" | \"activeCaptureRect\" | \"samplePointsNative\">;\n/** Input for one bounded frame. It is never a conversion from separate RGB pixels. */\nexport interface SensorRawProducerInput {\n frame: Omit<SensorRawFrameInput, \"samples\">;\n sites: readonly SensorRawProducerSiteInput[];\n /** If omitted, every event uses the existing global window 0..shutterSeconds. */\n exposureWindow?: SensorRawProducerExposureWindowInput;\n}\n/** Codes produced by the engine, with per-step diagnostics. The upstream radiance and response are as declared, not verified. */\nexport interface SensorRawProducerResult {\n schemaVersion: typeof SENSOR_RAW_PRODUCER_SCHEMA_VERSION;\n codeProducer: \"engine-charge-capacity-noise-adc\";\n upstreamOrigin: \"declared-eqe-and-dark-exposure-results\";\n upstreamRadiometryVerified: false;\n seedSchedule: \"murmur3-capture-seed-native-index-stream-v2\";\n frame: SensorRawFrame;\n localExposureWindows?: CalculationResult<CaptureExposureWindows>;\n sites: readonly {\n accumulatedCharge: ReturnType<typeof composeSensorAccumulatedCharge>;\n capacity: ReturnType<typeof assessSensorPhysicalChargeCapacity>;\n realization: ReturnType<typeof simulateSensorChargeRealization>;\n readout: ReturnType<typeof simulateSensorRawCode>;\n }[];\n}\nfunction fields(value: unknown, allowed: readonly string[]): Record<string, unknown> {\n return requireAllowlistedRecord(value, allowed, \"Invalid sensor RAW producer fields.\");\n}\nfunction publicId(value: unknown): string {\n return requirePublicOpaqueId(value, \"Expected public producer identity.\");\n}\nconst KEY_RECURSE = 0, KEY_IDENTITY = 1, KEY_IDENTITY_LIST = 2;\n/** Bounded cache of how the identity check classifies each property name (it depends only on the name). */\nconst IDENTITY_KEY_KINDS = new Map<string, number>();\n/** Bounded cache of strings already known to be valid public IDs (validity depends only on the string). */\nconst VALID_PUBLIC_IDS = new Set<string>();\nconst IDENTITY_WALK_MEMO_LIMIT = 4096;\nfunction identityKeyKind(key: string): number {\n // Array indices and other names ending in a digit match neither suffix.\n const last = key.charCodeAt(key.length - 1);\n if (last >= 48 && last <= 57) return KEY_RECURSE;\n let kind = IDENTITY_KEY_KINDS.get(key);\n if (kind === undefined) {\n kind = /(?:Id|Version)$/.test(key) ? KEY_IDENTITY : /Ids$/.test(key) ? KEY_IDENTITY_LIST : KEY_RECURSE;\n if (IDENTITY_KEY_KINDS.size < IDENTITY_WALK_MEMO_LIMIT) IDENTITY_KEY_KINDS.set(key, kind);\n }\n return kind;\n}\nfunction memoizedPublicId(value: unknown): void {\n if (typeof value === \"string\" && VALID_PUBLIC_IDS.has(value)) return;\n publicId(value);\n if (VALID_PUBLIC_IDS.size < IDENTITY_WALK_MEMO_LIMIT) VALID_PUBLIC_IDS.add(value as string);\n}\n/**\n * At any depth, every property whose name ends in Id or Version must hold a public ID, and every property\n * ending in Ids a bounded dense list of them. Order, keys and errors are the same as the earlier\n * Object.entries walk. Key classification and already-valid IDs are cached, because each depends only on\n * its string.\n */\nfunction publicIdentities(value: unknown): void {\n if (value === null || typeof value !== \"object\") return;\n const record = value as Record<string, unknown>, keys = Object.keys(record);\n for (let index = 0; index < keys.length; index++) {\n const key = keys[index]!, kind = identityKeyKind(key), child = record[key];\n if (kind === KEY_IDENTITY) memoizedPublicId(child);\n else if (kind === KEY_IDENTITY_LIST) dense(child, 256).forEach(memoizedPublicId);\n else if (child !== null && typeof child === \"object\") publicIdentities(child);\n }\n}\nfunction dense(value: unknown, maximum: number): unknown[] {\n if (!Array.isArray(value) || value.length > maximum || Array.from({ length: value.length }, (_, i) => i in value).includes(false)) {\n throw new InvalidConfigurationError(\"Expected bounded dense producer array.\");\n }\n return value;\n}\nfunction optionalEvidence(value: unknown): ReturnType<typeof parseEvidenceList> {\n return dense(value, 256).length === 0 ? [] : parseEvidenceList(value, \"optionalExposureEvidence\");\n}\nfunction exposureEvidence(value: unknown, temporalPhoto?: Record<string, unknown>): ComposeSensorAccumulatedChargeInput[\"photoSignal\"][\"componentEvidence\"] {\n if (temporalPhoto !== undefined) return parseSensorEqeTemporalPhotoSignal({ ...temporalPhoto, componentEvidence: value }).componentEvidence;\n const r = fields(value, [\"stationarity\", \"exposureBinding\"]);\n const b = fields(r.exposureBinding, [\"binding\", \"colorSamplingProfile\", \"nominalExposureDuration\", \"openingBoundary\", \"closingBoundary\"]);\n return { stationarity: parseEvidenceList(r.stationarity, \"stationarity\"), exposureBinding: {\n binding: parseEvidenceList(b.binding, \"binding\"), colorSamplingProfile: parseEvidenceList(b.colorSamplingProfile, \"colorSamplingProfile\"),\n nominalExposureDuration: parseEvidenceList(b.nominalExposureDuration, \"nominalExposureDuration\"),\n openingBoundary: optionalEvidence(b.openingBoundary), closingBoundary: optionalEvidence(b.closingBoundary) } };\n}\nconst common = [\"colorSamplingProfileId\", \"channelId\", \"site\", \"bindingId\", \"stationarityProfileId\", \"timeReference\",\n \"startOffsetSecondsFromOpeningReference\", \"endOffsetSecondsFromOpeningReference\", \"localExposureDurationSeconds\", \"componentEvidence\"];\nconst photoTrue = [\"timeStationarityEstablished\", \"temporalIntegrationApplied\", \"exposureDurationApplied\", \"countsAreExpectationValues\"];\nconst photoFalse = [\"timeVaryingSignalIntegrated\", \"multiFrameSequenceIntegrated\", \"darkChargeIncluded\", \"otherChargeIncluded\",\n \"physicalFullWellAssessmentAuthorized\", \"cameraSaturationAssessmentAuthorized\", \"saturationAssessed\", \"shotNoiseApplied\",\n \"readNoiseApplied\", \"adcQuantizationApplied\", \"rawCodeValueProduced\", \"integerPhotonCountSampled\", \"integerElectronCountSampled\", \"chargeCalculated\", \"currentCalculated\"];\nfunction chargeInput(value: unknown): ComposeSensorAccumulatedChargeInput {\n const r = fields(value, [\"photoSignal\", \"darkCharge\", \"additionalChargeComponents\", \"completenessProfile\"]);\n const temporal = r.photoSignal !== null && typeof r.photoSignal === \"object\" &&\n (r.photoSignal as Record<string, unknown>).kind === \"eqe-temporal-photo-signal\";\n const p = temporal ? parseSensorEqeTemporalPhotoSignal(r.photoSignal) as unknown as Record<string, unknown> : fields(r.photoSignal, [...common, ...photoTrue, ...photoFalse, \"kind\", \"stationarityStatus\", \"integrationMethod\",\n \"accumulatedSignalCompleteness\", \"incidentPhotonRatePerSecond\", \"expectedGeneratedElectronRatePerSecond\", \"expectedIncidentPhotonCount\", \"expectedGeneratedElectronCount\"]);\n const darkFalse = [\"integerDarkElectronCountSampled\", \"darkShotNoiseApplied\", \"darkCurrentCompensationApplied\", \"photoSignalIncluded\",\n \"otherChargeIncluded\", \"physicalFullWellAssessmentAuthorized\", \"saturationAssessed\"];\n const d = fields(r.darkCharge, [...common, ...darkFalse, \"darkCurrentProfileId\", \"operatingTemperatureC\", \"temperatureModel\",\n \"temperatureInterpolationUsed\", \"temporalIntegrationId\", \"darkCurrentElectronsPerSecond\", \"expectedDarkElectronCount\", \"countMeaning\", \"expectationValueOnly\", \"spatialDarkCurrentNonuniformityModeled\"]);\n if ((!temporal && (p.kind !== \"eqe-expected-counts\" || p.integrationMethod !== \"constant-rate-times-local-exposure-duration\" ||\n p.accumulatedSignalCompleteness !== \"photo-signal-only\" || (p.stationarityStatus !== \"established\" && p.stationarityStatus !== \"approximation\") ||\n photoTrue.some((k) => p[k] !== true) || photoFalse.some((k) => p[k] !== false))) || darkFalse.some((k) => d[k] !== false) ||\n d.expectationValueOnly !== true || d.countMeaning !== \"expected-thermally-generated-electrons\" ||\n typeof d.spatialDarkCurrentNonuniformityModeled !== \"boolean\" || typeof d.temperatureInterpolationUsed !== \"boolean\" ||\n (d.temperatureModel !== \"fixed-reference-temperature\" && d.temperatureModel !== \"piecewise-linear-temperature-table\" &&\n d.temperatureModel !== \"log-linear-temperature-table\")) {\n throw new InvalidConfigurationError(\"Producer requires untreated EQE/dark exposure expectations, not sampled, clipped or A/W charge.\");\n }\n if (d.temperatureModel === \"fixed-reference-temperature\" && d.temperatureInterpolationUsed !== false) {\n throw new InvalidConfigurationError(\"Fixed-temperature dark result cannot claim temperature interpolation.\");\n }\n for (const record of [p, d]) {\n for (const k of [\"colorSamplingProfileId\", \"channelId\", \"bindingId\", temporal ? \"temporalIntegrationId\" : \"stationarityProfileId\"]) publicId(record[k]);\n fields(record.site, [\"x\", \"y\"]);\n if (record.timeReference !== \"first-opening-boundary-phase\") throw new InvalidConfigurationError(\"Unsupported producer time origin.\");\n }\n publicId(d.darkCurrentProfileId);\n for (const [record, keys] of [[p, [\"incidentPhotonRatePerSecond\", \"expectedGeneratedElectronRatePerSecond\", \"expectedIncidentPhotonCount\", \"expectedGeneratedElectronCount\"]],\n [d, [\"darkCurrentElectronsPerSecond\", \"expectedDarkElectronCount\"]]] as const) {\n for (const k of keys) if (!(temporal && record === p && k.endsWith(\"RatePerSecond\")) && (typeof record[k] !== \"number\" || !Number.isFinite(record[k]) || record[k] < 0)) throw new InvalidConfigurationError(\"Invalid expected rates/counts.\");\n }\n const duration = p.localExposureDurationSeconds;\n if (typeof duration !== \"number\" || !Number.isFinite(duration) || duration <= 0 ||\n (!temporal && (p.expectedIncidentPhotonCount !== (p.incidentPhotonRatePerSecond as number)*duration ||\n p.expectedGeneratedElectronCount !== (p.expectedGeneratedElectronRatePerSecond as number)*duration)) ||\n d.expectedDarkElectronCount !== (d.darkCurrentElectronsPerSecond as number)*duration ||\n (p.expectedGeneratedElectronCount as number) > (p.expectedIncidentPhotonCount as number)) {\n throw new InvalidConfigurationError(\"Exposure expectations must match their exact temporal integral or constant-rate products and EQE domain.\");\n }\n const e = fields(d.componentEvidence, [\"darkCurrent\", \"siteApproximation\", \"exposure\"]);\n const charge = { photoSignal: { ...p, componentEvidence: exposureEvidence(p.componentEvidence, temporal ? p : undefined) },\n darkCharge: { ...d, componentEvidence: { darkCurrent: parseEvidenceList(e.darkCurrent, \"darkCurrent\"),\n siteApproximation: optionalEvidence(e.siteApproximation), exposure: exposureEvidence(e.exposure, temporal ? p : undefined) } },\n completenessProfile: parseSensorAccumulatedChargeCompletenessProfile(r.completenessProfile),\n ...(r.additionalChargeComponents === undefined ? {} : { additionalChargeComponents:\n dense(r.additionalChargeComponents, 32).map(parseSensorAdditionalStoredChargeComponent) }) } as unknown as ComposeSensorAccumulatedChargeInput;\n // The existing charge composition checks that photo, dark, additional and completeness events agree exactly.\n composeSensorAccumulatedCharge(charge);\n return charge;\n}\nfunction localWindows(frame: SensorRawProducerInput[\"frame\"], value: unknown): CalculationResult<CaptureExposureWindows> {\n const r = fields(value, [\"shutterMechanism\", \"nominalExposureDurationSeconds\", \"opening\", \"closing\"]);\n fields(r.nominalExposureDurationSeconds, [\"value\", \"unit\", \"evidence\"]);\n for (const boundary of [r.opening, r.closing]) {\n const b = fields(boundary, [\"kind\", \"directionNative\", \"traversalDurationSeconds\"]);\n if (b.directionNative !== undefined) fields(b.directionNative, [\"value\", \"evidence\"]);\n if (b.traversalDurationSeconds !== undefined) fields(b.traversalDurationSeconds, [\"value\", \"unit\", \"evidence\"]);\n }\n const native = frame.capture.geometry.nativeRaster;\n const timing = calculateCaptureExposureWindows({\n ...r as unknown as SensorRawProducerExposureWindowInput,\n nativeRaster: native,\n samplePointsNative: Array.from({ length: native.pixelWidth*native.pixelHeight }, (_, i) => ({\n x: i%native.pixelWidth+0.5, y: Math.floor(i/native.pixelWidth)+0.5\n }))\n });\n if (timing.value.nominalExposureDurationSeconds.value !== frame.capture.exposure.shutterSeconds) {\n throw new InvalidConfigurationError(\"Exposure schedule nominal duration differs from committed capture.\");\n }\n return timing;\n}\nfunction sourceBoundary(schedule: CaptureExposureWindows[\"opening\"][\"schedule\"]): SensorRawProducerExposureWindowInput[\"opening\"] {\n return schedule.kind === \"simultaneous\" ? { kind: \"simultaneous\" } : {\n kind: \"uniform-linear-native-scan\", directionNative: schedule.directionNative,\n traversalDurationSeconds: schedule.traversalDurationSeconds\n };\n}\n/** Internal: per-site validation shared by the reference path and bounded packed execution. */\nexport type NativeRawProducerFrameContext = Omit<SensorRawProducerInput[\"frame\"], \"capture\"> & {\n capture: Pick<SensorRawProducerInput[\"frame\"][\"capture\"], \"geometry\" | \"exposure\" | \"noise\" | \"focus\" | \"sceneStateId\" | \"sceneTimeSeconds\">;\n};\nexport function parseNativeRawProducerSite(site: unknown, i: number, frame: NativeRawProducerFrameContext,\n window?: CaptureExposureWindows[\"samples\"][number]): SensorRawProducerSiteInput {\n const native = frame.capture.geometry.nativeRaster;\n const s = fields(site, [\"charge\", \"samplingProfile\", \"capacityProfile\", \"operatingStateId\", \"readoutProfile\", \"regimeId\", \"fixedPatternNoise\"]);\n const charge = chargeInput(s.charge), p = charge.photoSignal;\n const contributors = resolveCaptureModeColorSamplingContributors({ nativeRaster: native, captureModeProfile: frame.captureModeProfile,\n modeId: frame.modeId, colorSamplingProfile: frame.colorSamplingProfile, bindingProfile: frame.bindingProfile,\n modeSampleIndexFullFrame: { x: i%native.pixelWidth, y: Math.floor(i/native.pixelWidth) } });\n\n if (contributors.totalContributorSites !== 1 || contributors.channelComposition.kind !== \"single-channel\" ||\n p.colorSamplingProfileId !== frame.colorSamplingProfile.profileId || p.channelId !== contributors.channelComposition.channelId ||\n p.site.x !== contributors.colorSamplingSiteRect.x || p.site.y !== contributors.colorSamplingSiteRect.y ||\n p.bindingId !== frame.bindingProfile.bindingId || p.startOffsetSecondsFromOpeningReference !== (window?.startOffsetSecondsFromOpeningReference ?? 0) ||\n p.endOffsetSecondsFromOpeningReference !== (window?.endOffsetSecondsFromOpeningReference ?? frame.capture.exposure.shutterSeconds) ||\n p.localExposureDurationSeconds !== (window?.localExposureDurationSeconds ?? frame.capture.exposure.shutterSeconds)) {\n throw new InvalidConfigurationError(\"Charge site/channel/binding/local exposure differs from committed capture.\");\n }\n const readoutProfile = parseSensorReadoutConversionProfile(s.readoutProfile);\n const isoGain = readoutProfile.regimes.find((regime) => regime.regimeId === s.regimeId)?.exposureIndexGain;\n if (isoGain !== undefined && isoGain.exposureIndex !== frame.capture.exposure.iso) {\n throw new InvalidConfigurationError(\"Readout regime ISO gain differs from the committed capture ISO.\");\n }\n return { charge, samplingProfile: parseSensorChargeSamplingProfile(s.samplingProfile), capacityProfile: parseSensorPhysicalChargeCapacityProfile(s.capacityProfile),\n operatingStateId: publicId(s.operatingStateId), readoutProfile, regimeId: publicId(s.regimeId),\n ...(s.fixedPatternNoise === undefined ? {} : { fixedPatternNoise: parseSensorFixedPatternNoiseProfile(s.fixedPatternNoise) }) };\n}\nexport function validateNativeRawReadoutIdentity(s: SensorRawProducerSiteInput, first: SensorRawProducerSiteInput): void {\n publicIdentities(s);\n const readout = resolveSensorReadoutRegime({ profile: s.readoutProfile, regimeId: s.regimeId });\n if (s.readoutProfile.profileId !== first.readoutProfile.profileId || s.regimeId !== first.regimeId ||\n readout.regime.adc.bitDepth > 16 || readout.regime.adc.digitalSaturationCode <= readout.regime.adc.blackLevelCode ||\n s.readoutProfile.colorSamplingProfileId !== s.charge.photoSignal.colorSamplingProfileId ||\n s.readoutProfile.channelId !== s.charge.photoSignal.channelId || s.samplingProfile.completenessProfileId !== s.charge.completenessProfile.profileId ||\n s.fixedPatternNoise?.profileId !== first.fixedPatternNoise?.profileId ||\n s.fixedPatternNoise?.sensorInstanceSeedUint32 !== first.fixedPatternNoise?.sensorInstanceSeedUint32) {\n throw new InvalidConfigurationError(\"Frame requires one readout identity/regime, one fixed-pattern identity and a positive uint16 RAW code span.\");\n }\n}\n/** The shared per-site pipeline holds all the charge, capacity, random-noise and ADC equations. `i` is the absolute native row-major index. */\nexport function calculateNativeRawSite(s: SensorRawProducerSiteInput, seed: number, i: number): SensorRawProducerResult[\"sites\"][number] {\n const accumulatedCharge = composeSensorAccumulatedCharge(s.charge);\n const capacity = assessSensorPhysicalChargeCapacity({ accumulatedCharge: accumulatedCharge.value, capacityProfile: s.capacityProfile,\n operatingStateId: s.operatingStateId, operatingTemperatureC: s.charge.darkCharge.operatingTemperatureC });\n const pattern = s.fixedPatternNoise === undefined ? {} : { fixedPatternNoise: s.fixedPatternNoise };\n const realization = simulateSensorChargeRealization({ accumulatedCharge: accumulatedCharge.value, samplingProfile: s.samplingProfile,\n seedUint32: deriveNativeSiteStreamSeedUint32(seed, i, NATIVE_SITE_CHARGE_STREAM_ID), ...pattern });\n const readout = simulateSensorRawCode({ chargeRealization: realization.value, physicalCapacityAssessment: capacity.value,\n readoutProfile: s.readoutProfile, regimeId: s.regimeId,\n readNoiseSeedUint32: deriveNativeSiteStreamSeedUint32(seed, i, NATIVE_SITE_READ_NOISE_STREAM_ID), ...pattern });\n return { accumulatedCharge, capacity, realization, readout };\n}\n/** The selected regime's declared INL, which the effective white level needs at saturation. */\nfunction regimeInl(site: SensorRawProducerSiteInput): { adcIntegralNonLinearity?: NonNullable<SensorReadoutConversionProfile[\"regimes\"][number][\"adc\"][\"integralNonLinearity\"]> } {\n const inl = site.readoutProfile.regimes.find((r) => r.regimeId === site.regimeId)?.adc.integralNonLinearity;\n return inl === undefined ? {} : { adcIntegralNonLinearity: inl };\n}\n/** Validates the complete per-site exposure inputs. Charge, noise or RAW codes are never accepted as a shortcut. */\nexport function parseSensorRawProducerInput(value: unknown): SensorRawProducerInput {\n const r = fields(value, [\"frame\", \"sites\", \"exposureWindow\"]), f = fields(r.frame, [\"frameId\", \"capture\", \"modeId\", \"captureModeProfile\", \"colorSamplingProfile\", \"bindingProfile\", \"containerBitDepth\"]);\n const capture = parseSimulatedCapture(f.capture), native = capture.geometry.nativeRaster, count = native.pixelWidth*native.pixelHeight;\n const sites = dense(r.sites, RAW_REFERENCE_MAX_NATIVE_SITES);\n const frame = { frameId: publicId(f.frameId), capture, modeId: publicId(f.modeId), containerBitDepth: 16 as const,\n captureModeProfile: parseCaptureModeProfile(f.captureModeProfile), colorSamplingProfile: parseSensorColorSamplingProfile(f.colorSamplingProfile),\n bindingProfile: parseNativeEffectiveRasterColorSamplingBindingProfile(f.bindingProfile) };\n const mode = frame.captureModeProfile.modes.find((m) => m.modeId === frame.modeId);\n if (f.containerBitDepth !== 16 || count > RAW_REFERENCE_MAX_NATIVE_SITES || sites.length !== count ||\n capture.noise.model.id !== SENSOR_RAW_PRODUCER_NOISE_MODEL.id || capture.noise.model.version !== SENSOR_RAW_PRODUCER_NOISE_MODEL.version ||\n frame.colorSamplingProfile.layout.kind !== \"periodic-mosaic\" || !mode || mode.acquisition.kind !== \"single-frame\" ||\n mode.perFrameSampling.kind !== \"native-effective-raster\" || (mode.reconstructionStages?.length ?? 0) !== 0) {\n throw new InvalidConfigurationError(\"Producer requires exact noise identity and bounded single-frame native CFA coverage.\");\n }\n const timing = r.exposureWindow === undefined ? undefined : localWindows(frame, r.exposureWindow);\n const parsed = sites.map((site, i) => parseNativeRawProducerSite(site, i, frame, timing?.value.samples[i]));\n for (const site of parsed) validateNativeRawReadoutIdentity(site, parsed[0]!);\n publicIdentities(frame);\n return { frame, sites: parsed, ...(timing === undefined ? {} : { exposureWindow: {\n shutterMechanism: timing.value.shutterMechanism,\n nominalExposureDurationSeconds: timing.value.nominalExposureDurationSeconds,\n opening: sourceBoundary(timing.value.opening.schedule), closing: sourceBoundary(timing.value.closing.schedule)\n } }) };\n}\n/** Runs accumulated charge → capacity → Poisson noise → read noise and ADC → native sample → immutable frame. */\nexport function simulateSensorRawFrame(input: SensorRawProducerInput): CalculationResult<SensorRawProducerResult> {\n const v = parseSensorRawProducerInput(input), seed = v.frame.capture.noise.seedUint32;\n const sites = v.sites.map((s, i) => calculateNativeRawSite(s, seed, i));\n const native = v.frame.capture.geometry.nativeRaster;\n const samples = sites.map((s, i) => createSensorRawCaptureSample({ rawCode: s.readout.value,\n ...regimeInl(v.sites[i]!),\n contributors: resolveCaptureModeColorSamplingContributors({ nativeRaster: native, captureModeProfile: v.frame.captureModeProfile,\n modeId: v.frame.modeId, colorSamplingProfile: v.frame.colorSamplingProfile, bindingProfile: v.frame.bindingProfile,\n modeSampleIndexFullFrame: { x: i%native.pixelWidth, y: Math.floor(i/native.pixelWidth) } }) }));\n return approximationResult({ schemaVersion: SENSOR_RAW_PRODUCER_SCHEMA_VERSION, codeProducer: \"engine-charge-capacity-noise-adc\",\n upstreamOrigin: \"declared-eqe-and-dark-exposure-results\", upstreamRadiometryVerified: false,\n seedSchedule: \"murmur3-capture-seed-native-index-stream-v2\", frame: createSensorRawFrame({ ...v.frame, samples }), sites,\n ...(v.exposureWindow === undefined ? {} : { localExposureWindows: localWindows(v.frame, v.exposureWindow) }) },\n \"native-sensor-raw-frame-producer\", SENSOR_RAW_PRODUCER_SCHEMA_VERSION, [\n \"Untreated EQE/dark exposure results and completeness evidence are upstream declarations; source radiometry is not independently verified\",\n \"Native row-major site seeds are MurmurHash3_x86_32 of (capture seed, absolute native index, stream 0 charge / 1 read noise); deterministic and non-cryptographic\",\n \"Existing scalar capacity/noise/readout approximations retain distinct physical/pre-ADC/digital saturation diagnostics; no blooming\",\n \"Optional fixed-pattern noise is deterministic per sensor instance (its own seed and absolute colour-sampling site), independent of the capture seed\",\n \"Stationarity applies separately to every exact local window; no time-varying radiance integration, multi-frame acquisition, RGB-to-RAW conversion or production-stage activation\",\n \"Stored capture float planes remain independent; same-RAW export must use the returned frame's reconstruction handoff\"]);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sensor-raw-producer.js","sourceRoot":"","sources":["../../src/capture/sensor-raw-producer.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Produces a sensor RAW frame from per-site exposure inputs, using the existing sensor steps:\n * accumulated charge → capacity → Poisson (shot) noise → read noise and ADC → native sample →\n * immutable frame.\n *\n * Inputs must be complete. Charge, noise or RAW codes cannot be passed in as a shortcut.\n * @see docs/SIMULATED_CAPTURE.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport { requireAllowlistedRecord, requirePublicOpaqueId } from \"../core/record-validation.js\";\n\nimport { parseSensorEqeTemporalPhotoSignal } from \"../sensor/temporal-photo-signal.js\";\nimport { RAW_REFERENCE_MAX_NATIVE_SITES } from \"./raw-frame-limits.js\";\n\nimport { approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { parseEvidenceList } from \"../core/evidence-provenance.js\";\nimport { parseSimulatedCapture } from \"./simulated-capture.js\";\nimport { createSensorRawFrame, type SensorRawFrameInput, type SensorRawFrame } from \"./sensor-raw-frame.js\";\nimport { composeSensorAccumulatedCharge, parseSensorAccumulatedChargeCompletenessProfile, parseSensorAdditionalStoredChargeComponent,\n type ComposeSensorPhotoAccumulatedChargeInput as ComposeSensorAccumulatedChargeInput } from \"../sensor/accumulated-charge.js\";\nimport { assessSensorPhysicalChargeCapacity, parseSensorPhysicalChargeCapacityProfile,\n type SensorPhysicalChargeCapacityProfile } from \"../sensor/physical-charge-capacity.js\";\nimport { simulateSensorChargeRealization, simulateSensorRawCode, parseSensorChargeSamplingProfile,\n parseSensorReadoutConversionProfile, resolveSensorReadoutRegime, type SensorChargeSamplingProfile, type SensorReadoutConversionProfile } from \"../sensor/raw-readout.js\";\nimport { createSensorRawCaptureSample } from \"../sensor/raw-reconstruction.js\";\nimport { parseSensorFixedPatternNoiseProfile, type SensorFixedPatternNoiseProfile } from \"../sensor/fixed-pattern-noise.js\";\nimport { deriveNativeSiteStreamSeedUint32, NATIVE_SITE_CHARGE_STREAM_ID, NATIVE_SITE_READ_NOISE_STREAM_ID } from \"../sensor/stochastic-seed.js\";\nimport { parseSensorColorSamplingProfile } from \"../sensor/color-sampling.js\";\nimport { parseCaptureModeProfile } from \"../sensor/capture-mode.js\";\nimport { parseNativeEffectiveRasterColorSamplingBindingProfile, resolveCaptureModeColorSamplingContributors } from \"../sensor/capture-color-sampling-binding.js\";\nimport { calculateCaptureExposureWindows, type CalculateCaptureExposureWindowsInput, type CaptureExposureWindows } from \"../sensor/exposure-window.js\";\n\nexport const SENSOR_RAW_PRODUCER_SCHEMA_VERSION = \"0.3.0\" as const;\n/**\n * Version of the capture noise model. It fixes the hashed per-site seed schedule and the signed electronic\n * readout behaviour.\n *\n * 0.4.0: exact ADC rounding with ties up, normal-approximation Poisson draws for means of 1e9 and above,\n * optional post-ADC digital gain and INL (integral non-linearity), and optional per-sensor fixed-pattern noise.\n */\nexport const SENSOR_RAW_PRODUCER_NOISE_MODEL = /* @__PURE__ */ Object.freeze({ id: \"photivra-native-raw-noise\", version: \"0.4.0\" } as const);\n/** For each native site: one declared exposure event (EQE photo signal, dark signal, charge completeness) and its readout state. */\nexport interface SensorRawProducerSiteInput {\n charge: ComposeSensorAccumulatedChargeInput;\n samplingProfile: SensorChargeSamplingProfile;\n capacityProfile: SensorPhysicalChargeCapacityProfile;\n operatingStateId: string;\n readoutProfile: SensorReadoutConversionProfile;\n regimeId: string;\n /** Optional fixed-pattern noise (FPN) for this sensor; one profile for the whole frame. Omit it to disable FPN. */\n fixedPatternNoise?: SensorFixedPatternNoiseProfile;\n}\n/** Exposure schedule for the full sensor. The producer owns the sampling coordinates. */\nexport type SensorRawProducerExposureWindowInput = Omit<CalculateCaptureExposureWindowsInput,\n \"nativeRaster\" | \"activeCaptureRect\" | \"samplePointsNative\">;\n/** Input for one bounded frame. It is never a conversion from separate RGB pixels. */\nexport interface SensorRawProducerInput {\n frame: Omit<SensorRawFrameInput, \"samples\">;\n sites: readonly SensorRawProducerSiteInput[];\n /** If omitted, every event uses the existing global window 0..shutterSeconds. */\n exposureWindow?: SensorRawProducerExposureWindowInput;\n}\n/** Codes produced by the engine, with per-step diagnostics. The upstream radiance and response are as declared, not verified. */\nexport interface SensorRawProducerResult {\n schemaVersion: typeof SENSOR_RAW_PRODUCER_SCHEMA_VERSION;\n codeProducer: \"engine-charge-capacity-noise-adc\";\n upstreamOrigin: \"declared-eqe-and-dark-exposure-results\";\n upstreamRadiometryVerified: false;\n seedSchedule: \"murmur3-capture-seed-native-index-stream-v2\";\n frame: SensorRawFrame;\n localExposureWindows?: CalculationResult<CaptureExposureWindows>;\n sites: readonly {\n accumulatedCharge: ReturnType<typeof composeSensorAccumulatedCharge>;\n capacity: ReturnType<typeof assessSensorPhysicalChargeCapacity>;\n realization: ReturnType<typeof simulateSensorChargeRealization>;\n readout: ReturnType<typeof simulateSensorRawCode>;\n }[];\n}\nfunction fields(value: unknown, allowed: readonly string[]): Record<string, unknown> {\n return requireAllowlistedRecord(value, allowed, \"Invalid sensor RAW producer fields.\");\n}\nfunction publicId(value: unknown): string {\n return requirePublicOpaqueId(value, \"Expected public producer identity.\");\n}\nconst KEY_RECURSE = 0, KEY_IDENTITY = 1, KEY_IDENTITY_LIST = 2;\n/** Bounded cache of how the identity check classifies each property name (it depends only on the name). */\nconst IDENTITY_KEY_KINDS = new Map<string, number>();\n/** Bounded cache of strings already known to be valid public IDs (validity depends only on the string). */\nconst VALID_PUBLIC_IDS = new Set<string>();\nconst IDENTITY_WALK_MEMO_LIMIT = 4096;\nfunction identityKeyKind(key: string): number {\n // Array indices and other names ending in a digit match neither suffix.\n const last = key.charCodeAt(key.length - 1);\n if (last >= 48 && last <= 57) return KEY_RECURSE;\n let kind = IDENTITY_KEY_KINDS.get(key);\n if (kind === undefined) {\n kind = /(?:Id|Version)$/.test(key) ? KEY_IDENTITY : /Ids$/.test(key) ? KEY_IDENTITY_LIST : KEY_RECURSE;\n if (IDENTITY_KEY_KINDS.size < IDENTITY_WALK_MEMO_LIMIT) IDENTITY_KEY_KINDS.set(key, kind);\n }\n return kind;\n}\nfunction memoizedPublicId(value: unknown): void {\n if (typeof value === \"string\" && VALID_PUBLIC_IDS.has(value)) return;\n publicId(value);\n if (VALID_PUBLIC_IDS.size < IDENTITY_WALK_MEMO_LIMIT) VALID_PUBLIC_IDS.add(value as string);\n}\n/**\n * At any depth, every property whose name ends in Id or Version must hold a public ID, and every property\n * ending in Ids a bounded dense list of them. Order, keys and errors are the same as the earlier\n * Object.entries walk. Key classification and already-valid IDs are cached, because each depends only on\n * its string.\n */\nfunction publicIdentities(value: unknown): void {\n if (value === null || typeof value !== \"object\") return;\n const record = value as Record<string, unknown>, keys = Object.keys(record);\n for (let index = 0; index < keys.length; index++) {\n const key = keys[index]!, kind = identityKeyKind(key), child = record[key];\n if (kind === KEY_IDENTITY) memoizedPublicId(child);\n else if (kind === KEY_IDENTITY_LIST) dense(child, 256).forEach(memoizedPublicId);\n else if (child !== null && typeof child === \"object\") publicIdentities(child);\n }\n}\nfunction dense(value: unknown, maximum: number): unknown[] {\n if (!Array.isArray(value) || value.length > maximum || Array.from({ length: value.length }, (_, i) => i in value).includes(false)) {\n throw new InvalidConfigurationError(\"Expected bounded dense producer array.\");\n }\n return value;\n}\nfunction optionalEvidence(value: unknown): ReturnType<typeof parseEvidenceList> {\n return dense(value, 256).length === 0 ? [] : parseEvidenceList(value, \"optionalExposureEvidence\");\n}\nfunction exposureEvidence(value: unknown, temporalPhoto?: Record<string, unknown>): ComposeSensorAccumulatedChargeInput[\"photoSignal\"][\"componentEvidence\"] {\n if (temporalPhoto !== undefined) return parseSensorEqeTemporalPhotoSignal({ ...temporalPhoto, componentEvidence: value }).componentEvidence;\n const r = fields(value, [\"stationarity\", \"exposureBinding\"]);\n const b = fields(r.exposureBinding, [\"binding\", \"colorSamplingProfile\", \"nominalExposureDuration\", \"openingBoundary\", \"closingBoundary\"]);\n return { stationarity: parseEvidenceList(r.stationarity, \"stationarity\"), exposureBinding: {\n binding: parseEvidenceList(b.binding, \"binding\"), colorSamplingProfile: parseEvidenceList(b.colorSamplingProfile, \"colorSamplingProfile\"),\n nominalExposureDuration: parseEvidenceList(b.nominalExposureDuration, \"nominalExposureDuration\"),\n openingBoundary: optionalEvidence(b.openingBoundary), closingBoundary: optionalEvidence(b.closingBoundary) } };\n}\nconst common = [\"colorSamplingProfileId\", \"channelId\", \"site\", \"bindingId\", \"stationarityProfileId\", \"timeReference\",\n \"startOffsetSecondsFromOpeningReference\", \"endOffsetSecondsFromOpeningReference\", \"localExposureDurationSeconds\", \"componentEvidence\"];\nconst photoTrue = [\"timeStationarityEstablished\", \"temporalIntegrationApplied\", \"exposureDurationApplied\", \"countsAreExpectationValues\"];\nconst photoFalse = [\"timeVaryingSignalIntegrated\", \"multiFrameSequenceIntegrated\", \"darkChargeIncluded\", \"otherChargeIncluded\",\n \"physicalFullWellAssessmentAuthorized\", \"cameraSaturationAssessmentAuthorized\", \"saturationAssessed\", \"shotNoiseApplied\",\n \"readNoiseApplied\", \"adcQuantizationApplied\", \"rawCodeValueProduced\", \"integerPhotonCountSampled\", \"integerElectronCountSampled\", \"chargeCalculated\", \"currentCalculated\"];\nfunction chargeInput(value: unknown): ComposeSensorAccumulatedChargeInput {\n const r = fields(value, [\"photoSignal\", \"darkCharge\", \"additionalChargeComponents\", \"completenessProfile\"]);\n const temporal = r.photoSignal !== null && typeof r.photoSignal === \"object\" &&\n (r.photoSignal as Record<string, unknown>).kind === \"eqe-temporal-photo-signal\";\n const p = temporal ? parseSensorEqeTemporalPhotoSignal(r.photoSignal) as unknown as Record<string, unknown> : fields(r.photoSignal, [...common, ...photoTrue, ...photoFalse, \"kind\", \"stationarityStatus\", \"integrationMethod\",\n \"accumulatedSignalCompleteness\", \"incidentPhotonRatePerSecond\", \"expectedGeneratedElectronRatePerSecond\", \"expectedIncidentPhotonCount\", \"expectedGeneratedElectronCount\"]);\n const darkFalse = [\"integerDarkElectronCountSampled\", \"darkShotNoiseApplied\", \"darkCurrentCompensationApplied\", \"photoSignalIncluded\",\n \"otherChargeIncluded\", \"physicalFullWellAssessmentAuthorized\", \"saturationAssessed\"];\n const d = fields(r.darkCharge, [...common, ...darkFalse, \"darkCurrentProfileId\", \"operatingTemperatureC\", \"temperatureModel\",\n \"temperatureInterpolationUsed\", \"temporalIntegrationId\", \"darkCurrentElectronsPerSecond\", \"expectedDarkElectronCount\", \"countMeaning\", \"expectationValueOnly\", \"spatialDarkCurrentNonuniformityModeled\"]);\n if ((!temporal && (p.kind !== \"eqe-expected-counts\" || p.integrationMethod !== \"constant-rate-times-local-exposure-duration\" ||\n p.accumulatedSignalCompleteness !== \"photo-signal-only\" || (p.stationarityStatus !== \"established\" && p.stationarityStatus !== \"approximation\") ||\n photoTrue.some((k) => p[k] !== true) || photoFalse.some((k) => p[k] !== false))) || darkFalse.some((k) => d[k] !== false) ||\n d.expectationValueOnly !== true || d.countMeaning !== \"expected-thermally-generated-electrons\" ||\n typeof d.spatialDarkCurrentNonuniformityModeled !== \"boolean\" || typeof d.temperatureInterpolationUsed !== \"boolean\" ||\n (d.temperatureModel !== \"fixed-reference-temperature\" && d.temperatureModel !== \"piecewise-linear-temperature-table\" &&\n d.temperatureModel !== \"log-linear-temperature-table\")) {\n throw new InvalidConfigurationError(\"Producer requires untreated EQE/dark exposure expectations, not sampled, clipped or A/W charge.\");\n }\n if (d.temperatureModel === \"fixed-reference-temperature\" && d.temperatureInterpolationUsed !== false) {\n throw new InvalidConfigurationError(\"Fixed-temperature dark result cannot claim temperature interpolation.\");\n }\n for (const record of [p, d]) {\n for (const k of [\"colorSamplingProfileId\", \"channelId\", \"bindingId\", temporal ? \"temporalIntegrationId\" : \"stationarityProfileId\"]) publicId(record[k]);\n fields(record.site, [\"x\", \"y\"]);\n if (record.timeReference !== \"first-opening-boundary-phase\") throw new InvalidConfigurationError(\"Unsupported producer time origin.\");\n }\n publicId(d.darkCurrentProfileId);\n for (const [record, keys] of [[p, [\"incidentPhotonRatePerSecond\", \"expectedGeneratedElectronRatePerSecond\", \"expectedIncidentPhotonCount\", \"expectedGeneratedElectronCount\"]],\n [d, [\"darkCurrentElectronsPerSecond\", \"expectedDarkElectronCount\"]]] as const) {\n for (const k of keys) if (!(temporal && record === p && k.endsWith(\"RatePerSecond\")) && (typeof record[k] !== \"number\" || !Number.isFinite(record[k]) || record[k] < 0)) throw new InvalidConfigurationError(\"Invalid expected rates/counts.\");\n }\n const duration = p.localExposureDurationSeconds;\n if (typeof duration !== \"number\" || !Number.isFinite(duration) || duration <= 0 ||\n (!temporal && (p.expectedIncidentPhotonCount !== (p.incidentPhotonRatePerSecond as number)*duration ||\n p.expectedGeneratedElectronCount !== (p.expectedGeneratedElectronRatePerSecond as number)*duration)) ||\n d.expectedDarkElectronCount !== (d.darkCurrentElectronsPerSecond as number)*duration ||\n (p.expectedGeneratedElectronCount as number) > (p.expectedIncidentPhotonCount as number)) {\n throw new InvalidConfigurationError(\"Exposure expectations must match their exact temporal integral or constant-rate products and EQE domain.\");\n }\n const e = fields(d.componentEvidence, [\"darkCurrent\", \"siteApproximation\", \"exposure\"]);\n const charge = { photoSignal: { ...p, componentEvidence: exposureEvidence(p.componentEvidence, temporal ? p : undefined) },\n darkCharge: { ...d, componentEvidence: { darkCurrent: parseEvidenceList(e.darkCurrent, \"darkCurrent\"),\n siteApproximation: optionalEvidence(e.siteApproximation), exposure: exposureEvidence(e.exposure, temporal ? p : undefined) } },\n completenessProfile: parseSensorAccumulatedChargeCompletenessProfile(r.completenessProfile),\n ...(r.additionalChargeComponents === undefined ? {} : { additionalChargeComponents:\n dense(r.additionalChargeComponents, 32).map(parseSensorAdditionalStoredChargeComponent) }) } as unknown as ComposeSensorAccumulatedChargeInput;\n // The existing charge composition checks that photo, dark, additional and completeness events agree exactly.\n composeSensorAccumulatedCharge(charge);\n return charge;\n}\nfunction localWindows(frame: SensorRawProducerInput[\"frame\"], value: unknown): CalculationResult<CaptureExposureWindows> {\n const r = fields(value, [\"shutterMechanism\", \"nominalExposureDurationSeconds\", \"opening\", \"closing\"]);\n fields(r.nominalExposureDurationSeconds, [\"value\", \"unit\", \"evidence\"]);\n for (const boundary of [r.opening, r.closing]) {\n const b = fields(boundary, [\"kind\", \"directionNative\", \"traversalDurationSeconds\"]);\n if (b.directionNative !== undefined) fields(b.directionNative, [\"value\", \"evidence\"]);\n if (b.traversalDurationSeconds !== undefined) fields(b.traversalDurationSeconds, [\"value\", \"unit\", \"evidence\"]);\n }\n const native = frame.capture.geometry.nativeRaster;\n const timing = calculateCaptureExposureWindows({\n ...r as unknown as SensorRawProducerExposureWindowInput,\n nativeRaster: native,\n samplePointsNative: Array.from({ length: native.pixelWidth*native.pixelHeight }, (_, i) => ({\n x: i%native.pixelWidth+0.5, y: Math.floor(i/native.pixelWidth)+0.5\n }))\n });\n if (timing.value.nominalExposureDurationSeconds.value !== frame.capture.exposure.shutterSeconds) {\n throw new InvalidConfigurationError(\"Exposure schedule nominal duration differs from committed capture.\");\n }\n return timing;\n}\nfunction sourceBoundary(schedule: CaptureExposureWindows[\"opening\"][\"schedule\"]): SensorRawProducerExposureWindowInput[\"opening\"] {\n return schedule.kind === \"simultaneous\" ? { kind: \"simultaneous\" } : {\n kind: \"uniform-linear-native-scan\", directionNative: schedule.directionNative,\n traversalDurationSeconds: schedule.traversalDurationSeconds\n };\n}\n/** Internal: per-site validation shared by the reference path and bounded packed execution. */\nexport type NativeRawProducerFrameContext = Omit<SensorRawProducerInput[\"frame\"], \"capture\"> & {\n capture: Pick<SensorRawProducerInput[\"frame\"][\"capture\"], \"geometry\" | \"exposure\" | \"noise\" | \"focus\" | \"sceneStateId\" | \"sceneTimeSeconds\">;\n};\nexport function parseNativeRawProducerSite(site: unknown, i: number, frame: NativeRawProducerFrameContext,\n window?: CaptureExposureWindows[\"samples\"][number]): SensorRawProducerSiteInput {\n const native = frame.capture.geometry.nativeRaster;\n const s = fields(site, [\"charge\", \"samplingProfile\", \"capacityProfile\", \"operatingStateId\", \"readoutProfile\", \"regimeId\", \"fixedPatternNoise\"]);\n const charge = chargeInput(s.charge), p = charge.photoSignal;\n const contributors = resolveCaptureModeColorSamplingContributors({ nativeRaster: native, captureModeProfile: frame.captureModeProfile,\n modeId: frame.modeId, colorSamplingProfile: frame.colorSamplingProfile, bindingProfile: frame.bindingProfile,\n modeSampleIndexFullFrame: { x: i%native.pixelWidth, y: Math.floor(i/native.pixelWidth) } });\n\n if (contributors.totalContributorSites !== 1 || contributors.channelComposition.kind !== \"single-channel\" ||\n p.colorSamplingProfileId !== frame.colorSamplingProfile.profileId || p.channelId !== contributors.channelComposition.channelId ||\n p.site.x !== contributors.colorSamplingSiteRect.x || p.site.y !== contributors.colorSamplingSiteRect.y ||\n p.bindingId !== frame.bindingProfile.bindingId || p.startOffsetSecondsFromOpeningReference !== (window?.startOffsetSecondsFromOpeningReference ?? 0) ||\n p.endOffsetSecondsFromOpeningReference !== (window?.endOffsetSecondsFromOpeningReference ?? frame.capture.exposure.shutterSeconds) ||\n p.localExposureDurationSeconds !== (window?.localExposureDurationSeconds ?? frame.capture.exposure.shutterSeconds)) {\n throw new InvalidConfigurationError(\"Charge site/channel/binding/local exposure differs from committed capture.\");\n }\n const readoutProfile = parseSensorReadoutConversionProfile(s.readoutProfile);\n const isoGain = readoutProfile.regimes.find((regime) => regime.regimeId === s.regimeId)?.exposureIndexGain;\n if (isoGain !== undefined && isoGain.exposureIndex !== frame.capture.exposure.iso) {\n throw new InvalidConfigurationError(\"Readout regime ISO gain differs from the committed capture ISO.\");\n }\n return { charge, samplingProfile: parseSensorChargeSamplingProfile(s.samplingProfile), capacityProfile: parseSensorPhysicalChargeCapacityProfile(s.capacityProfile),\n operatingStateId: publicId(s.operatingStateId), readoutProfile, regimeId: publicId(s.regimeId),\n ...(s.fixedPatternNoise === undefined ? {} : { fixedPatternNoise: parseSensorFixedPatternNoiseProfile(s.fixedPatternNoise) }) };\n}\nexport function validateNativeRawReadoutIdentity(s: SensorRawProducerSiteInput, first: SensorRawProducerSiteInput): void {\n publicIdentities(s);\n const readout = resolveSensorReadoutRegime({ profile: s.readoutProfile, regimeId: s.regimeId });\n if (s.readoutProfile.profileId !== first.readoutProfile.profileId || s.regimeId !== first.regimeId ||\n readout.regime.adc.bitDepth > 16 || readout.regime.adc.digitalSaturationCode <= readout.regime.adc.blackLevelCode ||\n s.readoutProfile.colorSamplingProfileId !== s.charge.photoSignal.colorSamplingProfileId ||\n s.readoutProfile.channelId !== s.charge.photoSignal.channelId || s.samplingProfile.completenessProfileId !== s.charge.completenessProfile.profileId ||\n s.fixedPatternNoise?.profileId !== first.fixedPatternNoise?.profileId ||\n s.fixedPatternNoise?.sensorInstanceSeedUint32 !== first.fixedPatternNoise?.sensorInstanceSeedUint32) {\n throw new InvalidConfigurationError(\"Frame requires one readout identity/regime, one fixed-pattern identity and a positive uint16 RAW code span.\");\n }\n}\n/** The shared per-site pipeline holds all the charge, capacity, random-noise and ADC equations. `i` is the absolute native row-major index. */\nexport function calculateNativeRawSite(s: SensorRawProducerSiteInput, seed: number, i: number): SensorRawProducerResult[\"sites\"][number] {\n const accumulatedCharge = composeSensorAccumulatedCharge(s.charge);\n const capacity = assessSensorPhysicalChargeCapacity({ accumulatedCharge: accumulatedCharge.value, capacityProfile: s.capacityProfile,\n operatingStateId: s.operatingStateId, operatingTemperatureC: s.charge.darkCharge.operatingTemperatureC });\n const pattern = s.fixedPatternNoise === undefined ? {} : { fixedPatternNoise: s.fixedPatternNoise };\n const realization = simulateSensorChargeRealization({ accumulatedCharge: accumulatedCharge.value, samplingProfile: s.samplingProfile,\n seedUint32: deriveNativeSiteStreamSeedUint32(seed, i, NATIVE_SITE_CHARGE_STREAM_ID), ...pattern });\n const readout = simulateSensorRawCode({ chargeRealization: realization.value, physicalCapacityAssessment: capacity.value,\n readoutProfile: s.readoutProfile, regimeId: s.regimeId,\n readNoiseSeedUint32: deriveNativeSiteStreamSeedUint32(seed, i, NATIVE_SITE_READ_NOISE_STREAM_ID), ...pattern });\n return { accumulatedCharge, capacity, realization, readout };\n}\n/** The selected regime's declared INL, which the effective white level needs at saturation. */\nfunction regimeInl(site: SensorRawProducerSiteInput): { adcIntegralNonLinearity?: NonNullable<SensorReadoutConversionProfile[\"regimes\"][number][\"adc\"][\"integralNonLinearity\"]> } {\n const inl = site.readoutProfile.regimes.find((r) => r.regimeId === site.regimeId)?.adc.integralNonLinearity;\n return inl === undefined ? {} : { adcIntegralNonLinearity: inl };\n}\n/** Validates the complete per-site exposure inputs. Charge, noise or RAW codes are never accepted as a shortcut. */\nexport function parseSensorRawProducerInput(value: unknown): SensorRawProducerInput {\n const r = fields(value, [\"frame\", \"sites\", \"exposureWindow\"]), f = fields(r.frame, [\"frameId\", \"capture\", \"modeId\", \"captureModeProfile\", \"colorSamplingProfile\", \"bindingProfile\", \"containerBitDepth\"]);\n const capture = parseSimulatedCapture(f.capture), native = capture.geometry.nativeRaster, count = native.pixelWidth*native.pixelHeight;\n const sites = dense(r.sites, RAW_REFERENCE_MAX_NATIVE_SITES);\n const frame = { frameId: publicId(f.frameId), capture, modeId: publicId(f.modeId), containerBitDepth: 16 as const,\n captureModeProfile: parseCaptureModeProfile(f.captureModeProfile), colorSamplingProfile: parseSensorColorSamplingProfile(f.colorSamplingProfile),\n bindingProfile: parseNativeEffectiveRasterColorSamplingBindingProfile(f.bindingProfile) };\n const mode = frame.captureModeProfile.modes.find((m) => m.modeId === frame.modeId);\n if (f.containerBitDepth !== 16 || count > RAW_REFERENCE_MAX_NATIVE_SITES || sites.length !== count ||\n capture.noise.model.id !== SENSOR_RAW_PRODUCER_NOISE_MODEL.id || capture.noise.model.version !== SENSOR_RAW_PRODUCER_NOISE_MODEL.version ||\n frame.colorSamplingProfile.layout.kind !== \"periodic-mosaic\" || !mode || mode.acquisition.kind !== \"single-frame\" ||\n mode.perFrameSampling.kind !== \"native-effective-raster\" || (mode.reconstructionStages?.length ?? 0) !== 0) {\n throw new InvalidConfigurationError(\"Producer requires exact noise identity and bounded single-frame native CFA coverage.\");\n }\n const timing = r.exposureWindow === undefined ? undefined : localWindows(frame, r.exposureWindow);\n const parsed = sites.map((site, i) => parseNativeRawProducerSite(site, i, frame, timing?.value.samples[i]));\n for (const site of parsed) validateNativeRawReadoutIdentity(site, parsed[0]!);\n publicIdentities(frame);\n return { frame, sites: parsed, ...(timing === undefined ? {} : { exposureWindow: {\n shutterMechanism: timing.value.shutterMechanism,\n nominalExposureDurationSeconds: timing.value.nominalExposureDurationSeconds,\n opening: sourceBoundary(timing.value.opening.schedule), closing: sourceBoundary(timing.value.closing.schedule)\n } }) };\n}\n/** Runs accumulated charge → capacity → Poisson noise → read noise and ADC → native sample → immutable frame. */\nexport function simulateSensorRawFrame(input: SensorRawProducerInput): CalculationResult<SensorRawProducerResult> {\n const v = parseSensorRawProducerInput(input), seed = v.frame.capture.noise.seedUint32;\n const sites = v.sites.map((s, i) => calculateNativeRawSite(s, seed, i));\n const native = v.frame.capture.geometry.nativeRaster;\n const samples = sites.map((s, i) => createSensorRawCaptureSample({ rawCode: s.readout.value,\n ...regimeInl(v.sites[i]!),\n contributors: resolveCaptureModeColorSamplingContributors({ nativeRaster: native, captureModeProfile: v.frame.captureModeProfile,\n modeId: v.frame.modeId, colorSamplingProfile: v.frame.colorSamplingProfile, bindingProfile: v.frame.bindingProfile,\n modeSampleIndexFullFrame: { x: i%native.pixelWidth, y: Math.floor(i/native.pixelWidth) } }) }));\n return approximationResult({ schemaVersion: SENSOR_RAW_PRODUCER_SCHEMA_VERSION, codeProducer: \"engine-charge-capacity-noise-adc\",\n upstreamOrigin: \"declared-eqe-and-dark-exposure-results\", upstreamRadiometryVerified: false,\n seedSchedule: \"murmur3-capture-seed-native-index-stream-v2\", frame: createSensorRawFrame({ ...v.frame, samples }), sites,\n ...(v.exposureWindow === undefined ? {} : { localExposureWindows: localWindows(v.frame, v.exposureWindow) }) },\n \"native-sensor-raw-frame-producer\", SENSOR_RAW_PRODUCER_SCHEMA_VERSION, [\n \"Untreated EQE/dark exposure results and completeness evidence are upstream declarations; source radiometry is not independently verified\",\n \"Native row-major site seeds are MurmurHash3_x86_32 of (capture seed, absolute native index, stream 0 charge / 1 read noise); deterministic and non-cryptographic\",\n \"Existing scalar capacity/noise/readout approximations retain distinct physical/pre-ADC/digital saturation diagnostics; no blooming\",\n \"Optional fixed-pattern noise is deterministic per sensor instance (its own seed and absolute colour-sampling site), independent of the capture seed\",\n \"Stationarity applies separately to every exact local window; no time-varying radiance integration, multi-frame acquisition, RGB-to-RAW conversion or production-stage activation\",\n \"Stored capture float planes remain independent; same-RAW export must use the returned frame's reconstruction handoff\"]);\n}\n"]}
|
|
@@ -15,10 +15,10 @@ import { chromaticAdaptationMatrix } from "./chromatic-adaptation.js";
|
|
|
15
15
|
import { parseSimulatedCapture } from "../capture/simulated-capture.js";
|
|
16
16
|
export const CAPTURE_COLOR_MODEL_VERSION = "0.1.0";
|
|
17
17
|
/** Explicit ideal colorimetric camera, not measured spectral sensor channels. */
|
|
18
|
-
export const VIRTUAL_COLOR_CAMERA_PROFILE = Object.freeze({ id: "photivra-colorimetric-rgb-d65", version: CAPTURE_COLOR_MODEL_VERSION });
|
|
18
|
+
export const VIRTUAL_COLOR_CAMERA_PROFILE = /* @__PURE__ */ Object.freeze({ id: "photivra-colorimetric-rgb-d65", version: CAPTURE_COLOR_MODEL_VERSION });
|
|
19
19
|
/** Linear light with sRGB primaries and a D65 white. No sRGB transfer curve is applied. */
|
|
20
|
-
export const LINEAR_CAPTURE_RGB_PROFILE = Object.freeze({ id: "linear-srgb-d65", version: CAPTURE_COLOR_MODEL_VERSION });
|
|
21
|
-
const D65 = Object.freeze({ x: .3127 / .3290, y: 1, z: (1 - .3127 - .3290) / .3290 });
|
|
20
|
+
export const LINEAR_CAPTURE_RGB_PROFILE = /* @__PURE__ */ Object.freeze({ id: "linear-srgb-d65", version: CAPTURE_COLOR_MODEL_VERSION });
|
|
21
|
+
const D65 = /* @__PURE__ */ Object.freeze({ x: .3127 / .3290, y: 1, z: (1 - .3127 - .3290) / .3290 });
|
|
22
22
|
const IDENTITY = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
|
|
23
23
|
function multiply(m, v) {
|
|
24
24
|
return m.map((r) => r[0] * v[0] + r[1] * v[1] + r[2] * v[2]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capture-color.js","sourceRoot":"","sources":["../../src/color/capture-color.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Colour for an ideal colorimetric capture: the versioned ideal camera basis, parsing of a capture\n * and its colour transform policy from untrusted JSON, and conversion to linear sRGB.\n *\n * The basis does not depend on rendering or serializer state.\n * @see docs/CAPTURE_COLOR.md for the equations, units, coordinate conventions, known blockers and\n * support limits.\n */\n\nimport { requireAllowlistedRecord, requirePublicOpaqueId } from \"../core/record-validation.js\";\nimport { calculatedResult, approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { InvalidScientificResultError } from \"../core/validation.js\";\nimport { chromaticAdaptationMatrix } from \"./chromatic-adaptation.js\";\nimport { parseSimulatedCapture, type SimulatedCapture, type CaptureLinearPlane, type CapturePublicProfileReference } from \"../capture/simulated-capture.js\";\n\nexport const CAPTURE_COLOR_MODEL_VERSION = \"0.1.0\" as const;\n/** Explicit ideal colorimetric camera, not measured spectral sensor channels. */\nexport const VIRTUAL_COLOR_CAMERA_PROFILE = Object.freeze({ id: \"photivra-colorimetric-rgb-d65\", version: CAPTURE_COLOR_MODEL_VERSION });\n/** Linear light with sRGB primaries and a D65 white. No sRGB transfer curve is applied. */\nexport const LINEAR_CAPTURE_RGB_PROFILE = Object.freeze({ id: \"linear-srgb-d65\", version: CAPTURE_COLOR_MODEL_VERSION });\nconst D65 = Object.freeze({ x: .3127/.3290, y: 1 as const, z: (1-.3127-.3290)/.3290 });\ntype Vector = readonly [number, number, number];\ntype Matrix = readonly [Vector, Vector, Vector];\nconst IDENTITY: Matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];\nfunction multiply(m: Matrix, v: Vector): Vector {\n return m.map((r) => r[0]*v[0]+r[1]*v[1]+r[2]*v[2]) as unknown as Vector;\n}\nfunction inverse(m: Matrix): Matrix {\n const [[a, b, c], [d, e, f], [g, h, i]] = m;\n const determinant = a*(e*i-f*h)-b*(d*i-f*g)+c*(d*h-e*g);\n return [[e*i-f*h, c*h-b*i, b*f-c*e], [f*g-d*i, a*i-c*g, c*d-a*f], [d*h-e*g, b*g-a*h, a*e-b*d]]\n .map((r) => r.map((v) => v/determinant)) as unknown as Matrix;\n}\n// Derive the basis independently from the published primary chromaticities, not from a copied matrix.\nconst primaries: readonly (readonly [number, number])[] = [[.64, .33], [.30, .60], [.15, .06]];\nconst columns = primaries.map(([x, y]): Vector => [x/y, 1, (1-x-y)/y]);\nconst basis = [0, 1, 2].map((i) => columns.map((c) => c[i]!)) as unknown as Matrix;\nconst scales = multiply(inverse(basis), [D65.x, 1, D65.z]);\nconst RGB_TO_XYZ = basis.map((row) => row.map((v, i) => v*scales[i]!)) as unknown as Matrix;\nconst XYZ_TO_RGB = inverse(RGB_TO_XYZ);\n\n/**\n * Cone-space transform for adapting to the adopted white. If omitted, the original\n * XYZ-diagonal scaling (model id `photivra-xyz-diagonal-adaptation`) is used unchanged.\n */\nexport type CaptureChromaticAdaptationTransform = \"bradford\" | \"cat16\";\nconst CAPTURE_ADAPTATION_TRANSFORMS: readonly string[] = [\"bradford\", \"cat16\"];\n/** One explicit colour interpretation. Gains and adaptation cannot both apply white balance by accident. */\nexport type CaptureColorWhiteBalance =\n | { kind: \"preserve-intent\" }\n | { kind: \"apply-resolved-rgb-gains\"; channelBasis: CapturePublicProfileReference }\n | { kind: \"adopted-white-xyz-scaling\"; transform?: CaptureChromaticAdaptationTransform };\n/** IDs name a new derived plane. The source capture is never changed. */\nexport interface CaptureColorTransformInput {\n capture: SimulatedCapture;\n sourcePlaneId: string;\n outputPlaneId: string;\n outputImageStateId: string;\n whiteBalance: CaptureColorWhiteBalance;\n}\n/** Profile data gives callers the complete row-major matrices and the conditions where they apply. */\nexport interface CaptureColorModel {\n version: typeof CAPTURE_COLOR_MODEL_VERSION;\n cameraProfile: CapturePublicProfileReference;\n outputProfile: CapturePublicProfileReference;\n referenceIlluminant: \"D65\";\n observer: \"cie-1931-2-degree\";\n referenceWhiteXyz: { x: number; y: 1; z: number };\n cameraRgbToXyz: Matrix;\n xyzToCameraRgb: Matrix;\n scientificStatus: \"calculated\";\n validConditions: readonly string[];\n publicEvidenceIds: readonly string[];\n}\n/** Returns the versioned ideal camera basis, independent of rendering/serializer state. */\nexport function resolveCaptureColorModel(): CaptureColorModel {\n return { version: CAPTURE_COLOR_MODEL_VERSION, cameraProfile: { ...VIRTUAL_COLOR_CAMERA_PROFILE },\n outputProfile: { ...LINEAR_CAPTURE_RGB_PROFILE }, referenceIlluminant: \"D65\", observer: \"cie-1931-2-degree\",\n referenceWhiteXyz: { ...D65 }, cameraRgbToXyz: RGB_TO_XYZ.map((r) => [...r]) as unknown as Matrix,\n xyzToCameraRgb: XYZ_TO_RGB.map((r) => [...r]) as unknown as Matrix, scientificStatus: \"calculated\",\n validConditions: [\"Ideal colorimetric basis only; virtual RGB is an invertible encoding of CIE XYZ\",\n \"Not spectral channels, electrons, commercial-camera RGB or a sensor calibration\",\n \"Signed finite scene-linear values; co-sited RGB; no transfer curve, gamut mapping or clipping\"],\n publicEvidenceIds: [\"w3c:css-color-4:srgb-primaries-d65\"] };\n}\nfunction record(v: unknown, keys: readonly string[]): Record<string, unknown> {\n return requireAllowlistedRecord(v, keys, \"Invalid color-transform fields.\");\n}\nfunction publicId(v: unknown): string {\n return requirePublicOpaqueId(v, \"Invalid public color ID.\");\n}\n/** Validates the whole capture and its explicit transform policy, read from untrusted JSON. */\nexport function parseCaptureColorTransformInput(value: unknown): CaptureColorTransformInput {\n const r = record(value, [\"capture\", \"sourcePlaneId\", \"outputPlaneId\", \"outputImageStateId\", \"whiteBalance\"]);\n const w = record(r.whiteBalance, [\"kind\", \"channelBasis\", \"transform\"]);\n let whiteBalance: CaptureColorWhiteBalance;\n if (w.kind === \"apply-resolved-rgb-gains\" && w.transform === undefined) {\n const p = record(w.channelBasis, [\"id\", \"version\"]);\n whiteBalance = { kind: w.kind, channelBasis: { id: publicId(p.id), version: publicId(p.version) } };\n } else if (w.kind === \"adopted-white-xyz-scaling\" && w.channelBasis === undefined && w.transform !== undefined) {\n if (typeof w.transform !== \"string\" || !CAPTURE_ADAPTATION_TRANSFORMS.includes(w.transform)) {\n throw new InvalidConfigurationError(\"Unsupported chromatic-adaptation transform.\");\n }\n whiteBalance = { kind: w.kind, transform: w.transform as CaptureChromaticAdaptationTransform };\n } else if ((w.kind === \"preserve-intent\" || w.kind === \"adopted-white-xyz-scaling\") && w.channelBasis === undefined && w.transform === undefined) {\n whiteBalance = { kind: w.kind };\n } else throw new InvalidConfigurationError(\"Unsupported or contradictory color WB policy.\");\n return { capture: parseSimulatedCapture(r.capture), sourcePlaneId: publicId(r.sourcePlaneId),\n outputPlaneId: publicId(r.outputPlaneId), outputImageStateId: publicId(r.outputImageStateId), whiteBalance };\n}\nexport interface CaptureColorTransformResult {\n plane: CaptureLinearPlane;\n colorModel: CaptureColorModel;\n sourcePlaneId: string;\n sourceImageStateId: string;\n whiteBalance: CaptureColorWhiteBalance;\n /** Matrix on CIE XYZ, identity when no adaptation; row-major, dimensionless. */\n chromaticAdaptationMatrix: Matrix;\n /** False: under mixed lighting, even scaling to the adopted white is a choice the camera makes. */\n claimsUniqueSceneWhite: false;\n}\nfunction adaptationProfileId(whiteBalance: CaptureColorWhiteBalance): string {\n return whiteBalance.kind === \"adopted-white-xyz-scaling\" && whiteBalance.transform !== undefined\n ? \"photivra-\" + whiteBalance.transform + \"-adaptation\"\n : \"photivra-xyz-diagonal-adaptation\";\n}\n/**\n * Converts a bounded inline XYZ (ideal-camera) plane to unclamped linear sRGB.\n * It reuses the resolved white-balance intent. It never estimates the lighting and never changes\n * exposure or noise. Adapting to the adopted white (XYZ diagonal by default, or an explicit\n * Bradford or CAT16 cone-space transform) is labelled an approximation, and\n * is separate from RGB gains.\n */\nexport function calculateCaptureColorTransform(input: CaptureColorTransformInput): CalculationResult<CaptureColorTransformResult> {\n const { capture, sourcePlaneId, outputPlaneId, outputImageStateId, whiteBalance } = parseCaptureColorTransformInput(input);\n const source = capture.planes.find((p) => p.id === sourcePlaneId);\n if (!source || source.storage.kind !== \"inline-float64\" || source.imageState === \"color-transformed-linear-rgb\" ||\n source.whiteBalanceApplication === \"applied-rgb-gains\" || source.whiteBalanceApplication === \"applied-chromatic-adaptation\" ||\n source.appliedTransforms.some((t) => t.kind !== \"digital-lens-correction\")) {\n throw new InvalidConfigurationError(\"Color requires an untreated inline XYZ or supported virtual camera plane.\");\n }\n if (capture.planes.some((p) => p.id === outputPlaneId || p.imageStateId === outputImageStateId)) {\n throw new InvalidConfigurationError(\"Derived color plane/state IDs must be new.\");\n }\n const virtual = source.imageState === \"virtual-sensor-channels\";\n if (virtual && (source.colorProfile?.id !== VIRTUAL_COLOR_CAMERA_PROFILE.id || source.colorProfile.version !== CAPTURE_COLOR_MODEL_VERSION ||\n JSON.stringify(source.channelIds) !== JSON.stringify([\"red\", \"green\", \"blue\"]))) {\n throw new InvalidConfigurationError(\"Unresolved spectral/sensor RGB cannot use the ideal colorimetric transform.\");\n }\n const adapt = whiteBalance.kind === \"adopted-white-xyz-scaling\";\n const reference = source.encodingReferenceWhiteXyz;\n if (!virtual && !adapt && (reference!.x !== D65.x || reference!.z !== D65.z)) {\n throw new InvalidConfigurationError(\"A different XYZ reference white requires an explicit adaptation choice.\");\n }\n const gains = whiteBalance.kind === \"apply-resolved-rgb-gains\";\n if (gains && (!capture.whiteBalanceIntent || whiteBalance.channelBasis.id !== VIRTUAL_COLOR_CAMERA_PROFILE.id ||\n whiteBalance.channelBasis.version !== CAPTURE_COLOR_MODEL_VERSION)) {\n throw new InvalidConfigurationError(\"Resolved WB gains require an explicit matching camera channel-basis binding.\");\n }\n let adaptation: Matrix = IDENTITY;\n if (adapt) {\n const white = capture.adoptedWhiteXyz;\n if (!white) throw new InvalidConfigurationError(\"Adopted-white adaptation requires an explicit adopted XYZ white.\");\n const x = D65.x/white.x, z = D65.z/white.z;\n if (!Number.isFinite(x) || !Number.isFinite(z) || x < 1e-6 || x > 1e6 || z < 1e-6 || z > 1e6) {\n throw new InvalidConfigurationError(\"Adopted-white scaling is outside the declared numerical domain.\");\n }\n if (whiteBalance.transform === undefined) adaptation = [[x, 0, 0], [0, 1, 0], [0, 0, z]];\n else {\n let m: Matrix;\n try {\n m = chromaticAdaptationMatrix({ transform: whiteBalance.transform, sourceWhiteXyz: white, destinationWhiteXyz: D65 }).matrix;\n } catch {\n throw new InvalidConfigurationError(\"Adopted-white adaptation is outside the transform's numerical domain.\");\n }\n if (m.flat().some((v) => Math.abs(v) > 1e6)) throw new InvalidConfigurationError(\"Adopted-white adaptation is outside the declared numerical domain.\");\n adaptation = m;\n }\n }\n const samples: number[] = [], values = source.storage.samples;\n for (let i = 0; i < values.length; i += 3) {\n const v: Vector = [values[i]!, values[i+1]!, values[i+2]!];\n let rgb = virtual && !adapt ? v : multiply(XYZ_TO_RGB, multiply(adaptation, virtual ? multiply(RGB_TO_XYZ, v) : v));\n if (gains) {\n const g = capture.whiteBalanceIntent!.channelGains;\n rgb = [rgb[0]*g.red, rgb[1]*g.green, rgb[2]*g.blue];\n }\n if (rgb.some((v) => !Number.isFinite(v))) throw new InvalidScientificResultError(\"Color transform produced a non-finite sample.\");\n samples.push(...rgb.map((v) => Object.is(v, -0) ? 0 : v));\n }\n const transforms: CaptureLinearPlane[\"appliedTransforms\"][number][] = [...source.appliedTransforms];\n if (adapt) transforms.push({ profile: { id: adaptationProfileId(whiteBalance), version: CAPTURE_COLOR_MODEL_VERSION }, kind: \"chromatic-adaptation\" });\n transforms.push({ profile: { ...LINEAR_CAPTURE_RGB_PROFILE }, kind: \"linear-color\" });\n if (gains) transforms.push({ profile: { id: capture.whiteBalanceIntent!.stateId, version: CAPTURE_COLOR_MODEL_VERSION }, kind: \"linear-color\" });\n const plane: CaptureLinearPlane = { ...source, id: outputPlaneId, imageStateId: outputImageStateId,\n imageState: \"color-transformed-linear-rgb\", channelIds: [\"red\", \"green\", \"blue\"], colorProfile: { ...LINEAR_CAPTURE_RGB_PROFILE },\n encodingReferenceWhiteXyz: { ...D65 }, appliedTransforms: transforms,\n whiteBalanceApplication: gains ? \"applied-rgb-gains\" : adapt ? \"applied-chromatic-adaptation\" : capture.whiteBalanceIntent ? \"intent-only\" : \"not-applicable\",\n storage: { kind: \"inline-float64\", samples } };\n // Validation enforces the capture-wide sample budget, the identities and finite output.\n const checked = parseSimulatedCapture({ ...capture, planes: [plane] }).planes[0]!;\n const result: CaptureColorTransformResult = { plane: checked, colorModel: resolveCaptureColorModel(), sourcePlaneId,\n sourceImageStateId: source.imageStateId, whiteBalance, chromaticAdaptationMatrix: adaptation.map((r) => [...r]) as unknown as Matrix,\n claimsUniqueSceneWhite: false };\n const assumptions = [\"Ideal CIE colorimetric virtual camera only; no sensor calibration inferred\", \"Source exposure/noise/saturation history retained; float samples never clipped\",\n \"WB intent, applied RGB gains and adopted-white adaptation are independent choices; no scene-white oracle\"];\n const transform = whiteBalance.kind === \"adopted-white-xyz-scaling\" ? whiteBalance.transform : undefined;\n return adapt ? transform === undefined\n ? approximationResult(result, \"capture-color-xyz-diagonal-adaptation\", CAPTURE_COLOR_MODEL_VERSION,\n [...assumptions, \"XYZ diagonal scaling is a limited chromatic-adaptation approximation, not Bradford or a color-appearance model\"])\n : approximationResult(result, \"capture-color-\" + transform + \"-adaptation\", CAPTURE_COLOR_MODEL_VERSION,\n [...assumptions, \"Complete (D = 1) linear \" + transform + \" von Kries-type adaptation to D65; corresponding-colour prediction is approximate and no color-appearance model is applied\"])\n : calculatedResult(result, \"capture-colorimetric-linear-rgb\", CAPTURE_COLOR_MODEL_VERSION, assumptions);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"capture-color.js","sourceRoot":"","sources":["../../src/color/capture-color.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Colour for an ideal colorimetric capture: the versioned ideal camera basis, parsing of a capture\n * and its colour transform policy from untrusted JSON, and conversion to linear sRGB.\n *\n * The basis does not depend on rendering or serializer state.\n * @see docs/CAPTURE_COLOR.md for the equations, units, coordinate conventions, known blockers and\n * support limits.\n */\n\nimport { requireAllowlistedRecord, requirePublicOpaqueId } from \"../core/record-validation.js\";\nimport { calculatedResult, approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { InvalidScientificResultError } from \"../core/validation.js\";\nimport { chromaticAdaptationMatrix } from \"./chromatic-adaptation.js\";\nimport { parseSimulatedCapture, type SimulatedCapture, type CaptureLinearPlane, type CapturePublicProfileReference } from \"../capture/simulated-capture.js\";\n\nexport const CAPTURE_COLOR_MODEL_VERSION = \"0.1.0\" as const;\n/** Explicit ideal colorimetric camera, not measured spectral sensor channels. */\nexport const VIRTUAL_COLOR_CAMERA_PROFILE = /* @__PURE__ */ Object.freeze({ id: \"photivra-colorimetric-rgb-d65\", version: CAPTURE_COLOR_MODEL_VERSION });\n/** Linear light with sRGB primaries and a D65 white. No sRGB transfer curve is applied. */\nexport const LINEAR_CAPTURE_RGB_PROFILE = /* @__PURE__ */ Object.freeze({ id: \"linear-srgb-d65\", version: CAPTURE_COLOR_MODEL_VERSION });\nconst D65 = /* @__PURE__ */ Object.freeze({ x: .3127/.3290, y: 1 as const, z: (1-.3127-.3290)/.3290 });\ntype Vector = readonly [number, number, number];\ntype Matrix = readonly [Vector, Vector, Vector];\nconst IDENTITY: Matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];\nfunction multiply(m: Matrix, v: Vector): Vector {\n return m.map((r) => r[0]*v[0]+r[1]*v[1]+r[2]*v[2]) as unknown as Vector;\n}\nfunction inverse(m: Matrix): Matrix {\n const [[a, b, c], [d, e, f], [g, h, i]] = m;\n const determinant = a*(e*i-f*h)-b*(d*i-f*g)+c*(d*h-e*g);\n return [[e*i-f*h, c*h-b*i, b*f-c*e], [f*g-d*i, a*i-c*g, c*d-a*f], [d*h-e*g, b*g-a*h, a*e-b*d]]\n .map((r) => r.map((v) => v/determinant)) as unknown as Matrix;\n}\n// Derive the basis independently from the published primary chromaticities, not from a copied matrix.\nconst primaries: readonly (readonly [number, number])[] = [[.64, .33], [.30, .60], [.15, .06]];\nconst columns = primaries.map(([x, y]): Vector => [x/y, 1, (1-x-y)/y]);\nconst basis = [0, 1, 2].map((i) => columns.map((c) => c[i]!)) as unknown as Matrix;\nconst scales = multiply(inverse(basis), [D65.x, 1, D65.z]);\nconst RGB_TO_XYZ = basis.map((row) => row.map((v, i) => v*scales[i]!)) as unknown as Matrix;\nconst XYZ_TO_RGB = inverse(RGB_TO_XYZ);\n\n/**\n * Cone-space transform for adapting to the adopted white. If omitted, the original\n * XYZ-diagonal scaling (model id `photivra-xyz-diagonal-adaptation`) is used unchanged.\n */\nexport type CaptureChromaticAdaptationTransform = \"bradford\" | \"cat16\";\nconst CAPTURE_ADAPTATION_TRANSFORMS: readonly string[] = [\"bradford\", \"cat16\"];\n/** One explicit colour interpretation. Gains and adaptation cannot both apply white balance by accident. */\nexport type CaptureColorWhiteBalance =\n | { kind: \"preserve-intent\" }\n | { kind: \"apply-resolved-rgb-gains\"; channelBasis: CapturePublicProfileReference }\n | { kind: \"adopted-white-xyz-scaling\"; transform?: CaptureChromaticAdaptationTransform };\n/** IDs name a new derived plane. The source capture is never changed. */\nexport interface CaptureColorTransformInput {\n capture: SimulatedCapture;\n sourcePlaneId: string;\n outputPlaneId: string;\n outputImageStateId: string;\n whiteBalance: CaptureColorWhiteBalance;\n}\n/** Profile data gives callers the complete row-major matrices and the conditions where they apply. */\nexport interface CaptureColorModel {\n version: typeof CAPTURE_COLOR_MODEL_VERSION;\n cameraProfile: CapturePublicProfileReference;\n outputProfile: CapturePublicProfileReference;\n referenceIlluminant: \"D65\";\n observer: \"cie-1931-2-degree\";\n referenceWhiteXyz: { x: number; y: 1; z: number };\n cameraRgbToXyz: Matrix;\n xyzToCameraRgb: Matrix;\n scientificStatus: \"calculated\";\n validConditions: readonly string[];\n publicEvidenceIds: readonly string[];\n}\n/** Returns the versioned ideal camera basis, independent of rendering/serializer state. */\nexport function resolveCaptureColorModel(): CaptureColorModel {\n return { version: CAPTURE_COLOR_MODEL_VERSION, cameraProfile: { ...VIRTUAL_COLOR_CAMERA_PROFILE },\n outputProfile: { ...LINEAR_CAPTURE_RGB_PROFILE }, referenceIlluminant: \"D65\", observer: \"cie-1931-2-degree\",\n referenceWhiteXyz: { ...D65 }, cameraRgbToXyz: RGB_TO_XYZ.map((r) => [...r]) as unknown as Matrix,\n xyzToCameraRgb: XYZ_TO_RGB.map((r) => [...r]) as unknown as Matrix, scientificStatus: \"calculated\",\n validConditions: [\"Ideal colorimetric basis only; virtual RGB is an invertible encoding of CIE XYZ\",\n \"Not spectral channels, electrons, commercial-camera RGB or a sensor calibration\",\n \"Signed finite scene-linear values; co-sited RGB; no transfer curve, gamut mapping or clipping\"],\n publicEvidenceIds: [\"w3c:css-color-4:srgb-primaries-d65\"] };\n}\nfunction record(v: unknown, keys: readonly string[]): Record<string, unknown> {\n return requireAllowlistedRecord(v, keys, \"Invalid color-transform fields.\");\n}\nfunction publicId(v: unknown): string {\n return requirePublicOpaqueId(v, \"Invalid public color ID.\");\n}\n/** Validates the whole capture and its explicit transform policy, read from untrusted JSON. */\nexport function parseCaptureColorTransformInput(value: unknown): CaptureColorTransformInput {\n const r = record(value, [\"capture\", \"sourcePlaneId\", \"outputPlaneId\", \"outputImageStateId\", \"whiteBalance\"]);\n const w = record(r.whiteBalance, [\"kind\", \"channelBasis\", \"transform\"]);\n let whiteBalance: CaptureColorWhiteBalance;\n if (w.kind === \"apply-resolved-rgb-gains\" && w.transform === undefined) {\n const p = record(w.channelBasis, [\"id\", \"version\"]);\n whiteBalance = { kind: w.kind, channelBasis: { id: publicId(p.id), version: publicId(p.version) } };\n } else if (w.kind === \"adopted-white-xyz-scaling\" && w.channelBasis === undefined && w.transform !== undefined) {\n if (typeof w.transform !== \"string\" || !CAPTURE_ADAPTATION_TRANSFORMS.includes(w.transform)) {\n throw new InvalidConfigurationError(\"Unsupported chromatic-adaptation transform.\");\n }\n whiteBalance = { kind: w.kind, transform: w.transform as CaptureChromaticAdaptationTransform };\n } else if ((w.kind === \"preserve-intent\" || w.kind === \"adopted-white-xyz-scaling\") && w.channelBasis === undefined && w.transform === undefined) {\n whiteBalance = { kind: w.kind };\n } else throw new InvalidConfigurationError(\"Unsupported or contradictory color WB policy.\");\n return { capture: parseSimulatedCapture(r.capture), sourcePlaneId: publicId(r.sourcePlaneId),\n outputPlaneId: publicId(r.outputPlaneId), outputImageStateId: publicId(r.outputImageStateId), whiteBalance };\n}\nexport interface CaptureColorTransformResult {\n plane: CaptureLinearPlane;\n colorModel: CaptureColorModel;\n sourcePlaneId: string;\n sourceImageStateId: string;\n whiteBalance: CaptureColorWhiteBalance;\n /** Matrix on CIE XYZ, identity when no adaptation; row-major, dimensionless. */\n chromaticAdaptationMatrix: Matrix;\n /** False: under mixed lighting, even scaling to the adopted white is a choice the camera makes. */\n claimsUniqueSceneWhite: false;\n}\nfunction adaptationProfileId(whiteBalance: CaptureColorWhiteBalance): string {\n return whiteBalance.kind === \"adopted-white-xyz-scaling\" && whiteBalance.transform !== undefined\n ? \"photivra-\" + whiteBalance.transform + \"-adaptation\"\n : \"photivra-xyz-diagonal-adaptation\";\n}\n/**\n * Converts a bounded inline XYZ (ideal-camera) plane to unclamped linear sRGB.\n * It reuses the resolved white-balance intent. It never estimates the lighting and never changes\n * exposure or noise. Adapting to the adopted white (XYZ diagonal by default, or an explicit\n * Bradford or CAT16 cone-space transform) is labelled an approximation, and\n * is separate from RGB gains.\n */\nexport function calculateCaptureColorTransform(input: CaptureColorTransformInput): CalculationResult<CaptureColorTransformResult> {\n const { capture, sourcePlaneId, outputPlaneId, outputImageStateId, whiteBalance } = parseCaptureColorTransformInput(input);\n const source = capture.planes.find((p) => p.id === sourcePlaneId);\n if (!source || source.storage.kind !== \"inline-float64\" || source.imageState === \"color-transformed-linear-rgb\" ||\n source.whiteBalanceApplication === \"applied-rgb-gains\" || source.whiteBalanceApplication === \"applied-chromatic-adaptation\" ||\n source.appliedTransforms.some((t) => t.kind !== \"digital-lens-correction\")) {\n throw new InvalidConfigurationError(\"Color requires an untreated inline XYZ or supported virtual camera plane.\");\n }\n if (capture.planes.some((p) => p.id === outputPlaneId || p.imageStateId === outputImageStateId)) {\n throw new InvalidConfigurationError(\"Derived color plane/state IDs must be new.\");\n }\n const virtual = source.imageState === \"virtual-sensor-channels\";\n if (virtual && (source.colorProfile?.id !== VIRTUAL_COLOR_CAMERA_PROFILE.id || source.colorProfile.version !== CAPTURE_COLOR_MODEL_VERSION ||\n JSON.stringify(source.channelIds) !== JSON.stringify([\"red\", \"green\", \"blue\"]))) {\n throw new InvalidConfigurationError(\"Unresolved spectral/sensor RGB cannot use the ideal colorimetric transform.\");\n }\n const adapt = whiteBalance.kind === \"adopted-white-xyz-scaling\";\n const reference = source.encodingReferenceWhiteXyz;\n if (!virtual && !adapt && (reference!.x !== D65.x || reference!.z !== D65.z)) {\n throw new InvalidConfigurationError(\"A different XYZ reference white requires an explicit adaptation choice.\");\n }\n const gains = whiteBalance.kind === \"apply-resolved-rgb-gains\";\n if (gains && (!capture.whiteBalanceIntent || whiteBalance.channelBasis.id !== VIRTUAL_COLOR_CAMERA_PROFILE.id ||\n whiteBalance.channelBasis.version !== CAPTURE_COLOR_MODEL_VERSION)) {\n throw new InvalidConfigurationError(\"Resolved WB gains require an explicit matching camera channel-basis binding.\");\n }\n let adaptation: Matrix = IDENTITY;\n if (adapt) {\n const white = capture.adoptedWhiteXyz;\n if (!white) throw new InvalidConfigurationError(\"Adopted-white adaptation requires an explicit adopted XYZ white.\");\n const x = D65.x/white.x, z = D65.z/white.z;\n if (!Number.isFinite(x) || !Number.isFinite(z) || x < 1e-6 || x > 1e6 || z < 1e-6 || z > 1e6) {\n throw new InvalidConfigurationError(\"Adopted-white scaling is outside the declared numerical domain.\");\n }\n if (whiteBalance.transform === undefined) adaptation = [[x, 0, 0], [0, 1, 0], [0, 0, z]];\n else {\n let m: Matrix;\n try {\n m = chromaticAdaptationMatrix({ transform: whiteBalance.transform, sourceWhiteXyz: white, destinationWhiteXyz: D65 }).matrix;\n } catch {\n throw new InvalidConfigurationError(\"Adopted-white adaptation is outside the transform's numerical domain.\");\n }\n if (m.flat().some((v) => Math.abs(v) > 1e6)) throw new InvalidConfigurationError(\"Adopted-white adaptation is outside the declared numerical domain.\");\n adaptation = m;\n }\n }\n const samples: number[] = [], values = source.storage.samples;\n for (let i = 0; i < values.length; i += 3) {\n const v: Vector = [values[i]!, values[i+1]!, values[i+2]!];\n let rgb = virtual && !adapt ? v : multiply(XYZ_TO_RGB, multiply(adaptation, virtual ? multiply(RGB_TO_XYZ, v) : v));\n if (gains) {\n const g = capture.whiteBalanceIntent!.channelGains;\n rgb = [rgb[0]*g.red, rgb[1]*g.green, rgb[2]*g.blue];\n }\n if (rgb.some((v) => !Number.isFinite(v))) throw new InvalidScientificResultError(\"Color transform produced a non-finite sample.\");\n samples.push(...rgb.map((v) => Object.is(v, -0) ? 0 : v));\n }\n const transforms: CaptureLinearPlane[\"appliedTransforms\"][number][] = [...source.appliedTransforms];\n if (adapt) transforms.push({ profile: { id: adaptationProfileId(whiteBalance), version: CAPTURE_COLOR_MODEL_VERSION }, kind: \"chromatic-adaptation\" });\n transforms.push({ profile: { ...LINEAR_CAPTURE_RGB_PROFILE }, kind: \"linear-color\" });\n if (gains) transforms.push({ profile: { id: capture.whiteBalanceIntent!.stateId, version: CAPTURE_COLOR_MODEL_VERSION }, kind: \"linear-color\" });\n const plane: CaptureLinearPlane = { ...source, id: outputPlaneId, imageStateId: outputImageStateId,\n imageState: \"color-transformed-linear-rgb\", channelIds: [\"red\", \"green\", \"blue\"], colorProfile: { ...LINEAR_CAPTURE_RGB_PROFILE },\n encodingReferenceWhiteXyz: { ...D65 }, appliedTransforms: transforms,\n whiteBalanceApplication: gains ? \"applied-rgb-gains\" : adapt ? \"applied-chromatic-adaptation\" : capture.whiteBalanceIntent ? \"intent-only\" : \"not-applicable\",\n storage: { kind: \"inline-float64\", samples } };\n // Validation enforces the capture-wide sample budget, the identities and finite output.\n const checked = parseSimulatedCapture({ ...capture, planes: [plane] }).planes[0]!;\n const result: CaptureColorTransformResult = { plane: checked, colorModel: resolveCaptureColorModel(), sourcePlaneId,\n sourceImageStateId: source.imageStateId, whiteBalance, chromaticAdaptationMatrix: adaptation.map((r) => [...r]) as unknown as Matrix,\n claimsUniqueSceneWhite: false };\n const assumptions = [\"Ideal CIE colorimetric virtual camera only; no sensor calibration inferred\", \"Source exposure/noise/saturation history retained; float samples never clipped\",\n \"WB intent, applied RGB gains and adopted-white adaptation are independent choices; no scene-white oracle\"];\n const transform = whiteBalance.kind === \"adopted-white-xyz-scaling\" ? whiteBalance.transform : undefined;\n return adapt ? transform === undefined\n ? approximationResult(result, \"capture-color-xyz-diagonal-adaptation\", CAPTURE_COLOR_MODEL_VERSION,\n [...assumptions, \"XYZ diagonal scaling is a limited chromatic-adaptation approximation, not Bradford or a color-appearance model\"])\n : approximationResult(result, \"capture-color-\" + transform + \"-adaptation\", CAPTURE_COLOR_MODEL_VERSION,\n [...assumptions, \"Complete (D = 1) linear \" + transform + \" von Kries-type adaptation to D65; corresponding-colour prediction is approximate and no color-appearance model is applied\"])\n : calculatedResult(result, \"capture-colorimetric-linear-rgb\", CAPTURE_COLOR_MODEL_VERSION, assumptions);\n}\n"]}
|
|
@@ -29,8 +29,8 @@ import { COLORIMETRY_MODEL_VERSION } from "./color-matching-functions.js";
|
|
|
29
29
|
import { copyMatrix, diagonalMatrix, invertMatrix3x3, multiplyMatrices, multiplyMatrixVector, parseWhiteXyz, parseXyz, requireFiniteResult, requireNonNegativeNumber, vectorToXyz, xyzToVector } from "./colorimetry-math.js";
|
|
30
30
|
import { requireInputKeys } from "../core/record-validation.js";
|
|
31
31
|
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
32
|
-
export const CHROMATIC_ADAPTATION_TRANSFORMS = Object.freeze(["bradford", "cat16", "xyz-scaling"]);
|
|
33
|
-
const CONE_MATRICES = Object.freeze({
|
|
32
|
+
export const CHROMATIC_ADAPTATION_TRANSFORMS = /* @__PURE__ */ Object.freeze(["bradford", "cat16", "xyz-scaling"]);
|
|
33
|
+
const CONE_MATRICES = /* @__PURE__ */ Object.freeze({
|
|
34
34
|
bradford: [[0.8951, 0.2664, -0.1614], [-0.7502, 1.7135, 0.0367], [0.0389, -0.0685, 1.0296]],
|
|
35
35
|
cat16: [[0.401288, 0.650173, -0.051461], [-0.250268, 1.204414, 0.045854], [-0.002079, 0.048952, 0.953127]],
|
|
36
36
|
"xyz-scaling": [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chromatic-adaptation.js","sourceRoot":"","sources":["../../src/color/chromatic-adaptation.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,gBAAgB,EAA0B,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EACL,UAAU,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,QAAQ,EACR,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,WAAW,EAGZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAK3E,MAAM,CAAC,MAAM,+BAA+B,GAA4C,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;AAE5I,MAAM,aAAa,GAAmE,MAAM,CAAC,MAAM,CAAC;IAClG,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3F,KAAK,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC1G,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CACjD,CAAC,CAAC;AAEH,SAAS,gBAAgB,CAAC,KAAc;IACtC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAE,+BAAqD,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACzG,MAAM,IAAI,yBAAyB,CAAC,4BAA4B,GAAG,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;IACvH,CAAC;IACD,OAAO,KAAqC,CAAC;AAC/C,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,oCAAoC,CAAC,SAAuC;IAC1F,OAAO,UAAU,CAAC,aAAa,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAqBD,kEAAkE;AAClE,MAAM,UAAU,yBAAyB,CAAC,KAA8C;IACtF,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;IACrE,MAAM,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC,mBAAmB,EAAE,qBAAqB,CAAC,CAAC;IACpF,MAAM,CAAC,GAAG,KAAK,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,KAAK,CAAC,kBAAkB,EAAE,oBAAoB,CAAC,CAAC;IAChI,IAAI,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,2BAA2B,CAAC,wCAAwC,CAAC,CAAC;IAC3F,MAAM,IAAI,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IACtC,MAAM,EAAE,GAAG,oBAAoB,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3D,MAAM,EAAE,GAAG,oBAAoB,CAAC,IAAI,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC;IAChE,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,2BAA2B,CAAC,0EAA0E,CAAC,CAAC;IACpH,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAE,GAAG,EAAE,CAAC,CAAC,CAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAiD,CAAC;IAC3H,MAAM,MAAM,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,eAAe,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACrH,mBAAmB,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,sBAAsB,CAAC,CAAC;IAC3D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AACxE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kCAAkC,CAAC,KAA8C;IAC/F,gBAAgB,CAAC,KAAK,EAAE,oCAAoC,EAAE,CAAC,WAAW,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAC5I,MAAM,KAAK,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO,gBAAgB,CAAC,KAAK,EAAE,uBAAuB,GAAG,KAAK,CAAC,SAAS,EAAE,yBAAyB,EAAE;QACnG,yEAAyE;QACzE,uGAAuG;KACxG,CAAC,CAAC;AACL,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,gCAAgC,CAAC,KAA2E;IAC1H,gBAAgB,CAAC,KAAK,EAAE,kCAAkC,EAAE,CAAC,WAAW,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,KAAK,CAAC,CAAC,CAAC;IACjJ,MAAM,UAAU,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,WAAW,CAAC,oBAAoB,CAAC,UAAU,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1G,mBAAmB,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;IACnE,OAAO,gBAAgB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,EAAE,uBAAuB,GAAG,UAAU,CAAC,SAAS,EAAE,yBAAyB,EAAE;QACrI,wDAAwD,GAAG,UAAU,CAAC,kBAAkB;KACzF,CAAC,CAAC;AACL,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Von Kries-type linear chromatic adaptation transforms (CATs) on CIE XYZ:\n * M = C⁻¹ · diag(Dᵢ) · C, Dᵢ = D · (Y_s / Y_d) · (ρᵢ,d / ρᵢ,s) + 1 − D\n * where C maps XYZ to a cone-like (\"sharpened\") space, ρ_s and ρ_d are the source and\n * destination whites in that space, and D ∈ [0, 1] is the degree of adaptation. This is\n * the one-step, two-illuminant form of Li et al. (2017) for CAT16; it is used for every\n * transform here. With D = 1 and equal white luminance, the source white maps exactly to\n * the destination white.\n *\n * Cone matrices (published factual constants):\n * - Bradford (linearized): Lam (1985) thesis, University of Bradford; Luo & Rhodes\n * (1999); as used in ICC.1:2010 Annex E. The original blue-channel non-linearity is\n * omitted, as in common practice.\n * - CAT16: Li, Li, Wang, Xu, Luo, Cui, Melgosa & Pointer (2016), \"A Revision of CIECAM02\n * and its CAT and UCS\", IS&T CIC24, pp. 208–212, Eq. (15) (M16),\n * doi:10.2352/ISSN.2169-2629.2017.32.208 (free from the IS&T library). Journal version:\n * Li et al. (2017), \"Comprehensive color solutions: CAM16, CAT16, and CAM16-UCS\",\n * Color Res. Appl. 42(6):703–718.\n * - XYZ scaling: identity cone matrix (diagonal scaling in XYZ; the weakest model).\n * The degree of adaptation D is supplied by the caller (default 1, complete adaptation).\n * CAT02, the von Kries Hunt–Pointer–Estévez matrix and the CIECAM02 formula for D are not\n * part of 2.0: no free source we could confirm prints them (owner decisions, 2026-10-17).\n * @see docs/COLORIMETRY.md for equations, coordinate/unit conventions and limits.\n */\n\nimport { calculatedResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport { COLORIMETRY_MODEL_VERSION } from \"./color-matching-functions.js\";\nimport {\n copyMatrix,\n diagonalMatrix,\n invertMatrix3x3,\n multiplyMatrices,\n multiplyMatrixVector,\n parseWhiteXyz,\n parseXyz,\n requireFiniteResult,\n requireNonNegativeNumber,\n vectorToXyz,\n xyzToVector,\n type CieXyzTristimulus,\n type ColorMatrix3x3\n} from \"./colorimetry-math.js\";\nimport { requireInputKeys } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\n/** Supported linear chromatic-adaptation transforms. */\nexport type ChromaticAdaptationTransform = \"bradford\" | \"cat16\" | \"xyz-scaling\";\n\nexport const CHROMATIC_ADAPTATION_TRANSFORMS: readonly ChromaticAdaptationTransform[] = Object.freeze([\"bradford\", \"cat16\", \"xyz-scaling\"]);\n\nconst CONE_MATRICES: Readonly<Record<ChromaticAdaptationTransform, ColorMatrix3x3>> = Object.freeze({\n bradford: [[0.8951, 0.2664, -0.1614], [-0.7502, 1.7135, 0.0367], [0.0389, -0.0685, 1.0296]],\n cat16: [[0.401288, 0.650173, -0.051461], [-0.250268, 1.204414, 0.045854], [-0.002079, 0.048952, 0.953127]],\n \"xyz-scaling\": [[1, 0, 0], [0, 1, 0], [0, 0, 1]]\n});\n\nfunction requireTransform(value: unknown): ChromaticAdaptationTransform {\n if (typeof value !== \"string\" || !(CHROMATIC_ADAPTATION_TRANSFORMS as readonly string[]).includes(value)) {\n throw new InvalidConfigurationError(\"transform must be one of: \" + CHROMATIC_ADAPTATION_TRANSFORMS.join(\", \") + \".\");\n }\n return value as ChromaticAdaptationTransform;\n}\n\n/** Returns a copy of the XYZ → cone-space matrix of a transform. */\nexport function resolveChromaticAdaptationConeMatrix(transform: ChromaticAdaptationTransform): ColorMatrix3x3 {\n return copyMatrix(CONE_MATRICES[requireTransform(transform)]);\n}\n\nexport interface CalculateChromaticAdaptationMatrixInput {\n transform: ChromaticAdaptationTransform;\n /** White of the source viewing/illumination condition (relative XYZ, Y > 0). */\n sourceWhiteXyz: CieXyzTristimulus;\n /** White of the destination condition (relative XYZ, Y > 0). */\n destinationWhiteXyz: CieXyzTristimulus;\n /** Degree of adaptation D in [0, 1]; defaults to 1 (complete adaptation). */\n degreeOfAdaptation?: number;\n}\n\nexport interface ChromaticAdaptationMatrix {\n transform: ChromaticAdaptationTransform;\n degreeOfAdaptation: number;\n /** Row-major XYZ_source → XYZ_destination matrix. */\n matrix: ColorMatrix3x3;\n /** The per-channel cone-space gains Dᵢ. */\n coneGains: readonly [number, number, number];\n}\n\n/** Internal: builds the adaptation matrix without an envelope. */\nexport function chromaticAdaptationMatrix(input: CalculateChromaticAdaptationMatrixInput): ChromaticAdaptationMatrix {\n const transform = requireTransform(input.transform);\n const source = parseWhiteXyz(input.sourceWhiteXyz, \"sourceWhiteXyz\");\n const destination = parseWhiteXyz(input.destinationWhiteXyz, \"destinationWhiteXyz\");\n const d = input.degreeOfAdaptation === undefined ? 1 : requireNonNegativeNumber(input.degreeOfAdaptation, \"degreeOfAdaptation\");\n if (d > 1) throw new InvalidScientificInputError(\"degreeOfAdaptation must lie in [0, 1].\");\n const cone = CONE_MATRICES[transform];\n const rs = multiplyMatrixVector(cone, xyzToVector(source));\n const rd = multiplyMatrixVector(cone, xyzToVector(destination));\n if (rs.some((v) => !(v > 0)) || rd.some((v) => !(v > 0))) {\n throw new InvalidScientificInputError(\"Both whites must have positive cone responses in the selected transform.\");\n }\n const yRatio = source.y / destination.y;\n const gains = [0, 1, 2].map((i) => d * yRatio * (rd[i]! / rs[i]!) + 1 - d) as unknown as readonly [number, number, number];\n const matrix = multiplyMatrices(multiplyMatrices(invertMatrix3x3(cone, \"cone matrix\"), diagonalMatrix(gains)), cone);\n requireFiniteResult(matrix.flat(), \"Chromatic adaptation\");\n return { transform, degreeOfAdaptation: d, matrix, coneGains: gains };\n}\n\n/**\n * Calculates a linear chromatic-adaptation matrix between two whites. Linear CATs are\n * standard models, but they predict corresponding colours only approximately. The matrix\n * itself is calculated exactly from the declared transform.\n */\nexport function calculateChromaticAdaptationMatrix(input: CalculateChromaticAdaptationMatrixInput): CalculationResult<ChromaticAdaptationMatrix> {\n requireInputKeys(input, \"calculateChromaticAdaptationMatrix\", [\"transform\", \"sourceWhiteXyz\", \"destinationWhiteXyz\", \"degreeOfAdaptation\"]);\n const value = chromaticAdaptationMatrix(input);\n return calculatedResult(value, \"chromatic-adaptation-\" + value.transform, COLORIMETRY_MODEL_VERSION, [\n \"Linear von Kries-type transform M = C⁻¹·diag(D·(Ys/Yd)·ρd/ρs + 1 − D)·C\",\n \"A linear CAT predicts corresponding colours only approximately; no colour-appearance model is applied\"\n ]);\n}\n\n/** Adapts one XYZ colour between whites with the selected transform. */\nexport function calculateChromaticallyAdaptedXyz(input: CalculateChromaticAdaptationMatrixInput & { xyz: CieXyzTristimulus }): CalculationResult<{ xyz: CieXyzTristimulus; matrix: ColorMatrix3x3 }> {\n requireInputKeys(input, \"calculateChromaticallyAdaptedXyz\", [\"transform\", \"sourceWhiteXyz\", \"destinationWhiteXyz\", \"degreeOfAdaptation\", \"xyz\"]);\n const adaptation = chromaticAdaptationMatrix(input);\n const xyz = vectorToXyz(multiplyMatrixVector(adaptation.matrix, xyzToVector(parseXyz(input.xyz, \"xyz\"))));\n requireFiniteResult([xyz.x, xyz.y, xyz.z], \"Chromatic adaptation\");\n return calculatedResult({ xyz, matrix: adaptation.matrix }, \"chromatic-adaptation-\" + adaptation.transform, COLORIMETRY_MODEL_VERSION, [\n \"Linear von Kries-type transform; degree of adaptation \" + adaptation.degreeOfAdaptation\n ]);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"chromatic-adaptation.js","sourceRoot":"","sources":["../../src/color/chromatic-adaptation.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Von Kries-type linear chromatic adaptation transforms (CATs) on CIE XYZ:\n * M = C⁻¹ · diag(Dᵢ) · C, Dᵢ = D · (Y_s / Y_d) · (ρᵢ,d / ρᵢ,s) + 1 − D\n * where C maps XYZ to a cone-like (\"sharpened\") space, ρ_s and ρ_d are the source and\n * destination whites in that space, and D ∈ [0, 1] is the degree of adaptation. This is\n * the one-step, two-illuminant form of Li et al. (2017) for CAT16; it is used for every\n * transform here. With D = 1 and equal white luminance, the source white maps exactly to\n * the destination white.\n *\n * Cone matrices (published factual constants):\n * - Bradford (linearized): Lam (1985) thesis, University of Bradford; Luo & Rhodes\n * (1999); as used in ICC.1:2010 Annex E. The original blue-channel non-linearity is\n * omitted, as in common practice.\n * - CAT16: Li, Li, Wang, Xu, Luo, Cui, Melgosa & Pointer (2016), \"A Revision of CIECAM02\n * and its CAT and UCS\", IS&T CIC24, pp. 208–212, Eq. (15) (M16),\n * doi:10.2352/ISSN.2169-2629.2017.32.208 (free from the IS&T library). Journal version:\n * Li et al. (2017), \"Comprehensive color solutions: CAM16, CAT16, and CAM16-UCS\",\n * Color Res. Appl. 42(6):703–718.\n * - XYZ scaling: identity cone matrix (diagonal scaling in XYZ; the weakest model).\n * The degree of adaptation D is supplied by the caller (default 1, complete adaptation).\n * CAT02, the von Kries Hunt–Pointer–Estévez matrix and the CIECAM02 formula for D are not\n * part of 2.0: no free source we could confirm prints them (owner decisions, 2026-10-17).\n * @see docs/COLORIMETRY.md for equations, coordinate/unit conventions and limits.\n */\n\nimport { calculatedResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport { COLORIMETRY_MODEL_VERSION } from \"./color-matching-functions.js\";\nimport {\n copyMatrix,\n diagonalMatrix,\n invertMatrix3x3,\n multiplyMatrices,\n multiplyMatrixVector,\n parseWhiteXyz,\n parseXyz,\n requireFiniteResult,\n requireNonNegativeNumber,\n vectorToXyz,\n xyzToVector,\n type CieXyzTristimulus,\n type ColorMatrix3x3\n} from \"./colorimetry-math.js\";\nimport { requireInputKeys } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\n/** Supported linear chromatic-adaptation transforms. */\nexport type ChromaticAdaptationTransform = \"bradford\" | \"cat16\" | \"xyz-scaling\";\n\nexport const CHROMATIC_ADAPTATION_TRANSFORMS: readonly ChromaticAdaptationTransform[] = /* @__PURE__ */ Object.freeze([\"bradford\", \"cat16\", \"xyz-scaling\"]);\n\nconst CONE_MATRICES: Readonly<Record<ChromaticAdaptationTransform, ColorMatrix3x3>> = /* @__PURE__ */ Object.freeze({\n bradford: [[0.8951, 0.2664, -0.1614], [-0.7502, 1.7135, 0.0367], [0.0389, -0.0685, 1.0296]],\n cat16: [[0.401288, 0.650173, -0.051461], [-0.250268, 1.204414, 0.045854], [-0.002079, 0.048952, 0.953127]],\n \"xyz-scaling\": [[1, 0, 0], [0, 1, 0], [0, 0, 1]]\n});\n\nfunction requireTransform(value: unknown): ChromaticAdaptationTransform {\n if (typeof value !== \"string\" || !(CHROMATIC_ADAPTATION_TRANSFORMS as readonly string[]).includes(value)) {\n throw new InvalidConfigurationError(\"transform must be one of: \" + CHROMATIC_ADAPTATION_TRANSFORMS.join(\", \") + \".\");\n }\n return value as ChromaticAdaptationTransform;\n}\n\n/** Returns a copy of the XYZ → cone-space matrix of a transform. */\nexport function resolveChromaticAdaptationConeMatrix(transform: ChromaticAdaptationTransform): ColorMatrix3x3 {\n return copyMatrix(CONE_MATRICES[requireTransform(transform)]);\n}\n\nexport interface CalculateChromaticAdaptationMatrixInput {\n transform: ChromaticAdaptationTransform;\n /** White of the source viewing/illumination condition (relative XYZ, Y > 0). */\n sourceWhiteXyz: CieXyzTristimulus;\n /** White of the destination condition (relative XYZ, Y > 0). */\n destinationWhiteXyz: CieXyzTristimulus;\n /** Degree of adaptation D in [0, 1]; defaults to 1 (complete adaptation). */\n degreeOfAdaptation?: number;\n}\n\nexport interface ChromaticAdaptationMatrix {\n transform: ChromaticAdaptationTransform;\n degreeOfAdaptation: number;\n /** Row-major XYZ_source → XYZ_destination matrix. */\n matrix: ColorMatrix3x3;\n /** The per-channel cone-space gains Dᵢ. */\n coneGains: readonly [number, number, number];\n}\n\n/** Internal: builds the adaptation matrix without an envelope. */\nexport function chromaticAdaptationMatrix(input: CalculateChromaticAdaptationMatrixInput): ChromaticAdaptationMatrix {\n const transform = requireTransform(input.transform);\n const source = parseWhiteXyz(input.sourceWhiteXyz, \"sourceWhiteXyz\");\n const destination = parseWhiteXyz(input.destinationWhiteXyz, \"destinationWhiteXyz\");\n const d = input.degreeOfAdaptation === undefined ? 1 : requireNonNegativeNumber(input.degreeOfAdaptation, \"degreeOfAdaptation\");\n if (d > 1) throw new InvalidScientificInputError(\"degreeOfAdaptation must lie in [0, 1].\");\n const cone = CONE_MATRICES[transform];\n const rs = multiplyMatrixVector(cone, xyzToVector(source));\n const rd = multiplyMatrixVector(cone, xyzToVector(destination));\n if (rs.some((v) => !(v > 0)) || rd.some((v) => !(v > 0))) {\n throw new InvalidScientificInputError(\"Both whites must have positive cone responses in the selected transform.\");\n }\n const yRatio = source.y / destination.y;\n const gains = [0, 1, 2].map((i) => d * yRatio * (rd[i]! / rs[i]!) + 1 - d) as unknown as readonly [number, number, number];\n const matrix = multiplyMatrices(multiplyMatrices(invertMatrix3x3(cone, \"cone matrix\"), diagonalMatrix(gains)), cone);\n requireFiniteResult(matrix.flat(), \"Chromatic adaptation\");\n return { transform, degreeOfAdaptation: d, matrix, coneGains: gains };\n}\n\n/**\n * Calculates a linear chromatic-adaptation matrix between two whites. Linear CATs are\n * standard models, but they predict corresponding colours only approximately. The matrix\n * itself is calculated exactly from the declared transform.\n */\nexport function calculateChromaticAdaptationMatrix(input: CalculateChromaticAdaptationMatrixInput): CalculationResult<ChromaticAdaptationMatrix> {\n requireInputKeys(input, \"calculateChromaticAdaptationMatrix\", [\"transform\", \"sourceWhiteXyz\", \"destinationWhiteXyz\", \"degreeOfAdaptation\"]);\n const value = chromaticAdaptationMatrix(input);\n return calculatedResult(value, \"chromatic-adaptation-\" + value.transform, COLORIMETRY_MODEL_VERSION, [\n \"Linear von Kries-type transform M = C⁻¹·diag(D·(Ys/Yd)·ρd/ρs + 1 − D)·C\",\n \"A linear CAT predicts corresponding colours only approximately; no colour-appearance model is applied\"\n ]);\n}\n\n/** Adapts one XYZ colour between whites with the selected transform. */\nexport function calculateChromaticallyAdaptedXyz(input: CalculateChromaticAdaptationMatrixInput & { xyz: CieXyzTristimulus }): CalculationResult<{ xyz: CieXyzTristimulus; matrix: ColorMatrix3x3 }> {\n requireInputKeys(input, \"calculateChromaticallyAdaptedXyz\", [\"transform\", \"sourceWhiteXyz\", \"destinationWhiteXyz\", \"degreeOfAdaptation\", \"xyz\"]);\n const adaptation = chromaticAdaptationMatrix(input);\n const xyz = vectorToXyz(multiplyMatrixVector(adaptation.matrix, xyzToVector(parseXyz(input.xyz, \"xyz\"))));\n requireFiniteResult([xyz.x, xyz.y, xyz.z], \"Chromatic adaptation\");\n return calculatedResult({ xyz, matrix: adaptation.matrix }, \"chromatic-adaptation-\" + adaptation.transform, COLORIMETRY_MODEL_VERSION, [\n \"Linear von Kries-type transform; degree of adaptation \" + adaptation.degreeOfAdaptation\n ]);\n}\n"]}
|
|
@@ -33,7 +33,7 @@ export const MAX_COLORIMETRIC_QUADRATURE_NODES = 100_000;
|
|
|
33
33
|
/** Upper bound on samples in a caller-supplied tabulated spectrum or CMF table. */
|
|
34
34
|
export const MAX_COLORIMETRIC_TABLE_SAMPLES = 100_000;
|
|
35
35
|
/** Wavelength domain over which the analytic CIE 1931 fit is accepted (the domain it was fitted on). */
|
|
36
|
-
export const ANALYTIC_CIE_1931_CMF_DOMAIN_NANOMETERS = Object.freeze({ minimum: 360, maximum: 830 });
|
|
36
|
+
export const ANALYTIC_CIE_1931_CMF_DOMAIN_NANOMETERS = /* @__PURE__ */ Object.freeze({ minimum: 360, maximum: 830 });
|
|
37
37
|
const X_LOBES = [[0.375817, 441.559, 15.3475, 94.5181], [-0.322164, 497.643, 23.3464, 30.5255], [0.968784, 600.86, 33.6528, 29.7704]];
|
|
38
38
|
const Y_LOBES = [[0.285798, 530.874, 16.3146, 31.077], [0.820879, 568.79, 46.8848, 40.4965]];
|
|
39
39
|
const Z_LOBES = [[1.2165, 436.962, 11.8408, 35.9867], [0.681263, 459.034, 25.9609, 13.7926]];
|