@photivra/engine 2.13.0 → 2.14.1

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.
Files changed (128) hide show
  1. package/CHANGELOG.md +75 -1
  2. package/CITATION.cff +1 -1
  3. package/NOTICE +5 -4
  4. package/README.md +10 -8
  5. package/SECURITY.md +1 -1
  6. package/THIRD_PARTY.md +16 -10
  7. package/dist/camera/lens-projection.js +2 -1
  8. package/dist/camera/lens-projection.js.map +1 -1
  9. package/dist/capture/dng-import.js +1 -1
  10. package/dist/capture/dng-import.js.map +1 -1
  11. package/dist/capture/host-yield-cadence.js +1 -1
  12. package/dist/capture/host-yield-cadence.js.map +1 -1
  13. package/dist/capture/native-environment-optical-stage.js +1 -1
  14. package/dist/capture/native-environment-optical-stage.js.map +1 -1
  15. package/dist/capture/native-raw.js +1 -1
  16. package/dist/capture/native-raw.js.map +1 -1
  17. package/dist/capture/packed-sensor-raw.js +3 -3
  18. package/dist/capture/packed-sensor-raw.js.map +1 -1
  19. package/dist/capture/sensor-raw-producer.js +1 -1
  20. package/dist/capture/sensor-raw-producer.js.map +1 -1
  21. package/dist/color/capture-color.js +3 -3
  22. package/dist/color/capture-color.js.map +1 -1
  23. package/dist/color/chromatic-adaptation.js +2 -2
  24. package/dist/color/chromatic-adaptation.js.map +1 -1
  25. package/dist/color/color-matching-functions.js +1 -1
  26. package/dist/color/color-matching-functions.js.map +1 -1
  27. package/dist/color/colorimetry-math.js +2 -2
  28. package/dist/color/colorimetry-math.js.map +1 -1
  29. package/dist/color/illuminants.js +3 -3
  30. package/dist/color/illuminants.js.map +1 -1
  31. package/dist/color/rgb-color-spaces.js +1 -1
  32. package/dist/color/rgb-color-spaces.js.map +1 -1
  33. package/dist/color/sensor-color-development.js +1 -1
  34. package/dist/color/sensor-color-development.js.map +1 -1
  35. package/dist/core/record-validation.js +3 -3
  36. package/dist/core/record-validation.js.map +1 -1
  37. package/dist/core/version.d.ts +1 -1
  38. package/dist/core/version.js +1 -1
  39. package/dist/core/version.js.map +1 -1
  40. package/dist/equipment/generic-prime-lenses.js +3 -3
  41. package/dist/equipment/generic-prime-lenses.js.map +1 -1
  42. package/dist/equipment/generic-tier-assets.d.ts +23 -1
  43. package/dist/equipment/generic-tier-assets.js +58 -30
  44. package/dist/equipment/generic-tier-assets.js.map +1 -1
  45. package/dist/equipment/generic-tier-presets.d.ts +6 -3
  46. package/dist/equipment/generic-tier-presets.js +26 -13
  47. package/dist/equipment/generic-tier-presets.js.map +1 -1
  48. package/dist/exposure/auto-iso-slowest-shutter.js +2 -1
  49. package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -1
  50. package/dist/exposure/flash-ttl.js +1 -1
  51. package/dist/exposure/flash-ttl.js.map +1 -1
  52. package/dist/exposure/flash.js +1 -1
  53. package/dist/exposure/flash.js.map +1 -1
  54. package/dist/facade/chart-material-layers.js +2 -2
  55. package/dist/facade/chart-material-layers.js.map +1 -1
  56. package/dist/facade/chart-radiance-batch.js +1 -1
  57. package/dist/facade/chart-radiance-batch.js.map +1 -1
  58. package/dist/facade/chart-scenes.d.ts +45 -8
  59. package/dist/facade/chart-scenes.js +101 -44
  60. package/dist/facade/chart-scenes.js.map +1 -1
  61. package/dist/facade/color-patches.d.ts +129 -0
  62. package/dist/facade/color-patches.js +209 -0
  63. package/dist/facade/color-patches.js.map +1 -0
  64. package/dist/facade/display-view-gpu.js +1 -1
  65. package/dist/facade/display-view-gpu.js.map +1 -1
  66. package/dist/facade/scene-radiance.js +2 -2
  67. package/dist/facade/scene-radiance.js.map +1 -1
  68. package/dist/facade/simulate-capture.d.ts +47 -3
  69. package/dist/facade/simulate-capture.js +71 -22
  70. package/dist/facade/simulate-capture.js.map +1 -1
  71. package/dist/facade/simulate-display-view.js +2 -2
  72. package/dist/facade/simulate-display-view.js.map +1 -1
  73. package/dist/gpu/chart-composite-gpu.js +2 -2
  74. package/dist/gpu/chart-composite-gpu.js.map +1 -1
  75. package/dist/gpu/display-view-composite-material-module.js +1 -1
  76. package/dist/gpu/display-view-composite-material-module.js.map +1 -1
  77. package/dist/gpu/image-kernel-execution.js +2 -2
  78. package/dist/gpu/image-kernel-execution.js.map +1 -1
  79. package/dist/gpu/temporal-sum-gpu.js +23 -23
  80. package/dist/gpu/webgpu-runtime.js +1 -1
  81. package/dist/gpu/webgpu-runtime.js.map +1 -1
  82. package/dist/gpu/wgsl-chart-composite-kernel.js +318 -318
  83. package/dist/gpu/wgsl-chart-composite-kernel.js.map +1 -1
  84. package/dist/gpu/wgsl-chart-kernel.js +117 -117
  85. package/dist/gpu/wgsl-chart-kernel.js.map +1 -1
  86. package/dist/gpu/wgsl-display-view-quality-kernel.js +505 -505
  87. package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
  88. package/dist/gpu/wgsl-display-view-speed-kernel.js +248 -248
  89. package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
  90. package/dist/gpu/wgsl-kernels.js +203 -203
  91. package/dist/gpu/wgsl-kernels.js.map +1 -1
  92. package/dist/gpu/wgsl-sensor-kernel.js +302 -302
  93. package/dist/gpu/wgsl-sensor-kernel.js.map +1 -1
  94. package/dist/index.d.ts +5 -3
  95. package/dist/index.js +4 -2
  96. package/dist/index.js.map +1 -1
  97. package/dist/motion/temporal-exposure-sum.js +1 -1
  98. package/dist/motion/temporal-exposure-sum.js.map +1 -1
  99. package/dist/optics/diffraction-psf-profile.js +4 -4
  100. package/dist/optics/diffraction-psf-profile.js.map +1 -1
  101. package/dist/optics/front-of-lens-filter.js +1 -1
  102. package/dist/optics/front-of-lens-filter.js.map +1 -1
  103. package/dist/optics/irradiance-convolution.js +1 -1
  104. package/dist/optics/irradiance-convolution.js.map +1 -1
  105. package/dist/output/native-capture-sdr.js +1 -1
  106. package/dist/output/native-capture-sdr.js.map +1 -1
  107. package/dist/output/png-encoder.js +2 -2
  108. package/dist/output/png-encoder.js.map +1 -1
  109. package/dist/output/print-contrast-reference.js +2 -2
  110. package/dist/output/print-contrast-reference.js.map +1 -1
  111. package/dist/output/print-jpeg.js +1 -1
  112. package/dist/output/print-jpeg.js.map +1 -1
  113. package/dist/sensor/fixed-pattern-noise.js +1 -1
  114. package/dist/sensor/fixed-pattern-noise.js.map +1 -1
  115. package/dist/sensor/readout-exposure-linkage.js +1 -1
  116. package/dist/sensor/readout-exposure-linkage.js.map +1 -1
  117. package/docs/API_REFERENCE.md +29 -1
  118. package/docs/QUICK_START.md +40 -5
  119. package/docs/USAGE.md +35 -1
  120. package/docs/api/core-version.md +1 -1
  121. package/docs/api/equipment-generic-tier-assets.md +41 -1
  122. package/docs/api/equipment-generic-tier-presets.md +11 -3
  123. package/docs/api/exports.json +107 -2
  124. package/docs/api/facade-chart-scenes.md +36 -5
  125. package/docs/api/facade-color-patches.md +150 -0
  126. package/docs/api/facade-simulate-capture.md +52 -2
  127. package/llms.txt +1 -0
  128. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"illuminants.js","sourceRoot":"","sources":["../../src/color/illuminants.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Illuminant spectra and correlated-colour-temperature (CCT) helpers.\n *\n * - Planckian radiator: exact Planck law (BIPM Mise en pratique for the kelvin, Absolute Primary\n * Radiometry 2018, Eq. 1, free) with the exact SI defining constants (h, c, k; BIPM SI Brochure\n * 9th ed. 2019), so c₂ = hc/k = 1.438776877…e-2 m·K (NIST CODATA 2022). Wavelength is the vacuum\n * wavelength.\n * - CIE standard illuminant A: Planck's law relative to 560 nm with the CIE's defining constants\n * c₂ = 1.435e-2 m·K and T = 2848 K (also CIE 15:2018 Eq. 4.1 / ISO/CIE 11664-2, paid):\n * S_A(λ) = 100 (560/λ)^5 (exp(1.435e7/(2848·560)) − 1)/(exp(1.435e7/(2848 λ)) − 1)\n * (≈ 2856 K with the exact c₂). Computed from the formula, not a copied table; it reproduces the\n * free CIE 1 nm table (DOI 10.25039/CIE.DS.8jsxjrsn) to its six significant digits.\n * - CIE daylight: the CIE daylight-locus chromaticity polynomial and the M₁/M₂ weights (CIE 15:2018,\n * paid; no free text of the formulas found). With three-decimal rounding they reproduce the free\n * CIE D55 and D65 tables. The S₀/S₁/S₂ basis is a CIE dataset (CC BY-SA 4.0, not bundled);\n * callers supply it.\n * - Planckian locus: the chromaticity of a Planckian radiator at T, computed by integrating Planck's\n * law against colour-matching functions. The default uses the engine's analytic CIE 1931 fit with\n * 1 nm nodes from 360 to 830 nm (so it inherits that fit's approximation); callers may select\n * tabulated CMFs and their own nodes. Valid 1000–100000 K.\n * - CCT from chromaticity: McCamy (1992) cubic (approximation), or a nearest-point\n * search on the Planckian locus in the CIE 1960 UCS (CCT and signed Duv as defined in Smet et al.,\n * LEUKOS 2023, free archival copy from the US DOE; also CIE 15:2018). Duv sign: positive above the\n * locus (toward green), negative below (toward magenta), following Ohno, \"Calculation of CCT and Duv\n * and Practical Conversion Formulae\", CORM 2011 slides (free), slide 5; the engine documents and\n * tests it.\n * @see docs/COLORIMETRY.md for equations, coordinate/unit conventions and limits.\n */\n\nimport { approximationResult, calculatedResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport type { SpectralWavelengthRangeNanometers } from \"../core/spectral.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport {\n COLORIMETRY_MODEL_VERSION,\n integrateSampledXyz,\n prepareColorMatchingFunctions,\n prepareColorimetricSpectrum,\n sampleColorimetricBasis,\n type ColorMatchingFunctionsSource,\n type ColorimetricQuadratureNode,\n type ColorimetricSpectralSample,\n type ColorimetricSpectrum\n} from \"./color-matching-functions.js\";\nimport {\n chromaticityOfUv,\n chromaticityOfXyz,\n parseChromaticity,\n requireFiniteNumber,\n requirePositiveNumber,\n requireRecordValue,\n uvOfChromaticity,\n type Cie1960UvChromaticity,\n type CieXyChromaticity\n} from \"./colorimetry-math.js\";\nimport { rejectUnknownFields, requireInputKeys } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { portableExpm1, portableHypot, portablePow } from \"../core/portable-math.js\";\n\n/** Exact SI defining constants (BIPM SI Brochure, 9th edition, 2019). */\nexport const PLANCK_CONSTANT_JOULE_SECONDS = 6.62607015e-34;\nexport const SPEED_OF_LIGHT_METERS_PER_SECOND = 299_792_458;\nexport const BOLTZMANN_CONSTANT_JOULES_PER_KELVIN = 1.380649e-23;\n/** Second radiation constant c₂ = hc/k in m·K (derived from the exact constants). */\nexport const SECOND_RADIATION_CONSTANT_METER_KELVIN = (PLANCK_CONSTANT_JOULE_SECONDS * SPEED_OF_LIGHT_METERS_PER_SECOND) / BOLTZMANN_CONSTANT_JOULES_PER_KELVIN;\nconst FIRST_RADIATION_CONSTANT_RADIANCE = 2 * PLANCK_CONSTANT_JOULE_SECONDS * SPEED_OF_LIGHT_METERS_PER_SECOND ** 2;\n/** The same constant with c² as one correctly rounded product (the portable evaluation below). */\nconst FIRST_RADIATION_CONSTANT_RADIANCE_PORTABLE = 2 * PLANCK_CONSTANT_JOULE_SECONDS * (SPEED_OF_LIGHT_METERS_PER_SECOND * SPEED_OF_LIGHT_METERS_PER_SECOND);\n/**\n * The portable functions the display view's evaluations use. They are passed as an argument rather than called directly\n * from the shared code, so a bundle that never calls a portable variant (every capture) does not contain them.\n */\ninterface PortableOps { pow(x: number, y: number): number; expm1(x: number): number; hypot(x: number, y: number): number }\nconst PORTABLE: PortableOps = { pow: portablePow, expm1: portableExpm1, hypot: portableHypot };\n\n/** Temperature range of the Planckian-locus models, K. */\nexport const PLANCKIAN_LOCUS_RANGE_KELVIN = Object.freeze({ minimum: 1000, maximum: 100000 });\n/** CIE daylight-locus validity, K. */\nexport const CIE_DAYLIGHT_LOCUS_RANGE_KELVIN = Object.freeze({ minimum: 4000, maximum: 25000 });\n/**\n * Engine limit: no CCT beyond |Duv| = 0.05, the range over which Smet et al. (2023, free) evaluate CCT\n * methods for nominally white light (CIE 15:2018 §9.5, paid, gives the same limit).\n */\nexport const MAX_CORRELATED_COLOR_TEMPERATURE_DUV = 0.05;\n\n/**\n * Planck's law for blackbody spectral radiance per unit (vacuum) wavelength:\n * L(λ, T) = 2hc² / λ⁵ / (exp(hc/(λkT)) − 1). Returns W·m⁻²·sr⁻¹·nm⁻¹.\n */\nexport function calculatePlanckianSpectralRadiance(input: { temperatureKelvin: number; wavelengthNanometers: number }): number {\n requireInputKeys(input, \"calculatePlanckianSpectralRadiance\", [\"temperatureKelvin\", \"wavelengthNanometers\"]);\n const t = requirePositiveNumber(input.temperatureKelvin, \"temperatureKelvin\");\n const nm = requirePositiveNumber(input.wavelengthNanometers, \"wavelengthNanometers\");\n return planckianRadiancePerNanometer(t, nm, undefined);\n}\n/**\n * Planck's law at temperature t (K) and wavelength nm. `portable` evaluates λ⁵ and e^x − 1 with the engine's portable\n * functions (`portablePow`, `portableExpm1`; within 1 and 2 ulps) instead of `**` and Math.expm1, whose last bits differ\n * between JavaScript engines (V8 12 and V8 13 differ in about 10 % of λ⁵); the display view uses it.\n */\nfunction planckianRadiancePerNanometer(t: number, nm: number, portable: PortableOps | undefined): number {\n const lambda = nm * 1e-9;\n const exponent = SECOND_RADIATION_CONSTANT_METER_KELVIN / (lambda * t);\n // expm1 keeps precision in the Rayleigh–Jeans limit; overflow gives radiance 0.\n const radiancePerMeter = portable ? FIRST_RADIATION_CONSTANT_RADIANCE_PORTABLE / portable.pow(lambda, 5) / portable.expm1(exponent)\n : FIRST_RADIATION_CONSTANT_RADIANCE / lambda ** 5 / Math.expm1(exponent);\n return radiancePerMeter * 1e-9;\n}\n\n/** Planckian spectral radiance (W·m⁻²·sr⁻¹·nm⁻¹) as a function spectrum over the given range. */\nexport function createPlanckianSpectrum(input: { temperatureKelvin: number; wavelengthRangeNanometers: SpectralWavelengthRangeNanometers }): ColorimetricSpectrum {\n return planckianSpectrum(input, undefined);\n}\n/** Internal (not exported from the package): {@link createPlanckianSpectrum} evaluated with the portable functions (the display view). */\nexport function createPortablePlanckianSpectrum(input: { temperatureKelvin: number; wavelengthRangeNanometers: SpectralWavelengthRangeNanometers }): ColorimetricSpectrum {\n return planckianSpectrum(input, PORTABLE);\n}\nfunction planckianSpectrum(input: { temperatureKelvin: number; wavelengthRangeNanometers: SpectralWavelengthRangeNanometers }, portable: PortableOps | undefined): ColorimetricSpectrum {\n requireInputKeys(input, \"createPlanckianSpectrum\", [\"temperatureKelvin\", \"wavelengthRangeNanometers\"]);\n const temperatureKelvin = requirePositiveNumber(input.temperatureKelvin, \"temperatureKelvin\");\n const range = requireRecordValue(input.wavelengthRangeNanometers, \"wavelengthRangeNanometers\");\n rejectUnknownFields(range, [\"minimum\", \"maximum\"], \"wavelengthRangeNanometers\");\n const spectrum: ColorimetricSpectrum = {\n kind: \"function\",\n wavelengthRangeNanometers: { minimum: range.minimum as number, maximum: range.maximum as number },\n evaluate: portable ? (wavelengthNanometers): number => planckianRadiancePerNanometer(temperatureKelvin, requirePositiveNumber(wavelengthNanometers, \"wavelengthNanometers\"), portable)\n : (wavelengthNanometers): number => calculatePlanckianSpectralRadiance({ temperatureKelvin, wavelengthNanometers })\n };\n prepareColorimetricSpectrum(spectrum, \"planckianSpectrum\");\n return spectrum;\n}\n\n/** CIE illuminant A defining range (nm). */\nexport const CIE_ILLUMINANT_A_RANGE_NANOMETERS = Object.freeze({ minimum: 300, maximum: 830 });\n\n/**\n * CIE standard illuminant A relative SPD from its defining formula (100 at 560 nm),\n * with c₂ = 1.435e-2 m·K and T = 2848 K as in the standard (≈ 2856 K with the\n * current c₂). Valid 300–830 nm.\n */\nexport function calculateCieIlluminantARelativeSpectralPower(wavelengthNanometers: number): number {\n return cieIlluminantA(wavelengthNanometers, undefined);\n}\n/** CIE illuminant A; `portable` evaluates the power and e^x − 1 with the portable functions (see planckianRadiancePerNanometer). */\nfunction cieIlluminantA(wavelengthNanometers: number, portable: PortableOps | undefined): number {\n const nm = requireFiniteNumber(wavelengthNanometers, \"wavelengthNanometers\");\n if (nm < CIE_ILLUMINANT_A_RANGE_NANOMETERS.minimum || nm > CIE_ILLUMINANT_A_RANGE_NANOMETERS.maximum) {\n throw new InvalidScientificInputError(\"CIE illuminant A is defined from 300 nm to 830 nm.\");\n }\n const c = 1.435e7 / 2848; // nm·K / K\n return portable ? 100 * portable.pow(560 / nm, 5) * (portable.expm1(c / 560) / portable.expm1(c / nm)) : 100 * (560 / nm) ** 5 * (Math.expm1(c / 560) / Math.expm1(c / nm));\n}\n\n/** CIE illuminant A as a function spectrum over its defining range. */\nexport function createCieIlluminantASpectrum(): ColorimetricSpectrum {\n return { kind: \"function\", wavelengthRangeNanometers: { ...CIE_ILLUMINANT_A_RANGE_NANOMETERS }, evaluate: calculateCieIlluminantARelativeSpectralPower };\n}\n/** Internal (not exported from the package): {@link createCieIlluminantASpectrum} evaluated with the portable functions (the display view). */\nexport function createPortableCieIlluminantASpectrum(): ColorimetricSpectrum {\n return { kind: \"function\", wavelengthRangeNanometers: { ...CIE_ILLUMINANT_A_RANGE_NANOMETERS }, evaluate: (nm) => cieIlluminantA(nm, PORTABLE) };\n}\n\nfunction requireTemperatureIn(t: unknown, range: { minimum: number; maximum: number }, what: string): number {\n const value = requirePositiveNumber(t, what);\n if (value < range.minimum || value > range.maximum) {\n throw new InvalidScientificInputError(what + \" must lie in [\" + range.minimum + \", \" + range.maximum + \"] K.\");\n }\n return value;\n}\n\nfunction daylightChromaticity(t: number, portable?: PortableOps): CieXyChromaticity {\n const t3 = portable ? portable.pow(t, 3) : t ** 3, t2 = portable ? t * t : t ** 2;\n const x = t <= 7000\n ? -4.6070e9 / t3 + 2.9678e6 / t2 + 0.09911e3 / t + 0.244063\n : -2.0064e9 / t3 + 1.9018e6 / t2 + 0.24748e3 / t + 0.237040;\n return { x, y: -3.000 * x * x + 2.870 * x - 0.275 };\n}\n\nexport interface CieDaylightComponentWeights {\n correlatedColorTemperatureKelvin: number;\n chromaticity: CieXyChromaticity;\n m1: number;\n m2: number;\n coefficientRounding: \"none\" | \"cie-three-decimals\";\n}\n\n/**\n * CIE daylight-locus chromaticity and S₁/S₂ weights for a CCT in 4000–25000 K\n * (CIE 15:2018 §4.1.2, paid; no free text of the formulas found). M₁, M₂ rounded to three decimals\n * reproduce the free CIE D55 and D65 tables (DOI 10.25039/CIE.DS.qewfb3kp, 10.25039/CIE.DS.hjfjmt59)\n * to their rounding; `coefficientRounding` makes that rounding explicit.\n * The temperature is used as given: D65's nominal 6500 K corresponds to 6504 K here.\n */\nexport function calculateCieDaylightComponentWeights(input: {\n correlatedColorTemperatureKelvin: number;\n coefficientRounding: \"none\" | \"cie-three-decimals\";\n}): CalculationResult<CieDaylightComponentWeights> {\n return cieDaylightComponentWeights(input, undefined);\n}\nfunction cieDaylightComponentWeights(input: { correlatedColorTemperatureKelvin: number; coefficientRounding: \"none\" | \"cie-three-decimals\" },\n portable: PortableOps | undefined): CalculationResult<CieDaylightComponentWeights> {\n requireInputKeys(input, \"calculateCieDaylightComponentWeights\", [\"correlatedColorTemperatureKelvin\", \"coefficientRounding\"]);\n const t = requireTemperatureIn(input.correlatedColorTemperatureKelvin, CIE_DAYLIGHT_LOCUS_RANGE_KELVIN, \"correlatedColorTemperatureKelvin\");\n if (input.coefficientRounding !== \"none\" && input.coefficientRounding !== \"cie-three-decimals\") {\n throw new InvalidConfigurationError(\"coefficientRounding must be \\\"none\\\" or \\\"cie-three-decimals\\\".\");\n }\n const xy = daylightChromaticity(t, portable);\n const m = 0.0241 + 0.2562 * xy.x - 0.7341 * xy.y;\n let m1 = (-1.3515 - 1.7703 * xy.x + 5.9114 * xy.y) / m;\n let m2 = (0.0300 - 31.4424 * xy.x + 30.0717 * xy.y) / m;\n if (input.coefficientRounding === \"cie-three-decimals\") {\n m1 = Math.round(m1 * 1000) / 1000;\n m2 = Math.round(m2 * 1000) / 1000;\n }\n return calculatedResult({ correlatedColorTemperatureKelvin: t, chromaticity: xy, m1, m2, coefficientRounding: input.coefficientRounding },\n \"cie-daylight-locus\", COLORIMETRY_MODEL_VERSION, [\"CIE daylight-locus polynomial and M1/M2 weights, checked against the free CIE D55 and D65 datasets (no free formula text found); valid 4000–25000 K\"]);\n}\n\n/** Caller-supplied CIE daylight basis S₀, S₁, S₂ (tabulated; CIE dataset not bundled). */\nexport interface CieDaylightBasis {\n s0: readonly ColorimetricSpectralSample[];\n s1: readonly ColorimetricSpectralSample[];\n s2: readonly ColorimetricSpectralSample[];\n /** Caller identity of the basis dataset (for example a DOI). */\n datasetId: string;\n}\n\n/**\n * Builds a CIE D-series relative SPD S(λ) = S₀ + M₁S₁ + M₂S₂ on the S₀ wavelengths from\n * caller-supplied basis tables (S₁, S₂ linearly interpolated; fail closed outside range).\n */\nexport function createCieDaylightSpectrum(input: {\n correlatedColorTemperatureKelvin: number;\n coefficientRounding: \"none\" | \"cie-three-decimals\";\n basis: CieDaylightBasis;\n}): ColorimetricSpectrum {\n return cieDaylightSpectrum(input, undefined);\n}\n/** Internal (not exported from the package): {@link createCieDaylightSpectrum} with the portable daylight-locus powers (the display view). */\nexport function createPortableCieDaylightSpectrum(input: Parameters<typeof createCieDaylightSpectrum>[0]): ColorimetricSpectrum {\n return cieDaylightSpectrum(input, PORTABLE);\n}\nfunction cieDaylightSpectrum(input: Parameters<typeof createCieDaylightSpectrum>[0], portable: PortableOps | undefined): ColorimetricSpectrum {\n requireInputKeys(input, \"createCieDaylightSpectrum\", [\"correlatedColorTemperatureKelvin\", \"coefficientRounding\", \"basis\"]);\n const weights = cieDaylightComponentWeights({\n correlatedColorTemperatureKelvin: input.correlatedColorTemperatureKelvin,\n coefficientRounding: input.coefficientRounding\n }, portable).value;\n const basis = requireRecordValue(input.basis, \"basis\");\n rejectUnknownFields(basis, [\"s0\", \"s1\", \"s2\", \"datasetId\"], \"basis\");\n if (typeof basis.datasetId !== \"string\" || basis.datasetId.trim().length === 0) {\n throw new InvalidConfigurationError(\"basis.datasetId must be a non-empty string.\");\n }\n const s0 = prepareColorimetricSpectrum({ kind: \"tabulated\", samples: input.basis.s0 }, \"basis.s0\");\n const s1 = prepareColorimetricSpectrum({ kind: \"tabulated\", samples: input.basis.s1 }, \"basis.s1\");\n const s2 = prepareColorimetricSpectrum({ kind: \"tabulated\", samples: input.basis.s2 }, \"basis.s2\");\n const samples = input.basis.s0.map((sample) => {\n const w = sample.wavelengthNanometers;\n return { wavelengthNanometers: w, value: s0.evaluate(w) + weights.m1 * s1.evaluate(w) + weights.m2 * s2.evaluate(w) };\n });\n return { kind: \"tabulated\", samples };\n}\n\n/** Selects how the Planckian locus is evaluated. */\nexport type PlanckianLocusModel =\n | {\n /** Planck's law integrated against the engine's analytic CIE 1931 CMFs, 1 nm nodes 360–830 nm (the default). */\n kind: \"planck-analytic-cmf\";\n }\n | {\n kind: \"planck-integration\";\n colorMatchingFunctions: ColorMatchingFunctionsSource;\n quadratureNodes: readonly ColorimetricQuadratureNode[];\n };\n\n/** Number of intervals of the coarse reciprocal-temperature scan that brackets the CCT search. */\nconst CCT_SCAN_STEPS = 200;\n/**\n * Convergence tolerance of the CCT root-find: it stops once a Newton (or bisection) step changes T by\n * at most this fraction of T (1e-6 K at 10000 K).\n */\nconst CCT_RELATIVE_TOLERANCE = 1e-10;\n\n/**\n * Locus uv and its first and second derivatives with respect to the reciprocal temperature x = 1/T\n * (K⁻¹), from the analytic derivatives of Planck's law integrated in the locus quadrature.\n */\ninterface LocusSample {\n u: number;\n v: number;\n du: number;\n dv: number;\n d2u: number;\n d2v: number;\n}\n\ninterface PreparedLocus {\n range: { minimum: number; maximum: number };\n approximation: boolean;\n model: string;\n chromaticity(t: number): CieXyChromaticity;\n /** uv and its x = 1/T derivatives at reciprocal temperature x. */\n sample(x: number): LocusSample;\n /** CIE 1960 uv at the coarse scan temperatures; computed once per prepared locus. */\n scan(): readonly Cie1960UvChromaticity[];\n}\n\n/**\n * Prepares a Planck-integration locus: the CMF values and 1/λ⁵ factors are sampled once, so each\n * temperature costs one exponential per node. Planck's constant factor 2hc² cancels in chromaticity.\n *\n * Derivatives: with x = 1/T, aᵢ = c₂/λᵢ and rᵢ = 1/(exp(aᵢx) − 1), Planck's law is proportional to\n * λᵢ⁻⁵ rᵢ, and exactly dr/dx = −a(r + r²) and d²r/dx² = a²(r + 3r² + 2r³) (differentiate\n * r = 1/(E − 1), E = exp(ax), and use E = 1 + 1/r). They are summed in the same quadrature as X, Y, Z.\n */\nfunction preparePlanckIntegrationLocus(cmfSource: ColorMatchingFunctionsSource, quadratureNodes: readonly ColorimetricQuadratureNode[], model: string,\n portable?: PortableOps): PreparedLocus {\n // `portable` (the display view): λ⁻⁵ and e^x − 1 from the portable functions, whose bits are the same in every engine.\n const expm1 = portable ? portable.expm1 : Math.expm1;\n const cmf = prepareColorMatchingFunctions(cmfSource);\n const unit = prepareColorimetricSpectrum({ kind: \"function\", wavelengthRangeNanometers: cmf.wavelengthRangeNanometers, evaluate: () => 1 });\n const basis = sampleColorimetricBasis(quadratureNodes, unit, cmf);\n const n = basis.nodes.length;\n const exponentPerKelvin = new Float64Array(n), inverseFifth = new Float64Array(n);\n // Per-node constants of the derivative sums: weight × CMF × λ⁻⁵ for X, Y and Z.\n const wx = new Float64Array(n), wy = new Float64Array(n), wz = new Float64Array(n);\n for (let i = 0; i < n; i++) {\n const lambda = basis.nodes[i]!.wavelengthNanometers * 1e-9;\n exponentPerKelvin[i] = SECOND_RADIATION_CONSTANT_METER_KELVIN / lambda;\n inverseFifth[i] = 1 / (portable ? portable.pow(lambda, 5) : lambda ** 5);\n const w = basis.weights[i]! * inverseFifth[i]!;\n wx[i] = w * basis.xBar[i]!; wy[i] = w * basis.yBar[i]!; wz[i] = w * basis.zBar[i]!;\n }\n const factor = new Float64Array(n);\n const range = PLANCKIAN_LOCUS_RANGE_KELVIN;\n let scanCache: readonly Cie1960UvChromaticity[] | undefined;\n const locus: PreparedLocus = {\n range,\n approximation: cmf.scientificStatus === \"approximation\",\n model,\n chromaticity(t: number): CieXyChromaticity {\n // expm1 keeps precision at long wavelengths; overflow at short ones gives 0, as in Planck's law.\n for (let i = 0; i < n; i++) factor[i] = inverseFifth[i]! / expm1(exponentPerKelvin[i]! / t);\n return chromaticityOfXyz(integrateSampledXyz(basis, factor));\n },\n sample(x: number): LocusSample {\n let sx = 0, sy = 0, sz = 0, sx1 = 0, sy1 = 0, sz1 = 0, sx2 = 0, sy2 = 0, sz2 = 0;\n for (let i = 0; i < n; i++) {\n const a = exponentPerKelvin[i]!;\n // An overflowing expm1 gives r = 0 and zero derivatives, the exact limit.\n const r = 1 / expm1(a * x), r2 = r * r;\n const q1 = r + r2, k1 = -a * q1, k2 = a * a * (q1 + 2 * r2 * (1 + r));\n const cx = wx[i]!, cy = wy[i]!, cz = wz[i]!;\n sx += cx * r; sy += cy * r; sz += cz * r;\n sx1 += cx * k1; sy1 += cy * k1; sz1 += cz * k1;\n sx2 += cx * k2; sy2 += cy * k2; sz2 += cz * k2;\n }\n // u = 4X/d, v = 6Y/d, d = X + 15Y + 3Z; quotient rule: q' = (N' − q d')/d, q'' = (N'' − 2q'd' − q d'')/d.\n const d = sx + 15 * sy + 3 * sz, d1 = sx1 + 15 * sy1 + 3 * sz1, d2 = sx2 + 15 * sy2 + 3 * sz2;\n if (!(d > 0) || !Number.isFinite(d)) throw new InvalidScientificInputError(\"Chromaticity requires X + Y + Z > 0.\");\n const u = (4 * sx) / d, v = (6 * sy) / d;\n const du = (4 * sx1 - u * d1) / d, dv = (6 * sy1 - v * d1) / d;\n return { u, v, du, dv, d2u: (4 * sx2 - 2 * du * d1 - u * d2) / d, d2v: (6 * sy2 - 2 * dv * d1 - v * d2) / d };\n },\n scan(): readonly Cie1960UvChromaticity[] {\n if (scanCache === undefined) {\n const lo = 1e6 / range.maximum, hi = 1e6 / range.minimum;\n scanCache = Array.from({ length: CCT_SCAN_STEPS + 1 }, (_, i) => uvOfChromaticity(locus.chromaticity(1e6 / (lo + ((hi - lo) * i) / CCT_SCAN_STEPS))));\n }\n return scanCache;\n }\n };\n return locus;\n}\n\n/** 1 nm nodes at 360, 361, …, 830 nm with Δλ = 1 nm (the CIE 15 summation convention). */\nconst DEFAULT_LOCUS_NODES: readonly ColorimetricQuadratureNode[] = Object.freeze(\n Array.from({ length: 471 }, (_, i) => Object.freeze({ wavelengthNanometers: 360 + i, wavelengthMeasureNanometers: 1 }))\n);\nlet defaultLocus: PreparedLocus | undefined, defaultPortableLocus: PreparedLocus | undefined;\n\n/** The default locus, prepared on first use and shared (its scan cache is computed once); `portable` for the display view. */\nfunction analyticCmfLocus(portable?: PortableOps): PreparedLocus {\n if (portable) {\n defaultPortableLocus ??= preparePlanckIntegrationLocus({ kind: \"analytic-cie-1931-multi-lobe-fit\" }, DEFAULT_LOCUS_NODES, \"planck-analytic-cmf\", portable);\n return defaultPortableLocus;\n }\n defaultLocus ??= preparePlanckIntegrationLocus({ kind: \"analytic-cie-1931-multi-lobe-fit\" }, DEFAULT_LOCUS_NODES, \"planck-analytic-cmf\");\n return defaultLocus;\n}\n\n/**\n * Planckian-locus chromaticity at T (1000–100000 K): Planck's law integrated against the engine's\n * analytic CIE 1931 CMFs with 1 nm nodes from 360 to 830 nm. An approximation, because the CMFs are\n * an analytic fit; with tabulated CMFs use {@link calculatePlanckianChromaticity}.\n */\nexport function estimatePlanckianLocusChromaticity(input: { temperatureKelvin: number }): CalculationResult<CieXyChromaticity> {\n requireInputKeys(input, \"estimatePlanckianLocusChromaticity\", [\"temperatureKelvin\"]);\n const t = requireTemperatureIn(input.temperatureKelvin, PLANCKIAN_LOCUS_RANGE_KELVIN, \"temperatureKelvin\");\n return approximationResult(analyticCmfLocus().chromaticity(t), \"planckian-locus-planck-analytic-cmf\", COLORIMETRY_MODEL_VERSION,\n [\"Planck's law integrated against the engine's analytic CIE 1931 CMF fit, 1 nm nodes 360–830 nm; valid 1000–100000 K\"]);\n}\n\nfunction prepareLocus(model: PlanckianLocusModel, portable?: PortableOps): PreparedLocus {\n const record = requireRecordValue(model, \"locus\");\n if (record.kind === \"planck-analytic-cmf\") {\n rejectUnknownFields(record, [\"kind\"], \"locus\");\n return analyticCmfLocus(portable);\n }\n if (record.kind !== \"planck-integration\") throw new InvalidConfigurationError(\"locus.kind is not supported.\");\n rejectUnknownFields(record, [\"kind\", \"colorMatchingFunctions\", \"quadratureNodes\"], \"locus\");\n const m = model as Extract<PlanckianLocusModel, { kind: \"planck-integration\" }>;\n const cmf = prepareColorMatchingFunctions(m.colorMatchingFunctions);\n return preparePlanckIntegrationLocus(m.colorMatchingFunctions, m.quadratureNodes, \"planck-integration-\" + cmf.sourceKind, portable);\n}\n\n/** Planckian chromaticity at T using either locus model. */\nexport function calculatePlanckianChromaticity(input: { temperatureKelvin: number; locus: PlanckianLocusModel }): CalculationResult<CieXyChromaticity> {\n requireInputKeys(input, \"calculatePlanckianChromaticity\", [\"temperatureKelvin\", \"locus\"]);\n const locus = prepareLocus(input.locus);\n const t = requireTemperatureIn(input.temperatureKelvin, locus.range, \"temperatureKelvin\");\n const value = locus.chromaticity(t);\n const assumptions = [\"Planckian locus model: \" + locus.model];\n return locus.approximation\n ? approximationResult(value, \"planckian-chromaticity\", COLORIMETRY_MODEL_VERSION, assumptions)\n : calculatedResult(value, \"planckian-chromaticity\", COLORIMETRY_MODEL_VERSION, assumptions);\n}\n\n/**\n * McCamy (1992) cubic estimate of CCT from CIE 1931 xy:\n * n = (x − 0.3320)/(0.1858 − y), CCT = 449 n³ + 3525 n² + 6823.3 n + 5520.33.\n * An approximation that carries no Duv. Measured for this engine (October 17, 2026) on points of a\n * Planckian locus integrated from the CIE 1931 2° 1 nm table (360–830 nm, exact c₂): it deviates by up\n * to 10 K over 2856–6504 K (largest near 3500 K), 19 K at 2000 K, 17 K at 8000 K, 118 K at 10000 K\n * and 442 K at 12500 K. See docs/COLORIMETRY.md.\n */\nexport function estimateCorrelatedColorTemperatureMcCamy(input: { chromaticity: CieXyChromaticity }): CalculationResult<{ correlatedColorTemperatureKelvin: number }> {\n requireInputKeys(input, \"estimateCorrelatedColorTemperatureMcCamy\", [\"chromaticity\"]);\n const xy = parseChromaticity(input.chromaticity, \"chromaticity\");\n const n = (xy.x - 0.3320) / (0.1858 - xy.y);\n const cct = 449 * n ** 3 + 3525 * n ** 2 + 6823.3 * n + 5520.33;\n if (!Number.isFinite(cct) || cct <= 0) throw new InvalidScientificInputError(\"Chromaticity is outside the McCamy approximation domain.\");\n return approximationResult({ correlatedColorTemperatureKelvin: cct }, \"cct-mccamy-1992\", COLORIMETRY_MODEL_VERSION,\n [\"McCamy (1992) cubic; intended for chromaticities near the Planckian locus, about 2000–12500 K\"]);\n}\n\n/** The \"above-locus\" unit normal at a sample: the increasing-T unit tangent (−du/dx, −dv/dx) turned by −90°. */\nfunction locusNormal(s: LocusSample, portable?: PortableOps): Cie1960UvChromaticity {\n const len = portable ? portable.hypot(s.du, s.dv) : Math.hypot(s.du, s.dv);\n const tangent = { u: -s.du / len, v: -s.dv / len };\n // u decreases as T rises, so turning the tangent by −90° points toward larger v (above the locus).\n return { u: tangent.v, v: -tangent.u };\n}\n\n/**\n * Nearest locus point to `target` in CIE 1960 uv: the root of the derivative of the squared distance\n * F = (u − u₀)² + (v − v₀)². Roots of dF/dT and of dF/dx (x = 1/T) coincide, since dx/dT = −1/T² ≠ 0;\n * the root-find runs in x with g = ½ dF/dx = (u − u₀)u′ + (v − v₀)v′ and\n * g′ = u′² + v′² + (u − u₀)u″ + (v − v₀)v″ (analytic, see {@link preparePlanckIntegrationLocus}).\n * The cached coarse scan brackets the minimum; a Newton step falls back to bisection whenever it would\n * leave the bracket. Returns the root and the locus sample there, or undefined when the nearest point\n * lies beyond the model's range (by more than the tolerance).\n */\nfunction nearestLocusPoint(locus: PreparedLocus, target: Cie1960UvChromaticity): { x: number; sample: LocusSample } | undefined {\n const steps = CCT_SCAN_STEPS;\n const lo = 1e6 / locus.range.maximum, hi = 1e6 / locus.range.minimum, step = (hi - lo) / steps;\n const gridX = (i: number): number => (lo + step * i) * 1e-6;\n const scan = locus.scan();\n const f = (i: number): number => (scan[i]!.u - target.u) ** 2 + (scan[i]!.v - target.v) ** 2;\n let best = 0, bestValue = Infinity;\n for (let i = 0; i <= steps; i++) {\n const value = f(i);\n if (value < bestValue) { bestValue = value; best = i; }\n }\n const tolerance = (x: number): number => CCT_RELATIVE_TOLERANCE * x;\n const derivatives = (s: LocusSample): { g: number; gp: number } => {\n const eu = s.u - target.u, ev = s.v - target.v;\n return { g: eu * s.du + ev * s.dv, gp: s.du * s.du + s.dv * s.dv + eu * s.d2u + ev * s.d2v };\n };\n let a: number, b: number, x: number;\n if (best === 0 || best === steps) {\n // The scan minimum is a range limit: the nearest point is inside only if F still falls inward.\n x = gridX(best);\n const s = locus.sample(x), { g, gp } = derivatives(s);\n if (best === 0 ? g >= 0 : g <= 0) {\n // At the limit within the tolerance (one Newton step estimates the distance), or beyond it.\n return g === 0 || (gp > 0 && Math.abs(g / gp) <= tolerance(x)) ? { x, sample: s } : undefined;\n }\n a = best === 0 ? x : gridX(steps - 1);\n b = best === 0 ? gridX(1) : x;\n } else {\n // A discrete minimum between its neighbours brackets a local minimum; start at the parabola vertex.\n a = gridX(best - 1); b = gridX(best + 1);\n const fm = f(best - 1), fp = f(best + 1), curvature = fm - 2 * bestValue + fp;\n x = gridX(best) + (curvature > 0 ? (step * 1e-6 * (fm - fp)) / (2 * curvature) : 0);\n }\n let s = locus.sample(x);\n for (let i = 0; i < 100; i++) {\n const { g, gp } = derivatives(s);\n if (g === 0) break;\n if (g < 0) a = x; else b = x;\n let next = x - g / gp;\n if (!(gp > 0) || !(next > a && next < b)) next = 0.5 * (a + b);\n const converged = Math.abs(next - x) <= tolerance(next) || b - a <= tolerance(next);\n x = next;\n s = locus.sample(x);\n if (converged) break;\n }\n return { x, sample: s };\n}\n\nexport interface CorrelatedColorTemperatureResult {\n correlatedColorTemperatureKelvin: number;\n /** Signed CIE 1960 uv distance from the locus; positive above (greenish), negative below (the engine's convention). */\n duv: number;\n}\n\n/**\n * CCT and Duv of a chromaticity as the nearest point of the Planckian locus in the CIE\n * 1960 UCS (Smet et al. 2023; also CIE 15:2018). Finds the root of the analytic temperature derivative\n * of the squared uv distance (safeguarded Newton with bisection fallback, bracketed by a cached coarse\n * scan in reciprocal temperature), converged until a step changes T by at most 1e-10 of T. Throws\n * (fails closed) when the nearest point lies beyond the model's range, or when |Duv| > 0.05 (see\n * {@link MAX_CORRELATED_COLOR_TEMPERATURE_DUV}). Duv is positive above the locus (toward green) and\n * negative below it, the engine's documented sign convention.\n */\nexport function calculateCorrelatedColorTemperature(input: { chromaticity: CieXyChromaticity; locus: PlanckianLocusModel }): CalculationResult<CorrelatedColorTemperatureResult> {\n requireInputKeys(input, \"calculateCorrelatedColorTemperature\", [\"chromaticity\", \"locus\"]);\n const xy = parseChromaticity(input.chromaticity, \"chromaticity\");\n const locus = prepareLocus(input.locus);\n const target = uvOfChromaticity(xy);\n const nearest = nearestLocusPoint(locus, target);\n if (nearest === undefined) throw new InvalidScientificInputError(\"Chromaticity's nearest Planckian point lies outside the locus model range.\");\n const t = Math.min(locus.range.maximum, Math.max(locus.range.minimum, 1 / nearest.x));\n const point = nearest.sample, normal = locusNormal(point);\n const duv = (target.u - point.u) * normal.u + (target.v - point.v) * normal.v;\n if (Math.abs(duv) > MAX_CORRELATED_COLOR_TEMPERATURE_DUV) {\n throw new InvalidScientificInputError(\"|Duv| exceeds 0.05; no CCT is reported this far from the Planckian locus (the range evaluated by Smet et al. 2023).\");\n }\n const value = { correlatedColorTemperatureKelvin: t, duv };\n const assumptions = [\"Nearest point on the Planckian locus in CIE 1960 uv; locus model: \" + locus.model, \"Duv sign: positive above the locus (toward green), negative below (engine convention)\"];\n return locus.approximation\n ? approximationResult(value, \"cct-duv-locus-search\", COLORIMETRY_MODEL_VERSION, assumptions)\n : calculatedResult(value, \"cct-duv-locus-search\", COLORIMETRY_MODEL_VERSION, assumptions);\n}\n\n/** Locus whose temperature defines a white for CCT + Duv. */\nexport type WhiteLocus = \"planckian\" | \"cie-daylight\";\n\n/**\n * Chromaticity for CCT and Duv: the locus point (Planckian or CIE daylight) offset by\n * Duv along the unit normal of the Planckian locus at the same temperature in the CIE\n * 1960 UCS. For `cie-daylight`, Duv = 0 returns the daylight-locus point itself.\n * Throws InvalidScientificInputError when the offset point is not a physical chromaticity\n * (x ≥ 0, y > 0, x + y ≤ 1), for example 2000 K with Duv +0.02 (x + y ≈ 1.06).\n */\nexport function calculateChromaticityFromCorrelatedColorTemperature(input: {\n correlatedColorTemperatureKelvin: number;\n duv: number;\n whiteLocus: WhiteLocus;\n locus: PlanckianLocusModel;\n}): CalculationResult<CieXyChromaticity> {\n return chromaticityFromCorrelatedColorTemperature(input, undefined);\n}\n/**\n * Internal (not exported from the package): {@link calculateChromaticityFromCorrelatedColorTemperature} with the locus's\n * λ⁻⁵, e^x − 1 and normal length and the daylight-locus powers from the portable functions (the display view's Kelvin\n * white balance), so the result has the same bits in every JavaScript engine.\n */\nexport function calculatePortableChromaticityFromCorrelatedColorTemperature(input: Parameters<typeof calculateChromaticityFromCorrelatedColorTemperature>[0]):\n CalculationResult<CieXyChromaticity> {\n return chromaticityFromCorrelatedColorTemperature(input, PORTABLE);\n}\nfunction chromaticityFromCorrelatedColorTemperature(input: Parameters<typeof calculateChromaticityFromCorrelatedColorTemperature>[0], portable: PortableOps | undefined):\n CalculationResult<CieXyChromaticity> {\n requireInputKeys(input, \"calculateChromaticityFromCorrelatedColorTemperature\", [\"correlatedColorTemperatureKelvin\", \"duv\", \"whiteLocus\", \"locus\"]);\n const locus = prepareLocus(input.locus, portable);\n const duv = requireFiniteNumber(input.duv, \"duv\");\n if (Math.abs(duv) > MAX_CORRELATED_COLOR_TEMPERATURE_DUV) throw new InvalidScientificInputError(\"|duv| must not exceed 0.05.\");\n if (input.whiteLocus !== \"planckian\" && input.whiteLocus !== \"cie-daylight\") throw new InvalidConfigurationError(\"whiteLocus is not supported.\");\n const range = input.whiteLocus === \"cie-daylight\"\n ? { minimum: Math.max(locus.range.minimum, CIE_DAYLIGHT_LOCUS_RANGE_KELVIN.minimum), maximum: Math.min(locus.range.maximum, CIE_DAYLIGHT_LOCUS_RANGE_KELVIN.maximum) }\n : locus.range;\n const t = requireTemperatureIn(input.correlatedColorTemperatureKelvin, range, \"correlatedColorTemperatureKelvin\");\n const normal = locusNormal(locus.sample(1 / t), portable);\n const base = uvOfChromaticity(input.whiteLocus === \"cie-daylight\" ? daylightChromaticity(t, portable) : locus.chromaticity(t));\n const value = chromaticityOfUv({ u: base.u + duv * normal.u, v: base.v + duv * normal.v });\n // The same domain parseChromaticity enforces on input, so every result can be passed back in.\n if (!(value.x >= 0) || !(value.y > 0) || !(value.x + value.y <= 1)) {\n throw new InvalidScientificInputError(\"correlatedColorTemperatureKelvin and duv give a chromaticity outside x >= 0, y > 0, x + y <= 1.\");\n }\n const assumptions = [\"White locus: \" + input.whiteLocus + \"; Duv offset along the Planckian-locus normal (\" + locus.model + \") in CIE 1960 uv\"];\n const exactDaylightPoint = input.whiteLocus === \"cie-daylight\" && duv === 0;\n return locus.approximation && !exactDaylightPoint\n ? approximationResult(value, \"chromaticity-from-cct-duv\", COLORIMETRY_MODEL_VERSION, assumptions)\n : calculatedResult(value, \"chromaticity-from-cct-duv\", COLORIMETRY_MODEL_VERSION, assumptions);\n}\n"]}
