code wiki / _hdl_build / nx_bmp_tiff_gate.nx
nx_bmp_tiff_gate.nx source
↩ module page · 346 lines · 15106 B
1// nx_bmp_tiff_gate.nx -- gate for C4 of the codec-chokepoint program (debt 1785903075): BMP READER
2// (1/8/24-bit, RLE8, bottom-up AND top-down) + baseline TIFF READER (LE+BE, strips, none+PackBits,
3// gray/RGB/palette) + chokepoint wiring. Fixtures are hand-assembled byte-exact files; the LZW tooth
4// proves the TIFF reader REFUSES what it cannot decode instead of emitting a wrong image; the BMP
5// witness is a real on-disk screenshot from the nishi-os lane. Inherits nx_gate_verdict.
6// license_tier: ORIGINAL expect_exit: 0
7import "nx_syscalls.nx"
8import "nx_gate_verdict.nx"
9import "nx_bmp_decode.nx"
10import "nx_tiff_decode.nx"
11import "nx_img_bytes_to_rgb.nx"
12import "nx_image.nx"
13import "nx_bmp.nx"
14
15func bt_w16(b: *u8, o: i64, v: i64) -> i64 { b[o]=(v&255) as u8; b[o+1]=((v>>8)&255) as u8; return o+2 }
16func bt_w32(b: *u8, o: i64, v: i64) -> i64 { b[o]=(v&255) as u8; b[o+1]=((v>>8)&255) as u8; b[o+2]=((v>>16)&255) as u8; b[o+3]=((v>>24)&255) as u8; return o+4 }
17// endian-aware writers for TIFF (le==1 little, else big)
18func bt_e16(b: *u8, o: i64, v: i64, le: i64) -> i64 { if le==1 { return bt_w16(b,o,v) } b[o]=((v>>8)&255) as u8; b[o+1]=(v&255) as u8; return o+2 }
19func bt_e32(b: *u8, o: i64, v: i64, le: i64) -> i64 { if le==1 { return bt_w32(b,o,v) } b[o]=((v>>24)&255) as u8; b[o+1]=((v>>16)&255) as u8; b[o+2]=((v>>8)&255) as u8; b[o+3]=(v&255) as u8; return o+4 }
20// one 12-byte IFD entry
21func bt_ent(b: *u8, o: i64, tag: i64, ty: i64, cnt: i64, val: i64, le: i64) -> i64 {
22 var p: i64=bt_e16(b,o,tag,le)
23 p=bt_e16(b,p,ty,le)
24 p=bt_e32(b,p,cnt,le)
25 // SHORT single values sit in the HIGH-ORDER position of the 4-byte field per spec:
26 // for LE that is bytes 0-1; for BE it is ALSO bytes 0-1 (left-justified).
27 if ty==3 { if cnt==1 { p=bt_e16(b,p,val,le); p=bt_e16(b,p,0,le); return p } }
28 p=bt_e32(b,p,val,le)
29 return p
30}
31
32// BMP header for uncompressed fixtures
33func bt_bmp_hdr(b: *u8, w: i64, h: i64, bits: i64, comp: i64, data_off: i64, imgsz: i64) -> i64 {
34 b[0]=0x42 as u8; b[1]=0x4D as u8
35 bt_w32(b,2,data_off+imgsz)
36 bt_w32(b,6,0)
37 bt_w32(b,10,data_off)
38 bt_w32(b,14,40)
39 bt_w32(b,18,w)
40 var hv: i64=h
41 if hv<0 { hv=hv+4294967296 }
42 bt_w32(b,22,hv)
43 bt_w16(b,26,1)
44 bt_w16(b,28,bits)
45 bt_w32(b,30,comp)
46 bt_w32(b,34,imgsz)
47 bt_w32(b,38,0); bt_w32(b,42,0); bt_w32(b,46,0); bt_w32(b,50,0)
48 return 54
49}
50
51func main() -> i64 {
52 let ctr: *i64 = gv_ctr()
53 gv_head("nx_bmp_tiff_gate -- BMP reader + baseline TIFF reader + chokepoint (C4)" as *u8)
54
55 // ---------- T1: 24-bit bottom-up BMP, 4x2 ----------
56 // display: row0 = (10,20,30)(11,21,31)(12,22,32)(13,23,33); row1 = (200,150,100)(201,151,101)...
57 // stored bottom-up: file rows = display row1 then row0, BGR, stride 4*3=12 (already 4-aligned)
58 let bmp1: *u8=sys_mmap(256)
59 bt_bmp_hdr(bmp1, 4, 2, 24, 0, 54, 24)
60 var o1: i64=54
61 var fx: i64=0
62 while fx<4 { bmp1[o1]=(100+fx) as u8; bmp1[o1+1]=(150+fx) as u8; bmp1[o1+2]=(200+fx) as u8; o1=o1+3; fx=fx+1 }
63 fx=0
64 while fx<4 { bmp1[o1]=(30+fx) as u8; bmp1[o1+1]=(20+fx) as u8; bmp1[o1+2]=(10+fx) as u8; o1=o1+3; fx=fx+1 }
65 let wh1: *i64=sys_mmap(32) as *i64
66 let r1: *u8=bmp_decode_rgb(bmp1, o1, wh1)
67 var t1: i64=0
68 if r1!=(0 as *u8) { if wh1[0]==4 { if wh1[1]==2 {
69 var ok1: i64=1
70 if (r1[0] as i64)!=10 { ok1=0 }
71 if (r1[1] as i64)!=20 { ok1=0 }
72 if (r1[2] as i64)!=30 { ok1=0 }
73 if (r1[9] as i64)!=13 { ok1=0 }
74 if (r1[12] as i64)!=200 { ok1=0 }
75 if (r1[13] as i64)!=150 { ok1=0 }
76 if (r1[14] as i64)!=100 { ok1=0 }
77 if (r1[21] as i64)!=203 { ok1=0 }
78 t1=ok1
79 } } }
80 gv_check("T1 BMP 24-bit bottom-up decode (flip + BGR->RGB KAT)" as *u8, t1, ctr)
81
82 // ---------- T2: top-down 24-bit (negative height) with the SAME display image ----------
83 let bmp2: *u8=sys_mmap(256)
84 bt_bmp_hdr(bmp2, 4, 0-2, 24, 0, 54, 24)
85 var o2: i64=54
86 fx=0
87 while fx<4 { bmp2[o2]=(30+fx) as u8; bmp2[o2+1]=(20+fx) as u8; bmp2[o2+2]=(10+fx) as u8; o2=o2+3; fx=fx+1 }
88 fx=0
89 while fx<4 { bmp2[o2]=(100+fx) as u8; bmp2[o2+1]=(150+fx) as u8; bmp2[o2+2]=(200+fx) as u8; o2=o2+3; fx=fx+1 }
90 let wh2: *i64=sys_mmap(32) as *i64
91 let r2: *u8=bmp_decode_rgb(bmp2, o2, wh2)
92 var t2: i64=0
93 if r2!=(0 as *u8) { if r1!=(0 as *u8) {
94 var same2: i64=1
95 var q2: i64=0
96 while q2<24 { if r1[q2]!=r2[q2] { same2=0; q2=24 } else { q2=q2+1 } }
97 t2=same2
98 } }
99 gv_check("T2 BMP top-down (negative height) decodes identical image" as *u8, t2, ctr)
100
101 // ---------- T3: 8-bit palette BMP, 4x1 ----------
102 // palette: idx0=(250,10,5) idx1=(1,2,3) idx2=(90,91,92) idx3=(7,8,9) (stored BGRA)
103 let bmp3: *u8=sys_mmap(256)
104 bt_bmp_hdr(bmp3, 4, 1, 8, 0, 54+16, 4)
105 bt_w32(bmp3, 46, 4)
106 var o3: i64=54
107 bmp3[o3]=5 as u8; bmp3[o3+1]=10 as u8; bmp3[o3+2]=250 as u8; bmp3[o3+3]=0 as u8
108 bmp3[o3+4]=3 as u8; bmp3[o3+5]=2 as u8; bmp3[o3+6]=1 as u8; bmp3[o3+7]=0 as u8
109 bmp3[o3+8]=92 as u8; bmp3[o3+9]=91 as u8; bmp3[o3+10]=90 as u8; bmp3[o3+11]=0 as u8
110 bmp3[o3+12]=9 as u8; bmp3[o3+13]=8 as u8; bmp3[o3+14]=7 as u8; bmp3[o3+15]=0 as u8
111 o3=o3+16
112 bmp3[o3]=3 as u8; bmp3[o3+1]=0 as u8; bmp3[o3+2]=2 as u8; bmp3[o3+3]=1 as u8
113 o3=o3+4
114 let wh3: *i64=sys_mmap(32) as *i64
115 let r3: *u8=bmp_decode_rgb(bmp3, o3, wh3)
116 var t3: i64=0
117 if r3!=(0 as *u8) { if wh3[0]==4 { if wh3[1]==1 {
118 var ok3: i64=1
119 if (r3[0] as i64)!=7 { ok3=0 }
120 if (r3[3] as i64)!=250 { ok3=0 }
121 if (r3[4] as i64)!=10 { ok3=0 }
122 if (r3[6] as i64)!=90 { ok3=0 }
123 if (r3[11] as i64)!=3 { ok3=0 }
124 t3=ok3
125 } } }
126 gv_check("T3 BMP 8-bit palette decode KAT" as *u8, t3, ctr)
127
128 // ---------- T4: RLE8 BMP, 6x2: run + absolute + EOL + EOD ----------
129 // display row0 (stored second, bottom-up): AA AA AA 01 02 03 ; row1: BB x6
130 let bmp4: *u8=sys_mmap(512)
131 bt_bmp_hdr(bmp4, 6, 2, 8, 1, 54+1024, 64)
132 // palette: 256 entries, entry i = (i,i,i) gray so index==value
133 var pi4: i64=0
134 while pi4<256 { let po4: i64=54+pi4*4; bmp4[po4]=pi4 as u8; bmp4[po4+1]=pi4 as u8; bmp4[po4+2]=pi4 as u8; bmp4[po4+3]=0 as u8; pi4=pi4+1 }
135 var o4: i64=54+1024
136 // bottom-up: first encoded row = display row1: run of 6 x 0xBB, EOL
137 bmp4[o4]=6 as u8; bmp4[o4+1]=0xBB as u8; o4=o4+2
138 bmp4[o4]=0 as u8; bmp4[o4+1]=0 as u8; o4=o4+2
139 // second encoded row = display row0: run 3 x 0xAA, absolute 3: 01 02 03 (pad), EOD
140 bmp4[o4]=3 as u8; bmp4[o4+1]=0xAA as u8; o4=o4+2
141 bmp4[o4]=0 as u8; bmp4[o4+1]=3 as u8; bmp4[o4+2]=1 as u8; bmp4[o4+3]=2 as u8; bmp4[o4+4]=3 as u8; bmp4[o4+5]=0 as u8; o4=o4+6
142 bmp4[o4]=0 as u8; bmp4[o4+1]=1 as u8; o4=o4+2
143 let wh4: *i64=sys_mmap(32) as *i64
144 let r4: *u8=bmp_decode_rgb(bmp4, o4, wh4)
145 var t4: i64=0
146 if r4!=(0 as *u8) { if wh4[0]==6 { if wh4[1]==2 {
147 var ok4: i64=1
148 if (r4[0] as i64)!=170 { ok4=0 }
149 if (r4[2*3] as i64)!=170 { ok4=0 }
150 if (r4[3*3] as i64)!=1 { ok4=0 }
151 if (r4[4*3] as i64)!=2 { ok4=0 }
152 if (r4[5*3] as i64)!=3 { ok4=0 }
153 if (r4[6*3] as i64)!=187 { ok4=0 }
154 if (r4[11*3] as i64)!=187 { ok4=0 }
155 t4=ok4
156 } } }
157 gv_check("T4 BMP RLE8 decode (run + absolute + EOL + EOD)" as *u8, t4, ctr)
158
159 // ---------- T5 BITE: truncated BMP refused, intact decodes ----------
160 var b5bad: i64=0
161 let wh5: *i64=sys_mmap(32) as *i64
162 let r5: *u8=bmp_decode_rgb(bmp1, 40, wh5)
163 if r5==(0 as *u8) { b5bad=1 }
164 var b5good: i64=0
165 if r1==(0 as *u8) { b5good=1 }
166 gv_bite("T5 truncated-BMP refusal" as *u8, b5bad, b5good, ctr)
167
168 // ---------- T6: LE TIFF RGB8, 4x2, TWO strips (rps=1), uncompressed ----------
169 let tif1: *u8=sys_mmap(1024)
170 tif1[0]=0x49 as u8; tif1[1]=0x49 as u8; tif1[2]=0x2A as u8; tif1[3]=0x00 as u8
171 bt_w32(tif1,4,32)
172 // strip0 @8 = row0: (60+x, 61+x, 62+x); strip1 @20 = row1: (5+x, 6+x, 7+x)
173 var sx6: i64=0
174 while sx6<4 { tif1[8+sx6*3]=(60+sx6) as u8; tif1[8+sx6*3+1]=(61+sx6) as u8; tif1[8+sx6*3+2]=(62+sx6) as u8; sx6=sx6+1 }
175 sx6=0
176 while sx6<4 { tif1[20+sx6*3]=(5+sx6) as u8; tif1[20+sx6*3+1]=(6+sx6) as u8; tif1[20+sx6*3+2]=(7+sx6) as u8; sx6=sx6+1 }
177 var p6: i64=32
178 p6=bt_e16(tif1,p6,9,1)
179 p6=bt_ent(tif1,p6,256,3,1,4,1)
180 p6=bt_ent(tif1,p6,257,3,1,2,1)
181 p6=bt_ent(tif1,p6,258,3,3,146,1)
182 p6=bt_ent(tif1,p6,259,3,1,1,1)
183 p6=bt_ent(tif1,p6,262,3,1,2,1)
184 p6=bt_ent(tif1,p6,273,4,2,152,1)
185 p6=bt_ent(tif1,p6,277,3,1,3,1)
186 p6=bt_ent(tif1,p6,278,3,1,1,1)
187 p6=bt_ent(tif1,p6,279,4,2,160,1)
188 p6=bt_e32(tif1,p6,0,1)
189 bt_e16(tif1,146,8,1); bt_e16(tif1,148,8,1); bt_e16(tif1,150,8,1)
190 bt_e32(tif1,152,8,1); bt_e32(tif1,156,20,1)
191 bt_e32(tif1,160,12,1); bt_e32(tif1,164,12,1)
192 let len6: i64=168
193 let wh6: *i64=sys_mmap(32) as *i64
194 let r6: *u8=tiff_decode_rgb(tif1, len6, wh6)
195 var t6: i64=0
196 if r6!=(0 as *u8) { if wh6[0]==4 { if wh6[1]==2 {
197 var ok6: i64=1
198 if (r6[0] as i64)!=60 { ok6=0 }
199 if (r6[1] as i64)!=61 { ok6=0 }
200 if (r6[11] as i64)!=65 { ok6=0 }
201 if (r6[12] as i64)!=5 { ok6=0 }
202 if (r6[23] as i64)!=10 { ok6=0 }
203 t6=ok6
204 } } }
205 gv_check("T6 TIFF LE RGB8 two-strip decode KAT" as *u8, t6, ctr)
206
207 // ---------- T7: BE TIFF gray8 photometric 0 (white-is-zero -> inverted) 4x1 ----------
208 let tif2: *u8=sys_mmap(512)
209 tif2[0]=0x4D as u8; tif2[1]=0x4D as u8; tif2[2]=0x00 as u8; tif2[3]=0x2A as u8
210 bt_e32(tif2,4,16,0)
211 tif2[8]=0 as u8; tif2[9]=100 as u8; tif2[10]=200 as u8; tif2[11]=255 as u8
212 var p7: i64=16
213 p7=bt_e16(tif2,p7,8,0)
214 p7=bt_ent(tif2,p7,256,3,1,4,0)
215 p7=bt_ent(tif2,p7,257,3,1,1,0)
216 p7=bt_ent(tif2,p7,258,3,1,8,0)
217 p7=bt_ent(tif2,p7,259,3,1,1,0)
218 p7=bt_ent(tif2,p7,262,3,1,0,0)
219 p7=bt_ent(tif2,p7,273,4,1,8,0)
220 p7=bt_ent(tif2,p7,277,3,1,1,0)
221 p7=bt_ent(tif2,p7,279,4,1,4,0)
222 p7=bt_e32(tif2,p7,0,0)
223 let wh7: *i64=sys_mmap(32) as *i64
224 let r7: *u8=tiff_decode_rgb(tif2, p7, wh7)
225 var t7: i64=0
226 if r7!=(0 as *u8) { if wh7[0]==4 { if wh7[1]==1 {
227 var ok7: i64=1
228 if (r7[0] as i64)!=255 { ok7=0 }
229 if (r7[3] as i64)!=155 { ok7=0 }
230 if (r7[6] as i64)!=55 { ok7=0 }
231 if (r7[9] as i64)!=0 { ok7=0 }
232 if (r7[10] as i64)!=0 { ok7=0 }
233 t7=ok7
234 } } }
235 gv_check("T7 TIFF BE gray8 white-is-zero decode (inversion KAT)" as *u8, t7, ctr)
236
237 // ---------- T8: LE TIFF RGB8 PackBits (run + literal packets) 4x1 ----------
238 let tif3: *u8=sys_mmap(512)
239 tif3[0]=0x49 as u8; tif3[1]=0x49 as u8; tif3[2]=0x2A as u8; tif3[3]=0x00 as u8
240 bt_w32(tif3,4,32)
241 // row = (170,170,170)(170,170,170)(1,2,3)(4,5,6): packbits = [251,170] + [5, 1 2 3 4 5 6]
242 tif3[8]=251 as u8; tif3[9]=170 as u8
243 tif3[10]=5 as u8; tif3[11]=1 as u8; tif3[12]=2 as u8; tif3[13]=3 as u8; tif3[14]=4 as u8; tif3[15]=5 as u8; tif3[16]=6 as u8
244 var p8: i64=32
245 p8=bt_e16(tif3,p8,9,1)
246 p8=bt_ent(tif3,p8,256,3,1,4,1)
247 p8=bt_ent(tif3,p8,257,3,1,1,1)
248 p8=bt_ent(tif3,p8,258,3,3,146,1)
249 p8=bt_ent(tif3,p8,259,3,1,32773,1)
250 p8=bt_ent(tif3,p8,262,3,1,2,1)
251 p8=bt_ent(tif3,p8,273,4,1,8,1)
252 p8=bt_ent(tif3,p8,277,3,1,3,1)
253 p8=bt_ent(tif3,p8,278,3,1,1,1)
254 p8=bt_ent(tif3,p8,279,4,1,9,1)
255 p8=bt_e32(tif3,p8,0,1)
256 bt_e16(tif3,146,8,1); bt_e16(tif3,148,8,1); bt_e16(tif3,150,8,1)
257 let wh8: *i64=sys_mmap(32) as *i64
258 let r8: *u8=tiff_decode_rgb(tif3, 152, wh8)
259 var t8: i64=0
260 if r8!=(0 as *u8) { if wh8[0]==4 { if wh8[1]==1 {
261 var ok8: i64=1
262 if (r8[0] as i64)!=170 { ok8=0 }
263 if (r8[5] as i64)!=170 { ok8=0 }
264 if (r8[6] as i64)!=1 { ok8=0 }
265 if (r8[8] as i64)!=3 { ok8=0 }
266 if (r8[9] as i64)!=4 { ok8=0 }
267 if (r8[11] as i64)!=6 { ok8=0 }
268 t8=ok8
269 } } }
270 gv_check("T8 TIFF PackBits decode (run + literal)" as *u8, t8, ctr)
271
272 // ---------- T9 BITE: TIFF with LZW compression is REFUSED (never a wrong image) ----------
273 let tif4: *u8=sys_mmap(512)
274 var c9: i64=0
275 while c9<168 { tif4[c9]=tif1[c9]; c9=c9+1 }
276 // entry 4 (tag 259) value field: IFD @32 +2 +3*12 +8 = 78
277 bt_e16(tif4,78,5,1)
278 let wh9: *i64=sys_mmap(32) as *i64
279 let r9: *u8=tiff_decode_rgb(tif4, 168, wh9)
280 var b9bad: i64=0
281 if r9==(0 as *u8) { b9bad=1 }
282 var b9good: i64=0
283 if r6==(0 as *u8) { b9good=1 }
284 gv_bite("T9 TIFF LZW-compression refusal (honest partial)" as *u8, b9bad, b9good, ctr)
285
286 // ---------- T10: chokepoint carries BOTH new formats ----------
287 let whA: *i64=sys_mmap(32) as *i64
288 let cA: *u8=nx_img_bytes_to_rgb(bmp1, o1, whA)
289 let whB: *i64=sys_mmap(32) as *i64
290 let cB: *u8=nx_img_bytes_to_rgb(tif1, len6, whB)
291 var t10: i64=0
292 if cA!=(0 as *u8) { if cB!=(0 as *u8) {
293 if (cA[0] as i64)==10 { if (cB[0] as i64)==60 { t10=1 } }
294 } }
295 gv_check("T10 chokepoint nx_img_bytes_to_rgb decodes BMP and TIFF" as *u8, t10, ctr)
296
297 // ---------- T11: WRITER ROUND-TRIP witness -- the months-old nx_bmp writer
298 // and today's reader are independently written implementations; byte-exact
299 // agreement through a real file is the cross-check a third-party file would
300 // give (no third-party BMP exists on the estate: measured, 0 under knowledge).
301 var t11: i64=0
302 let img11: *Image = nx_image_alloc(5, 3, 3)
303 if img11!=(0 as *Image) {
304 var iy: i64=0
305 while iy<3 {
306 var ix: i64=0
307 while ix<5 {
308 nx_image_set(img11, ix, iy, 0, ix*40+7)
309 nx_image_set(img11, ix, iy, 1, iy*70+11)
310 nx_image_set(img11, ix, iy, 2, (ix+iy)*30+2)
311 ix=ix+1
312 }
313 iy=iy+1
314 }
315 let wr11: i64 = bmp_write(img11, "/tmp/nx_bmp_rt.bmp" as *u8)
316 if wr11==0 {
317 let wbox: *i64=sys_mmap(16) as *i64
318 let wraw: *u8=sys_read_file("/tmp/nx_bmp_rt.bmp" as *u8, wbox)
319 if wraw!=(0 as *u8) {
320 let wh11: *i64=sys_mmap(32) as *i64
321 let r11: *u8=bmp_decode_rgb(wraw, wbox[0], wh11)
322 if r11!=(0 as *u8) { if wh11[0]==5 { if wh11[1]==3 {
323 var ok11: i64=1
324 var cy: i64=0
325 while cy<3 {
326 var cx: i64=0
327 while cx<5 {
328 let co11: i64=(cy*5+cx)*3
329 if (r11[co11] as i64)!=cx*40+7 { ok11=0 }
330 if (r11[co11+1] as i64)!=cy*70+11 { ok11=0 }
331 if (r11[co11+2] as i64)!=(cx+cy)*30+2 { ok11=0 }
332 cx=cx+1
333 }
334 cy=cy+1
335 }
336 t11=ok11
337 } } }
338 }
339 }
340 }
341 gv_check("T11 nx_bmp writer -> reader round-trip byte-exact (5x3, padded rows)" as *u8, t11, ctr)
342
343 let rc: i64 = gv_verdict("BMP-TIFF-GATE" as *u8, ctr, "90s bitmap + baseline TIFF readers live at the chokepoint" as *u8)
344 sys_exit(rc)
345 return rc
346}