code wiki / (root) / nx_webpprobe.nx

nx_webpprobe.nx source

↩ module page · 142 lines · 5248 B

1// nx_webpprobe.nx -- DIAGNOSTIC: which WebP variant is actually on the wire? 2// 3// Our webp_decode() searches for the VP8L (lossless) fourcc and returns 0 for anything else, so wiring it 4// in blind would fix an unknown fraction of the gap. RIFF layout: 'RIFF' <size> 'WEBP' <fourcc> -- so the 5// variant is bytes 12..15. This walks a directory and reports the split, which decides whether closing the 6// WebP gap is a WIRING job (VP8L) or a CODEC job (VP8 lossy intra). 7// 8// usage: nx_webpprobe <dir> 9 10import "nx_str.nx" 11import "nx_syscalls.nx" 12import "nx_dir.nx" 13import "nx_webp.nx" 14 15const WP_MAXROWS: i64 = 4096 16const WP_ARENA: i64 = 1048576 17const WP_PATH: i64 = 4096 18 19func wp_puts(s: *u8) -> i64 { sys_write(1, s, nx_str_len(s)); return 0 } 20 21func wp_pi(v: i64) -> i64 { 22 let t: *u8 = sys_mmap(32) 23 let o: *u8 = sys_mmap(32) 24 var m: i64 = v 25 var k: i64 = 0 26 if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) } 27 if m == 0 { t[0] = 48; k = 1 } 28 while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 } 29 var i: i64 = 0 30 while i < k { o[i] = t[k - 1 - i]; i = i + 1 } 31 sys_write(1, o, k) 32 return 0 33} 34 35func wp_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[off+i] = s[i]; i = i + 1 } return off + i } 36 37func wp_fourcc_is(b: *u8, off: i64, a: i64, c: i64, d: i64, e: i64) -> i64 { 38 if (b[off] as i64) != a { return 0 } 39 if (b[off+1] as i64) != c { return 0 } 40 if (b[off+2] as i64) != d { return 0 } 41 if (b[off+3] as i64) != e { return 0 } 42 return 1 43} 44 45func main(argc: i64, argv: *i64) -> i64 { 46 var dir: *u8 = "knowledge/media/julia_kyoka" as *u8 47 if argc >= 2 { dir = argv[1] as *u8 } 48 49 let rows: *NxDirRow = sys_mmap(NX_DIR_ROW_BYTES * WP_MAXROWS) as *NxDirRow 50 let arena: *u8 = sys_mmap(WP_ARENA) 51 let res: *NxDirResult = sys_mmap(NX_DIR_RESULT_BYTES) as *NxDirResult 52 let lrc: i64 = nx_dir_list(dir, rows, WP_MAXROWS, arena, WP_ARENA, 0, res) 53 wp_puts("=== nx_webpprobe dir=" as *u8); wp_puts(dir) 54 wp_puts(" entries=" as *u8); wp_pi(res.n_filled); wp_puts(" list_rc=" as *u8); wp_pi(lrc); wp_puts("\n" as *u8) 55 56 let path: *u8 = sys_mmap(WP_PATH) 57 let lenbox: *i64 = sys_mmap(16) as *i64 58 let wh: *i64 = sys_mmap(32) as *i64 59 60 var n_webp: i64 = 0 61 var n_vp8: i64 = 0 62 var n_vp8l: i64 = 0 63 var n_vp8x: i64 = 0 64 var n_other: i64 = 0 65 var n_gif: i64 = 0 66 var dec_ok: i64 = 0 67 var dec_fail: i64 = 0 68 69 var i: i64 = 0 70 while i < res.n_filled { 71 let row: *NxDirRow = nx_dir_row_at(rows, i) 72 var st: i64 = 0 73 if nx_dir_row_is_regular_file(row) != 1 { st = 1 } 74 75 if st == 0 { 76 var po: i64 = wp_cat(path, 0, dir) 77 po = wp_cat(path, po, "/" as *u8) 78 var c: i64 = 0 79 while c < row.name_len { path[po + c] = row.name_ptr[c]; c = c + 1 } 80 path[po + row.name_len] = 0 as u8 81 } 82 83 var buf: *u8 = 0 as *u8 84 if st == 0 { 85 buf = sys_read_file(path, lenbox) 86 if buf == 0 as *u8 { st = 1 } 87 } 88 if st == 0 { if lenbox[0] < 20 { st = 1 } } 89 90 // GIF87a / GIF89a 91 if st == 0 { 92 if wp_fourcc_is(buf, 0, 71, 73, 70, 56) == 1 { n_gif = n_gif + 1; st = 1 } 93 } 94 95 // RIFF ....WEBP 96 var iswebp: i64 = 0 97 if st == 0 { 98 if wp_fourcc_is(buf, 0, 82, 73, 70, 70) == 1 { 99 if wp_fourcc_is(buf, 8, 87, 69, 66, 80) == 1 { iswebp = 1 } 100 } 101 if iswebp == 0 { st = 1 } 102 } 103 104 if st == 0 { 105 n_webp = n_webp + 1 106 var kind: *u8 = "OTHER" as *u8 107 if wp_fourcc_is(buf, 12, 86, 80, 56, 76) == 1 { kind = "VP8L" as *u8; n_vp8l = n_vp8l + 1 } 108 else { if wp_fourcc_is(buf, 12, 86, 80, 56, 88) == 1 { kind = "VP8X" as *u8; n_vp8x = n_vp8x + 1 } 109 else { if wp_fourcc_is(buf, 12, 86, 80, 56, 32) == 1 { kind = "VP8 " as *u8; n_vp8 = n_vp8 + 1 } 110 else { n_other = n_other + 1 } } } 111 112 wh[0] = 0 113 wh[1] = 0 114 let argb: *i64 = webp_decode(buf, lenbox[0], wh) 115 var ok: i64 = 0 116 if argb != 0 as *i64 { if wh[0] > 0 { ok = 1 } } 117 if ok == 1 { dec_ok = dec_ok + 1 } else { dec_fail = dec_fail + 1 } 118 119 wp_puts(" " as *u8); wp_puts(kind) 120 wp_puts(" decode=" as *u8); wp_pi(ok) 121 wp_puts(" w=" as *u8); wp_pi(wh[0]) 122 wp_puts(" h=" as *u8); wp_pi(wh[1]) 123 wp_puts(" bytes=" as *u8); wp_pi(lenbox[0]) 124 wp_puts(" " as *u8); sys_write(1, row.name_ptr, row.name_len); wp_puts("\n" as *u8) 125 } 126 127 i = i + 1 128 } 129 130 wp_puts("{\"tool\":\"nx_webpprobe\",\"entries\":" as *u8); wp_pi(res.n_filled) 131 wp_puts(",\"webp\":" as *u8); wp_pi(n_webp) 132 wp_puts(",\"vp8l_lossless\":" as *u8); wp_pi(n_vp8l) 133 wp_puts(",\"vp8_lossy\":" as *u8); wp_pi(n_vp8) 134 wp_puts(",\"vp8x_extended\":" as *u8); wp_pi(n_vp8x) 135 wp_puts(",\"other_fourcc\":" as *u8); wp_pi(n_other) 136 wp_puts(",\"gif\":" as *u8); wp_pi(n_gif) 137 wp_puts(",\"webp_decode_ok\":" as *u8); wp_pi(dec_ok) 138 wp_puts(",\"webp_decode_fail\":" as *u8); wp_pi(dec_fail) 139 wp_puts("}\nWEBPPROBE-OK\n" as *u8) 140 sys_exit(0) 141 return 0 142}