1
+ {"version":3,"file":"illuminants.js","sourceRoot":"","sources":["../../src/color/illuminants.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Illuminant spectra and correlated-colour-temperature (CCT) helpers.\n *\n * - Planckian radiator: exact Planck law (BIPM Mise en pratique for the kelvin, Absolute Primary\n * Radiometry 2018, Eq. 1, free) with the exact SI defining constants (h, c, k; BIPM SI Brochure\n * 9th ed. 2019), so c₂ = hc/k = 1.438776877…e-2 m·K (NIST CODATA 2022). Wavelength is the vacuum\n * wavelength.\n * - CIE standard illuminant A: Planck's law relative to 560 nm with the CIE's defining constants\n * c₂ = 1.435e-2 m·K and T = 2848 K (also CIE 15:2018 Eq. 4.1 / ISO/CIE 11664-2, paid):\n * S_A(λ) = 100 (560/λ)^5 (exp(1.435e7/(2848·560)) − 1)/(exp(1.435e7/(2848 λ)) − 1)\n * (≈ 2856 K with the exact c₂). Computed from the formula, not a copied table; it reproduces the\n * free CIE 1 nm table (DOI 10.25039/CIE.DS.8jsxjrsn) to its six significant digits.\n * - CIE daylight: the CIE daylight-locus chromaticity polynomial and the M₁/M₂ weights (CIE 15:2018,\n * paid; no free text of the formulas found). With three-decimal rounding they reproduce the free\n * CIE D55 and D65 tables. The S₀/S₁/S₂ basis is a CIE dataset (CC BY-SA 4.0, not bundled);\n * callers supply it.\n * - Planckian locus: the chromaticity of a Planckian radiator at T, computed by integrating Planck's\n * law against colour-matching functions. The default uses the engine's analytic CIE 1931 fit with\n * 1 nm nodes from 360 to 830 nm (so it inherits that fit's approximation); callers may select\n * tabulated CMFs and their own nodes. Valid 1000–100000 K.\n * - CCT from chromaticity: McCamy (1992) cubic (approximation), or a nearest-point\n * search on the Planckian locus in the CIE 1960 UCS (CCT and signed Duv as defined in Smet et al.,\n * LEUKOS 2023, free archival copy from the US DOE; also CIE 15:2018). Duv sign: positive above the\n * locus (toward green), negative below (toward magenta), following Ohno, \"Calculation of CCT and Duv\n * and Practical Conversion Formulae\", CORM 2011 slides (free), slide 5; the engine documents and\n * tests it.\n * @see docs/COLORIMETRY.md for equations, coordinate/unit conventions and limits.\n */\n\nimport { approximationResult, calculatedResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport type { SpectralWavelengthRangeNanometers } from \"../core/spectral.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport {\n COLORIMETRY_MODEL_VERSION,\n integrateSampledXyz,\n prepareColorMatchingFunctions,\n prepareColorimetricSpectrum,\n sampleColorimetricBasis,\n type ColorMatchingFunctionsSource,\n type ColorimetricQuadratureNode,\n type ColorimetricSpectralSample,\n type ColorimetricSpectrum\n} from \"./color-matching-functions.js\";\nimport {\n chromaticityOfUv,\n chromaticityOfXyz,\n parseChromaticity,\n requireFiniteNumber,\n requirePositiveNumber,\n requireRecordValue,\n uvOfChromaticity,\n type Cie1960UvChromaticity,\n type CieXyChromaticity\n} from \"./colorimetry-math.js\";\nimport { rejectUnknownFields, requireInputKeys } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { portableExpm1, portableHypot, portablePow } from \"../core/portable-math.js\";\n\n/** Exact SI defining constants (BIPM SI Brochure, 9th edition, 2019). */\nexport const PLANCK_CONSTANT_JOULE_SECONDS = 6.62607015e-34;\nexport const SPEED_OF_LIGHT_METERS_PER_SECOND = 299_792_458;\nexport const BOLTZMANN_CONSTANT_JOULES_PER_KELVIN = 1.380649e-23;\n/** Second radiation constant c₂ = hc/k in m·K (derived from the exact constants). */\nexport const SECOND_RADIATION_CONSTANT_METER_KELVIN = (PLANCK_CONSTANT_JOULE_SECONDS * SPEED_OF_LIGHT_METERS_PER_SECOND) / BOLTZMANN_CONSTANT_JOULES_PER_KELVIN;\nconst FIRST_RADIATION_CONSTANT_RADIANCE = 2 * PLANCK_CONSTANT_JOULE_SECONDS * SPEED_OF_LIGHT_METERS_PER_SECOND ** 2;\n/** The same constant with c² as one correctly rounded product (the portable evaluation below). */\nconst FIRST_RADIATION_CONSTANT_RADIANCE_PORTABLE = 2 * PLANCK_CONSTANT_JOULE_SECONDS * (SPEED_OF_LIGHT_METERS_PER_SECOND * SPEED_OF_LIGHT_METERS_PER_SECOND);\n/**\n * The portable functions the display view's evaluations use. They are passed as an argument rather than called directly\n * from the shared code, so a bundle that never calls a portable variant (every capture) does not contain them.\n */\ninterface PortableOps { pow(x: number, y: number): number; expm1(x: number): number; hypot(x: number, y: number): number }\nconst PORTABLE: PortableOps = { pow: portablePow, expm1: portableExpm1, hypot: portableHypot };\n\n/** Temperature range of the Planckian-locus models, K. */\nexport const PLANCKIAN_LOCUS_RANGE_KELVIN = /* @__PURE__ */ Object.freeze({ minimum: 1000, maximum: 100000 });\n/** CIE daylight-locus validity, K. */\nexport const CIE_DAYLIGHT_LOCUS_RANGE_KELVIN = /* @__PURE__ */ Object.freeze({ minimum: 4000, maximum: 25000 });\n/**\n * Engine limit: no CCT beyond |Duv| = 0.05, the range over which Smet et al. (2023, free) evaluate CCT\n * methods for nominally white light (CIE 15:2018 §9.5, paid, gives the same limit).\n */\nexport const MAX_CORRELATED_COLOR_TEMPERATURE_DUV = 0.05;\n\n/**\n * Planck's law for blackbody spectral radiance per unit (vacuum) wavelength:\n * L(λ, T) = 2hc² / λ⁵ / (exp(hc/(λkT)) − 1). Returns W·m⁻²·sr⁻¹·nm⁻¹.\n */\nexport function calculatePlanckianSpectralRadiance(input: { temperatureKelvin: number; wavelengthNanometers: number }): number {\n requireInputKeys(input, \"calculatePlanckianSpectralRadiance\", [\"temperatureKelvin\", \"wavelengthNanometers\"]);\n const t = requirePositiveNumber(input.temperatureKelvin, \"temperatureKelvin\");\n const nm = requirePositiveNumber(input.wavelengthNanometers, \"wavelengthNanometers\");\n return planckianRadiancePerNanometer(t, nm, undefined);\n}\n/**\n * Planck's law at temperature t (K) and wavelength nm. `portable` evaluates λ⁵ and e^x − 1 with the engine's portable\n * functions (`portablePow`, `portableExpm1`; within 1 and 2 ulps) instead of `**` and Math.expm1, whose last bits differ\n * between JavaScript engines (V8 12 and V8 13 differ in about 10 % of λ⁵); the display view uses it.\n */\nfunction planckianRadiancePerNanometer(t: number, nm: number, portable: PortableOps | undefined): number {\n const lambda = nm * 1e-9;\n const exponent = SECOND_RADIATION_CONSTANT_METER_KELVIN / (lambda * t);\n // expm1 keeps precision in the Rayleigh–Jeans limit; overflow gives radiance 0.\n const radiancePerMeter = portable ? FIRST_RADIATION_CONSTANT_RADIANCE_PORTABLE / portable.pow(lambda, 5) / portable.expm1(exponent)\n : FIRST_RADIATION_CONSTANT_RADIANCE / lambda ** 5 / Math.expm1(exponent);\n return radiancePerMeter * 1e-9;\n}\n\n/** Planckian spectral radiance (W·m⁻²·sr⁻¹·nm⁻¹) as a function spectrum over the given range. */\nexport function createPlanckianSpectrum(input: { temperatureKelvin: number; wavelengthRangeNanometers: SpectralWavelengthRangeNanometers }): ColorimetricSpectrum {\n return planckianSpectrum(input, undefined);\n}\n/** Internal (not exported from the package): {@link createPlanckianSpectrum} evaluated with the portable functions (the display view). */\nexport function createPortablePlanckianSpectrum(input: { temperatureKelvin: number; wavelengthRangeNanometers: SpectralWavelengthRangeNanometers }): ColorimetricSpectrum {\n return planckianSpectrum(input, PORTABLE);\n}\nfunction planckianSpectrum(input: { temperatureKelvin: number; wavelengthRangeNanometers: SpectralWavelengthRangeNanometers }, portable: PortableOps | undefined): ColorimetricSpectrum {\n requireInputKeys(input, \"createPlanckianSpectrum\", [\"temperatureKelvin\", \"wavelengthRangeNanometers\"]);\n const temperatureKelvin = requirePositiveNumber(input.temperatureKelvin, \"temperatureKelvin\");\n const range = requireRecordValue(input.wavelengthRangeNanometers, \"wavelengthRangeNanometers\");\n rejectUnknownFields(range, [\"minimum\", \"maximum\"], \"wavelengthRangeNanometers\");\n const spectrum: ColorimetricSpectrum = {\n kind: \"function\",\n wavelengthRangeNanometers: { minimum: range.minimum as number, maximum: range.maximum as number },\n evaluate: portable ? (wavelengthNanometers): number => planckianRadiancePerNanometer(temperatureKelvin, requirePositiveNumber(wavelengthNanometers, \"wavelengthNanometers\"), portable)\n : (wavelengthNanometers): number => calculatePlanckianSpectralRadiance({ temperatureKelvin, wavelengthNanometers })\n };\n prepareColorimetricSpectrum(spectrum, \"planckianSpectrum\");\n return spectrum;\n}\n\n/** CIE illuminant A defining range (nm). */\nexport const CIE_ILLUMINANT_A_RANGE_NANOMETERS = /* @__PURE__ */ Object.freeze({ minimum: 300, maximum: 830 });\n\n/**\n * CIE standard illuminant A relative SPD from its defining formula (100 at 560 nm),\n * with c₂ = 1.435e-2 m·K and T = 2848 K as in the standard (≈ 2856 K with the\n * current c₂). Valid 300–830 nm.\n */\nexport function calculateCieIlluminantARelativeSpectralPower(wavelengthNanometers: number): number {\n return cieIlluminantA(wavelengthNanometers, undefined);\n}\n/** CIE illuminant A; `portable` evaluates the power and e^x − 1 with the portable functions (see planckianRadiancePerNanometer). */\nfunction cieIlluminantA(wavelengthNanometers: number, portable: PortableOps | undefined): number {\n const nm = requireFiniteNumber(wavelengthNanometers, \"wavelengthNanometers\");\n if (nm < CIE_ILLUMINANT_A_RANGE_NANOMETERS.minimum || nm > CIE_ILLUMINANT_A_RANGE_NANOMETERS.maximum) {\n throw new InvalidScientificInputError(\"CIE illuminant A is defined from 300 nm to 830 nm.\");\n }\n const c = 1.435e7 / 2848; // nm·K / K\n return portable ? 100 * portable.pow(560 / nm, 5) * (portable.expm1(c / 560) / portable.expm1(c / nm)) : 100 * (560 / nm) ** 5 * (Math.expm1(c / 560) / Math.expm1(c / nm));\n}\n\n/** CIE illuminant A as a function spectrum over its defining range. */\nexport function createCieIlluminantASpectrum(): ColorimetricSpectrum {\n return { kind: \"function\", wavelengthRangeNanometers: { ...CIE_ILLUMINANT_A_RANGE_NANOMETERS }, evaluate: calculateCieIlluminantARelativeSpectralPower };\n}\n/** Internal (not exported from the package): {@link createCieIlluminantASpectrum} evaluated with the portable functions (the display view). */\nexport function createPortableCieIlluminantASpectrum(): ColorimetricSpectrum {\n return { kind: \"function\", wavelengthRangeNanometers: { ...CIE_ILLUMINANT_A_RANGE_NANOMETERS }, evaluate: (nm) => cieIlluminantA(nm, PORTABLE) };\n}\n\nfunction requireTemperatureIn(t: unknown, range: { minimum: number; maximum: number }, what: string): number {\n const value = requirePositiveNumber(t, what);\n if (value < range.minimum || value > range.maximum) {\n throw new InvalidScientificInputError(what + \" must lie in [\" + range.minimum + \", \" + range.maximum + \"] K.\");\n }\n return value;\n}\n\nfunction daylightChromaticity(t: number, portable?: PortableOps): CieXyChromaticity {\n const t3 = portable ? portable.pow(t, 3) : t ** 3, t2 = portable ? t * t : t ** 2;\n const x = t <= 7000\n ? -4.6070e9 / t3 + 2.9678e6 / t2 + 0.09911e3 / t + 0.244063\n : -2.0064e9 / t3 + 1.9018e6 / t2 + 0.24748e3 / t + 0.237040;\n return { x, y: -3.000 * x * x + 2.870 * x - 0.275 };\n}\n\nexport interface CieDaylightComponentWeights {\n correlatedColorTemperatureKelvin: number;\n chromaticity: CieXyChromaticity;\n m1: number;\n m2: number;\n coefficientRounding: \"none\" | \"cie-three-decimals\";\n}\n\n/**\n * CIE daylight-locus chromaticity and S₁/S₂ weights for a CCT in 4000–25000 K\n * (CIE 15:2018 §4.1.2, paid; no free text of the formulas found). M₁, M₂ rounded to three decimals\n * reproduce the free CIE D55 and D65 tables (DOI 10.25039/CIE.DS.qewfb3kp, 10.25039/CIE.DS.hjfjmt59)\n * to their rounding; `coefficientRounding` makes that rounding explicit.\n * The temperature is used as given: D65's nominal 6500 K corresponds to 6504 K here.\n */\nexport function calculateCieDaylightComponentWeights(input: {\n correlatedColorTemperatureKelvin: number;\n coefficientRounding: \"none\" | \"cie-three-decimals\";\n}): CalculationResult<CieDaylightComponentWeights> {\n return cieDaylightComponentWeights(input, undefined);\n}\nfunction cieDaylightComponentWeights(input: { correlatedColorTemperatureKelvin: number; coefficientRounding: \"none\" | \"cie-three-decimals\" },\n portable: PortableOps | undefined): CalculationResult<CieDaylightComponentWeights> {\n requireInputKeys(input, \"calculateCieDaylightComponentWeights\", [\"correlatedColorTemperatureKelvin\", \"coefficientRounding\"]);\n const t = requireTemperatureIn(input.correlatedColorTemperatureKelvin, CIE_DAYLIGHT_LOCUS_RANGE_KELVIN, \"correlatedColorTemperatureKelvin\");\n if (input.coefficientRounding !== \"none\" && input.coefficientRounding !== \"cie-three-decimals\") {\n throw new InvalidConfigurationError(\"coefficientRounding must be \\\"none\\\" or \\\"cie-three-decimals\\\".\");\n }\n const xy = daylightChromaticity(t, portable);\n const m = 0.0241 + 0.2562 * xy.x - 0.7341 * xy.y;\n let m1 = (-1.3515 - 1.7703 * xy.x + 5.9114 * xy.y) / m;\n let m2 = (0.0300 - 31.4424 * xy.x + 30.0717 * xy.y) / m;\n if (input.coefficientRounding === \"cie-three-decimals\") {\n m1 = Math.round(m1 * 1000) / 1000;\n m2 = Math.round(m2 * 1000) / 1000;\n }\n return calculatedResult({ correlatedColorTemperatureKelvin: t, chromaticity: xy, m1, m2, coefficientRounding: input.coefficientRounding },\n \"cie-daylight-locus\", COLORIMETRY_MODEL_VERSION, [\"CIE daylight-locus polynomial and M1/M2 weights, checked against the free CIE D55 and D65 datasets (no free formula text found); valid 4000–25000 K\"]);\n}\n\n/** Caller-supplied CIE daylight basis S₀, S₁, S₂ (tabulated; CIE dataset not bundled). */\nexport interface CieDaylightBasis {\n s0: readonly ColorimetricSpectralSample[];\n s1: readonly ColorimetricSpectralSample[];\n s2: readonly ColorimetricSpectralSample[];\n /** Caller identity of the basis dataset (for example a DOI). */\n datasetId: string;\n}\n\n/**\n * Builds a CIE D-series relative SPD S(λ) = S₀ + M₁S₁ + M₂S₂ on the S₀ wavelengths from\n * caller-supplied basis tables (S₁, S₂ linearly interpolated; fail closed outside range).\n */\nexport function createCieDaylightSpectrum(input: {\n correlatedColorTemperatureKelvin: number;\n coefficientRounding: \"none\" | \"cie-three-decimals\";\n basis: CieDaylightBasis;\n}): ColorimetricSpectrum {\n return cieDaylightSpectrum(input, undefined);\n}\n/** Internal (not exported from the package): {@link createCieDaylightSpectrum} with the portable daylight-locus powers (the display view). */\nexport function createPortableCieDaylightSpectrum(input: Parameters<typeof createCieDaylightSpectrum>[0]): ColorimetricSpectrum {\n return cieDaylightSpectrum(input, PORTABLE);\n}\nfunction cieDaylightSpectrum(input: Parameters<typeof createCieDaylightSpectrum>[0], portable: PortableOps | undefined): ColorimetricSpectrum {\n requireInputKeys(input, \"createCieDaylightSpectrum\", [\"correlatedColorTemperatureKelvin\", \"coefficientRounding\", \"basis\"]);\n const weights = cieDaylightComponentWeights({\n correlatedColorTemperatureKelvin: input.correlatedColorTemperatureKelvin,\n coefficientRounding: input.coefficientRounding\n }, portable).value;\n const basis = requireRecordValue(input.basis, \"basis\");\n rejectUnknownFields(basis, [\"s0\", \"s1\", \"s2\", \"datasetId\"], \"basis\");\n if (typeof basis.datasetId !== \"string\" || basis.datasetId.trim().length === 0) {\n throw new InvalidConfigurationError(\"basis.datasetId must be a non-empty string.\");\n }\n const s0 = prepareColorimetricSpectrum({ kind: \"tabulated\", samples: input.basis.s0 }, \"basis.s0\");\n const s1 = prepareColorimetricSpectrum({ kind: \"tabulated\", samples: input.basis.s1 }, \"basis.s1\");\n const s2 = prepareColorimetricSpectrum({ kind: \"tabulated\", samples: input.basis.s2 }, \"basis.s2\");\n const samples = input.basis.s0.map((sample) => {\n const w = sample.wavelengthNanometers;\n return { wavelengthNanometers: w, value: s0.evaluate(w) + weights.m1 * s1.evaluate(w) + weights.m2 * s2.evaluate(w) };\n });\n return { kind: \"tabulated\", samples };\n}\n\n/** Selects how the Planckian locus is evaluated. */\nexport type PlanckianLocusModel =\n | {\n /** Planck's law integrated against the engine's analytic CIE 1931 CMFs, 1 nm nodes 360–830 nm (the default). */\n kind: \"planck-analytic-cmf\";\n }\n | {\n kind: \"planck-integration\";\n colorMatchingFunctions: ColorMatchingFunctionsSource;\n quadratureNodes: readonly ColorimetricQuadratureNode[];\n };\n\n/** Number of intervals of the coarse reciprocal-temperature scan that brackets the CCT search. */\nconst CCT_SCAN_STEPS = 200;\n/**\n * Convergence tolerance of the CCT root-find: it stops once a Newton (or bisection) step changes T by\n * at most this fraction of T (1e-6 K at 10000 K).\n */\nconst CCT_RELATIVE_TOLERANCE = 1e-10;\n\n/**\n * Locus uv and its first and second derivatives with respect to the reciprocal temperature x = 1/T\n * (K⁻¹), from the analytic derivatives of Planck's law integrated in the locus quadrature.\n */\ninterface LocusSample {\n u: number;\n v: number;\n du: number;\n dv: number;\n d2u: number;\n d2v: number;\n}\n\ninterface PreparedLocus {\n range: { minimum: number; maximum: number };\n approximation: boolean;\n model: string;\n chromaticity(t: number): CieXyChromaticity;\n /** uv and its x = 1/T derivatives at reciprocal temperature x. */\n sample(x: number): LocusSample;\n /** CIE 1960 uv at the coarse scan temperatures; computed once per prepared locus. */\n scan(): readonly Cie1960UvChromaticity[];\n}\n\n/**\n * Prepares a Planck-integration locus: the CMF values and 1/λ⁵ factors are sampled once, so each\n * temperature costs one exponential per node. Planck's constant factor 2hc² cancels in chromaticity.\n *\n * Derivatives: with x = 1/T, aᵢ = c₂/λᵢ and rᵢ = 1/(exp(aᵢx) − 1), Planck's law is proportional to\n * λᵢ⁻⁵ rᵢ, and exactly dr/dx = −a(r + r²) and d²r/dx² = a²(r + 3r² + 2r³) (differentiate\n * r = 1/(E − 1), E = exp(ax), and use E = 1 + 1/r). They are summed in the same quadrature as X, Y, Z.\n */\nfunction preparePlanckIntegrationLocus(cmfSource: ColorMatchingFunctionsSource, quadratureNodes: readonly ColorimetricQuadratureNode[], model: string,\n portable?: PortableOps): PreparedLocus {\n // `portable` (the display view): λ⁻⁵ and e^x − 1 from the portable functions, whose bits are the same in every engine.\n const expm1 = portable ? portable.expm1 : Math.expm1;\n const cmf = prepareColorMatchingFunctions(cmfSource);\n const unit = prepareColorimetricSpectrum({ kind: \"function\", wavelengthRangeNanometers: cmf.wavelengthRangeNanometers, evaluate: () => 1 });\n const basis = sampleColorimetricBasis(quadratureNodes, unit, cmf);\n const n = basis.nodes.length;\n const exponentPerKelvin = new Float64Array(n), inverseFifth = new Float64Array(n);\n // Per-node constants of the derivative sums: weight × CMF × λ⁻⁵ for X, Y and Z.\n const wx = new Float64Array(n), wy = new Float64Array(n), wz = new Float64Array(n);\n for (let i = 0; i < n; i++) {\n const lambda = basis.nodes[i]!.wavelengthNanometers * 1e-9;\n exponentPerKelvin[i] = SECOND_RADIATION_CONSTANT_METER_KELVIN / lambda;\n inverseFifth[i] = 1 / (portable ? portable.pow(lambda, 5) : lambda ** 5);\n const w = basis.weights[i]! * inverseFifth[i]!;\n wx[i] = w * basis.xBar[i]!; wy[i] = w * basis.yBar[i]!; wz[i] = w * basis.zBar[i]!;\n }\n const factor = new Float64Array(n);\n const range = PLANCKIAN_LOCUS_RANGE_KELVIN;\n let scanCache: readonly Cie1960UvChromaticity[] | undefined;\n const locus: PreparedLocus = {\n range,\n approximation: cmf.scientificStatus === \"approximation\",\n model,\n chromaticity(t: number): CieXyChromaticity {\n // expm1 keeps precision at long wavelengths; overflow at short ones gives 0, as in Planck's law.\n for (let i = 0; i < n; i++) factor[i] = inverseFifth[i]! / expm1(exponentPerKelvin[i]! / t);\n return chromaticityOfXyz(integrateSampledXyz(basis, factor));\n },\n sample(x: number): LocusSample {\n let sx = 0, sy = 0, sz = 0, sx1 = 0, sy1 = 0, sz1 = 0, sx2 = 0, sy2 = 0, sz2 = 0;\n for (let i = 0; i < n; i++) {\n const a = exponentPerKelvin[i]!;\n // An overflowing expm1 gives r = 0 and zero derivatives, the exact limit.\n const r = 1 / expm1(a * x), r2 = r * r;\n const q1 = r + r2, k1 = -a * q1, k2 = a * a * (q1 + 2 * r2 * (1 + r));\n const cx = wx[i]!, cy = wy[i]!, cz = wz[i]!;\n sx += cx * r; sy += cy * r; sz += cz * r;\n sx1 += cx * k1; sy1 += cy * k1; sz1 += cz * k1;\n sx2 += cx * k2; sy2 += cy * k2; sz2 += cz * k2;\n }\n // u = 4X/d, v = 6Y/d, d = X + 15Y + 3Z; quotient rule: q' = (N' − q d')/d, q'' = (N'' − 2q'd' − q d'')/d.\n const d = sx + 15 * sy + 3 * sz, d1 = sx1 + 15 * sy1 + 3 * sz1, d2 = sx2 + 15 * sy2 + 3 * sz2;\n if (!(d > 0) || !Number.isFinite(d)) throw new InvalidScientificInputError(\"Chromaticity requires X + Y + Z > 0.\");\n const u = (4 * sx) / d, v = (6 * sy) / d;\n const du = (4 * sx1 - u * d1) / d, dv = (6 * sy1 - v * d1) / d;\n return { u, v, du, dv, d2u: (4 * sx2 - 2 * du * d1 - u * d2) / d, d2v: (6 * sy2 - 2 * dv * d1 - v * d2) / d };\n },\n scan(): readonly Cie1960UvChromaticity[] {\n if (scanCache === undefined) {\n const lo = 1e6 / range.maximum, hi = 1e6 / range.minimum;\n scanCache = Array.from({ length: CCT_SCAN_STEPS + 1 }, (_, i) => uvOfChromaticity(locus.chromaticity(1e6 / (lo + ((hi - lo) * i) / CCT_SCAN_STEPS))));\n }\n return scanCache;\n }\n };\n return locus;\n}\n\n/** 1 nm nodes at 360, 361, …, 830 nm with Δλ = 1 nm (the CIE 15 summation convention). */\nconst DEFAULT_LOCUS_NODES: readonly ColorimetricQuadratureNode[] = Object.freeze(\n Array.from({ length: 471 }, (_, i) => Object.freeze({ wavelengthNanometers: 360 + i, wavelengthMeasureNanometers: 1 }))\n);\nlet defaultLocus: PreparedLocus | undefined, defaultPortableLocus: PreparedLocus | undefined;\n\n/** The default locus, prepared on first use and shared (its scan cache is computed once); `portable` for the display view. */\nfunction analyticCmfLocus(portable?: PortableOps): PreparedLocus {\n if (portable) {\n defaultPortableLocus ??= preparePlanckIntegrationLocus({ kind: \"analytic-cie-1931-multi-lobe-fit\" }, DEFAULT_LOCUS_NODES, \"planck-analytic-cmf\", portable);\n return defaultPortableLocus;\n }\n defaultLocus ??= preparePlanckIntegrationLocus({ kind: \"analytic-cie-1931-multi-lobe-fit\" }, DEFAULT_LOCUS_NODES, \"planck-analytic-cmf\");\n return defaultLocus;\n}\n\n/**\n * Planckian-locus chromaticity at T (1000–100000 K): Planck's law integrated against the engine's\n * analytic CIE 1931 CMFs with 1 nm nodes from 360 to 830 nm. An approximation, because the CMFs are\n * an analytic fit; with tabulated CMFs use {@link calculatePlanckianChromaticity}.\n */\nexport function estimatePlanckianLocusChromaticity(input: { temperatureKelvin: number }): CalculationResult<CieXyChromaticity> {\n requireInputKeys(input, \"estimatePlanckianLocusChromaticity\", [\"temperatureKelvin\"]);\n const t = requireTemperatureIn(input.temperatureKelvin, PLANCKIAN_LOCUS_RANGE_KELVIN, \"temperatureKelvin\");\n return approximationResult(analyticCmfLocus().chromaticity(t), \"planckian-locus-planck-analytic-cmf\", COLORIMETRY_MODEL_VERSION,\n [\"Planck's law integrated against the engine's analytic CIE 1931 CMF fit, 1 nm nodes 360–830 nm; valid 1000–100000 K\"]);\n}\n\nfunction prepareLocus(model: PlanckianLocusModel, portable?: PortableOps): PreparedLocus {\n const record = requireRecordValue(model, \"locus\");\n if (record.kind === \"planck-analytic-cmf\") {\n rejectUnknownFields(record, [\"kind\"], \"locus\");\n return analyticCmfLocus(portable);\n }\n if (record.kind !== \"planck-integration\") throw new InvalidConfigurationError(\"locus.kind is not supported.\");\n rejectUnknownFields(record, [\"kind\", \"colorMatchingFunctions\", \"quadratureNodes\"], \"locus\");\n const m = model as Extract<PlanckianLocusModel, { kind: \"planck-integration\" }>;\n const cmf = prepareColorMatchingFunctions(m.colorMatchingFunctions);\n return preparePlanckIntegrationLocus(m.colorMatchingFunctions, m.quadratureNodes, \"planck-integration-\" + cmf.sourceKind, portable);\n}\n\n/** Planckian chromaticity at T using either locus model. */\nexport function calculatePlanckianChromaticity(input: { temperatureKelvin: number; locus: PlanckianLocusModel }): CalculationResult<CieXyChromaticity> {\n requireInputKeys(input, \"calculatePlanckianChromaticity\", [\"temperatureKelvin\", \"locus\"]);\n const locus = prepareLocus(input.locus);\n const t = requireTemperatureIn(input.temperatureKelvin, locus.range, \"temperatureKelvin\");\n const value = locus.chromaticity(t);\n const assumptions = [\"Planckian locus model: \" + locus.model];\n return locus.approximation\n ? approximationResult(value, \"planckian-chromaticity\", COLORIMETRY_MODEL_VERSION, assumptions)\n : calculatedResult(value, \"planckian-chromaticity\", COLORIMETRY_MODEL_VERSION, assumptions);\n}\n\n/**\n * McCamy (1992) cubic estimate of CCT from CIE 1931 xy:\n * n = (x − 0.3320)/(0.1858 − y), CCT = 449 n³ + 3525 n² + 6823.3 n + 5520.33.\n * An approximation that carries no Duv. Measured for this engine (October 17, 2026) on points of a\n * Planckian locus integrated from the CIE 1931 2° 1 nm table (360–830 nm, exact c₂): it deviates by up\n * to 10 K over 2856–6504 K (largest near 3500 K), 19 K at 2000 K, 17 K at 8000 K, 118 K at 10000 K\n * and 442 K at 12500 K. See docs/COLORIMETRY.md.\n */\nexport function estimateCorrelatedColorTemperatureMcCamy(input: { chromaticity: CieXyChromaticity }): CalculationResult<{ correlatedColorTemperatureKelvin: number }> {\n requireInputKeys(input, \"estimateCorrelatedColorTemperatureMcCamy\", [\"chromaticity\"]);\n const xy = parseChromaticity(input.chromaticity, \"chromaticity\");\n const n = (xy.x - 0.3320) / (0.1858 - xy.y);\n const cct = 449 * n ** 3 + 3525 * n ** 2 + 6823.3 * n + 5520.33;\n if (!Number.isFinite(cct) || cct <= 0) throw new InvalidScientificInputError(\"Chromaticity is outside the McCamy approximation domain.\");\n return approximationResult({ correlatedColorTemperatureKelvin: cct }, \"cct-mccamy-1992\", COLORIMETRY_MODEL_VERSION,\n [\"McCamy (1992) cubic; intended for chromaticities near the Planckian locus, about 2000–12500 K\"]);\n}\n\n/** The \"above-locus\" unit normal at a sample: the increasing-T unit tangent (−du/dx, −dv/dx) turned by −90°. */\nfunction locusNormal(s: LocusSample, portable?: PortableOps): Cie1960UvChromaticity {\n const len = portable ? portable.hypot(s.du, s.dv) : Math.hypot(s.du, s.dv);\n const tangent = { u: -s.du / len, v: -s.dv / len };\n // u decreases as T rises, so turning the tangent by −90° points toward larger v (above the locus).\n return { u: tangent.v, v: -tangent.u };\n}\n\n/**\n * Nearest locus point to `target` in CIE 1960 uv: the root of the derivative of the squared distance\n * F = (u − u₀)² + (v − v₀)². Roots of dF/dT and of dF/dx (x = 1/T) coincide, since dx/dT = −1/T² ≠ 0;\n * the root-find runs in x with g = ½ dF/dx = (u − u₀)u′ + (v − v₀)v′ and\n * g′ = u′² + v′² + (u − u₀)u″ + (v − v₀)v″ (analytic, see {@link preparePlanckIntegrationLocus}).\n * The cached coarse scan brackets the minimum; a Newton step falls back to bisection whenever it would\n * leave the bracket. Returns the root and the locus sample there, or undefined when the nearest point\n * lies beyond the model's range (by more than the tolerance).\n */\nfunction nearestLocusPoint(locus: PreparedLocus, target: Cie1960UvChromaticity): { x: number; sample: LocusSample } | undefined {\n const steps = CCT_SCAN_STEPS;\n const lo = 1e6 / locus.range.maximum, hi = 1e6 / locus.range.minimum, step = (hi - lo) / steps;\n const gridX = (i: number): number => (lo + step * i) * 1e-6;\n const scan = locus.scan();\n const f = (i: number): number => (scan[i]!.u - target.u) ** 2 + (scan[i]!.v - target.v) ** 2;\n let best = 0, bestValue = Infinity;\n for (let i = 0; i <= steps; i++) {\n const value = f(i);\n if (value < bestValue) { bestValue = value; best = i; }\n }\n const tolerance = (x: number): number => CCT_RELATIVE_TOLERANCE * x;\n const derivatives = (s: LocusSample): { g: number; gp: number } => {\n const eu = s.u - target.u, ev = s.v - target.v;\n return { g: eu * s.du + ev * s.dv, gp: s.du * s.du + s.dv * s.dv + eu * s.d2u + ev * s.d2v };\n };\n let a: number, b: number, x: number;\n if (best === 0 || best === steps) {\n // The scan minimum is a range limit: the nearest point is inside only if F still falls inward.\n x = gridX(best);\n const s = locus.sample(x), { g, gp } = derivatives(s);\n if (best === 0 ? g >= 0 : g <= 0) {\n // At the limit within the tolerance (one Newton step estimates the distance), or beyond it.\n return g === 0 || (gp > 0 && Math.abs(g / gp) <= tolerance(x)) ? { x, sample: s } : undefined;\n }\n a = best === 0 ? x : gridX(steps - 1);\n b = best === 0 ? gridX(1) : x;\n } else {\n // A discrete minimum between its neighbours brackets a local minimum; start at the parabola vertex.\n a = gridX(best - 1); b = gridX(best + 1);\n const fm = f(best - 1), fp = f(best + 1), curvature = fm - 2 * bestValue + fp;\n x = gridX(best) + (curvature > 0 ? (step * 1e-6 * (fm - fp)) / (2 * curvature) : 0);\n }\n let s = locus.sample(x);\n for (let i = 0; i < 100; i++) {\n const { g, gp } = derivatives(s);\n if (g === 0) break;\n if (g < 0) a = x; else b = x;\n let next = x - g / gp;\n if (!(gp > 0) || !(next > a && next < b)) next = 0.5 * (a + b);\n const converged = Math.abs(next - x) <= tolerance(next) || b - a <= tolerance(next);\n x = next;\n s = locus.sample(x);\n if (converged) break;\n }\n return { x, sample: s };\n}\n\nexport interface CorrelatedColorTemperatureResult {\n correlatedColorTemperatureKelvin: number;\n /** Signed CIE 1960 uv distance from the locus; positive above (greenish), negative below (the engine's convention). */\n duv: number;\n}\n\n/**\n * CCT and Duv of a chromaticity as the nearest point of the Planckian locus in the CIE\n * 1960 UCS (Smet et al. 2023; also CIE 15:2018). Finds the root of the analytic temperature derivative\n * of the squared uv distance (safeguarded Newton with bisection fallback, bracketed by a cached coarse\n * scan in reciprocal temperature), converged until a step changes T by at most 1e-10 of T. Throws\n * (fails closed) when the nearest point lies beyond the model's range, or when |Duv| > 0.05 (see\n * {@link MAX_CORRELATED_COLOR_TEMPERATURE_DUV}). Duv is positive above the locus (toward green) and\n * negative below it, the engine's documented sign convention.\n */\nexport function calculateCorrelatedColorTemperature(input: { chromaticity: CieXyChromaticity; locus: PlanckianLocusModel }): CalculationResult<CorrelatedColorTemperatureResult> {\n requireInputKeys(input, \"calculateCorrelatedColorTemperature\", [\"chromaticity\", \"locus\"]);\n const xy = parseChromaticity(input.chromaticity, \"chromaticity\");\n const locus = prepareLocus(input.locus);\n const target = uvOfChromaticity(xy);\n const nearest = nearestLocusPoint(locus, target);\n if (nearest === undefined) throw new InvalidScientificInputError(\"Chromaticity's nearest Planckian point lies outside the locus model range.\");\n const t = Math.min(locus.range.maximum, Math.max(locus.range.minimum, 1 / nearest.x));\n const point = nearest.sample, normal = locusNormal(point);\n const duv = (target.u - point.u) * normal.u + (target.v - point.v) * normal.v;\n if (Math.abs(duv) > MAX_CORRELATED_COLOR_TEMPERATURE_DUV) {\n throw new InvalidScientificInputError(\"|Duv| exceeds 0.05; no CCT is reported this far from the Planckian locus (the range evaluated by Smet et al. 2023).\");\n }\n const value = { correlatedColorTemperatureKelvin: t, duv };\n const assumptions = [\"Nearest point on the Planckian locus in CIE 1960 uv; locus model: \" + locus.model, \"Duv sign: positive above the locus (toward green), negative below (engine convention)\"];\n return locus.approximation\n ? approximationResult(value, \"cct-duv-locus-search\", COLORIMETRY_MODEL_VERSION, assumptions)\n : calculatedResult(value, \"cct-duv-locus-search\", COLORIMETRY_MODEL_VERSION, assumptions);\n}\n\n/** Locus whose temperature defines a white for CCT + Duv. */\nexport type WhiteLocus = \"planckian\" | \"cie-daylight\";\n\n/**\n * Chromaticity for CCT and Duv: the locus point (Planckian or CIE daylight) offset by\n * Duv along the unit normal of the Planckian locus at the same temperature in the CIE\n * 1960 UCS. For `cie-daylight`, Duv = 0 returns the daylight-locus point itself.\n * Throws InvalidScientificInputError when the offset point is not a physical chromaticity\n * (x ≥ 0, y > 0, x + y ≤ 1), for example 2000 K with Duv +0.02 (x + y ≈ 1.06).\n */\nexport function calculateChromaticityFromCorrelatedColorTemperature(input: {\n correlatedColorTemperatureKelvin: number;\n duv: number;\n whiteLocus: WhiteLocus;\n locus: PlanckianLocusModel;\n}): CalculationResult<CieXyChromaticity> {\n return chromaticityFromCorrelatedColorTemperature(input, undefined);\n}\n/**\n * Internal (not exported from the package): {@link calculateChromaticityFromCorrelatedColorTemperature} with the locus's\n * λ⁻⁵, e^x − 1 and normal length and the daylight-locus powers from the portable functions (the display view's Kelvin\n * white balance), so the result has the same bits in every JavaScript engine.\n */\nexport function calculatePortableChromaticityFromCorrelatedColorTemperature(input: Parameters<typeof calculateChromaticityFromCorrelatedColorTemperature>[0]):\n CalculationResult<CieXyChromaticity> {\n return chromaticityFromCorrelatedColorTemperature(input, PORTABLE);\n}\nfunction chromaticityFromCorrelatedColorTemperature(input: Parameters<typeof calculateChromaticityFromCorrelatedColorTemperature>[0], portable: PortableOps | undefined):\n CalculationResult<CieXyChromaticity> {\n requireInputKeys(input, \"calculateChromaticityFromCorrelatedColorTemperature\", [\"correlatedColorTemperatureKelvin\", \"duv\", \"whiteLocus\", \"locus\"]);\n const locus = prepareLocus(input.locus, portable);\n const duv = requireFiniteNumber(input.duv, \"duv\");\n if (Math.abs(duv) > MAX_CORRELATED_COLOR_TEMPERATURE_DUV) throw new InvalidScientificInputError(\"|duv| must not exceed 0.05.\");\n if (input.whiteLocus !== \"planckian\" && input.whiteLocus !== \"cie-daylight\") throw new InvalidConfigurationError(\"whiteLocus is not supported.\");\n const range = input.whiteLocus === \"cie-daylight\"\n ? { minimum: Math.max(locus.range.minimum, CIE_DAYLIGHT_LOCUS_RANGE_KELVIN.minimum), maximum: Math.min(locus.range.maximum, CIE_DAYLIGHT_LOCUS_RANGE_KELVIN.maximum) }\n : locus.range;\n const t = requireTemperatureIn(input.correlatedColorTemperatureKelvin, range, \"correlatedColorTemperatureKelvin\");\n const normal = locusNormal(locus.sample(1 / t), portable);\n const base = uvOfChromaticity(input.whiteLocus === \"cie-daylight\" ? daylightChromaticity(t, portable) : locus.chromaticity(t));\n const value = chromaticityOfUv({ u: base.u + duv * normal.u, v: base.v + duv * normal.v });\n // The same domain parseChromaticity enforces on input, so every result can be passed back in.\n if (!(value.x >= 0) || !(value.y > 0) || !(value.x + value.y <= 1)) {\n throw new InvalidScientificInputError(\"correlatedColorTemperatureKelvin and duv give a chromaticity outside x >= 0, y > 0, x + y <= 1.\");\n }\n const assumptions = [\"White locus: \" + input.whiteLocus + \"; Duv offset along the Planckian-locus normal (\" + locus.model + \") in CIE 1960 uv\"];\n const exactDaylightPoint = input.whiteLocus === \"cie-daylight\" && duv === 0;\n return locus.approximation && !exactDaylightPoint\n ? approximationResult(value, \"chromaticity-from-cct-duv\", COLORIMETRY_MODEL_VERSION, assumptions)\n : calculatedResult(value, \"chromaticity-from-cct-duv\", COLORIMETRY_MODEL_VERSION, assumptions);\n}\n"]}
@@ -48,7 +48,7 @@ export function calculateRgbToXyzMatrices(input) {
48
48
  requireFiniteResult([...value.rgbToXyz.flat(), ...value.xyzToRgb.flat()], "RGB matrix derivation");
49
49
  return calculatedResult(value, "rgb-xyz-matrix-smpte-rp177", COLORIMETRY_MODEL_VERSION);
50
50
  }
