@photivra/engine 0.1.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/CITATION.cff +1 -1
  3. package/README.md +61 -12
  4. package/dist/camera/equivalent-focal-length.d.ts +34 -0
  5. package/dist/camera/equivalent-focal-length.d.ts.map +1 -0
  6. package/dist/camera/equivalent-focal-length.js +33 -0
  7. package/dist/camera/equivalent-focal-length.js.map +1 -0
  8. package/dist/camera/field-of-view.d.ts +40 -3
  9. package/dist/camera/field-of-view.d.ts.map +1 -1
  10. package/dist/camera/field-of-view.js +66 -24
  11. package/dist/camera/field-of-view.js.map +1 -1
  12. package/dist/core/calculation-result.d.ts.map +1 -1
  13. package/dist/core/calculation-result.js +14 -2
  14. package/dist/core/calculation-result.js.map +1 -1
  15. package/dist/core/configuration-error.d.ts +9 -0
  16. package/dist/core/configuration-error.d.ts.map +1 -0
  17. package/dist/core/configuration-error.js +13 -0
  18. package/dist/core/configuration-error.js.map +1 -0
  19. package/dist/core/evidence-provenance.d.ts +40 -0
  20. package/dist/core/evidence-provenance.d.ts.map +1 -0
  21. package/dist/core/evidence-provenance.js +79 -0
  22. package/dist/core/evidence-provenance.js.map +1 -0
  23. package/dist/core/image-formation.d.ts +70 -0
  24. package/dist/core/image-formation.d.ts.map +1 -0
  25. package/dist/core/image-formation.js +335 -0
  26. package/dist/core/image-formation.js.map +1 -0
  27. package/dist/exposure/exposure.d.ts +31 -0
  28. package/dist/exposure/exposure.d.ts.map +1 -1
  29. package/dist/exposure/exposure.js +35 -0
  30. package/dist/exposure/exposure.js.map +1 -1
  31. package/dist/index.d.ts +16 -4
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +16 -4
  34. package/dist/index.js.map +1 -1
  35. package/dist/motion/camera-rotation.d.ts +91 -0
  36. package/dist/motion/camera-rotation.d.ts.map +1 -0
  37. package/dist/motion/camera-rotation.js +157 -0
  38. package/dist/motion/camera-rotation.js.map +1 -0
  39. package/dist/optics/focus-breathing.d.ts +73 -0
  40. package/dist/optics/focus-breathing.d.ts.map +1 -0
  41. package/dist/optics/focus-breathing.js +77 -0
  42. package/dist/optics/focus-breathing.js.map +1 -0
  43. package/dist/optics/illumination-vignetting.d.ts +59 -0
  44. package/dist/optics/illumination-vignetting.d.ts.map +1 -0
  45. package/dist/optics/illumination-vignetting.js +107 -0
  46. package/dist/optics/illumination-vignetting.js.map +1 -0
  47. package/dist/optics/lateral-chromatic-aberration.d.ts +93 -0
  48. package/dist/optics/lateral-chromatic-aberration.d.ts.map +1 -0
  49. package/dist/optics/lateral-chromatic-aberration.js +174 -0
  50. package/dist/optics/lateral-chromatic-aberration.js.map +1 -0
  51. package/dist/optics/psf-foundation.d.ts +102 -0
  52. package/dist/optics/psf-foundation.d.ts.map +1 -0
  53. package/dist/optics/psf-foundation.js +164 -0
  54. package/dist/optics/psf-foundation.js.map +1 -0
  55. package/dist/optics/radial-distortion.d.ts +91 -0
  56. package/dist/optics/radial-distortion.d.ts.map +1 -0
  57. package/dist/optics/radial-distortion.js +198 -0
  58. package/dist/optics/radial-distortion.js.map +1 -0
  59. package/dist/output/capture-geometry.d.ts +225 -0
  60. package/dist/output/capture-geometry.d.ts.map +1 -0
  61. package/dist/output/capture-geometry.js +478 -0
  62. package/dist/output/capture-geometry.js.map +1 -0
  63. package/dist/schema/validation.d.ts +1 -8
  64. package/dist/schema/validation.d.ts.map +1 -1
  65. package/dist/schema/validation.js +2 -11
  66. package/dist/schema/validation.js.map +1 -1
  67. package/dist/sensor/architecture.d.ts +40 -0
  68. package/dist/sensor/architecture.d.ts.map +1 -0
  69. package/dist/sensor/architecture.js +98 -0
  70. package/dist/sensor/architecture.js.map +1 -0
  71. package/dist/sensor/radiometry-readiness.d.ts +111 -0
  72. package/dist/sensor/radiometry-readiness.d.ts.map +1 -0
  73. package/dist/sensor/radiometry-readiness.js +294 -0
  74. package/dist/sensor/radiometry-readiness.js.map +1 -0
  75. package/dist/sensor/sensor-geometry.d.ts +99 -0
  76. package/dist/sensor/sensor-geometry.d.ts.map +1 -0
  77. package/dist/sensor/sensor-geometry.js +71 -0
  78. package/dist/sensor/sensor-geometry.js.map +1 -0
  79. package/dist/simulation/poc-simulation.d.ts +93 -1
  80. package/dist/simulation/poc-simulation.d.ts.map +1 -1
  81. package/dist/simulation/poc-simulation.js +308 -24
  82. package/dist/simulation/poc-simulation.js.map +1 -1
  83. package/docs/API_STYLE.md +35 -2
  84. package/docs/ARCHITECTURE.md +179 -1
  85. package/docs/IMAGE_FORMATION.md +142 -0
  86. package/docs/MOTION_AND_SIGNAL.md +54 -1
  87. package/docs/PHYSICS_FOUNDATION.md +190 -3
  88. package/docs/POC_API.md +73 -7
  89. package/docs/PROVENANCE.md +24 -0
  90. package/docs/PSF_FOUNDATION.md +133 -0
  91. package/docs/STABILIZATION.md +17 -4
  92. package/docs/USAGE.md +680 -4
  93. package/package.json +2 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configuration-error.js","sourceRoot":"","sources":["../../src/core/configuration-error.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;GAGG;AACH,MAAM,OAAO,yBAA0B,SAAQ,SAAS;IAC7C,IAAI,GAAG,uBAAuB,CAAC;IAExC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF"}
