nx_cinematographer.nx source
↩ module page · 217 lines · 9072 B
1// nx_cinematographer.nx -- Best Cinematography axis: lens + aperture + palette + composition.
2//
3// Substrate's cinematographer-eye classifier. Each axis is a typed
4// sealed enum + per-target appropriateness score. Composer chooses
5// the cinematography target for the scene (editorial / candid /
6// fashion / documentary / cinematic) and the substrate scores how
7// well a render matches that target.
8//
9// Output is the BEST CINEMATOGRAPHY composite Q10 + sealed verdict
10// FRAMING / COMPOSITION / LENS-WRONG / AMATEUR / PROFESSIONAL / AWARD-WORTHY.
11
12// nx_safety_envelope:
13// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
14// sil_target: SIL1
15// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
16// verdict: NOT_YET_EVALUATED
17
18import "nx_syscalls.nx"
19const NX_MAGIC_1024: i64 = 1024
20
21// Sealed lens enums.
22const NX_LENS_UNKNOWN: i64 = 0
23const NX_LENS_WIDE_24MM: i64 = 1 // environmental / dramatic
24const NX_LENS_NORMAL_50MM: i64 = 2 // documentary / candid
25const NX_LENS_PORTRAIT_85MM: i64 = 3 // fashion / editorial subject focus
26const NX_LENS_LONG_135MM: i64 = 4 // tight portrait, compressed background
27const NX_LENS_MACRO: i64 = 5 // detail / extreme close-up
28
29// Sealed aperture enums.
30const NX_APERTURE_F14: i64 = 1 // f/1.4 — extremely shallow DoF, dreamy
31const NX_APERTURE_F18: i64 = 2 // f/1.8 — shallow, bokeh
32const NX_APERTURE_F28: i64 = 3 // f/2.8 — soft separation
33const NX_APERTURE_F4: i64 = 4 // f/4 — moderate
34const NX_APERTURE_F56: i64 = 5 // f/5.6 — environmental in focus
35const NX_APERTURE_F8: i64 = 6 // f/8 — deep DoF, sharp throughout
36
37// Sealed composition enums.
38const NX_COMP_RULE_OF_THIRDS: i64 = 1
39const NX_COMP_CENTERED: i64 = 2
40const NX_COMP_LEADING_LINES: i64 = 3
41const NX_COMP_OFF_BALANCE: i64 = 4
42const NX_COMP_GOLDEN_SPIRAL: i64 = 5
43const NX_COMP_TRIANGULAR: i64 = 6
44
45// Sealed cinematography target — what scene is going for.
46const NX_CINE_TARGET_EDITORIAL: i64 = 1 // fashion-mag, refined, posed
47const NX_CINE_TARGET_CANDID: i64 = 2 // unposed, photojournalistic
48const NX_CINE_TARGET_FASHION: i64 = 3 // stylized, bold, fashion shoot
49const NX_CINE_TARGET_DOCUMENTARY: i64 = 4 // observational, real
50const NX_CINE_TARGET_CINEMATIC: i64 = 5 // moody, color-graded, film
51const NX_CINE_TARGET_GLAMOUR: i64 = 6 // soft, flattering, intimate
52
53const NX_CINE_RES_LENS_SCORE: i64 = 0
54const NX_CINE_RES_APERTURE_SCORE: i64 = 1
55const NX_CINE_RES_COMP_SCORE: i64 = 2
56const NX_CINE_RES_COMPOSITE: i64 = 3
57const NX_CINE_RES_VERDICT: i64 = 4
58const NX_CINE_RES_FAIL_AXIS: i64 = 5
59const NX_CINE_RES_FIELDS: i64 = 6
60
61const NX_CINE_V_LENS_WRONG: i64 = 0
62const NX_CINE_V_AMATEUR: i64 = 1
63const NX_CINE_V_PROFESSIONAL: i64 = 2
64const NX_CINE_V_AWARD_WORTHY: i64 = 3
65
66const NX_CINE_AXIS_LENS: i64 = 0
67const NX_CINE_AXIS_APERTURE: i64 = 1
68const NX_CINE_AXIS_COMPOSITION: i64 = 2
69
70// Score lens choice against target cinematography.
71func nx_cine_lens_score(target: i64, lens: i64) -> i64 {
72 if target == NX_CINE_TARGET_EDITORIAL {
73 if lens == NX_LENS_PORTRAIT_85MM { return NX_MAGIC_1024 }
74 if lens == NX_LENS_LONG_135MM { return 870 }
75 if lens == NX_LENS_NORMAL_50MM { return 614 }
76 return 256
77 }
78 if target == NX_CINE_TARGET_CANDID {
79 if lens == NX_LENS_NORMAL_50MM { return NX_MAGIC_1024 }
80 if lens == NX_LENS_WIDE_24MM { return 819 }
81 if lens == NX_LENS_PORTRAIT_85MM { return 614 }
82 return 410
83 }
84 if target == NX_CINE_TARGET_FASHION {
85 if lens == NX_LENS_PORTRAIT_85MM { return NX_MAGIC_1024 }
86 if lens == NX_LENS_LONG_135MM { return 870 }
87 if lens == NX_LENS_WIDE_24MM { return 768 } // dramatic editorial wide
88 return 410
89 }
90 if target == NX_CINE_TARGET_DOCUMENTARY {
91 if lens == NX_LENS_NORMAL_50MM { return NX_MAGIC_1024 }
92 if lens == NX_LENS_WIDE_24MM { return 870 }
93 return 410
94 }
95 if target == NX_CINE_TARGET_CINEMATIC {
96 if lens == NX_LENS_PORTRAIT_85MM { return NX_MAGIC_1024 }
97 if lens == NX_LENS_LONG_135MM { return 870 }
98 if lens == NX_LENS_WIDE_24MM { return 768 }
99 return 512
100 }
101 if target == NX_CINE_TARGET_GLAMOUR {
102 if lens == NX_LENS_PORTRAIT_85MM { return NX_MAGIC_1024 }
103 if lens == NX_LENS_LONG_135MM { return 870 }
104 if lens == NX_LENS_MACRO { return 768 }
105 return 410
106 }
107 return 614
108}
109
110// Score aperture choice against target.
111func nx_cine_aperture_score(target: i64, aperture: i64) -> i64 {
112 if target == NX_CINE_TARGET_EDITORIAL {
113 if aperture == NX_APERTURE_F28 { return NX_MAGIC_1024 }
114 if aperture == NX_APERTURE_F4 { return 870 }
115 if aperture == NX_APERTURE_F18 { return 870 }
116 return 410
117 }
118 if target == NX_CINE_TARGET_CANDID {
119 if aperture == NX_APERTURE_F28 { return NX_MAGIC_1024 }
120 if aperture == NX_APERTURE_F4 { return 870 }
121 if aperture == NX_APERTURE_F56 { return 768 }
122 return 614
123 }
124 if target == NX_CINE_TARGET_FASHION {
125 if aperture == NX_APERTURE_F18 { return NX_MAGIC_1024 }
126 if aperture == NX_APERTURE_F28 { return 870 }
127 return 410
128 }
129 if target == NX_CINE_TARGET_DOCUMENTARY {
130 if aperture == NX_APERTURE_F4 { return NX_MAGIC_1024 }
131 if aperture == NX_APERTURE_F56 { return 870 }
132 if aperture == NX_APERTURE_F8 { return 768 }
133 return 410
134 }
135 if target == NX_CINE_TARGET_CINEMATIC {
136 if aperture == NX_APERTURE_F14 { return NX_MAGIC_1024 }
137 if aperture == NX_APERTURE_F18 { return 920 }
138 if aperture == NX_APERTURE_F28 { return 768 }
139 return 410
140 }
141 if target == NX_CINE_TARGET_GLAMOUR {
142 if aperture == NX_APERTURE_F14 { return NX_MAGIC_1024 }
143 if aperture == NX_APERTURE_F18 { return 920 }
144 if aperture == NX_APERTURE_F28 { return 768 }
145 return 410
146 }
147 return 614
148}
149
150// Score composition choice against target.
151func nx_cine_composition_score(target: i64, composition: i64) -> i64 {
152 if target == NX_CINE_TARGET_EDITORIAL {
153 if composition == NX_COMP_CENTERED { return NX_MAGIC_1024 }
154 if composition == NX_COMP_RULE_OF_THIRDS { return 870 }
155 if composition == NX_COMP_TRIANGULAR { return 768 }
156 return 512
157 }
158 if target == NX_CINE_TARGET_CANDID {
159 if composition == NX_COMP_OFF_BALANCE { return NX_MAGIC_1024 }
160 if composition == NX_COMP_RULE_OF_THIRDS { return 870 }
161 return 614
162 }
163 if target == NX_CINE_TARGET_FASHION {
164 if composition == NX_COMP_CENTERED { return NX_MAGIC_1024 }
165 if composition == NX_COMP_GOLDEN_SPIRAL { return 870 }
166 if composition == NX_COMP_TRIANGULAR { return 768 }
167 return 410
168 }
169 if target == NX_CINE_TARGET_DOCUMENTARY {
170 if composition == NX_COMP_RULE_OF_THIRDS { return NX_MAGIC_1024 }
171 if composition == NX_COMP_LEADING_LINES { return 870 }
172 if composition == NX_COMP_OFF_BALANCE { return 768 }
173 return 410
174 }
175 if target == NX_CINE_TARGET_CINEMATIC {
176 if composition == NX_COMP_LEADING_LINES { return NX_MAGIC_1024 }
177 if composition == NX_COMP_RULE_OF_THIRDS { return 870 }
178 if composition == NX_COMP_GOLDEN_SPIRAL { return 920 }
179 return 410
180 }
181 if target == NX_CINE_TARGET_GLAMOUR {
182 if composition == NX_COMP_CENTERED { return NX_MAGIC_1024 }
183 if composition == NX_COMP_RULE_OF_THIRDS { return 870 }
184 return 614
185 }
186 return 614
187}
188
189// Composite cinematographer score: lens 35% + aperture 30% + composition 35%.
190func nx_cinematographer(target: i64, lens: i64, aperture: i64,
191 composition: i64, result: *i64) -> i64 {
192 var i: i64 = 0
193 while i < NX_CINE_RES_FIELDS { result[i] = 0; i = i + 1 }
194
195 let lens_s: i64 = nx_cine_lens_score(target, lens)
196 let ap_s: i64 = nx_cine_aperture_score(target, aperture)
197 let comp_s: i64 = nx_cine_composition_score(target, composition)
198 result[NX_CINE_RES_LENS_SCORE] = lens_s
199 result[NX_CINE_RES_APERTURE_SCORE] = ap_s
200 result[NX_CINE_RES_COMP_SCORE] = comp_s
201
202 let composite: i64 = (lens_s * 35 + ap_s * 30 + comp_s * 35) / 100
203 result[NX_CINE_RES_COMPOSITE] = composite
204
205 var verdict: i64 = NX_CINE_V_LENS_WRONG
206 if composite >= 410 { verdict = NX_CINE_V_AMATEUR }
207 if composite >= 614 { verdict = NX_CINE_V_PROFESSIONAL }
208 if composite >= 819 { verdict = NX_CINE_V_AWARD_WORTHY }
209 result[NX_CINE_RES_VERDICT] = verdict
210
211 var min_s: i64 = lens_s
212 var min_a: i64 = NX_CINE_AXIS_LENS
213 if ap_s < min_s { min_s = ap_s; min_a = NX_CINE_AXIS_APERTURE }
214 if comp_s < min_s { min_s = comp_s; min_a = NX_CINE_AXIS_COMPOSITION }
215 result[NX_CINE_RES_FAIL_AXIS] = min_a
216 return 0
217}