code wiki / (root) / nx_webp_vp8l_gate.nx

nx_webp_vp8l_gate.nx source

↩ module page · 175 lines · 8483 B

1// nx_webp_vp8l_gate.nx -- proves the VP8L pixel-decoder math and the WebP 2// container walk. 3// 4// These are the pieces that decide whether a decoded image is CORRECT rather 5// than merely produced: the 14 predictors, the per-channel average, the 6// distance-plane mapping (VP8L's 2-D neighbourhood addressing, where an 7// off-by-one silently shifts every back-reference), the prefix-code value 8// rule, and the 5-byte header. 9// 10// NON-VACUITY: T10/T11/T12 are negative controls -- a non-RIFF buffer, a RIFF 11// that is not WEBP, and a bad VP8L signature must each be REFUSED. A decoder 12// that returns a plausible buffer for garbage is worse than one that returns 13// nothing. 14// 15// license_tier: ORIGINAL 16import "nx_syscalls.nx" 17import "nx_bitstream.nx" 18import "nx_huffman.nx" 19import "nx_webp_huff.nx" 20import "nx_webp_vp8l.nx" 21import "nx_webp.nx" 22 23func g_puts(s: *u8) -> i64 { 24 var i: i64 = 0 25 while s[i] != (0 as u8) { i = i + 1 } 26 sys_write(1, s, i) 27 return i 28} 29 30func main() -> i64 { 31 var fails: i64 = 0 32 33 // ---- T1: ceil-divide used for every sub-image size ---- 34 if vl_subsample_size(1, 0) != 1 { fails = fails + 1 } 35 if vl_subsample_size(5, 2) != 2 { fails = fails + 1 } 36 if vl_subsample_size(8, 3) != 1 { fails = fails + 1 } 37 if vl_subsample_size(9, 3) != 2 { fails = fails + 1 } 38 39 // ---- T2: per-channel average, no cross-channel carry ---- 40 // 0xff000000 and 0x00000000 -> alpha 127, everything else 0 41 if vl_average2(0xff000000, 0x00000000) != 0x7f000000 { fails = fails + 1 } 42 // 0x10203040 with itself is itself 43 if vl_average2(0x10203040, 0x10203040) != 0x10203040 { fails = fails + 1 } 44 45 // ---- T3: the trivial predictors select the right neighbour ---- 46 let L: i64 = 0x11111111 47 let T: i64 = 0x22222222 48 let TL: i64 = 0x33333333 49 let TR: i64 = 0x44444444 50 if vl_predict(0, L, T, TL, TR) != NX_VP8L_BLACK { fails = fails + 1 } 51 if vl_predict(1, L, T, TL, TR) != L { fails = fails + 1 } 52 if vl_predict(2, L, T, TL, TR) != T { fails = fails + 1 } 53 if vl_predict(3, L, T, TL, TR) != TR { fails = fails + 1 } 54 if vl_predict(4, L, T, TL, TR) != TL { fails = fails + 1 } 55 56 // ---- T4: clamped add-subtract saturates instead of wrapping ---- 57 // 0xff + 0xff - 0x00 must clamp to 0xff, never wrap to 0xfe 58 if vl_clamp_add_sub_full(0xffffffff, 0xffffffff, 0x00000000) != 0xffffffff { fails = fails + 1 } 59 // 0x00 + 0x00 - 0xff must clamp to 0, never wrap high 60 if vl_clamp_add_sub_full(0x00000000, 0x00000000, 0xffffffff) != 0x00000000 { fails = fails + 1 } 61 62 // ---- T5: Select picks top when the gradient favours it ---- 63 // identical neighbours -> the rule returns top 64 if vl_select(T, T, T) != T { fails = fails + 1 } 65 66 // ---- T6: distance-plane mapping ---- 67 let plane: *i64 = sys_mmap(NX_VP8L_PLANE_CODES * 8 + 64) as *i64 68 vl_plane_table(plane) 69 // code 1 -> table[0]=0x18 -> y=1, x=8-8=0 -> dist = 1*xsize + 0 70 if vl_dist_map(plane, 1, 32) != 32 { fails = fails + 1 } 71 // code 2 -> table[1]=0x07 -> y=0, x=8-7=1 -> dist = 1 72 if vl_dist_map(plane, 2, 32) != 1 { fails = fails + 1 } 73 // beyond the plane table, distances are linear 74 if vl_dist_map(plane, 121, 32) != 1 { fails = fails + 1 } 75 if vl_dist_map(plane, 130, 32) != 10 { fails = fails + 1 } 76 // a mapped distance can never be below 1 (would read forward) 77 if vl_dist_map(plane, 97, 32) < 1 { fails = fails + 1 } 78 79 // ---- T7: prefix-code values below 4 are literal ---- 80 let dummy: *u8 = sys_mmap(64) 81 dummy[0] = 0x00 as u8; dummy[1] = 0x00 as u8; dummy[2] = 0x00 as u8; dummy[3] = 0x00 as u8 82 let bsp: *NxBitStream = nx_bitstream_alloc(dummy, 4) 83 if vl_prefix_value(bsp, 0) != 1 { fails = fails + 1 } 84 if vl_prefix_value(bsp, 3) != 4 { fails = fails + 1 } 85 86 // ---- T8: palette packing thresholds ---- 87 if wb_palette_bits(2) != 3 { fails = fails + 1 } 88 if wb_palette_bits(4) != 2 { fails = fails + 1 } 89 if wb_palette_bits(16) != 1 { fails = fails + 1 } 90 if wb_palette_bits(17) != 0 { fails = fails + 1 } 91 92 // ---- T9: the 5-byte VP8L header, hand-encoded ---- 93 // {0x2f, 0x0f, 0xc0, 0x01, 0x00} = sig, w-1=15, h-1=7, alpha=0, ver=0 94 let hb: *u8 = sys_mmap(64) 95 hb[0] = 0x2f as u8; hb[1] = 0x0f as u8; hb[2] = 0xc0 as u8 96 hb[3] = 0x01 as u8; hb[4] = 0x00 as u8 97 let bsh: *NxBitStream = nx_bitstream_alloc(hb, 5) 98 let wh: *i64 = sys_mmap(64) as *i64 99 if vp8l_read_header(bsh, wh) != 1 { fails = fails + 1 } else { 100 if wh[0] != 16 { fails = fails + 1 } 101 if wh[1] != 8 { fails = fails + 1 } 102 } 103 104 // ---- T10 NEG: a bad VP8L signature is REFUSED ---- 105 let bad: *u8 = sys_mmap(64) 106 bad[0] = 0x2e as u8; bad[1] = 0x00 as u8; bad[2] = 0x00 as u8 107 bad[3] = 0x00 as u8; bad[4] = 0x00 as u8 108 let bsb: *NxBitStream = nx_bitstream_alloc(bad, 5) 109 if vp8l_read_header(bsb, wh) != 0 { fails = fails + 1 } 110 111 // ---- T11 NEG: a non-RIFF buffer decodes to nothing ---- 112 let nr: *u8 = sys_mmap(64) 113 var k: i64 = 0 114 while k < 32 { nr[k] = 0x41 as u8; k = k + 1 } 115 if webp_decode(nr, 32, wh) != (0 as *i64) { fails = fails + 1 } 116 117 // ---- T12 NEG: RIFF that is not WEBP (e.g. WAVE audio) is REFUSED ---- 118 let rw: *u8 = sys_mmap(64) 119 rw[0] = 0x52 as u8; rw[1] = 0x49 as u8; rw[2] = 0x46 as u8; rw[3] = 0x46 as u8 120 rw[8] = 0x57 as u8; rw[9] = 0x41 as u8; rw[10] = 0x56 as u8; rw[11] = 0x45 as u8 121 k = 12 122 while k < 32 { rw[k] = 0x00 as u8; k = k + 1 } 123 if webp_decode(rw, 32, wh) != (0 as *i64) { fails = fails + 1 } 124 125 // ---- T13 NEG: WEBP with no VP8L chunk is REFUSED (not guessed at) ---- 126 let nv: *u8 = sys_mmap(64) 127 nv[0] = 0x52 as u8; nv[1] = 0x49 as u8; nv[2] = 0x46 as u8; nv[3] = 0x46 as u8 128 nv[8] = 0x57 as u8; nv[9] = 0x45 as u8; nv[10] = 0x42 as u8; nv[11] = 0x50 as u8 129 // a VP8 (lossy) chunk, which this decoder does not handle 130 nv[12] = 0x56 as u8; nv[13] = 0x50 as u8; nv[14] = 0x38 as u8; nv[15] = 0x20 as u8 131 nv[16] = 0x04 as u8; nv[17] = 0x00 as u8; nv[18] = 0x00 as u8; nv[19] = 0x00 as u8 132 if webp_decode(nv, 32, wh) != (0 as *i64) { fails = fails + 1 } 133 134 // ---- T14: inverse subtract-green adds green back into red and blue ---- 135 let px: *i64 = sys_mmap(64) as *i64 136 px[0] = vl_argb(0xff, 0x10, 0x20, 0x30) 137 vl_inv_subtract_green(px, 1) 138 // red = 0x10 + 0x20 = 0x30, blue = 0x30 + 0x20 = 0x50, green unchanged 139 if px[0] != vl_argb(0xff, 0x30, 0x20, 0x50) { fails = fails + 1 } 140 141 // ---- T15: END-TO-END -- a complete 1x1 lossless WebP decoded to pixels ---- 142 // Hand-assembled to the spec, byte by byte, so the test depends on no 143 // external fixture and no other decoder: 144 // RIFF(24) WEBP VP8L(12) 145 // header 2f | w-1=0 (14b) | h-1=0 (14b) | alpha=0 | ver=0 146 // stream no transform, no colour cache, no meta image, then five 147 // SIMPLE one-symbol trees: G=64 R=32 B=16 A=255, dist=0 148 // Every tree is single-symbol, so all five decode consuming ZERO bits -- 149 // this exercises the exact zero-bit path the huff gate isolates, but now 150 // through the whole container -> stream -> pixel path. 151 let f: *u8 = sys_mmap(64) 152 f[0]=0x52 as u8; f[1]=0x49 as u8; f[2]=0x46 as u8; f[3]=0x46 as u8 153 f[4]=0x18 as u8; f[5]=0x00 as u8; f[6]=0x00 as u8; f[7]=0x00 as u8 154 f[8]=0x57 as u8; f[9]=0x45 as u8; f[10]=0x42 as u8; f[11]=0x50 as u8 155 f[12]=0x56 as u8; f[13]=0x50 as u8; f[14]=0x38 as u8; f[15]=0x4c as u8 156 f[16]=0x0c as u8; f[17]=0x00 as u8; f[18]=0x00 as u8; f[19]=0x00 as u8 157 f[20]=0x2f as u8; f[21]=0x00 as u8; f[22]=0x00 as u8; f[23]=0x00 as u8 158 f[24]=0x00 as u8; f[25]=0x28 as u8; f[26]=0x50 as u8; f[27]=0x41 as u8 159 f[28]=0x0a as u8; f[29]=0xd1 as u8; f[30]=0xff as u8; f[31]=0x00 as u8 160 let img: *i64 = webp_decode(f, 32, wh) 161 if img == (0 as *i64) { fails = fails + 1 } else { 162 if wh[0] != 1 { fails = fails + 1 } 163 if wh[1] != 1 { fails = fails + 1 } 164 if img[0] != vl_argb(255, 32, 64, 16) { fails = fails + 1 } 165 } 166 167 if fails == 0 { 168 g_puts("GATE nx_webp_vp8l verdict=GREEN pass=15/15 (subsample; per-channel average; predictors 0-4; clamp saturates; Select; distance-plane map; prefix values; palette bits; header 16x8; NEG bad-sig/non-RIFF/RIFF-WAVE/no-VP8L refused; inverse subtract-green; END-TO-END 1x1 lossless WebP -> ARGB ff204010)\n" as *u8) 169 sys_exit(0) 170 return 0 171 } 172 g_puts("GATE nx_webp_vp8l verdict=RED\n" as *u8) 173 sys_exit(1) 174 return 1 175}