code wiki / _hdl_build / nx_uiq_visual_lib.nx

nx_uiq_visual_lib.nx source

↩ module page · 180 lines · 8456 B

1// nx_uiq_visual_lib.nx -- SOVEREIGN visual-render metrics: the deterministic-pixel half of the 2// perceptual axis, computed on a REAL rendered PNG. Attacks the marker-vs-rendered gap no other 3// sovereign UI tool can (none execute CSS): a page that passes every structural/console check yet 4// renders BLANK (the banked "google scored 97% while rendering nothing" failure). DRY (rule 15): 5// reuses the shipped sovereign PNG decoder via nx_visual_diff's vd_load (VdImg{px,w,h,nc}) + its 6// vd_content_extent (rendered height / layout parity) -- ZERO new decode code. nx_png_write for KAT fixtures. 7// HONEST ENVELOPE (declared in output): measures the pixels of WHATEVER png it is given; render 8// FIDELITY is the input's property (a Chrome screenshot = real CSS/JS; the sovereign br_shot_png = no-JS). 9// Deterministic GUARDRAILS half; perceptual "premium" judging stays partnership-gated (VLM, will-not-fake). 10// license_tier: ORIGINAL genealogy: experiential visual; composes nx_visual_diff + nx_png_decoder + nx_png_write 11import "nx_visual_diff.nx" 12import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 13import "nx_png_write.nx" 14const UV_MAGIC_1024: i64 = 1024 15 16const UV_BLANK_PERMILLE: i64 = 20 17const UV_SPARSE_PERMILLE: i64 = 50 18const UV_INK_DELTA: i64 = 24 19const UV_STEP: i64 = 6 20 21func uv_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 22func uv_abs(v: i64) -> i64 { if v<0 { return 0-v } return v } 23func uv_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 24func uv_streq(s: *u8, sl: i64, lit: *u8) -> i64 { var i: i64=0; while lit[i]!=(0 as u8){ if i>=sl { return 0 } if s[i]!=lit[i] { return 0 } i=i+1 } if i!=sl { return 0 } return 1 } 25// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 26// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 27// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 28// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 29func uv_pn(v: i64) -> i64 { nxi_out(v); return 0 } 30func uv_catn(d: *u8, off: i64, v: i64) -> i64 { 31 let t: *u8 = sys_mmap(28); var m: i64=v; var o: i64=off; if m<0 { d[o]=45 as u8; o=o+1; m=0-m } 32 var k: i64=0; if m==0 { t[0]=48 as u8; k=1 } while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } 33 var i: i64=0; while i<k { d[o]=t[k-1-i]; o=o+1; i=i+1 } return o 34} 35func uv_cat(d: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; var o: i64=off; while s[i]!=(0 as u8){d[o]=s[i]; o=o+1; i=i+1} return o } 36 37// metrics over a VdImg: out[0]=ink_permille out[1]=distinct_colors out[2]=mean_lum out[3]=sampled_px 38func uv_metrics(im: *VdImg, out: *i64) -> i64 { 39 let w: i64 = im.w 40 let h: i64 = im.h 41 let nc: i64 = im.nc 42 let px: *u8 = im.px 43 out[0]=0; out[1]=0; out[2]=0; out[3]=0 44 if w<4 { return 0 } 45 if h<4 { return 0 } 46 let bo: i64 = (2*w + 2)*nc 47 let bR: i64 = px[bo] as i64 48 let bG: i64 = px[bo+1] as i64 49 let bB: i64 = px[bo+2] as i64 50 let seen: *u8 = sys_mmap(512) 51 var nonbg: i64=0 52 var tot: i64=0 53 var lum: i64=0 54 var y: i64=0 55 while y<h { 56 var x: i64=0 57 while x<w { 58 let o: i64 = (y*w + x)*nc 59 let R: i64 = px[o] as i64 60 let G: i64 = px[o+1] as i64 61 let B: i64 = px[o+2] as i64 62 tot=tot+1 63 lum = lum + (54*R + 183*G + 19*B)/256 64 let bk: i64 = (R>>5)*64 + (G>>5)*8 + (B>>5) 65 seen[bk]=1 as u8 66 let d: i64 = uv_abs(R-bR)+uv_abs(G-bG)+uv_abs(B-bB) 67 if d>UV_INK_DELTA { nonbg=nonbg+1 } 68 x=x+UV_STEP 69 } 70 y=y+UV_STEP 71 } 72 var ncnt: i64=0 73 var i: i64=0 74 while i<512 { if seen[i]==(1 as u8) { ncnt=ncnt+1 } i=i+1 } 75 if tot==0 { return 0 } 76 out[0] = 1000*nonbg/tot 77 out[1] = ncnt 78 out[2] = lum/tot 79 out[3] = tot 80 return 0 81} 82 83func uv_verdict(d: *u8, off: i64, ink: i64) -> i64 { 84 if ink<UV_BLANK_PERMILLE { return uv_cat(d, off, "BLANK-SUSPECT" as *u8) } 85 if ink<UV_SPARSE_PERMILLE { return uv_cat(d, off, "SPARSE" as *u8) } 86 return uv_cat(d, off, "RENDERED" as *u8) 87} 88 89// analyze a PNG path -> emit JSON (emit=1) ; returns ink_permille (or -1 on load failure) 90func uv_analyze(path: *u8, emit: i64) -> i64 { 91 let im: *VdImg = vd_load(path) 92 if (im as i64)==0 { 93 if emit==1 { uv_w("{\"organ\":\"nx_uiq_visual\",\"error\":\"cannot load/decode png (unsupported: Adam7 interlace or 16-bit depth (palette IS supported))\"}\n" as *u8) } 94 return 0-1 95 } 96 let out: *i64 = sys_mmap(64) as *i64 97 uv_metrics(im, out) 98 let ext: i64 = vd_content_extent(im, UV_INK_DELTA) 99 if emit==1 { 100 let jb: *u8 = sys_mmap(UV_MAGIC_1024) 101 var j: i64=0 102 j = uv_cat(jb, 0, "{\"organ\":\"nx_uiq_visual\",\"w\":" as *u8) 103 j = uv_catn(jb, j, im.w) 104 j = uv_cat(jb, j, ",\"h\":" as *u8) 105 j = uv_catn(jb, j, im.h) 106 j = uv_cat(jb, j, ",\"channels\":" as *u8) 107 j = uv_catn(jb, j, im.nc) 108 j = uv_cat(jb, j, ",\"ink_permille\":" as *u8) 109 j = uv_catn(jb, j, out[0]) 110 j = uv_cat(jb, j, ",\"distinct_colors\":" as *u8) 111 j = uv_catn(jb, j, out[1]) 112 j = uv_cat(jb, j, ",\"mean_lum\":" as *u8) 113 j = uv_catn(jb, j, out[2]) 114 j = uv_cat(jb, j, ",\"content_extent_px\":" as *u8) 115 j = uv_catn(jb, j, ext) 116 j = uv_cat(jb, j, ",\"sampled_px\":" as *u8) 117 j = uv_catn(jb, j, out[3]) 118 j = uv_cat(jb, j, ",\"verdict\":\"" as *u8) 119 j = uv_verdict(jb, j, out[0]) 120 j = uv_cat(jb, j, "\",\"env\":\"real-pixel;ink-vs-corner-bg;blank<2pct;sparse<5pct;render-fidelity=input-property;guardrails-not-perceptual-VLM\"}\n" as *u8) 121 sys_write(1, jb, j) 122 } 123 return out[0] 124} 125 126// ---- KAT fixtures: encode known RGB via the sovereign nx_png_write_rgb, decode+analyze, assert ---- 127func uv_mk_solid(path: *u8, w: i64, h: i64, r: i64, g: i64, b: i64) -> i64 { 128 let rgb: *u8 = sys_mmap(w*h*3 + 16) 129 var i: i64=0 130 while i<w*h { rgb[i*3]=r as u8; rgb[i*3+1]=g as u8; rgb[i*3+2]=b as u8; i=i+1 } 131 return nx_png_write_rgb(path, rgb, w, h) 132} 133// gradient over a BLACK corner (bg) = many colors, high ink 134func uv_mk_rich(path: *u8, w: i64, h: i64) -> i64 { 135 let rgb: *u8 = sys_mmap(w*h*3 + 16) 136 var y: i64=0 137 while y<h { var x: i64=0; while x<w { let o: i64=(y*w+x)*3; rgb[o]=(x*4) as u8; rgb[o+1]=(y*4) as u8; rgb[o+2]=((x+y)*2) as u8; x=x+1 } y=y+1 } 138 let s: i64=(2*w+2)*3; rgb[s]=0 as u8; rgb[s+1]=0 as u8; rgb[s+2]=0 as u8 139 rgb[0]=0 as u8; rgb[1]=0 as u8; rgb[2]=0 as u8 140 return nx_png_write_rgb(path, rgb, w, h) 141} 142// bg everywhere except a content band [y0,y1) -> exercises content_extent 143func uv_mk_band(path: *u8, w: i64, h: i64, y0: i64, y1: i64) -> i64 { 144 let rgb: *u8 = sys_mmap(w*h*3 + 16) 145 var y: i64=0 146 while y<h { var x: i64=0; while x<w { let o: i64=(y*w+x)*3; if y>=y0 { if y<y1 { rgb[o]=200 as u8; rgb[o+1]=50 as u8; rgb[o+2]=50 as u8 } else { rgb[o]=20 as u8; rgb[o+1]=20 as u8; rgb[o+2]=20 as u8 } } else { rgb[o]=20 as u8; rgb[o+1]=20 as u8; rgb[o+2]=20 as u8 } x=x+1 } y=y+1 } 147 return nx_png_write_rgb(path, rgb, w, h) 148} 149 150// selftest: encode->decode->analyze, assert blank vs rich discrimination + exact content extent. 0=GREEN. 151func uv_selftest() -> i64 { 152 var f: i64=0 153 uv_mk_rich("uiqviskat_rich.png" as *u8, 64, 64) 154 let ir: *VdImg = vd_load("uiqviskat_rich.png" as *u8) 155 if (ir as i64)==0 { return 99 } 156 let orr: *i64 = sys_mmap(64) as *i64 157 uv_metrics(ir, orr) 158 if orr[0]<500 { f=f+1 } 159 if orr[1]<8 { f=f+1 } 160 let er: i64 = vd_content_extent(ir, UV_INK_DELTA) 161 if er!=64 { f=f+1 } 162 uv_mk_solid("uiqviskat_blank.png" as *u8, 64, 64, 128, 128, 128) 163 let ib: *VdImg = vd_load("uiqviskat_blank.png" as *u8) 164 if (ib as i64)==0 { return 98 } 165 let ob: *i64 = sys_mmap(64) as *i64 166 uv_metrics(ib, ob) 167 if ob[0]!=0 { f=f+1 } 168 if ob[0]>=UV_BLANK_PERMILLE { f=f+1 } 169 let eb: i64 = vd_content_extent(ib, UV_INK_DELTA) 170 if eb!=0 { f=f+1 } 171 uv_mk_band("uiqviskat_band.png" as *u8, 64, 64, 16, 48) 172 let iband: *VdImg = vd_load("uiqviskat_band.png" as *u8) 173 if (iband as i64)==0 { return 97 } 174 let ext: i64 = vd_content_extent(iband, UV_INK_DELTA) 175 if ext!=48 { f=f+1 } 176 let oband: *i64 = sys_mmap(64) as *i64 177 uv_metrics(iband, oband) 178 if oband[0]<UV_SPARSE_PERMILLE { f=f+1 } 179 return f 180}