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}