code wiki / _hdl_build / nx_reader_panels_gate.nx
nx_reader_panels_gate.nx source
↩ module page · 133 lines · 7338 B
1import "nx_gate_grow.nx"
2import "nx_gate_gn.nx"
3import "nx_gate_read.nx"
4// nx_reader_panels_gate.nx -- SOVEREIGN in-process referee for the panel detector (rp_detect/rp_emit). No
5// socket/shell: chdir /tmp, SYNTHESIZE comic pages in memory (white paper, dark panel rects with real gutters),
6// assert detection + reading order + the end-to-end JPEG->panels.json path + two NEGATIVE controls.
7// T1 2x2 grid page -> exactly 4 panels
8// T2 RTL reading order: first panel = TOP-RIGHT, rects within +/-8px of drawn (JPEG-free, pure rp_detect)
9// T3 LTR reading order: first panel = TOP-LEFT
10// T4 end-to-end: encode the page as a REAL baseline JPEG -> rp_emit -> panels.json has "n":4 + "rtl":1
11// T5 NEG blank page -> 0 panels (no fabricated panels on empty paper)
12// T6 NEG single full-bleed panel (margins, no gutters) -> exactly 1 panel, trimmed to the ink bbox
13// GREEN iff 6/6. license_tier: ORIGINAL expect_exit: 0
14import "nx_syscalls.nx"
15import "nx_reader_panels.nx" // rp_detect / rp_emit (+ transitively nx_img_bytes_to_rgb)
16import "nx_jpeg_color_write.nx"
17import "nx_quant_table.nx"
18import "nx_jpeg_huff_enc.nx"
19import "nx_zigzag.nx"
20import "nx_dct8.nx"
21
22func gw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
23func g_has(hay: *u8, n: i64, needle: *u8) -> i64 {
24 var nn: i64 = 0; while needle[nn] != (0 as u8) { nn = nn + 1 }
25 if nn == 0 { return 0 }
26 var i: i64 = 0
27 while i + nn <= n { var m: i64 = 1; var j: i64 = 0; while j < nn { if (hay[i + j] as i64) != (needle[j] as i64) { m = 0; j = nn } else { j = j + 1 } } if m == 1 { return 1 } i = i + 1 }
28 return 0
29}
30func g_near(a: i64, b: i64, tol: i64) -> i64 { var d: i64 = a - b; if d < 0 { d = 0 - d }; if d <= tol { return 1 } return 0 }
31
32// paint page white then fill rect [x,y,w,h] with dark gray (ink)
33func g_white(rgb: *u8, W: i64, H: i64) -> i64 {
34 var i: i64 = 0; let n: i64 = W * H * 3
35 while i < n { rgb[i] = 255 as u8; i = i + 1 }
36 return 0
37}
38func g_fill(rgb: *u8, W: i64, x: i64, y: i64, w2: i64, h2: i64) -> i64 {
39 var yy: i64 = y
40 while yy < y + h2 {
41 var xx: i64 = x
42 while xx < x + w2 {
43 let o: i64 = (yy * W + xx) * 3
44 rgb[o] = 60 as u8; rgb[o + 1] = 60 as u8; rgb[o + 2] = 60 as u8
45 xx = xx + 1
46 }
47 yy = yy + 1
48 }
49 return 0
50}
51
52func main() -> i64 {
53 gw("reader-panels SOVEREIGN in-process gate (synth comic pages -> detect + order + emit asserts)\n" as *u8)
54 if sys_chdir("/tmp" as *u8) != 0 { gw("CHDIR /tmp FAIL\n" as *u8); sys_exit(1) }
55 var pass: i64 = 0
56
57 // ---- the 2x2 test page: 800x592, panels (40,40,320,232) (440,40,320,232) (40,320,320,232) (440,320,320,232)
58 let W: i64 = 800; let H: i64 = 592
59 let rgb: *u8 = sys_mmap(W * H * 3 + 16)
60 g_white(rgb, W, H)
61 g_fill(rgb, W, 40, 40, 320, 232)
62 g_fill(rgb, W, 440, 40, 320, 232)
63 g_fill(rgb, W, 40, 320, 320, 232)
64 g_fill(rgb, W, 440, 320, 320, 232)
65
66 let pan: *i64 = sys_mmap(8 * 4 * 64) as *i64
67 let n1: i64 = rp_detect(rgb, W, H, 1, pan)
68 gw(" rtl detect n=" as *u8); gn(n1); gw(" p0=[" as *u8); gn(pan[0]); gw("," as *u8); gn(pan[1]); gw("," as *u8); gn(pan[2]); gw("," as *u8); gn(pan[3]); gw("]\n" as *u8)
69 pass = pass + grow("T1 2x2 grid -> exactly 4 panels\x00" as *u8, n1 == 4)
70
71 // rtl full order: p0=(440,40) TR, p1=(40,40) TL, p2=(440,320) BR, p3=(40,320) BL
72 var t2: i64 = 0
73 if n1 == 4 {
74 var okc: i64 = 1
75 if g_near(pan[0], 440, 8) == 0 { okc = 0 } // p0 x = TR
76 if g_near(pan[1], 40, 8) == 0 { okc = 0 } // p0 y
77 if g_near(pan[2], 320, 8) == 0 { okc = 0 } // p0 w
78 if g_near(pan[3], 232, 8) == 0 { okc = 0 } // p0 h
79 if g_near(pan[4], 40, 8) == 0 { okc = 0 } // p1 x = TL
80 if g_near(pan[8], 440, 8) == 0 { okc = 0 } // p2 x = BR
81 if g_near(pan[9], 320, 8) == 0 { okc = 0 } // p2 y = bottom band
82 if g_near(pan[12], 40, 8) == 0 { okc = 0 } // p3 x = BL
83 t2 = okc
84 }
85 pass = pass + grow("T2 RTL order = TR,TL,BR,BL + rects within +/-8px of drawn\x00" as *u8, t2)
86
87 let n2: i64 = rp_detect(rgb, W, H, 0, pan)
88 var t3: i64 = 0
89 if n2 == 4 { if g_near(pan[0], 40, 8) == 1 { if g_near(pan[4], 440, 8) == 1 { t3 = 1 } } }
90 pass = pass + grow("T3 LTR order = TL,TR first\x00" as *u8, t3)
91
92 // ---- T4 end-to-end via a REAL baseline JPEG ----
93 let dcB: *i64 = sys_mmap(20*8) as *i64; let dcV: *i64 = sys_mmap(20*8) as *i64
94 let acB: *i64 = sys_mmap(20*8) as *i64; let acV: *i64 = sys_mmap(200*8) as *i64
95 let ndc: i64 = jhe_dc_bits(dcB); jhe_dc_val(dcV); let nac: i64 = jhe_ac_bits(acB); jhe_ac_val(acV)
96 let dcCO: *i64 = sys_mmap(256*8) as *i64; let dcSI: *i64 = sys_mmap(256*8) as *i64
97 let acCO: *i64 = sys_mmap(256*8) as *i64; let acSI: *i64 = sys_mmap(256*8) as *i64
98 jhe_gen(dcB, dcV, ndc, dcCO, dcSI); jhe_gen(acB, acV, nac, acCO, acSI)
99 let qtL: *i64 = sys_mmap(64*8) as *i64; nx_qt_luma(qtL, 72)
100 let qtC: *i64 = sys_mmap(64*8) as *i64; nx_qt_chroma(qtC, 72)
101 let to_zz: *i64 = sys_mmap(64*8) as *i64; let from_zz: *i64 = sys_mmap(64*8) as *i64; nx_zigzag_init(to_zz, from_zz)
102 let DM: *i64 = sys_mmap(64*8) as *i64; nx_dct8_init(DM)
103 let scratch: *i64 = sys_mmap(64*8) as *i64; let tti: *i64 = sys_mmap(8*8) as *i64; let tto: *i64 = sys_mmap(8*8) as *i64
104 let jout: *u8 = sys_mmap(W * H * 3 + 8192)
105 let jlen: i64 = jcw_write_color(jout, W, H, rgb, qtL, qtC, dcB, dcV, acB, acV, dcCO, dcSI, acCO, acSI, to_zz, from_zz, DM, scratch, tti, tto)
106 let sfd: i64 = sys_openat_wr("rptest_src.jpg" as *u8, 0x1a4)
107 if sfd >= 0 { sys_write(sfd, jout, jlen); sys_close(sfd) }
108 let np4: i64 = rp_emit("rptest_src.jpg" as *u8, "rptest_out" as *u8, 1)
109 gw(" rp_emit np=" as *u8); gn(np4); gw("\n" as *u8)
110 var t4: i64 = 0
111 let mb: *u8 = sys_mmap(8192)
112 let mn: i64 = g_read("rptest_out/panels.json" as *u8, mb, 8192)
113 if np4 == 4 { if mn > 0 { if g_has(mb, mn, "\"n\":4" as *u8) == 1 { if g_has(mb, mn, "\"rtl\":1" as *u8) == 1 { t4 = 1 } } } }
114 pass = pass + grow("T4 real JPEG -> rp_emit -> panels.json n=4 rtl=1\x00" as *u8, t4)
115
116 // ---- T5 NEG blank page ----
117 g_white(rgb, W, H)
118 let n5: i64 = rp_detect(rgb, W, H, 1, pan)
119 pass = pass + grow("T5 NEG blank page -> 0 panels (no fabrication)\x00" as *u8, n5 == 0)
120
121 // ---- T6 NEG single full-bleed panel (margins, no gutters) -> 1 panel at the ink bbox ----
122 g_white(rgb, W, H)
123 g_fill(rgb, W, 40, 40, 720, 512)
124 let n6: i64 = rp_detect(rgb, W, H, 1, pan)
125 var t6: i64 = 0
126 if n6 == 1 { if g_near(pan[0], 40, 8) == 1 { if g_near(pan[1], 40, 8) == 1 { if g_near(pan[2], 720, 8) == 1 { if g_near(pan[3], 512, 8) == 1 { t6 = 1 } } } } }
127 gw(" fullbleed n=" as *u8); gn(n6); gw(" p0=[" as *u8); gn(pan[0]); gw("," as *u8); gn(pan[1]); gw("," as *u8); gn(pan[2]); gw("," as *u8); gn(pan[3]); gw("]\n" as *u8)
128 pass = pass + grow("T6 NEG no-gutter page -> exactly 1 panel trimmed to ink bbox\x00" as *u8, t6)
129
130 gw("pass=" as *u8); gn(pass); gw("/6\n" as *u8)
131 if pass == 6 { gw("verdict=GREEN (sovereign panel detection: otsu ink + interior gutter X-Y cut + banded RTL/LTR order + emit, fail-closed)\n" as *u8); sys_exit(0); return 0 }
132 gw("verdict=RED\n" as *u8); sys_exit(1); return 1
133}