code wiki / (root) / nx_jpegprobe.nx

nx_jpegprobe.nx source

↩ module page · 144 lines · 5597 B

1// nx_jpegprobe.nx -- DIAGNOSTIC: why does the image indexer skip real web JPEGs? 2// 3// nx_imgsearch walkdir over 64 real gathered images indexed only 12 (187 permille). All 64 passed magic 4// sniff at gather time, so the loss is in the DECODER. This names the failing tooth mechanically instead 5// of guessing: for every file in a directory it reports SOF2-progressive yes/no, the nx_jpeg_decode_LUMA 6// return code (the path nx_img_to_gray -> nx_imgsearch actually uses), and -- only when luma failed -- the 7// nx_jpeg_decode_RGB return code. The cross-tab progressive AND luma-fail AND rgb-ok is the smoking gun 8// for a branch that exists in one sibling and not the other. 9// 10// usage: nx_jpegprobe <dir> 11 12import "nx_str.nx" 13import "nx_syscalls.nx" 14import "nx_dir.nx" 15import "nx_jpeg_ascii.nx" 16import "nx_jpeg_progressive.nx" 17 18const JP_MAXROWS: i64 = 4096 19const JP_ARENA: i64 = 1048576 20const JP_PATH: i64 = 4096 21 22func jp_puts(s: *u8) -> i64 { sys_write(1, s, nx_str_len(s)); return 0 } 23 24func jp_pi(v: i64) -> i64 { 25 let t: *u8 = sys_mmap(32) 26 let o: *u8 = sys_mmap(32) 27 var m: i64 = v 28 var k: i64 = 0 29 if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) } 30 if m == 0 { t[0] = 48; k = 1 } 31 while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 } 32 var i: i64 = 0 33 while i < k { o[i] = t[k - 1 - i]; i = i + 1 } 34 sys_write(1, o, k) 35 return 0 36} 37 38func jp_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 } 39 40func main(argc: i64, argv: *i64) -> i64 { 41 var dir: *u8 = "knowledge/media/julia_kyoka" as *u8 42 if argc >= 2 { dir = argv[1] as *u8 } 43 44 let rows: *NxDirRow = sys_mmap(NX_DIR_ROW_BYTES * JP_MAXROWS) as *NxDirRow 45 let arena: *u8 = sys_mmap(JP_ARENA) 46 let res: *NxDirResult = sys_mmap(NX_DIR_RESULT_BYTES) as *NxDirResult 47 let lrc: i64 = nx_dir_list(dir, rows, JP_MAXROWS, arena, JP_ARENA, 0, res) 48 jp_puts("=== nx_jpegprobe dir=" as *u8); jp_puts(dir) 49 jp_puts(" list_rc=" as *u8); jp_pi(lrc) 50 jp_puts(" entries=" as *u8); jp_pi(res.n_filled); jp_puts(" ===\n" as *u8) 51 52 let path: *u8 = sys_mmap(JP_PATH) 53 let lenbox: *i64 = sys_mmap(16) as *i64 54 let pl: *i64 = sys_mmap(16) as *i64 55 let pw: *i64 = sys_mmap(16) as *i64 56 let ph: *i64 = sys_mmap(16) as *i64 57 let ps: *i64 = sys_mmap(16) as *i64 58 59 var total: i64 = 0 60 var jpegs: i64 = 0 61 var pngs: i64 = 0 62 var prog: i64 = 0 63 var luma_ok: i64 = 0 64 var luma_fail: i64 = 0 65 var prog_luma_fail: i64 = 0 66 var prog_rgb_ok: i64 = 0 67 var base_luma_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 = jp_cat(path, 0, dir) 77 po = jp_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 total = total + 1 82 } 83 84 var buf: *u8 = 0 as *u8 85 if st == 0 { 86 buf = sys_read_file(path, lenbox) 87 if buf == 0 as *u8 { st = 1 } 88 } 89 90 var isjpeg: i64 = 0 91 if st == 0 { 92 if lenbox[0] > 4 { 93 if buf[0] == (255 as u8) { if buf[1] == (216 as u8) { isjpeg = 1 } } 94 if buf[1] == (80 as u8) { if buf[2] == (78 as u8) { pngs = pngs + 1 } } 95 } 96 if isjpeg == 0 { st = 1 } 97 } 98 99 var isprog: i64 = 0 100 if st == 0 { 101 jpegs = jpegs + 1 102 isprog = nx_jpeg_is_progressive(buf, lenbox[0]) 103 if isprog == 1 { prog = prog + 1 } 104 } 105 106 var lrc2: i64 = 0 107 if st == 0 { 108 lrc2 = nx_jpeg_decode_luma(buf, lenbox[0], pl, pw, ph, ps) 109 if lrc2 == NX_JPEG_ASCII_OK { luma_ok = luma_ok + 1 } 110 if lrc2 != NX_JPEG_ASCII_OK { luma_fail = luma_fail + 1 } 111 if lrc2 != NX_JPEG_ASCII_OK { if isprog == 1 { prog_luma_fail = prog_luma_fail + 1 } } 112 if lrc2 != NX_JPEG_ASCII_OK { if isprog == 0 { base_luma_fail = base_luma_fail + 1 } } 113 } 114 115 // only decode RGB when luma FAILED -- bounds allocation, and that is the interesting cell 116 if st == 0 { 117 if lrc2 != NX_JPEG_ASCII_OK { 118 let rb: *i64 = sys_mmap(16) as *i64 119 let rrc: i64 = nx_jpeg_decode_rgb(buf, lenbox[0], rb, pw, ph) 120 if rrc == NX_JPEG_ASCII_OK { prog_rgb_ok = prog_rgb_ok + 1 } 121 jp_puts(" FAIL luma_rc=" as *u8); jp_pi(lrc2) 122 jp_puts(" rgb_rc=" as *u8); jp_pi(rrc) 123 jp_puts(" progressive=" as *u8); jp_pi(isprog) 124 jp_puts(" bytes=" as *u8); jp_pi(lenbox[0]) 125 jp_puts(" " as *u8); sys_write(1, row.name_ptr, row.name_len); jp_puts("\n" as *u8) 126 } 127 } 128 129 i = i + 1 130 } 131 132 jp_puts("{\"tool\":\"nx_jpegprobe\",\"files\":" as *u8); jp_pi(total) 133 jp_puts(",\"jpeg\":" as *u8); jp_pi(jpegs) 134 jp_puts(",\"png\":" as *u8); jp_pi(pngs) 135 jp_puts(",\"progressive\":" as *u8); jp_pi(prog) 136 jp_puts(",\"luma_ok\":" as *u8); jp_pi(luma_ok) 137 jp_puts(",\"luma_fail\":" as *u8); jp_pi(luma_fail) 138 jp_puts(",\"progressive_and_luma_fail\":" as *u8); jp_pi(prog_luma_fail) 139 jp_puts(",\"baseline_and_luma_fail\":" as *u8); jp_pi(base_luma_fail) 140 jp_puts(",\"luma_fail_but_rgb_ok\":" as *u8); jp_pi(prog_rgb_ok) 141 jp_puts("}\nJPEGPROBE-OK\n" as *u8) 142 sys_exit(0) 143 return 0 144}