code wiki / _hdl_build / nx_gif_color_gate.nx
nx_gif_color_gate.nx source
↩ module page · 181 lines · 7748 B
1// nx_gif_color_gate.nx -- gate for C2 of the codec-chokepoint program (debt 1785903075): GIF palette
2// COLOR decode + DE-INTERLACE, at the decoder (gif_decode_rgb) AND through the shared chokepoint
3// (nx_img_bytes_to_rgb). Fixtures are hand-built byte-exact GIF89a files: a 4x4 4-colour palette image
4// stored non-interlaced (rows 0,1,2,3) and interlaced (pass order 0,2,1,3 + descriptor bit 6), whose
5// DECODED images must be identical. The synthetic LZW uses CLEAR-before-every-literal (no dictionary
6// growth), so T6 decodes a REAL gathered web GIF (third-party encoder, real dictionary growth) as the
7// independent witness. Inherits nx_gate_verdict. license_tier: ORIGINAL expect_exit: 0
8import "nx_syscalls.nx"
9import "nx_gate_verdict.nx"
10import "nx_gif_decode.nx"
11import "nx_img_bytes_to_rgb.nx"
12
13// append one 3-bit LZW code, LSB-first (GIF bit order); buf must be zeroed (OR-only)
14func gg_putcode(buf: *u8, bitpos: *i64, code: i64) -> i64 {
15 var i: i64=0
16 while i<3 {
17 let bit: i64=(code>>i)&1
18 let bp: i64=bitpos[0]
19 if bit==1 { let by: i64=bp/8; let bo: i64=bp%8; buf[by]=((buf[by] as i64)|(1<<bo)) as u8 }
20 bitpos[0]=bitpos[0]+1
21 i=i+1
22 }
23 return 0
24}
25
26// build a 4x4 GIF89a with a 4-entry GCT (red,green,blue,white) whose pixel-index
27// STORAGE sequence is pixseq[16]; interlaced sets descriptor bit 6. returns length.
28func gg_build_gif(out: *u8, pixseq: *u8, interlaced: i64) -> i64 {
29 out[0]=0x47 as u8; out[1]=0x49 as u8; out[2]=0x46 as u8
30 out[3]=0x38 as u8; out[4]=0x39 as u8; out[5]=0x61 as u8
31 out[6]=4 as u8; out[7]=0 as u8; out[8]=4 as u8; out[9]=0 as u8
32 out[10]=0x81 as u8; out[11]=0 as u8; out[12]=0 as u8
33 out[13]=255 as u8; out[14]=0 as u8; out[15]=0 as u8
34 out[16]=0 as u8; out[17]=255 as u8; out[18]=0 as u8
35 out[19]=0 as u8; out[20]=0 as u8; out[21]=255 as u8
36 out[22]=255 as u8; out[23]=255 as u8; out[24]=255 as u8
37 var o: i64=25
38 out[o]=0x2C as u8
39 out[o+1]=0 as u8; out[o+2]=0 as u8; out[o+3]=0 as u8; out[o+4]=0 as u8
40 out[o+5]=4 as u8; out[o+6]=0 as u8; out[o+7]=4 as u8; out[o+8]=0 as u8
41 if interlaced==1 { out[o+9]=0x40 as u8 } else { out[o+9]=0 as u8 }
42 o=o+10
43 out[o]=2 as u8; o=o+1
44 let lzbuf: *u8=sys_mmap(256)
45 let bitpos: *i64=sys_mmap(8) as *i64
46 bitpos[0]=0
47 var p: i64=0
48 while p<16 { gg_putcode(lzbuf,bitpos,4); gg_putcode(lzbuf,bitpos,pixseq[p] as i64); p=p+1 }
49 gg_putcode(lzbuf,bitpos,5)
50 let nbytes: i64=(bitpos[0]+7)/8
51 out[o]=nbytes as u8; o=o+1
52 var q: i64=0
53 while q<nbytes { out[o]=lzbuf[q]; o=o+1; q=q+1 }
54 out[o]=0 as u8; o=o+1
55 out[o]=0x3B as u8; o=o+1
56 return o
57}
58
59func main() -> i64 {
60 let ctr: *i64 = gv_ctr()
61 gv_head("nx_gif_color_gate -- GIF palette colour + de-interlace, decoder and chokepoint" as *u8)
62
63 // display image: row y = colour y. non-interlaced storage = rows 0,1,2,3;
64 // interlaced storage = pass order rows 0,2,1,3.
65 let seq_n: *u8=sys_mmap(32)
66 let seq_i: *u8=sys_mmap(32)
67 var r: i64=0
68 while r<4 { var c: i64=0; while c<4 { seq_n[r*4+c]=r as u8; c=c+1 } r=r+1 }
69 var c2: i64=0
70 while c2<4 { seq_i[c2]=0 as u8; seq_i[4+c2]=2 as u8; seq_i[8+c2]=1 as u8; seq_i[12+c2]=3 as u8; c2=c2+1 }
71
72 let gif_n: *u8=sys_mmap(512)
73 let gif_i: *u8=sys_mmap(512)
74 let len_n: i64=gg_build_gif(gif_n, seq_n, 0)
75 let len_i: i64=gg_build_gif(gif_i, seq_i, 1)
76
77 // the two files must genuinely DIFFER on the wire (vacuity guard for T2)
78 var files_differ: i64=0
79 if len_n==len_i { var di: i64=0; while di<len_n { if gif_n[di]!=gif_i[di] { files_differ=1; di=len_n } else { di=di+1 } } } else { files_differ=1 }
80
81 // T1 palette colour KAT on the non-interlaced file
82 let wh1: *i64=sys_mmap(32) as *i64
83 let rgb1: *u8=gif_decode_rgb(gif_n, len_n, wh1)
84 var t1: i64=0
85 if rgb1!=(0 as *u8) { if wh1[0]==4 { if wh1[1]==4 {
86 var ok1: i64=1
87 var y1: i64=0
88 while y1<4 {
89 var x1: i64=0
90 while x1<4 {
91 let o1: i64=(y1*4+x1)*3
92 var er: i64=0
93 var eg: i64=0
94 var eb: i64=0
95 if y1==0 { er=255 }
96 if y1==1 { eg=255 }
97 if y1==2 { eb=255 }
98 if y1==3 { er=255; eg=255; eb=255 }
99 if (rgb1[o1] as i64)!=er { ok1=0 }
100 if (rgb1[o1+1] as i64)!=eg { ok1=0 }
101 if (rgb1[o1+2] as i64)!=eb { ok1=0 }
102 x1=x1+1
103 }
104 y1=y1+1
105 }
106 t1=ok1
107 } } }
108 gv_check("T1 gif_decode_rgb exact palette colours (4x4 KAT)" as *u8, t1, ctr)
109
110 // T2 interlaced file decodes to the IDENTICAL display image
111 let wh2: *i64=sys_mmap(32) as *i64
112 let rgb2: *u8=gif_decode_rgb(gif_i, len_i, wh2)
113 var t2: i64=0
114 if rgb2!=(0 as *u8) { if files_differ==1 {
115 var same2: i64=1
116 var p2: i64=0
117 while p2<48 { if rgb1[p2]!=rgb2[p2] { same2=0; p2=48 } else { p2=p2+1 } }
118 t2=same2
119 } }
120 gv_check("T2 interlaced storage decodes IDENTICAL to non-interlaced (files differ on wire)" as *u8, t2, ctr)
121
122 // T3 historic gray contract: Rec.709 of the palette rows = 53,182,18,255
123 let wh3: *i64=sys_mmap(32) as *i64
124 let gray3: *u8=gif_decode(gif_n, len_n, wh3)
125 var t3: i64=0
126 if gray3!=(0 as *u8) {
127 var ok3: i64=1
128 if (gray3[0] as i64)!=53 { ok3=0 }
129 if (gray3[5] as i64)!=182 { ok3=0 }
130 if (gray3[10] as i64)!=18 { ok3=0 }
131 if (gray3[15] as i64)!=255 { ok3=0 }
132 t3=ok3
133 }
134 gv_check("T3 gif_decode gray contract: Rec.709 rows 53/182/18/255" as *u8, t3, ctr)
135
136 // T4 BITE: a truncated GIF must be refused; the full file must decode
137 var bite_bad: i64=0
138 let wh4: *i64=sys_mmap(32) as *i64
139 let bad4: *u8=gif_decode_rgb(gif_n, 10, wh4)
140 if bad4==(0 as *u8) { bite_bad=1 }
141 var bite_good: i64=0
142 if rgb1==(0 as *u8) { bite_good=1 }
143 gv_bite("T4 truncated-GIF refusal" as *u8, bite_bad, bite_good, ctr)
144
145 // T5 the CHOKEPOINT delivers colour: before this rung it expanded gray R=G=B
146 let wh5: *i64=sys_mmap(32) as *i64
147 let ck5: *u8=nx_img_bytes_to_rgb(gif_n, len_n, wh5)
148 var t5: i64=0
149 if ck5!=(0 as *u8) { if wh5[0]==4 { if wh5[1]==4 {
150 if (ck5[0] as i64)==255 { if (ck5[1] as i64)==0 { if (ck5[2] as i64)==0 { t5=1 } } }
151 } } }
152 gv_check("T5 chokepoint nx_img_bytes_to_rgb returns COLOUR (R=255,G=0,B=0)" as *u8, t5, ctr)
153
154 // T6 INDEPENDENT WITNESS: a real gathered web GIF (third-party encoder, real
155 // LZW dictionary growth -- the synthetic CLEAR-spam stream never grows).
156 var t6: i64=0
157 var w6: i64=0
158 var h6: i64=0
159 let wbox: *i64=sys_mmap(16) as *i64
160 let wraw: *u8=sys_read_file("knowledge/media/barack_obama/1ec1849912da1655c037f34873dd363f848a2db9651624fd2098ef02c2c07a3c.gif" as *u8, wbox)
161 if wraw!=(0 as *u8) {
162 let wh6: *i64=sys_mmap(32) as *i64
163 let rgb6: *u8=gif_decode_rgb(wraw, wbox[0], wh6)
164 if rgb6!=(0 as *u8) {
165 w6=wh6[0]; h6=wh6[1]
166 if w6>0 { if h6>0 {
167 var vmin: i64=255
168 var vmax: i64=0
169 var s6: i64=0
170 while s6<w6*h6*3 { let pv: i64=rgb6[s6] as i64; if pv<vmin { vmin=pv } if pv>vmax { vmax=pv } s6=s6+37 }
171 if vmax-vmin>10 { t6=1 }
172 } }
173 }
174 }
175 gv_puts(" [witness gif w=" as *u8); gv_num(w6); gv_puts(" h=" as *u8); gv_num(h6); gv_puts("]\n" as *u8)
176 gv_check("T6 real gathered web GIF decodes with structure (independent LZW witness)" as *u8, t6, ctr)
177
178 let rc: i64 = gv_verdict("GIF-COLOR-GATE" as *u8, ctr, "palette colour + de-interlace at decoder and chokepoint" as *u8)
179 sys_exit(rc)
180 return rc
181}