51
- const D65_CHROMATICITY = Object.freeze({ x: 0.3127, y: 0.3290 });
51
+ const D65_CHROMATICITY = /* @__PURE__ */ Object.freeze({ x: 0.3127, y: 0.3290 });
52
52
  const BT709_PRIMARIES = { red: { x: 0.64, y: 0.33 }, green: { x: 0.30, y: 0.60 }, blue: { x: 0.15, y: 0.06 } };
53
53
  const SPACES = {
54
54
  srgb: { primaries: BT709_PRIMARIES, transferFunction: "srgb", sources: ["W3C CSS Color Module Level 4 srgb", "ITU-R BT.709-6"] },
@@ -1 +1 @@
1
- {"version":3,"file":"rgb-color-spaces.js","sourceRoot":"","sources":["../../src/color/rgb-color-spaces.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Wide-gamut output primitives (standalone; output wiring belongs to the SDR/export stages):\n * - RGB ↔ XYZ matrices derived numerically from primary and white chromaticities: RGB (1, 1, 1)\n * is the white (W3C CSS Color 4 §2, free), never copied matrices. They equal the CSS Color 4\n * sample-code matrices to about 1e-15 (test/colorimetry-output-and-camera.test.ts).\n * sRGB / BT.709: ITU-R BT.709-6 and W3C CSS Color 4 `srgb` (also IEC 61966-2-1:1999); Display P3:\n * P3 primaries with D65 white as specified for `display-p3` in W3C CSS Color 4 (also SMPTE EG 432-1:2010);\n * BT.2020: ITU-R BT.2020-2. All use D65 (0.3127, 0.3290).\n * - Transfer functions: sRGB (W3C CSS Color 4; also IEC 61966-2-1; also Display P3), BT.709 OETF, BT.1886 EOTF\n * (ITU-R BT.1886). The BT.2100 PQ and HLG transfer functions are not part of 2.0 (owner decision,\n * 2026-10-17: their patent holders offer only licence-on-request declarations; see THIRD_PARTY.md).\n * Constants are the published values of those standards.\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 { decodeSrgbComponent, encodeSrgbComponent } from \"./srgb-transfer.js\";\nimport { COLORIMETRY_MODEL_VERSION } from \"./color-matching-functions.js\";\nimport {\n copyMatrix,\n invertMatrix3x3,\n multiplyMatrixVector,\n parseChromaticity,\n requireFiniteNumber,\n requireFiniteResult,\n requireNonNegativeNumber,\n requirePositiveNumber,\n requireRecordValue,\n xyzOfChromaticity,\n type CieXyChromaticity,\n type CieXyzTristimulus,\n type ColorMatrix3x3\n} from \"./colorimetry-math.js\";\nimport { rejectUnknownFields, requireInputKeys } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\n/** RGB primaries as CIE 1931 xy chromaticities. */\nexport interface RgbPrimaryChromaticities {\n red: CieXyChromaticity;\n green: CieXyChromaticity;\n blue: CieXyChromaticity;\n}\n\nexport interface RgbToXyzMatrices {\n /** Linear RGB (white = 1, 1, 1) → XYZ with white Y = 1. */\n rgbToXyz: ColorMatrix3x3;\n xyzToRgb: ColorMatrix3x3;\n whiteXyz: CieXyzTristimulus;\n}\n\n/** Internal: derivation from primaries and white (see {@link calculateRgbToXyzMatrices}) without an envelope. */\nexport function rgbToXyzMatrices(primaries: RgbPrimaryChromaticities, white: CieXyChromaticity): RgbToXyzMatrices {\n const p = requireRecordValue(primaries, \"primaries\");\n rejectUnknownFields(p, [\"red\", \"green\", \"blue\"], \"primaries\");\n const columns = ([\"red\", \"green\", \"blue\"] as const).map((k) => xyzOfChromaticity(parseChromaticity(p[k], \"primaries.\" + k)));\n const basis: ColorMatrix3x3 = [\n [columns[0]!.x, columns[1]!.x, columns[2]!.x],\n [columns[0]!.y, columns[1]!.y, columns[2]!.y],\n [columns[0]!.z, columns[1]!.z, columns[2]!.z]\n ];\n const whiteXyz = xyzOfChromaticity(parseChromaticity(white, \"whiteChromaticity\"));\n const s = multiplyMatrixVector(invertMatrix3x3(basis, \"primary matrix\"), [whiteXyz.x, whiteXyz.y, whiteXyz.z]);\n if (s.some((v) => !(v > 0))) throw new InvalidScientificInputError(\"The white point must lie strictly inside the primary triangle.\");\n const rgbToXyz = basis.map((row) => row.map((v, i) => v * s[i]!)) as unknown as ColorMatrix3x3;\n return { rgbToXyz, xyzToRgb: invertMatrix3x3(rgbToXyz, \"rgbToXyz\"), whiteXyz };\n}\n\n/**\n * Derives RGB ↔ XYZ matrices from primaries and white chromaticity: columns are the primaries'\n * XYZ (Y = 1) scaled so that RGB (1, 1, 1) maps to the white (W3C CSS Color 4, free; also SMPTE\n * RP 177). The derivation is written out in docs/COLORIMETRY.md.\n */\nexport function calculateRgbToXyzMatrices(input: { primaries: RgbPrimaryChromaticities; whiteChromaticity: CieXyChromaticity }): CalculationResult<RgbToXyzMatrices> {\n requireInputKeys(input, \"calculateRgbToXyzMatrices\", [\"primaries\", \"whiteChromaticity\"]);\n const value = rgbToXyzMatrices(input.primaries, input.whiteChromaticity);\n requireFiniteResult([...value.rgbToXyz.flat(), ...value.xyzToRgb.flat()], \"RGB matrix derivation\");\n return calculatedResult(value, \"rgb-xyz-matrix-smpte-rp177\", COLORIMETRY_MODEL_VERSION);\n}\n\nexport type RgbColorSpaceId = \"srgb\" | \"display-p3\" | \"rec709\" | \"rec2020\";\nexport type RgbTransferFunctionId = \"srgb\" | \"bt709-oetf-bt1886-eotf\" | \"bt2020-oetf\";\n\nexport interface RgbColorSpaceDefinition extends RgbToXyzMatrices {\n id: RgbColorSpaceId;\n primaries: RgbPrimaryChromaticities;\n whiteChromaticity: CieXyChromaticity;\n /** Conventional non-linear (SDR) encoding of this space. */\n transferFunction: RgbTransferFunctionId;\n sources: readonly string[];\n}\n\nconst D65_CHROMATICITY: CieXyChromaticity = Object.freeze({ x: 0.3127, y: 0.3290 });\nconst BT709_PRIMARIES: RgbPrimaryChromaticities = { red: { x: 0.64, y: 0.33 }, green: { x: 0.30, y: 0.60 }, blue: { x: 0.15, y: 0.06 } };\nconst SPACES: Readonly<Record<RgbColorSpaceId, { primaries: RgbPrimaryChromaticities; transferFunction: RgbTransferFunctionId; sources: readonly string[] }>> = {\n srgb: { primaries: BT709_PRIMARIES, transferFunction: \"srgb\", sources: [\"W3C CSS Color Module Level 4 srgb\", \"ITU-R BT.709-6\"] },\n rec709: { primaries: BT709_PRIMARIES, transferFunction: \"bt709-oetf-bt1886-eotf\", sources: [\"ITU-R BT.709-6\", \"ITU-R BT.1886\"] },\n \"display-p3\": {\n primaries: { red: { x: 0.680, y: 0.320 }, green: { x: 0.265, y: 0.690 }, blue: { x: 0.150, y: 0.060 } },\n transferFunction: \"srgb\", sources: [\"W3C CSS Color Module Level 4 display-p3 (P3 primaries, D65, sRGB transfer)\", \"ITU-T H.273 ColourPrimaries 12\"]\n },\n rec2020: {\n primaries: { red: { x: 0.708, y: 0.292 }, green: { x: 0.170, y: 0.797 }, blue: { x: 0.131, y: 0.046 } },\n transferFunction: \"bt2020-oetf\", sources: [\"ITU-R BT.2020-2\"]\n }\n};\n\n/** Resolves a named RGB colour space with numerically derived matrices (all D65). */\nexport function resolveRgbColorSpace(id: RgbColorSpaceId): CalculationResult<RgbColorSpaceDefinition> {\n const space = typeof id === \"string\" && Object.hasOwn(SPACES, id) ? SPACES[id] : undefined;\n if (space === undefined) throw new InvalidConfigurationError(\"Unknown RGB colour space.\");\n const matrices = rgbToXyzMatrices(space.primaries, D65_CHROMATICITY);\n const value: RgbColorSpaceDefinition = {\n id, primaries: JSON.parse(JSON.stringify(space.primaries)) as RgbPrimaryChromaticities, whiteChromaticity: { ...D65_CHROMATICITY },\n transferFunction: space.transferFunction, sources: [...space.sources],\n rgbToXyz: copyMatrix(matrices.rgbToXyz), xyzToRgb: copyMatrix(matrices.xyzToRgb), whiteXyz: matrices.whiteXyz\n };\n return calculatedResult(value, \"rgb-color-space-\" + id, COLORIMETRY_MODEL_VERSION, [\"Matrices derived from primaries and D65 white so that RGB (1, 1, 1) is the white (W3C CSS Color 4)\"]);\n}\n\n// ---------------------------------------------------------------- transfers\n\n/** sRGB / Display P3 encoding (W3C CSS Color 4; also IEC 61966-2-1) of one linear component; negative values use the linear segment. */\nexport function evaluateSrgbEncoding(linear: number): number {\n return encodeSrgbComponent(requireFiniteNumber(linear, \"linear\"));\n}\n\n/** sRGB / Display P3 decoding of one non-linear component. */\nexport function evaluateSrgbDecoding(encoded: number): number {\n return decodeSrgbComponent(requireFiniteNumber(encoded, \"encoded\"));\n}\n\n/**\n * ITU-R BT.709-6 / BT.2020-2 (10-bit) OETF: V = 4.5 L for L < 0.018, otherwise\n * 1.099 L^0.45 − 0.099. Scene-referred camera encoding, not a display EOTF.\n */\nexport function evaluateBt709Oetf(sceneLinear: number): number {\n const l = requireFiniteNumber(sceneLinear, \"sceneLinear\");\n return l < 0.018 ? 4.5 * l : 1.099 * l ** 0.45 - 0.099;\n}\n\n/** Inverse of the BT.709 OETF: L = V/4.5 for V < 0.081, otherwise ((V + 0.099)/1.099)^(1/0.45). */\nexport function evaluateBt709InverseOetf(encoded: number): number {\n const v = requireFiniteNumber(encoded, \"encoded\");\n return v < 4.5 * 0.018 ? v / 4.5 : ((v + 0.099) / 1.099) ** (1 / 0.45);\n}\n\nexport interface Bt1886Eotf {\n whiteLuminanceCdPerSquareMeter: number;\n blackLuminanceCdPerSquareMeter: number;\n /** a = (Lw^(1/γ) − Lb^(1/γ))^γ */\n a: number;\n /** b = Lb^(1/γ) / (Lw^(1/γ) − Lb^(1/γ)) */\n b: number;\n /** L = a · max(V + b, 0)^2.4 in cd/m². */\n decode(signal: number): number;\n /** Inverse: V = (L/a)^(1/2.4) − b. */\n encode(luminanceCdPerSquareMeter: number): number;\n}\n\n/** Prepares the ITU-R BT.1886 reference EOTF (γ = 2.4) for a display's white and black luminance. */\nexport function prepareBt1886Eotf(input: { whiteLuminanceCdPerSquareMeter: number; blackLuminanceCdPerSquareMeter: number }): Bt1886Eotf {\n requireInputKeys(input, \"prepareBt1886Eotf\", [\"whiteLuminanceCdPerSquareMeter\", \"blackLuminanceCdPerSquareMeter\"]);\n const lw = requirePositiveNumber(input.whiteLuminanceCdPerSquareMeter, \"whiteLuminanceCdPerSquareMeter\");\n const lb = requireNonNegativeNumber(input.blackLuminanceCdPerSquareMeter, \"blackLuminanceCdPerSquareMeter\");\n if (!(lb < lw)) throw new InvalidScientificInputError(\"blackLuminanceCdPerSquareMeter must be below the white luminance.\");\n const g = 2.4, root = lw ** (1 / g) - lb ** (1 / g);\n const a = root ** g, b = lb ** (1 / g) / root;\n return Object.freeze({\n whiteLuminanceCdPerSquareMeter: lw, blackLuminanceCdPerSquareMeter: lb, a, b,\n decode: (signal: number) => a * Math.max(requireFiniteNumber(signal, \"signal\") + b, 0) ** g,\n encode: (luminance: number) => (requireNonNegativeNumber(luminance, \"luminanceCdPerSquareMeter\") / a) ** (1 / g) - b\n });\n}\n"]}
1
+ {"version":3,"file":"rgb-color-spaces.js","sourceRoot":"","sources":["../../src/color/rgb-color-spaces.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,gBAAgB,EAA0B,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EACL,UAAU,EACV,eAAe,EACf,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EAIlB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAgB3E,iHAAiH;AACjH,MAAM,UAAU,gBAAgB,CAAC,SAAmC,EAAE,KAAwB;IAC5F,MAAM,CAAC,GAAG,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACrD,mBAAmB,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAI,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7H,MAAM,KAAK,GAAmB;QAC5B,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;QAC7C,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;QAC7C,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;KAC9C,CAAC;IACF,MAAM,QAAQ,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAClF,MAAM,CAAC,GAAG,oBAAoB,CAAC,eAAe,CAAC,KAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/G,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,2BAA2B,CAAC,gEAAgE,CAAC,CAAC;IACrI,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,CAA8B,CAAC;IAC/F,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;AACjF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAAoF;IAC5H,gBAAgB,CAAC,KAAK,EAAE,2BAA2B,EAAE,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC,CAAC;IACzF,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACzE,mBAAmB,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,uBAAuB,CAAC,CAAC;IACnG,OAAO,gBAAgB,CAAC,KAAK,EAAE,4BAA4B,EAAE,yBAAyB,CAAC,CAAC;AAC1F,CAAC;AAcD,MAAM,gBAAgB,GAAsB,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AACpG,MAAM,eAAe,GAA6B,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;AACzI,MAAM,MAAM,GAAoJ;IAC9J,IAAI,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,mCAAmC,EAAE,gBAAgB,CAAC,EAAE;IAChI,MAAM,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,OAAO,EAAE,CAAC,gBAAgB,EAAE,eAAe,CAAC,EAAE;IAChI,YAAY,EAAE;QACZ,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE;QACvG,gBAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,4EAA4E,EAAE,gCAAgC,CAAC;KACpJ;IACD,OAAO,EAAE;QACP,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE;QACvG,gBAAgB,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,iBAAiB,CAAC;KAC9D;CACF,CAAC;AAEF,qFAAqF;AACrF,MAAM,UAAU,oBAAoB,CAAC,EAAmB;IACtD,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3F,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,yBAAyB,CAAC,2BAA2B,CAAC,CAAC;IAC1F,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACrE,MAAM,KAAK,GAA4B;QACrC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAA6B,EAAE,iBAAiB,EAAE,EAAE,GAAG,gBAAgB,EAAE;QAClI,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;QACrE,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ;KAC9G,CAAC;IACF,OAAO,gBAAgB,CAAC,KAAK,EAAE,kBAAkB,GAAG,EAAE,EAAE,yBAAyB,EAAE,CAAC,oGAAoG,CAAC,CAAC,CAAC;AAC7L,CAAC;AAED,6EAA6E;AAE7E,wIAAwI;AACxI,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,OAAO,mBAAmB,CAAC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,OAAO,mBAAmB,CAAC,mBAAmB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;AACtE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAmB;IACnD,MAAM,CAAC,GAAG,mBAAmB,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,CAAC;AACzD,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,wBAAwB,CAAC,OAAe;IACtD,MAAM,CAAC,GAAG,mBAAmB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AACzE,CAAC;AAeD,qGAAqG;AACrG,MAAM,UAAU,iBAAiB,CAAC,KAAyF;IACzH,gBAAgB,CAAC,KAAK,EAAE,mBAAmB,EAAE,CAAC,gCAAgC,EAAE,gCAAgC,CAAC,CAAC,CAAC;IACnH,MAAM,EAAE,GAAG,qBAAqB,CAAC,KAAK,CAAC,8BAA8B,EAAE,gCAAgC,CAAC,CAAC;IACzG,MAAM,EAAE,GAAG,wBAAwB,CAAC,KAAK,CAAC,8BAA8B,EAAE,gCAAgC,CAAC,CAAC;IAC5G,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;QAAE,MAAM,IAAI,2BAA2B,CAAC,mEAAmE,CAAC,CAAC;IAC3H,MAAM,CAAC,GAAG,GAAG,EAAE,IAAI,GAAG,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;IAC9C,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,8BAA8B,EAAE,EAAE,EAAE,8BAA8B,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;QAC5E,MAAM,EAAE,CAAC,MAAc,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC;QAC3F,MAAM,EAAE,CAAC,SAAiB,EAAE,EAAE,CAAC,CAAC,wBAAwB,CAAC,SAAS,EAAE,2BAA2B,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;KACrH,CAAC,CAAC;AACL,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Wide-gamut output primitives (standalone; output wiring belongs to the SDR/export stages):\n * - RGB ↔ XYZ matrices derived numerically from primary and white chromaticities: RGB (1, 1, 1)\n * is the white (W3C CSS Color 4 §2, free), never copied matrices. They equal the CSS Color 4\n * sample-code matrices to about 1e-15 (test/colorimetry-output-and-camera.test.ts).\n * sRGB / BT.709: ITU-R BT.709-6 and W3C CSS Color 4 `srgb` (also IEC 61966-2-1:1999); Display P3:\n * P3 primaries with D65 white as specified for `display-p3` in W3C CSS Color 4 (also SMPTE EG 432-1:2010);\n * BT.2020: ITU-R BT.2020-2. All use D65 (0.3127, 0.3290).\n * - Transfer functions: sRGB (W3C CSS Color 4; also IEC 61966-2-1; also Display P3), BT.709 OETF, BT.1886 EOTF\n * (ITU-R BT.1886). The BT.2100 PQ and HLG transfer functions are not part of 2.0 (owner decision,\n * 2026-10-17: their patent holders offer only licence-on-request declarations; see THIRD_PARTY.md).\n * Constants are the published values of those standards.\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 { decodeSrgbComponent, encodeSrgbComponent } from \"./srgb-transfer.js\";\nimport { COLORIMETRY_MODEL_VERSION } from \"./color-matching-functions.js\";\nimport {\n copyMatrix,\n invertMatrix3x3,\n multiplyMatrixVector,\n parseChromaticity,\n requireFiniteNumber,\n requireFiniteResult,\n requireNonNegativeNumber,\n requirePositiveNumber,\n requireRecordValue,\n xyzOfChromaticity,\n type CieXyChromaticity,\n type CieXyzTristimulus,\n type ColorMatrix3x3\n} from \"./colorimetry-math.js\";\nimport { rejectUnknownFields, requireInputKeys } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\n/** RGB primaries as CIE 1931 xy chromaticities. */\nexport interface RgbPrimaryChromaticities {\n red: CieXyChromaticity;\n green: CieXyChromaticity;\n blue: CieXyChromaticity;\n}\n\nexport interface RgbToXyzMatrices {\n /** Linear RGB (white = 1, 1, 1) → XYZ with white Y = 1. */\n rgbToXyz: ColorMatrix3x3;\n xyzToRgb: ColorMatrix3x3;\n whiteXyz: CieXyzTristimulus;\n}\n\n/** Internal: derivation from primaries and white (see {@link calculateRgbToXyzMatrices}) without an envelope. */\nexport function rgbToXyzMatrices(primaries: RgbPrimaryChromaticities, white: CieXyChromaticity): RgbToXyzMatrices {\n const p = requireRecordValue(primaries, \"primaries\");\n rejectUnknownFields(p, [\"red\", \"green\", \"blue\"], \"primaries\");\n const columns = ([\"red\", \"green\", \"blue\"] as const).map((k) => xyzOfChromaticity(parseChromaticity(p[k], \"primaries.\" + k)));\n const basis: ColorMatrix3x3 = [\n [columns[0]!.x, columns[1]!.x, columns[2]!.x],\n [columns[0]!.y, columns[1]!.y, columns[2]!.y],\n [columns[0]!.z, columns[1]!.z, columns[2]!.z]\n ];\n const whiteXyz = xyzOfChromaticity(parseChromaticity(white, \"whiteChromaticity\"));\n const s = multiplyMatrixVector(invertMatrix3x3(basis, \"primary matrix\"), [whiteXyz.x, whiteXyz.y, whiteXyz.z]);\n if (s.some((v) => !(v > 0))) throw new InvalidScientificInputError(\"The white point must lie strictly inside the primary triangle.\");\n const rgbToXyz = basis.map((row) => row.map((v, i) => v * s[i]!)) as unknown as ColorMatrix3x3;\n return { rgbToXyz, xyzToRgb: invertMatrix3x3(rgbToXyz, \"rgbToXyz\"), whiteXyz };\n}\n\n/**\n * Derives RGB ↔ XYZ matrices from primaries and white chromaticity: columns are the primaries'\n * XYZ (Y = 1) scaled so that RGB (1, 1, 1) maps to the white (W3C CSS Color 4, free; also SMPTE\n * RP 177). The derivation is written out in docs/COLORIMETRY.md.\n */\nexport function calculateRgbToXyzMatrices(input: { primaries: RgbPrimaryChromaticities; whiteChromaticity: CieXyChromaticity }): CalculationResult<RgbToXyzMatrices> {\n requireInputKeys(input, \"calculateRgbToXyzMatrices\", [\"primaries\", \"whiteChromaticity\"]);\n const value = rgbToXyzMatrices(input.primaries, input.whiteChromaticity);\n requireFiniteResult([...value.rgbToXyz.flat(), ...value.xyzToRgb.flat()], \"RGB matrix derivation\");\n return calculatedResult(value, \"rgb-xyz-matrix-smpte-rp177\", COLORIMETRY_MODEL_VERSION);\n}\n\nexport type RgbColorSpaceId = \"srgb\" | \"display-p3\" | \"rec709\" | \"rec2020\";\nexport type RgbTransferFunctionId = \"srgb\" | \"bt709-oetf-bt1886-eotf\" | \"bt2020-oetf\";\n\nexport interface RgbColorSpaceDefinition extends RgbToXyzMatrices {\n id: RgbColorSpaceId;\n primaries: RgbPrimaryChromaticities;\n whiteChromaticity: CieXyChromaticity;\n /** Conventional non-linear (SDR) encoding of this space. */\n transferFunction: RgbTransferFunctionId;\n sources: readonly string[];\n}\n\nconst D65_CHROMATICITY: CieXyChromaticity = /* @__PURE__ */ Object.freeze({ x: 0.3127, y: 0.3290 });\nconst BT709_PRIMARIES: RgbPrimaryChromaticities = { red: { x: 0.64, y: 0.33 }, green: { x: 0.30, y: 0.60 }, blue: { x: 0.15, y: 0.06 } };\nconst SPACES: Readonly<Record<RgbColorSpaceId, { primaries: RgbPrimaryChromaticities; transferFunction: RgbTransferFunctionId; sources: readonly string[] }>> = {\n srgb: { primaries: BT709_PRIMARIES, transferFunction: \"srgb\", sources: [\"W3C CSS Color Module Level 4 srgb\", \"ITU-R BT.709-6\"] },\n rec709: { primaries: BT709_PRIMARIES, transferFunction: \"bt709-oetf-bt1886-eotf\", sources: [\"ITU-R BT.709-6\", \"ITU-R BT.1886\"] },\n \"display-p3\": {\n primaries: { red: { x: 0.680, y: 0.320 }, green: { x: 0.265, y: 0.690 }, blue: { x: 0.150, y: 0.060 } },\n transferFunction: \"srgb\", sources: [\"W3C CSS Color Module Level 4 display-p3 (P3 primaries, D65, sRGB transfer)\", \"ITU-T H.273 ColourPrimaries 12\"]\n },\n rec2020: {\n primaries: { red: { x: 0.708, y: 0.292 }, green: { x: 0.170, y: 0.797 }, blue: { x: 0.131, y: 0.046 } },\n transferFunction: \"bt2020-oetf\", sources: [\"ITU-R BT.2020-2\"]\n }\n};\n\n/** Resolves a named RGB colour space with numerically derived matrices (all D65). */\nexport function resolveRgbColorSpace(id: RgbColorSpaceId): CalculationResult<RgbColorSpaceDefinition> {\n const space = typeof id === \"string\" && Object.hasOwn(SPACES, id) ? SPACES[id] : undefined;\n if (space === undefined) throw new InvalidConfigurationError(\"Unknown RGB colour space.\");\n const matrices = rgbToXyzMatrices(space.primaries, D65_CHROMATICITY);\n const value: RgbColorSpaceDefinition = {\n id, primaries: JSON.parse(JSON.stringify(space.primaries)) as RgbPrimaryChromaticities, whiteChromaticity: { ...D65_CHROMATICITY },\n transferFunction: space.transferFunction, sources: [...space.sources],\n rgbToXyz: copyMatrix(matrices.rgbToXyz), xyzToRgb: copyMatrix(matrices.xyzToRgb), whiteXyz: matrices.whiteXyz\n };\n return calculatedResult(value, \"rgb-color-space-\" + id, COLORIMETRY_MODEL_VERSION, [\"Matrices derived from primaries and D65 white so that RGB (1, 1, 1) is the white (W3C CSS Color 4)\"]);\n}\n\n// ---------------------------------------------------------------- transfers\n\n/** sRGB / Display P3 encoding (W3C CSS Color 4; also IEC 61966-2-1) of one linear component; negative values use the linear segment. */\nexport function evaluateSrgbEncoding(linear: number): number {\n return encodeSrgbComponent(requireFiniteNumber(linear, \"linear\"));\n}\n\n/** sRGB / Display P3 decoding of one non-linear component. */\nexport function evaluateSrgbDecoding(encoded: number): number {\n return decodeSrgbComponent(requireFiniteNumber(encoded, \"encoded\"));\n}\n\n/**\n * ITU-R BT.709-6 / BT.2020-2 (10-bit) OETF: V = 4.5 L for L < 0.018, otherwise\n * 1.099 L^0.45 − 0.099. Scene-referred camera encoding, not a display EOTF.\n */\nexport function evaluateBt709Oetf(sceneLinear: number): number {\n const l = requireFiniteNumber(sceneLinear, \"sceneLinear\");\n return l < 0.018 ? 4.5 * l : 1.099 * l ** 0.45 - 0.099;\n}\n\n/** Inverse of the BT.709 OETF: L = V/4.5 for V < 0.081, otherwise ((V + 0.099)/1.099)^(1/0.45). */\nexport function evaluateBt709InverseOetf(encoded: number): number {\n const v = requireFiniteNumber(encoded, \"encoded\");\n return v < 4.5 * 0.018 ? v / 4.5 : ((v + 0.099) / 1.099) ** (1 / 0.45);\n}\n\nexport interface Bt1886Eotf {\n whiteLuminanceCdPerSquareMeter: number;\n blackLuminanceCdPerSquareMeter: number;\n /** a = (Lw^(1/γ) − Lb^(1/γ))^γ */\n a: number;\n /** b = Lb^(1/γ) / (Lw^(1/γ) − Lb^(1/γ)) */\n b: number;\n /** L = a · max(V + b, 0)^2.4 in cd/m². */\n decode(signal: number): number;\n /** Inverse: V = (L/a)^(1/2.4) − b. */\n encode(luminanceCdPerSquareMeter: number): number;\n}\n\n/** Prepares the ITU-R BT.1886 reference EOTF (γ = 2.4) for a display's white and black luminance. */\nexport function prepareBt1886Eotf(input: { whiteLuminanceCdPerSquareMeter: number; blackLuminanceCdPerSquareMeter: number }): Bt1886Eotf {\n requireInputKeys(input, \"prepareBt1886Eotf\", [\"whiteLuminanceCdPerSquareMeter\", \"blackLuminanceCdPerSquareMeter\"]);\n const lw = requirePositiveNumber(input.whiteLuminanceCdPerSquareMeter, \"whiteLuminanceCdPerSquareMeter\");\n const lb = requireNonNegativeNumber(input.blackLuminanceCdPerSquareMeter, \"blackLuminanceCdPerSquareMeter\");\n if (!(lb < lw)) throw new InvalidScientificInputError(\"blackLuminanceCdPerSquareMeter must be below the white luminance.\");\n const g = 2.4, root = lw ** (1 / g) - lb ** (1 / g);\n const a = root ** g, b = lb ** (1 / g) / root;\n return Object.freeze({\n whiteLuminanceCdPerSquareMeter: lw, blackLuminanceCdPerSquareMeter: lb, a, b,\n decode: (signal: number) => a * Math.max(requireFiniteNumber(signal, \"signal\") + b, 0) ** g,\n encode: (luminance: number) => (requireNonNegativeNumber(luminance, \"luminanceCdPerSquareMeter\") / a) ** (1 / g) - b\n });\n}\n"]}
@@ -40,7 +40,7 @@
40
40
  */
41
41
  import { InvalidConfigurationError } from "../core/configuration-error.js";
42
42
  import { resolveCaptureColorModel } from "./capture-color.js";
43
- export const SENSOR_COLOR_DEVELOPMENT_MODEL = Object.freeze({ id: "sensor-color-development", version: "2.0.0" });
43
+ export const SENSOR_COLOR_DEVELOPMENT_MODEL = /* @__PURE__ */ Object.freeze({ id: "sensor-color-development", version: "2.0.0" });
44
44
  /** Normalized channel level where `reconstruct` starts blending toward neutral. */
45
45
  export const RAW_HIGHLIGHT_RECONSTRUCTION_START = 0.8;
46
46
  /** Profiles whose camera neutral is within this relative distance of [1,1,1] are white-normalized. */
@@ -1 +1 @@
1
- {"version":3,"file":"sensor-color-development.js","sourceRoot":"","sources":["../../src/color/sensor-color-development.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * RAW colour development: turns normalized sensor RGB into linear sRGB, using a declared D65 camera\n * profile. Internal.\n *\n * The caller is responsible for the profile's evidence, for binding it to the CFA (colour filter\n * array) and colour basis, and for applying white balance (WB) only once. Only validated 3×3 matrices\n * are accepted, and their declared determinant and inverse bounds are kept.\n *\n * Development model (`sensor-color-development` 2.0.0). The input c is the normalized camera\n * channels: black level subtracted, divided by the effective white level and clipped at 1 per site,\n * all earlier in the pipeline.\n *\n * b = highlight(diag(g)·c), linear sRGB = X · M · diag(w) · b\n *\n * Where:\n * - M is the profile's camera→XYZ matrix and X is the XYZ→linear-sRGB matrix.\n * - w = M⁻¹·XYZ(D65), normalized to green. These are the camera-neutral coordinates of D65\n * (DNG 1.7 \"camera neutral\").\n * - The WB gains g map the scene white to equal channel values. diag(w) then maps equal channel values\n * to D65, for any invertible M. So a grey card lit by the gains' illuminant comes out neutral,\n * whether or not M is white-normalized.\n * - Without a resolved WB intent, g = 1/w, and development reduces to X·M·c (a D65 scene white).\n * - The camera neutral of the scene white, written to DNG `AsShotNeutral`, is g_green/g.\n * This module does not chromatically adapt the scene, infer calibration, change geometry or write\n * container metadata.\n *\n * Highlight handling (after each site is clipped at the sensor white level):\n * - `clip` (default): every WB-scaled channel is clipped at the smallest gain. That is the level at\n * which the least-amplified channel saturates, so fully clipped pixels stay neutral. This is the\n * documented default of dcraw (`-H 0`, \"clip all highlights to solid white\") and of most raw\n * converters.\n * - `reconstruct`: a desaturation blend defined by this engine. Let s be the largest normalized\n * channel. The weight t = clamp((s − 0.8)/0.2, 0, 1) blends the unclipped WB result u toward the\n * neutral n = max_k min(u_k, g_min): b = (1 − t)·u + t·n. Below 0.8 of white, colour is unchanged\n * and unclipped; at white it is neutral. This approximation follows the idea of highlight\n * desaturation (Guo, Cheng & Hu, \"Correcting over-exposure in photographs\", CVPR 2010). It does not\n * recover the clipped scene signal.\n * @see docs/PHOTOGRAPHIC_EXPORT.md and docs/NATIVE_RAW_AND_PRINT.md for equations and limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { resolveCaptureColorModel } from \"./capture-color.js\";\n\ntype Matrix = readonly (readonly number[])[];\nexport const SENSOR_COLOR_DEVELOPMENT_MODEL = Object.freeze({ id: \"sensor-color-development\", version: \"2.0.0\" } as const);\n/** RAW development highlight policy; see the module notes. */\nexport type RawHighlightMode = \"clip\" | \"reconstruct\";\n/** Normalized channel level where `reconstruct` starts blending toward neutral. */\nexport const RAW_HIGHLIGHT_RECONSTRUCTION_START = 0.8;\n/** Profiles whose camera neutral is within this relative distance of [1,1,1] are white-normalized. */\nconst WHITE_NORMALIZED_TOLERANCE = 1e-12;\n\n/** Multiply in declared row order: ((0 + m0·v0) + m1·v1) + m2·v2. */\nfunction multiply(m: Matrix, values: readonly number[]): number[] {\n return m.map((row) => row.reduce((sum, v, i) => sum+v*values[i]!, 0));\n}\n/** Accepts validated 3×3 matrices only, and keeps their declared determinant and inverse bounds. */\nexport function invertSensorColorMatrix(m: Matrix): number[][] {\n const [a,b,c,d,e,f,g,h,i]=m.flat() as number[], det=a!*(e!*i!-f!*h!)-b!*(d!*i!-f!*g!)+c!*(d!*h!-e!*g!);\n if (!Number.isFinite(det) || Math.abs(det)<1e-9) throw new InvalidConfigurationError(\"Export color matrix is singular or outside supported conditioning.\");\n const result=[[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!]].map((r) => r.map((v) => v/det));\n if (result.flat().some((v) => !Number.isFinite(v) || Math.abs(v)>100)) throw new InvalidConfigurationError(\"Export inverse color matrix exceeds supported range.\");\n return result;\n}\n\n/** Camera coordinates of the declared D65 white (not normalized). The caller decides container policy. */\nexport function sensorColorReferenceWhite(xyzToCamera: Matrix): number[] {\n const white = resolveCaptureColorModel().referenceWhiteXyz;\n return multiply(xyzToCamera, [white.x, 1, white.z]);\n}\n\n/** Per-pixel highlight/WB counters accumulated by {@link SensorColorDevelopment.developInto}. */\nexport interface SensorColorDevelopmentCounts { whiteBalanceClippedSampleCount: number; reconstructedPixelCount: number }\n\nexport interface SensorColorDevelopment {\n referenceWhiteXyz: { x: number; y: 1; z: number };\n /** Green-normalized camera-neutral coordinates of D65 (exactly [1,1,1] for white-normalized profiles). */\n cameraNeutralD65: readonly number[];\n /** Applied channel gains: the resolved WB gains, or 1/cameraNeutralD65 when WB is not required. */\n appliedGains: readonly number[];\n /** Green-normalized camera neutral of the assumed scene white: g_green/g (DNG AsShotNeutral). */\n asShotNeutral: readonly number[];\n /** X·M·diag(w) rows, applied as two products in the documented order. */\n cameraToXyz: readonly (readonly number[])[];\n highlightMode: RawHighlightMode;\n /** Develops one normalized camera pixel into out[offset..offset+2] (linear sRGB/D65); updates counts. */\n developInto(c0: number, c1: number, c2: number, out: Float64Array | number[], offset: number, counts: SensorColorDevelopmentCounts): void;\n /** Convenience array form of developInto (counts discarded). */\n develop(values: readonly number[]): number[];\n}\n\n/**\n * Internal development of validated, normalized sensor RGB with a declared D65 profile.\n * `gains` is the resolved WB intent, or null when WB is not required. Both the packed native path and\n * the bounded reference path use the returned operator, so there is one implementation.\n */\nexport function prepareSensorColorDevelopment(cameraChannelsToXyz: Matrix, gains: readonly number[] | null,\n highlightMode: RawHighlightMode = \"clip\"): SensorColorDevelopment {\n if (highlightMode !== \"clip\" && highlightMode !== \"reconstruct\") throw new InvalidConfigurationError(\"Unsupported RAW highlight mode.\");\n const model = resolveCaptureColorModel();\n const raw = sensorColorReferenceWhite(invertSensorColorMatrix(cameraChannelsToXyz));\n if (raw.some((x) => !(x > 0) || !Number.isFinite(x))) throw new InvalidConfigurationError(\"Reference white requires positive camera coordinates.\");\n let neutral = raw.map((x) => x/raw[1]!);\n if (neutral.every((x) => Math.abs(x-1) <= WHITE_NORMALIZED_TOLERANCE)) neutral = [1, 1, 1];\n if (gains && (gains.length !== 3 || gains.some((x) => !(x > 0) || !Number.isFinite(x)))) throw new InvalidConfigurationError(\"White-balance gains must be positive and finite.\");\n const applied = gains ? [...gains] : neutral.map((x) => 1/x);\n const asShot = applied.map((x) => applied[1]!/x), clipLevel = Math.min(...applied);\n const m = cameraChannelsToXyz.map((row) => row.map((v, i) => v*neutral[i]!)), x = model.xyzToCameraRgb;\n const m0 = m[0]!, m1 = m[1]!, m2 = m[2]!, x0 = x[0]!, x1 = x[1]!, x2 = x[2]!;\n const g0 = applied[0]!, g1 = applied[1]!, g2 = applied[2]!, reconstruct = highlightMode === \"reconstruct\";\n const start = RAW_HIGHLIGHT_RECONSTRUCTION_START;\n function developInto(c0: number, c1: number, c2: number, out: Float64Array | number[], offset: number, counts: SensorColorDevelopmentCounts): void {\n const u0 = c0*g0, u1 = c1*g1, u2 = c2*g2;\n let b0: number, b1: number, b2: number;\n const k0 = u0 > clipLevel ? clipLevel : u0, k1 = u1 > clipLevel ? clipLevel : u1, k2 = u2 > clipLevel ? clipLevel : u2;\n if (!reconstruct) {\n b0 = k0; b1 = k1; b2 = k2;\n counts.whiteBalanceClippedSampleCount += Number(u0 > clipLevel)+Number(u1 > clipLevel)+Number(u2 > clipLevel);\n } else {\n const s = c0 > c1 ? (c0 > c2 ? c0 : c2) : (c1 > c2 ? c1 : c2);\n if (s > start) {\n const t = s >= 1 ? 1 : (s-start)/(1-start), n = k0 > k1 ? (k0 > k2 ? k0 : k2) : (k1 > k2 ? k1 : k2);\n b0 = (1-t)*u0+t*n; b1 = (1-t)*u1+t*n; b2 = (1-t)*u2+t*n; counts.reconstructedPixelCount++;\n } else { b0 = u0; b1 = u1; b2 = u2; }\n }\n const X = ((0+m0[0]!*b0)+m0[1]!*b1)+m0[2]!*b2, Y = ((0+m1[0]!*b0)+m1[1]!*b1)+m1[2]!*b2, Z = ((0+m2[0]!*b0)+m2[1]!*b1)+m2[2]!*b2;\n out[offset] = ((0+x0[0]!*X)+x0[1]!*Y)+x0[2]!*Z;\n out[offset+1] = ((0+x1[0]!*X)+x1[1]!*Y)+x1[2]!*Z;\n out[offset+2] = ((0+x2[0]!*X)+x2[1]!*Y)+x2[2]!*Z;\n }\n return {\n referenceWhiteXyz: model.referenceWhiteXyz, cameraNeutralD65: Object.freeze(neutral), appliedGains: Object.freeze(applied),\n asShotNeutral: Object.freeze(asShot), cameraToXyz: m, highlightMode, developInto,\n develop(values: readonly number[]): number[] {\n const out = [0, 0, 0]; developInto(values[0]!, values[1]!, values[2]!, out, 0, { whiteBalanceClippedSampleCount: 0, reconstructedPixelCount: 0 }); return out;\n }\n };\n}\n"]}
1
+ {"version":3,"file":"sensor-color-development.js","sourceRoot":"","sources":["../../src/color/sensor-color-development.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAG9D,MAAM,CAAC,MAAM,8BAA8B,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,0BAA0B,EAAE,OAAO,EAAE,OAAO,EAAW,CAAC,CAAC;AAG3I,mFAAmF;AACnF,MAAM,CAAC,MAAM,kCAAkC,GAAG,GAAG,CAAC;AACtD,sGAAsG;AACtG,MAAM,0BAA0B,GAAG,KAAK,CAAC;AAEzC,qEAAqE;AACrE,SAAS,QAAQ,CAAC,CAAS,EAAE,MAAyB;IACpD,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAC,CAAC,GAAC,MAAM,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC;AACD,oGAAoG;AACpG,MAAM,UAAU,uBAAuB,CAAC,CAAS;IAC/C,MAAM,CAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,CAAC,CAAC,GAAC,CAAC,CAAC,IAAI,EAAc,EAAE,GAAG,GAAC,CAAE,GAAC,CAAC,CAAE,GAAC,CAAE,GAAC,CAAE,GAAC,CAAE,CAAC,GAAC,CAAE,GAAC,CAAC,CAAE,GAAC,CAAE,GAAC,CAAE,GAAC,CAAE,CAAC,GAAC,CAAE,GAAC,CAAC,CAAE,GAAC,CAAE,GAAC,CAAE,GAAC,CAAE,CAAC,CAAC;IACvG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAC,IAAI;QAAE,MAAM,IAAI,yBAAyB,CAAC,oEAAoE,CAAC,CAAC;IAC3J,MAAM,MAAM,GAAC,CAAC,CAAC,CAAE,GAAC,CAAE,GAAC,CAAE,GAAC,CAAE,EAAC,CAAE,GAAC,CAAE,GAAC,CAAE,GAAC,CAAE,EAAC,CAAE,GAAC,CAAE,GAAC,CAAE,GAAC,CAAE,CAAC,EAAC,CAAC,CAAE,GAAC,CAAE,GAAC,CAAE,GAAC,CAAE,EAAC,CAAE,GAAC,CAAE,GAAC,CAAE,GAAC,CAAE,EAAC,CAAE,GAAC,CAAE,GAAC,CAAE,GAAC,CAAE,CAAC,EAAC,CAAC,CAAE,GAAC,CAAE,GAAC,CAAE,GAAC,CAAE,EAAC,CAAE,GAAC,CAAE,GAAC,CAAE,GAAC,CAAE,EAAC,CAAE,GAAC,CAAE,GAAC,CAAE,GAAC,CAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAC,GAAG,CAAC,CAAC,CAAC;IACjK,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAC,GAAG,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,sDAAsD,CAAC,CAAC;IACnK,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,yBAAyB,CAAC,WAAmB;IAC3D,MAAM,KAAK,GAAG,wBAAwB,EAAE,CAAC,iBAAiB,CAAC;IAC3D,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC;AAsBD;;;;GAIG;AACH,MAAM,UAAU,6BAA6B,CAAC,mBAA2B,EAAE,KAA+B,EACxG,gBAAkC,MAAM;IACxC,IAAI,aAAa,KAAK,MAAM,IAAI,aAAa,KAAK,aAAa;QAAE,MAAM,IAAI,yBAAyB,CAAC,iCAAiC,CAAC,CAAC;IACxI,MAAM,KAAK,GAAG,wBAAwB,EAAE,CAAC;IACzC,MAAM,GAAG,GAAG,yBAAyB,CAAC,uBAAuB,CAAC,mBAAmB,CAAC,CAAC,CAAC;IACpF,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,uDAAuD,CAAC,CAAC;IACnJ,IAAI,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CAAC;IACxC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAC,CAAC,CAAC,IAAI,0BAA0B,CAAC;QAAE,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3F,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,kDAAkD,CAAC,CAAC;IACjL,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAE,GAAC,CAAC,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;IACnF,MAAM,CAAC,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,cAAc,CAAC;IACvG,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;IAC7E,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAE,EAAE,EAAE,GAAG,OAAO,CAAC,CAAC,CAAE,EAAE,EAAE,GAAG,OAAO,CAAC,CAAC,CAAE,EAAE,WAAW,GAAG,aAAa,KAAK,aAAa,CAAC;IAC1G,MAAM,KAAK,GAAG,kCAAkC,CAAC;IACjD,SAAS,WAAW,CAAC,EAAU,EAAE,EAAU,EAAE,EAAU,EAAE,GAA4B,EAAE,MAAc,EAAE,MAAoC;QACzI,MAAM,EAAE,GAAG,EAAE,GAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAC,EAAE,CAAC;QACzC,IAAI,EAAU,EAAE,EAAU,EAAE,EAAU,CAAC;QACvC,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QACvH,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,EAAE,GAAG,EAAE,CAAC;YAAC,EAAE,GAAG,EAAE,CAAC;YAAC,EAAE,GAAG,EAAE,CAAC;YAC1B,MAAM,CAAC,8BAA8B,IAAI,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,GAAC,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,GAAC,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC;QAChH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC9D,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC;gBACd,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAC,KAAK,CAAC,GAAC,CAAC,CAAC,GAAC,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACpG,EAAE,GAAG,CAAC,CAAC,GAAC,CAAC,CAAC,GAAC,EAAE,GAAC,CAAC,GAAC,CAAC,CAAC;gBAAC,EAAE,GAAG,CAAC,CAAC,GAAC,CAAC,CAAC,GAAC,EAAE,GAAC,CAAC,GAAC,CAAC,CAAC;gBAAC,EAAE,GAAG,CAAC,CAAC,GAAC,CAAC,CAAC,GAAC,EAAE,GAAC,CAAC,GAAC,CAAC,CAAC;gBAAC,MAAM,CAAC,uBAAuB,EAAE,CAAC;YAC5F,CAAC;iBAAM,CAAC;gBAAC,EAAE,GAAG,EAAE,CAAC;gBAAC,EAAE,GAAG,EAAE,CAAC;gBAAC,EAAE,GAAG,EAAE,CAAC;YAAC,CAAC;QACvC,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,EAAE,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,EAAE,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,EAAE,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,EAAE,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,EAAE,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,EAAE,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,EAAE,CAAC;QAChI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,CAAC,CAAC;QAC/C,GAAG,CAAC,MAAM,GAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,CAAC,CAAC;QACjD,GAAG,CAAC,MAAM,GAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,CAAC,CAAC,GAAC,EAAE,CAAC,CAAC,CAAE,GAAC,CAAC,CAAC;IACnD,CAAC;IACD,OAAO;QACL,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;QAC1H,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,WAAW;QAChF,OAAO,CAAC,MAAyB;YAC/B,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAE,EAAE,MAAM,CAAC,CAAC,CAAE,EAAE,MAAM,CAAC,CAAC,CAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,8BAA8B,EAAE,CAAC,EAAE,uBAAuB,EAAE,CAAC,EAAE,CAAC,CAAC;YAAC,OAAO,GAAG,CAAC;QAChK,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * RAW colour development: turns normalized sensor RGB into linear sRGB, using a declared D65 camera\n * profile. Internal.\n *\n * The caller is responsible for the profile's evidence, for binding it to the CFA (colour filter\n * array) and colour basis, and for applying white balance (WB) only once. Only validated 3×3 matrices\n * are accepted, and their declared determinant and inverse bounds are kept.\n *\n * Development model (`sensor-color-development` 2.0.0). The input c is the normalized camera\n * channels: black level subtracted, divided by the effective white level and clipped at 1 per site,\n * all earlier in the pipeline.\n *\n * b = highlight(diag(g)·c), linear sRGB = X · M · diag(w) · b\n *\n * Where:\n * - M is the profile's camera→XYZ matrix and X is the XYZ→linear-sRGB matrix.\n * - w = M⁻¹·XYZ(D65), normalized to green. These are the camera-neutral coordinates of D65\n * (DNG 1.7 \"camera neutral\").\n * - The WB gains g map the scene white to equal channel values. diag(w) then maps equal channel values\n * to D65, for any invertible M. So a grey card lit by the gains' illuminant comes out neutral,\n * whether or not M is white-normalized.\n * - Without a resolved WB intent, g = 1/w, and development reduces to X·M·c (a D65 scene white).\n * - The camera neutral of the scene white, written to DNG `AsShotNeutral`, is g_green/g.\n * This module does not chromatically adapt the scene, infer calibration, change geometry or write\n * container metadata.\n *\n * Highlight handling (after each site is clipped at the sensor white level):\n * - `clip` (default): every WB-scaled channel is clipped at the smallest gain. That is the level at\n * which the least-amplified channel saturates, so fully clipped pixels stay neutral. This is the\n * documented default of dcraw (`-H 0`, \"clip all highlights to solid white\") and of most raw\n * converters.\n * - `reconstruct`: a desaturation blend defined by this engine. Let s be the largest normalized\n * channel. The weight t = clamp((s − 0.8)/0.2, 0, 1) blends the unclipped WB result u toward the\n * neutral n = max_k min(u_k, g_min): b = (1 − t)·u + t·n. Below 0.8 of white, colour is unchanged\n * and unclipped; at white it is neutral. This approximation follows the idea of highlight\n * desaturation (Guo, Cheng & Hu, \"Correcting over-exposure in photographs\", CVPR 2010). It does not\n * recover the clipped scene signal.\n * @see docs/PHOTOGRAPHIC_EXPORT.md and docs/NATIVE_RAW_AND_PRINT.md for equations and limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { resolveCaptureColorModel } from \"./capture-color.js\";\n\ntype Matrix = readonly (readonly number[])[];\nexport const SENSOR_COLOR_DEVELOPMENT_MODEL = /* @__PURE__ */ Object.freeze({ id: \"sensor-color-development\", version: \"2.0.0\" } as const);\n/** RAW development highlight policy; see the module notes. */\nexport type RawHighlightMode = \"clip\" | \"reconstruct\";\n/** Normalized channel level where `reconstruct` starts blending toward neutral. */\nexport const RAW_HIGHLIGHT_RECONSTRUCTION_START = 0.8;\n/** Profiles whose camera neutral is within this relative distance of [1,1,1] are white-normalized. */\nconst WHITE_NORMALIZED_TOLERANCE = 1e-12;\n\n/** Multiply in declared row order: ((0 + m0·v0) + m1·v1) + m2·v2. */\nfunction multiply(m: Matrix, values: readonly number[]): number[] {\n return m.map((row) => row.reduce((sum, v, i) => sum+v*values[i]!, 0));\n}\n/** Accepts validated 3×3 matrices only, and keeps their declared determinant and inverse bounds. */\nexport function invertSensorColorMatrix(m: Matrix): number[][] {\n const [a,b,c,d,e,f,g,h,i]=m.flat() as number[], det=a!*(e!*i!-f!*h!)-b!*(d!*i!-f!*g!)+c!*(d!*h!-e!*g!);\n if (!Number.isFinite(det) || Math.abs(det)<1e-9) throw new InvalidConfigurationError(\"Export color matrix is singular or outside supported conditioning.\");\n const result=[[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!]].map((r) => r.map((v) => v/det));\n if (result.flat().some((v) => !Number.isFinite(v) || Math.abs(v)>100)) throw new InvalidConfigurationError(\"Export inverse color matrix exceeds supported range.\");\n return result;\n}\n\n/** Camera coordinates of the declared D65 white (not normalized). The caller decides container policy. */\nexport function sensorColorReferenceWhite(xyzToCamera: Matrix): number[] {\n const white = resolveCaptureColorModel().referenceWhiteXyz;\n return multiply(xyzToCamera, [white.x, 1, white.z]);\n}\n\n/** Per-pixel highlight/WB counters accumulated by {@link SensorColorDevelopment.developInto}. */\nexport interface SensorColorDevelopmentCounts { whiteBalanceClippedSampleCount: number; reconstructedPixelCount: number }\n\nexport interface SensorColorDevelopment {\n referenceWhiteXyz: { x: number; y: 1; z: number };\n /** Green-normalized camera-neutral coordinates of D65 (exactly [1,1,1] for white-normalized profiles). */\n cameraNeutralD65: readonly number[];\n /** Applied channel gains: the resolved WB gains, or 1/cameraNeutralD65 when WB is not required. */\n appliedGains: readonly number[];\n /** Green-normalized camera neutral of the assumed scene white: g_green/g (DNG AsShotNeutral). */\n asShotNeutral: readonly number[];\n /** X·M·diag(w) rows, applied as two products in the documented order. */\n cameraToXyz: readonly (readonly number[])[];\n highlightMode: RawHighlightMode;\n /** Develops one normalized camera pixel into out[offset..offset+2] (linear sRGB/D65); updates counts. */\n developInto(c0: number, c1: number, c2: number, out: Float64Array | number[], offset: number, counts: SensorColorDevelopmentCounts): void;\n /** Convenience array form of developInto (counts discarded). */\n develop(values: readonly number[]): number[];\n}\n\n/**\n * Internal development of validated, normalized sensor RGB with a declared D65 profile.\n * `gains` is the resolved WB intent, or null when WB is not required. Both the packed native path and\n * the bounded reference path use the returned operator, so there is one implementation.\n */\nexport function prepareSensorColorDevelopment(cameraChannelsToXyz: Matrix, gains: readonly number[] | null,\n highlightMode: RawHighlightMode = \"clip\"): SensorColorDevelopment {\n if (highlightMode !== \"clip\" && highlightMode !== \"reconstruct\") throw new InvalidConfigurationError(\"Unsupported RAW highlight mode.\");\n const model = resolveCaptureColorModel();\n const raw = sensorColorReferenceWhite(invertSensorColorMatrix(cameraChannelsToXyz));\n if (raw.some((x) => !(x > 0) || !Number.isFinite(x))) throw new InvalidConfigurationError(\"Reference white requires positive camera coordinates.\");\n let neutral = raw.map((x) => x/raw[1]!);\n if (neutral.every((x) => Math.abs(x-1) <= WHITE_NORMALIZED_TOLERANCE)) neutral = [1, 1, 1];\n if (gains && (gains.length !== 3 || gains.some((x) => !(x > 0) || !Number.isFinite(x)))) throw new InvalidConfigurationError(\"White-balance gains must be positive and finite.\");\n const applied = gains ? [...gains] : neutral.map((x) => 1/x);\n const asShot = applied.map((x) => applied[1]!/x), clipLevel = Math.min(...applied);\n const m = cameraChannelsToXyz.map((row) => row.map((v, i) => v*neutral[i]!)), x = model.xyzToCameraRgb;\n const m0 = m[0]!, m1 = m[1]!, m2 = m[2]!, x0 = x[0]!, x1 = x[1]!, x2 = x[2]!;\n const g0 = applied[0]!, g1 = applied[1]!, g2 = applied[2]!, reconstruct = highlightMode === \"reconstruct\";\n const start = RAW_HIGHLIGHT_RECONSTRUCTION_START;\n function developInto(c0: number, c1: number, c2: number, out: Float64Array | number[], offset: number, counts: SensorColorDevelopmentCounts): void {\n const u0 = c0*g0, u1 = c1*g1, u2 = c2*g2;\n let b0: number, b1: number, b2: number;\n const k0 = u0 > clipLevel ? clipLevel : u0, k1 = u1 > clipLevel ? clipLevel : u1, k2 = u2 > clipLevel ? clipLevel : u2;\n if (!reconstruct) {\n b0 = k0; b1 = k1; b2 = k2;\n counts.whiteBalanceClippedSampleCount += Number(u0 > clipLevel)+Number(u1 > clipLevel)+Number(u2 > clipLevel);\n } else {\n const s = c0 > c1 ? (c0 > c2 ? c0 : c2) : (c1 > c2 ? c1 : c2);\n if (s > start) {\n const t = s >= 1 ? 1 : (s-start)/(1-start), n = k0 > k1 ? (k0 > k2 ? k0 : k2) : (k1 > k2 ? k1 : k2);\n b0 = (1-t)*u0+t*n; b1 = (1-t)*u1+t*n; b2 = (1-t)*u2+t*n; counts.reconstructedPixelCount++;\n } else { b0 = u0; b1 = u1; b2 = u2; }\n }\n const X = ((0+m0[0]!*b0)+m0[1]!*b1)+m0[2]!*b2, Y = ((0+m1[0]!*b0)+m1[1]!*b1)+m1[2]!*b2, Z = ((0+m2[0]!*b0)+m2[1]!*b1)+m2[2]!*b2;\n out[offset] = ((0+x0[0]!*X)+x0[1]!*Y)+x0[2]!*Z;\n out[offset+1] = ((0+x1[0]!*X)+x1[1]!*Y)+x1[2]!*Z;\n out[offset+2] = ((0+x2[0]!*X)+x2[1]!*Y)+x2[2]!*Z;\n }\n return {\n referenceWhiteXyz: model.referenceWhiteXyz, cameraNeutralD65: Object.freeze(neutral), appliedGains: Object.freeze(applied),\n asShotNeutral: Object.freeze(asShot), cameraToXyz: m, highlightMode, developInto,\n develop(values: readonly number[]): number[] {\n const out = [0, 0, 0]; developInto(values[0]!, values[1]!, values[2]!, out, 0, { whiteBalanceClippedSampleCount: 0, reconstructedPixelCount: 0 }); return out;\n }\n };\n}\n"]}
@@ -100,9 +100,9 @@ export function requireFixedFieldsWhenPresent(record, fixed, path) {
100
100
  * Fields of the shared relative / not-quantified uncertainty union used by many evidence-backed
101
101
  * profiles: `{ kind: "relative", fraction, basis }` or `{ kind: "not-quantified", limitation }`.
102
102
  */
103
- export const UNCERTAINTY_VARIANT_FIELDS = Object.freeze({
104
- relative: Object.freeze(["kind", "fraction", "basis"]),
105
- "not-quantified": Object.freeze(["kind", "limitation"])
103
+ export const UNCERTAINTY_VARIANT_FIELDS = /* @__PURE__ */ Object.freeze({
104
+ relative: /* @__PURE__ */ Object.freeze(["kind", "fraction", "basis"]),
105
+ "not-quantified": /* @__PURE__ */ Object.freeze(["kind", "limitation"])
106
106
  });
107
107
  /**
108
108
  * For a record whose allowed fields depend on a discriminator (for example `kind` or
@@ -1 +1 @@
1
- {"version":3,"file":"record-validation.js","sourceRoot":"","sources":["../../src/core/record-validation.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Shared input checks used by the domain parsers: plain-record and allowed-key checks, the\n * public identifier grammar, and guards for the top-level argument of a public function.\n * Each domain keeps its own schema and error messages.\n * @see docs/API_STYLE.md for equations, coordinate/unit conventions, blockers and support limits.\n */\n\nimport { InvalidConfigurationError } from \"./configuration-error.js\";\n\n/**\n * Checks that a value is a plain record whose keys are all on an allowlist. The caller\n * supplies the domain's schema and error messages.\n *\n * Returns the original record. It does not copy, freeze or strip fields, require missing\n * fields, or check child values. Like the domain parsers, it checks own enumerable string keys.\n * From 2.0.0 an unknown key also names the field: `<message> Unknown field \"<field>\".`\n */\nexport function requireAllowlistedRecord(\n value: unknown, allowedKeys: readonly string[], message: string\n): Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n throw new InvalidConfigurationError(message);\n }\n for (const key in value) {\n if (Object.hasOwn(value, key) && !allowedKeys.includes(key)) {\n throw new InvalidConfigurationError(`${message} Unknown field ${JSON.stringify(key)}.`);\n }\n }\n return value as Record<string, unknown>;\n}\n\n/**\n * Shared grammar for public identifiers: 1–128 ASCII characters. The first is a letter or\n * digit. The rest are letters, digits, dot, underscore, colon or hyphen.\n *\n * The identifier is opaque: no trimming, case conversion or path/URL interpretation. Each\n * domain decides what the identifier means and keeps its exact error message.\n */\nexport function requirePublicOpaqueId(value: unknown, message: string): string {\n if (!isPublicOpaqueId(value)) {\n throw new InvalidConfigurationError(message);\n }\n return value;\n}\n\n/** Same grammar for domains that combine ID rejection with other field checks. */\nexport function isPublicOpaqueId(value: unknown): value is string {\n return typeof value === \"string\" && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(value);\n}\n\n/**\n * Guard for a public function's input object. If it receives null, a primitive or an array,\n * it throws the domain's InvalidConfigurationError, never a raw TypeError from reading a\n * property. It does not check fields.\n */\nexport function requireInputObject(value: unknown, label: string): void {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n throw new InvalidConfigurationError(`${label} must be an object.`);\n }\n}\n\n/** Root-function input guard for a required array argument; see requireInputObject. */\nexport function requireInputArray(value: unknown, label: string): void {\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(`${label} must be an array.`);\n }\n}\n\n/**\n * Input object guard for simple scalar calculators that also rejects unknown keys. A misspelled\n * or wrong-unit field (for example focusDistanceMm instead of focusDistanceM) is never silently ignored.\n */\nexport function requireInputKeys(value: unknown, functionName: string, allowedKeys: readonly string[]): void {\n requireInputObject(value, `${functionName} input`);\n // for-in over own keys avoids allocating a key array on hot scalar paths.\n for (const key in value as object) {\n if (Object.hasOwn(value as object, key) && !allowedKeys.includes(key)) {\n throw new InvalidConfigurationError(`${functionName} input has unknown field ${JSON.stringify(key)}.`);\n }\n }\n}\n\n/**\n * Rejects any own enumerable key of a versioned or engine record that is not on its allowlist, with\n * the message `<path> has unknown field \"<field>\".` The caller has already checked that `record` is\n * a plain object. Used at every object level of the `parse*()` record parsers, so a misspelled or\n * stale field in a stored profile fails instead of being silently dropped.\n */\nexport function rejectUnknownFields(record: object, allowedKeys: readonly string[], path: string): void {\n for (const key in record) {\n if (Object.hasOwn(record, key) && !allowedKeys.includes(key)) {\n throw new InvalidConfigurationError(`${path} has unknown field ${JSON.stringify(key)}.`);\n }\n }\n}\n\n/**\n * Checks the fixed-value flags that a parser writes into its own output (for example\n * `sceneRadianceCalculated: false`). They may be passed back in, so a parsed record parses again,\n * but only with exactly the fixed value; any other value is rejected rather than ignored.\n */\nexport function requireFixedFieldsWhenPresent(\n record: Readonly<Record<string, unknown>>, fixed: Readonly<Record<string, boolean | string>>, path: string\n): void {\n for (const key of Object.keys(fixed)) {\n if (record[key] !== undefined && record[key] !== fixed[key]) {\n throw new InvalidConfigurationError(`${path}.${key} must be ${JSON.stringify(fixed[key])} when supplied.`);\n }\n }\n}\n\n/**\n * Fields of the shared relative / not-quantified uncertainty union used by many evidence-backed\n * profiles: `{ kind: \"relative\", fraction, basis }` or `{ kind: \"not-quantified\", limitation }`.\n */\nexport const UNCERTAINTY_VARIANT_FIELDS: Readonly<Record<string, readonly string[]>> = Object.freeze({\n relative: Object.freeze([\"kind\", \"fraction\", \"basis\"]),\n \"not-quantified\": Object.freeze([\"kind\", \"limitation\"])\n});\n\n/**\n * For a record whose allowed fields depend on a discriminator (for example `kind` or\n * `schemaVersion`), rejects fields that the selected variant does not define. An unrecognized\n * discriminator is left to the caller, which reports it with its own message.\n */\nexport function rejectUnknownVariantFields(\n record: Readonly<Record<string, unknown>>, discriminator: string,\n allowedByVariant: Readonly<Record<string, readonly string[]>>, path: string\n): void {\n const variant = record[discriminator];\n if (typeof variant === \"string\" && Object.hasOwn(allowedByVariant, variant)) {\n rejectUnknownFields(record, allowedByVariant[variant]!, path);\n }\n}\n"]}
1
+ {"version":3,"file":"record-validation.js","sourceRoot":"","sources":["../../src/core/record-validation.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Shared input checks used by the domain parsers: plain-record and allowed-key checks, the\n * public identifier grammar, and guards for the top-level argument of a public function.\n * Each domain keeps its own schema and error messages.\n * @see docs/API_STYLE.md for equations, coordinate/unit conventions, blockers and support limits.\n */\n\nimport { InvalidConfigurationError } from \"./configuration-error.js\";\n\n/**\n * Checks that a value is a plain record whose keys are all on an allowlist. The caller\n * supplies the domain's schema and error messages.\n *\n * Returns the original record. It does not copy, freeze or strip fields, require missing\n * fields, or check child values. Like the domain parsers, it checks own enumerable string keys.\n * From 2.0.0 an unknown key also names the field: `<message> Unknown field \"<field>\".`\n */\nexport function requireAllowlistedRecord(\n value: unknown, allowedKeys: readonly string[], message: string\n): Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n throw new InvalidConfigurationError(message);\n }\n for (const key in value) {\n if (Object.hasOwn(value, key) && !allowedKeys.includes(key)) {\n throw new InvalidConfigurationError(`${message} Unknown field ${JSON.stringify(key)}.`);\n }\n }\n return value as Record<string, unknown>;\n}\n\n/**\n * Shared grammar for public identifiers: 1–128 ASCII characters. The first is a letter or\n * digit. The rest are letters, digits, dot, underscore, colon or hyphen.\n *\n * The identifier is opaque: no trimming, case conversion or path/URL interpretation. Each\n * domain decides what the identifier means and keeps its exact error message.\n */\nexport function requirePublicOpaqueId(value: unknown, message: string): string {\n if (!isPublicOpaqueId(value)) {\n throw new InvalidConfigurationError(message);\n }\n return value;\n}\n\n/** Same grammar for domains that combine ID rejection with other field checks. */\nexport function isPublicOpaqueId(value: unknown): value is string {\n return typeof value === \"string\" && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(value);\n}\n\n/**\n * Guard for a public function's input object. If it receives null, a primitive or an array,\n * it throws the domain's InvalidConfigurationError, never a raw TypeError from reading a\n * property. It does not check fields.\n */\nexport function requireInputObject(value: unknown, label: string): void {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n throw new InvalidConfigurationError(`${label} must be an object.`);\n }\n}\n\n/** Root-function input guard for a required array argument; see requireInputObject. */\nexport function requireInputArray(value: unknown, label: string): void {\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(`${label} must be an array.`);\n }\n}\n\n/**\n * Input object guard for simple scalar calculators that also rejects unknown keys. A misspelled\n * or wrong-unit field (for example focusDistanceMm instead of focusDistanceM) is never silently ignored.\n */\nexport function requireInputKeys(value: unknown, functionName: string, allowedKeys: readonly string[]): void {\n requireInputObject(value, `${functionName} input`);\n // for-in over own keys avoids allocating a key array on hot scalar paths.\n for (const key in value as object) {\n if (Object.hasOwn(value as object, key) && !allowedKeys.includes(key)) {\n throw new InvalidConfigurationError(`${functionName} input has unknown field ${JSON.stringify(key)}.`);\n }\n }\n}\n\n/**\n * Rejects any own enumerable key of a versioned or engine record that is not on its allowlist, with\n * the message `<path> has unknown field \"<field>\".` The caller has already checked that `record` is\n * a plain object. Used at every object level of the `parse*()` record parsers, so a misspelled or\n * stale field in a stored profile fails instead of being silently dropped.\n */\nexport function rejectUnknownFields(record: object, allowedKeys: readonly string[], path: string): void {\n for (const key in record) {\n if (Object.hasOwn(record, key) && !allowedKeys.includes(key)) {\n throw new InvalidConfigurationError(`${path} has unknown field ${JSON.stringify(key)}.`);\n }\n }\n}\n\n/**\n * Checks the fixed-value flags that a parser writes into its own output (for example\n * `sceneRadianceCalculated: false`). They may be passed back in, so a parsed record parses again,\n * but only with exactly the fixed value; any other value is rejected rather than ignored.\n */\nexport function requireFixedFieldsWhenPresent(\n record: Readonly<Record<string, unknown>>, fixed: Readonly<Record<string, boolean | string>>, path: string\n): void {\n for (const key of Object.keys(fixed)) {\n if (record[key] !== undefined && record[key] !== fixed[key]) {\n throw new InvalidConfigurationError(`${path}.${key} must be ${JSON.stringify(fixed[key])} when supplied.`);\n }\n }\n}\n\n/**\n * Fields of the shared relative / not-quantified uncertainty union used by many evidence-backed\n * profiles: `{ kind: \"relative\", fraction, basis }` or `{ kind: \"not-quantified\", limitation }`.\n */\nexport const UNCERTAINTY_VARIANT_FIELDS: Readonly<Record<string, readonly string[]>> = /* @__PURE__ */ Object.freeze({\n relative: /* @__PURE__ */ Object.freeze([\"kind\", \"fraction\", \"basis\"]),\n \"not-quantified\": /* @__PURE__ */ Object.freeze([\"kind\", \"limitation\"])\n});\n\n/**\n * For a record whose allowed fields depend on a discriminator (for example `kind` or\n * `schemaVersion`), rejects fields that the selected variant does not define. An unrecognized\n * discriminator is left to the caller, which reports it with its own message.\n */\nexport function rejectUnknownVariantFields(\n record: Readonly<Record<string, unknown>>, discriminator: string,\n allowedByVariant: Readonly<Record<string, readonly string[]>>, path: string\n): void {\n const variant = record[discriminator];\n if (typeof variant === \"string\" && Object.hasOwn(allowedByVariant, variant)) {\n rejectUnknownFields(record, allowedByVariant[variant]!, path);\n }\n}\n"]}
@@ -6,4 +6,4 @@
6
6
  * own versions. Release checks confirm it matches package.json and the packed package.
7
7
  * @see docs/RELEASE_1_0_1.md
8
8
  */
9
- export declare const ENGINE_API_VERSION: "2.13.0";
9
+ export declare const ENGINE_API_VERSION: "2.14.1";
@@ -7,5 +7,5 @@
7
7
  * own versions. Release checks confirm it matches package.json and the packed package.
8
8
  * @see docs/RELEASE_1_0_1.md
9
9
  */
10
- export const ENGINE_API_VERSION = "2.13.0";
10
+ export const ENGINE_API_VERSION = "2.14.1";
11
11
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/core/version.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAiB,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Version of the engine release. Since 1.0.1 it equals the npm package version.\n *\n * New captures and plans record this version as their creator. Archived records keep the\n * version they were made with. Proof-of-concept (POC), schema and model contracts have their\n * own versions. Release checks confirm it matches package.json and the packed package.\n * @see docs/RELEASE_1_0_1.md\n */\nexport const ENGINE_API_VERSION = \"2.13.0\" as const;\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/core/version.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAiB,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Version of the engine release. Since 1.0.1 it equals the npm package version.\n *\n * New captures and plans record this version as their creator. Archived records keep the\n * version they were made with. Proof-of-concept (POC), schema and model contracts have their\n * own versions. Release checks confirm it matches package.json and the packed package.\n * @see docs/RELEASE_1_0_1.md\n */\nexport const ENGINE_API_VERSION = \"2.14.1\" as const;\n"]}
@@ -15,15 +15,15 @@ import { InvalidConfigurationError } from "../core/configuration-error.js";
15
15
  import { requireInputKeys, requireInputObject } from "../core/record-validation.js";
