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}