code wiki / (root) / nx_quality_driver.nx

nx_quality_driver.nx source

↩ module page · 100 lines · 3379 B

1// nx_quality_driver.nx -- MINIMAL substrate driver: real image -> verdict JSON. 2// 3// Reads /tmp/nx_img.raw (24-byte LE header + raw RGB bytes), runs the 4// safest detectors that don't trip the codegen bug (single function call, 5// no struct returns mid-chain), emits JSON to stdout. svc-quality 6// invokes this as a subprocess per render. 7// 8// Inline-in-main pattern because nxc2 codegen bug forbids the wrapper 9// pattern for some detector compositions. The driver does each detector 10// inline; result fields packed into one flat-array and printed as JSON. 11// 12// Output: 13// {"palette_kind":N,"warm_q10":N,"saturation_q10":N,"mean_r":N,"mean_g":N,"mean_b":N,"image_w":N,"image_h":N} 14 15// nx_safety_envelope: 16// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 17// sil_target: SIL1 18// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 19// verdict: NOT_YET_EVALUATED 20 21import "nx_syscalls.nx" 22import "nx_image.nx" 23import "nx_image_load_raw.nx" 24import "nx_color_palette.nx" 25const K_MAGIC_2048: i64 = 2048 26 27// Write null-terminated key string into buf at pos. Returns new pos. 28func nx_qd_puts(buf: *u8, pos: i64, s: *u8) -> i64 { 29 var p: i64 = pos 30 var i: i64 = 0 31 while s[i] != 0 { 32 buf[p] = s[i] 33 p = p + 1 34 i = i + 1 35 } 36 return p 37} 38 39// Write i64 as decimal to buf. Returns new pos. 40func nx_qd_putint(buf: *u8, pos: i64, v: i64) -> i64 { 41 if v == 0 { buf[pos] = 48; return pos + 1 } 42 var n: i64 = v 43 var p: i64 = pos 44 if n < 0 { buf[p] = 45; p = p + 1; n = -n } 45 let start: i64 = p 46 while n > 0 { 47 let d: i64 = n - (n / 10) * 10 48 buf[p] = 48 + d 49 p = p + 1 50 n = n / 10 51 } 52 var a: i64 = start 53 var b: i64 = p - 1 54 while a < b { 55 let t: i64 = buf[a] 56 buf[a] = buf[b] 57 buf[b] = t 58 a = a + 1 59 b = b - 1 60 } 61 return p 62} 63 64func main() -> i64 { 65 let path: *u8 = "/tmp/nx_img.raw" 66 let img: *Image = nx_image_load_raw(path) 67 if img == (0 as *Image) { 68 let err: *u8 = "{\"error\":\"image_load_failed\"}\n" 69 let len_e: *i64 = (sys_mmap(8 + 8)) as *i64 70 sys_read_file(err, len_e) // hack: use sys_write would be cleaner 71 return 1 72 } 73 74 // Run color palette classifier inline. 75 let pal_res: *i64 = (sys_mmap(NX_PAL_RES_FIELDS * 8 + 16)) as *i64 76 nx_color_palette(img, pal_res) 77 78 // Build JSON output in a buffer. 79 let out: *u8 = sys_mmap(K_MAGIC_2048) 80 var p: i64 = 0 81 p = nx_qd_puts(out, p, "{\"image_w\":") 82 p = nx_qd_putint(out, p, img.width) 83 p = nx_qd_puts(out, p, ",\"image_h\":") 84 p = nx_qd_putint(out, p, img.height) 85 p = nx_qd_puts(out, p, ",\"palette_kind\":") 86 p = nx_qd_putint(out, p, pal_res[NX_PAL_RES_KIND]) 87 p = nx_qd_puts(out, p, ",\"warm_q10\":") 88 p = nx_qd_putint(out, p, pal_res[NX_PAL_RES_WARM_Q10]) 89 p = nx_qd_puts(out, p, ",\"saturation_q10\":") 90 p = nx_qd_putint(out, p, pal_res[NX_PAL_RES_SAT_Q10]) 91 p = nx_qd_puts(out, p, ",\"mean_r\":") 92 p = nx_qd_putint(out, p, pal_res[NX_PAL_RES_MEAN_R]) 93 p = nx_qd_puts(out, p, ",\"mean_g\":") 94 p = nx_qd_putint(out, p, pal_res[NX_PAL_RES_MEAN_G]) 95 p = nx_qd_puts(out, p, ",\"mean_b\":") 96 p = nx_qd_putint(out, p, pal_res[NX_PAL_RES_MEAN_B]) 97 p = nx_qd_puts(out, p, "}\n") 98 sys_write(1, out, p) 99 return 0 100}