16
16
  import { calculateEquivalentFocalLength35Mm } from "../camera/equivalent-focal-length.js";
17
17
  /** Full-frame-equivalent focal lengths of the generic prime family, mm. */
18
- export const GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM = Object.freeze([10, 12, 14, 16, 20, 24, 28, 35, 40, 50, 85, 105, 135, 200, 300, 400, 500, 600, 800, 1200]);
18
+ export const GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM = /* @__PURE__ */ Object.freeze([10, 12, 14, 16, 20, 24, 28, 35, 40, 50, 85, 105, 135, 200, 300, 400, 500, 600, 800, 1200]);
19
19
  /**
20
20
  * The marked third-stop f-numbers (the conventional rounded values of N = 2^(k/6), k = 0, 1, …), from f/1 to f/32.
21
21
  * A lens's `fNumbers` are those within its range; any f-number inside the range is accepted.
22
22
  */
23
- export const GENERIC_PRIME_THIRD_STOP_F_NUMBERS = Object.freeze([1, 1.1, 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.5, 2.8, 3.2, 3.5, 4, 4.5, 5, 5.6, 6.3, 7.1, 8, 9, 10, 11,
23
+ export const GENERIC_PRIME_THIRD_STOP_F_NUMBERS = /* @__PURE__ */ Object.freeze([1, 1.1, 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.5, 2.8, 3.2, 3.5, 4, 4.5, 5, 5.6, 6.3, 7.1, 8, 9, 10, 11,
24
24
  13, 14, 16, 18, 20, 22, 25, 29, 32]);
25
25
  /** Minimum focus rule: the object distance at this magnification, but at least `minimumDistanceM`. */
26
- export const GENERIC_PRIME_MINIMUM_FOCUS = Object.freeze({ magnification: 0.15, minimumDistanceM: 0.1 });
26
+ export const GENERIC_PRIME_MINIMUM_FOCUS = /* @__PURE__ */ Object.freeze({ magnification: 0.15, minimumDistanceM: 0.1 });
27
27
  /** Widest f-number by equivalent focal length (inclusive upper bounds of each class). */
28
28
  const WIDEST = [[16, 2.8], [28, 1.8], [85, 1.4], [135, 2], [300, 2.8], [600, 4], [800, 5.6], [1200, 8]];
29
29
  /** Narrowest f-number by equivalent focal length. */