@@ -0,0 +1,40 @@
1
+ export type EvidenceSourceOrigin = "manufacturer" | "third-party" | "photivra";
2
+ export type EvidenceReuseStatus = "factual-reference-only" | "reusable-data" | "photivra-owned";
3
+ export interface EvidenceProvenance {
4
+ /** Who originated the underlying fact/data. */
5
+ sourceOrigin: EvidenceSourceOrigin;
6
+ /**
7
+ * Public/stable source reference or Photivra evidence identifier.
8
+ *
9
+ * The engine does not fetch this reference at runtime.
10
+ */
11
+ sourceReference: string;
12
+ /**
13
+ * How the referenced material may be used by Photivra.
14
+ *
15
+ * This is intentionally independent from source origin: a manufacturer or
16
+ * third party may publish either factual-reference-only material or
17
+ * explicitly reusable licensed data.
18
+ */
19
+ reuseStatus: EvidenceReuseStatus;
20
+ /** Required when reuseStatus is reusable-data. */
21
+ license?: string;
22
+ note?: string;
23
+ }
24
+ export interface EvidenceBackedFact<T> {
25
+ value: T;
26
+ /** One or more independent evidence records supporting this fact. */
27
+ evidence: readonly EvidenceProvenance[];
28
+ }
29
+ /**
30
+ * Parses one provenance/evidence record.
31
+ *
32
+ * Source origin and reuse status are intentionally orthogonal. The parser only
33
+ * rejects combinations that are intrinsically contradictory.
34
+ */
35
+ export declare function parseEvidenceProvenance(value: unknown, path: string): EvidenceProvenance;
36
+ /**
37
+ * Parses a non-empty evidence array.
38
+ */
39
+ export declare function parseEvidenceList(value: unknown, path: string): readonly EvidenceProvenance[];
40
+ //# sourceMappingURL=evidence-provenance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence-provenance.d.ts","sourceRoot":"","sources":["../../src/core/evidence-provenance.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,oBAAoB,GAC5B,cAAc,GACd,aAAa,GACb,UAAU,CAAC;AAEf,MAAM,MAAM,mBAAmB,GAC3B,wBAAwB,GACxB,eAAe,GACf,gBAAgB,CAAC;AAErB,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,YAAY,EAAE,oBAAoB,CAAC;IACnC;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,WAAW,EAAE,mBAAmB,CAAC;IACjC,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,KAAK,EAAE,CAAC,CAAC;IACT,qEAAqE;IACrE,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACzC;AAmCD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,GACX,kBAAkB,CA6DpB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,GACX,SAAS,kBAAkB,EAAE,CAU/B"}
@@ -0,0 +1,79 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { InvalidConfigurationError } from "./configuration-error.js";
3
+ const SOURCE_ORIGINS = new Set([
4
+ "manufacturer",
5
+ "third-party",
6
+ "photivra"
7
+ ]);
8
+ const REUSE_STATUSES = new Set([
9
+ "factual-reference-only",
10
+ "reusable-data",
11
+ "photivra-owned"
12
+ ]);
13
+ function requireRecord(value, path) {
14
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
15
+ throw new InvalidConfigurationError(`${path} must be an object.`);
16
+ }
17
+ return value;
18
+ }
19
+ function requireNonEmptyString(record, key, path) {
20
+ const value = record[key];
21
+ if (typeof value !== "string" || value.trim().length === 0) {
22
+ throw new InvalidConfigurationError(`${path}.${key} must be a non-empty string.`);
23
+ }
24
+ return value;
25
+ }
26
+ /**
27
+ * Parses one provenance/evidence record.
28
+ *
29
+ * Source origin and reuse status are intentionally orthogonal. The parser only
30
+ * rejects combinations that are intrinsically contradictory.
31
+ */
32
+ export function parseEvidenceProvenance(value, path) {
33
+ const record = requireRecord(value, path);
34
+ const sourceOrigin = requireNonEmptyString(record, "sourceOrigin", path);
35
+ const sourceReference = requireNonEmptyString(record, "sourceReference", path);
36
+ const reuseStatus = requireNonEmptyString(record, "reuseStatus", path);
37
+ if (!SOURCE_ORIGINS.has(sourceOrigin)) {
38
+ throw new InvalidConfigurationError(`${path}.sourceOrigin is invalid.`);
39
+ }
40
+ if (!REUSE_STATUSES.has(reuseStatus)) {
41
+ throw new InvalidConfigurationError(`${path}.reuseStatus is invalid.`);
42
+ }
43
+ const typedOrigin = sourceOrigin;
44
+ const typedReuseStatus = reuseStatus;
45
+ if (typedReuseStatus === "photivra-owned" &&
46
+ typedOrigin !== "photivra") {
47
+ throw new InvalidConfigurationError(`${path}.photivra-owned evidence must have sourceOrigin "photivra".`);
48
+ }
49
+ const license = record.license;
50
+ if (license !== undefined &&
51
+ (typeof license !== "string" || license.trim().length === 0)) {
52
+ throw new InvalidConfigurationError(`${path}.license must be a non-empty string when supplied.`);
53
+ }
54
+ if (typedReuseStatus === "reusable-data" && license === undefined) {
55
+ throw new InvalidConfigurationError(`${path}.license is required for reusable-data provenance.`);
56
+ }
57
+ const note = record.note;
58
+ if (note !== undefined &&
59
+ (typeof note !== "string" || note.trim().length === 0)) {
60
+ throw new InvalidConfigurationError(`${path}.note must be a non-empty string when supplied.`);
61
+ }
62
+ return {
63
+ sourceOrigin: typedOrigin,
64
+ sourceReference,
65
+ reuseStatus: typedReuseStatus,
66
+ ...(license === undefined ? {} : { license }),
67
+ ...(note === undefined ? {} : { note })
68
+ };
69
+ }
70
+ /**
71
+ * Parses a non-empty evidence array.
72
+ */
73
+ export function parseEvidenceList(value, path) {
74
+ if (!Array.isArray(value) || value.length === 0) {
75
+ throw new InvalidConfigurationError(`${path} must be a non-empty array.`);
76
+ }
77
+ return value.map((entry, index) => parseEvidenceProvenance(entry, `${path}[${index}]`));
78
+ }
79
+ //# sourceMappingURL=evidence-provenance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence-provenance.js","sourceRoot":"","sources":["../../src/core/evidence-provenance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Version of the public image-formation ordering contract.
3
+ *
4
+ * This version is independent from package, root-engine, and composed-POC
5
+ * versions. It describes semantic ownership/order only; it does not imply that
6
+ * every reserved stage is implemented.
7
+ */
8
+ export declare const IMAGE_FORMATION_CONTRACT_VERSION: "0.2.0";
9
+ export type ImageFormationDomainId = "scene-ray-geometry" | "lens-pupil-throughput" | "field-wavelength-psf" | "temporal-exposure-readout" | "sensor-output-display";
10
+ export type ImageFormationCoordinateSpaceId = "scene-metric" | "image-plane-metric" | "native-sensor-physical" | "native-raster" | "oriented-capture-raster" | "output-raster" | "display";
11
+ export type ImageFormationStageId = "scene-ray-projection" | "lens-field-pupil-evaluation" | "field-wavelength-psf" | "temporal-exposure-readout" | "sensor-optical-stack" | "photosite-cfa-sampling" | "sensor-charge-statistics" | "read-noise-conversion" | "adc-quantization" | "reconstruction" | "physical-orientation-transform" | "output-crop-resample" | "display-processing";
12
+ export type ImageFormationImplementationStatus = "existing-foundation" | "partial-foundation" | "reserved-contract";
13
+ export type ImageFormationEffectId = "focus-breathing" | "geometric-distortion" | "lateral-chromatic-aberration" | "illumination-vignetting" | "mechanical-vignetting" | "non-circular-diffraction" | "field-curvature" | "field-sharpness-falloff" | "field-dependent-bokeh" | "spatial-camera-rotation" | "rolling-readout" | "photosite-cfa-sampling" | "photon-charge-statistics" | "read-noise-conversion" | "demosaic-remosaic";
14
+ export interface ImageFormationCoordinateSpaceContract {
15
+ id: ImageFormationCoordinateSpaceId;
16
+ unit: "m" | "mm" | "px" | "display-dependent";
17
+ origin: string;
18
+ axes: string;
19
+ note: string;
20
+ }
21
+ export interface ImageFormationStageContract {
22
+ id: ImageFormationStageId;
23
+ domain: ImageFormationDomainId;
24
+ status: ImageFormationImplementationStatus;
25
+ coordinateSpaces: readonly ImageFormationCoordinateSpaceId[];
26
+ requiredUpstreamStages: readonly ImageFormationStageId[];
27
+ coupledStages: readonly ImageFormationStageId[];
28
+ purpose: string;
29
+ }
30
+ export interface ImageFormationEffectPlacement {
31
+ id: ImageFormationEffectId;
32
+ primaryStage: ImageFormationStageId;
33
+ coupledStages: readonly ImageFormationStageId[];
34
+ note: string;
35
+ }
36
+ export interface ImageFormationTemporalContract {
37
+ authoritativeTimeUnit: "s";
38
+ origin: "exposure-start";
39
+ normalizedTimeIsDerivedOnly: true;
40
+ exposureDurationAndReadoutTimingAreIndependent: true;
41
+ globalReadoutDoesNotImplyZeroMotionBlur: true;
42
+ nativeReadoutDirectionRemainsNativeUnderOrientation: true;
43
+ note: string;
44
+ }
45
+ export interface ImageFormationRendererContract {
46
+ geometricWarpSampling: "inverse-map-destination-to-source";
47
+ alphaRepresentation: "premultiplied";
48
+ occlusionRule: "preserve-depth-order-across-warps";
49
+ previewAndReferenceShareScientificContract: true;
50
+ backendMayApproximateButNotRedefineSemantics: true;
51
+ note: string;
52
+ }
53
+ export interface ImageFormationContract {
54
+ version: typeof IMAGE_FORMATION_CONTRACT_VERSION;
55
+ domains: readonly ImageFormationDomainId[];
56
+ coordinateSpaces: readonly ImageFormationCoordinateSpaceContract[];
57
+ stages: readonly ImageFormationStageContract[];
58
+ effectPlacements: readonly ImageFormationEffectPlacement[];
59
+ temporal: ImageFormationTemporalContract;
60
+ renderer: ImageFormationRendererContract;
61
+ notes: readonly string[];
62
+ }
63
+ /**
64
+ * Returns the public image-formation ownership/order contract.
65
+ *
66
+ * The result is descriptive metadata, not a renderer implementation or an
67
+ * assertion that every reserved stage is currently available.
68
+ */
69
+ export declare function getImageFormationContract(): ImageFormationContract;
70
+ //# sourceMappingURL=image-formation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-formation.d.ts","sourceRoot":"","sources":["../../src/core/image-formation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,335 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * Version of the public image-formation ordering contract.
4
+ *
5
+ * This version is independent from package, root-engine, and composed-POC
6
+ * versions. It describes semantic ownership/order only; it does not imply that
7
+ * every reserved stage is implemented.
8
+ */
9
+ export const IMAGE_FORMATION_CONTRACT_VERSION = "0.2.0";
10
+ const DOMAINS = [
11
+ "scene-ray-geometry",
12
+ "lens-pupil-throughput",
13
+ "field-wavelength-psf",
14
+ "temporal-exposure-readout",
15
+ "sensor-output-display"
16
+ ];
17
+ const COORDINATE_SPACES = [
18
+ {
19
+ id: "scene-metric",
20
+ unit: "m",
21
+ origin: "scene/camera model defined by the scene or projection contract",
22
+ axes: "scene/world axes remain owned by the scene/projection contract",
23
+ note: "Do not reinterpret scene axes as raster axes."
24
+ },
25
+ {
26
+ id: "image-plane-metric",
27
+ unit: "mm",
28
+ origin: "optical axis",
29
+ axes: "+X right, +Y up",
30
+ note: "This preserves the legacy projected-motion/image-plane convention."
31
+ },
32
+ {
33
+ id: "native-sensor-physical",
34
+ unit: "mm",
35
+ origin: "optical axis",
36
+ axes: "+X right, +Y down in native sensor-facing coordinates",
37
+ note: "Physical sensor coordinates remain invariant under camera orientation."
38
+ },
39
+ {
40
+ id: "native-raster",
41
+ unit: "px",
42
+ origin: "top-left of the native effective image raster",
43
+ axes: "+X right, +Y down; rectangles use half-open integer extents",
44
+ note: "Native coordinates remain invariant under physical camera rotation."
45
+ },
46
+ {
47
+ id: "oriented-capture-raster",
48
+ unit: "px",
49
+ origin: "top-left after the explicit physical-orientation transform",
50
+ axes: "+X right, +Y down",
51
+ note: "This is derived from native coordinates; it never redefines native readout direction."
52
+ },
53
+ {
54
+ id: "output-raster",
55
+ unit: "px",
56
+ origin: "top-left of the declared output raster",
57
+ axes: "+X right, +Y down",
58
+ note: "Digital crop/resampling does not mutate physical sensor identity."
59
+ },
60
+ {
61
+ id: "display",
62
+ unit: "display-dependent",
63
+ origin: "consumer/display contract",
64
+ axes: "consumer/display contract",
65
+ note: "Display/tone/UI coordinates are not authoritative camera-science coordinates."
66
+ }
67
+ ];
68
+ const STAGES = [
69
+ {
70
+ id: "scene-ray-projection",
71
+ domain: "scene-ray-geometry",
72
+ status: "existing-foundation",
73
+ coordinateSpaces: ["scene-metric", "image-plane-metric"],
74
+ requiredUpstreamStages: [],
75
+ coupledStages: ["temporal-exposure-readout"],
76
+ purpose: "Project scene geometry into the optical image plane while preserving explicit metric geometry and focus-aware projection."
77
+ },
78
+ {
79
+ id: "lens-field-pupil-evaluation",
80
+ domain: "lens-pupil-throughput",
81
+ status: "partial-foundation",
82
+ coordinateSpaces: ["image-plane-metric", "native-sensor-physical"],
83
+ requiredUpstreamStages: ["scene-ray-projection"],
84
+ coupledStages: ["field-wavelength-psf"],
85
+ purpose: "Own focus-dependent framing, geometric field mapping, wavelength/channel field mapping, illumination throughput, and pupil clipping inputs."
86
+ },
87
+ {
88
+ id: "field-wavelength-psf",
89
+ domain: "field-wavelength-psf",
90
+ status: "partial-foundation",
91
+ coordinateSpaces: ["image-plane-metric", "native-sensor-physical"],
92
+ requiredUpstreamStages: ["lens-field-pupil-evaluation"],
93
+ coupledStages: ["temporal-exposure-readout"],
94
+ purpose: "Own field-, depth-, pupil-, and wavelength-dependent point-spread behavior including defocus and diffraction without collapsing independent effects into one undocumented blur scalar."
95
+ },
96
+ {
97
+ id: "temporal-exposure-readout",
98
+ domain: "temporal-exposure-readout",
99
+ status: "partial-foundation",
100
+ coordinateSpaces: ["scene-metric", "image-plane-metric", "native-raster"],
101
+ requiredUpstreamStages: [
102
+ "scene-ray-projection",
103
+ "lens-field-pupil-evaluation",
104
+ "field-wavelength-psf"
105
+ ],
106
+ coupledStages: ["photosite-cfa-sampling"],
107
+ purpose: "Evaluate time-dependent scene/camera mapping over exposure windows and reserve independent native-sensor readout scheduling for rolling/global capture."
108
+ },
109
+ {
110
+ id: "sensor-optical-stack",
111
+ domain: "sensor-output-display",
112
+ status: "reserved-contract",
113
+ coordinateSpaces: ["native-sensor-physical"],
114
+ requiredUpstreamStages: ["field-wavelength-psf"],
115
+ coupledStages: ["photosite-cfa-sampling"],
116
+ purpose: "Reserve optical low-pass filter, cover-glass, and microlens behavior before photosite/color sampling."
117
+ },
118
+ {
119
+ id: "photosite-cfa-sampling",
120
+ domain: "sensor-output-display",
121
+ status: "reserved-contract",
122
+ coordinateSpaces: ["native-sensor-physical", "native-raster"],
123
+ requiredUpstreamStages: ["sensor-optical-stack"],
124
+ coupledStages: ["temporal-exposure-readout"],
125
+ purpose: "Reserve photosite/CFA spatial sampling while keeping native sensor coordinates and readout timing explicit."
126
+ },
127
+ {
128
+ id: "sensor-charge-statistics",
129
+ domain: "sensor-output-display",
130
+ status: "partial-foundation",
131
+ coordinateSpaces: ["native-raster"],
132
+ requiredUpstreamStages: [
133
+ "photosite-cfa-sampling",
134
+ "temporal-exposure-readout"
135
+ ],
136
+ coupledStages: [],
137
+ purpose: "Reserve photon/electron integration and shot-statistics semantics separately from later electronic read noise."
138
+ },
139
+ {
140
+ id: "read-noise-conversion",
141
+ domain: "sensor-output-display",
142
+ status: "partial-foundation",
143
+ coordinateSpaces: ["native-raster"],
144
+ requiredUpstreamStages: ["sensor-charge-statistics"],
145
+ coupledStages: [],
146
+ purpose: "Reserve electronic read-noise and conversion behavior independently from photon shot statistics."
147
+ },
148
+ {
149
+ id: "adc-quantization",
150
+ domain: "sensor-output-display",
151
+ status: "reserved-contract",
152
+ coordinateSpaces: ["native-raster"],
153
+ requiredUpstreamStages: ["read-noise-conversion"],
154
+ coupledStages: [],
155
+ purpose: "Reserve analog-to-digital conversion, clipping, and quantization after sensor/electronic signal formation."
156
+ },
157
+ {
158
+ id: "reconstruction",
159
+ domain: "sensor-output-display",
160
+ status: "reserved-contract",
161
+ coordinateSpaces: ["native-raster"],
162
+ requiredUpstreamStages: ["adc-quantization"],
163
+ coupledStages: [],
164
+ purpose: "Reserve demosaic/remosaic, binning-aware reconstruction, pixel-shift combination, and related capture-mode processing."
165
+ },
166
+ {
167
+ id: "physical-orientation-transform",
168
+ domain: "sensor-output-display",
169
+ status: "existing-foundation",
170
+ coordinateSpaces: ["native-raster", "oriented-capture-raster"],
171
+ requiredUpstreamStages: ["reconstruction"],
172
+ coupledStages: ["temporal-exposure-readout"],
173
+ purpose: "Transform reconstructed native-raster coordinates into oriented capture coordinates without redefining native sensor/readout coordinates. The coordinate transform primitive already exists independently; this dependency reserves its full-pipeline placement."
174
+ },
175
+ {
176
+ id: "output-crop-resample",
177
+ domain: "sensor-output-display",
178
+ status: "existing-foundation",
179
+ coordinateSpaces: ["oriented-capture-raster", "output-raster"],
180
+ requiredUpstreamStages: ["physical-orientation-transform"],
181
+ coupledStages: [],
182
+ purpose: "Apply digital/output crop and resampling while preserving physical capture identity and explicit axis-aware scale."
183
+ },
184
+ {
185
+ id: "display-processing",
186
+ domain: "sensor-output-display",
187
+ status: "reserved-contract",
188
+ coordinateSpaces: ["output-raster", "display"],
189
+ requiredUpstreamStages: ["output-crop-resample"],
190
+ coupledStages: [],
191
+ purpose: "Reserve tone/display/output processing after camera-science geometry and sampling; this stage must not redefine upstream physical quantities."
192
+ }
193
+ ];
194
+ const EFFECT_PLACEMENTS = [
195
+ {
196
+ id: "focus-breathing",
197
+ primaryStage: "lens-field-pupil-evaluation",
198
+ coupledStages: ["scene-ray-projection"],
199
+ note: "Focus breathing changes projection/magnification and must not be implemented as post-output crop or display scaling."
200
+ },
201
+ {
202
+ id: "geometric-distortion",
203
+ primaryStage: "lens-field-pupil-evaluation",
204
+ coupledStages: [],
205
+ note: "Distortion is a field-coordinate mapping, not a blur."
206
+ },
207
+ {
208
+ id: "lateral-chromatic-aberration",
209
+ primaryStage: "lens-field-pupil-evaluation",
210
+ coupledStages: ["field-wavelength-psf"],
211
+ note: "Lateral CA is wavelength/channel-dependent field mapping; wavelength-aware PSF models may share the same spectral basis."
212
+ },
213
+ {
214
+ id: "illumination-vignetting",
215
+ primaryStage: "lens-field-pupil-evaluation",
216
+ coupledStages: [],
217
+ note: "Illumination vignetting changes field-dependent throughput only and is distinct from pupil clipping."
218
+ },
219
+ {
220
+ id: "mechanical-vignetting",
221
+ primaryStage: "lens-field-pupil-evaluation",
222
+ coupledStages: ["field-wavelength-psf"],
223
+ note: "Mechanical/pupil clipping changes both throughput and the effective pupil/PSF, including cat's-eye bokeh."
224
+ },
225
+ {
226
+ id: "non-circular-diffraction",
227
+ primaryStage: "field-wavelength-psf",
228
+ coupledStages: ["lens-field-pupil-evaluation"],
229
+ note: "Non-circular diffraction consumes an explicit pupil representation; preserve the current circular Airy result as a separate model."
230
+ },
231
+ {
232
+ id: "field-curvature",
233
+ primaryStage: "field-wavelength-psf",
234
+ coupledStages: [],
235
+ note: "Field curvature is field-dependent focus/PSF behavior, not geometric distortion."
236
+ },
237
+ {
238
+ id: "field-sharpness-falloff",
239
+ primaryStage: "field-wavelength-psf",
240
+ coupledStages: [],
241
+ note: "Field sharpness must be represented through a defensible field-dependent PSF or related optical model, not a synthetic quality score."
242
+ },
243
+ {
244
+ id: "field-dependent-bokeh",
245
+ primaryStage: "field-wavelength-psf",
246
+ coupledStages: ["lens-field-pupil-evaluation"],
247
+ note: "Field-dependent bokeh may depend on pupil clipping and field position; do not collapse it into aperture blade count alone."
248
+ },
249
+ {
250
+ id: "spatial-camera-rotation",
251
+ primaryStage: "temporal-exposure-readout",
252
+ coupledStages: ["scene-ray-projection"],
253
+ note: "Rotation should be evaluable as a time-parameterized mapping; depth-dependent camera translation is outside the initial rotation model."
254
+ },
255
+ {
256
+ id: "rolling-readout",
257
+ primaryStage: "temporal-exposure-readout",
258
+ coupledStages: ["photosite-cfa-sampling", "physical-orientation-transform"],
259
+ note: "Readout timing is native-sensor timing. Physical orientation changes how native scan direction maps to the scene but does not redefine native coordinates."
260
+ },
261
+ {
262
+ id: "photosite-cfa-sampling",
263
+ primaryStage: "photosite-cfa-sampling",
264
+ coupledStages: ["sensor-optical-stack", "temporal-exposure-readout"],
265
+ note: "CFA/photosite sampling follows the sensor optical stack and participates in the declared exposure/readout schedule."
266
+ },
267
+ {
268
+ id: "photon-charge-statistics",
269
+ primaryStage: "sensor-charge-statistics",
270
+ coupledStages: [],
271
+ note: "Photon/charge statistics remain separate from electronic read noise and require explicit radiometric prerequisites."
272
+ },
273
+ {
274
+ id: "read-noise-conversion",
275
+ primaryStage: "read-noise-conversion",
276
+ coupledStages: [],
277
+ note: "Electronic read noise/conversion is downstream of charge formation and must not alter photon shot-noise semantics."
278
+ },
279
+ {
280
+ id: "demosaic-remosaic",
281
+ primaryStage: "reconstruction",
282
+ coupledStages: ["photosite-cfa-sampling"],
283
+ note: "Reconstruction consumes declared capture-mode/CFA sampling rather than redefining the native photosite layout."
284
+ }
285
+ ];
286
+ const TEMPORAL = {
287
+ authoritativeTimeUnit: "s",
288
+ origin: "exposure-start",
289
+ normalizedTimeIsDerivedOnly: true,
290
+ exposureDurationAndReadoutTimingAreIndependent: true,
291
+ globalReadoutDoesNotImplyZeroMotionBlur: true,
292
+ nativeReadoutDirectionRemainsNativeUnderOrientation: true,
293
+ note: "Time-parameterized optical/camera mapping should be evaluated in seconds from exposure start. A normalized [0,1] parameter may be derived for algorithms but is not the authoritative physical time. Rolling/global readout timing is separate from local exposure duration."
294
+ };
295
+ const RENDERER = {
296
+ geometricWarpSampling: "inverse-map-destination-to-source",
297
+ alphaRepresentation: "premultiplied",
298
+ occlusionRule: "preserve-depth-order-across-warps",
299
+ previewAndReferenceShareScientificContract: true,
300
+ backendMayApproximateButNotRedefineSemantics: true,
301
+ note: "Renderer implementations may use bounded preview approximations or higher-fidelity reference evaluation, but both consume the same engine-owned parameters. Geometric warps should inverse-sample destination locations to avoid forward-warp holes, preserve premultiplied-alpha semantics, and must not reorder scene occlusion merely because a field warp is applied."
302
+ };
303
+ const NOTES = [
304
+ "This contract defines scientific ownership, coordinate semantics, and dependency/coupling boundaries. It does not claim that reserved stages are implemented.",
305
+ "The stage graph is a dependency/ownership graph, not a claim that every physical interaction can be evaluated as one independent serial post-process.",
306
+ "Independent effects may be combined computationally only when the implementation documents mathematical equivalence and preserves the public stage/effect semantics.",
307
+ "Generic/parametric virtual-lens models must remain explicitly generic until defensible calibrated data with compatible reuse rights exists."
308
+ ];
309
+ /**
310
+ * Returns the public image-formation ownership/order contract.
311
+ *
312
+ * The result is descriptive metadata, not a renderer implementation or an
313
+ * assertion that every reserved stage is currently available.
314
+ */
315
+ export function getImageFormationContract() {
316
+ return {
317
+ version: IMAGE_FORMATION_CONTRACT_VERSION,
318
+ domains: [...DOMAINS],
319
+ coordinateSpaces: COORDINATE_SPACES.map((space) => ({ ...space })),
320
+ stages: STAGES.map((stage) => ({
321
+ ...stage,
322
+ coordinateSpaces: [...stage.coordinateSpaces],
323
+ requiredUpstreamStages: [...stage.requiredUpstreamStages],
324
+ coupledStages: [...stage.coupledStages]
325
+ })),
326
+ effectPlacements: EFFECT_PLACEMENTS.map((effect) => ({
327
+ ...effect,
328
+ coupledStages: [...effect.coupledStages]
329
+ })),
330
+ temporal: { ...TEMPORAL },
331
+ renderer: { ...RENDERER },
332
+ notes: [...NOTES]
333
+ };
334
+ }
335
+ //# sourceMappingURL=image-formation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-formation.js","sourceRoot":"","sources":["../../src/core/image-formation.ts"],"names":[],"mappings":"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"}
@@ -32,6 +32,37 @@ export interface RelativeOpticalExposure {
32
32
  * response and therefore must not be interpreted as a photon-count result.
33
33
  */
34
34
  export declare function calculateRelativeOpticalExposure(input: CalculateRelativeOpticalExposureInput): CalculationResult<RelativeOpticalExposure>;
35
+ export interface CalculateRelativeRenderedExposureInput {
36
+ aperture: number;
37
+ shutterSeconds: number;
38
+ iso: number;
39
+ referenceAperture: number;
40
+ referenceShutterSeconds: number;
41
+ referenceIso: number;
42
+ }
43
+ export interface RelativeRenderedExposure {
44
+ /** Nominal linear rendering multiplier; 1 equals the reference settings. */
45
+ factor: number;
46
+ /** Difference from the reference in stops. Positive means a brighter rendering. */
47
+ stops: number;
48
+ /** Image-plane optical exposure ratio before nominal ISO gain. */
49
+ opticalFactor: number;
50
+ /** Nominal ISO gain ratio relative to the reference ISO. */
51
+ isoGainFactor: number;
52
+ }
53
+ /**
54
+ * Calculates a relative linear rendering exposure from aperture, shutter, and
55
+ * nominal ISO gain.
56
+ *
57
+ * This relation is intended for deterministic educational rendering relative to
58
+ * a declared reference exposure. ISO is treated as a brightness/gain control;
59
+ * it does not create photons and this function does not model sensor noise,
60
+ * clipping, tone mapping, lens transmission, or absolute scene luminance.
61
+ *
62
+ * @param input Current and reference aperture/shutter/ISO settings.
63
+ * @returns Relative rendering factor and stop difference.
64
+ */
65
+ export declare function calculateRelativeRenderedExposure(input: CalculateRelativeRenderedExposureInput): CalculationResult<RelativeRenderedExposure>;
35
66
  export interface CalculateEquivalentIsoInput {
36
67
  baseIso: number;
37
68
  baseAperture: number;
@@ -1 +1 @@
1
- {"version":3,"file":"exposure.d.ts","sourceRoot":"","sources":["../../src/exposure/exposure.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,+BAA+B,CAAC;AAGvC,MAAM,WAAW,8BAA8B;IAC7C,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,8BAA8B,GACpC,iBAAiB,CAAC,MAAM,CAAC,CAU3B;AAED,MAAM,WAAW,qCAAqC;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB;IACtC,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,qCAAqC,GAC3C,iBAAiB,CAAC,uBAAuB,CAAC,CA6B5C;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,2BAA2B,GACjC,iBAAiB,CAAC,MAAM,CAAC,CAuB3B"}
1
+ {"version":3,"file":"exposure.d.ts","sourceRoot":"","sources":["../../src/exposure/exposure.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,+BAA+B,CAAC;AAGvC,MAAM,WAAW,8BAA8B;IAC7C,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,8BAA8B,GACpC,iBAAiB,CAAC,MAAM,CAAC,CAU3B;AAED,MAAM,WAAW,qCAAqC;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB;IACtC,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,qCAAqC,GAC3C,iBAAiB,CAAC,uBAAuB,CAAC,CA6B5C;AAED,MAAM,WAAW,sCAAsC;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uBAAuB,EAAE,MAAM,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,aAAa,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,sCAAsC,GAC5C,iBAAiB,CAAC,wBAAwB,CAAC,CA6B7C;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,2BAA2B,GACjC,iBAAiB,CAAC,MAAM,CAAC,CAuB3B"}
@@ -37,6 +37,41 @@ export function calculateRelativeOpticalExposure(input) {
37
37
  "Sensor response is not modeled"
38
38
  ]);
39
39
  }
40
+ /**
41
+ * Calculates a relative linear rendering exposure from aperture, shutter, and
42
+ * nominal ISO gain.
43
+ *
44
+ * This relation is intended for deterministic educational rendering relative to
45
+ * a declared reference exposure. ISO is treated as a brightness/gain control;
46
+ * it does not create photons and this function does not model sensor noise,
47
+ * clipping, tone mapping, lens transmission, or absolute scene luminance.
48
+ *
49
+ * @param input Current and reference aperture/shutter/ISO settings.
50
+ * @returns Relative rendering factor and stop difference.
51
+ */
52
+ export function calculateRelativeRenderedExposure(input) {
53
+ requirePositiveFinite("iso", input.iso);
54
+ requirePositiveFinite("referenceIso", input.referenceIso);
55
+ const optical = calculateRelativeOpticalExposure({
56
+ aperture: input.aperture,
57
+ shutterSeconds: input.shutterSeconds,
58
+ referenceAperture: input.referenceAperture,
59
+ referenceShutterSeconds: input.referenceShutterSeconds
60
+ });
61
+ const isoGainFactor = input.iso / input.referenceIso;
62
+ const factor = optical.value.factor * isoGainFactor;
63
+ return calculatedResult({
64
+ factor,
65
+ stops: Math.log2(factor),
66
+ opticalFactor: optical.value.factor,
67
+ isoGainFactor
68
+ }, "relative-rendered-exposure", "1.0.0", [
69
+ "Constant scene illumination",
70
+ "ISO is treated as nominal rendering gain, not photon creation",
71
+ "Lens transmission and sensor-specific gain behavior are not modeled",
72
+ "Clipping and display tone mapping are not modeled"
73
+ ]);
74
+ }
40
75
  /**
41
76
  * Calculates the ISO/gain setting that preserves nominal rendered exposure
42
77
  * after changing aperture and/or shutter, assuming all other factors remain