code wiki / _hdl_build / nx_colorspace_gate.nx

nx_colorspace_gate.nx source

↩ module page · 69 lines · 4295 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" 11 12func g_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 13func 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 } 14 15func main() -> i64 { 16 g_puts("nx_colorspace gate (sovereign RGB<->YCbCr + 4:2:0, MEASURED)\n" as *u8) 17 var pass: i64 = 0; var total: i64 = 0 18 19 let W: i64 = 8; let H: i64 = 8; let n: i64 = W*H 20 let r: *u8 = sys_mmap(n); let g: *u8 = sys_mmap(n); let b: *u8 = sys_mmap(n) 21 let y: *u8 = sys_mmap(n); let cb: *u8 = sys_mmap(n); let cr: *u8 = sys_mmap(n) 22 let r2: *u8 = sys_mmap(n); let g2: *u8 = sys_mmap(n); let b2: *u8 = sys_mmap(n) 23 24 // a varied colour image 25 var i: i64 = 0 26 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 } 27 28 // 1) round-trip 29 cs_rgb_to_yuv(r, g, b, n, y, cb, cr) 30 cs_yuv_to_rgb(y, cb, cr, n, r2, g2, b2) 31 let er: i64 = planemax(r, r2, n); let eg: i64 = planemax(g, g2, n); let eb: i64 = planemax(b, b2, n) 32 var emax: i64 = er; if eg > emax { emax = eg } if eb > emax { emax = eb } 33 g_puts(" [measure] RGB round-trip max error = " as *u8); g_pn(emax); g_puts(" (0-255 scale)\n" as *u8) 34 pass = pass + g_check("RGB->YCbCr->RGB round-trip bounded (<= 8)" as *u8, emax <= 8); total=total+1 35 36 // 2) neutral gray 37 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 } 38 cs_rgb_to_yuv(r, g, b, n, y, cb, cr) 39 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) 40 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 41 42 // 3) pure red 43 k = 0; while k < n { r[k]=255 as u8; g[k]=0 as u8; b[k]=0 as u8; k=k+1 } 44 cs_rgb_to_yuv(r, g, b, n, y, cb, cr) 45 cs_yuv_to_rgb(y, cb, cr, n, r2, g2, b2) 46 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) 47 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 48 49 // 4) 4:2:0 on a smooth chroma plane 50 let hf: *u8 = sys_mmap(n) // smooth full-res chroma 51 let half: *u8 = sys_mmap(n/4) 52 let up: *u8 = sys_mmap(n) 53 var yy: i64 = 0 54 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 55 cs_subsample(hf, W, H, half) 56 cs_upsample(half, W, H, up) 57 let ce: i64 = planemax(hf, up, n) 58 g_puts(" [measure] 4:2:0 chroma subsample->upsample max error = " as *u8); g_pn(ce); g_puts(" (smooth chroma)\n" as *u8) 59 pass = pass + g_check("4:2:0 on smooth chroma near-lossless (<= 4)" as *u8, ce <= 4); total=total+1 60 61 // 5) anti-tautology: red vs blue 62 let yr: i64 = cs_y(255,0,0); let cbr: i64 = cs_cb(255,0,0); let crr: i64 = cs_cr(255,0,0) 63 let ybl: i64 = cs_y(0,0,255); let cbbl: i64 = cs_cb(0,0,255); let crbl: i64 = cs_cr(0,0,255) 64 pass = pass + g_check("anti-tautology: red YCbCr != blue YCbCr" as *u8, (cbr != cbbl) & (crr != crbl)); total=total+1 65 66 g_puts("---- colorspace gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 67 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 68 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 69}