code wiki / _hdl_build / nx_look_compose.nx
nx_look_compose.nx source
↩ module page · 118 lines · 5856 B
1// nx_look_compose.nx -- SOVEREIGN composer for the LOOK gate (2026-07-29; retires compose.py per the
2// sovereign-no-python law: 3rd-party code is benchmark/oracle ONLY, never a lane instrument).
3// Reads THREE 8-bit grayscale BMPs (the nx_vcodec_look_dump output: SOURCE, arm A, arm B), writes ONE
4// composite grayscale BMP: the three panes side by side with a 4px white gutter, optionally a CROP of
5// each pane scaled 2x (nearest -- pixel truth, no resampling opinions). Browsers render BMP natively,
6// so the published review strip needs no PNG and no external encoder.
7// usage: nx_look_compose <src.bmp> <a.bmp> <b.bmp> <out.bmp> [x0 y0 cw ch]
8// no crop args -> full-frame strip; with crop args -> 2x-scaled crop strip.
9// CIF-class only (dimensions read from the BMP header; all three must match; width*panes padded to 4).
10// license: ORIGINAL
11import "nx_syscalls.nx"
12const LC_MAGIC_2835: i64 = 2835
13
14const LC_GUT: i64 = 4 // gutter px between panes (white)
15const LC_HDR: i64 = 1078 // 14 + 40 + 256*4 grayscale palette
16
17func gw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
18func gn(v: i64) -> i64 {
19 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m}
20 let t: *u8=sys_mmap(28); 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}
21 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
22func atoi(a: *u8) -> i64 { var v: i64=0; var i: i64=0
23 while a[i] != (0 as u8) { v = v*10 + ((a[i]&0xff)-48); i=i+1 } return v }
24func rd32le(b: *u8, off: i64) -> i64 {
25 return (b[off]&0xff) + ((b[off+1]&0xff)<<8) + ((b[off+2]&0xff)<<16) + ((b[off+3]&0xff)<<24) }
26func wr32le(b: *u8, off: i64, v: i64) -> i64 {
27 b[off]=(v&0xff) as u8; b[off+1]=((v>>8)&0xff) as u8
28 b[off+2]=((v>>16)&0xff) as u8; b[off+3]=((v>>24)&0xff) as u8; return 0 }
29func wr16le(b: *u8, off: i64, v: i64) -> i64 {
30 b[off]=(v&0xff) as u8; b[off+1]=((v>>8)&0xff) as u8; return 0 }
31
32// read one 8-bit BMP; returns TOP-DOWN luma buffer; wh[0]=w wh[1]=h; 0 on failure
33func bmp_read(path: *u8, wh: *i64) -> *u8 {
34 let box: *i64 = sys_mmap(16) as *i64
35 let d: *u8 = sys_read_file(path, box)
36 if (d as i64) == 0 { return 0 as *u8 }
37 if box[0] < LC_HDR { return 0 as *u8 }
38 if d[0] != (66 as u8) { return 0 as *u8 }
39 if d[1] != (77 as u8) { return 0 as *u8 }
40 let off: i64 = rd32le(d, 10)
41 let w: i64 = rd32le(d, 18)
42 let h: i64 = rd32le(d, 22)
43 if w <= 0 { return 0 as *u8 }
44 if h <= 0 { return 0 as *u8 }
45 if (w % 4) != 0 { gw("width must be /4 (unpadded rows)\n" as *u8); return 0 as *u8 }
46 let out: *u8 = sys_mmap(w*h + 64)
47 var y: i64 = 0
48 while y < h { var x: i64 = 0
49 while x < w { out[y*w + x] = d[off + (h-1-y)*w + x]; x = x + 1 } y = y + 1 }
50 wh[0] = w; wh[1] = h
51 return out }
52
53func bmp_write(path: *u8, luma: *u8, w: i64, h: i64) -> i64 {
54 let isz: i64 = w*h
55 let fsz: i64 = LC_HDR + isz
56 let buf: *u8 = sys_mmap(fsz + 64)
57 buf[0]=66 as u8; buf[1]=77 as u8
58 wr32le(buf, 2, fsz); wr32le(buf, 6, 0); wr32le(buf, 10, LC_HDR)
59 wr32le(buf, 14, 40); wr32le(buf, 18, w); wr32le(buf, 22, h)
60 wr16le(buf, 26, 1); wr16le(buf, 28, 8)
61 wr32le(buf, 30, 0); wr32le(buf, 34, isz)
62 wr32le(buf, 38, LC_MAGIC_2835); wr32le(buf, 42, LC_MAGIC_2835)
63 wr32le(buf, 46, 256); wr32le(buf, 50, 0)
64 var c: i64=0
65 while c<256 { let o: i64=54+c*4
66 buf[o]=c as u8; buf[o+1]=c as u8; buf[o+2]=c as u8; buf[o+3]=0 as u8; c=c+1 }
67 var y: i64=0
68 while y<h { var x: i64=0
69 while x<w { buf[LC_HDR + (h-1-y)*w + x] = luma[y*w + x]; x=x+1 } y=y+1 }
70 let fd: i64 = sys_openat_wr(path, 0x1a4)
71 if fd < 0 { gw("out open fail\n" as *u8); return 1 }
72 sys_write(fd, buf, fsz)
73 sys_close(fd)
74 return 0 }
75
76func main(argc: i64, argv: *i64) -> i64 {
77 if argc < 5 { gw("usage: nx_look_compose <src.bmp> <a.bmp> <b.bmp> <out.bmp> [x0 y0 cw ch]\n" as *u8); return 1 }
78 let wh: *i64 = sys_mmap(32) as *i64
79 let ps: *u8 = bmp_read(argv[1] as *u8, wh)
80 let W: i64 = wh[0]; let H: i64 = wh[1]
81 let pa: *u8 = bmp_read(argv[2] as *u8, wh)
82 if wh[0] != W { gw("dim mismatch a\n" as *u8); return 1 }
83 let pb: *u8 = bmp_read(argv[3] as *u8, wh)
84 if wh[0] != W { gw("dim mismatch b\n" as *u8); return 1 }
85 if (ps as i64)==0 { gw("read fail src\n" as *u8); return 1 }
86 if (pa as i64)==0 { gw("read fail a\n" as *u8); return 1 }
87 if (pb as i64)==0 { gw("read fail b\n" as *u8); return 1 }
88 // pane geometry: full frame, or 2x crop
89 var px: i64 = 0
90 var py: i64 = 0
91 var pw: i64 = W
92 var ph: i64 = H
93 var sc: i64 = 1
94 if argc >= 9 { px = atoi(argv[5] as *u8); py = atoi(argv[6] as *u8)
95 pw = atoi(argv[7] as *u8); ph = atoi(argv[8] as *u8); sc = 2
96 if px + pw > W { gw("crop x overflow\n" as *u8); return 1 }
97 if py + ph > H { gw("crop y overflow\n" as *u8); return 1 } }
98 let ow0: i64 = pw*sc*3 + LC_GUT*2
99 let ow: i64 = ((ow0 + 3) / 4) * 4 // BMP rows pad to 4; we pad the CANVAS instead (white)
100 let oh: i64 = ph*sc
101 let canvas: *u8 = sys_mmap(ow*oh + 64)
102 var i: i64 = 0
103 while i < ow*oh { canvas[i] = 255 as u8; i = i + 1 }
104 var pane: i64 = 0
105 while pane < 3 {
106 var src: *u8 = ps
107 if pane == 1 { src = pa }
108 if pane == 2 { src = pb }
109 let ox: i64 = pane * (pw*sc + LC_GUT)
110 var y: i64 = 0
111 while y < ph*sc { var x: i64 = 0
112 while x < pw*sc {
113 canvas[y*ow + ox + x] = src[(py + y/sc)*W + px + x/sc]
114 x = x + 1 } y = y + 1 }
115 pane = pane + 1 }
116 if bmp_write(argv[4] as *u8, canvas, ow, oh) != 0 { return 1 }
117 gw("LOOK-COMPOSE OK " as *u8); gn(ow); gw("x" as *u8); gn(oh); gw(" panes=SRC|A|B scale=" as *u8); gn(sc); gw("\n" as *u8)
118 return 0 }