code wiki / _hdl_build / nx_colorspace_gate.nx
nx_colorspace_gate.nx source
↩ module page · 77 lines · 4739 B
1// nx_colorspace_gate.nx -- proves + MEASURES sovereign RGB<->YCbCr + 4:2:0 (nx_colorspace). Native, no node.
2// 1) round-trip RGB->YCbCr->RGB within a bounded integer error (MEASURED)
3// 2) neutral gray -> Cb=Cr=128 (correct chroma centering)
4// 3) pure red -> Cr>128 (red chroma) + round-trips back to red
5// 4) 4:2:0 subsample->upsample on smooth chroma is near-lossless (MEASURED)
6// 5) anti-tautology: distinct colours -> distinct YCbCr
7// license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_gate_emit_lib.nx"
10import "nx_colorspace.nx"
11import "nx_gate_verdict.nx"
12
13func g_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
14func planemax(a: *u8, b: *u8, n: i64) -> i64 { var m: i64=0; var i: i64=0; while i<n { let e: i64=g_abs((a[i] as i64)-(b[i] as i64)); if e>m { m=e } i=i+1 } return m }
15
16func main() -> i64 {
17 g_puts("nx_colorspace gate (sovereign RGB<->YCbCr + 4:2:0, MEASURED)\n" as *u8)
18 var pass: i64 = 0; var total: i64 = 0
19
20 let W: i64 = 8; let H: i64 = 8; let n: i64 = W*H
21 let r: *u8 = sys_mmap(n); let g: *u8 = sys_mmap(n); let b: *u8 = sys_mmap(n)
22 let y: *u8 = sys_mmap(n); let cb: *u8 = sys_mmap(n); let cr: *u8 = sys_mmap(n)
23 let r2: *u8 = sys_mmap(n); let g2: *u8 = sys_mmap(n); let b2: *u8 = sys_mmap(n)
24
25 // a varied colour image
26 var i: i64 = 0
27 while i < n { r[i] = ((i*4) & 0xff) as u8; g[i] = ((255 - i*3) & 0xff) as u8; b[i] = ((i*9 + 30) & 0xff) as u8; i = i + 1 }
28
29 // 1) round-trip
30 cs_rgb_to_yuv(r, g, b, n, y, cb, cr)
31 cs_yuv_to_rgb(y, cb, cr, n, r2, g2, b2)
32 let er: i64 = planemax(r, r2, n); let eg: i64 = planemax(g, g2, n); let eb: i64 = planemax(b, b2, n)
33 var emax: i64 = er; if eg > emax { emax = eg } if eb > emax { emax = eb }
34 g_puts(" [measure] RGB round-trip max error = " as *u8); g_pn(emax); g_puts(" (0-255 scale)\n" as *u8)
35 pass = pass + g_check("RGB->YCbCr->RGB round-trip bounded (<= 8)" as *u8, emax <= 8); total=total+1
36
37 // 2) neutral gray
38 var k: i64 = 0; while k < n { r[k]=100 as u8; g[k]=100 as u8; b[k]=100 as u8; k=k+1 }
39 cs_rgb_to_yuv(r, g, b, n, y, cb, cr)
40 g_puts(" [measure] gray(100): Y=" as *u8); g_pn(y[0] as i64); g_puts(" Cb=" as *u8); g_pn(cb[0] as i64); g_puts(" Cr=" as *u8); g_pn(cr[0] as i64); g_puts("\n" as *u8)
41 pass = pass + g_check("neutral gray -> Cb=Cr=128 (centered chroma)" as *u8, (cb[0]==(128 as u8)) & (cr[0]==(128 as u8)) & (g_abs((y[0] as i64)-100)<=1)); total=total+1
42
43 // 3) pure red
44 k = 0; while k < n { r[k]=255 as u8; g[k]=0 as u8; b[k]=0 as u8; k=k+1 }
45 cs_rgb_to_yuv(r, g, b, n, y, cb, cr)
46 cs_yuv_to_rgb(y, cb, cr, n, r2, g2, b2)
47 g_puts(" [measure] red(255,0,0) -> Cr=" as *u8); g_pn(cr[0] as i64); g_puts(" round-trips to R=" as *u8); g_pn(r2[0] as i64); g_puts(" G=" as *u8); g_pn(g2[0] as i64); g_puts(" B=" as *u8); g_pn(b2[0] as i64); g_puts("\n" as *u8)
48 pass = pass + g_check("red -> Cr>128 + round-trips back to red" as *u8, ((cr[0] as i64) > 128) & ((r2[0] as i64) > 200) & ((g2[0] as i64) < 50) & ((b2[0] as i64) < 50)); total=total+1
49
50 // 4) 4:2:0 on a smooth chroma plane
51 let hf: *u8 = sys_mmap(n) // smooth full-res chroma
52 let half: *u8 = sys_mmap(n/4)
53 let up: *u8 = sys_mmap(n)
54 var yy: i64 = 0
55 while yy < H { var xx: i64 = 0; while xx < W { hf[yy*W+xx] = (110 + xx + yy) as u8; xx=xx+1 } yy=yy+1 } // smooth gradient
56 cs_subsample(hf, W, H, half)
57 cs_upsample(half, W, H, up)
58 let ce: i64 = planemax(hf, up, n)
59 g_puts(" [measure] 4:2:0 chroma subsample->upsample max error = " as *u8); g_pn(ce); g_puts(" (smooth chroma)\n" as *u8)
60 pass = pass + g_check("4:2:0 on smooth chroma near-lossless (<= 4)" as *u8, ce <= 4); total=total+1
61
62 // 5) anti-tautology: red vs blue
63 let yr: i64 = cs_y(255,0,0); let cbr: i64 = cs_cb(255,0,0); let crr: i64 = cs_cr(255,0,0)
64 let ybl: i64 = cs_y(0,0,255); let cbbl: i64 = cs_cb(0,0,255); let crbl: i64 = cs_cr(0,0,255)
65 pass = pass + g_check("anti-tautology: red YCbCr != blue YCbCr" as *u8, (cbr != cbbl) & (crr != crbl)); total=total+1
66
67 g_puts("---- colorspace gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8)
68 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
69 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
70 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
71 let ctr__dry: *i64 = gv_ctr()
72 ctr__dry[0] = pass
73 ctr__dry[1] = total
74 let rc__dry: i64 = gv_verdict("COLORSPACE-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
75 sys_exit(rc__dry)
76 return rc__dry
77}